[pve-devel] [PATCH 1/2] openvswitch hybrid network model implementation

Alexandre Derumier aderumier at odiso.com
Fri Apr 25 08:08:18 CEST 2014


to be able to use iptables firewall (I have done prelimary test, it's works fine with current pve-firewall model),
this patch implemented an hybris network model like openstack.

each tap interface have a dedicated linux bridge ("vmbr-tapXXXiY)"
this linux bridge is connected to ovs bridge through ovs internal port ("ovsint-tapXXXiY))

(feel free to change bridge and ovsint port name)

we don't use veth pair for interconnect because it's too slow

performance test:
http://www.ustack.com/wp-content/uploads/2013/10/Neutron-performance-testing.pdf

show that the hybrid model with ovsintport is almost fast than a single linux bridge or a single ovs bridge.

Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 data/PVE/Network.pm |   82 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 77 insertions(+), 5 deletions(-)

diff --git a/data/PVE/Network.pm b/data/PVE/Network.pm
index 4677bf9..0f8ed2f 100644
--- a/data/PVE/Network.pm
+++ b/data/PVE/Network.pm
@@ -2,10 +2,11 @@ package PVE::Network;
 
 use strict;
 use warnings;
-use PVE::Tools qw(run_command);
+use PVE::Tools qw(run_command file_get_contents);
 use PVE::ProcFSTools;
 use PVE::INotify;
 use File::Basename;
+use JSON;
 
 # host network related utility functions
 
@@ -70,8 +71,13 @@ sub tap_create {
 sub tap_plug {
     my ($iface, $bridge, $tag) = @_;
 
+    my $iface_suffix = $1 if $iface =~ m/^tap((\d+)i(\d+))$/;
+    die "wrong interface name $iface" if !$iface_suffix;
+
+    my $ovsintport = "ovsint$iface_suffix";
+
     #cleanup old port config from any openvswitch bridge
-    eval {run_command("/usr/bin/ovs-vsctl del-port $iface", outfunc => sub {}, errfunc => sub {}) };
+    eval {run_command("/usr/bin/ovs-vsctl del-port $ovsintport", outfunc => sub {}, errfunc => sub {}) };
 
     if (-d "/sys/class/net/$bridge/bridge") {
 	my $newbridge = activate_bridge_vlan($bridge, $tag);
@@ -80,10 +86,47 @@ sub tap_plug {
 	system("/sbin/brctl addif $newbridge $iface") == 0 ||
 	    die "can't add interface to bridge\n";
     } else {
-	my $cmd = "/usr/bin/ovs-vsctl add-port $bridge $iface";
+
+	my $bridge_hash = {};
+
+	eval { $bridge_hash = read_openvswitch_config() };
+
+	die "$bridge is not an linux bridge or openvswitch switch" if !$bridge_hash->{$bridge};
+
+	my $bridgetap = "fwbr$iface_suffix";
+	my $cmd = "/usr/bin/ovs-vsctl add-port $bridge $ovsintport";
 	$cmd .= " tag=$tag" if $tag;
+	$cmd .= " -- set Interface $ovsintport type=internal";
 	system($cmd) == 0 ||
-	    die "can't add interface to bridge\n";
+	    die "$cmd : can't create ovs intport $ovsintport\n";
+
+	# set the same mtu for ovs int port
+	my $bridgemtu = PVE::Tools::file_read_firstline("/sys/class/net/$bridge/mtu");
+	    die "bridge '$bridge' does not exist\n" if !$bridgemtu;
+
+	eval { 
+	    PVE::Tools::run_command("/sbin/ifconfig $ovsintport mtu $bridgemtu");
+	};
+
+	# add bridgetap if it doesn't already exist
+	if (! -d "/sys/class/net/$bridgetap") {
+	system("/sbin/brctl addbr $bridgetap") == 0 ||
+	    die "can't add bridge $bridgetap\n";
+	}
+
+	# be sure to have the bridgetap up
+	system("/sbin/ip link set $bridgetap up") == 0 ||
+	    die "can't up bridge $bridgetap\n";
+
+	# add ovsintport to bridgetap
+	system("/sbin/brctl addif $bridgetap $ovsintport") == 0 ||
+	    die "can't add interface $ovsintport to bridge $bridgetap\n";
+
+	# add vm tap interface to bridgetap
+	system("/sbin/brctl addif $bridgetap $iface") == 0 ||
+	    die "can't add interface $iface to bridge $bridgetap\n";
+
+
     }
 }
 
@@ -96,7 +139,17 @@ sub tap_unplug {
 	system("/sbin/brctl delif $bridge $iface") == 0 ||
 	    die "can't del interface from bridge\n";
     } else {
-	system ("/usr/bin/ovs-vsctl del-port $iface") == 0 ||
+
+	my $iface_suffix = $1 if $iface =~ m/^tap((\d+)i(\d+))$/;
+	die "wrong interface name $iface" if !$iface_suffix;
+
+	my $ovsintport = "ovsint$iface_suffix";
+	my $bridgetap = "fwbr$iface_suffix";
+
+	system("/sbin/brctl delif $bridgetap $iface") == 0 ||
+	    die "can't del interface from bridge $bridgetap\n";
+
+	system ("/usr/bin/ovs-vsctl del-port $ovsintport") == 0 ||
 	    die "can't del interface from bridge\n";
     }
 }
@@ -193,4 +246,23 @@ sub activate_bridge_vlan {
     return $bridgevlan;
 }
 
+sub read_openvswitch_config {
+
+    my $filename = '/etc/openvswitch/conf.db';
+    my $config = file_get_contents($filename, 5*1024*1024);
+    my @lines = split('\n', $config);
+    my $bridge_hash = {};
+    foreach my $line (@lines) {
+	my $json = {};
+	eval { $json = decode_json($line)};
+	foreach my $bridgekey (keys %{$json->{Bridge}}) {
+	    my $bridgename = $json->{Bridge}->{$bridgekey}->{name};
+	    $bridge_hash->{$bridgename} = 1 if $bridgename;
+        }
+    }
+
+    return $bridge_hash;
+
+}
+
 1;
-- 
1.7.10.4



More information about the pve-devel mailing list