+++ /dev/null
-#!/usr/bin/python
-#
-# Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
-# Author: Roopa Prabhu, roopa@cumulusnetworks.com
-# Julien Fortin, julien@cumulusnetworks.com
-#
-
-import os
-import re
-import glob
-import shlex
-import signal
-import socket
-import subprocess
-
-from string import maketrans
-from ipaddr import IPNetwork, IPv6Network
-
-try:
- import ifupdown2.ifupdown.statemanager as statemanager
- import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
-
- from ifupdown2.nlmanager.nlmanager import Link, Route
-
- from ifupdown2.ifupdown.iface import *
- from ifupdown2.ifupdown.utils import utils
- from ifupdown2.ifupdown.netlink import netlink
-
- from ifupdown2.ifupdownaddons.utilsbase import utilsBase
- from ifupdown2.ifupdownaddons.cache import linkCache, MSTPAttrsCache
-except ImportError:
- import ifupdown.ifupdownflags as ifupdownflags
- import ifupdown.statemanager as statemanager
-
- from nlmanager.nlmanager import Link, Route
-
- from ifupdown.iface import *
- from ifupdown.utils import utils
- from ifupdown.netlink import netlink
-
- from ifupdownaddons.utilsbase import utilsBase
- from ifupdownaddons.cache import linkCache, MSTPAttrsCache
-
-
-class LinkUtils(utilsBase):
- """
- This class contains helper methods to cache and manipulate interfaces through
- non-netlink APIs (sysfs, iproute2, brctl...)
- """
- _CACHE_FILL_DONE = False
- VXLAN_UDP_PORT = 4789
-
- ipbatchbuf = ''
- ipbatch = False
- ipbatch_pause = False
-
- bridge_utils_is_installed = os.path.exists(utils.brctl_cmd)
- bridge_utils_missing_warning = True
-
- DEFAULT_IP_METRIC = 1024
- ADDR_METRIC_SUPPORT = None
-
- mac_translate_tab = maketrans(":.-,", " ")
-
- def __init__(self, *args, **kargs):
- utilsBase.__init__(self, *args, **kargs)
-
- self.supported_command = {
- '%s -c -json vlan show' % utils.bridge_cmd: True,
- 'showmcqv4src': True
- }
- self.bridge_vlan_cache = {}
- self.bridge_vlan_cache_fill_done = False
-
- if not ifupdownflags.flags.PERFMODE and not LinkUtils._CACHE_FILL_DONE:
- self._fill_cache()
-
- if LinkUtils.ADDR_METRIC_SUPPORT is None:
- try:
- cmd = [utils.ip_cmd, 'addr', 'help']
- self.logger.info('executing %s addr help' % utils.ip_cmd)
-
- process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- stdout, stderr = process.communicate()
- LinkUtils.ADDR_METRIC_SUPPORT = '[ metric METRIC ]' in stderr or ''
- self.logger.info('address metric support: %s' % ('OK' if LinkUtils.ADDR_METRIC_SUPPORT else 'KO'))
- except Exception:
- LinkUtils.ADDR_METRIC_SUPPORT = False
- self.logger.info('address metric support: KO')
-
- @classmethod
- def mac_str_to_int(cls, mac):
- mac_int = 0
- if mac:
- for n in mac.translate(cls.mac_translate_tab).split():
- mac_int += int(n, 16)
- return mac_int
-
- @classmethod
- def addr_metric_support(cls):
- return cls.ADDR_METRIC_SUPPORT
-
- @classmethod
- def get_default_ip_metric(cls):
- return cls.DEFAULT_IP_METRIC
-
- @classmethod
- def reset(cls):
- LinkUtils._CACHE_FILL_DONE = False
- LinkUtils.ipbatchbuf = ''
- LinkUtils.ipbatch = False
- LinkUtils.ipbatch_pause = False
-
- def _fill_cache(self):
- if not LinkUtils._CACHE_FILL_DONE:
- self._link_fill()
- self._addr_fill()
- LinkUtils._CACHE_FILL_DONE = True
- return True
- return False
-
- @staticmethod
- def _get_vland_id(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
- """
-
- if LinkUtils._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
-
- if True:
- try:
- [linkCache.update_attrdict([ifname], linkattrs)
- for ifname, linkattrs in netlink.link_dump(ifacename).items()]
- except Exception as e:
- self.logger.info('%s' % str(e))
- # this netlink call replaces the call to _link_fill_iproute2_cmd()
- # We shouldn't have netlink calls in the iproute2 module, this will
- # be removed in the future. We plan to release, a flexible backend
- # (netlink+iproute2) by default we will use netlink backend but with
- # a CLI arg we can switch to iproute2 backend.
- # Until we decide to create this "backend" switch capability,
- # we have to put the netlink call inside the iproute2 module.
- else:
- self._link_fill_iproute2_cmd(ifacename, refresh)
-
- self._fill_bond_info(ifacename)
- self._fill_bridge_info(ifacename)
-
- def _fill_bridge_info(self, ifacename):
-
- if True: # netlink
- brports = {}
-
- if ifacename:
- cache_dict = {ifacename: linkCache.links.get(ifacename, {})}
- else:
- cache_dict = linkCache.links
-
- for ifname, obj in cache_dict.items():
- slave_kind = obj.get('slave_kind')
- if not slave_kind and slave_kind != 'bridge':
- continue
-
- info_slave_data = obj.get('info_slave_data')
- if not info_slave_data:
- continue
-
- ifla_master = obj.get('master')
- if not ifla_master:
- raise Exception('No master associated with bridge port %s' % ifname)
-
- for nl_attr in [
- Link.IFLA_BRPORT_STATE,
- Link.IFLA_BRPORT_COST,
- Link.IFLA_BRPORT_PRIORITY,
- ]:
- if nl_attr not in info_slave_data and LinkUtils.bridge_utils_is_installed:
- self._fill_bridge_info_brctl()
- return
-
- brport_attrs = {
- 'pathcost': str(info_slave_data.get(Link.IFLA_BRPORT_COST, 0)),
- 'fdelay': format(float(info_slave_data.get(Link.IFLA_BRPORT_FORWARD_DELAY_TIMER, 0) / 100), '.2f'),
- 'portmcrouter': str(info_slave_data.get(Link.IFLA_BRPORT_MULTICAST_ROUTER, 0)),
- 'portmcfl': str(info_slave_data.get(Link.IFLA_BRPORT_FAST_LEAVE, 0)),
- 'portprio': str(info_slave_data.get(Link.IFLA_BRPORT_PRIORITY, 0)),
- 'unicast-flood': str(info_slave_data.get(Link.IFLA_BRPORT_UNICAST_FLOOD, 0)),
- 'multicast-flood': str(info_slave_data.get(Link.IFLA_BRPORT_MCAST_FLOOD, 0)),
- 'learning': str(info_slave_data.get(Link.IFLA_BRPORT_LEARNING, 0)),
- 'arp-nd-suppress': str(info_slave_data.get(Link.IFLA_BRPORT_ARP_SUPPRESS, 0))
- }
-
- if ifla_master in brports:
- brports[ifla_master][ifname] = brport_attrs
- else:
- brports[ifla_master] = {ifname: brport_attrs}
-
- linkCache.update_attrdict([ifla_master, 'linkinfo', 'ports'], brports[ifla_master])
- else:
- if LinkUtils.bridge_utils_is_installed:
- self._fill_bridge_info_brctl()
-
- def _fill_bridge_info_brctl(self):
- brctlout = utils.exec_command('%s show' % utils.brctl_cmd)
- if not brctlout:
- return
-
- for bline in brctlout.splitlines()[1:]:
- bitems = bline.split()
- if len(bitems) < 2:
- continue
- try:
- linkCache.update_attrdict([bitems[0], 'linkinfo'],
- {'stp': bitems[2]})
- except KeyError:
- linkCache.update_attrdict([bitems[0]],
- {'linkinfo': {'stp': bitems[2]}})
- self._bridge_attrs_fill(bitems[0])
-
- def _bridge_attrs_fill(self, bridgename):
- battrs = {}
- bports = {}
-
- try:
- # Get all bridge attributes
- # battrs['pathcost'] = broutlines[3].split('path cost')[1].strip()
-
- try:
- battrs['maxage'] = self.read_file_oneline(
- '/sys/class/net/%s/bridge/max_age' % bridgename)
- except:
- pass
-
-
- try:
- battrs['hello'] = self.read_file_oneline(
- '/sys/class/net/%s/bridge/hello_time' % bridgename)
- except:
- pass
-
- try:
- battrs['fd'] = self.read_file_oneline(
- '/sys/class/net/%s/bridge/forward_delay' % bridgename)
- except:
- pass
-
- try:
- battrs['ageing'] = self.read_file_oneline(
- '/sys/class/net/%s/bridge/ageing_time' % bridgename)
- except:
- pass
-
- try:
- battrs['mcrouter'] = self.read_file_oneline(
- '/sys/class/net/%s/bridge/multicast_router' % bridgename)
- except:
- pass
-
- try:
- battrs['bridgeprio'] = self.read_file_oneline(
- '/sys/class/net/%s/bridge/priority' % bridgename)
- except:
- pass
-
- try:
- battrs['vlan-protocol'] = VlanProtocols.ID_TO_ETHERTYPES[
- self.read_file_oneline(
- '/sys/class/net/%s/bridge/vlan_protocol' % bridgename)]
- except:
- pass
-
- try:
- battrs.update(self._bridge_get_mcattrs_from_sysfs(bridgename))
- except:
- pass
-
- # XXX: comment this out until mc attributes become available
- # with brctl again
-
- # battrs['mciqc'] = broutlines[11].split('mc init query count')[1].strip()
- # battrs['mclmt'] = broutlines[13].split('mc last member timer')[1].split()[0].strip()
- except Exception, e:
- self.logger.warn('%s: error while processing bridge attributes: %s' % (bridgename, str(e)))
- pass
-
- linkCache.update_attrdict([bridgename, 'linkinfo'], battrs)
-
- names = [os.path.basename(x) for x in glob.glob("/sys/class/net/%s/brif/*" % bridgename)]
- for pname in names:
- bportattrs = {}
- try:
-
- bportattrs['pathcost'] = self.read_file_oneline(
- '/sys/class/net/%s/brport/path_cost' % pname)
- bportattrs['fdelay'] = self.read_file_oneline(
- '/sys/class/net/%s/brport/forward_delay_timer' % pname)
- bportattrs['portmcrouter'] = self.read_file_oneline(
- '/sys/class/net/%s/brport/multicast_router' % pname)
- bportattrs['portmcfl'] = self.read_file_oneline(
- '/sys/class/net/%s/brport/multicast_fast_leave' % pname)
- bportattrs['portprio'] = self.read_file_oneline(
- '/sys/class/net/%s/brport/priority' % pname)
- bportattrs['unicast-flood'] = self.read_file_oneline(
- '/sys/class/net/%s/brport/unicast_flood' % pname)
- bportattrs['multicast-flood'] = self.read_file_oneline(
- '/sys/class/net/%s/brport/multicast_flood' % pname)
- bportattrs['learning'] = self.read_file_oneline(
- '/sys/class/net/%s/brport/learning' % pname)
- bportattrs['arp-nd-suppress'] = self.read_file_oneline(
- '/sys/class/net/%s/brport/neigh_suppress' % pname)
-
- #bportattrs['mcrouters'] = self.read_file_oneline(
- # '/sys/class/net/%s/brport/multicast_router' % pname)
- #bportattrs['mc fast leave'] = self.read_file_oneline(
- # '/sys/class/net/%s/brport/multicast_fast_leave' % pname)
-
- except Exception, e:
- self.logger.warn('%s: error while processing bridge attributes: %s' % (bridgename, str(e)))
- bports[pname] = bportattrs
- linkCache.update_attrdict([bridgename, 'linkinfo', 'ports'], bports)
-
- _bridge_sysfs_mcattrs = {
- 'mclmc': 'multicast_last_member_count',
- 'mcrouter': 'multicast_router',
- 'mcsnoop': 'multicast_snooping',
- 'mcsqc': 'multicast_startup_query_count',
- 'mcqifaddr': 'multicast_query_use_ifaddr',
- 'mcquerier': 'multicast_querier',
- 'hashel': 'hash_elasticity',
- 'hashmax': 'hash_max',
- 'mclmi': 'multicast_last_member_interval',
- 'mcmi': 'multicast_membership_interval',
- 'mcqpi': 'multicast_querier_interval',
- 'mcqi': 'multicast_query_interval',
- 'mcqri': 'multicast_query_response_interval',
- 'mcsqi': 'multicast_startup_query_interval',
- 'igmp-version': 'multicast_igmp_version',
- 'mld-version': 'multicast_mld_version',
- 'vlan-stats': 'vlan_stats_enabled',
- 'mcstats': 'multicast_stats_enabled',
- }
-
- def _bridge_get_mcattrs_from_sysfs(self, bridgename):
- mcattrsdivby100 = ['mclmi', 'mcmi', 'mcqpi', 'mcqi', 'mcqri', 'mcsqi']
- mcattrs = {}
-
- for m, s in self._bridge_sysfs_mcattrs.items():
- n = self.read_file_oneline('/sys/class/net/%s/bridge/%s' % (bridgename, s))
- if m in mcattrsdivby100:
- try:
- v = int(n) / 100
- mcattrs[m] = str(v)
- except Exception, e:
- self.logger.warn('error getting mc attr %s (%s)' % (m, str(e)))
- pass
- else:
- mcattrs[m] = n
- return mcattrs
-
- def _fill_bond_info(self, ifacename):
- bonding_masters = self.read_file_oneline('/sys/class/net/bonding_masters')
- if not bonding_masters:
- return
-
- bond_masters_list = bonding_masters.split()
-
- if ifacename:
- if ifacename in bond_masters_list:
- bond_masters_list = [ifacename]
- else:
- # we want to refresh this interface only if it's a bond master
- return
-
- for bondname in bond_masters_list:
- try:
- if bondname not in linkCache.links:
- linkCache.set_attr([bondname], {'linkinfo': {}})
- linkCache.set_attr([bondname, 'linkinfo', 'slaves'],
- self.read_file_oneline('/sys/class/net/%s/bonding/slaves'
- % bondname).split())
- try:
- # if some attribute are missing we try to get the bond attributes via sysfs
- bond_linkinfo = linkCache.links[bondname]['linkinfo']
- for attr in [Link.IFLA_BOND_MODE, Link.IFLA_BOND_XMIT_HASH_POLICY, Link.IFLA_BOND_MIN_LINKS]:
- if attr not in bond_linkinfo:
- self._fill_bond_info_sysfs(bondname)
- # after we fill in the cache we can continue to the next bond
- break
- except:
- self._fill_bond_info_sysfs(bondname)
-
- except Exception as e:
- self.logger.debug('LinkUtils: bond cache error: %s' % str(e))
-
- def _fill_bond_info_sysfs(self, bondname):
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_MIN_LINKS],
- self.read_file_oneline(
- '/sys/class/net/%s/bonding/min_links'
- % bondname))
- except Exception as e:
- self.logger.debug(str(e))
-
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_MODE],
- self.read_file_oneline('/sys/class/net/%s/bonding/mode'
- % bondname).split()[0])
- except Exception as e:
- self.logger.debug(str(e))
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_XMIT_HASH_POLICY],
- self.read_file_oneline(
- '/sys/class/net/%s/bonding/xmit_hash_policy'
- % bondname).split()[0])
- except Exception as e:
- self.logger.debug(str(e))
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_AD_LACP_RATE],
- self.read_file_oneline('/sys/class/net/%s/bonding/lacp_rate'
- % bondname).split()[1])
- except Exception as e:
- self.logger.debug(str(e))
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_AD_ACTOR_SYS_PRIO],
- self.read_file_oneline('/sys/class/net/%s/bonding/ad_actor_sys_prio'
- % bondname))
- except Exception as e:
- self.logger.debug(str(e))
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_AD_ACTOR_SYSTEM],
- self.read_file_oneline('/sys/class/net/%s/bonding/ad_actor_system'
- % bondname))
- except Exception as e:
- self.logger.debug(str(e))
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_AD_LACP_BYPASS],
- self.read_file_oneline('/sys/class/net/%s/bonding/lacp_bypass'
- % bondname).split()[1])
- except Exception as e:
- self.logger.debug(str(e))
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_UPDELAY],
- self.read_file_oneline('/sys/class/net/%s/bonding/updelay'
- % bondname))
- except Exception as e:
- self.logger.debug(str(e))
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_DOWNDELAY],
- self.read_file_oneline('/sys/class/net/%s/bonding/downdelay'
- % bondname))
- except Exception as e:
- self.logger.debug(str(e))
-
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_USE_CARRIER],
- self.read_file_oneline('/sys/class/net/%s/bonding/use_carrier' % bondname))
- except Exception as e:
- self.logger.debug(str(e))
-
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_MIIMON],
- self.read_file_oneline('/sys/class/net/%s/bonding/miimon' % bondname))
- except Exception as e:
- self.logger.debug(str(e))
-
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_NUM_PEER_NOTIF],
- self.read_file_oneline('/sys/class/net/%s/bonding/num_unsol_na' % bondname))
- except Exception as e:
- self.logger.debug(str(e))
-
- try:
- linkCache.set_attr([bondname, 'linkinfo', Link.IFLA_BOND_NUM_PEER_NOTIF],
- self.read_file_oneline('/sys/class/net/%s/bonding/num_grat_arp' % bondname))
- except Exception as e:
- self.logger.debug(str(e))
-
-
- def _link_fill_iproute2_cmd(self, ifacename=None, refresh=False):
- warn = True
- linkout = {}
- if LinkUtils._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
- 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 = dict()
- 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] in ['link/gre', 'link/ipip', 'link/sit', 'link/gre6', 'link/tunnel6', 'gretap']:
- linkattrs['kind'] = 'tunnel'
- tunattrs = {'mode': citems[i].split('/')[-1],
- 'endpoint' : None,
- 'local' : None,
- 'ttl' : None,
- 'physdev' : None}
- for j in range(i, len(citems)):
- if citems[j] == 'local':
- tunattrs['local'] = citems[j + 1]
- elif citems[j] == 'remote':
- tunattrs['endpoint'] = citems[j + 1]
- elif citems[j] == 'ttl':
- tunattrs['ttl'] = citems[j + 1]
- elif citems[j] == 'dev':
- tunattrs['physdev'] = citems[j + 1]
- elif citems[j] in ['vti', 'vti6', 'ip6gre', 'ipip6', 'ip6ip6']:
- tunattrs['mode'] = citems[j]
- linkattrs['linkinfo'] = tunattrs
- break
- elif citems[i] == 'link/ppp':
- linkattrs['kind'] = 'ppp'
- 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'
- elif citems[j] == 'dev':
- vattrs['physdev'] = citems[j + 1]
- 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] == 'veth':
- linkattrs['kind'] = 'veth'
- elif citems[i] == 'vrf_slave':
- linkattrs['slave_kind'] = 'vrf_slave'
- break
- elif citems[i] == 'macvlan' and citems[i + 1] == 'mode':
- linkattrs['kind'] = 'macvlan'
- elif citems[i] == 'xfrm':
- linkattrs['kind'] = 'xfrm'
- 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()]
-
- @staticmethod
- def _addr_filter(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
- """
- if LinkUtils._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
-
- if True:
- try:
- [linkCache.update_attrdict([ifname], linkattrs)
- for ifname, linkattrs in netlink.addr_dump(ifname=ifacename).items()]
- except Exception as e:
- self.logger.info(str(e))
-
- # this netlink call replaces the call to _addr_fill_iproute2_cmd()
- # We shouldn't have netlink calls in the iproute2 module, this will
- # be removed in the future. We plan to release, a flexible backend
- # (netlink+iproute2) by default we will use netlink backend but with
- # a CLI arg we can switch to iproute2 backend.
- # Until we decide to create this "backend" switch capability,
- # we have to put the netlink call inside the iproute2 module.
-
- else:
- self._addr_fill_iproute2_cmd(ifacename, refresh)
-
- def _addr_fill_iproute2_cmd(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 LinkUtils._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 = dict()
- 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 = dict()
- 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 = dict()
- 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 del_cache_entry(self, ifname):
- try:
- del linkCache.links[ifname]
- except:
- pass
-
- def cache_get(self, t, attrlist, refresh=False):
- return self._cache_get(t, attrlist, refresh)
-
- def _cache_get(self, t, 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 t == 'link':
- self._link_fill(attrlist[0], refresh)
- elif t == '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)))
- return None
-
- def cache_check(self, attrlist, value, refresh=False):
- return self._cache_check('link', attrlist, value, refresh=refresh)
-
- def _cache_check(self, t, attrlist, value, refresh=False):
- try:
- return self._cache_get(t, attrlist, refresh) == value
- except Exception, e:
- self.logger.debug('_cache_check(%s) : [%s]'
- % (str(attrlist), str(e)))
- return False
-
- def cache_update(self, attrlist, value):
- return self._cache_update(attrlist, value)
-
- @staticmethod
- def _cache_update(attrlist, value):
- if ifupdownflags.flags.DRYRUN:
- return
- try:
- if attrlist[-1] == 'slaves':
- linkCache.append_to_attrlist(attrlist, value)
- return
- linkCache.set_attr(attrlist, value)
- except:
- pass
-
- @staticmethod
- def _cache_delete(attrlist, value=None):
- if ifupdownflags.flags.DRYRUN:
- return
- try:
- if value:
- linkCache.remove_from_attrlist(attrlist, value)
- else:
- linkCache.del_attr(attrlist)
- except:
- pass
-
- @staticmethod
- def _cache_invalidate():
- linkCache.invalidate()
- LinkUtils._CACHE_FILL_DONE = False
-
- @staticmethod
- def batch_start():
- LinkUtils.ipbatcbuf = ''
- LinkUtils.ipbatch = True
- LinkUtils.ipbatch_pause = False
-
- @staticmethod
- def add_to_batch(cmd):
- LinkUtils.ipbatchbuf += cmd + '\n'
-
- @staticmethod
- def batch_pause():
- LinkUtils.ipbatch_pause = True
-
- @staticmethod
- def batch_resume():
- LinkUtils.ipbatch_pause = False
-
- def batch_commit(self):
- if not LinkUtils.ipbatchbuf:
- LinkUtils.ipbatchbuf = ''
- LinkUtils.ipbatch = False
- LinkUtils.ipbatch_pause = False
- return
- try:
- utils.exec_command('%s -force -batch -' % utils.ip_cmd,
- stdin=self.ipbatchbuf)
- except:
- raise
- finally:
- LinkUtils.ipbatchbuf = ''
- LinkUtils.ipbatch = False
- LinkUtils.ipbatch_pause = False
-
- def bridge_batch_commit(self):
- if not LinkUtils.ipbatchbuf:
- LinkUtils.ipbatchbuf = ''
- LinkUtils.ipbatch = False
- LinkUtils.ipbatch_pause = False
- return
- try:
- utils.exec_command('%s -force -batch -'
- % utils.bridge_cmd, stdin=self.ipbatchbuf)
- except:
- raise
- finally:
- LinkUtils.ipbatchbuf = ''
- LinkUtils.ipbatch = False
- LinkUtils.ipbatch_pause = False
-
- def addr_show(self, ifacename=None):
- if ifacename:
- if not self.link_exists(ifacename):
- return
- return utils.exec_commandl([utils.ip_cmd,
- '-o', 'addr', 'show', 'dev', ifacename])
- else:
- return utils.exec_commandl([utils.ip_cmd,
- '-o', 'addr', 'show'])
-
- @staticmethod
- def link_show(ifacename=None):
- if ifacename:
- return utils.exec_commandl([utils.ip_cmd,
- '-o', '-d', 'link', 'show', 'dev', ifacename])
- else:
- return utils.exec_commandl([utils.ip_cmd,
- '-o', '-d', 'link', 'show'])
-
- def addr_add(self, ifacename, address, broadcast=None,
- peer=None, scope=None, preferred_lifetime=None, metric=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 metric:
- cmd += ' metric %s' % metric
-
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- self.add_to_batch(cmd)
- else:
- utils.exec_command('%s %s' % (utils.ip_cmd, 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('%s %s' % (utils.ip_cmd, cmd))
- self._cache_delete([ifacename, 'addrs', address])
-
- def addr_flush(self, ifacename):
- cmd = 'addr flush dev %s' % ifacename
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- self.add_to_batch(cmd)
- else:
- utils.exec_command('%s %s' % (utils.ip_cmd, cmd))
- self._cache_delete([ifacename, 'addrs'])
-
- def del_addr_all(self, ifacename, skip_addrs=[]):
- if not skip_addrs:
- skip_addrs = []
- runningaddrsdict = self.get_running_addrs(ifname=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 get_running_addrs(self, ifaceobj=None, ifname=None, details=True, addr_virtual_ifaceobj=None):
- """
- We now support addr with link scope. Since the kernel may add it's
- own link address to some interfaces we need to filter them out and
- make sure we only deal with the addresses set by ifupdown2.
-
- To do so we look at the previous configuration made by ifupdown2
- (with the help of the statemanager) together with the addresses
- specified by the user in /etc/network/interfaces, these addresses
- are then compared to the running state of the intf (ip addr show)
- made via a netlink addr dump.
- For each configured addresses of scope link, we check if it was
- previously configured by ifupdown2 to create a final set of the
- addresses watched by ifupdown2
- """
- if not ifaceobj and not ifname:
- return None
-
- config_addrs = set()
-
- if ifaceobj:
- interface_name = ifaceobj.name
- else:
- interface_name = ifname
-
- if addr_virtual_ifaceobj:
- for attr_name in ["address-virtual", "vrrp"]:
- for virtual in addr_virtual_ifaceobj.get_attr_value(attr_name) or []:
- for ip in virtual.split():
- try:
- IPNetwork(ip)
- config_addrs.add(ip)
- except:
- pass
-
- saved_ifaceobjs = statemanager.statemanager_api.get_ifaceobjs(addr_virtual_ifaceobj.name)
- for saved_ifaceobj in saved_ifaceobjs or []:
- for virtual in saved_ifaceobj.get_attr_value(attr_name) or []:
- for ip in virtual.split():
- try:
- IPNetwork(ip)
- config_addrs.add(ip)
- except:
- pass
- else:
- if ifaceobj:
- for addr in ifaceobj.get_attr_value('address') or []:
- config_addrs.add(addr)
-
- saved_ifaceobjs = statemanager.statemanager_api.get_ifaceobjs(interface_name)
- for saved_ifaceobj in saved_ifaceobjs or []:
- for addr in saved_ifaceobj.get_attr_value('address') or []:
- config_addrs.add(addr)
-
- running_addrs = OrderedDict()
- cached_addrs = self.addr_get(interface_name)
- if cached_addrs:
- for addr, addr_details in cached_addrs.items():
- try:
- scope = int(addr_details['scope'])
- except Exception:
- try:
- d = {}
- addr_obj = IPNetwork(addr)
- if isinstance(addr_obj, IPv6Network):
- d['family'] = 'inet6'
- else:
- d['family'] = 'inet'
- running_addrs[addr] = d
- except:
- running_addrs[addr] = {}
- continue
- if (scope & Route.RT_SCOPE_LINK and addr in config_addrs) or not scope & Route.RT_SCOPE_LINK:
- running_addrs[addr] = addr_details
- else:
- return None
-
- if details:
- return running_addrs
- return running_addrs.keys()
-
- @staticmethod
- def compare_user_config_vs_running_state(running_addrs, user_addrs):
- ip4 = []
- ip6 = []
-
- for ip in user_addrs or []:
- obj = IPNetwork(ip)
-
- if type(obj) == IPv6Network:
- ip6.append(str(obj))
- else:
- ip4.append(str(obj))
-
- running_ipobj = []
- for ip in running_addrs or []:
- running_ipobj.append(str(IPNetwork(ip)))
-
- return running_ipobj == (ip4 + ip6)
-
- def addr_add_multiple(self, ifaceobj, ifacename, addrs, purge_existing=False, metric=None):
- # 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.get_running_addrs(
- ifname=ifacename,
- details=False,
- addr_virtual_ifaceobj=ifaceobj
- )
- addrs = utils.get_normalized_ip_addr(ifacename, addrs)
-
- if self.compare_user_config_vs_running_state(runningaddrs, addrs):
- 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.logger.warning('%s: %s' % (ifacename, str(e)))
- for a in addrs:
- try:
- self.addr_add(ifacename, a, metric=metric)
- 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 LinkUtils.ipbatch:
- self.add_to_batch(cmd)
- else:
- utils.exec_command('%s %s' % (utils.ip_cmd, 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, t=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 t:
- cmd += ' type %s' % t
- cmd += ' %s' % key
- if value:
- cmd += ' %s' % value
- if state:
- cmd += ' %s' % state
- if LinkUtils.ipbatch:
- self.add_to_batch(cmd)
- else:
- utils.exec_command('%s %s' % (utils.ip_cmd, cmd))
- if key not in ['master', 'nomaster']:
- self._cache_update([ifacename, key], value)
-
- def link_set_hwaddress(self, ifacename, hwaddress, force=False, keep_down=False):
- if not force:
- link_hwaddress = self.link_get_hwaddress(ifacename)
-
- if self.mac_str_to_int(link_hwaddress) == self.mac_str_to_int(hwaddress):
- return False
-
- self.link_down(ifacename)
- cmd = 'link set dev %s address %s' % (ifacename, hwaddress)
- if LinkUtils.ipbatch:
- self.add_to_batch(cmd)
- else:
- utils.exec_command('%s %s' % (utils.ip_cmd, cmd))
-
- if not keep_down:
- self.link_up(ifacename)
- self._cache_update([ifacename, 'hwaddress'], hwaddress)
- return True
-
- def link_set_mtu(self, ifacename, mtu):
- if ifupdownflags.flags.DRYRUN:
- return True
- if not mtu or not ifacename: return
- self.write_file('/sys/class/net/%s/mtu' % ifacename, mtu)
- self._cache_update([ifacename, 'mtu'], mtu)
-
- def link_set_alias(self, ifacename, alias):
- self.write_file('/sys/class/net/%s/ifalias' % ifacename,
- '\n' if not alias else 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)
-
- @staticmethod
- def route_add_gateway(ifacename, gateway, vrf=None, metric=None, onlink=True):
- if not gateway:
- return
- if not vrf:
- cmd = '%s route add default via %s proto kernel' % (utils.ip_cmd,
- gateway)
- else:
- cmd = ('%s route add table %s default via %s proto kernel' %
- (utils.ip_cmd, vrf, gateway))
- # Add metric
- if metric:
- cmd += ' metric %s' % metric
- cmd += ' dev %s' % ifacename
-
- if onlink:
- cmd += " onlink"
-
- utils.exec_command(cmd)
-
- @staticmethod
- def route_del_gateway(ifacename, gateway, vrf=None, metric=None):
- # delete default gw
- if not gateway:
- return
- if not vrf:
- cmd = ('%s route del default via %s proto kernel' %
- (utils.ip_cmd, gateway))
- else:
- cmd = ('%s route del table %s default via %s proto kernel' %
- (utils.ip_cmd, vrf, gateway))
- if metric:
- cmd += ' metric %s' % metric
- cmd += ' dev %s' % ifacename
- utils.exec_command(cmd)
-
- @staticmethod
- def _get_vrf_id(ifacename):
- try:
- return linkCache.vrfs[ifacename]['table']
- except KeyError:
- dump = netlink.link_dump(ifacename)
-
- [linkCache.update_attrdict([ifname], linkattrs)
- for ifname, linkattrs in dump.items()]
-
- if dump and dump.get(ifacename, {}).get('kind') == 'vrf':
- vrf_table = dump.get(ifacename, {}).get('linkinfo', {}).get('table')
- linkCache.vrfs[ifacename] = {'table': vrf_table}
- return vrf_table
-
- return None
-
- def fix_ipv6_route_metric(self, ifaceobj, macvlan_ifacename, ips):
- vrf_table = None
-
- if ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE:
- try:
- for upper_iface in ifaceobj.upperifaces:
- vrf_table = self._get_vrf_id(upper_iface)
- if vrf_table:
- break
- except:
- pass
-
- ip_route_del = []
- for ip in ips:
- ip_network_obj = IPNetwork(ip)
-
- if type(ip_network_obj) == IPv6Network:
- route_prefix = '%s/%d' % (ip_network_obj.network, ip_network_obj.prefixlen)
-
- if vrf_table:
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- LinkUtils.add_to_batch('route del %s table %s dev %s' % (route_prefix, vrf_table, macvlan_ifacename))
- else:
- utils.exec_commandl([utils.ip_cmd, 'route', 'del', route_prefix, 'table', vrf_table, 'dev', macvlan_ifacename])
- else:
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- LinkUtils.add_to_batch('route del %s dev %s' % (route_prefix, macvlan_ifacename))
- else:
- utils.exec_commandl([utils.ip_cmd, 'route', 'del', route_prefix, 'dev', macvlan_ifacename])
- ip_route_del.append((route_prefix, vrf_table))
-
- for ip, vrf_table in ip_route_del:
- if vrf_table:
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- LinkUtils.add_to_batch('route add %s table %s dev %s proto kernel metric 9999' % (ip, vrf_table, macvlan_ifacename))
- else:
- utils.exec_commandl([utils.ip_cmd, 'route', 'add', ip, 'table', vrf_table, 'dev', macvlan_ifacename, 'proto', 'kernel' 'metric', '9999'])
- else:
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- LinkUtils.add_to_batch('route add %s dev %s proto kernel metric 9999' % (ip, macvlan_ifacename))
- else:
- utils.exec_commandl([utils.ip_cmd, 'route', 'add', ip, 'dev', macvlan_ifacename, 'proto', 'kernel' 'metric', '9999'])
-
- def link_create_vlan(self, vlan_device_name, vlan_raw_device, vlanid):
- if self.link_exists(vlan_device_name):
- return
- utils.exec_command('%s link add link %s name %s type vlan id %d' %
- (utils.ip_cmd,
- 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 LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- self.add_to_batch(cmd)
- else:
- utils.exec_command('%s %s' % (utils.ip_cmd, cmd))
- self._cache_update([name], {})
-
- def get_vxlan_peers(self, dev, svcnodeip):
- cmd = '%s fdb show brport %s' % (utils.bridge_cmd,
- 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')
- 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 tunnel_create(self, tunnelname, mode, attrs={}):
- """ generic link_create function """
- if self.link_exists(tunnelname):
- return
-
- cmd = ''
- if '6' in mode:
- cmd = ' -6'
-
- if mode in ['gretap']:
- cmd += ' link add %s type %s' % (tunnelname, mode)
- else:
- cmd += ' tunnel add %s mode %s' % (tunnelname, mode)
-
- 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([tunnelname], {})
-
- def tunnel_change(self, tunnelname, attrs={}):
- """ tunnel change function """
- if not self.link_exists(tunnelname):
- return
- cmd = 'tunnel change'
- cmd += ' %s' %(tunnelname)
- 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)
-
- def link_create_vxlan(self, name, vxlanid,
- localtunnelip=None,
- svcnodeip=None,
- remoteips=None,
- learning='on',
- ageing=None,
- anycastip=None,
- ttl=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 ttl is not None:
- args += ' ttl %s' % ttl
-
- if self.link_exists(name):
- cmd = 'link set dev %s type vxlan dstport %d' % (name, LinkUtils.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, LinkUtils.VXLAN_UDP_PORT)
-
- if localtunnelip:
- args += ' local %s' % localtunnelip
- cmd += args
-
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- self.add_to_batch(cmd)
- else:
- utils.exec_command('%s %s' % (utils.ip_cmd, cmd))
-
- # XXX: update linkinfo correctly
- #self._cache_update([name], {})
-
- @staticmethod
- def link_exists(ifacename):
- if ifupdownflags.flags.DRYRUN:
- return True
- return os.path.exists('/sys/class/net/%s' % ifacename)
-
- @staticmethod
- def link_exists_nodryrun(ifname):
- return os.path.exists('/sys/class/net/%s' % ifname)
-
- 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
-
- @staticmethod
- def link_add_macvlan(ifname, macvlan_ifacename, mode):
- utils.exec_commandl(['ip', 'link', 'add', 'link', ifname, 'name', macvlan_ifacename, 'type', 'macvlan', 'mode', mode])
-
- @staticmethod
- def link_add_xfrm(ifname, xfrm_name, xfrm_id):
- utils.exec_commandl(['ip', 'link', 'add', xfrm_name, 'type', 'xfrm', 'dev', ifname, 'if_id', xfrm_id])
-
- @staticmethod
- def route_add(route):
- utils.exec_command('%s route add %s' % (utils.ip_cmd,
- route))
-
- @staticmethod
- def route6_add(route):
- utils.exec_command('%s -6 route add %s' % (utils.ip_cmd,
- route))
-
- def get_vlandev_attrs(self, ifacename):
- return (self._cache_get('link', [ifacename, 'link']),
- self._cache_get('link', [ifacename, 'linkinfo', 'vlanid']),
- self._cache_get('link', [ifacename, 'linkinfo', 'vlan_protocol']))
-
- def get_vlan_protocol(self, ifacename):
- return self._cache_get('link', [ifacename, 'linkinfo', 'vlan_protocol'])
-
- def get_vxlandev_attrs(self, ifacename):
- return self._cache_get('link', [ifacename, 'linkinfo'])
-
- def get_vxlandev_learning(self, ifacename):
- return self._cache_get('link', [ifacename, 'linkinfo', Link.IFLA_VXLAN_LEARNING])
-
- def set_vxlandev_learning(self, ifacename, learn):
- if learn == 'on':
- utils.exec_command('%s link set dev %s type vxlan learning' %
- (utils.ip_cmd, ifacename))
- self._cache_update([ifacename, 'linkinfo', 'learning'], 'on')
- else:
- utils.exec_command('%s link set dev %s type vxlan nolearning' %
- (utils.ip_cmd, ifacename))
- self._cache_update([ifacename, 'linkinfo', 'learning'], 'off')
-
- 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_mtu_sysfs(self, ifacename):
- return self.read_file_oneline('/sys/class/net/%s/mtu'
- % ifacename)
-
- def link_get_kind(self, ifacename):
- return self._cache_get('link', [ifacename, 'kind'])
-
- def link_get_slave_kind(self, ifacename):
- return self._cache_get('link', [ifacename, 'slave_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, t, attrs={}):
- """ generic link_create function """
- if self.link_exists(ifacename):
- return
- cmd = 'link add'
- cmd += ' name %s type %s' % (ifacename, t)
- if attrs:
- for k, v in attrs.iteritems():
- cmd += ' %s' % k
- if v:
- cmd += ' %s' % v
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- self.add_to_batch(cmd)
- else:
- utils.exec_command('%s %s' % (utils.ip_cmd, cmd))
- self._cache_update([ifacename], {})
-
- def link_delete(self, ifacename):
- if not self.link_exists(ifacename):
- return
- cmd = 'link del %s' % ifacename
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- self.add_to_batch(cmd)
- else:
- utils.exec_command('%s %s' % (utils.ip_cmd, 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 get_brport_peer_link(self, bridgename):
- try:
- return self._cache_get('link', [bridgename, 'info_slave_data', Link.IFLA_BRPORT_PEER_LINK])
- except:
- return None
-
- @staticmethod
- def bridge_port_vids_add(bridgeportname, vids):
- [utils.exec_command('%s vlan add vid %s dev %s' %
- (utils.bridge_cmd,
- v, bridgeportname)) for v in vids]
-
- @staticmethod
- def bridge_port_vids_del(bridgeportname, vids):
- if not vids:
- return
- [utils.exec_command('%s vlan del vid %s dev %s' %
- (utils.bridge_cmd,
- v, bridgeportname)) for v in vids]
-
- @staticmethod
- def bridge_port_vids_flush(bridgeportname, vid):
- utils.exec_command('%s vlan del vid %s dev %s' %
- (utils.bridge_cmd,
- vid, bridgeportname))
-
- @staticmethod
- def bridge_port_vids_get(bridgeportname):
- bridgeout = utils.exec_command('%s vlan show dev %s' %
- (utils.bridge_cmd,
- bridgeportname))
- if not bridgeout:
- return []
- brvlanlines = bridgeout.readlines()[2:]
- vids = [l.strip() for l in brvlanlines]
- return [v for v in vids if v]
-
- @staticmethod
- def bridge_port_vids_get_all():
- brvlaninfo = {}
- bridgeout = utils.exec_command('%s -c vlan show'
- % utils.bridge_cmd)
- 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['%s -c -json vlan show'
- % utils.bridge_cmd]:
- return {}
- brvlaninfo = {}
- try:
- bridgeout = utils.exec_command('%s -c -json vlan show'
- % utils.bridge_cmd)
- except:
- self.supported_command['%s -c -json vlan show'
- % utils.bridge_cmd] = False
- self.logger.info('%s -c -json vlan show: skipping unsupported command'
- % utils.bridge_cmd)
- try:
- return self.get_bridge_vlan_nojson()
- except Exception as e:
- self.logger.info('bridge: get_bridge_vlan_nojson: %s' % str(e))
- return {}
-
- if not bridgeout: return brvlaninfo
- try:
- vlan_json = json.loads(bridgeout, encoding="utf-8")
- except Exception, e:
- self.logger.info('json loads failed with (%s)' % str(e))
- return {}
-
- try:
- if isinstance(vlan_json, list):
- # newer iproute2 version changed the bridge vlan show output
- # ifupdown2 relies on the previous format, we have the convert
- # data into old format
- bridge_port_vids = dict()
-
- for intf in vlan_json:
- bridge_port_vids[intf["ifname"]] = intf["vlans"]
-
- return bridge_port_vids
- else:
- # older iproute2 version have different ways to dump vlans
- # ifupdown2 prefers the following syntax:
- # {
- # "vx-1002": [{
- # "vlan": 1002,
- # "flags": ["PVID", "Egress Untagged"]
- # }
- # ],
- # "vx-1004": [{
- # "vlan": 1004,
- # "flags": ["PVID", "Egress Untagged"]
- # }]
- # }
- return vlan_json
- except Exception as e:
- self.logger.debug("bridge vlan show: Unknown json output: %s" % str(e))
- return vlan_json
-
- @staticmethod
- def get_bridge_vlan_nojson():
- vlan_json = {}
- bridgeout = utils.exec_commandl([utils.bridge_cmd, '-c', 'vlan', 'show'])
- if bridgeout:
- output = [line.split('\n') for line in bridgeout.split('\n\n')]
- output[0] = output[0][1:]
- for line in output:
- current_swp = None
- if not line:
- continue
- for entry in line:
- if not entry:
- continue
- prefix, vlan = entry.split('\t')
- if prefix:
- current_swp = prefix
- vlan_json[prefix] = []
- v = {}
- vlan = vlan[1:]
- try:
- v['vlan'] = int(vlan)
- except:
- try:
- if '-' in vlan:
- start, end = vlan.split('-')
- if ' ' in end:
- end = end[0:end.index(' ')]
- v['vlan'] = int(start)
- v['vlanEnd'] = int(end)
- else:
- v['vlan'] = int(vlan[0:vlan.index(' ')])
- flags = []
- if 'PVID' in vlan:
- flags.append('PVID')
- if 'Egress Untagged' in vlan:
- flags.append('Egress Untagged')
- v['flags'] = flags
- except:
- continue
- vlan_json[current_swp].append(v)
- return vlan_json
-
- def bridge_vlan_cache_get(self, ifacename, refresh=False):
- if not self.bridge_vlan_cache_fill_done or refresh:
- self.bridge_vlan_cache = self.bridge_port_vids_get_all_json()
- self.bridge_vlan_cache_fill_done = True
- return self.bridge_vlan_cache.get(ifacename, {})
-
- def bridge_vlan_get_pvid(self, ifacename, refresh=False):
- pvid = 0
-
- for vinfo in self.bridge_vlan_cache_get(ifacename, refresh):
- v = vinfo.get('vlan')
- pvid = v if 'PVID' in vinfo.get('flags', []) else 0
- if pvid:
- return pvid
- return pvid
-
- def bridge_vlan_get_vids(self, ifacename, refresh=False):
- vids = []
-
- for vinfo in self.bridge_vlan_cache_get(ifacename, refresh):
- v = vinfo.get('vlan')
- ispvid = True if 'PVID' in vinfo.get('flags', []) else False
- if ispvid:
- pvid = v if 'PVID' in vinfo.get('flags', []) else 0
- if pvid == 1:
- continue
- vEnd = vinfo.get('vlanEnd')
- if vEnd:
- vids.extend(range(v, vEnd + 1))
- else:
- vids.append(v)
- return vids
-
- def bridge_vlan_get_vids_n_pvid(self, ifacename, refresh=False):
- vids = []
- pvid = 0
-
- for vinfo in self.bridge_vlan_cache_get(ifacename, refresh):
- v = vinfo.get('vlan')
- ispvid = True if 'PVID' in vinfo.get('flags', []) else False
- if ispvid:
- pvid = v if 'PVID' in vinfo.get('flags', []) else 0
- vEnd = vinfo.get('vlanEnd')
- if vEnd:
- vids.extend(range(v, vEnd + 1))
- else:
- vids.append(v)
- return vids, pvid
-
- def bridge_port_pvid_add(self, bridgeportname, pvid):
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- self.add_to_batch('vlan add vid %s untagged pvid dev %s' %
- (pvid, bridgeportname))
- else:
- utils.exec_command('%s vlan add vid %s untagged pvid dev %s' %
- (utils.bridge_cmd,
- pvid, bridgeportname))
-
- def bridge_port_pvid_del(self, bridgeportname, pvid):
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- self.add_to_batch('vlan del vid %s untagged pvid dev %s' %
- (pvid, bridgeportname))
- else:
- utils.exec_command('%s vlan del vid %s untagged pvid dev %s' %
- (utils.bridge_cmd,
- 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 LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- [self.add_to_batch('vlan add vid %s dev %s %s' %
- (v, bridgeportname, target)) for v in vids]
- else:
- [utils.exec_command('%s vlan add vid %s dev %s %s' %
- (utils.bridge_cmd,
- v, bridgeportname, target)) for v in vids]
-
- def bridge_vids_del(self, bridgeportname, vids, bridge=True):
- target = 'self' if bridge else ''
- if LinkUtils.ipbatch and not LinkUtils.ipbatch_pause:
- [self.add_to_batch('vlan del vid %s dev %s %s' %
- (v, bridgeportname, target)) for v in vids]
- else:
- [utils.exec_command('%s vlan del vid %s dev %s %s' %
- (utils.bridge_cmd,
- v, bridgeportname, target)) for v in vids]
-
- @staticmethod
- def bridge_fdb_add(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('%s fdb replace %s dev %s %s %s %s' %
- (utils.bridge_cmd,
- address, dev, vlan_str, target, dst_str))
-
- @staticmethod
- def bridge_fdb_append(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('%s fdb append %s dev %s %s %s %s' %
- (utils.bridge_cmd,
- address, dev, vlan_str, target, dst_str))
-
- @staticmethod
- def bridge_fdb_del(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('%s fdb del %s dev %s %s %s %s' %
- (utils.bridge_cmd,
- 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
-
- @staticmethod
- def bridge_port_get_bridge_name(bridgeport):
- filename = '/sys/class/net/%s/brport/bridge' % bridgeport
- try:
- return os.path.basename(os.readlink(filename))
- except:
- return None
-
- @staticmethod
- def bridge_port_exists(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('%s fdb show dev %s'
- % (utils.bridge_cmd, 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))
- return fdbs
- except Exception:
- return None
-
- @staticmethod
- def is_bridge(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
- return ret
-
- def ip_route_get_dev(self, prefix, vrf_master=None):
- try:
- if vrf_master:
- cmd = '%s route get %s vrf %s' % (utils.ip_cmd, prefix, vrf_master)
- else:
- cmd = '%s route get %s' % (utils.ip_cmd, prefix)
-
- output = utils.exec_command(cmd)
- 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))
- return None
-
- @staticmethod
- def link_get_lowers(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 []
-
- @staticmethod
- def link_get_uppers(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 Exception:
- return None
-
- def link_get_vrfs(self):
- if not LinkUtils._CACHE_FILL_DONE:
- self._fill_cache()
- return linkCache.vrfs
-
- @staticmethod
- def cache_get_info_slave(attrlist):
- try:
- return linkCache.get_attr(attrlist)
- except:
- return None
-
- def get_brport_learning(self, ifacename):
- learn = self.read_file_oneline('/sys/class/net/%s/brport/learning'
- % ifacename)
- if learn and learn == '1':
- return 'on'
- else:
- return 'off'
-
- def get_brport_learning_bool(self, ifacename):
- return utils.get_boolean_from_string(self.read_file_oneline('/sys/class/net/%s/brport/learning' % ifacename))
-
- def set_brport_learning(self, ifacename, learn):
- if learn == 'off':
- return self.write_file('/sys/class/net/%s/brport/learning'
- % ifacename, '0')
- else:
- return self.write_file('/sys/class/net/%s/brport/learning'
- % ifacename, '1')
-
- #################################################################################
- ################################### BOND UTILS ##################################
- #################################################################################
-
- def _link_cache_get(self, attrlist, refresh=False):
- return self._cache_get('link', attrlist, refresh)
-
- def cache_delete(self, attrlist, value=None):
- return self._cache_delete(attrlist, value)
-
- def link_cache_get(self, attrlist, refresh=False):
- return self._link_cache_get(attrlist, refresh)
-
- def link_cache_check(self, attrlist, value, refresh=False):
- return self._link_cache_check(attrlist, value, refresh)
-
- def _link_cache_check(self, attrlist, value, refresh=False):
- try:
- return self._link_cache_get(attrlist, refresh) == value
- except Exception, e:
- self.logger.debug('_cache_check(%s) : [%s]'
- % (str(attrlist), str(e)))
- pass
- return False
-
- bondcmd_attrmap = {
- Link.IFLA_BOND_MODE: 'mode',
- Link.IFLA_BOND_MIIMON: 'miimon',
- Link.IFLA_BOND_USE_CARRIER: 'use_carrier',
- Link.IFLA_BOND_AD_LACP_RATE: 'lacp_rate',
- Link.IFLA_BOND_XMIT_HASH_POLICY: 'xmit_hash_policy',
- Link.IFLA_BOND_MIN_LINKS: 'min_links',
- Link.IFLA_BOND_NUM_PEER_NOTIF: 'num_grat_arp',
- Link.IFLA_BOND_AD_ACTOR_SYSTEM: 'ad_actor_system',
- Link.IFLA_BOND_AD_ACTOR_SYS_PRIO: 'ad_actor_sys_prio',
- Link.IFLA_BOND_AD_LACP_BYPASS: 'lacp_bypass',
- Link.IFLA_BOND_UPDELAY: 'updelay',
- Link.IFLA_BOND_DOWNDELAY: 'downdelay',
- }
-
- def bond_set_attrs_nl(self, bondname, ifla_info_data):
- bond_attr_name = 'None' # for log purpose (in case an exception raised)
- for nl_attr, value in ifla_info_data.items():
- try:
- bond_attr_name = self.bondcmd_attrmap[nl_attr]
- file_path = '/sys/class/net/%s/bonding/%s' % (bondname, bond_attr_name)
- if os.path.exists(file_path):
- self.write_file(file_path, str(value))
- except Exception as e:
- exception_str = '%s: %s %s: %s' % (bondname, bond_attr_name, value, str(e))
- if ifupdownflags.flags.FORCE:
- self.logger.warning(exception_str)
- else:
- self.logger.debug(exception_str)
-
- def bond_set_attrs(self, bondname, attrdict, prehook):
- for attrname, attrval in attrdict.items():
- if (self._link_cache_check([bondname, 'linkinfo',
- attrname], attrval)):
- continue
- if (attrname == 'mode'
- or attrname == 'xmit_hash_policy'
- or attrname == 'lacp_rate' or attrname == 'min_links'):
- if prehook:
- prehook(bondname)
- try:
- if ((attrname not in ['lacp_rate',
- 'lacp_bypass']) or
- self._link_cache_check([bondname, 'linkinfo', 'mode'], '802.3ad',
- True)):
- self.write_file('/sys/class/net/%s/bonding/%s'
- % (bondname, attrname), attrval)
- except Exception, e:
- if ifupdownflags.flags.FORCE:
- self.logger.warn(str(e))
- pass
- else:
- raise
-
- def bond_set_use_carrier(self, bondname, use_carrier):
- if not use_carrier or (use_carrier != '0' and use_carrier != '1'):
- return
- if (self._link_cache_check([bondname, 'linkinfo', 'use_carrier'],
- use_carrier)):
- return
- self.write_file('/sys/class/net/%s' % bondname +
- '/bonding/use_carrier', use_carrier)
- self._cache_update([bondname, 'linkinfo',
- 'use_carrier'], use_carrier)
-
- def bond_get_use_carrier(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'use_carrier'])
-
- def bond_get_use_carrier_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_USE_CARRIER])
-
- def bond_set_xmit_hash_policy(self, bondname, hash_policy, prehook=None):
- valid_values = ['layer2', 'layer3+4', 'layer2+3']
- if not hash_policy:
- return
- if hash_policy not in valid_values:
- raise Exception('invalid hash policy value %s' % hash_policy)
- if (self._link_cache_check([bondname, 'linkinfo', 'xmit_hash_policy'],
- hash_policy)):
- return
- if prehook:
- prehook(bondname)
- self.write_file('/sys/class/net/%s' % bondname +
- '/bonding/xmit_hash_policy', hash_policy)
- self._cache_update([bondname, 'linkinfo', 'xmit_hash_policy'],
- hash_policy)
-
- def bond_get_xmit_hash_policy(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'xmit_hash_policy'])
-
- def bond_get_xmit_hash_policy_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_XMIT_HASH_POLICY])
-
- def bond_set_miimon(self, bondname, miimon):
- if (self._link_cache_check([bondname, 'linkinfo', 'miimon'],
- miimon)):
- return
- self.write_file('/sys/class/net/%s' % bondname +
- '/bonding/miimon', miimon)
- self._cache_update([bondname, 'linkinfo', 'miimon'], miimon)
-
- def bond_get_miimon(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'miimon'])
-
- def bond_get_miimon_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_MIIMON])
-
- def bond_set_mode(self, bondname, mode, prehook=None):
- valid_modes = ['balance-rr', 'active-backup', 'balance-xor',
- 'broadcast', '802.3ad', 'balance-tlb', 'balance-alb']
- if not mode:
- return
- if mode not in valid_modes:
- raise Exception('invalid mode %s' % mode)
- if (self._link_cache_check([bondname, 'linkinfo', 'mode'],
- mode)):
- return
- if prehook:
- prehook(bondname)
- self.write_file('/sys/class/net/%s' % bondname + '/bonding/mode', mode)
- self._cache_update([bondname, 'linkinfo', 'mode'], mode)
-
- def bond_get_mode(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'mode'])
-
- def bond_get_mode_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_MODE])
-
- def bond_set_lacp_rate(self, bondname, lacp_rate, prehook=None, posthook=None):
- if not lacp_rate or (lacp_rate != '0' and lacp_rate != '1'):
- return
- if (self._link_cache_check([bondname, 'linkinfo', 'lacp_rate'],
- lacp_rate)):
- return
- if prehook:
- prehook(bondname)
- try:
- self.write_file('/sys/class/net/%s' % bondname +
- '/bonding/lacp_rate', lacp_rate)
- except:
- raise
- finally:
- if posthook:
- prehook(bondname)
- self._cache_update([bondname, 'linkinfo',
- 'lacp_rate'], lacp_rate)
-
- def bond_get_lacp_rate(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'lacp_rate'])
-
- def bond_get_lacp_rate_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_AD_LACP_RATE])
-
- def bond_set_lacp_bypass_allow(self, bondname, allow, prehook=None, posthook=None):
- if self._link_cache_check([bondname, 'linkinfo', 'lacp_bypass'], allow):
- return
- if prehook:
- prehook(bondname)
- try:
- self.write_file('/sys/class/net/%s' % bondname +
- '/bonding/lacp_bypass', allow)
- except:
- raise
- finally:
- if posthook:
- posthook(bondname)
- self._cache_update([bondname, 'linkinfo',
- 'lacp_bypass'], allow)
-
- def bond_get_lacp_bypass_allow(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'lacp_bypass'])
-
- def bond_get_lacp_bypass_allow_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_AD_LACP_BYPASS])
-
- def bond_set_min_links(self, bondname, min_links, prehook=None):
- if (self._link_cache_check([bondname, 'linkinfo', 'min_links'],
- min_links)):
- return
- if prehook:
- prehook(bondname)
- self.write_file('/sys/class/net/%s/bonding/min_links' % bondname,
- min_links)
- self._cache_update([bondname, 'linkinfo', 'min_links'], min_links)
-
- def bond_get_min_links(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'min_links'])
-
- def get_min_links_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_MIN_LINKS])
-
- def bond_get_ad_actor_system(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'ad_actor_system'])
-
- def bond_get_ad_actor_system_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_AD_ACTOR_SYSTEM])
-
- def bond_get_ad_actor_sys_prio(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'ad_actor_sys_prio'])
-
- def bond_get_ad_actor_sys_prio_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_AD_ACTOR_SYS_PRIO])
-
- def bond_get_num_unsol_na(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'num_unsol_na'])
-
- def bond_get_num_unsol_na_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_NUM_PEER_NOTIF])
-
- def bond_get_num_grat_arp(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'num_grat_arp'])
-
- def bond_get_num_grat_arp_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_NUM_PEER_NOTIF])
-
- def bond_get_updelay(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'updelay'])
-
- def bond_get_updelay_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_UPDELAY])
-
- def bond_get_downdelay(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', 'downdelay'])
-
- def bond_get_downdelay_nl(self, bondname):
- return self._link_cache_get([bondname, 'linkinfo', Link.IFLA_BOND_DOWNDELAY])
-
- def bond_enslave_slave(self, bondname, slave, prehook=None, posthook=None):
- slaves = self._link_cache_get([bondname, 'linkinfo', 'slaves'])
- if slaves and slave in slaves:
- return
- if prehook:
- prehook(slave)
- self.write_file('/sys/class/net/%s' % bondname +
- '/bonding/slaves', '+' + slave)
- if posthook:
- posthook(slave)
- self._cache_update([bondname, 'linkinfo', 'slaves'], slave)
-
- def bond_remove_slave(self, bondname, slave):
- slaves = self._link_cache_get([bondname, 'linkinfo', 'slaves'])
- if not slaves or slave not in slaves:
- return
- sysfs_bond_path = ('/sys/class/net/%s' % bondname +
- '/bonding/slaves')
- if not os.path.exists(sysfs_bond_path):
- return
- self.write_file(sysfs_bond_path, '-' + slave)
- self._cache_delete([bondname, 'linkinfo', 'slaves'], slave)
-
- def bond_remove_slaves_all(self, bondname):
- if not self._link_cache_get([bondname, 'linkinfo', 'slaves']):
- return
- slaves = None
- sysfs_bond_path = ('/sys/class/net/%s' % bondname +
- '/bonding/slaves')
- try:
- with open(sysfs_bond_path, 'r') as f:
- slaves = f.readline().strip().split()
- except IOError, e:
- raise Exception('error reading slaves of bond %s (%s)' % (bondname, str(e)))
- for slave in slaves:
- self.link_down(slave)
- try:
- self.bond_remove_slave(bondname, slave)
- except Exception, e:
- if not ifupdownflags.flags.FORCE:
- raise Exception('error removing slave %s from bond %s (%s)' % (slave, bondname, str(e)))
- else:
- pass
- self._cache_delete([bondname, 'linkinfo', 'slaves'])
-
- @staticmethod
- def bond_load_bonding_module():
- return utils.exec_command('%s -q bonding' % utils.modprobe_cmd)
-
- def create_bond(self, bondname):
- if self.bond_exists(bondname):
- return
- # load_bonding_module() has already been run
- self.write_file('/sys/class/net/bonding_masters', '+' + bondname)
- self._cache_update([bondname], {})
-
- def delete_bond(self, bondname):
- if not os.path.exists('/sys/class/net/%s' % bondname):
- return
- self.write_file('/sys/class/net/bonding_masters', '-' + bondname)
- self._cache_delete([bondname])
-
- def bond_get_slaves(self, bondname):
- slaves = self._link_cache_get([bondname, 'linkinfo', 'slaves'])
- if slaves:
- return list(slaves)
- slavefile = '/sys/class/net/%s/bonding/slaves' % bondname
- if os.path.exists(slavefile):
- buf = self.read_file_oneline(slavefile)
- if buf:
- slaves = buf.split()
- if not slaves:
- return []
- self._cache_update([bondname, 'linkinfo', 'slaves'], slaves)
- return list(slaves)
-
- def bond_slave_exists(self, bond, slave):
- slaves = self.bond_get_slaves(bond)
- if not slaves:
- return False
- return slave in slaves
-
- @staticmethod
- def bond_exists(bondname):
- return os.path.exists('/sys/class/net/%s/bonding' % bondname)
-
- #################################################################################
- ################################## BRIDGE UTILS #################################
- #################################################################################
-
- def create_bridge(self, bridgename):
- if not LinkUtils.bridge_utils_is_installed:
- return
- if self.bridge_exists(bridgename):
- return
- utils.exec_command('%s addbr %s' % (utils.brctl_cmd, bridgename))
- self._cache_update([bridgename], {})
-
- def delete_bridge(self, bridgename):
- if not LinkUtils.bridge_utils_is_installed:
- return
- if not self.bridge_exists(bridgename):
- return
- utils.exec_command('%s delbr %s' % (utils.brctl_cmd, bridgename))
- self._cache_invalidate()
-
- def add_bridge_port(self, bridgename, bridgeportname):
- """ Add port to bridge """
- if not LinkUtils.bridge_utils_is_installed:
- return
- ports = self._link_cache_get([bridgename, 'linkinfo', 'ports'])
- if ports and ports.get(bridgeportname):
- return
- utils.exec_command('%s addif %s %s' % (utils.brctl_cmd, bridgename, bridgeportname))
- self._cache_update([bridgename, 'linkinfo', 'ports', bridgeportname], {})
-
- def delete_bridge_port(self, bridgename, bridgeportname):
- """ Delete port from bridge """
- if not LinkUtils.bridge_utils_is_installed:
- return
- ports = self._link_cache_get([bridgename, 'linkinfo', 'ports'])
- if not ports or not ports.get(bridgeportname):
- return
- utils.exec_command('%s delif %s %s' % (utils.brctl_cmd, bridgename, bridgeportname))
- self._cache_delete([bridgename, 'linkinfo', 'ports', 'bridgeportname'])
-
- def set_bridgeport_attrs(self, bridgename, bridgeportname, attrdict):
- portattrs = self._link_cache_get([bridgename, 'linkinfo', 'ports', bridgeportname])
- if portattrs == None:
- portattrs = {}
- for k, v in attrdict.iteritems():
- if ifupdownflags.flags.CACHE:
- curval = portattrs.get(k)
- if curval and curval == v:
- continue
- if k == 'unicast-flood':
- self.write_file('/sys/class/net/%s/brport/unicast_flood' % bridgeportname, v)
- elif k == 'multicast-flood':
- self.write_file('/sys/class/net/%s/brport/multicast_flood' % bridgeportname, v)
- elif k == 'learning':
- self.write_file('/sys/class/net/%s/brport/learning' % bridgeportname, v)
- elif k == 'arp-nd-suppress':
- self.write_file('/sys/class/net/%s/brport/neigh_suppress' % bridgeportname, v)
- else:
- if not LinkUtils.bridge_utils_is_installed:
- continue
- utils.exec_command('%s set%s %s %s %s' % (utils.brctl_cmd, k, bridgename, bridgeportname, v))
-
- def set_bridgeport_attr(self, bridgename, bridgeportname,
- attrname, attrval):
- if not LinkUtils.bridge_utils_is_installed:
- return
- if self._link_cache_check([bridgename, 'linkinfo', 'ports', bridgeportname, attrname], attrval):
- return
- utils.exec_command('%s set%s %s %s %s' %
- (utils.brctl_cmd,
- attrname,
- bridgename,
- bridgeportname,
- attrval))
-
- def set_bridge_attrs(self, bridgename, attrdict):
- for k, v in attrdict.iteritems():
- if not v:
- continue
- if self._link_cache_check([bridgename, 'linkinfo', k], v):
- continue
- try:
- if k == 'igmp-version':
- self.write_file('/sys/class/net/%s/bridge/'
- 'multicast_igmp_version' % bridgename, v)
- elif k == 'mld-version':
- self.write_file('/sys/class/net/%s/bridge/'
- 'multicast_mld_version' % bridgename, v)
- elif k == 'vlan-protocol':
- self.write_file('/sys/class/net/%s/bridge/'
- 'vlan_protocol' % bridgename,
- VlanProtocols.ETHERTYPES_TO_ID.get(v.upper(),
- None))
- elif k == 'vlan-stats':
- self.write_file('/sys/class/net/%s/bridge/'
- 'vlan_stats_enabled' % bridgename, v)
- elif k == 'mcstats':
- self.write_file('/sys/class/net/%s/bridge/'
- 'multicast_stats_enabled' % bridgename, v)
- else:
- if not LinkUtils.bridge_utils_is_installed:
- continue
- cmd = ('%s set%s %s %s' %
- (utils.brctl_cmd, k, bridgename, v))
- utils.exec_command(cmd)
- except Exception, e:
- self.logger.warn('%s: %s' % (bridgename, str(e)))
- pass
-
- def set_bridge_attr(self, bridgename, attrname, attrval):
- if self._link_cache_check([bridgename, 'linkinfo', attrname], attrval):
- return
- if attrname == 'igmp-version':
- self.write_file('/sys/class/net/%s/bridge/multicast_igmp_version'
- % bridgename, attrval)
- elif attrname == 'mld-version':
- self.write_file('/sys/class/net/%s/bridge/multicast_mld_version'
- % bridgename, attrval)
- elif attrname == 'vlan-protocol':
- self.write_file('/sys/class/net/%s/bridge/vlan_protocol'
- % bridgename, VlanProtocols.ETHERTYPES_TO_ID[attrval.upper()])
- elif attrname == 'vlan-stats':
- self.write_file('/sys/class/net/%s/bridge/vlan_stats_enabled'
- % bridgename, attrval)
- elif attrname == 'mcstats':
- self.write_file('/sys/class/net/%s/bridge/multicast_stats_enabled'
- % bridgename, attrval)
- else:
- if not LinkUtils.bridge_utils_is_installed:
- return
- cmd = '%s set%s %s %s' % (utils.brctl_cmd,
- attrname, bridgename, attrval)
- utils.exec_command(cmd)
-
- def get_bridge_attrs(self, bridgename):
- attrs = self._link_cache_get([bridgename, 'linkinfo'])
- no_ints_attrs = {}
- for key, value in attrs.items():
- if type(key) == str:
- no_ints_attrs[key] = value
- return no_ints_attrs
-
- def get_bridgeport_attrs(self, bridgename, bridgeportname):
- return self._link_cache_get([bridgename, 'linkinfo', 'ports',
- bridgeportname])
-
- def get_bridgeport_attr(self, bridgename, bridgeportname, attrname):
- return self._link_cache_get([bridgename, 'linkinfo', 'ports',
- bridgeportname, attrname])
-
- @staticmethod
- def bridge_set_stp(bridge, stp_state):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s stp %s %s' % (utils.brctl_cmd, bridge, stp_state))
-
- def bridge_get_stp(self, bridge):
- sysfs_stpstate = '/sys/class/net/%s/bridge/stp_state' % bridge
- if not os.path.exists(sysfs_stpstate):
- return 'error'
- stpstate = self.read_file_oneline(sysfs_stpstate)
- if not stpstate:
- return 'error'
- try:
- if int(stpstate) > 0:
- return 'yes'
- elif int(stpstate) == 0:
- return 'no'
- except:
- return 'unknown'
-
- @staticmethod
- def _conv_value_to_user(s):
- try:
- ret = int(s) / 100
- return '%d' % ret
- except:
- return None
-
- def read_value_from_sysfs(self, filename, preprocess_func):
- value = self.read_file_oneline(filename)
- if not value:
- return None
- return preprocess_func(value)
-
- @staticmethod
- def bridge_set_ageing(bridge, ageing):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setageing %s %s' % (utils.brctl_cmd, bridge, ageing))
-
- def bridge_get_ageing(self, bridge):
- return self.read_value_from_sysfs('/sys/class/net/%s/bridge/ageing_time'
- % bridge, self._conv_value_to_user)
-
- @staticmethod
- def set_bridgeprio(bridge, prio):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setbridgeprio %s %s' % (utils.brctl_cmd, bridge, prio))
-
- def get_bridgeprio(self, bridge):
- return self.read_file_oneline(
- '/sys/class/net/%s/bridge/priority' % bridge)
-
- @staticmethod
- def bridge_set_fd(bridge, fd):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setfd %s %s' % (utils.brctl_cmd, bridge, fd))
-
- def bridge_get_fd(self, bridge):
- return self.read_value_from_sysfs(
- '/sys/class/net/%s/bridge/forward_delay'
- % bridge, self._conv_value_to_user)
-
- def bridge_set_gcint(self, bridge, gcint):
- raise Exception('set_gcint not implemented')
-
- @staticmethod
- def bridge_set_hello(bridge, hello):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s sethello %s %s' % (utils.brctl_cmd, bridge, hello))
-
- def bridge_get_hello(self, bridge):
- return self.read_value_from_sysfs('/sys/class/net/%s/bridge/hello_time'
- % bridge, self._conv_value_to_user)
-
- @staticmethod
- def bridge_set_maxage(bridge, maxage):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setmaxage %s %s' % (utils.brctl_cmd, bridge, maxage))
-
- def bridge_get_maxage(self, bridge):
- return self.read_value_from_sysfs('/sys/class/net/%s/bridge/max_age'
- % bridge, self._conv_value_to_user)
-
- @staticmethod
- def bridge_set_pathcost(bridge, port, pathcost):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setpathcost %s %s %s' % (utils.brctl_cmd, bridge, port, pathcost))
-
- def bridge_get_pathcost(self, bridge, port):
- return self.read_file_oneline('/sys/class/net/%s/brport/path_cost'
- % port)
-
- @staticmethod
- def bridge_set_portprio(bridge, port, prio):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setportprio %s %s %s' % (utils.brctl_cmd, bridge, port, prio))
-
- def bridge_get_portprio(self, bridge, port):
- return self.read_file_oneline('/sys/class/net/%s/brport/priority'
- % port)
-
- @staticmethod
- def bridge_set_hashmax(bridge, hashmax):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s sethashmax %s %s' % (utils.brctl_cmd, bridge, hashmax))
-
- def bridge_get_hashmax(self, bridge):
- return self.read_file_oneline('/sys/class/net/%s/bridge/hash_max'
- % bridge)
-
- @staticmethod
- def bridge_set_hashel(bridge, hashel):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s sethashel %s %s' % (utils.brctl_cmd, bridge, hashel))
-
- def bridge_get_hashel(self, bridge):
- return self.read_file_oneline('/sys/class/net/%s/bridge/hash_elasticity'
- % bridge)
-
- @staticmethod
- def bridge_set_mclmc(bridge, mclmc):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setmclmc %s %s' % (utils.brctl_cmd, bridge, mclmc))
-
- def bridge_get_mclmc(self, bridge):
- return self.read_file_oneline(
- '/sys/class/net/%s/bridge/multicast_last_member_count'
- % bridge)
-
- @staticmethod
- def bridge_set_mcrouter(bridge, mcrouter):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setmcrouter %s %s' % (utils.brctl_cmd, bridge, mcrouter))
-
- def bridge_get_mcrouter(self, bridge):
- return self.read_file_oneline(
- '/sys/class/net/%s/bridge/multicast_router' % bridge)
-
- @staticmethod
- def bridge_set_mcsnoop(bridge, mcsnoop):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setmcsnoop %s %s' % (utils.brctl_cmd, bridge, mcsnoop))
-
- def bridge_get_mcsnoop(self, bridge):
- return self.read_file_oneline(
- '/sys/class/net/%s/bridge/multicast_snooping' % bridge)
-
- @staticmethod
- def bridge_set_mcsqc(bridge, mcsqc):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setmcsqc %s %s' % (utils.brctl_cmd, bridge, mcsqc))
-
- def bridge_get_mcsqc(self, bridge):
- return self.read_file_oneline(
- '/sys/class/net/%s/bridge/multicast_startup_query_count'
- % bridge)
-
- @staticmethod
- def bridge_set_mcqifaddr(bridge, mcqifaddr):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setmcqifaddr %s %s' % (utils.brctl_cmd, bridge, mcqifaddr))
-
- def bridge_get_mcqifaddr(self, bridge):
- return self.read_file_oneline(
- '/sys/class/net/%s/bridge/multicast_startup_query_use_ifaddr'
- % bridge)
-
- @staticmethod
- def bridge_set_mcquerier(bridge, mcquerier):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setmcquerier %s %s' % (utils.brctl_cmd, bridge, mcquerier))
-
- def bridge_get_mcquerier(self, bridge):
- return self.read_file_oneline(
- '/sys/class/net/%s/bridge/multicast_querier' % bridge)
-
- def bridge_set_mcqv4src(self, bridge, vlan, mcquerier):
- try:
- vlan = int(vlan)
- except:
- self.logger.info('%s: set mcqv4src vlan: invalid parameter %s: %s' %(bridge, vlan, str(e)))
- return
- if vlan == 0 or vlan > 4095:
- self.logger.warn('mcqv4src vlan \'%d\' invalid range' % vlan)
- return
-
- ip = mcquerier.split('.')
- if len(ip) != 4:
- self.logger.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier)
- return
- for k in ip:
- if not k.isdigit() or int(k, 10) < 0 or int(k, 10) > 255:
- self.logger.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier)
- return
-
- if not LinkUtils.bridge_utils_is_installed:
- return
-
- utils.exec_command('%s setmcqv4src %s %d %s' %
- (utils.brctl_cmd, bridge, vlan, mcquerier))
-
- def bridge_del_mcqv4src(self, bridge, vlan):
- if not LinkUtils.bridge_utils_is_installed:
- return
- try:
- vlan = int(vlan)
- except:
- self.logger.info('%s: del mcqv4src vlan: invalid parameter %s: %s' %(bridge, vlan, str(e)))
- return
- utils.exec_command('%s delmcqv4src %s %d' % (utils.brctl_cmd, bridge, vlan))
-
- def bridge_get_mcqv4src(self, bridge, vlan=None):
- if not LinkUtils.bridge_utils_is_installed:
- return {}
- if not self.supported_command['showmcqv4src']:
- return {}
- mcqv4src = {}
- try:
- mcqout = utils.exec_command('%s showmcqv4src %s' %
- (utils.brctl_cmd, bridge))
- except Exception as e:
- s = str(e).lower()
- if 'never heard' in s:
- msg = ('%s showmcqv4src: skipping unsupported command'
- % utils.brctl_cmd)
- self.logger.info(msg)
- self.supported_command['showmcqv4src'] = False
- return {}
- raise
- if not mcqout:
- return {}
- mcqlines = mcqout.splitlines()
- for l in mcqlines[1:]:
- l = l.strip()
- k, d, v = l.split('\t')
- if not k or not v:
- continue
- mcqv4src[k] = v
- if vlan:
- return mcqv4src.get(vlan)
- return mcqv4src
-
- def bridge_get_mcqv4src_sysfs(self, bridge, vlan=None):
- if not LinkUtils.bridge_utils_is_installed:
- return {}
- if not self.supported_command['showmcqv4src']:
- return {}
- if ifupdownflags.flags.PERFMODE:
- return {}
- mcqv4src = {}
- try:
- filename = '/sys/class/net/%s/bridge/multicast_v4_queriers' % bridge
- if os.path.exists(filename):
- for line in self.read_file(filename) or []:
- vlan_id, ip = line.split('=')
- mcqv4src[vlan_id] = ip.strip()
- except Exception as e:
- s = str(e).lower()
- msg = ('%s showmcqv4src: skipping unsupported command'
- % utils.brctl_cmd)
- self.logger.info(msg)
- self.supported_command['showmcqv4src'] = False
- return {}
- if vlan:
- return mcqv4src.get(vlan)
- return mcqv4src
-
- @staticmethod
- def bridge_set_mclmi(bridge, mclmi):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setmclmi %s %s' % (utils.brctl_cmd, bridge, mclmi))
-
- def bridge_get_mclmi(self, bridge):
- return self.read_file_oneline(
- '/sys/class/net/%s/bridge/multicast_last_member_interval'
- % bridge)
-
- @staticmethod
- def bridge_set_mcmi(bridge, mcmi):
- if not LinkUtils.bridge_utils_is_installed:
- return
- utils.exec_command('%s setmcmi %s %s' % (utils.brctl_cmd, bridge, mcmi))
-
- def bridge_get_mcmi(self, bridge):
- return self.read_file_oneline(
- '/sys/class/net/%s/bridge/multicast_membership_interval'
- % bridge)
-
- @staticmethod
- def bridge_exists(bridge):
- return os.path.exists('/sys/class/net/%s/bridge' % bridge)
-
- @staticmethod
- def is_bridge_port(ifacename):
- return os.path.exists('/sys/class/net/%s/brport' % ifacename)
-
- @staticmethod
- def bridge_port_exists(bridge, bridgeportname):
- try:
- return os.path.exists('/sys/class/net/%s/brif/%s' % (bridge, bridgeportname))
- except:
- return False
-
- @staticmethod
- def get_bridge_ports(bridgename):
- try:
- return os.listdir('/sys/class/net/%s/brif/' % bridgename)
- except:
- return []
-
- def reset_addr_cache(self, ifname):
- try:
- linkCache.links[ifname]['addrs'] = {}
- self.logger.debug('%s: reset address cache' % ifname)
- except:
- pass
-
- def get_ipv6_addrgen_mode(self, ifname):
- try:
- return self._cache_get('link', [ifname, 'af_spec', socket.AF_INET6])[Link.IFLA_INET6_ADDR_GEN_MODE]
- except:
- # default to 0 (eui64)
- return 0
-
- def ipv6_addrgen(self, ifname, addrgen, link_created):
- try:
- # IFLA_INET6_ADDR_GEN_MODE values:
- # 0 = eui64
- # 1 = none
- if self._link_cache_get([ifname, 'af_spec', socket.AF_INET6])[Link.IFLA_INET6_ADDR_GEN_MODE] == addrgen:
- self.logger.debug('%s: ipv6 addrgen already %s' % (ifname, 'off' if addrgen else 'on'))
- return
-
- disabled_ipv6 = self.read_file_oneline('/proc/sys/net/ipv6/conf/%s/disable_ipv6' % ifname)
- if not disabled_ipv6 or int(disabled_ipv6) == 1:
- self.logger.info('%s: cannot set addrgen: ipv6 is disabled on this device' % ifname)
- return
-
- if int(self._link_cache_get([ifname, 'mtu'])) < 1280:
- self.logger.info('%s: ipv6 addrgen is disabled on device with MTU '
- 'lower than 1280: cannot set addrgen %s' % (ifname, 'off' if addrgen else 'on'))
- return
- except (KeyError, TypeError):
- self.logger.debug('%s: ipv6 addrgen probably not supported or disabled on this device' % ifname)
- return
- except Exception:
- pass
-
- if not link_created:
- # When setting addrgenmode it is necessary to flap the macvlan
- # device. After flapping the device we also need to re-add all
- # the user configuration. The best way to add the user config
- # is to flush our internal address cache
- self.reset_addr_cache(ifname)
-
- cmd = 'link set dev %s addrgenmode %s' % (ifname, Link.ifla_inet6_addr_gen_mode_dict.get(addrgen))
-
- is_link_up = self.is_link_up(ifname)
-
- if is_link_up:
- self.link_down(ifname)
-
- #if LinkUtils.ipbatch:
- # self.add_to_batch(cmd)
- #else:
- # because this command might fail on older kernel its better to not batch it
- utils.exec_command('%s %s' % (utils.ip_cmd, cmd))
-
- if is_link_up:
- self.link_up(ifname)