1
0
mirror of https://github.com/CumulusNetworks/ifupdown2.git synced 2024-05-06 15:54:50 +00:00
Files
CumulusNetworks-ifupdown2/ifupdownaddons/iproute2.py
Roopa Prabhu 42e85fc834 [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>
2016-10-19 22:23:05 -07:00

940 lines
34 KiB
Python

#!/usr/bin/python
#
# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
# Author: Roopa Prabhu, roopa@cumulusnetworks.com
#
import os
import glob
import shlex
import signal
import subprocess
from ifupdown.utils import utils
from collections import OrderedDict
from utilsbase import *
from systemutils import *
from cache import *
import ifupdown.ifupdownflags as ifupdownflags
VXLAN_UDP_PORT = 4789
class iproute2(utilsBase):
""" This class contains helper methods to cache and interact with the
commands in the iproute2 package """
_cache_fill_done = False
ipbatchbuf = ''
ipbatch = False
ipbatch_pause = False
def __init__(self, *args, **kargs):
utilsBase.__init__(self, *args, **kargs)
if ifupdownflags.flags.CACHE:
self._fill_cache()
self.supported_command = {
'/sbin/bridge -c -json vlan show': True
}
def _fill_cache(self):
if not iproute2._cache_fill_done:
self._link_fill()
self._addr_fill()
iproute2._cache_fill_done = True
return True
return False
def _get_vland_id(self, citems, i, warn):
try:
sub = citems[i:]
index = sub.index('id')
int(sub[index + 1])
return sub[index + 1]
except:
if warn:
raise Exception('invalid use of \'vlan\' keyword')
return None
def _link_fill(self, ifacename=None, refresh=False):
""" fills cache with link information
if ifacename argument given, fill cache for ifacename, else
fill cache for all interfaces in the system
"""
warn = True
linkout = {}
vxrd_running = False
if iproute2._cache_fill_done and not refresh: return
try:
# if ifacename already present, return
if (ifacename and not refresh and
linkCache.get_attr([ifacename, 'ifflag'])):
return
except:
pass
cmdout = self.link_show(ifacename=ifacename)
if not cmdout:
return
# read vxrd.pid and cache the running state before going through
# every interface in the system
if systemUtils.is_service_running(None, '/var/run/vxrd.pid'):
vxrd_running = True
for c in cmdout.splitlines():
citems = c.split()
ifnamenlink = citems[1].split('@')
if len(ifnamenlink) > 1:
ifname = ifnamenlink[0]
iflink = ifnamenlink[1].strip(':')
else:
ifname = ifnamenlink[0].strip(':')
iflink = None
linkattrs = {}
linkattrs['link'] = iflink
linkattrs['ifindex'] = citems[0].strip(':')
flags = citems[2].strip('<>').split(',')
linkattrs['flags'] = flags
linkattrs['ifflag'] = 'UP' if 'UP' in flags else 'DOWN'
for i in range(0, len(citems)):
try:
if citems[i] == 'mtu':
linkattrs['mtu'] = citems[i + 1]
elif citems[i] == 'state':
linkattrs['state'] = citems[i + 1]
elif citems[i] == 'link/ether':
linkattrs['hwaddress'] = citems[i + 1]
elif citems[i] == 'vlan':
vlanid = self._get_vland_id(citems, i, warn)
if vlanid:
linkattrs['linkinfo'] = {'vlanid': vlanid}
linkattrs['kind'] = 'vlan'
elif citems[i] == 'dummy':
linkattrs['kind'] = 'dummy'
elif citems[i] == 'vxlan' and citems[i + 1] == 'id':
linkattrs['kind'] = 'vxlan'
vattrs = {'vxlanid': citems[i + 2],
'svcnode': None,
'remote': [],
'ageing': citems[i + 2],
'learning': 'on'}
for j in range(i + 2, len(citems)):
if citems[j] == 'local':
vattrs['local'] = citems[j + 1]
elif citems[j] == 'remote':
vattrs['svcnode'] = citems[j + 1]
elif citems[j] == 'ageing':
vattrs['ageing'] = citems[j + 1]
elif citems[j] == 'nolearning':
vattrs['learning'] = 'off'
# get vxlan peer nodes if provisioned by user and not by vxrd
if not vxrd_running:
peers = self.get_vxlan_peers(ifname, vattrs['svcnode'])
if peers:
vattrs['remote'] = peers
linkattrs['linkinfo'] = vattrs
break
elif citems[i] == 'vrf' and citems[i + 1] == 'table':
vattrs = {'table': citems[i + 2]}
linkattrs['linkinfo'] = vattrs
linkattrs['kind'] = 'vrf'
linkCache.vrfs[ifname] = vattrs
break
elif citems[i] == 'vrf_slave':
linkattrs['kind'] = 'vrf_slave'
break
elif citems[i] == 'macvlan' and citems[i + 1] == 'mode':
linkattrs['kind'] = 'macvlan'
except Exception as e:
if warn:
self.logger.debug('%s: parsing error: id, mtu, state, link/ether, vlan, dummy, vxlan, local, remote, ageing, nolearning, vrf, table, vrf_slave are reserved keywords: %s' % (ifname, str(e)))
warn = False
#linkattrs['alias'] = self.read_file_oneline(
# '/sys/class/net/%s/ifalias' %ifname)
linkout[ifname] = linkattrs
[linkCache.update_attrdict([ifname], linkattrs)
for ifname, linkattrs in linkout.items()]
def _addr_filter(self, ifname, addr, scope=None):
default_addrs = ['127.0.0.1/8', '::1/128' , '0.0.0.0']
if ifname == 'lo' and addr in default_addrs:
return True
if scope and scope == 'link':
return True
return False
def _addr_fill(self, ifacename=None, refresh=False):
""" fills cache with address information
if ifacename argument given, fill cache for ifacename, else
fill cache for all interfaces in the system
"""
linkout = {}
if iproute2._cache_fill_done and not refresh: return
try:
# Check if ifacename is already full, in which case, return
if ifacename and not refresh:
linkCache.get_attr([ifacename, 'addrs'])
return
except:
pass
cmdout = self.addr_show(ifacename=ifacename)
if not cmdout:
return
for c in cmdout.splitlines():
citems = c.split()
ifnamenlink = citems[1].split('@')
if len(ifnamenlink) > 1:
ifname = ifnamenlink[0]
else:
ifname = ifnamenlink[0].strip(':')
if not linkout.get(ifname):
linkattrs = {}
linkattrs['addrs'] = OrderedDict({})
try:
linkout[ifname].update(linkattrs)
except KeyError:
linkout[ifname] = linkattrs
if citems[2] == 'inet':
if self._addr_filter(ifname, citems[3], scope=citems[5]):
continue
addrattrs = {}
addrattrs['scope'] = citems[5]
addrattrs['type'] = 'inet'
linkout[ifname]['addrs'][citems[3]] = addrattrs
elif citems[2] == 'inet6':
if self._addr_filter(ifname, citems[3], scope=citems[5]):
continue
if citems[5] == 'link': continue #skip 'link' addresses
addrattrs = {}
addrattrs['scope'] = citems[5]
addrattrs['type'] = 'inet6'
linkout[ifname]['addrs'][citems[3]] = addrattrs
[linkCache.update_attrdict([ifname], linkattrs)
for ifname, linkattrs in linkout.items()]
def _cache_get(self, type, attrlist, refresh=False):
try:
if ifupdownflags.flags.DRYRUN:
return False
if ifupdownflags.flags.CACHE:
if self._fill_cache():
# if we filled the cache, return new data
return linkCache.get_attr(attrlist)
if not refresh:
return linkCache.get_attr(attrlist)
if type == 'link':
self._link_fill(attrlist[0], refresh)
elif type == 'addr':
self._addr_fill(attrlist[0], refresh)
else:
self._link_fill(attrlist[0], refresh)
self._addr_fill(attrlist[0], refresh)
return linkCache.get_attr(attrlist)
except Exception, e:
self.logger.debug('_cache_get(%s) : [%s]'
%(str(attrlist), str(e)))
pass
return None
def _cache_check(self, type, attrlist, value, refresh=False):
try:
attrvalue = self._cache_get(type, attrlist, refresh)
if attrvalue and attrvalue == value:
return True
except Exception, e:
self.logger.debug('_cache_check(%s) : [%s]'
%(str(attrlist), str(e)))
pass
return False
def _cache_update(self, attrlist, value):
if ifupdownflags.flags.DRYRUN: return
try:
linkCache.add_attr(attrlist, value)
except:
pass
def _cache_delete(self, attrlist):
if ifupdownflags.flags.DRYRUN: return
try:
linkCache.del_attr(attrlist)
except:
pass
def _cache_invalidate(self):
linkCache.invalidate()
iproute2._cache_fill_done = False
def batch_start(self):
self.ipbatcbuf = ''
self.ipbatch = True
self.ipbatch_pause = False
def add_to_batch(self, cmd):
self.ipbatchbuf += cmd + '\n'
def batch_pause(self):
self.ipbatch_pause = True
def batch_resume(self):
self.ipbatch_pause = False
def batch_commit(self):
if not self.ipbatchbuf:
self.ipbatchbuf = ''
self.ipbatch = False
self.ipbatch_pause = False
return
try:
utils.exec_command('ip -force -batch -', stdin=self.ipbatchbuf)
except:
raise
finally:
self.ipbatchbuf = ''
self.ipbatch = False
self.ipbatch_pause = False
def bridge_batch_commit(self):
if not self.ipbatchbuf:
self.ipbatchbuf = ''
self.ipbatch = False
self.ipbatch_pause = False
return
try:
utils.exec_command('bridge -force -batch -', stdin=self.ipbatchbuf)
except:
raise
finally:
self.ipbatchbuf = ''
self.ipbatch = False
self.ipbatch_pause = False
def addr_show(self, ifacename=None):
if ifacename:
if not self.link_exists(ifacename):
return
return utils.exec_commandl(['ip', '-o', 'addr', 'show', 'dev',
ifacename])
else:
return utils.exec_commandl(['ip', '-o', 'addr', 'show'])
def link_show(self, ifacename=None):
if ifacename:
return utils.exec_commandl(['ip', '-o', '-d', 'link', 'show', 'dev',
ifacename])
else:
return utils.exec_commandl(['ip', '-o', '-d', 'link', 'show'])
def addr_add(self, ifacename, address, broadcast=None,
peer=None, scope=None, preferred_lifetime=None):
if not address:
return
cmd = 'addr add %s' %address
if broadcast:
cmd += ' broadcast %s' %broadcast
if peer:
cmd += ' peer %s' %peer
if scope:
cmd += ' scope %s' %scope
if preferred_lifetime:
cmd += ' preferred_lft %s' %preferred_lifetime
cmd += ' dev %s' %ifacename
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
self._cache_update([ifacename, 'addrs', address], {})
def addr_del(self, ifacename, address, broadcast=None,
peer=None, scope=None):
""" Delete ipv4 address """
if not address:
return
if not self._cache_get('addr', [ifacename, 'addrs', address]):
return
cmd = 'addr del %s' %address
if broadcast:
cmd += 'broadcast %s' %broadcast
if peer:
cmd += 'peer %s' %peer
if scope:
cmd += 'scope %s' %scope
cmd += ' dev %s' %ifacename
utils.exec_command('ip %s' % cmd)
self._cache_delete([ifacename, 'addrs', address])
def addr_flush(self, ifacename):
cmd = 'addr flush dev %s' %ifacename
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
self._cache_delete([ifacename, 'addrs'])
def del_addr_all(self, ifacename, skip_addrs=[]):
if not skip_addrs: skip_addrs = []
runningaddrsdict = self.addr_get(ifacename)
try:
# XXX: ignore errors. Fix this to delete secondary addresses
# first
[self.addr_del(ifacename, a) for a in
set(runningaddrsdict.keys()).difference(skip_addrs)]
except:
# ignore errors
pass
def addr_get(self, ifacename, details=True, refresh=False):
addrs = self._cache_get('addr', [ifacename, 'addrs'],
refresh=refresh)
if not addrs:
return None
if details:
return addrs
return addrs.keys()
def addr_add_multiple(self, ifacename, addrs, purge_existing=False):
# purges address
if purge_existing:
# if perfmode is not set and also if iface has no sibling
# objects, purge addresses that are not present in the new
# config
runningaddrs = self.addr_get(ifacename, details=False)
if addrs == runningaddrs:
return
try:
# if primary address is not same, there is no need to keep any.
# reset all addresses
if (addrs and runningaddrs and
(addrs[0] != runningaddrs[0])):
self.del_addr_all(ifacename)
else:
self.del_addr_all(ifacename, addrs)
except Exception, e:
self.log_warn(str(e))
for a in addrs:
try:
self.addr_add(ifacename, a)
except Exception, e:
self.logger.error(str(e))
def _link_set_ifflag(self, ifacename, value):
# Dont look at the cache, the cache may have stale value
# because link status can be changed by external
# entity (One such entity is ifupdown main program)
cmd = 'link set dev %s %s' %(ifacename, value.lower())
if self.ipbatch:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
def link_up(self, ifacename):
self._link_set_ifflag(ifacename, 'UP')
def link_down(self, ifacename):
self._link_set_ifflag(ifacename, 'DOWN')
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)):
return
cmd = 'link set dev %s' %ifacename
if type:
cmd += ' type %s' %type
cmd += ' %s' %key
if value:
cmd += ' %s' %value
if state:
cmd += ' %s' %state
if self.ipbatch:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
if key not in ['master', 'nomaster']:
self._cache_update([ifacename, key], value)
def link_set_hwaddress(self, ifacename, hwaddress, force=False):
if not force:
if self._cache_check('link', [ifacename, 'hwaddress'], hwaddress):
return
self.link_down(ifacename)
cmd = 'link set dev %s address %s' %(ifacename, hwaddress)
if self.ipbatch:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
self.link_up(ifacename)
self._cache_update([ifacename, 'hwaddress'], hwaddress)
def link_set_mtu(self, ifacename, mtu):
if ifupdownflags.flags.DRYRUN:
return True
if not mtu or not ifacename: return
with open('/sys/class/net/%s/mtu' % ifacename, 'w') as f:
f.write(mtu)
self._cache_update([ifacename, 'mtu'], mtu)
def link_set_alias(self, ifacename, alias):
utils.exec_commandl(['ip', 'link', 'set', 'dev', ifacename,
'alias', alias])
def link_get_alias(self, ifacename):
return self.read_file_oneline('/sys/class/net/%s/ifalias'
%ifacename)
def link_isloopback(self, ifacename):
flags = self._cache_get('link', [ifacename, 'flags'])
if not flags:
return
if 'LOOPBACK' in flags:
return True
return False
def link_get_status(self, ifacename):
return self._cache_get('link', [ifacename, 'ifflag'], refresh=True)
def route_add_gateway(self, ifacename, gateway, vrf=None, metric=None):
if not gateway:
return
if not vrf:
cmd = 'ip route add default via %s' %gateway
else:
cmd = 'ip route add table %s default via %s' %(vrf, gateway)
# Add metric
if metric:
cmd += 'metric %s' %metric
cmd += ' dev %s' %ifacename
utils.exec_command(cmd)
def route_del_gateway(self, ifacename, gateway, vrf=None, metric=None):
# delete default gw
if not gateway:
return
if not vrf:
cmd = 'ip route del default via %s' %gateway
else:
cmd = 'ip route del table %s default via %s' %(vrf, gateway)
if metric:
cmd += ' metric %s' %metric
cmd += ' dev %s' %ifacename
utils.exec_command(cmd)
def route6_add_gateway(self, ifacename, gateway):
if not gateway:
return
return utils.exec_command('ip -6 route add default via %s dev %s' %
(gateway, ifacename))
def route6_del_gateway(self, ifacename, gateway):
if not gateway:
return
return utils.exec_command('ip -6 route del default via %s dev %s' %
(gateway, ifacename))
def link_create_vlan(self, vlan_device_name, vlan_raw_device, vlanid):
if self.link_exists(vlan_device_name):
return
utils.exec_command('ip link add link %s name %s type vlan id %d' %
(vlan_raw_device, vlan_device_name, vlanid))
self._cache_update([vlan_device_name], {})
def link_create_vlan_from_name(self, vlan_device_name):
v = vlan_device_name.split('.')
if len(v) != 2:
self.logger.warn('invalid vlan device name %s' %vlan_device_name)
return
self.link_create_vlan(vlan_device_name, v[0], v[1])
def link_create_macvlan(self, name, linkdev, mode='private'):
if self.link_exists(name):
return
cmd = ('link add link %s' %linkdev +
' name %s' %name +
' type macvlan mode %s' %mode)
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
self._cache_update([name], {})
def get_vxlan_peers(self, dev, svcnodeip):
cmd = 'bridge fdb show brport %s' % dev
cur_peers = []
try:
ps = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, close_fds=False)
utils.enable_subprocess_signal_forwarding(ps, signal.SIGINT)
output = subprocess.check_output(('grep', '00:00:00:00:00:00'), stdin=ps.stdout)
ps.wait()
utils.disable_subprocess_signal_forwarding(signal.SIGINT)
try:
ppat = re.compile('\s+dst\s+(\d+.\d+.\d+.\d+)\s+')
for l in output.split('\n'):
m = ppat.search(l)
if m and m.group(1) != svcnodeip:
cur_peers.append(m.group(1))
except:
self.logger.warn('error parsing ip link output')
pass
except subprocess.CalledProcessError as e:
if e.returncode != 1:
self.logger.error(str(e))
finally:
utils.disable_subprocess_signal_forwarding(signal.SIGINT)
return cur_peers
def link_create_vxlan(self, name, vxlanid,
localtunnelip=None,
svcnodeip=None,
remoteips=None,
learning='on',
ageing=None,
anycastip=None):
if svcnodeip and remoteips:
raise Exception("svcnodeip and remoteip is mutually exclusive")
args = ''
if svcnodeip:
args += ' remote %s' %svcnodeip
if ageing:
args += ' ageing %s' %ageing
if learning == 'off':
args += ' nolearning'
if self.link_exists(name):
cmd = 'link set dev %s type vxlan dstport %d' %(name, VXLAN_UDP_PORT)
vxlanattrs = self.get_vxlandev_attrs(name)
# on ifreload do not overwrite anycast_ip to individual ip if clagd
# has modified
if vxlanattrs:
running_localtunnelip = vxlanattrs.get('local')
if anycastip and running_localtunnelip and anycastip == running_localtunnelip:
localtunnelip = running_localtunnelip
running_svcnode = vxlanattrs.get('svcnode')
if running_svcnode and not svcnodeip:
args += ' noremote'
else:
cmd = 'link add dev %s type vxlan id %s dstport %d' %(name, vxlanid, VXLAN_UDP_PORT)
if localtunnelip:
args += ' local %s' %localtunnelip
cmd += args
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
# XXX: update linkinfo correctly
self._cache_update([name], {})
def link_exists(self, ifacename):
if ifupdownflags.flags.DRYRUN:
return True
return os.path.exists('/sys/class/net/%s' %ifacename)
def link_get_ifindex(self, ifacename):
if ifupdownflags.flags.DRYRUN:
return True
return self.read_file_oneline('/sys/class/net/%s/ifindex' %ifacename)
def is_vlan_device_by_name(self, ifacename):
if re.search(r'\.', ifacename):
return True
return False
def route_add(self, route):
utils.exec_command('ip route add %s' % route)
def route6_add(self, route):
utils.exec_command('ip -6 route add %s' % route)
def get_vlandev_attrs(self, ifacename):
return (self._cache_get('link', [ifacename, 'link']),
self._cache_get('link', [ifacename, 'linkinfo', 'vlanid']))
def get_vxlandev_attrs(self, ifacename):
return self._cache_get('link', [ifacename, 'linkinfo'])
def link_get_linkinfo_attrs(self, ifacename):
return self._cache_get('link', [ifacename, 'linkinfo'])
def link_get_mtu(self, ifacename, refresh=False):
return self._cache_get('link', [ifacename, 'mtu'], refresh=refresh)
def link_get_kind(self, ifacename):
return self._cache_get('link', [ifacename, 'kind'])
def link_get_hwaddress(self, ifacename):
address = self._cache_get('link', [ifacename, 'hwaddress'])
# newly created logical interface addresses dont end up in the cache
# read hwaddress from sysfs file for these interfaces
if not address:
address = self.read_file_oneline('/sys/class/net/%s/address'
%ifacename)
return address
def link_create(self, ifacename, type, attrs={}):
""" generic link_create function """
if self.link_exists(ifacename):
return
cmd = 'link add'
cmd += ' name %s type %s' %(ifacename, type)
if attrs:
for k, v in attrs.iteritems():
cmd += ' %s' %k
if v:
cmd += ' %s' %v
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
self._cache_update([ifacename], {})
def link_delete(self, ifacename):
if not self.link_exists(ifacename):
return
cmd = 'link del %s' %ifacename
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
self._cache_invalidate()
def link_get_master(self, ifacename):
sysfs_master_path = '/sys/class/net/%s/master' %ifacename
if os.path.exists(sysfs_master_path):
link_path = os.readlink(sysfs_master_path)
if link_path:
return os.path.basename(link_path)
else:
return None
else:
return self._cache_get('link', [ifacename, 'master'])
def bridge_port_vids_add(self, bridgeportname, vids):
[utils.exec_command('bridge vlan add vid %s dev %s' %
(v, bridgeportname)) for v in vids]
def bridge_port_vids_del(self, bridgeportname, vids):
if not vids:
return
[utils.exec_command('bridge vlan del vid %s dev %s' %
(v, bridgeportname)) for v in vids]
def bridge_port_vids_flush(self, bridgeportname, vid):
utils.exec_command('bridge vlan del vid %s dev %s' %
(vid, bridgeportname))
def bridge_port_vids_get(self, bridgeportname):
utils.exec_command('/sbin/bridge vlan show %s' % bridgeportname)
bridgeout = utils.exec_command('/sbin/bridge vlan show dev %s' %
bridgeportname)
if not bridgeout: return []
brvlanlines = bridgeout.readlines()[2:]
vids = [l.strip() for l in brvlanlines]
return [v for v in vids if v]
def bridge_port_vids_get_all(self):
brvlaninfo = {}
bridgeout = utils.exec_command('/sbin/bridge -c vlan show')
if not bridgeout: return brvlaninfo
brvlanlines = bridgeout.splitlines()
brportname=None
for l in brvlanlines[1:]:
if l and not l.startswith(' ') and not l.startswith('\t'):
attrs = l.split()
brportname = attrs[0].strip()
brvlaninfo[brportname] = {'pvid' : None, 'vlan' : []}
l = ' '.join(attrs[1:])
if not brportname or not l:
continue
l = l.strip()
if 'PVID' in l:
brvlaninfo[brportname]['pvid'] = l.split()[0]
elif 'Egress Untagged' not in l:
brvlaninfo[brportname]['vlan'].append(l)
return brvlaninfo
def bridge_port_vids_get_all_json(self):
if not self.supported_command['/sbin/bridge -c -json vlan show']:
return {}
brvlaninfo = {}
try:
bridgeout = utils.exec_command('/sbin/bridge -c -json vlan show')
except:
self.supported_command['/sbin/bridge -c -json vlan show'] = False
self.logger.info('/sbin/bridge -c -json vlan show: skipping unsupported command')
return {}
if not bridgeout: return brvlaninfo
try:
vlan_json_dict = json.loads(bridgeout, encoding="utf-8")
except Exception, e:
self.logger.info('json loads failed with (%s)' %str(e))
return {}
return vlan_json_dict
def bridge_port_pvid_add(self, bridgeportname, pvid):
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch('vlan add vid %s untagged pvid dev %s' %
(pvid, bridgeportname))
else:
utils.exec_command('bridge vlan add vid %s untagged pvid dev %s' %
(pvid, bridgeportname))
def bridge_port_pvid_del(self, bridgeportname, pvid):
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch('vlan del vid %s untagged pvid dev %s' %
(pvid, bridgeportname))
else:
utils.exec_command('bridge vlan del vid %s untagged pvid dev %s' %
(pvid, bridgeportname))
def bridge_port_pvids_get(self, bridgeportname):
return self.read_file_oneline('/sys/class/net/%s/brport/pvid'
%bridgeportname)
def bridge_vids_add(self, bridgeportname, vids, bridge=True):
target = 'self' if bridge else ''
if self.ipbatch and not self.ipbatch_pause:
[self.add_to_batch('vlan add vid %s dev %s %s' %
(v, bridgeportname, target)) for v in vids]
else:
[utils.exec_command('bridge vlan add vid %s dev %s %s' %
(v, bridgeportname, target)) for v in vids]
def bridge_vids_del(self, bridgeportname, vids, bridge=True):
target = 'self' if bridge else ''
if self.ipbatch and not self.ipbatch_pause:
[self.add_to_batch('vlan del vid %s dev %s %s' %
(v, bridgeportname, target)) for v in vids]
else:
[utils.exec_command('bridge vlan del vid %s dev %s %s' %
(v, bridgeportname, target)) for v in vids]
def bridge_fdb_add(self, dev, address, vlan=None, bridge=True, remote=None):
target = 'self' if bridge else ''
vlan_str = ''
if vlan:
vlan_str = 'vlan %s ' % vlan
dst_str = ''
if remote:
dst_str = 'dst %s ' % remote
utils.exec_command('bridge fdb replace %s dev %s %s %s %s' %
(address, dev, vlan_str, target, dst_str))
def bridge_fdb_append(self, dev, address, vlan=None, bridge=True, remote=None):
target = 'self' if bridge else ''
vlan_str = ''
if vlan:
vlan_str = 'vlan %s ' % vlan
dst_str = ''
if remote:
dst_str = 'dst %s ' % remote
utils.exec_command('bridge fdb append %s dev %s %s %s %s' %
(address, dev, vlan_str, target, dst_str))
def bridge_fdb_del(self, dev, address, vlan=None, bridge=True, remote=None):
target = 'self' if bridge else ''
vlan_str = ''
if vlan:
vlan_str = 'vlan %s ' % vlan
dst_str = ''
if remote:
dst_str = 'dst %s ' % remote
utils.exec_command('bridge fdb del %s dev %s %s %s %s' %
(address, dev, vlan_str, target, dst_str))
def bridge_is_vlan_aware(self, bridgename):
filename = '/sys/class/net/%s/bridge/vlan_filtering' %bridgename
if os.path.exists(filename) and self.read_file_oneline(filename) == '1':
return True
return False
def bridge_port_get_bridge_name(self, bridgeport):
filename = '/sys/class/net/%s/brport/bridge' %bridgeport
try:
return os.path.basename(os.readlink(filename))
except:
return None
def bridge_port_exists(self, bridge, bridgeportname):
try:
return os.path.exists('/sys/class/net/%s/brif/%s'
%(bridge, bridgeportname))
except Exception:
return False
def bridge_fdb_show_dev(self, dev):
try:
fdbs = {}
output = utils.exec_command('bridge fdb show dev %s' % dev)
if output:
for fdb_entry in output.splitlines():
try:
entries = fdb_entry.split()
fdbs.setdefault(entries[2], []).append(entries[0])
except:
self.logger.debug('%s: invalid fdb line \'%s\''
%(dev, fdb_entry))
pass
return fdbs
except Exception:
return None
def is_bridge(self, bridge):
return os.path.exists('/sys/class/net/%s/bridge' %bridge)
def is_link_up(self, ifacename):
ret = False
try:
flags = self.read_file_oneline('/sys/class/net/%s/flags' %ifacename)
iflags = int(flags, 16)
if (iflags & 0x0001):
ret = True
except:
ret = False
pass
return ret
def ip_route_get_dev(self, prefix):
try:
output = utils.exec_command('ip route get %s' % prefix)
if output:
rline = output.splitlines()[0]
if rline:
rattrs = rline.split()
return rattrs[rattrs.index('dev') + 1]
except Exception, e:
self.logger.debug('ip_route_get_dev: failed .. %s' %str(e))
pass
return None
def link_get_lowers(self, ifacename):
try:
lowers = glob.glob("/sys/class/net/%s/lower_*" %ifacename)
if not lowers:
return []
return [os.path.basename(l)[6:] for l in lowers]
except:
return []
def link_get_uppers(self, ifacename):
try:
uppers = glob.glob("/sys/class/net/%s/upper_*" %ifacename)
if not uppers:
return None
return [ os.path.basename(u)[6:] for u in uppers ]
except:
return None
def link_get_vrfs(self):
self._fill_cache()
return linkCache.vrfs