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)

View File

@@ -151,8 +151,7 @@ class vrf(moduleBase):
continue
self.iproute2_vrf_map[int(table)] = vrf_name
except Exception, e:
self.logger.info('vrf: iproute2_vrf_map: unable to parse %s'
%l)
self.logger.info('vrf: iproute2_vrf_map: unable to parse %s (%s)' %(l, str(e)))
pass
vrfs = self.ipcmd.link_get_vrfs()
@@ -392,8 +391,8 @@ class vrf(moduleBase):
try:
master_exists = True
if vrf_exists or self.ipcmd.link_exists(vrfname):
upper = self.ipcmd.link_get_upper(ifacename)
if not upper or upper != vrfname:
uppers = self.ipcmd.link_get_uppers(ifacename)
if not uppers or vrfname not in uppers:
self._handle_existing_connections(ifaceobj, vrfname)
self.ipcmd.link_set(ifacename, 'master', vrfname)
elif ifaceobj:

View File

@@ -62,6 +62,7 @@ class ifaceLinkPrivFlags():
VRF_SLAVE = 0x00100
BRIDGE_VLAN_AWARE = 0x01000
BRIDGE_VXLAN = 0x10000
ADDRESS_VIRTUAL_SLAVE = 0x100000
@classmethod
def get_str(cls, flag):

View File

@@ -434,7 +434,8 @@ class iproute2(utilsBase):
def link_down(self, ifacename):
self._link_set_ifflag(ifacename, 'DOWN')
def link_set(self, ifacename, key, value=None, force=False, type=None):
def link_set(self, ifacename, key, value=None,
force=False, type=None, state=None):
if not force:
if (key not in ['master', 'nomaster'] and
self._cache_check('link', [ifacename, key], value)):
@@ -445,6 +446,8 @@ class iproute2(utilsBase):
cmd += ' %s' %key
if value:
cmd += ' %s' %value
if state:
cmd += ' %s' %state
if self.ipbatch:
self.add_to_batch(cmd)
else:
@@ -922,12 +925,12 @@ class iproute2(utilsBase):
except:
return []
def link_get_upper(self, ifacename):
def link_get_uppers(self, ifacename):
try:
upper = glob.glob("/sys/class/net/%s/upper_*" %ifacename)
if not upper:
uppers = glob.glob("/sys/class/net/%s/upper_*" %ifacename)
if not uppers:
return None
return os.path.basename(upper[0])[6:]
return [ os.path.basename(u)[6:] for u in uppers ]
except:
return None