X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ifupdown2%2Fifupdownaddons%2FLinkUtils.py;h=575a8425d12f8d353747cf16d8fb59f671ef9248;hb=3e8a915365531273c12662ffbb0f7a65e400c62d;hp=1b886e27bcad8e6996f6e5a4ecfbf72c043f7f50;hpb=007cae3525b2c43b7d114f2e471f2f01e86ffe5b;p=mirror_ifupdown2.git diff --git a/ifupdown2/ifupdownaddons/LinkUtils.py b/ifupdown2/ifupdownaddons/LinkUtils.py index 1b886e2..575a842 100644 --- a/ifupdown2/ifupdownaddons/LinkUtils.py +++ b/ifupdown2/ifupdownaddons/LinkUtils.py @@ -231,41 +231,38 @@ class LinkUtils(utilsBase): battrs = {} bports = {} - brout = utils.exec_command('%s showstp %s' % (utils.brctl_cmd, bridgename)) - chunks = re.split(r'\n\n', brout, maxsplit=0, flags=re.MULTILINE) - try: # Get all bridge attributes - broutlines = chunks[0].splitlines() # battrs['pathcost'] = broutlines[3].split('path cost')[1].strip() try: - battrs['maxage'] = broutlines[4].split('bridge max age')[ - 1].strip().replace('.00', '') + battrs['maxage'] = self.read_file_oneline( + '/sys/class/net/%s/bridge/max_age' % bridgename) except: pass + try: - battrs['hello'] = broutlines[5].split('bridge hello time')[ - 1].strip().replace('.00', '') + battrs['hello'] = self.read_file_oneline( + '/sys/class/net/%s/bridge/hello_time' % bridgename) except: pass try: - battrs['fd'] = broutlines[6].split('bridge forward delay')[ - 1].strip().replace('.00', '') + battrs['fd'] = self.read_file_oneline( + '/sys/class/net/%s/bridge/forward_delay' % bridgename) except: pass try: - battrs['ageing'] = broutlines[7].split('ageing time')[ - 1].strip().replace('.00', '') + battrs['ageing'] = self.read_file_oneline( + '/sys/class/net/%s/bridge/ageing_time' % bridgename) except: pass try: - battrs['mcrouter'] = broutlines[12].split('mc router')[ - 1].strip().split('\t\t\t')[0] + battrs['mcrouter'] = self.read_file_oneline( + '/sys/class/net/%s/bridge/multicast_router' % bridgename) except: pass @@ -289,30 +286,24 @@ class LinkUtils(utilsBase): # XXX: comment this out until mc attributes become available # with brctl again - # battrs['hashel'] = broutlines[10].split('hash elasticity')[1].split()[0].strip() - # battrs['hashmax'] = broutlines[10].split('hash max')[1].strip() - # battrs['mclmc'] = broutlines[11].split('mc last member count')[1].split()[0].strip() + # battrs['mciqc'] = broutlines[11].split('mc init query count')[1].strip() - # battrs['mcrouter'] = broutlines[12].split('mc router')[1].split()[0].strip() - ##battrs['mcsnoop'] = broutlines[12].split('mc snooping')[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) - for cidx in range(1, len(chunks)): - bpout = chunks[cidx].lstrip('\n') - if not bpout or bpout[0] == ' ': - continue - bplines = bpout.splitlines() - pname = bplines[0].split()[0] + + names = [os.path.basename(x) for x in glob.glob("/sys/class/net/%s/brif/*" % bridgename)] + for pname in names: bportattrs = {} try: - bportattrs['pathcost'] = bplines[2].split( - 'path cost')[1].strip() - bportattrs['fdelay'] = bplines[4].split( - 'forward delay timer')[1].strip() + + 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( @@ -327,8 +318,12 @@ class LinkUtils(utilsBase): '/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'] = bplines[6].split('mc router')[1].split()[0].strip() - # bportattrs['mc fast leave'] = bplines[6].split('mc fast leave')[1].strip() + + #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 @@ -545,6 +540,8 @@ class LinkUtils(utilsBase): 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': @@ -698,6 +695,12 @@ class LinkUtils(utilsBase): [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) @@ -932,23 +935,24 @@ class LinkUtils(utilsBase): 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 []: @@ -1113,7 +1117,7 @@ class LinkUtils(utilsBase): 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: @@ -1126,6 +1130,10 @@ class LinkUtils(utilsBase): if metric: cmd += 'metric %s' % metric cmd += ' dev %s' % ifacename + + if onlink: + cmd += " onlink" + utils.exec_command(cmd) @staticmethod @@ -1266,13 +1274,16 @@ class LinkUtils(utilsBase): if '6' in mode: cmd = ' -6 ' - cmd += 'tunnel add' - cmd += ' %s mode %s' %(tunnelname, mode) + 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: @@ -1294,7 +1305,6 @@ class LinkUtils(utilsBase): 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, @@ -1302,7 +1312,8 @@ class LinkUtils(utilsBase): 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 = '' @@ -1312,6 +1323,8 @@ class LinkUtils(utilsBase): 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) @@ -1361,8 +1374,8 @@ class LinkUtils(utilsBase): 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): @@ -1543,11 +1556,40 @@ class LinkUtils(utilsBase): 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(): @@ -2595,6 +2637,31 @@ class LinkUtils(utilsBase): 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: @@ -2661,7 +2728,20 @@ class LinkUtils(utilsBase): 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 - except: + + 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: @@ -2671,17 +2751,18 @@ class LinkUtils(utilsBase): # is to flush our internal address cache self.reset_addr_cache(ifname) - cmd = 'link set dev %s addrgenmode %s' % (ifname, 'none' if addrgen else 'eui64') + 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)