3 # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
5 # Julien Fortin, julien@cumulusnetworks.com
16 from ipaddr
import IPNetwork
, IPv6Network
19 import ifupdown2
.ifupdown
.statemanager
as statemanager
20 import ifupdown2
.ifupdown
.ifupdownflags
as ifupdownflags
22 from ifupdown2
.nlmanager
.nlmanager
import Link
, Route
24 from ifupdown2
.ifupdown
.iface
import *
25 from ifupdown2
.ifupdown
.utils
import utils
26 from ifupdown2
.ifupdown
.netlink
import netlink
28 from ifupdown2
.ifupdownaddons
.utilsbase
import utilsBase
29 from ifupdown2
.ifupdownaddons
.cache
import linkCache
, MSTPAttrsCache
31 import ifupdown
.ifupdownflags
as ifupdownflags
32 import ifupdown
.statemanager
as statemanager
34 from nlmanager
.nlmanager
import Link
, Route
36 from ifupdown
.iface
import *
37 from ifupdown
.utils
import utils
38 from ifupdown
.netlink
import netlink
40 from ifupdownaddons
.utilsbase
import utilsBase
41 from ifupdownaddons
.cache
import linkCache
, MSTPAttrsCache
44 class LinkUtils(utilsBase
):
46 This class contains helper methods to cache and manipulate interfaces through
47 non-netlink APIs (sysfs, iproute2, brctl...)
49 _CACHE_FILL_DONE
= False
56 bridge_utils_is_installed
= os
.path
.exists(utils
.brctl_cmd
)
57 bridge_utils_missing_warning
= True
59 DEFAULT_IP_METRIC
= 1024
60 ADDR_METRIC_SUPPORT
= None
62 def __init__(self
, *args
, **kargs
):
63 utilsBase
.__init
__(self
, *args
, **kargs
)
65 self
.supported_command
= {
66 '%s -c -json vlan show' % utils
.bridge_cmd
: True,
69 self
.bridge_vlan_cache
= {}
70 self
.bridge_vlan_cache_fill_done
= False
72 if not ifupdownflags
.flags
.PERFMODE
and not LinkUtils
._CACHE
_FILL
_DONE
:
75 if LinkUtils
.ADDR_METRIC_SUPPORT
is None:
77 cmd
= [utils
.ip_cmd
, 'addr', 'help']
78 self
.logger
.info('executing %s addr help' % utils
.ip_cmd
)
80 process
= subprocess
.Popen(cmd
, stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
)
81 stdout
, stderr
= process
.communicate()
82 LinkUtils
.ADDR_METRIC_SUPPORT
= '[ metric METRIC ]' in stderr
or ''
83 self
.logger
.info('address metric support: %s' % ('OK' if LinkUtils
.ADDR_METRIC_SUPPORT
else 'KO'))
85 LinkUtils
.ADDR_METRIC_SUPPORT
= False
86 self
.logger
.info('address metric support: KO')
89 def addr_metric_support(cls
):
90 return cls
.ADDR_METRIC_SUPPORT
93 def get_default_ip_metric(cls
):
94 return cls
.DEFAULT_IP_METRIC
98 LinkUtils
._CACHE
_FILL
_DONE
= False
99 LinkUtils
.ipbatchbuf
= ''
100 LinkUtils
.ipbatch
= False
101 LinkUtils
.ipbatch_pause
= False
103 def _fill_cache(self
):
104 if not LinkUtils
._CACHE
_FILL
_DONE
:
107 LinkUtils
._CACHE
_FILL
_DONE
= True
112 def _get_vland_id(citems
, i
, warn
):
115 index
= sub
.index('id')
117 return sub
[index
+ 1]
120 raise Exception('invalid use of \'vlan\' keyword')
123 def _link_fill(self
, ifacename
=None, refresh
=False):
124 """ fills cache with link information
126 if ifacename argument given, fill cache for ifacename, else
127 fill cache for all interfaces in the system
130 if LinkUtils
._CACHE
_FILL
_DONE
and not refresh
:
133 # if ifacename already present, return
134 if (ifacename
and not refresh
and
135 linkCache
.get_attr([ifacename
, 'ifflag'])):
142 [linkCache
.update_attrdict([ifname
], linkattrs
)
143 for ifname
, linkattrs
in netlink
.link_dump(ifacename
).items()]
144 except Exception as e
:
145 self
.logger
.info('%s' % str(e
))
146 # this netlink call replaces the call to _link_fill_iproute2_cmd()
147 # We shouldn't have netlink calls in the iproute2 module, this will
148 # be removed in the future. We plan to release, a flexible backend
149 # (netlink+iproute2) by default we will use netlink backend but with
150 # a CLI arg we can switch to iproute2 backend.
151 # Until we decide to create this "backend" switch capability,
152 # we have to put the netlink call inside the iproute2 module.
154 self
._link
_fill
_iproute
2_cmd
(ifacename
, refresh
)
156 self
._fill
_bond
_info
(ifacename
)
157 self
._fill
_bridge
_info
(ifacename
)
159 def _fill_bridge_info(self
, ifacename
):
165 cache_dict
= {ifacename
: linkCache
.links
.get(ifacename
, {})}
167 cache_dict
= linkCache
.links
169 for ifname
, obj
in cache_dict
.items():
170 slave_kind
= obj
.get('slave_kind')
171 if not slave_kind
and slave_kind
!= 'bridge':
174 info_slave_data
= obj
.get('info_slave_data')
175 if not info_slave_data
:
178 ifla_master
= obj
.get('master')
180 raise Exception('No master associated with bridge port %s' % ifname
)
183 Link
.IFLA_BRPORT_STATE
,
184 Link
.IFLA_BRPORT_COST
,
185 Link
.IFLA_BRPORT_PRIORITY
,
187 if nl_attr
not in info_slave_data
and LinkUtils
.bridge_utils_is_installed
:
188 self
._fill
_bridge
_info
_brctl
()
192 'pathcost': str(info_slave_data
.get(Link
.IFLA_BRPORT_COST
, 0)),
193 'fdelay': format(float(info_slave_data
.get(Link
.IFLA_BRPORT_FORWARD_DELAY_TIMER
, 0) / 100), '.2f'),
194 'portmcrouter': str(info_slave_data
.get(Link
.IFLA_BRPORT_MULTICAST_ROUTER
, 0)),
195 'portmcfl': str(info_slave_data
.get(Link
.IFLA_BRPORT_FAST_LEAVE
, 0)),
196 'portprio': str(info_slave_data
.get(Link
.IFLA_BRPORT_PRIORITY
, 0)),
197 'unicast-flood': str(info_slave_data
.get(Link
.IFLA_BRPORT_UNICAST_FLOOD
, 0)),
198 'multicast-flood': str(info_slave_data
.get(Link
.IFLA_BRPORT_MCAST_FLOOD
, 0)),
199 'learning': str(info_slave_data
.get(Link
.IFLA_BRPORT_LEARNING
, 0)),
200 'arp-nd-suppress': str(info_slave_data
.get(Link
.IFLA_BRPORT_ARP_SUPPRESS
, 0))
203 if ifla_master
in brports
:
204 brports
[ifla_master
][ifname
] = brport_attrs
206 brports
[ifla_master
] = {ifname
: brport_attrs
}
208 linkCache
.update_attrdict([ifla_master
, 'linkinfo', 'ports'], brports
[ifla_master
])
210 if LinkUtils
.bridge_utils_is_installed
:
211 self
._fill
_bridge
_info
_brctl
()
213 def _fill_bridge_info_brctl(self
):
214 brctlout
= utils
.exec_command('%s show' % utils
.brctl_cmd
)
218 for bline
in brctlout
.splitlines()[1:]:
219 bitems
= bline
.split()
223 linkCache
.update_attrdict([bitems
[0], 'linkinfo'],
226 linkCache
.update_attrdict([bitems
[0]],
227 {'linkinfo': {'stp': bitems
[2]}})
228 self
._bridge
_attrs
_fill
(bitems
[0])
230 def _bridge_attrs_fill(self
, bridgename
):
234 brout
= utils
.exec_command('%s showstp %s' % (utils
.brctl_cmd
, bridgename
))
235 chunks
= re
.split(r
'\n\n', brout
, maxsplit
=0, flags
=re
.MULTILINE
)
238 # Get all bridge attributes
239 broutlines
= chunks
[0].splitlines()
240 # battrs['pathcost'] = broutlines[3].split('path cost')[1].strip()
243 battrs
['maxage'] = broutlines
[4].split('bridge max age')[
244 1].strip().replace('.00', '')
249 battrs
['hello'] = broutlines
[5].split('bridge hello time')[
250 1].strip().replace('.00', '')
255 battrs
['fd'] = broutlines
[6].split('bridge forward delay')[
256 1].strip().replace('.00', '')
261 battrs
['ageing'] = broutlines
[7].split('ageing time')[
262 1].strip().replace('.00', '')
267 battrs
['mcrouter'] = broutlines
[12].split('mc router')[
268 1].strip().split('\t\t\t')[0]
273 battrs
['bridgeprio'] = self
.read_file_oneline(
274 '/sys/class/net/%s/bridge/priority' % bridgename
)
279 battrs
['vlan-protocol'] = VlanProtocols
.ID_TO_ETHERTYPES
[
280 self
.read_file_oneline(
281 '/sys/class/net/%s/bridge/vlan_protocol' % bridgename
)]
286 battrs
.update(self
._bridge
_get
_mcattrs
_from
_sysfs
(bridgename
))
290 # XXX: comment this out until mc attributes become available
292 # battrs['hashel'] = broutlines[10].split('hash elasticity')[1].split()[0].strip()
293 # battrs['hashmax'] = broutlines[10].split('hash max')[1].strip()
294 # battrs['mclmc'] = broutlines[11].split('mc last member count')[1].split()[0].strip()
295 # battrs['mciqc'] = broutlines[11].split('mc init query count')[1].strip()
296 # battrs['mcrouter'] = broutlines[12].split('mc router')[1].split()[0].strip()
297 ##battrs['mcsnoop'] = broutlines[12].split('mc snooping')[1].strip()
298 # battrs['mclmt'] = broutlines[13].split('mc last member timer')[1].split()[0].strip()
300 self
.logger
.warn('%s: error while processing bridge attributes: %s' % (bridgename
, str(e
)))
303 linkCache
.update_attrdict([bridgename
, 'linkinfo'], battrs
)
304 for cidx
in range(1, len(chunks
)):
305 bpout
= chunks
[cidx
].lstrip('\n')
306 if not bpout
or bpout
[0] == ' ':
308 bplines
= bpout
.splitlines()
309 pname
= bplines
[0].split()[0]
312 bportattrs
['pathcost'] = bplines
[2].split(
313 'path cost')[1].strip()
314 bportattrs
['fdelay'] = bplines
[4].split(
315 'forward delay timer')[1].strip()
316 bportattrs
['portmcrouter'] = self
.read_file_oneline(
317 '/sys/class/net/%s/brport/multicast_router' % pname
)
318 bportattrs
['portmcfl'] = self
.read_file_oneline(
319 '/sys/class/net/%s/brport/multicast_fast_leave' % pname
)
320 bportattrs
['portprio'] = self
.read_file_oneline(
321 '/sys/class/net/%s/brport/priority' % pname
)
322 bportattrs
['unicast-flood'] = self
.read_file_oneline(
323 '/sys/class/net/%s/brport/unicast_flood' % pname
)
324 bportattrs
['multicast-flood'] = self
.read_file_oneline(
325 '/sys/class/net/%s/brport/multicast_flood' % pname
)
326 bportattrs
['learning'] = self
.read_file_oneline(
327 '/sys/class/net/%s/brport/learning' % pname
)
328 bportattrs
['arp-nd-suppress'] = self
.read_file_oneline(
329 '/sys/class/net/%s/brport/neigh_suppress' % pname
)
330 # bportattrs['mcrouters'] = bplines[6].split('mc router')[1].split()[0].strip()
331 # bportattrs['mc fast leave'] = bplines[6].split('mc fast leave')[1].strip()
333 self
.logger
.warn('%s: error while processing bridge attributes: %s' % (bridgename
, str(e
)))
334 bports
[pname
] = bportattrs
335 linkCache
.update_attrdict([bridgename
, 'linkinfo', 'ports'], bports
)
337 _bridge_sysfs_mcattrs
= {
338 'mclmc': 'multicast_last_member_count',
339 'mcrouter': 'multicast_router',
340 'mcsnoop': 'multicast_snooping',
341 'mcsqc': 'multicast_startup_query_count',
342 'mcqifaddr': 'multicast_query_use_ifaddr',
343 'mcquerier': 'multicast_querier',
344 'hashel': 'hash_elasticity',
345 'hashmax': 'hash_max',
346 'mclmi': 'multicast_last_member_interval',
347 'mcmi': 'multicast_membership_interval',
348 'mcqpi': 'multicast_querier_interval',
349 'mcqi': 'multicast_query_interval',
350 'mcqri': 'multicast_query_response_interval',
351 'mcsqi': 'multicast_startup_query_interval',
352 'igmp-version': 'multicast_igmp_version',
353 'mld-version': 'multicast_mld_version',
354 'vlan-stats': 'vlan_stats_enabled',
355 'mcstats': 'multicast_stats_enabled',
358 def _bridge_get_mcattrs_from_sysfs(self
, bridgename
):
359 mcattrsdivby100
= ['mclmi', 'mcmi', 'mcqpi', 'mcqi', 'mcqri', 'mcsqi']
362 for m
, s
in self
._bridge
_sysfs
_mcattrs
.items():
363 n
= self
.read_file_oneline('/sys/class/net/%s/bridge/%s' % (bridgename
, s
))
364 if m
in mcattrsdivby100
:
369 self
.logger
.warn('error getting mc attr %s (%s)' % (m
, str(e
)))
375 def _fill_bond_info(self
, ifacename
):
376 bonding_masters
= self
.read_file_oneline('/sys/class/net/bonding_masters')
377 if not bonding_masters
:
380 bond_masters_list
= bonding_masters
.split()
383 if ifacename
in bond_masters_list
:
384 bond_masters_list
= [ifacename
]
386 # we want to refresh this interface only if it's a bond master
389 for bondname
in bond_masters_list
:
391 if bondname
not in linkCache
.links
:
392 linkCache
.set_attr([bondname
], {'linkinfo': {}})
393 linkCache
.set_attr([bondname
, 'linkinfo', 'slaves'],
394 self
.read_file_oneline('/sys/class/net/%s/bonding/slaves'
397 # if some attribute are missing we try to get the bond attributes via sysfs
398 bond_linkinfo
= linkCache
.links
[bondname
]['linkinfo']
399 for attr
in [Link
.IFLA_BOND_MODE
, Link
.IFLA_BOND_XMIT_HASH_POLICY
, Link
.IFLA_BOND_MIN_LINKS
]:
400 if attr
not in bond_linkinfo
:
401 self
._fill
_bond
_info
_sysfs
(bondname
)
402 # after we fill in the cache we can continue to the next bond
405 self
._fill
_bond
_info
_sysfs
(bondname
)
407 except Exception as e
:
408 self
.logger
.debug('LinkUtils: bond cache error: %s' % str(e
))
410 def _fill_bond_info_sysfs(self
, bondname
):
412 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_MIN_LINKS
],
413 self
.read_file_oneline(
414 '/sys/class/net/%s/bonding/min_links'
416 except Exception as e
:
417 self
.logger
.debug(str(e
))
420 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_MODE
],
421 self
.read_file_oneline('/sys/class/net/%s/bonding/mode'
422 % bondname
).split()[0])
423 except Exception as e
:
424 self
.logger
.debug(str(e
))
426 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_XMIT_HASH_POLICY
],
427 self
.read_file_oneline(
428 '/sys/class/net/%s/bonding/xmit_hash_policy'
429 % bondname
).split()[0])
430 except Exception as e
:
431 self
.logger
.debug(str(e
))
433 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_RATE
],
434 self
.read_file_oneline('/sys/class/net/%s/bonding/lacp_rate'
435 % bondname
).split()[1])
436 except Exception as e
:
437 self
.logger
.debug(str(e
))
439 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
],
440 self
.read_file_oneline('/sys/class/net/%s/bonding/ad_actor_sys_prio'
442 except Exception as e
:
443 self
.logger
.debug(str(e
))
445 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYSTEM
],
446 self
.read_file_oneline('/sys/class/net/%s/bonding/ad_actor_system'
448 except Exception as e
:
449 self
.logger
.debug(str(e
))
451 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_BYPASS
],
452 self
.read_file_oneline('/sys/class/net/%s/bonding/lacp_bypass'
453 % bondname
).split()[1])
454 except Exception as e
:
455 self
.logger
.debug(str(e
))
457 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_UPDELAY
],
458 self
.read_file_oneline('/sys/class/net/%s/bonding/updelay'
460 except Exception as e
:
461 self
.logger
.debug(str(e
))
463 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_DOWNDELAY
],
464 self
.read_file_oneline('/sys/class/net/%s/bonding/downdelay'
466 except Exception as e
:
467 self
.logger
.debug(str(e
))
470 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_USE_CARRIER
],
471 self
.read_file_oneline('/sys/class/net/%s/bonding/use_carrier' % bondname
))
472 except Exception as e
:
473 self
.logger
.debug(str(e
))
476 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_MIIMON
],
477 self
.read_file_oneline('/sys/class/net/%s/bonding/miimon' % bondname
))
478 except Exception as e
:
479 self
.logger
.debug(str(e
))
482 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
],
483 self
.read_file_oneline('/sys/class/net/%s/bonding/num_unsol_na' % bondname
))
484 except Exception as e
:
485 self
.logger
.debug(str(e
))
488 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
],
489 self
.read_file_oneline('/sys/class/net/%s/bonding/num_grat_arp' % bondname
))
490 except Exception as e
:
491 self
.logger
.debug(str(e
))
494 def _link_fill_iproute2_cmd(self
, ifacename
=None, refresh
=False):
497 if LinkUtils
._CACHE
_FILL
_DONE
and not refresh
:
500 # if ifacename already present, return
501 if (ifacename
and not refresh
and
502 linkCache
.get_attr([ifacename
, 'ifflag'])):
506 cmdout
= self
.link_show(ifacename
=ifacename
)
509 for c
in cmdout
.splitlines():
511 ifnamenlink
= citems
[1].split('@')
512 if len(ifnamenlink
) > 1:
513 ifname
= ifnamenlink
[0]
514 iflink
= ifnamenlink
[1].strip(':')
516 ifname
= ifnamenlink
[0].strip(':')
519 linkattrs
['link'] = iflink
520 linkattrs
['ifindex'] = citems
[0].strip(':')
521 flags
= citems
[2].strip('<>').split(',')
522 linkattrs
['flags'] = flags
523 linkattrs
['ifflag'] = 'UP' if 'UP' in flags
else 'DOWN'
524 for i
in range(0, len(citems
)):
526 if citems
[i
] == 'mtu':
527 linkattrs
['mtu'] = citems
[i
+ 1]
528 elif citems
[i
] == 'state':
529 linkattrs
['state'] = citems
[i
+ 1]
530 elif citems
[i
] == 'link/ether':
531 linkattrs
['hwaddress'] = citems
[i
+ 1]
532 elif citems
[i
] in ['link/gre', 'link/ipip', 'link/sit', 'link/gre6', 'link/tunnel6', 'gretap']:
533 linkattrs
['kind'] = 'tunnel'
534 tunattrs
= {'mode': citems
[i
].split('/')[-1],
539 for j
in range(i
, len(citems
)):
540 if citems
[j
] == 'local':
541 tunattrs
['local'] = citems
[j
+ 1]
542 elif citems
[j
] == 'remote':
543 tunattrs
['endpoint'] = citems
[j
+ 1]
544 elif citems
[j
] == 'ttl':
545 tunattrs
['ttl'] = citems
[j
+ 1]
546 elif citems
[j
] == 'dev':
547 tunattrs
['physdev'] = citems
[j
+ 1]
548 elif citems
[j
] in ['vti', 'vti6', 'ip6gre', 'ipip6', 'ip6ip6']:
549 tunattrs
['mode'] = citems
[j
]
550 linkattrs
['linkinfo'] = tunattrs
552 elif citems
[i
] == 'link/ppp':
553 linkattrs
['kind'] = 'ppp'
554 elif citems
[i
] == 'vlan':
555 vlanid
= self
._get
_vland
_id
(citems
, i
, warn
)
557 linkattrs
['linkinfo'] = {'vlanid': vlanid
}
558 linkattrs
['kind'] = 'vlan'
559 elif citems
[i
] == 'dummy':
560 linkattrs
['kind'] = 'dummy'
561 elif citems
[i
] == 'vxlan' and citems
[i
+ 1] == 'id':
562 linkattrs
['kind'] = 'vxlan'
563 vattrs
= {'vxlanid': citems
[i
+ 2],
566 'ageing': citems
[i
+ 2],
568 for j
in range(i
+ 2, len(citems
)):
569 if citems
[j
] == 'local':
570 vattrs
['local'] = citems
[j
+ 1]
571 elif citems
[j
] == 'remote':
572 vattrs
['svcnode'] = citems
[j
+ 1]
573 elif citems
[j
] == 'ageing':
574 vattrs
['ageing'] = citems
[j
+ 1]
575 elif citems
[j
] == 'nolearning':
576 vattrs
['learning'] = 'off'
577 elif citems
[j
] == 'dev':
578 vattrs
['physdev'] = citems
[j
+ 1]
579 linkattrs
['linkinfo'] = vattrs
581 elif citems
[i
] == 'vrf' and citems
[i
+ 1] == 'table':
582 vattrs
= {'table': citems
[i
+ 2]}
583 linkattrs
['linkinfo'] = vattrs
584 linkattrs
['kind'] = 'vrf'
585 linkCache
.vrfs
[ifname
] = vattrs
587 elif citems
[i
] == 'veth':
588 linkattrs
['kind'] = 'veth'
589 elif citems
[i
] == 'vrf_slave':
590 linkattrs
['slave_kind'] = 'vrf_slave'
592 elif citems
[i
] == 'macvlan' and citems
[i
+ 1] == 'mode':
593 linkattrs
['kind'] = 'macvlan'
594 except Exception as e
:
596 self
.logger
.debug('%s: parsing error: id, mtu, state, '
597 'link/ether, vlan, dummy, vxlan, local, '
598 'remote, ageing, nolearning, vrf, table, '
599 'vrf_slave are reserved keywords: %s' %
602 # linkattrs['alias'] = self.read_file_oneline(
603 # '/sys/class/net/%s/ifalias' %ifname)
604 linkout
[ifname
] = linkattrs
605 [linkCache
.update_attrdict([ifname
], linkattrs
)
606 for ifname
, linkattrs
in linkout
.items()]
609 def _addr_filter(ifname
, addr
, scope
=None):
610 default_addrs
= ['127.0.0.1/8', '::1/128', '0.0.0.0']
611 if ifname
== 'lo' and addr
in default_addrs
:
613 if scope
and scope
== 'link':
617 def _addr_fill(self
, ifacename
=None, refresh
=False):
618 """ fills cache with address information
620 if ifacename argument given, fill cache for ifacename, else
621 fill cache for all interfaces in the system
623 if LinkUtils
._CACHE
_FILL
_DONE
and not refresh
:
626 # Check if ifacename is already full, in which case, return
627 if ifacename
and not refresh
:
628 linkCache
.get_attr([ifacename
, 'addrs'])
635 [linkCache
.update_attrdict([ifname
], linkattrs
)
636 for ifname
, linkattrs
in netlink
.addr_dump(ifname
=ifacename
).items()]
637 except Exception as e
:
638 self
.logger
.info(str(e
))
640 # this netlink call replaces the call to _addr_fill_iproute2_cmd()
641 # We shouldn't have netlink calls in the iproute2 module, this will
642 # be removed in the future. We plan to release, a flexible backend
643 # (netlink+iproute2) by default we will use netlink backend but with
644 # a CLI arg we can switch to iproute2 backend.
645 # Until we decide to create this "backend" switch capability,
646 # we have to put the netlink call inside the iproute2 module.
649 self
._addr
_fill
_iproute
2_cmd
(ifacename
, refresh
)
651 def _addr_fill_iproute2_cmd(self
, ifacename
=None, refresh
=False):
652 """ fills cache with address information
654 if ifacename argument given, fill cache for ifacename, else
655 fill cache for all interfaces in the system
658 if LinkUtils
._CACHE
_FILL
_DONE
and not refresh
:
661 # Check if ifacename is already full, in which case, return
662 if ifacename
and not refresh
:
663 linkCache
.get_attr([ifacename
, 'addrs'])
667 cmdout
= self
.addr_show(ifacename
=ifacename
)
670 for c
in cmdout
.splitlines():
672 ifnamenlink
= citems
[1].split('@')
673 if len(ifnamenlink
) > 1:
674 ifname
= ifnamenlink
[0]
676 ifname
= ifnamenlink
[0].strip(':')
677 if not linkout
.get(ifname
):
679 linkattrs
['addrs'] = OrderedDict({})
681 linkout
[ifname
].update(linkattrs
)
683 linkout
[ifname
] = linkattrs
684 if citems
[2] == 'inet':
685 if self
._addr
_filter
(ifname
, citems
[3], scope
=citems
[5]):
688 addrattrs
['scope'] = citems
[5]
689 addrattrs
['type'] = 'inet'
690 linkout
[ifname
]['addrs'][citems
[3]] = addrattrs
691 elif citems
[2] == 'inet6':
692 if self
._addr
_filter
(ifname
, citems
[3], scope
=citems
[5]):
694 if citems
[5] == 'link':
695 continue # skip 'link' addresses
697 addrattrs
['scope'] = citems
[5]
698 addrattrs
['type'] = 'inet6'
699 linkout
[ifname
]['addrs'][citems
[3]] = addrattrs
700 [linkCache
.update_attrdict([ifname
], linkattrs
)
701 for ifname
, linkattrs
in linkout
.items()]
703 def cache_get(self
, t
, attrlist
, refresh
=False):
704 return self
._cache
_get
(t
, attrlist
, refresh
)
706 def _cache_get(self
, t
, attrlist
, refresh
=False):
708 if ifupdownflags
.flags
.DRYRUN
:
710 if ifupdownflags
.flags
.CACHE
:
711 if self
._fill
_cache
():
712 # if we filled the cache, return new data
713 return linkCache
.get_attr(attrlist
)
715 return linkCache
.get_attr(attrlist
)
717 self
._link
_fill
(attrlist
[0], refresh
)
719 self
._addr
_fill
(attrlist
[0], refresh
)
721 self
._link
_fill
(attrlist
[0], refresh
)
722 self
._addr
_fill
(attrlist
[0], refresh
)
723 return linkCache
.get_attr(attrlist
)
725 self
.logger
.debug('_cache_get(%s) : [%s]' % (str(attrlist
), str(e
)))
728 def cache_check(self
, attrlist
, value
, refresh
=False):
729 return self
._cache
_check
('link', attrlist
, value
, refresh
=refresh
)
731 def _cache_check(self
, t
, attrlist
, value
, refresh
=False):
733 return self
._cache
_get
(t
, attrlist
, refresh
) == value
735 self
.logger
.debug('_cache_check(%s) : [%s]'
736 % (str(attrlist
), str(e
)))
739 def cache_update(self
, attrlist
, value
):
740 return self
._cache
_update
(attrlist
, value
)
743 def _cache_update(attrlist
, value
):
744 if ifupdownflags
.flags
.DRYRUN
:
747 if attrlist
[-1] == 'slaves':
748 linkCache
.append_to_attrlist(attrlist
, value
)
750 linkCache
.set_attr(attrlist
, value
)
755 def _cache_delete(attrlist
, value
=None):
756 if ifupdownflags
.flags
.DRYRUN
:
760 linkCache
.remove_from_attrlist(attrlist
, value
)
762 linkCache
.del_attr(attrlist
)
767 def _cache_invalidate():
768 linkCache
.invalidate()
769 LinkUtils
._CACHE
_FILL
_DONE
= False
773 LinkUtils
.ipbatcbuf
= ''
774 LinkUtils
.ipbatch
= True
775 LinkUtils
.ipbatch_pause
= False
778 def add_to_batch(cmd
):
779 LinkUtils
.ipbatchbuf
+= cmd
+ '\n'
783 LinkUtils
.ipbatch_pause
= True
787 LinkUtils
.ipbatch_pause
= False
789 def batch_commit(self
):
790 if not LinkUtils
.ipbatchbuf
:
791 LinkUtils
.ipbatchbuf
= ''
792 LinkUtils
.ipbatch
= False
793 LinkUtils
.ipbatch_pause
= False
796 utils
.exec_command('%s -force -batch -' % utils
.ip_cmd
,
797 stdin
=self
.ipbatchbuf
)
801 LinkUtils
.ipbatchbuf
= ''
802 LinkUtils
.ipbatch
= False
803 LinkUtils
.ipbatch_pause
= False
805 def bridge_batch_commit(self
):
806 if not LinkUtils
.ipbatchbuf
:
807 LinkUtils
.ipbatchbuf
= ''
808 LinkUtils
.ipbatch
= False
809 LinkUtils
.ipbatch_pause
= False
812 utils
.exec_command('%s -force -batch -'
813 % utils
.bridge_cmd
, stdin
=self
.ipbatchbuf
)
817 LinkUtils
.ipbatchbuf
= ''
818 LinkUtils
.ipbatch
= False
819 LinkUtils
.ipbatch_pause
= False
821 def addr_show(self
, ifacename
=None):
823 if not self
.link_exists(ifacename
):
825 return utils
.exec_commandl([utils
.ip_cmd
,
826 '-o', 'addr', 'show', 'dev', ifacename
])
828 return utils
.exec_commandl([utils
.ip_cmd
,
829 '-o', 'addr', 'show'])
832 def link_show(ifacename
=None):
834 return utils
.exec_commandl([utils
.ip_cmd
,
835 '-o', '-d', 'link', 'show', 'dev', ifacename
])
837 return utils
.exec_commandl([utils
.ip_cmd
,
838 '-o', '-d', 'link', 'show'])
840 def addr_add(self
, ifacename
, address
, broadcast
=None,
841 peer
=None, scope
=None, preferred_lifetime
=None, metric
=None):
844 cmd
= 'addr add %s' % address
846 cmd
+= ' broadcast %s' % broadcast
848 cmd
+= ' peer %s' % peer
850 cmd
+= ' scope %s' % scope
851 if preferred_lifetime
:
852 cmd
+= ' preferred_lft %s' % preferred_lifetime
853 cmd
+= ' dev %s' % ifacename
856 cmd
+= ' metric %s' % metric
858 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
859 self
.add_to_batch(cmd
)
861 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
862 self
._cache
_update
([ifacename
, 'addrs', address
], {})
864 def addr_del(self
, ifacename
, address
, broadcast
=None,
865 peer
=None, scope
=None):
866 """ Delete ipv4 address """
869 if not self
._cache
_get
('addr', [ifacename
, 'addrs', address
]):
871 cmd
= 'addr del %s' % address
873 cmd
+= 'broadcast %s' % broadcast
875 cmd
+= 'peer %s' % peer
877 cmd
+= 'scope %s' % scope
878 cmd
+= ' dev %s' % ifacename
879 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
880 self
._cache
_delete
([ifacename
, 'addrs', address
])
882 def addr_flush(self
, ifacename
):
883 cmd
= 'addr flush dev %s' % ifacename
884 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
885 self
.add_to_batch(cmd
)
887 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
888 self
._cache
_delete
([ifacename
, 'addrs'])
890 def del_addr_all(self
, ifacename
, skip_addrs
=[]):
893 runningaddrsdict
= self
.get_running_addrs(ifname
=ifacename
)
895 # XXX: ignore errors. Fix this to delete secondary addresses
897 [self
.addr_del(ifacename
, a
) for a
in
898 set(runningaddrsdict
.keys()).difference(skip_addrs
)]
903 def addr_get(self
, ifacename
, details
=True, refresh
=False):
904 addrs
= self
._cache
_get
('addr', [ifacename
, 'addrs'], refresh
=refresh
)
911 def get_running_addrs(self
, ifaceobj
=None, ifname
=None, details
=True, addr_virtual_ifaceobj
=None):
913 We now support addr with link scope. Since the kernel may add it's
914 own link address to some interfaces we need to filter them out and
915 make sure we only deal with the addresses set by ifupdown2.
917 To do so we look at the previous configuration made by ifupdown2
918 (with the help of the statemanager) together with the addresses
919 specified by the user in /etc/network/interfaces, these addresses
920 are then compared to the running state of the intf (ip addr show)
921 made via a netlink addr dump.
922 For each configured addresses of scope link, we check if it was
923 previously configured by ifupdown2 to create a final set of the
924 addresses watched by ifupdown2
926 if not ifaceobj
and not ifname
:
932 interface_name
= ifaceobj
.name
934 interface_name
= ifname
936 if addr_virtual_ifaceobj
:
937 for virtual
in addr_virtual_ifaceobj
.get_attr_value('address-virtual') or []:
938 for ip
in virtual
.split():
945 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(addr_virtual_ifaceobj
.name
)
946 for saved_ifaceobj
in saved_ifaceobjs
or []:
947 for virtual
in saved_ifaceobj
.get_attr_value('address-virtual') or []:
948 for ip
in virtual
.split():
956 for addr
in ifaceobj
.get_attr_value('address') or []:
957 config_addrs
.add(addr
)
959 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(interface_name
)
960 for saved_ifaceobj
in saved_ifaceobjs
or []:
961 for addr
in saved_ifaceobj
.get_attr_value('address') or []:
962 config_addrs
.add(addr
)
964 running_addrs
= OrderedDict()
965 cached_addrs
= self
.addr_get(interface_name
)
967 for addr
, addr_details
in cached_addrs
.items():
969 scope
= int(addr_details
['scope'])
973 addr_obj
= IPNetwork(addr
)
974 if isinstance(addr_obj
, IPv6Network
):
975 d
['family'] = 'inet6'
978 running_addrs
[addr
] = d
980 running_addrs
[addr
] = {}
982 if (scope
& Route
.RT_SCOPE_LINK
and addr
in config_addrs
) or not scope
& Route
.RT_SCOPE_LINK
:
983 running_addrs
[addr
] = addr_details
989 return running_addrs
.keys()
992 def compare_user_config_vs_running_state(running_addrs
, user_addrs
):
996 for ip
in user_addrs
or []:
999 if type(obj
) == IPv6Network
:
1005 for ip
in running_addrs
or []:
1006 running_ipobj
.append(IPNetwork(ip
))
1008 return running_ipobj
== (ip4
+ ip6
)
1010 def addr_add_multiple(self
, ifaceobj
, ifacename
, addrs
, purge_existing
=False, metric
=None):
1013 # if perfmode is not set and also if iface has no sibling
1014 # objects, purge addresses that are not present in the new
1016 runningaddrs
= self
.get_running_addrs(
1019 addr_virtual_ifaceobj
=ifaceobj
1021 addrs
= utils
.get_normalized_ip_addr(ifacename
, addrs
)
1023 if self
.compare_user_config_vs_running_state(runningaddrs
, addrs
):
1026 # if primary address is not same, there is no need to keep any.
1027 # reset all addresses
1028 if (addrs
and runningaddrs
and
1029 (addrs
[0] != runningaddrs
[0])):
1030 self
.del_addr_all(ifacename
)
1032 self
.del_addr_all(ifacename
, addrs
)
1033 except Exception, e
:
1034 self
.logger
.warning('%s: %s' % (ifacename
, str(e
)))
1037 self
.addr_add(ifacename
, a
, metric
=metric
)
1038 except Exception, e
:
1039 self
.logger
.error(str(e
))
1041 def _link_set_ifflag(self
, ifacename
, value
):
1042 # Dont look at the cache, the cache may have stale value
1043 # because link status can be changed by external
1044 # entity (One such entity is ifupdown main program)
1045 cmd
= 'link set dev %s %s' % (ifacename
, value
.lower())
1046 if LinkUtils
.ipbatch
:
1047 self
.add_to_batch(cmd
)
1049 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1051 def link_up(self
, ifacename
):
1052 self
._link
_set
_ifflag
(ifacename
, 'UP')
1054 def link_down(self
, ifacename
):
1055 self
._link
_set
_ifflag
(ifacename
, 'DOWN')
1057 def link_set(self
, ifacename
, key
, value
=None,
1058 force
=False, t
=None, state
=None):
1060 if (key
not in ['master', 'nomaster'] and
1061 self
._cache
_check
('link', [ifacename
, key
], value
)):
1063 cmd
= 'link set dev %s' % ifacename
1065 cmd
+= ' type %s' % t
1068 cmd
+= ' %s' % value
1070 cmd
+= ' %s' % state
1071 if LinkUtils
.ipbatch
:
1072 self
.add_to_batch(cmd
)
1074 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1075 if key
not in ['master', 'nomaster']:
1076 self
._cache
_update
([ifacename
, key
], value
)
1078 def link_set_hwaddress(self
, ifacename
, hwaddress
, force
=False):
1080 if self
._cache
_check
('link', [ifacename
, 'hwaddress'], hwaddress
):
1082 self
.link_down(ifacename
)
1083 cmd
= 'link set dev %s address %s' % (ifacename
, hwaddress
)
1084 if LinkUtils
.ipbatch
:
1085 self
.add_to_batch(cmd
)
1087 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1088 self
.link_up(ifacename
)
1089 self
._cache
_update
([ifacename
, 'hwaddress'], hwaddress
)
1091 def link_set_mtu(self
, ifacename
, mtu
):
1092 if ifupdownflags
.flags
.DRYRUN
:
1094 if not mtu
or not ifacename
: return
1095 self
.write_file('/sys/class/net/%s/mtu' % ifacename
, mtu
)
1096 self
._cache
_update
([ifacename
, 'mtu'], mtu
)
1098 def link_set_alias(self
, ifacename
, alias
):
1099 self
.write_file('/sys/class/net/%s/ifalias' % ifacename
,
1100 '\n' if not alias
else alias
)
1102 def link_get_alias(self
, ifacename
):
1103 return self
.read_file_oneline('/sys/class/net/%s/ifalias'
1106 def link_isloopback(self
, ifacename
):
1107 flags
= self
._cache
_get
('link', [ifacename
, 'flags'])
1110 if 'LOOPBACK' in flags
:
1114 def link_get_status(self
, ifacename
):
1115 return self
._cache
_get
('link', [ifacename
, 'ifflag'], refresh
=True)
1118 def route_add_gateway(ifacename
, gateway
, vrf
=None, metric
=None, onlink
=True):
1122 cmd
= '%s route add default via %s proto kernel' % (utils
.ip_cmd
,
1125 cmd
= ('%s route add table %s default via %s proto kernel' %
1126 (utils
.ip_cmd
, vrf
, gateway
))
1129 cmd
+= 'metric %s' % metric
1130 cmd
+= ' dev %s' % ifacename
1135 utils
.exec_command(cmd
)
1138 def route_del_gateway(ifacename
, gateway
, vrf
=None, metric
=None):
1143 cmd
= ('%s route del default via %s proto kernel' %
1144 (utils
.ip_cmd
, gateway
))
1146 cmd
= ('%s route del table %s default via %s proto kernel' %
1147 (utils
.ip_cmd
, vrf
, gateway
))
1149 cmd
+= ' metric %s' % metric
1150 cmd
+= ' dev %s' % ifacename
1151 utils
.exec_command(cmd
)
1154 def _get_vrf_id(ifacename
):
1156 return linkCache
.vrfs
[ifacename
]['table']
1158 dump
= netlink
.link_dump(ifacename
)
1160 [linkCache
.update_attrdict([ifname
], linkattrs
)
1161 for ifname
, linkattrs
in dump
.items()]
1163 if dump
and dump
.get(ifacename
, {}).get('kind') == 'vrf':
1164 vrf_table
= dump
.get(ifacename
, {}).get('linkinfo', {}).get('table')
1165 linkCache
.vrfs
[ifacename
] = {'table': vrf_table
}
1170 def fix_ipv6_route_metric(self
, ifaceobj
, macvlan_ifacename
, ips
):
1173 if ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
:
1175 for upper_iface
in ifaceobj
.upperifaces
:
1176 vrf_table
= self
._get
_vrf
_id
(upper_iface
)
1184 ip_network_obj
= IPNetwork(ip
)
1186 if type(ip_network_obj
) == IPv6Network
:
1187 route_prefix
= '%s/%d' % (ip_network_obj
.network
, ip_network_obj
.prefixlen
)
1190 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1191 LinkUtils
.add_to_batch('route del %s table %s dev %s' % (route_prefix
, vrf_table
, macvlan_ifacename
))
1193 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'table', vrf_table
, 'dev', macvlan_ifacename
])
1195 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1196 LinkUtils
.add_to_batch('route del %s dev %s' % (route_prefix
, macvlan_ifacename
))
1198 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'dev', macvlan_ifacename
])
1199 ip_route_del
.append((route_prefix
, vrf_table
))
1201 for ip
, vrf_table
in ip_route_del
:
1203 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1204 LinkUtils
.add_to_batch('route add %s table %s dev %s proto kernel metric 9999' % (ip
, vrf_table
, macvlan_ifacename
))
1206 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'table', vrf_table
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1208 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1209 LinkUtils
.add_to_batch('route add %s dev %s proto kernel metric 9999' % (ip
, macvlan_ifacename
))
1211 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1213 def link_create_vlan(self
, vlan_device_name
, vlan_raw_device
, vlanid
):
1214 if self
.link_exists(vlan_device_name
):
1216 utils
.exec_command('%s link add link %s name %s type vlan id %d' %
1218 vlan_raw_device
, vlan_device_name
, vlanid
))
1219 self
._cache
_update
([vlan_device_name
], {})
1221 def link_create_vlan_from_name(self
, vlan_device_name
):
1222 v
= vlan_device_name
.split('.')
1224 self
.logger
.warn('invalid vlan device name %s' % vlan_device_name
)
1226 self
.link_create_vlan(vlan_device_name
, v
[0], v
[1])
1228 def link_create_macvlan(self
, name
, linkdev
, mode
='private'):
1229 if self
.link_exists(name
):
1231 cmd
= ('link add link %s' % linkdev
+
1233 ' type macvlan mode %s' % mode
)
1234 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1235 self
.add_to_batch(cmd
)
1237 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1238 self
._cache
_update
([name
], {})
1240 def get_vxlan_peers(self
, dev
, svcnodeip
):
1241 cmd
= '%s fdb show brport %s' % (utils
.bridge_cmd
,
1245 ps
= subprocess
.Popen(shlex
.split(cmd
), stdout
=subprocess
.PIPE
, close_fds
=False)
1246 utils
.enable_subprocess_signal_forwarding(ps
, signal
.SIGINT
)
1247 output
= subprocess
.check_output(('grep', '00:00:00:00:00:00'), stdin
=ps
.stdout
)
1249 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1251 ppat
= re
.compile('\s+dst\s+(\d+.\d+.\d+.\d+)\s+')
1252 for l
in output
.split('\n'):
1254 if m
and m
.group(1) != svcnodeip
:
1255 cur_peers
.append(m
.group(1))
1257 self
.logger
.warn('error parsing ip link output')
1258 except subprocess
.CalledProcessError
as e
:
1259 if e
.returncode
!= 1:
1260 self
.logger
.error(str(e
))
1262 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1266 def tunnel_create(self
, tunnelname
, mode
, attrs
={}):
1267 """ generic link_create function """
1268 if self
.link_exists(tunnelname
):
1275 if mode
in ['gretap']:
1276 cmd
+= 'link add %s type %s' % (tunnelname
, mode
)
1278 cmd
+= 'tunnel add %s mode %s' % (tunnelname
, mode
)
1281 for k
, v
in attrs
.iteritems():
1285 if self
.ipbatch
and not self
.ipbatch_pause
:
1286 self
.add_to_batch(cmd
)
1288 utils
.exec_command('ip %s' % cmd
)
1289 self
._cache
_update
([tunnelname
], {})
1291 def tunnel_change(self
, tunnelname
, attrs
={}):
1292 """ tunnel change function """
1293 if not self
.link_exists(tunnelname
):
1295 cmd
= 'tunnel change'
1296 cmd
+= ' %s' %(tunnelname)
1298 for k
, v
in attrs
.iteritems():
1302 if self
.ipbatch
and not self
.ipbatch_pause
:
1303 self
.add_to_batch(cmd
)
1305 utils
.exec_command('ip %s' % cmd
)
1307 def link_create_vxlan(self
, name
, vxlanid
,
1314 if svcnodeip
and remoteips
:
1315 raise Exception("svcnodeip and remoteip is mutually exclusive")
1318 args
+= ' remote %s' % svcnodeip
1320 args
+= ' ageing %s' % ageing
1321 if learning
== 'off':
1322 args
+= ' nolearning'
1324 if self
.link_exists(name
):
1325 cmd
= 'link set dev %s type vxlan dstport %d' % (name
, LinkUtils
.VXLAN_UDP_PORT
)
1326 vxlanattrs
= self
.get_vxlandev_attrs(name
)
1327 # on ifreload do not overwrite anycast_ip to individual ip if clagd
1330 running_localtunnelip
= vxlanattrs
.get('local')
1331 if anycastip
and running_localtunnelip
and anycastip
== running_localtunnelip
:
1332 localtunnelip
= running_localtunnelip
1333 running_svcnode
= vxlanattrs
.get('svcnode')
1334 if running_svcnode
and not svcnodeip
:
1337 cmd
= 'link add dev %s type vxlan id %s dstport %d' % (name
, vxlanid
, LinkUtils
.VXLAN_UDP_PORT
)
1340 args
+= ' local %s' % localtunnelip
1343 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1344 self
.add_to_batch(cmd
)
1346 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1348 # XXX: update linkinfo correctly
1349 #self._cache_update([name], {})
1352 def link_exists(ifacename
):
1353 if ifupdownflags
.flags
.DRYRUN
:
1355 return os
.path
.exists('/sys/class/net/%s' % ifacename
)
1358 def link_exists_nodryrun(ifname
):
1359 return os
.path
.exists('/sys/class/net/%s' % ifname
)
1361 def link_get_ifindex(self
, ifacename
):
1362 if ifupdownflags
.flags
.DRYRUN
:
1364 return self
.read_file_oneline('/sys/class/net/%s/ifindex' % ifacename
)
1366 def is_vlan_device_by_name(self
, ifacename
):
1367 if re
.search(r
'\.', ifacename
):
1372 def link_add_macvlan(ifname
, macvlan_ifacename
):
1373 utils
.exec_commandl(['ip', 'link', 'add', 'link', ifname
, 'name', macvlan_ifacename
, 'type', 'macvlan', 'mode', 'private'])
1376 def route_add(route
):
1377 utils
.exec_command('%s route add %s' % (utils
.ip_cmd
,
1381 def route6_add(route
):
1382 utils
.exec_command('%s -6 route add %s' % (utils
.ip_cmd
,
1385 def get_vlandev_attrs(self
, ifacename
):
1386 return (self
._cache
_get
('link', [ifacename
, 'link']),
1387 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlanid']),
1388 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol']))
1390 def get_vlan_protocol(self
, ifacename
):
1391 return self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol'])
1393 def get_vxlandev_attrs(self
, ifacename
):
1394 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1396 def get_vxlandev_learning(self
, ifacename
):
1397 return self
._cache
_get
('link', [ifacename
, 'linkinfo', Link
.IFLA_VXLAN_LEARNING
])
1399 def set_vxlandev_learning(self
, ifacename
, learn
):
1401 utils
.exec_command('%s link set dev %s type vxlan learning' %
1402 (utils
.ip_cmd
, ifacename
))
1403 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'on')
1405 utils
.exec_command('%s link set dev %s type vxlan nolearning' %
1406 (utils
.ip_cmd
, ifacename
))
1407 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'off')
1409 def link_get_linkinfo_attrs(self
, ifacename
):
1410 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1412 def link_get_mtu(self
, ifacename
, refresh
=False):
1413 return self
._cache
_get
('link', [ifacename
, 'mtu'], refresh
=refresh
)
1415 def link_get_mtu_sysfs(self
, ifacename
):
1416 return self
.read_file_oneline('/sys/class/net/%s/mtu'
1419 def link_get_kind(self
, ifacename
):
1420 return self
._cache
_get
('link', [ifacename
, 'kind'])
1422 def link_get_slave_kind(self
, ifacename
):
1423 return self
._cache
_get
('link', [ifacename
, 'slave_kind'])
1425 def link_get_hwaddress(self
, ifacename
):
1426 address
= self
._cache
_get
('link', [ifacename
, 'hwaddress'])
1427 # newly created logical interface addresses dont end up in the cache
1428 # read hwaddress from sysfs file for these interfaces
1430 address
= self
.read_file_oneline('/sys/class/net/%s/address'
1434 def link_create(self
, ifacename
, t
, attrs
={}):
1435 """ generic link_create function """
1436 if self
.link_exists(ifacename
):
1439 cmd
+= ' name %s type %s' % (ifacename
, t
)
1441 for k
, v
in attrs
.iteritems():
1445 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1446 self
.add_to_batch(cmd
)
1448 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1449 self
._cache
_update
([ifacename
], {})
1451 def link_delete(self
, ifacename
):
1452 if not self
.link_exists(ifacename
):
1454 cmd
= 'link del %s' % ifacename
1455 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1456 self
.add_to_batch(cmd
)
1458 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1459 self
._cache
_invalidate
()
1461 def link_get_master(self
, ifacename
):
1462 sysfs_master_path
= '/sys/class/net/%s/master' % ifacename
1463 if os
.path
.exists(sysfs_master_path
):
1464 link_path
= os
.readlink(sysfs_master_path
)
1466 return os
.path
.basename(link_path
)
1470 return self
._cache
_get
('link', [ifacename
, 'master'])
1472 def get_brport_peer_link(self
, bridgename
):
1474 return self
._cache
_get
('link', [bridgename
, 'info_slave_data', Link
.IFLA_BRPORT_PEER_LINK
])
1479 def bridge_port_vids_add(bridgeportname
, vids
):
1480 [utils
.exec_command('%s vlan add vid %s dev %s' %
1482 v
, bridgeportname
)) for v
in vids
]
1485 def bridge_port_vids_del(bridgeportname
, vids
):
1488 [utils
.exec_command('%s vlan del vid %s dev %s' %
1490 v
, bridgeportname
)) for v
in vids
]
1493 def bridge_port_vids_flush(bridgeportname
, vid
):
1494 utils
.exec_command('%s vlan del vid %s dev %s' %
1496 vid
, bridgeportname
))
1499 def bridge_port_vids_get(bridgeportname
):
1500 bridgeout
= utils
.exec_command('%s vlan show dev %s' %
1505 brvlanlines
= bridgeout
.readlines()[2:]
1506 vids
= [l
.strip() for l
in brvlanlines
]
1507 return [v
for v
in vids
if v
]
1510 def bridge_port_vids_get_all():
1512 bridgeout
= utils
.exec_command('%s -c vlan show'
1516 brvlanlines
= bridgeout
.splitlines()
1518 for l
in brvlanlines
[1:]:
1519 if l
and not l
.startswith(' ') and not l
.startswith('\t'):
1521 brportname
= attrs
[0].strip()
1522 brvlaninfo
[brportname
] = {'pvid': None, 'vlan': []}
1523 l
= ' '.join(attrs
[1:])
1524 if not brportname
or not l
:
1528 brvlaninfo
[brportname
]['pvid'] = l
.split()[0]
1529 elif 'Egress Untagged' not in l
:
1530 brvlaninfo
[brportname
]['vlan'].append(l
)
1533 def bridge_port_vids_get_all_json(self
):
1534 if not self
.supported_command
['%s -c -json vlan show'
1535 % utils
.bridge_cmd
]:
1539 bridgeout
= utils
.exec_command('%s -c -json vlan show'
1542 self
.supported_command
['%s -c -json vlan show'
1543 % utils
.bridge_cmd
] = False
1544 self
.logger
.info('%s -c -json vlan show: skipping unsupported command'
1547 return self
.get_bridge_vlan_nojson()
1548 except Exception as e
:
1549 self
.logger
.info('bridge: get_bridge_vlan_nojson: %s' % str(e
))
1552 if not bridgeout
: return brvlaninfo
1554 vlan_json
= json
.loads(bridgeout
, encoding
="utf-8")
1555 except Exception, e
:
1556 self
.logger
.info('json loads failed with (%s)' % str(e
))
1560 if isinstance(vlan_json
, list):
1561 # newer iproute2 version changed the bridge vlan show output
1562 # ifupdown2 relies on the previous format, we have the convert
1563 # data into old format
1564 bridge_port_vids
= dict()
1566 for intf
in vlan_json
:
1567 bridge_port_vids
[intf
["ifname"]] = intf
["vlans"]
1569 return bridge_port_vids
1571 # older iproute2 version have different ways to dump vlans
1572 # ifupdown2 prefers the following syntax:
1576 # "flags": ["PVID", "Egress Untagged"]
1581 # "flags": ["PVID", "Egress Untagged"]
1585 except Exception as e
:
1586 self
.logger
.debug("bridge vlan show: Unknown json output: %s" % str(e
))
1590 def get_bridge_vlan_nojson():
1592 bridgeout
= utils
.exec_commandl([utils
.bridge_cmd
, '-c', 'vlan', 'show'])
1594 output
= [line
.split('\n') for line
in bridgeout
.split('\n\n')]
1595 output
[0] = output
[0][1:]
1603 prefix
, vlan
= entry
.split('\t')
1605 current_swp
= prefix
1606 vlan_json
[prefix
] = []
1610 v
['vlan'] = int(vlan
)
1614 start
, end
= vlan
.split('-')
1616 end
= end
[0:end
.index(' ')]
1617 v
['vlan'] = int(start
)
1618 v
['vlanEnd'] = int(end
)
1620 v
['vlan'] = int(vlan
[0:vlan
.index(' ')])
1623 flags
.append('PVID')
1624 if 'Egress Untagged' in vlan
:
1625 flags
.append('Egress Untagged')
1629 vlan_json
[current_swp
].append(v
)
1632 def bridge_vlan_cache_get(self
, ifacename
, refresh
=False):
1633 if not self
.bridge_vlan_cache_fill_done
or refresh
:
1634 self
.bridge_vlan_cache
= self
.bridge_port_vids_get_all_json()
1635 self
.bridge_vlan_cache_fill_done
= True
1636 return self
.bridge_vlan_cache
.get(ifacename
, {})
1638 def bridge_vlan_get_pvid(self
, ifacename
, refresh
=False):
1641 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1642 v
= vinfo
.get('vlan')
1643 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1648 def bridge_vlan_get_vids(self
, ifacename
, refresh
=False):
1651 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1652 v
= vinfo
.get('vlan')
1653 ispvid
= True if 'PVID' in vinfo
.get('flags', []) else False
1655 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1658 vEnd
= vinfo
.get('vlanEnd')
1660 vids
.extend(range(v
, vEnd
+ 1))
1665 def bridge_vlan_get_vids_n_pvid(self
, ifacename
, refresh
=False):
1669 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1670 v
= vinfo
.get('vlan')
1671 ispvid
= True if 'PVID' in vinfo
.get('flags', []) else False
1673 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1674 vEnd
= vinfo
.get('vlanEnd')
1676 vids
.extend(range(v
, vEnd
+ 1))
1681 def bridge_port_pvid_add(self
, bridgeportname
, pvid
):
1682 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1683 self
.add_to_batch('vlan add vid %s untagged pvid dev %s' %
1684 (pvid
, bridgeportname
))
1686 utils
.exec_command('%s vlan add vid %s untagged pvid dev %s' %
1688 pvid
, bridgeportname
))
1690 def bridge_port_pvid_del(self
, bridgeportname
, pvid
):
1691 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1692 self
.add_to_batch('vlan del vid %s untagged pvid dev %s' %
1693 (pvid
, bridgeportname
))
1695 utils
.exec_command('%s vlan del vid %s untagged pvid dev %s' %
1697 pvid
, bridgeportname
))
1699 def bridge_port_pvids_get(self
, bridgeportname
):
1700 return self
.read_file_oneline('/sys/class/net/%s/brport/pvid'
1703 def bridge_vids_add(self
, bridgeportname
, vids
, bridge
=True):
1704 target
= 'self' if bridge
else ''
1705 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1706 [self
.add_to_batch('vlan add vid %s dev %s %s' %
1707 (v
, bridgeportname
, target
)) for v
in vids
]
1709 [utils
.exec_command('%s vlan add vid %s dev %s %s' %
1711 v
, bridgeportname
, target
)) for v
in vids
]
1713 def bridge_vids_del(self
, bridgeportname
, vids
, bridge
=True):
1714 target
= 'self' if bridge
else ''
1715 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1716 [self
.add_to_batch('vlan del vid %s dev %s %s' %
1717 (v
, bridgeportname
, target
)) for v
in vids
]
1719 [utils
.exec_command('%s vlan del vid %s dev %s %s' %
1721 v
, bridgeportname
, target
)) for v
in vids
]
1724 def bridge_fdb_add(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1725 target
= 'self' if bridge
else ''
1728 vlan_str
= 'vlan %s ' % vlan
1732 dst_str
= 'dst %s ' % remote
1734 utils
.exec_command('%s fdb replace %s dev %s %s %s %s' %
1736 address
, dev
, vlan_str
, target
, dst_str
))
1739 def bridge_fdb_append(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1740 target
= 'self' if bridge
else ''
1743 vlan_str
= 'vlan %s ' % vlan
1747 dst_str
= 'dst %s ' % remote
1749 utils
.exec_command('%s fdb append %s dev %s %s %s %s' %
1751 address
, dev
, vlan_str
, target
, dst_str
))
1754 def bridge_fdb_del(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1755 target
= 'self' if bridge
else ''
1758 vlan_str
= 'vlan %s ' % vlan
1762 dst_str
= 'dst %s ' % remote
1763 utils
.exec_command('%s fdb del %s dev %s %s %s %s' %
1765 address
, dev
, vlan_str
, target
, dst_str
))
1767 def bridge_is_vlan_aware(self
, bridgename
):
1768 filename
= '/sys/class/net/%s/bridge/vlan_filtering' % bridgename
1769 if os
.path
.exists(filename
) and self
.read_file_oneline(filename
) == '1':
1774 def bridge_port_get_bridge_name(bridgeport
):
1775 filename
= '/sys/class/net/%s/brport/bridge' % bridgeport
1777 return os
.path
.basename(os
.readlink(filename
))
1782 def bridge_port_exists(bridge
, bridgeportname
):
1784 return os
.path
.exists('/sys/class/net/%s/brif/%s'
1785 % (bridge
, bridgeportname
))
1789 def bridge_fdb_show_dev(self
, dev
):
1792 output
= utils
.exec_command('%s fdb show dev %s'
1793 % (utils
.bridge_cmd
, dev
))
1795 for fdb_entry
in output
.splitlines():
1797 entries
= fdb_entry
.split()
1798 fdbs
.setdefault(entries
[2], []).append(entries
[0])
1800 self
.logger
.debug('%s: invalid fdb line \'%s\''
1807 def is_bridge(bridge
):
1808 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
1810 def is_link_up(self
, ifacename
):
1813 flags
= self
.read_file_oneline('/sys/class/net/%s/flags' % ifacename
)
1814 iflags
= int(flags
, 16)
1821 def ip_route_get_dev(self
, prefix
, vrf_master
=None):
1824 cmd
= '%s route get %s vrf %s' % (utils
.ip_cmd
, prefix
, vrf_master
)
1826 cmd
= '%s route get %s' % (utils
.ip_cmd
, prefix
)
1828 output
= utils
.exec_command(cmd
)
1830 rline
= output
.splitlines()[0]
1832 rattrs
= rline
.split()
1833 return rattrs
[rattrs
.index('dev') + 1]
1834 except Exception, e
:
1835 self
.logger
.debug('ip_route_get_dev: failed .. %s' % str(e
))
1839 def link_get_lowers(ifacename
):
1841 lowers
= glob
.glob("/sys/class/net/%s/lower_*" % ifacename
)
1844 return [os
.path
.basename(l
)[6:] for l
in lowers
]
1849 def link_get_uppers(ifacename
):
1851 uppers
= glob
.glob("/sys/class/net/%s/upper_*" % ifacename
)
1854 return [os
.path
.basename(u
)[6:] for u
in uppers
]
1858 def link_get_vrfs(self
):
1859 if not LinkUtils
._CACHE
_FILL
_DONE
:
1861 return linkCache
.vrfs
1864 def cache_get_info_slave(attrlist
):
1866 return linkCache
.get_attr(attrlist
)
1870 def get_brport_learning(self
, ifacename
):
1871 learn
= self
.read_file_oneline('/sys/class/net/%s/brport/learning'
1873 if learn
and learn
== '1':
1878 def get_brport_learning_bool(self
, ifacename
):
1879 return utils
.get_boolean_from_string(self
.read_file_oneline('/sys/class/net/%s/brport/learning' % ifacename
))
1881 def set_brport_learning(self
, ifacename
, learn
):
1883 return self
.write_file('/sys/class/net/%s/brport/learning'
1886 return self
.write_file('/sys/class/net/%s/brport/learning'
1889 #################################################################################
1890 ################################### BOND UTILS ##################################
1891 #################################################################################
1893 def _link_cache_get(self
, attrlist
, refresh
=False):
1894 return self
._cache
_get
('link', attrlist
, refresh
)
1896 def cache_delete(self
, attrlist
, value
=None):
1897 return self
._cache
_delete
(attrlist
, value
)
1899 def link_cache_get(self
, attrlist
, refresh
=False):
1900 return self
._link
_cache
_get
(attrlist
, refresh
)
1902 def link_cache_check(self
, attrlist
, value
, refresh
=False):
1903 return self
._link
_cache
_check
(attrlist
, value
, refresh
)
1905 def _link_cache_check(self
, attrlist
, value
, refresh
=False):
1907 return self
._link
_cache
_get
(attrlist
, refresh
) == value
1908 except Exception, e
:
1909 self
.logger
.debug('_cache_check(%s) : [%s]'
1910 % (str(attrlist
), str(e
)))
1915 Link
.IFLA_BOND_MODE
: 'mode',
1916 Link
.IFLA_BOND_MIIMON
: 'miimon',
1917 Link
.IFLA_BOND_USE_CARRIER
: 'use_carrier',
1918 Link
.IFLA_BOND_AD_LACP_RATE
: 'lacp_rate',
1919 Link
.IFLA_BOND_XMIT_HASH_POLICY
: 'xmit_hash_policy',
1920 Link
.IFLA_BOND_MIN_LINKS
: 'min_links',
1921 Link
.IFLA_BOND_NUM_PEER_NOTIF
: 'num_grat_arp',
1922 Link
.IFLA_BOND_AD_ACTOR_SYSTEM
: 'ad_actor_system',
1923 Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
: 'ad_actor_sys_prio',
1924 Link
.IFLA_BOND_AD_LACP_BYPASS
: 'lacp_bypass',
1925 Link
.IFLA_BOND_UPDELAY
: 'updelay',
1926 Link
.IFLA_BOND_DOWNDELAY
: 'downdelay',
1929 def bond_set_attrs_nl(self
, bondname
, ifla_info_data
):
1930 bond_attr_name
= 'None' # for log purpose (in case an exception raised)
1931 for nl_attr
, value
in ifla_info_data
.items():
1933 bond_attr_name
= self
.bondcmd_attrmap
[nl_attr
]
1934 file_path
= '/sys/class/net/%s/bonding/%s' % (bondname
, bond_attr_name
)
1935 if os
.path
.exists(file_path
):
1936 self
.write_file(file_path
, str(value
))
1937 except Exception as e
:
1938 exception_str
= '%s: %s %s: %s' % (bondname
, bond_attr_name
, value
, str(e
))
1939 if ifupdownflags
.flags
.FORCE
:
1940 self
.logger
.warning(exception_str
)
1942 self
.logger
.debug(exception_str
)
1944 def bond_set_attrs(self
, bondname
, attrdict
, prehook
):
1945 for attrname
, attrval
in attrdict
.items():
1946 if (self
._link
_cache
_check
([bondname
, 'linkinfo',
1947 attrname
], attrval
)):
1949 if (attrname
== 'mode'
1950 or attrname
== 'xmit_hash_policy'
1951 or attrname
== 'lacp_rate' or attrname
== 'min_links'):
1955 if ((attrname
not in ['lacp_rate',
1957 self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'], '802.3ad',
1959 self
.write_file('/sys/class/net/%s/bonding/%s'
1960 % (bondname
, attrname
), attrval
)
1961 except Exception, e
:
1962 if ifupdownflags
.flags
.FORCE
:
1963 self
.logger
.warn(str(e
))
1968 def bond_set_use_carrier(self
, bondname
, use_carrier
):
1969 if not use_carrier
or (use_carrier
!= '0' and use_carrier
!= '1'):
1971 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'use_carrier'],
1974 self
.write_file('/sys/class/net/%s' % bondname
+
1975 '/bonding/use_carrier', use_carrier
)
1976 self
._cache
_update
([bondname
, 'linkinfo',
1977 'use_carrier'], use_carrier
)
1979 def bond_get_use_carrier(self
, bondname
):
1980 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'use_carrier'])
1982 def bond_get_use_carrier_nl(self
, bondname
):
1983 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_USE_CARRIER
])
1985 def bond_set_xmit_hash_policy(self
, bondname
, hash_policy
, prehook
=None):
1986 valid_values
= ['layer2', 'layer3+4', 'layer2+3']
1989 if hash_policy
not in valid_values
:
1990 raise Exception('invalid hash policy value %s' % hash_policy
)
1991 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'xmit_hash_policy'],
1996 self
.write_file('/sys/class/net/%s' % bondname
+
1997 '/bonding/xmit_hash_policy', hash_policy
)
1998 self
._cache
_update
([bondname
, 'linkinfo', 'xmit_hash_policy'],
2001 def bond_get_xmit_hash_policy(self
, bondname
):
2002 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'xmit_hash_policy'])
2004 def bond_get_xmit_hash_policy_nl(self
, bondname
):
2005 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_XMIT_HASH_POLICY
])
2007 def bond_set_miimon(self
, bondname
, miimon
):
2008 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'miimon'],
2011 self
.write_file('/sys/class/net/%s' % bondname
+
2012 '/bonding/miimon', miimon
)
2013 self
._cache
_update
([bondname
, 'linkinfo', 'miimon'], miimon
)
2015 def bond_get_miimon(self
, bondname
):
2016 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'miimon'])
2018 def bond_get_miimon_nl(self
, bondname
):
2019 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIIMON
])
2021 def bond_set_mode(self
, bondname
, mode
, prehook
=None):
2022 valid_modes
= ['balance-rr', 'active-backup', 'balance-xor',
2023 'broadcast', '802.3ad', 'balance-tlb', 'balance-alb']
2026 if mode
not in valid_modes
:
2027 raise Exception('invalid mode %s' % mode
)
2028 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'],
2033 self
.write_file('/sys/class/net/%s' % bondname
+ '/bonding/mode', mode
)
2034 self
._cache
_update
([bondname
, 'linkinfo', 'mode'], mode
)
2036 def bond_get_mode(self
, bondname
):
2037 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'mode'])
2039 def bond_get_mode_nl(self
, bondname
):
2040 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MODE
])
2042 def bond_set_lacp_rate(self
, bondname
, lacp_rate
, prehook
=None, posthook
=None):
2043 if not lacp_rate
or (lacp_rate
!= '0' and lacp_rate
!= '1'):
2045 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_rate'],
2051 self
.write_file('/sys/class/net/%s' % bondname
+
2052 '/bonding/lacp_rate', lacp_rate
)
2058 self
._cache
_update
([bondname
, 'linkinfo',
2059 'lacp_rate'], lacp_rate
)
2061 def bond_get_lacp_rate(self
, bondname
):
2062 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_rate'])
2064 def bond_get_lacp_rate_nl(self
, bondname
):
2065 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_RATE
])
2067 def bond_set_lacp_bypass_allow(self
, bondname
, allow
, prehook
=None, posthook
=None):
2068 if self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_bypass'], allow
):
2073 self
.write_file('/sys/class/net/%s' % bondname
+
2074 '/bonding/lacp_bypass', allow
)
2080 self
._cache
_update
([bondname
, 'linkinfo',
2081 'lacp_bypass'], allow
)
2083 def bond_get_lacp_bypass_allow(self
, bondname
):
2084 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_bypass'])
2086 def bond_get_lacp_bypass_allow_nl(self
, bondname
):
2087 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_BYPASS
])
2089 def bond_set_min_links(self
, bondname
, min_links
, prehook
=None):
2090 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'min_links'],
2095 self
.write_file('/sys/class/net/%s/bonding/min_links' % bondname
,
2097 self
._cache
_update
([bondname
, 'linkinfo', 'min_links'], min_links
)
2099 def bond_get_min_links(self
, bondname
):
2100 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'min_links'])
2102 def get_min_links_nl(self
, bondname
):
2103 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIN_LINKS
])
2105 def bond_get_ad_actor_system(self
, bondname
):
2106 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_system'])
2108 def bond_get_ad_actor_system_nl(self
, bondname
):
2109 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYSTEM
])
2111 def bond_get_ad_actor_sys_prio(self
, bondname
):
2112 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_sys_prio'])
2114 def bond_get_ad_actor_sys_prio_nl(self
, bondname
):
2115 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
])
2117 def bond_get_num_unsol_na(self
, bondname
):
2118 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_unsol_na'])
2120 def bond_get_num_unsol_na_nl(self
, bondname
):
2121 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2123 def bond_get_num_grat_arp(self
, bondname
):
2124 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_grat_arp'])
2126 def bond_get_num_grat_arp_nl(self
, bondname
):
2127 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2129 def bond_get_updelay(self
, bondname
):
2130 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'updelay'])
2132 def bond_get_updelay_nl(self
, bondname
):
2133 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_UPDELAY
])
2135 def bond_get_downdelay(self
, bondname
):
2136 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'downdelay'])
2138 def bond_get_downdelay_nl(self
, bondname
):
2139 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_DOWNDELAY
])
2141 def bond_enslave_slave(self
, bondname
, slave
, prehook
=None, posthook
=None):
2142 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2143 if slaves
and slave
in slaves
:
2147 self
.write_file('/sys/class/net/%s' % bondname
+
2148 '/bonding/slaves', '+' + slave
)
2151 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slave
)
2153 def bond_remove_slave(self
, bondname
, slave
):
2154 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2155 if not slaves
or slave
not in slaves
:
2157 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2159 if not os
.path
.exists(sysfs_bond_path
):
2161 self
.write_file(sysfs_bond_path
, '-' + slave
)
2162 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'], slave
)
2164 def bond_remove_slaves_all(self
, bondname
):
2165 if not self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves']):
2168 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2171 with
open(sysfs_bond_path
, 'r') as f
:
2172 slaves
= f
.readline().strip().split()
2174 raise Exception('error reading slaves of bond %s (%s)' % (bondname
, str(e
)))
2175 for slave
in slaves
:
2176 self
.link_down(slave
)
2178 self
.bond_remove_slave(bondname
, slave
)
2179 except Exception, e
:
2180 if not ifupdownflags
.flags
.FORCE
:
2181 raise Exception('error removing slave %s from bond %s (%s)' % (slave
, bondname
, str(e
)))
2184 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'])
2187 def bond_load_bonding_module():
2188 return utils
.exec_command('%s -q bonding' % utils
.modprobe_cmd
)
2190 def create_bond(self
, bondname
):
2191 if self
.bond_exists(bondname
):
2193 # load_bonding_module() has already been run
2194 self
.write_file('/sys/class/net/bonding_masters', '+' + bondname
)
2195 self
._cache
_update
([bondname
], {})
2197 def delete_bond(self
, bondname
):
2198 if not os
.path
.exists('/sys/class/net/%s' % bondname
):
2200 self
.write_file('/sys/class/net/bonding_masters', '-' + bondname
)
2201 self
._cache
_delete
([bondname
])
2203 def bond_get_slaves(self
, bondname
):
2204 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2207 slavefile
= '/sys/class/net/%s/bonding/slaves' % bondname
2208 if os
.path
.exists(slavefile
):
2209 buf
= self
.read_file_oneline(slavefile
)
2211 slaves
= buf
.split()
2214 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slaves
)
2217 def bond_slave_exists(self
, bond
, slave
):
2218 slaves
= self
.bond_get_slaves(bond
)
2221 return slave
in slaves
2224 def bond_exists(bondname
):
2225 return os
.path
.exists('/sys/class/net/%s/bonding' % bondname
)
2227 #################################################################################
2228 ################################## BRIDGE UTILS #################################
2229 #################################################################################
2231 def create_bridge(self
, bridgename
):
2232 if not LinkUtils
.bridge_utils_is_installed
:
2234 if self
.bridge_exists(bridgename
):
2236 utils
.exec_command('%s addbr %s' % (utils
.brctl_cmd
, bridgename
))
2237 self
._cache
_update
([bridgename
], {})
2239 def delete_bridge(self
, bridgename
):
2240 if not LinkUtils
.bridge_utils_is_installed
:
2242 if not self
.bridge_exists(bridgename
):
2244 utils
.exec_command('%s delbr %s' % (utils
.brctl_cmd
, bridgename
))
2245 self
._cache
_invalidate
()
2247 def add_bridge_port(self
, bridgename
, bridgeportname
):
2248 """ Add port to bridge """
2249 if not LinkUtils
.bridge_utils_is_installed
:
2251 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2252 if ports
and ports
.get(bridgeportname
):
2254 utils
.exec_command('%s addif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2255 self
._cache
_update
([bridgename
, 'linkinfo', 'ports', bridgeportname
], {})
2257 def delete_bridge_port(self
, bridgename
, bridgeportname
):
2258 """ Delete port from bridge """
2259 if not LinkUtils
.bridge_utils_is_installed
:
2261 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2262 if not ports
or not ports
.get(bridgeportname
):
2264 utils
.exec_command('%s delif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2265 self
._cache
_delete
([bridgename
, 'linkinfo', 'ports', 'bridgeportname'])
2267 def set_bridgeport_attrs(self
, bridgename
, bridgeportname
, attrdict
):
2268 portattrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports', bridgeportname
])
2269 if portattrs
== None:
2271 for k
, v
in attrdict
.iteritems():
2272 if ifupdownflags
.flags
.CACHE
:
2273 curval
= portattrs
.get(k
)
2274 if curval
and curval
== v
:
2276 if k
== 'unicast-flood':
2277 self
.write_file('/sys/class/net/%s/brport/unicast_flood' % bridgeportname
, v
)
2278 elif k
== 'multicast-flood':
2279 self
.write_file('/sys/class/net/%s/brport/multicast_flood' % bridgeportname
, v
)
2280 elif k
== 'learning':
2281 self
.write_file('/sys/class/net/%s/brport/learning' % bridgeportname
, v
)
2282 elif k
== 'arp-nd-suppress':
2283 self
.write_file('/sys/class/net/%s/brport/neigh_suppress' % bridgeportname
, v
)
2285 if not LinkUtils
.bridge_utils_is_installed
:
2287 utils
.exec_command('%s set%s %s %s %s' % (utils
.brctl_cmd
, k
, bridgename
, bridgeportname
, v
))
2289 def set_bridgeport_attr(self
, bridgename
, bridgeportname
,
2291 if not LinkUtils
.bridge_utils_is_installed
:
2293 if self
._link
_cache
_check
([bridgename
, 'linkinfo', 'ports', bridgeportname
, attrname
], attrval
):
2295 utils
.exec_command('%s set%s %s %s %s' %
2302 def set_bridge_attrs(self
, bridgename
, attrdict
):
2303 for k
, v
in attrdict
.iteritems():
2306 if self
._link
_cache
_check
([bridgename
, 'linkinfo', k
], v
):
2309 if k
== 'igmp-version':
2310 self
.write_file('/sys/class/net/%s/bridge/'
2311 'multicast_igmp_version' % bridgename
, v
)
2312 elif k
== 'mld-version':
2313 self
.write_file('/sys/class/net/%s/bridge/'
2314 'multicast_mld_version' % bridgename
, v
)
2315 elif k
== 'vlan-protocol':
2316 self
.write_file('/sys/class/net/%s/bridge/'
2317 'vlan_protocol' % bridgename
,
2318 VlanProtocols
.ETHERTYPES_TO_ID
.get(v
.upper(),
2320 elif k
== 'vlan-stats':
2321 self
.write_file('/sys/class/net/%s/bridge/'
2322 'vlan_stats_enabled' % bridgename
, v
)
2323 elif k
== 'mcstats':
2324 self
.write_file('/sys/class/net/%s/bridge/'
2325 'multicast_stats_enabled' % bridgename
, v
)
2327 if not LinkUtils
.bridge_utils_is_installed
:
2329 cmd
= ('%s set%s %s %s' %
2330 (utils
.brctl_cmd
, k
, bridgename
, v
))
2331 utils
.exec_command(cmd
)
2332 except Exception, e
:
2333 self
.logger
.warn('%s: %s' % (bridgename
, str(e
)))
2336 def set_bridge_attr(self
, bridgename
, attrname
, attrval
):
2337 if self
._link
_cache
_check
([bridgename
, 'linkinfo', attrname
], attrval
):
2339 if attrname
== 'igmp-version':
2340 self
.write_file('/sys/class/net/%s/bridge/multicast_igmp_version'
2341 % bridgename
, attrval
)
2342 elif attrname
== 'mld-version':
2343 self
.write_file('/sys/class/net/%s/bridge/multicast_mld_version'
2344 % bridgename
, attrval
)
2345 elif attrname
== 'vlan-protocol':
2346 self
.write_file('/sys/class/net/%s/bridge/vlan_protocol'
2347 % bridgename
, VlanProtocols
.ETHERTYPES_TO_ID
[attrval
.upper()])
2348 elif attrname
== 'vlan-stats':
2349 self
.write_file('/sys/class/net/%s/bridge/vlan_stats_enabled'
2350 % bridgename
, attrval
)
2351 elif attrname
== 'mcstats':
2352 self
.write_file('/sys/class/net/%s/bridge/multicast_stats_enabled'
2353 % bridgename
, attrval
)
2355 if not LinkUtils
.bridge_utils_is_installed
:
2357 cmd
= '%s set%s %s %s' % (utils
.brctl_cmd
,
2358 attrname
, bridgename
, attrval
)
2359 utils
.exec_command(cmd
)
2361 def get_bridge_attrs(self
, bridgename
):
2362 attrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo'])
2364 for key
, value
in attrs
.items():
2365 if type(key
) == str:
2366 no_ints_attrs
[key
] = value
2367 return no_ints_attrs
2369 def get_bridgeport_attrs(self
, bridgename
, bridgeportname
):
2370 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2373 def get_bridgeport_attr(self
, bridgename
, bridgeportname
, attrname
):
2374 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2375 bridgeportname
, attrname
])
2378 def bridge_set_stp(bridge
, stp_state
):
2379 if not LinkUtils
.bridge_utils_is_installed
:
2381 utils
.exec_command('%s stp %s %s' % (utils
.brctl_cmd
, bridge
, stp_state
))
2383 def bridge_get_stp(self
, bridge
):
2384 sysfs_stpstate
= '/sys/class/net/%s/bridge/stp_state' % bridge
2385 if not os
.path
.exists(sysfs_stpstate
):
2387 stpstate
= self
.read_file_oneline(sysfs_stpstate
)
2391 if int(stpstate
) > 0:
2393 elif int(stpstate
) == 0:
2399 def _conv_value_to_user(s
):
2406 def read_value_from_sysfs(self
, filename
, preprocess_func
):
2407 value
= self
.read_file_oneline(filename
)
2410 return preprocess_func(value
)
2413 def bridge_set_ageing(bridge
, ageing
):
2414 if not LinkUtils
.bridge_utils_is_installed
:
2416 utils
.exec_command('%s setageing %s %s' % (utils
.brctl_cmd
, bridge
, ageing
))
2418 def bridge_get_ageing(self
, bridge
):
2419 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/ageing_time'
2420 % bridge
, self
._conv
_value
_to
_user
)
2423 def set_bridgeprio(bridge
, prio
):
2424 if not LinkUtils
.bridge_utils_is_installed
:
2426 utils
.exec_command('%s setbridgeprio %s %s' % (utils
.brctl_cmd
, bridge
, prio
))
2428 def get_bridgeprio(self
, bridge
):
2429 return self
.read_file_oneline(
2430 '/sys/class/net/%s/bridge/priority' % bridge
)
2433 def bridge_set_fd(bridge
, fd
):
2434 if not LinkUtils
.bridge_utils_is_installed
:
2436 utils
.exec_command('%s setfd %s %s' % (utils
.brctl_cmd
, bridge
, fd
))
2438 def bridge_get_fd(self
, bridge
):
2439 return self
.read_value_from_sysfs(
2440 '/sys/class/net/%s/bridge/forward_delay'
2441 % bridge
, self
._conv
_value
_to
_user
)
2443 def bridge_set_gcint(self
, bridge
, gcint
):
2444 raise Exception('set_gcint not implemented')
2447 def bridge_set_hello(bridge
, hello
):
2448 if not LinkUtils
.bridge_utils_is_installed
:
2450 utils
.exec_command('%s sethello %s %s' % (utils
.brctl_cmd
, bridge
, hello
))
2452 def bridge_get_hello(self
, bridge
):
2453 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/hello_time'
2454 % bridge
, self
._conv
_value
_to
_user
)
2457 def bridge_set_maxage(bridge
, maxage
):
2458 if not LinkUtils
.bridge_utils_is_installed
:
2460 utils
.exec_command('%s setmaxage %s %s' % (utils
.brctl_cmd
, bridge
, maxage
))
2462 def bridge_get_maxage(self
, bridge
):
2463 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/max_age'
2464 % bridge
, self
._conv
_value
_to
_user
)
2467 def bridge_set_pathcost(bridge
, port
, pathcost
):
2468 if not LinkUtils
.bridge_utils_is_installed
:
2470 utils
.exec_command('%s setpathcost %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, pathcost
))
2472 def bridge_get_pathcost(self
, bridge
, port
):
2473 return self
.read_file_oneline('/sys/class/net/%s/brport/path_cost'
2477 def bridge_set_portprio(bridge
, port
, prio
):
2478 if not LinkUtils
.bridge_utils_is_installed
:
2480 utils
.exec_command('%s setportprio %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, prio
))
2482 def bridge_get_portprio(self
, bridge
, port
):
2483 return self
.read_file_oneline('/sys/class/net/%s/brport/priority'
2487 def bridge_set_hashmax(bridge
, hashmax
):
2488 if not LinkUtils
.bridge_utils_is_installed
:
2490 utils
.exec_command('%s sethashmax %s %s' % (utils
.brctl_cmd
, bridge
, hashmax
))
2492 def bridge_get_hashmax(self
, bridge
):
2493 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_max'
2497 def bridge_set_hashel(bridge
, hashel
):
2498 if not LinkUtils
.bridge_utils_is_installed
:
2500 utils
.exec_command('%s sethashel %s %s' % (utils
.brctl_cmd
, bridge
, hashel
))
2502 def bridge_get_hashel(self
, bridge
):
2503 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_elasticity'
2507 def bridge_set_mclmc(bridge
, mclmc
):
2508 if not LinkUtils
.bridge_utils_is_installed
:
2510 utils
.exec_command('%s setmclmc %s %s' % (utils
.brctl_cmd
, bridge
, mclmc
))
2512 def bridge_get_mclmc(self
, bridge
):
2513 return self
.read_file_oneline(
2514 '/sys/class/net/%s/bridge/multicast_last_member_count'
2518 def bridge_set_mcrouter(bridge
, mcrouter
):
2519 if not LinkUtils
.bridge_utils_is_installed
:
2521 utils
.exec_command('%s setmcrouter %s %s' % (utils
.brctl_cmd
, bridge
, mcrouter
))
2523 def bridge_get_mcrouter(self
, bridge
):
2524 return self
.read_file_oneline(
2525 '/sys/class/net/%s/bridge/multicast_router' % bridge
)
2528 def bridge_set_mcsnoop(bridge
, mcsnoop
):
2529 if not LinkUtils
.bridge_utils_is_installed
:
2531 utils
.exec_command('%s setmcsnoop %s %s' % (utils
.brctl_cmd
, bridge
, mcsnoop
))
2533 def bridge_get_mcsnoop(self
, bridge
):
2534 return self
.read_file_oneline(
2535 '/sys/class/net/%s/bridge/multicast_snooping' % bridge
)
2538 def bridge_set_mcsqc(bridge
, mcsqc
):
2539 if not LinkUtils
.bridge_utils_is_installed
:
2541 utils
.exec_command('%s setmcsqc %s %s' % (utils
.brctl_cmd
, bridge
, mcsqc
))
2543 def bridge_get_mcsqc(self
, bridge
):
2544 return self
.read_file_oneline(
2545 '/sys/class/net/%s/bridge/multicast_startup_query_count'
2549 def bridge_set_mcqifaddr(bridge
, mcqifaddr
):
2550 if not LinkUtils
.bridge_utils_is_installed
:
2552 utils
.exec_command('%s setmcqifaddr %s %s' % (utils
.brctl_cmd
, bridge
, mcqifaddr
))
2554 def bridge_get_mcqifaddr(self
, bridge
):
2555 return self
.read_file_oneline(
2556 '/sys/class/net/%s/bridge/multicast_startup_query_use_ifaddr'
2560 def bridge_set_mcquerier(bridge
, mcquerier
):
2561 if not LinkUtils
.bridge_utils_is_installed
:
2563 utils
.exec_command('%s setmcquerier %s %s' % (utils
.brctl_cmd
, bridge
, mcquerier
))
2565 def bridge_get_mcquerier(self
, bridge
):
2566 return self
.read_file_oneline(
2567 '/sys/class/net/%s/bridge/multicast_querier' % bridge
)
2569 def bridge_set_mcqv4src(self
, bridge
, vlan
, mcquerier
):
2573 self
.logger
.info('%s: set mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2575 if vlan
== 0 or vlan
> 4095:
2576 self
.logger
.warn('mcqv4src vlan \'%d\' invalid range' % vlan
)
2579 ip
= mcquerier
.split('.')
2581 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2584 if not k
.isdigit() or int(k
, 10) < 0 or int(k
, 10) > 255:
2585 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2588 if not LinkUtils
.bridge_utils_is_installed
:
2591 utils
.exec_command('%s setmcqv4src %s %d %s' %
2592 (utils
.brctl_cmd
, bridge
, vlan
, mcquerier
))
2594 def bridge_del_mcqv4src(self
, bridge
, vlan
):
2595 if not LinkUtils
.bridge_utils_is_installed
:
2600 self
.logger
.info('%s: del mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2602 utils
.exec_command('%s delmcqv4src %s %d' % (utils
.brctl_cmd
, bridge
, vlan
))
2604 def bridge_get_mcqv4src(self
, bridge
, vlan
=None):
2605 if not LinkUtils
.bridge_utils_is_installed
:
2607 if not self
.supported_command
['showmcqv4src']:
2611 mcqout
= utils
.exec_command('%s showmcqv4src %s' %
2612 (utils
.brctl_cmd
, bridge
))
2613 except Exception as e
:
2615 if 'never heard' in s
:
2616 msg
= ('%s showmcqv4src: skipping unsupported command'
2618 self
.logger
.info(msg
)
2619 self
.supported_command
['showmcqv4src'] = False
2624 mcqlines
= mcqout
.splitlines()
2625 for l
in mcqlines
[1:]:
2627 k
, d
, v
= l
.split('\t')
2632 return mcqv4src
.get(vlan
)
2635 def bridge_get_mcqv4src_sysfs(self
, bridge
, vlan
=None):
2636 if not LinkUtils
.bridge_utils_is_installed
:
2638 if not self
.supported_command
['showmcqv4src']:
2640 if ifupdownflags
.flags
.PERFMODE
:
2644 filename
= '/sys/class/net/%s/bridge/multicast_v4_queriers' % bridge
2645 if os
.path
.exists(filename
):
2646 for line
in self
.read_file(filename
) or []:
2647 vlan_id
, ip
= line
.split('=')
2648 mcqv4src
[vlan_id
] = ip
.strip()
2649 except Exception as e
:
2651 msg
= ('%s showmcqv4src: skipping unsupported command'
2653 self
.logger
.info(msg
)
2654 self
.supported_command
['showmcqv4src'] = False
2657 return mcqv4src
.get(vlan
)
2661 def bridge_set_mclmi(bridge
, mclmi
):
2662 if not LinkUtils
.bridge_utils_is_installed
:
2664 utils
.exec_command('%s setmclmi %s %s' % (utils
.brctl_cmd
, bridge
, mclmi
))
2666 def bridge_get_mclmi(self
, bridge
):
2667 return self
.read_file_oneline(
2668 '/sys/class/net/%s/bridge/multicast_last_member_interval'
2672 def bridge_set_mcmi(bridge
, mcmi
):
2673 if not LinkUtils
.bridge_utils_is_installed
:
2675 utils
.exec_command('%s setmcmi %s %s' % (utils
.brctl_cmd
, bridge
, mcmi
))
2677 def bridge_get_mcmi(self
, bridge
):
2678 return self
.read_file_oneline(
2679 '/sys/class/net/%s/bridge/multicast_membership_interval'
2683 def bridge_exists(bridge
):
2684 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
2687 def is_bridge_port(ifacename
):
2688 return os
.path
.exists('/sys/class/net/%s/brport' % ifacename
)
2691 def bridge_port_exists(bridge
, bridgeportname
):
2693 return os
.path
.exists('/sys/class/net/%s/brif/%s' % (bridge
, bridgeportname
))
2698 def get_bridge_ports(bridgename
):
2700 return os
.listdir('/sys/class/net/%s/brif/' % bridgename
)
2704 def reset_addr_cache(self
, ifname
):
2706 linkCache
.links
[ifname
]['addrs'] = {}
2707 self
.logger
.debug('%s: reset address cache' % ifname
)
2711 def get_ipv6_addrgen_mode(self
, ifname
):
2713 return self
._cache
_get
('link', [ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
]
2715 # default to 0 (eui64)
2718 def ipv6_addrgen(self
, ifname
, addrgen
, link_created
):
2720 # IFLA_INET6_ADDR_GEN_MODE values:
2723 if self
._link
_cache
_get
([ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
] == addrgen
:
2724 self
.logger
.debug('%s: ipv6 addrgen already %s' % (ifname
, 'off' if addrgen
else 'on'))
2727 disabled_ipv6
= self
.read_file_oneline('/proc/sys/net/ipv6/conf/%s/disable_ipv6' % ifname
)
2728 if not disabled_ipv6
or int(disabled_ipv6
) == 1:
2729 self
.logger
.info('%s: cannot set addrgen: ipv6 is disabled on this device' % ifname
)
2732 if int(self
._link
_cache
_get
([ifname
, 'mtu'])) < 1280:
2733 self
.logger
.info('%s: ipv6 addrgen is disabled on device with MTU '
2734 'lower than 1280: cannot set addrgen %s' % (ifname
, 'off' if addrgen
else 'on'))
2736 except (KeyError, TypeError):
2737 self
.logger
.debug('%s: ipv6 addrgen probably not supported or disabled on this device' % ifname
)
2742 if not link_created
:
2743 # When setting addrgenmode it is necessary to flap the macvlan
2744 # device. After flapping the device we also need to re-add all
2745 # the user configuration. The best way to add the user config
2746 # is to flush our internal address cache
2747 self
.reset_addr_cache(ifname
)
2749 cmd
= 'link set dev %s addrgenmode %s' % (ifname
, 'none' if addrgen
else 'eui64')
2751 is_link_up
= self
.is_link_up(ifname
)
2754 self
.link_down(ifname
)
2756 if LinkUtils
.ipbatch
:
2757 self
.add_to_batch(cmd
)
2759 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
2762 self
.link_up(ifname
)