[pve-devel] Add support for OVS Trunk

Benjamin Lessani | Sonassi - The Magento Experts ben at sonassi.com
Sun Sep 14 21:36:58 CEST 2014


This has been a bugbear for me for a while and put me off using Proxmox. As
it was never possible to pass a single interface with tagged VLANs on it
(versus multiple interfaces, all untagged).

 

Now that OVS is a part of Proxmox, it makes sense to be able to give guests
tagged ports (so that routers/firewalls can be put in guests). This isn't an
"elegant" set of patches, but merely enough to get the job done.

 

I hope this is of help, I don't mind refining it a little more if necessary.


 

 

 

diff --git a/usr/share/perl5/PVE/API2/Qemu.pm
b/usr/share/perl5/PVE/API2/Qemu.pm

index df6045c..db54d50 100644

--- a/usr/share/perl5/PVE/API2/Qemu.pm

+++ b/usr/share/perl5/PVE/API2/Qemu.pm

@@ -847,9 +847,9 @@ my $vmconfig_update_net = sub {

             PVE::Network::tap_rate_limit($iface, $newnet->{rate});

         }

 

-        if(($newnet->{bridge} ne $oldnet->{bridge}) || ($newnet->{tag} ne
$oldnet->{tag}) || ($newnet->{tags} ne $oldnet->{tags}) ||

+        if(($newnet->{bridge} ne $oldnet->{bridge}) || ($newnet->{tag} ne
$oldnet->{tag}) || ($newnet->{firewall} ne $oldnet->{firew

             PVE::Network::tap_unplug($iface);

-            PVE::Network::tap_plug($iface, $newnet->{bridge},
$newnet->{tag}, $newnet->{tags}, $newnet->{firewall});

+            PVE::Network::tap_plug($iface, $newnet->{bridge},
$newnet->{tag}, $newnet->{firewall},  $newnet->{trunks});

         }

 

         }else{

diff --git a/usr/share/perl5/PVE/Network.pm b/usr/share/perl5/PVE/Network.pm

index a352c5e..869378e 100644

--- a/usr/share/perl5/PVE/Network.pm

+++ b/usr/share/perl5/PVE/Network.pm

@@ -113,11 +113,15 @@ my $bridge_add_interface = sub {

};

 

my $ovs_bridge_add_port = sub {

-    my ($bridge, $iface, $tag, $internal) = @_;

+    my ($bridge, $iface, $tag, $internal, $trunks) = @_;

+

+    $trunks =~ s/;/,/g if $trunks;

 

     my $cmd = "/usr/bin/ovs-vsctl add-port $bridge $iface";

     $cmd .= " tag=$tag" if $tag;

+    $cmd .= " trunk=$trunks" if $trunks;

     $cmd .= " -- set Interface $iface type=internal" if $internal;

+

     system($cmd) == 0 ||

     die "can't add ovs port '$iface'\n";

};

@@ -171,7 +175,7 @@ my $create_firewall_bridge_linux = sub {

};

 

my $create_firewall_bridge_ovs = sub {

-    my ($iface, $bridge, $tag) = @_;

+    my ($iface, $bridge, $tag, $trunks) = @_;

 

     my ($vmid, $devid) = &$parse_tap_devive_name($iface);

     my ($fwbr, undef, undef, $ovsintport) = &$compute_fwbr_names($vmid,
$devid);

@@ -183,7 +187,7 @@ my $create_firewall_bridge_ovs = sub {

 

     &$bridge_add_interface($fwbr, $iface);

 

-    &$ovs_bridge_add_port($bridge, $ovsintport, $tag, 1);

+    &$ovs_bridge_add_port($bridge, $ovsintport, $tag, 1, $trunks);

 

     # set the same mtu for ovs int port

     PVE::Tools::run_command("/sbin/ifconfig $ovsintport mtu $bridgemtu");

@@ -216,7 +220,7 @@ my $cleanup_firewall_bridge = sub {

};

 

sub tap_plug {

-    my ($iface, $bridge, $tag, $tags, $firewall) = @_;

+    my ($iface, $bridge, $tag, $firewall, $trunks) = @_;

 

     #cleanup old port config from any openvswitch bridge

     eval {run_command("/usr/bin/ovs-vsctl del-port $iface", outfunc => sub
{}, errfunc => sub {}) };

@@ -234,9 +238,9 @@ sub tap_plug {

     &$cleanup_firewall_bridge($iface); # remove stale devices

 

     if ($firewall) {

-        &$create_firewall_bridge_ovs($iface, $bridge, $tag);

+        &$create_firewall_bridge_ovs($iface, $bridge, $tag, $trunks);

     } else {

-        &$ovs_bridge_add_port($bridge, $iface, $tag);

+        &$ovs_bridge_add_port($bridge, $iface, $tag, 0, $trunks);

     }

     }

}

diff --git a/usr/share/perl5/PVE/QemuServer.pm
b/usr/share/perl5/PVE/QemuServer.pm

index 9b1d342..85970f3 100644

--- a/usr/share/perl5/PVE/QemuServer.pm

+++ b/usr/share/perl5/PVE/QemuServer.pm

@@ -485,7 +485,7 @@ my $nic_model_list_txt = join(' ', sort
@$nic_model_list);

my $netdesc = {

     optional => 1,

     type => 'string', format => 'pve-qm-net',

-    typetext => "MODEL=XX:XX:XX:XX:XX:XX
[,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>][,tag=<vlanid>][,tags=<vlan
ids>][,firewall

+    typetext => "MODEL=XX:XX:XX:XX:XX:XX
[,bridge=<dev>][,queues=<nbqueues>][,rate=<mbps>][,tag=<vlanid>][,firewall=0
|1][,trunks=<vl

     description => <<EODESCR,

Specify network devices.

 

@@ -1322,10 +1322,10 @@ sub parse_net {

         $res->{rate} = $1;

     } elsif ($kvp =~ m/^tag=(\d+)$/) {

         $res->{tag} = $1;

-    } elsif ($kvp =~ m/^tags=([0-9;]+)$/) {

-        $res->{tags} = $1;

     } elsif ($kvp =~ m/^firewall=(\d+)$/) {

         $res->{firewall} = $1;

+    } elsif ($kvp =~ m/^trunks=([0-9;]+)$/) {

+        $res->{trunks} = $1;

     } else {

         return undef;

     }

@@ -1345,8 +1345,8 @@ sub print_net {

     $res .= ",bridge=$net->{bridge}" if $net->{bridge};

     $res .= ",rate=$net->{rate}" if $net->{rate};

     $res .= ",tag=$net->{tag}" if $net->{tag};

-    $res .= ",tags=$net->{tags}" if $net->{tags};

     $res .= ",firewall=$net->{firewall}" if $net->{firewall};

+    $res .= ",trunks=$net->{trunks}" if $net->{trunks};

 

     return $res;

}

diff --git a/usr/share/pve-manager/ext4/pvemanagerlib.js
b/usr/share/pve-manager/ext4/pvemanagerlib.js

index 5353508..4866058 100644

--- a/usr/share/pve-manager/ext4/pvemanagerlib.js

+++ b/usr/share/pve-manager/ext4/pvemanagerlib.js

@@ -1304,6 +1304,8 @@ Ext.define('PVE.Parser', { statics: {

         res.rate = match_res[1];

         } else if ((match_res = p.match(/^tag=(\d+(\.\d+)?)$/)) !== null) {

                 res.tag = match_res[1];

+        } else if ((match_res = p.match(/^trunks=([0-9;]+)$/)) !== null) {

+                res.trunks = match_res[1];

         } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {

                 res.firewall = match_res[1];

         } else {

@@ -1330,6 +1332,9 @@ Ext.define('PVE.Parser', { statics: {

         if (net.tag) {

         netstr += ",tag=" + net.tag;

         }

+        if (net.trunks) {

+        netstr += ",trunks=" + net.trunks;

+        }

         if (net.firewall) {

         netstr += ",firewall=" + net.firewall;

         }

@@ -1441,7 +1446,8 @@ Ext.define('PVE.Parser', { statics: {

             }

             data['bridge'] = bridge_res[1];

             data['tag'] = bridge_res[4];

-            data['firewall'] = bridge_res[5] ? 1 : 0;

+            data['tag'] = bridge_res[5];

+            data['firewall'] = bridge_res[6] ? 1 : 0;

         } else {

             data[match_res[1]] = match_res[2];

         }

@@ -1465,12 +1471,15 @@ Ext.define('PVE.Parser', { statics: {

 

     Ext.Object.each(netif, function(iface, data) {

         var tmparray = [];

-        Ext.Array.each(['ifname', 'mac', 'bridge', 'host_ifname' ,
'host_mac', 'mac_filter', 'tag', 'firewall'], function(key) {

+        Ext.Array.each(['ifname', 'mac', 'bridge', 'host_ifname' ,
'host_mac', 'mac_filter', 'tag', 'trunks', 'firewall'], function(

         var value = data[key];

         if (key === 'bridge'){

             if(data['tag']){

             value = value + 'v' + data['tag'];

             }

+            if(data['trunks']){

+            value = value + 'v' + data['trunks'];

+            }

             if (data['firewall']){

             value = value + 'f';

             }

@@ -3999,6 +4008,18 @@ Ext.define('PVE.form.VlanField', {

     me.callParent();

     }

});

+Ext.define('PVE.form.VlansField', {

+    extend: 'Ext.form.field.Text',

+    alias: ['widget.pveVlansField'],

+

+    deleteEmpty: false,

+

+    emptyText: 'no VLANs',

+

+    fieldLabel: gettext('VLAN Trunks'),

+

+    allowBlank: true,

+});

Ext.define('PVE.form.Checkbox', {

     extend: 'Ext.form.field.Checkbox',

     alias: ['widget.pvecheckbox'],

@@ -15149,6 +15170,7 @@ Ext.define('PVE.qemu.MemoryEdit', {

     } else if (values.networkmode === 'bridge') {

         me.network.bridge = values.bridge;

         me.network.tag = values.tag;

+        me.network.trunks = values.trunks;

         me.network.firewall = values.firewall;

     } else {

         me.network.bridge = undefined;

@@ -15221,6 +15243,7 @@ Ext.define('PVE.qemu.MemoryEdit', {

             me.down('field[name=bridge]').setDisabled(!value);

             me.down('field[name=bridge]').validate();

             me.down('field[name=tag]').setDisabled(!value);

+            me.down('field[name=trunks]').setDisabled(!value);

             me.down('field[name=firewall]').setDisabled(!value);

             }

         }

@@ -15234,6 +15257,13 @@ Ext.define('PVE.qemu.MemoryEdit', {

         },

         me.bridgesel,

         {

+        xtype: 'pveVlansField',

+        name: 'trunks',

+        value: '',

+        labelAlign: 'right'

+        },

+        me.bridgesel,

+        {

         xtype: 'pvecheckbox',

         fieldLabel: gettext('Firewall'),

         name: 'firewall',

@@ -19211,6 +19241,11 @@ Ext.define('PVE.OpenVZ.NetIfEdit', {

             value: cdata.tag,

         },

         {

+            xtype: 'pveVlansField',

+            name: 'trunks',

+            value: cdata.trunks

+        },

+        {

             xtype: 'pvecheckbox',

             fieldLabel: gettext('Firewall'),

             name: 'firewall',

@@ -19564,7 +19599,7 @@ Ext.define('PVE.openvz.NetworkView', {

     Ext.define('pve-openvz-network', {

     extend: "Ext.data.Model",

     proxy: { type: 'memory' },

-    fields: [ 'id', 'type', 'value', 'ifname', 'mac', 'bridge',
'host_ifname', 'host_mac', 'tag', 'firewall' ]

+    fields: [ 'id', 'type', 'value', 'ifname', 'mac', 'bridge',
'host_ifname', 'host_mac', 'tag', 'trunks', 'firewall' ]

     });

 

});

diff --git a/var/lib/qemu-server/pve-bridge b/var/lib/qemu-server/pve-bridge

index d6c5eb8..48f63f5 100755

--- a/var/lib/qemu-server/pve-bridge

+++ b/var/lib/qemu-server/pve-bridge

@@ -30,6 +30,6 @@ PVE::Network::tap_create($iface, $net->{bridge});

 

PVE::Network::tap_rate_limit($iface, $net->{rate}) if $net->{rate};

 

-PVE::Network::tap_plug($iface, $net->{bridge}, $net->{tag},
$net->{firewall});

+PVE::Network::tap_plug($iface, $net->{bridge}, $net->{tag},
$net->{firewall}, $net->{trunks});

 

exit 0;

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.proxmox.com/pipermail/pve-devel/attachments/20140914/5c9254b7/attachment.htm>


More information about the pve-devel mailing list