1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00

[PATCH ifupdown2] addons: addressvirtual: fixup macvlan device enslavements for vrfs

Ticket: CM-12988
Reviewed By: julien, nikhil, dsa
Testing Done: tested ifup and ifdown of vrf devices with address virtual
slaves

This patch fixes up macvlan device enslavements when vrf device
or vrf slave is brought down and up. address virtual macvlan
devices on vrf slaves need to enslaved to the vrf. This
patch checks and fixes up those vrf enslavements for the following
cases:
ifdown <vrf_device> && ifup <vrf_device>
ifdown <vrf_slave> && ifup <vrf_slave>

starting state:
------------
$ip -br link show
myvrf            UP  46:c6:44:db:37:60 <NOARP,MASTER,UP,LOWER_UP>
bridge.901@bridge UP 44:38:39:00:77:88 <UP,BROADCAST,MULTICAST,UP>
bridge-901-v0@bridge.901 UP 00:00:5e:00:01:81 <UP,BROADCAST,MULTICAST,UP>

$ifdown myvrf
$ip -br link show
bridge.901@bridge DOWN           44:38:39:00:77:88 <BROADCAST,MULTICAST>
bridge-901-v0@bridge.901 DOWN    00:00:5e:00:01:81 <BROADCAST,MULTICAST,M-DOWN>

before patch (macvlan device bridge-901-v0 did not come up:
----------------------------------------
$ifup myvrf
$ip -br link show
bridge.901@bridge UP 44:38:39:00:77:88 <UP,BROADCAST,MULTICAST,UP>
bridge-901-v0@bridge.901 DOWN  00:00:5e:00:01:81 <BROADCAST,MULTICAST>
myvrf            UP             ce:a6:e1:85:75:73 <NOARP,MASTER,UP,LOWER_UP>

after patch:
------------
$ifup myvrf
$ip -br link show
bridge.901@bridge UP 44:38:39:00:77:88 <UP,BROADCAST,MULTICAST,UP>
bridge-901-v0@bridge.901 UP 00:00:5e:00:01:81 <UP,BROADCAST,MULTICAST,UP>
myvrf                   UP     ce:a6:e1:85:75:73 <NOARP,MASTER,UP,LOWER_UP>

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
This commit is contained in:
Roopa Prabhu
2016-10-19 10:43:45 -07:00
parent 90649d374a
commit 42e85fc834
4 changed files with 85 additions and 19 deletions

View File

@@ -36,10 +36,9 @@ class addressvirtual(moduleBase):
self.ipcmd = None
self._bridge_fdb_query_cache = {}
def _is_supported(self, ifaceobj):
if ifaceobj.get_attr_value_first('address-virtual'):
return True
return False
def get_dependent_ifacenames(self, ifaceobj, ifacenames_all=None):
if ifaceobj.get_attr_value('address-virtual'):
ifaceobj.link_privflags |= ifaceLinkPrivFlags.ADDRESS_VIRTUAL_SLAVE
def _get_macvlan_prefix(self, ifaceobj):
return '%s-v' %ifaceobj.name[0:13].replace('.', '-')
@@ -292,10 +291,73 @@ class addressvirtual(moduleBase):
self.logger.error("%s: Multicast bit is set in the virtual mac address '%s'" %(ifaceobj.name, mac))
return False
return True
except Exception, e:
except Exception:
return False
def _up(self, ifaceobj):
def _fixup_vrf_enslavements(self, ifaceobj, ifaceobj_getfunc=None):
""" This function fixes up address virtual interfaces
(macvlans) on vrf slaves. Since this fixup is an overhead,
this must be called only in cases when ifupdown2 is
called on the vrf device or its slave and not when
ifupdown2 is called for all devices. When all
interfaces are brought up, the expectation is that
the normal path will fix up a vrf device or its slaves"""
if not ifaceobj_getfunc:
return
if ((ifaceobj.link_kind & ifaceLinkKind.VRF) and
self.ipcmd.link_exists(ifaceobj.name)):
# if I am a vrf device and I have slaves
# that have address virtual config,
# enslave the slaves 'address virtual
# interfaces (macvlans)' to myself:
running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
if running_slaves:
# pick up any existing slaves of a vrf device and
# look for their upperdevices and enslave them to the
# vrf device:
for s in running_slaves:
sobjs = ifaceobj_getfunc(s)
if (sobjs and
(sobjs[0].link_privflags & ifaceLinkPrivFlags.ADDRESS_VIRTUAL_SLAVE)):
# enslave all its upper devices to
# the vrf device
upperdevs = self.ipcmd.link_get_uppers(sobjs[0].name)
if not upperdevs:
continue
for u in upperdevs:
# skip vrf device which
# will also show up in the
# upper device list
if u == ifaceobj.name:
continue
self.ipcmd.link_set(u, 'master', ifaceobj.name,
state='up')
elif ((ifaceobj.link_privflags & ifaceLinkPrivFlags.ADDRESS_VIRTUAL_SLAVE) and
(ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE) and
self.ipcmd.link_exists(ifaceobj.name)):
# If I am a vrf slave and I have 'address virtual'
# config, make sure my addrress virtual interfaces
# (macvlans) are also enslaved to the vrf device
vrfname = ifaceobj.get_attr_value_first('vrf')
if not vrfname or not self.ipcmd.link_exists(vrfname):
return
running_uppers = self.ipcmd.link_get_uppers(ifaceobj.name)
if not running_uppers:
return
macvlan_prefix = self._get_macvlan_prefix(ifaceobj)
if not macvlan_prefix:
return
for u in running_uppers:
if u == vrfname:
continue
if u.startswith(macvlan_prefix):
self.ipcmd.link_set(u, 'master', vrfname,
state='up')
def _up(self, ifaceobj, ifaceobj_getfunc=None):
if not ifupdownflags.flags.ALL:
self._fixup_vrf_enslavements(ifaceobj, ifaceobj_getfunc)
address_virtual_list = ifaceobj.get_attr_value('address-virtual')
if not address_virtual_list:
# XXX: address virtual is not present. In which case,
@@ -313,7 +375,7 @@ class addressvirtual(moduleBase):
return
self._apply_address_config(ifaceobj, address_virtual_list)
def _down(self, ifaceobj):
def _down(self, ifaceobj, ifaceobj_getfunc=None):
try:
self._remove_address_config(ifaceobj,
ifaceobj.get_attr_value('address-virtual'))
@@ -383,7 +445,7 @@ class addressvirtual(moduleBase):
av_idx += 1
return
def _query_running(self, ifaceobjrunning):
def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
macvlan_prefix = self._get_macvlan_prefix(ifaceobjrunning)
address_virtuals = glob.glob("/sys/class/net/%s*" %macvlan_prefix)
for av in address_virtuals:
@@ -411,7 +473,8 @@ class addressvirtual(moduleBase):
if not self.ipcmd:
self.ipcmd = iproute2()
def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
def run(self, ifaceobj, operation, query_ifaceobj=None,
ifaceobj_getfunc=None, **extra_args):
""" run vlan configuration on the interface object passed as argument
Args:
@@ -436,4 +499,4 @@ class addressvirtual(moduleBase):
if operation == 'query-checkcurr':
op_handler(self, ifaceobj, query_ifaceobj)
else:
op_handler(self, ifaceobj)
op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)