import glob
import shlex
import signal
+import socket
import subprocess
from ipaddr import IPNetwork, IPv6Network
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:
interface_name = ifname
if addr_virtual_ifaceobj:
- for virtual in addr_virtual_ifaceobj.get_attr_value('address-virtual') 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('address-virtual') or []:
+ 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 []:
return self._cache_get('link', [ifacename, 'ifflag'], refresh=True)
@staticmethod
- def route_add_gateway(ifacename, gateway, vrf=None, metric=None):
+ def route_add_gateway(ifacename, gateway, vrf=None, metric=None, onlink=True):
if not gateway:
return
if not vrf:
if metric:
cmd += 'metric %s' % metric
cmd += ' dev %s' % ifacename
+
+ if onlink:
+ cmd += " onlink"
+
utils.exec_command(cmd)
@staticmethod
""" generic link_create function """
if self.link_exists(tunnelname):
return
- cmd = 'tunnel add'
- cmd += ' %s mode %s' %(tunnelname, mode)
+
+ 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
+ cmd += ' %s' % k
if v:
- cmd += ' %s' %v
+ cmd += ' %s' % v
if self.ipbatch and not self.ipbatch_pause:
self.add_to_batch(cmd)
else:
self.add_to_batch(cmd)
else:
utils.exec_command('ip %s' % cmd)
- self._cache_update([tunnelname], {})
def link_create_vxlan(self, name, vxlanid,
localtunnelip=None,
remoteips=None,
learning='on',
ageing=None,
- anycastip=None):
+ anycastip=None,
+ ttl=None):
if svcnodeip and remoteips:
raise Exception("svcnodeip and remoteip is mutually exclusive")
args = ''
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)
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 False
@staticmethod
- def link_add_macvlan(ifname, macvlan_ifacename):
- utils.exec_commandl(['ip', 'link', 'add', 'link', ifname, 'name', macvlan_ifacename, 'type', 'macvlan', 'mode', 'private'])
+ 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 route_add(route):
if not bridgeout: return brvlaninfo
try:
- vlan_json_dict = json.loads(bridgeout, encoding="utf-8")
+ vlan_json = json.loads(bridgeout, encoding="utf-8")
except Exception, e:
self.logger.info('json loads failed with (%s)' % str(e))
return {}
- return vlan_json_dict
+
+ 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():
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:
except:
return []
- def ipv6_addrgen(self, ifname, addrgen):
- cmd = 'link set dev %s addrgenmode %s' % (ifname, 'eui64' if addrgen else 'none')
+ 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:
- utils.exec_command('%s %s' % (utils.ip_cmd, cmd))
+ #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)