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 attr_name
in ["address-virtual", "vrrp"]:
938 for virtual
in addr_virtual_ifaceobj
.get_attr_value(attr_name
) or []:
939 for ip
in virtual
.split():
946 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(addr_virtual_ifaceobj
.name
)
947 for saved_ifaceobj
in saved_ifaceobjs
or []:
948 for virtual
in saved_ifaceobj
.get_attr_value(attr_name
) or []:
949 for ip
in virtual
.split():
957 for addr
in ifaceobj
.get_attr_value('address') or []:
958 config_addrs
.add(addr
)
960 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(interface_name
)
961 for saved_ifaceobj
in saved_ifaceobjs
or []:
962 for addr
in saved_ifaceobj
.get_attr_value('address') or []:
963 config_addrs
.add(addr
)
965 running_addrs
= OrderedDict()
966 cached_addrs
= self
.addr_get(interface_name
)
968 for addr
, addr_details
in cached_addrs
.items():
970 scope
= int(addr_details
['scope'])
974 addr_obj
= IPNetwork(addr
)
975 if isinstance(addr_obj
, IPv6Network
):
976 d
['family'] = 'inet6'
979 running_addrs
[addr
] = d
981 running_addrs
[addr
] = {}
983 if (scope
& Route
.RT_SCOPE_LINK
and addr
in config_addrs
) or not scope
& Route
.RT_SCOPE_LINK
:
984 running_addrs
[addr
] = addr_details
990 return running_addrs
.keys()
993 def compare_user_config_vs_running_state(running_addrs
, user_addrs
):
997 for ip
in user_addrs
or []:
1000 if type(obj
) == IPv6Network
:
1006 for ip
in running_addrs
or []:
1007 running_ipobj
.append(IPNetwork(ip
))
1009 return running_ipobj
== (ip4
+ ip6
)
1011 def addr_add_multiple(self
, ifaceobj
, ifacename
, addrs
, purge_existing
=False, metric
=None):
1014 # if perfmode is not set and also if iface has no sibling
1015 # objects, purge addresses that are not present in the new
1017 runningaddrs
= self
.get_running_addrs(
1020 addr_virtual_ifaceobj
=ifaceobj
1022 addrs
= utils
.get_normalized_ip_addr(ifacename
, addrs
)
1024 if self
.compare_user_config_vs_running_state(runningaddrs
, addrs
):
1027 # if primary address is not same, there is no need to keep any.
1028 # reset all addresses
1029 if (addrs
and runningaddrs
and
1030 (addrs
[0] != runningaddrs
[0])):
1031 self
.del_addr_all(ifacename
)
1033 self
.del_addr_all(ifacename
, addrs
)
1034 except Exception, e
:
1035 self
.logger
.warning('%s: %s' % (ifacename
, str(e
)))
1038 self
.addr_add(ifacename
, a
, metric
=metric
)
1039 except Exception, e
:
1040 self
.logger
.error(str(e
))
1042 def _link_set_ifflag(self
, ifacename
, value
):
1043 # Dont look at the cache, the cache may have stale value
1044 # because link status can be changed by external
1045 # entity (One such entity is ifupdown main program)
1046 cmd
= 'link set dev %s %s' % (ifacename
, value
.lower())
1047 if LinkUtils
.ipbatch
:
1048 self
.add_to_batch(cmd
)
1050 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1052 def link_up(self
, ifacename
):
1053 self
._link
_set
_ifflag
(ifacename
, 'UP')
1055 def link_down(self
, ifacename
):
1056 self
._link
_set
_ifflag
(ifacename
, 'DOWN')
1058 def link_set(self
, ifacename
, key
, value
=None,
1059 force
=False, t
=None, state
=None):
1061 if (key
not in ['master', 'nomaster'] and
1062 self
._cache
_check
('link', [ifacename
, key
], value
)):
1064 cmd
= 'link set dev %s' % ifacename
1066 cmd
+= ' type %s' % t
1069 cmd
+= ' %s' % value
1071 cmd
+= ' %s' % state
1072 if LinkUtils
.ipbatch
:
1073 self
.add_to_batch(cmd
)
1075 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1076 if key
not in ['master', 'nomaster']:
1077 self
._cache
_update
([ifacename
, key
], value
)
1079 def link_set_hwaddress(self
, ifacename
, hwaddress
, force
=False):
1081 if self
._cache
_check
('link', [ifacename
, 'hwaddress'], hwaddress
):
1083 self
.link_down(ifacename
)
1084 cmd
= 'link set dev %s address %s' % (ifacename
, hwaddress
)
1085 if LinkUtils
.ipbatch
:
1086 self
.add_to_batch(cmd
)
1088 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1089 self
.link_up(ifacename
)
1090 self
._cache
_update
([ifacename
, 'hwaddress'], hwaddress
)
1092 def link_set_mtu(self
, ifacename
, mtu
):
1093 if ifupdownflags
.flags
.DRYRUN
:
1095 if not mtu
or not ifacename
: return
1096 self
.write_file('/sys/class/net/%s/mtu' % ifacename
, mtu
)
1097 self
._cache
_update
([ifacename
, 'mtu'], mtu
)
1099 def link_set_alias(self
, ifacename
, alias
):
1100 self
.write_file('/sys/class/net/%s/ifalias' % ifacename
,
1101 '\n' if not alias
else alias
)
1103 def link_get_alias(self
, ifacename
):
1104 return self
.read_file_oneline('/sys/class/net/%s/ifalias'
1107 def link_isloopback(self
, ifacename
):
1108 flags
= self
._cache
_get
('link', [ifacename
, 'flags'])
1111 if 'LOOPBACK' in flags
:
1115 def link_get_status(self
, ifacename
):
1116 return self
._cache
_get
('link', [ifacename
, 'ifflag'], refresh
=True)
1119 def route_add_gateway(ifacename
, gateway
, vrf
=None, metric
=None, onlink
=True):
1123 cmd
= '%s route add default via %s proto kernel' % (utils
.ip_cmd
,
1126 cmd
= ('%s route add table %s default via %s proto kernel' %
1127 (utils
.ip_cmd
, vrf
, gateway
))
1130 cmd
+= 'metric %s' % metric
1131 cmd
+= ' dev %s' % ifacename
1136 utils
.exec_command(cmd
)
1139 def route_del_gateway(ifacename
, gateway
, vrf
=None, metric
=None):
1144 cmd
= ('%s route del default via %s proto kernel' %
1145 (utils
.ip_cmd
, gateway
))
1147 cmd
= ('%s route del table %s default via %s proto kernel' %
1148 (utils
.ip_cmd
, vrf
, gateway
))
1150 cmd
+= ' metric %s' % metric
1151 cmd
+= ' dev %s' % ifacename
1152 utils
.exec_command(cmd
)
1155 def _get_vrf_id(ifacename
):
1157 return linkCache
.vrfs
[ifacename
]['table']
1159 dump
= netlink
.link_dump(ifacename
)
1161 [linkCache
.update_attrdict([ifname
], linkattrs
)
1162 for ifname
, linkattrs
in dump
.items()]
1164 if dump
and dump
.get(ifacename
, {}).get('kind') == 'vrf':
1165 vrf_table
= dump
.get(ifacename
, {}).get('linkinfo', {}).get('table')
1166 linkCache
.vrfs
[ifacename
] = {'table': vrf_table
}
1171 def fix_ipv6_route_metric(self
, ifaceobj
, macvlan_ifacename
, ips
):
1174 if ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
:
1176 for upper_iface
in ifaceobj
.upperifaces
:
1177 vrf_table
= self
._get
_vrf
_id
(upper_iface
)
1185 ip_network_obj
= IPNetwork(ip
)
1187 if type(ip_network_obj
) == IPv6Network
:
1188 route_prefix
= '%s/%d' % (ip_network_obj
.network
, ip_network_obj
.prefixlen
)
1191 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1192 LinkUtils
.add_to_batch('route del %s table %s dev %s' % (route_prefix
, vrf_table
, macvlan_ifacename
))
1194 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'table', vrf_table
, 'dev', macvlan_ifacename
])
1196 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1197 LinkUtils
.add_to_batch('route del %s dev %s' % (route_prefix
, macvlan_ifacename
))
1199 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'dev', macvlan_ifacename
])
1200 ip_route_del
.append((route_prefix
, vrf_table
))
1202 for ip
, vrf_table
in ip_route_del
:
1204 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1205 LinkUtils
.add_to_batch('route add %s table %s dev %s proto kernel metric 9999' % (ip
, vrf_table
, macvlan_ifacename
))
1207 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'table', vrf_table
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1209 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1210 LinkUtils
.add_to_batch('route add %s dev %s proto kernel metric 9999' % (ip
, macvlan_ifacename
))
1212 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1214 def link_create_vlan(self
, vlan_device_name
, vlan_raw_device
, vlanid
):
1215 if self
.link_exists(vlan_device_name
):
1217 utils
.exec_command('%s link add link %s name %s type vlan id %d' %
1219 vlan_raw_device
, vlan_device_name
, vlanid
))
1220 self
._cache
_update
([vlan_device_name
], {})
1222 def link_create_vlan_from_name(self
, vlan_device_name
):
1223 v
= vlan_device_name
.split('.')
1225 self
.logger
.warn('invalid vlan device name %s' % vlan_device_name
)
1227 self
.link_create_vlan(vlan_device_name
, v
[0], v
[1])
1229 def link_create_macvlan(self
, name
, linkdev
, mode
='private'):
1230 if self
.link_exists(name
):
1232 cmd
= ('link add link %s' % linkdev
+
1234 ' type macvlan mode %s' % mode
)
1235 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1236 self
.add_to_batch(cmd
)
1238 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1239 self
._cache
_update
([name
], {})
1241 def get_vxlan_peers(self
, dev
, svcnodeip
):
1242 cmd
= '%s fdb show brport %s' % (utils
.bridge_cmd
,
1246 ps
= subprocess
.Popen(shlex
.split(cmd
), stdout
=subprocess
.PIPE
, close_fds
=False)
1247 utils
.enable_subprocess_signal_forwarding(ps
, signal
.SIGINT
)
1248 output
= subprocess
.check_output(('grep', '00:00:00:00:00:00'), stdin
=ps
.stdout
)
1250 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1252 ppat
= re
.compile('\s+dst\s+(\d+.\d+.\d+.\d+)\s+')
1253 for l
in output
.split('\n'):
1255 if m
and m
.group(1) != svcnodeip
:
1256 cur_peers
.append(m
.group(1))
1258 self
.logger
.warn('error parsing ip link output')
1259 except subprocess
.CalledProcessError
as e
:
1260 if e
.returncode
!= 1:
1261 self
.logger
.error(str(e
))
1263 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1267 def tunnel_create(self
, tunnelname
, mode
, attrs
={}):
1268 """ generic link_create function """
1269 if self
.link_exists(tunnelname
):
1276 if mode
in ['gretap']:
1277 cmd
+= 'link add %s type %s' % (tunnelname
, mode
)
1279 cmd
+= 'tunnel add %s mode %s' % (tunnelname
, mode
)
1282 for k
, v
in attrs
.iteritems():
1286 if self
.ipbatch
and not self
.ipbatch_pause
:
1287 self
.add_to_batch(cmd
)
1289 utils
.exec_command('ip %s' % cmd
)
1290 self
._cache
_update
([tunnelname
], {})
1292 def tunnel_change(self
, tunnelname
, attrs
={}):
1293 """ tunnel change function """
1294 if not self
.link_exists(tunnelname
):
1296 cmd
= 'tunnel change'
1297 cmd
+= ' %s' %(tunnelname)
1299 for k
, v
in attrs
.iteritems():
1303 if self
.ipbatch
and not self
.ipbatch_pause
:
1304 self
.add_to_batch(cmd
)
1306 utils
.exec_command('ip %s' % cmd
)
1308 def link_create_vxlan(self
, name
, vxlanid
,
1316 if svcnodeip
and remoteips
:
1317 raise Exception("svcnodeip and remoteip is mutually exclusive")
1320 args
+= ' remote %s' % svcnodeip
1322 args
+= ' ageing %s' % ageing
1323 if learning
== 'off':
1324 args
+= ' nolearning'
1326 args
+= ' ttl %s' % ttl
1328 if self
.link_exists(name
):
1329 cmd
= 'link set dev %s type vxlan dstport %d' % (name
, LinkUtils
.VXLAN_UDP_PORT
)
1330 vxlanattrs
= self
.get_vxlandev_attrs(name
)
1331 # on ifreload do not overwrite anycast_ip to individual ip if clagd
1334 running_localtunnelip
= vxlanattrs
.get('local')
1335 if anycastip
and running_localtunnelip
and anycastip
== running_localtunnelip
:
1336 localtunnelip
= running_localtunnelip
1337 running_svcnode
= vxlanattrs
.get('svcnode')
1338 if running_svcnode
and not svcnodeip
:
1341 cmd
= 'link add dev %s type vxlan id %s dstport %d' % (name
, vxlanid
, LinkUtils
.VXLAN_UDP_PORT
)
1344 args
+= ' local %s' % localtunnelip
1347 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1348 self
.add_to_batch(cmd
)
1350 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1352 # XXX: update linkinfo correctly
1353 #self._cache_update([name], {})
1356 def link_exists(ifacename
):
1357 if ifupdownflags
.flags
.DRYRUN
:
1359 return os
.path
.exists('/sys/class/net/%s' % ifacename
)
1362 def link_exists_nodryrun(ifname
):
1363 return os
.path
.exists('/sys/class/net/%s' % ifname
)
1365 def link_get_ifindex(self
, ifacename
):
1366 if ifupdownflags
.flags
.DRYRUN
:
1368 return self
.read_file_oneline('/sys/class/net/%s/ifindex' % ifacename
)
1370 def is_vlan_device_by_name(self
, ifacename
):
1371 if re
.search(r
'\.', ifacename
):
1376 def link_add_macvlan(ifname
, macvlan_ifacename
, mode
):
1377 utils
.exec_commandl(['ip', 'link', 'add', 'link', ifname
, 'name', macvlan_ifacename
, 'type', 'macvlan', 'mode', mode
])
1380 def route_add(route
):
1381 utils
.exec_command('%s route add %s' % (utils
.ip_cmd
,
1385 def route6_add(route
):
1386 utils
.exec_command('%s -6 route add %s' % (utils
.ip_cmd
,
1389 def get_vlandev_attrs(self
, ifacename
):
1390 return (self
._cache
_get
('link', [ifacename
, 'link']),
1391 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlanid']),
1392 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol']))
1394 def get_vlan_protocol(self
, ifacename
):
1395 return self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol'])
1397 def get_vxlandev_attrs(self
, ifacename
):
1398 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1400 def get_vxlandev_learning(self
, ifacename
):
1401 return self
._cache
_get
('link', [ifacename
, 'linkinfo', Link
.IFLA_VXLAN_LEARNING
])
1403 def set_vxlandev_learning(self
, ifacename
, learn
):
1405 utils
.exec_command('%s link set dev %s type vxlan learning' %
1406 (utils
.ip_cmd
, ifacename
))
1407 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'on')
1409 utils
.exec_command('%s link set dev %s type vxlan nolearning' %
1410 (utils
.ip_cmd
, ifacename
))
1411 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'off')
1413 def link_get_linkinfo_attrs(self
, ifacename
):
1414 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1416 def link_get_mtu(self
, ifacename
, refresh
=False):
1417 return self
._cache
_get
('link', [ifacename
, 'mtu'], refresh
=refresh
)
1419 def link_get_mtu_sysfs(self
, ifacename
):
1420 return self
.read_file_oneline('/sys/class/net/%s/mtu'
1423 def link_get_kind(self
, ifacename
):
1424 return self
._cache
_get
('link', [ifacename
, 'kind'])
1426 def link_get_slave_kind(self
, ifacename
):
1427 return self
._cache
_get
('link', [ifacename
, 'slave_kind'])
1429 def link_get_hwaddress(self
, ifacename
):
1430 address
= self
._cache
_get
('link', [ifacename
, 'hwaddress'])
1431 # newly created logical interface addresses dont end up in the cache
1432 # read hwaddress from sysfs file for these interfaces
1434 address
= self
.read_file_oneline('/sys/class/net/%s/address'
1438 def link_create(self
, ifacename
, t
, attrs
={}):
1439 """ generic link_create function """
1440 if self
.link_exists(ifacename
):
1443 cmd
+= ' name %s type %s' % (ifacename
, t
)
1445 for k
, v
in attrs
.iteritems():
1449 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1450 self
.add_to_batch(cmd
)
1452 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1453 self
._cache
_update
([ifacename
], {})
1455 def link_delete(self
, ifacename
):
1456 if not self
.link_exists(ifacename
):
1458 cmd
= 'link del %s' % ifacename
1459 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1460 self
.add_to_batch(cmd
)
1462 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1463 self
._cache
_invalidate
()
1465 def link_get_master(self
, ifacename
):
1466 sysfs_master_path
= '/sys/class/net/%s/master' % ifacename
1467 if os
.path
.exists(sysfs_master_path
):
1468 link_path
= os
.readlink(sysfs_master_path
)
1470 return os
.path
.basename(link_path
)
1474 return self
._cache
_get
('link', [ifacename
, 'master'])
1476 def get_brport_peer_link(self
, bridgename
):
1478 return self
._cache
_get
('link', [bridgename
, 'info_slave_data', Link
.IFLA_BRPORT_PEER_LINK
])
1483 def bridge_port_vids_add(bridgeportname
, vids
):
1484 [utils
.exec_command('%s vlan add vid %s dev %s' %
1486 v
, bridgeportname
)) for v
in vids
]
1489 def bridge_port_vids_del(bridgeportname
, vids
):
1492 [utils
.exec_command('%s vlan del vid %s dev %s' %
1494 v
, bridgeportname
)) for v
in vids
]
1497 def bridge_port_vids_flush(bridgeportname
, vid
):
1498 utils
.exec_command('%s vlan del vid %s dev %s' %
1500 vid
, bridgeportname
))
1503 def bridge_port_vids_get(bridgeportname
):
1504 bridgeout
= utils
.exec_command('%s vlan show dev %s' %
1509 brvlanlines
= bridgeout
.readlines()[2:]
1510 vids
= [l
.strip() for l
in brvlanlines
]
1511 return [v
for v
in vids
if v
]
1514 def bridge_port_vids_get_all():
1516 bridgeout
= utils
.exec_command('%s -c vlan show'
1520 brvlanlines
= bridgeout
.splitlines()
1522 for l
in brvlanlines
[1:]:
1523 if l
and not l
.startswith(' ') and not l
.startswith('\t'):
1525 brportname
= attrs
[0].strip()
1526 brvlaninfo
[brportname
] = {'pvid': None, 'vlan': []}
1527 l
= ' '.join(attrs
[1:])
1528 if not brportname
or not l
:
1532 brvlaninfo
[brportname
]['pvid'] = l
.split()[0]
1533 elif 'Egress Untagged' not in l
:
1534 brvlaninfo
[brportname
]['vlan'].append(l
)
1537 def bridge_port_vids_get_all_json(self
):
1538 if not self
.supported_command
['%s -c -json vlan show'
1539 % utils
.bridge_cmd
]:
1543 bridgeout
= utils
.exec_command('%s -c -json vlan show'
1546 self
.supported_command
['%s -c -json vlan show'
1547 % utils
.bridge_cmd
] = False
1548 self
.logger
.info('%s -c -json vlan show: skipping unsupported command'
1551 return self
.get_bridge_vlan_nojson()
1552 except Exception as e
:
1553 self
.logger
.info('bridge: get_bridge_vlan_nojson: %s' % str(e
))
1556 if not bridgeout
: return brvlaninfo
1558 vlan_json
= json
.loads(bridgeout
, encoding
="utf-8")
1559 except Exception, e
:
1560 self
.logger
.info('json loads failed with (%s)' % str(e
))
1564 if isinstance(vlan_json
, list):
1565 # newer iproute2 version changed the bridge vlan show output
1566 # ifupdown2 relies on the previous format, we have the convert
1567 # data into old format
1568 bridge_port_vids
= dict()
1570 for intf
in vlan_json
:
1571 bridge_port_vids
[intf
["ifname"]] = intf
["vlans"]
1573 return bridge_port_vids
1575 # older iproute2 version have different ways to dump vlans
1576 # ifupdown2 prefers the following syntax:
1580 # "flags": ["PVID", "Egress Untagged"]
1585 # "flags": ["PVID", "Egress Untagged"]
1589 except Exception as e
:
1590 self
.logger
.debug("bridge vlan show: Unknown json output: %s" % str(e
))
1594 def get_bridge_vlan_nojson():
1596 bridgeout
= utils
.exec_commandl([utils
.bridge_cmd
, '-c', 'vlan', 'show'])
1598 output
= [line
.split('\n') for line
in bridgeout
.split('\n\n')]
1599 output
[0] = output
[0][1:]
1607 prefix
, vlan
= entry
.split('\t')
1609 current_swp
= prefix
1610 vlan_json
[prefix
] = []
1614 v
['vlan'] = int(vlan
)
1618 start
, end
= vlan
.split('-')
1620 end
= end
[0:end
.index(' ')]
1621 v
['vlan'] = int(start
)
1622 v
['vlanEnd'] = int(end
)
1624 v
['vlan'] = int(vlan
[0:vlan
.index(' ')])
1627 flags
.append('PVID')
1628 if 'Egress Untagged' in vlan
:
1629 flags
.append('Egress Untagged')
1633 vlan_json
[current_swp
].append(v
)
1636 def bridge_vlan_cache_get(self
, ifacename
, refresh
=False):
1637 if not self
.bridge_vlan_cache_fill_done
or refresh
:
1638 self
.bridge_vlan_cache
= self
.bridge_port_vids_get_all_json()
1639 self
.bridge_vlan_cache_fill_done
= True
1640 return self
.bridge_vlan_cache
.get(ifacename
, {})
1642 def bridge_vlan_get_pvid(self
, ifacename
, refresh
=False):
1645 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1646 v
= vinfo
.get('vlan')
1647 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1652 def bridge_vlan_get_vids(self
, ifacename
, refresh
=False):
1655 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1656 v
= vinfo
.get('vlan')
1657 ispvid
= True if 'PVID' in vinfo
.get('flags', []) else False
1659 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1662 vEnd
= vinfo
.get('vlanEnd')
1664 vids
.extend(range(v
, vEnd
+ 1))
1669 def bridge_vlan_get_vids_n_pvid(self
, ifacename
, refresh
=False):
1673 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1674 v
= vinfo
.get('vlan')
1675 ispvid
= True if 'PVID' in vinfo
.get('flags', []) else False
1677 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1678 vEnd
= vinfo
.get('vlanEnd')
1680 vids
.extend(range(v
, vEnd
+ 1))
1685 def bridge_port_pvid_add(self
, bridgeportname
, pvid
):
1686 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1687 self
.add_to_batch('vlan add vid %s untagged pvid dev %s' %
1688 (pvid
, bridgeportname
))
1690 utils
.exec_command('%s vlan add vid %s untagged pvid dev %s' %
1692 pvid
, bridgeportname
))
1694 def bridge_port_pvid_del(self
, bridgeportname
, pvid
):
1695 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1696 self
.add_to_batch('vlan del vid %s untagged pvid dev %s' %
1697 (pvid
, bridgeportname
))
1699 utils
.exec_command('%s vlan del vid %s untagged pvid dev %s' %
1701 pvid
, bridgeportname
))
1703 def bridge_port_pvids_get(self
, bridgeportname
):
1704 return self
.read_file_oneline('/sys/class/net/%s/brport/pvid'
1707 def bridge_vids_add(self
, bridgeportname
, vids
, bridge
=True):
1708 target
= 'self' if bridge
else ''
1709 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1710 [self
.add_to_batch('vlan add vid %s dev %s %s' %
1711 (v
, bridgeportname
, target
)) for v
in vids
]
1713 [utils
.exec_command('%s vlan add vid %s dev %s %s' %
1715 v
, bridgeportname
, target
)) for v
in vids
]
1717 def bridge_vids_del(self
, bridgeportname
, vids
, bridge
=True):
1718 target
= 'self' if bridge
else ''
1719 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1720 [self
.add_to_batch('vlan del vid %s dev %s %s' %
1721 (v
, bridgeportname
, target
)) for v
in vids
]
1723 [utils
.exec_command('%s vlan del vid %s dev %s %s' %
1725 v
, bridgeportname
, target
)) for v
in vids
]
1728 def bridge_fdb_add(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1729 target
= 'self' if bridge
else ''
1732 vlan_str
= 'vlan %s ' % vlan
1736 dst_str
= 'dst %s ' % remote
1738 utils
.exec_command('%s fdb replace %s dev %s %s %s %s' %
1740 address
, dev
, vlan_str
, target
, dst_str
))
1743 def bridge_fdb_append(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1744 target
= 'self' if bridge
else ''
1747 vlan_str
= 'vlan %s ' % vlan
1751 dst_str
= 'dst %s ' % remote
1753 utils
.exec_command('%s fdb append %s dev %s %s %s %s' %
1755 address
, dev
, vlan_str
, target
, dst_str
))
1758 def bridge_fdb_del(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1759 target
= 'self' if bridge
else ''
1762 vlan_str
= 'vlan %s ' % vlan
1766 dst_str
= 'dst %s ' % remote
1767 utils
.exec_command('%s fdb del %s dev %s %s %s %s' %
1769 address
, dev
, vlan_str
, target
, dst_str
))
1771 def bridge_is_vlan_aware(self
, bridgename
):
1772 filename
= '/sys/class/net/%s/bridge/vlan_filtering' % bridgename
1773 if os
.path
.exists(filename
) and self
.read_file_oneline(filename
) == '1':
1778 def bridge_port_get_bridge_name(bridgeport
):
1779 filename
= '/sys/class/net/%s/brport/bridge' % bridgeport
1781 return os
.path
.basename(os
.readlink(filename
))
1786 def bridge_port_exists(bridge
, bridgeportname
):
1788 return os
.path
.exists('/sys/class/net/%s/brif/%s'
1789 % (bridge
, bridgeportname
))
1793 def bridge_fdb_show_dev(self
, dev
):
1796 output
= utils
.exec_command('%s fdb show dev %s'
1797 % (utils
.bridge_cmd
, dev
))
1799 for fdb_entry
in output
.splitlines():
1801 entries
= fdb_entry
.split()
1802 fdbs
.setdefault(entries
[2], []).append(entries
[0])
1804 self
.logger
.debug('%s: invalid fdb line \'%s\''
1811 def is_bridge(bridge
):
1812 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
1814 def is_link_up(self
, ifacename
):
1817 flags
= self
.read_file_oneline('/sys/class/net/%s/flags' % ifacename
)
1818 iflags
= int(flags
, 16)
1825 def ip_route_get_dev(self
, prefix
, vrf_master
=None):
1828 cmd
= '%s route get %s vrf %s' % (utils
.ip_cmd
, prefix
, vrf_master
)
1830 cmd
= '%s route get %s' % (utils
.ip_cmd
, prefix
)
1832 output
= utils
.exec_command(cmd
)
1834 rline
= output
.splitlines()[0]
1836 rattrs
= rline
.split()
1837 return rattrs
[rattrs
.index('dev') + 1]
1838 except Exception, e
:
1839 self
.logger
.debug('ip_route_get_dev: failed .. %s' % str(e
))
1843 def link_get_lowers(ifacename
):
1845 lowers
= glob
.glob("/sys/class/net/%s/lower_*" % ifacename
)
1848 return [os
.path
.basename(l
)[6:] for l
in lowers
]
1853 def link_get_uppers(ifacename
):
1855 uppers
= glob
.glob("/sys/class/net/%s/upper_*" % ifacename
)
1858 return [os
.path
.basename(u
)[6:] for u
in uppers
]
1862 def link_get_vrfs(self
):
1863 if not LinkUtils
._CACHE
_FILL
_DONE
:
1865 return linkCache
.vrfs
1868 def cache_get_info_slave(attrlist
):
1870 return linkCache
.get_attr(attrlist
)
1874 def get_brport_learning(self
, ifacename
):
1875 learn
= self
.read_file_oneline('/sys/class/net/%s/brport/learning'
1877 if learn
and learn
== '1':
1882 def get_brport_learning_bool(self
, ifacename
):
1883 return utils
.get_boolean_from_string(self
.read_file_oneline('/sys/class/net/%s/brport/learning' % ifacename
))
1885 def set_brport_learning(self
, ifacename
, learn
):
1887 return self
.write_file('/sys/class/net/%s/brport/learning'
1890 return self
.write_file('/sys/class/net/%s/brport/learning'
1893 #################################################################################
1894 ################################### BOND UTILS ##################################
1895 #################################################################################
1897 def _link_cache_get(self
, attrlist
, refresh
=False):
1898 return self
._cache
_get
('link', attrlist
, refresh
)
1900 def cache_delete(self
, attrlist
, value
=None):
1901 return self
._cache
_delete
(attrlist
, value
)
1903 def link_cache_get(self
, attrlist
, refresh
=False):
1904 return self
._link
_cache
_get
(attrlist
, refresh
)
1906 def link_cache_check(self
, attrlist
, value
, refresh
=False):
1907 return self
._link
_cache
_check
(attrlist
, value
, refresh
)
1909 def _link_cache_check(self
, attrlist
, value
, refresh
=False):
1911 return self
._link
_cache
_get
(attrlist
, refresh
) == value
1912 except Exception, e
:
1913 self
.logger
.debug('_cache_check(%s) : [%s]'
1914 % (str(attrlist
), str(e
)))
1919 Link
.IFLA_BOND_MODE
: 'mode',
1920 Link
.IFLA_BOND_MIIMON
: 'miimon',
1921 Link
.IFLA_BOND_USE_CARRIER
: 'use_carrier',
1922 Link
.IFLA_BOND_AD_LACP_RATE
: 'lacp_rate',
1923 Link
.IFLA_BOND_XMIT_HASH_POLICY
: 'xmit_hash_policy',
1924 Link
.IFLA_BOND_MIN_LINKS
: 'min_links',
1925 Link
.IFLA_BOND_NUM_PEER_NOTIF
: 'num_grat_arp',
1926 Link
.IFLA_BOND_AD_ACTOR_SYSTEM
: 'ad_actor_system',
1927 Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
: 'ad_actor_sys_prio',
1928 Link
.IFLA_BOND_AD_LACP_BYPASS
: 'lacp_bypass',
1929 Link
.IFLA_BOND_UPDELAY
: 'updelay',
1930 Link
.IFLA_BOND_DOWNDELAY
: 'downdelay',
1933 def bond_set_attrs_nl(self
, bondname
, ifla_info_data
):
1934 bond_attr_name
= 'None' # for log purpose (in case an exception raised)
1935 for nl_attr
, value
in ifla_info_data
.items():
1937 bond_attr_name
= self
.bondcmd_attrmap
[nl_attr
]
1938 file_path
= '/sys/class/net/%s/bonding/%s' % (bondname
, bond_attr_name
)
1939 if os
.path
.exists(file_path
):
1940 self
.write_file(file_path
, str(value
))
1941 except Exception as e
:
1942 exception_str
= '%s: %s %s: %s' % (bondname
, bond_attr_name
, value
, str(e
))
1943 if ifupdownflags
.flags
.FORCE
:
1944 self
.logger
.warning(exception_str
)
1946 self
.logger
.debug(exception_str
)
1948 def bond_set_attrs(self
, bondname
, attrdict
, prehook
):
1949 for attrname
, attrval
in attrdict
.items():
1950 if (self
._link
_cache
_check
([bondname
, 'linkinfo',
1951 attrname
], attrval
)):
1953 if (attrname
== 'mode'
1954 or attrname
== 'xmit_hash_policy'
1955 or attrname
== 'lacp_rate' or attrname
== 'min_links'):
1959 if ((attrname
not in ['lacp_rate',
1961 self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'], '802.3ad',
1963 self
.write_file('/sys/class/net/%s/bonding/%s'
1964 % (bondname
, attrname
), attrval
)
1965 except Exception, e
:
1966 if ifupdownflags
.flags
.FORCE
:
1967 self
.logger
.warn(str(e
))
1972 def bond_set_use_carrier(self
, bondname
, use_carrier
):
1973 if not use_carrier
or (use_carrier
!= '0' and use_carrier
!= '1'):
1975 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'use_carrier'],
1978 self
.write_file('/sys/class/net/%s' % bondname
+
1979 '/bonding/use_carrier', use_carrier
)
1980 self
._cache
_update
([bondname
, 'linkinfo',
1981 'use_carrier'], use_carrier
)
1983 def bond_get_use_carrier(self
, bondname
):
1984 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'use_carrier'])
1986 def bond_get_use_carrier_nl(self
, bondname
):
1987 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_USE_CARRIER
])
1989 def bond_set_xmit_hash_policy(self
, bondname
, hash_policy
, prehook
=None):
1990 valid_values
= ['layer2', 'layer3+4', 'layer2+3']
1993 if hash_policy
not in valid_values
:
1994 raise Exception('invalid hash policy value %s' % hash_policy
)
1995 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'xmit_hash_policy'],
2000 self
.write_file('/sys/class/net/%s' % bondname
+
2001 '/bonding/xmit_hash_policy', hash_policy
)
2002 self
._cache
_update
([bondname
, 'linkinfo', 'xmit_hash_policy'],
2005 def bond_get_xmit_hash_policy(self
, bondname
):
2006 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'xmit_hash_policy'])
2008 def bond_get_xmit_hash_policy_nl(self
, bondname
):
2009 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_XMIT_HASH_POLICY
])
2011 def bond_set_miimon(self
, bondname
, miimon
):
2012 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'miimon'],
2015 self
.write_file('/sys/class/net/%s' % bondname
+
2016 '/bonding/miimon', miimon
)
2017 self
._cache
_update
([bondname
, 'linkinfo', 'miimon'], miimon
)
2019 def bond_get_miimon(self
, bondname
):
2020 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'miimon'])
2022 def bond_get_miimon_nl(self
, bondname
):
2023 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIIMON
])
2025 def bond_set_mode(self
, bondname
, mode
, prehook
=None):
2026 valid_modes
= ['balance-rr', 'active-backup', 'balance-xor',
2027 'broadcast', '802.3ad', 'balance-tlb', 'balance-alb']
2030 if mode
not in valid_modes
:
2031 raise Exception('invalid mode %s' % mode
)
2032 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'],
2037 self
.write_file('/sys/class/net/%s' % bondname
+ '/bonding/mode', mode
)
2038 self
._cache
_update
([bondname
, 'linkinfo', 'mode'], mode
)
2040 def bond_get_mode(self
, bondname
):
2041 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'mode'])
2043 def bond_get_mode_nl(self
, bondname
):
2044 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MODE
])
2046 def bond_set_lacp_rate(self
, bondname
, lacp_rate
, prehook
=None, posthook
=None):
2047 if not lacp_rate
or (lacp_rate
!= '0' and lacp_rate
!= '1'):
2049 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_rate'],
2055 self
.write_file('/sys/class/net/%s' % bondname
+
2056 '/bonding/lacp_rate', lacp_rate
)
2062 self
._cache
_update
([bondname
, 'linkinfo',
2063 'lacp_rate'], lacp_rate
)
2065 def bond_get_lacp_rate(self
, bondname
):
2066 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_rate'])
2068 def bond_get_lacp_rate_nl(self
, bondname
):
2069 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_RATE
])
2071 def bond_set_lacp_bypass_allow(self
, bondname
, allow
, prehook
=None, posthook
=None):
2072 if self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_bypass'], allow
):
2077 self
.write_file('/sys/class/net/%s' % bondname
+
2078 '/bonding/lacp_bypass', allow
)
2084 self
._cache
_update
([bondname
, 'linkinfo',
2085 'lacp_bypass'], allow
)
2087 def bond_get_lacp_bypass_allow(self
, bondname
):
2088 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_bypass'])
2090 def bond_get_lacp_bypass_allow_nl(self
, bondname
):
2091 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_BYPASS
])
2093 def bond_set_min_links(self
, bondname
, min_links
, prehook
=None):
2094 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'min_links'],
2099 self
.write_file('/sys/class/net/%s/bonding/min_links' % bondname
,
2101 self
._cache
_update
([bondname
, 'linkinfo', 'min_links'], min_links
)
2103 def bond_get_min_links(self
, bondname
):
2104 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'min_links'])
2106 def get_min_links_nl(self
, bondname
):
2107 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIN_LINKS
])
2109 def bond_get_ad_actor_system(self
, bondname
):
2110 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_system'])
2112 def bond_get_ad_actor_system_nl(self
, bondname
):
2113 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYSTEM
])
2115 def bond_get_ad_actor_sys_prio(self
, bondname
):
2116 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_sys_prio'])
2118 def bond_get_ad_actor_sys_prio_nl(self
, bondname
):
2119 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
])
2121 def bond_get_num_unsol_na(self
, bondname
):
2122 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_unsol_na'])
2124 def bond_get_num_unsol_na_nl(self
, bondname
):
2125 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2127 def bond_get_num_grat_arp(self
, bondname
):
2128 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_grat_arp'])
2130 def bond_get_num_grat_arp_nl(self
, bondname
):
2131 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2133 def bond_get_updelay(self
, bondname
):
2134 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'updelay'])
2136 def bond_get_updelay_nl(self
, bondname
):
2137 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_UPDELAY
])
2139 def bond_get_downdelay(self
, bondname
):
2140 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'downdelay'])
2142 def bond_get_downdelay_nl(self
, bondname
):
2143 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_DOWNDELAY
])
2145 def bond_enslave_slave(self
, bondname
, slave
, prehook
=None, posthook
=None):
2146 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2147 if slaves
and slave
in slaves
:
2151 self
.write_file('/sys/class/net/%s' % bondname
+
2152 '/bonding/slaves', '+' + slave
)
2155 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slave
)
2157 def bond_remove_slave(self
, bondname
, slave
):
2158 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2159 if not slaves
or slave
not in slaves
:
2161 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2163 if not os
.path
.exists(sysfs_bond_path
):
2165 self
.write_file(sysfs_bond_path
, '-' + slave
)
2166 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'], slave
)
2168 def bond_remove_slaves_all(self
, bondname
):
2169 if not self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves']):
2172 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2175 with
open(sysfs_bond_path
, 'r') as f
:
2176 slaves
= f
.readline().strip().split()
2178 raise Exception('error reading slaves of bond %s (%s)' % (bondname
, str(e
)))
2179 for slave
in slaves
:
2180 self
.link_down(slave
)
2182 self
.bond_remove_slave(bondname
, slave
)
2183 except Exception, e
:
2184 if not ifupdownflags
.flags
.FORCE
:
2185 raise Exception('error removing slave %s from bond %s (%s)' % (slave
, bondname
, str(e
)))
2188 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'])
2191 def bond_load_bonding_module():
2192 return utils
.exec_command('%s -q bonding' % utils
.modprobe_cmd
)
2194 def create_bond(self
, bondname
):
2195 if self
.bond_exists(bondname
):
2197 # load_bonding_module() has already been run
2198 self
.write_file('/sys/class/net/bonding_masters', '+' + bondname
)
2199 self
._cache
_update
([bondname
], {})
2201 def delete_bond(self
, bondname
):
2202 if not os
.path
.exists('/sys/class/net/%s' % bondname
):
2204 self
.write_file('/sys/class/net/bonding_masters', '-' + bondname
)
2205 self
._cache
_delete
([bondname
])
2207 def bond_get_slaves(self
, bondname
):
2208 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2211 slavefile
= '/sys/class/net/%s/bonding/slaves' % bondname
2212 if os
.path
.exists(slavefile
):
2213 buf
= self
.read_file_oneline(slavefile
)
2215 slaves
= buf
.split()
2218 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slaves
)
2221 def bond_slave_exists(self
, bond
, slave
):
2222 slaves
= self
.bond_get_slaves(bond
)
2225 return slave
in slaves
2228 def bond_exists(bondname
):
2229 return os
.path
.exists('/sys/class/net/%s/bonding' % bondname
)
2231 #################################################################################
2232 ################################## BRIDGE UTILS #################################
2233 #################################################################################
2235 def create_bridge(self
, bridgename
):
2236 if not LinkUtils
.bridge_utils_is_installed
:
2238 if self
.bridge_exists(bridgename
):
2240 utils
.exec_command('%s addbr %s' % (utils
.brctl_cmd
, bridgename
))
2241 self
._cache
_update
([bridgename
], {})
2243 def delete_bridge(self
, bridgename
):
2244 if not LinkUtils
.bridge_utils_is_installed
:
2246 if not self
.bridge_exists(bridgename
):
2248 utils
.exec_command('%s delbr %s' % (utils
.brctl_cmd
, bridgename
))
2249 self
._cache
_invalidate
()
2251 def add_bridge_port(self
, bridgename
, bridgeportname
):
2252 """ Add port to bridge """
2253 if not LinkUtils
.bridge_utils_is_installed
:
2255 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2256 if ports
and ports
.get(bridgeportname
):
2258 utils
.exec_command('%s addif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2259 self
._cache
_update
([bridgename
, 'linkinfo', 'ports', bridgeportname
], {})
2261 def delete_bridge_port(self
, bridgename
, bridgeportname
):
2262 """ Delete port from bridge """
2263 if not LinkUtils
.bridge_utils_is_installed
:
2265 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2266 if not ports
or not ports
.get(bridgeportname
):
2268 utils
.exec_command('%s delif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2269 self
._cache
_delete
([bridgename
, 'linkinfo', 'ports', 'bridgeportname'])
2271 def set_bridgeport_attrs(self
, bridgename
, bridgeportname
, attrdict
):
2272 portattrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports', bridgeportname
])
2273 if portattrs
== None:
2275 for k
, v
in attrdict
.iteritems():
2276 if ifupdownflags
.flags
.CACHE
:
2277 curval
= portattrs
.get(k
)
2278 if curval
and curval
== v
:
2280 if k
== 'unicast-flood':
2281 self
.write_file('/sys/class/net/%s/brport/unicast_flood' % bridgeportname
, v
)
2282 elif k
== 'multicast-flood':
2283 self
.write_file('/sys/class/net/%s/brport/multicast_flood' % bridgeportname
, v
)
2284 elif k
== 'learning':
2285 self
.write_file('/sys/class/net/%s/brport/learning' % bridgeportname
, v
)
2286 elif k
== 'arp-nd-suppress':
2287 self
.write_file('/sys/class/net/%s/brport/neigh_suppress' % bridgeportname
, v
)
2289 if not LinkUtils
.bridge_utils_is_installed
:
2291 utils
.exec_command('%s set%s %s %s %s' % (utils
.brctl_cmd
, k
, bridgename
, bridgeportname
, v
))
2293 def set_bridgeport_attr(self
, bridgename
, bridgeportname
,
2295 if not LinkUtils
.bridge_utils_is_installed
:
2297 if self
._link
_cache
_check
([bridgename
, 'linkinfo', 'ports', bridgeportname
, attrname
], attrval
):
2299 utils
.exec_command('%s set%s %s %s %s' %
2306 def set_bridge_attrs(self
, bridgename
, attrdict
):
2307 for k
, v
in attrdict
.iteritems():
2310 if self
._link
_cache
_check
([bridgename
, 'linkinfo', k
], v
):
2313 if k
== 'igmp-version':
2314 self
.write_file('/sys/class/net/%s/bridge/'
2315 'multicast_igmp_version' % bridgename
, v
)
2316 elif k
== 'mld-version':
2317 self
.write_file('/sys/class/net/%s/bridge/'
2318 'multicast_mld_version' % bridgename
, v
)
2319 elif k
== 'vlan-protocol':
2320 self
.write_file('/sys/class/net/%s/bridge/'
2321 'vlan_protocol' % bridgename
,
2322 VlanProtocols
.ETHERTYPES_TO_ID
.get(v
.upper(),
2324 elif k
== 'vlan-stats':
2325 self
.write_file('/sys/class/net/%s/bridge/'
2326 'vlan_stats_enabled' % bridgename
, v
)
2327 elif k
== 'mcstats':
2328 self
.write_file('/sys/class/net/%s/bridge/'
2329 'multicast_stats_enabled' % bridgename
, v
)
2331 if not LinkUtils
.bridge_utils_is_installed
:
2333 cmd
= ('%s set%s %s %s' %
2334 (utils
.brctl_cmd
, k
, bridgename
, v
))
2335 utils
.exec_command(cmd
)
2336 except Exception, e
:
2337 self
.logger
.warn('%s: %s' % (bridgename
, str(e
)))
2340 def set_bridge_attr(self
, bridgename
, attrname
, attrval
):
2341 if self
._link
_cache
_check
([bridgename
, 'linkinfo', attrname
], attrval
):
2343 if attrname
== 'igmp-version':
2344 self
.write_file('/sys/class/net/%s/bridge/multicast_igmp_version'
2345 % bridgename
, attrval
)
2346 elif attrname
== 'mld-version':
2347 self
.write_file('/sys/class/net/%s/bridge/multicast_mld_version'
2348 % bridgename
, attrval
)
2349 elif attrname
== 'vlan-protocol':
2350 self
.write_file('/sys/class/net/%s/bridge/vlan_protocol'
2351 % bridgename
, VlanProtocols
.ETHERTYPES_TO_ID
[attrval
.upper()])
2352 elif attrname
== 'vlan-stats':
2353 self
.write_file('/sys/class/net/%s/bridge/vlan_stats_enabled'
2354 % bridgename
, attrval
)
2355 elif attrname
== 'mcstats':
2356 self
.write_file('/sys/class/net/%s/bridge/multicast_stats_enabled'
2357 % bridgename
, attrval
)
2359 if not LinkUtils
.bridge_utils_is_installed
:
2361 cmd
= '%s set%s %s %s' % (utils
.brctl_cmd
,
2362 attrname
, bridgename
, attrval
)
2363 utils
.exec_command(cmd
)
2365 def get_bridge_attrs(self
, bridgename
):
2366 attrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo'])
2368 for key
, value
in attrs
.items():
2369 if type(key
) == str:
2370 no_ints_attrs
[key
] = value
2371 return no_ints_attrs
2373 def get_bridgeport_attrs(self
, bridgename
, bridgeportname
):
2374 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2377 def get_bridgeport_attr(self
, bridgename
, bridgeportname
, attrname
):
2378 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2379 bridgeportname
, attrname
])
2382 def bridge_set_stp(bridge
, stp_state
):
2383 if not LinkUtils
.bridge_utils_is_installed
:
2385 utils
.exec_command('%s stp %s %s' % (utils
.brctl_cmd
, bridge
, stp_state
))
2387 def bridge_get_stp(self
, bridge
):
2388 sysfs_stpstate
= '/sys/class/net/%s/bridge/stp_state' % bridge
2389 if not os
.path
.exists(sysfs_stpstate
):
2391 stpstate
= self
.read_file_oneline(sysfs_stpstate
)
2395 if int(stpstate
) > 0:
2397 elif int(stpstate
) == 0:
2403 def _conv_value_to_user(s
):
2410 def read_value_from_sysfs(self
, filename
, preprocess_func
):
2411 value
= self
.read_file_oneline(filename
)
2414 return preprocess_func(value
)
2417 def bridge_set_ageing(bridge
, ageing
):
2418 if not LinkUtils
.bridge_utils_is_installed
:
2420 utils
.exec_command('%s setageing %s %s' % (utils
.brctl_cmd
, bridge
, ageing
))
2422 def bridge_get_ageing(self
, bridge
):
2423 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/ageing_time'
2424 % bridge
, self
._conv
_value
_to
_user
)
2427 def set_bridgeprio(bridge
, prio
):
2428 if not LinkUtils
.bridge_utils_is_installed
:
2430 utils
.exec_command('%s setbridgeprio %s %s' % (utils
.brctl_cmd
, bridge
, prio
))
2432 def get_bridgeprio(self
, bridge
):
2433 return self
.read_file_oneline(
2434 '/sys/class/net/%s/bridge/priority' % bridge
)
2437 def bridge_set_fd(bridge
, fd
):
2438 if not LinkUtils
.bridge_utils_is_installed
:
2440 utils
.exec_command('%s setfd %s %s' % (utils
.brctl_cmd
, bridge
, fd
))
2442 def bridge_get_fd(self
, bridge
):
2443 return self
.read_value_from_sysfs(
2444 '/sys/class/net/%s/bridge/forward_delay'
2445 % bridge
, self
._conv
_value
_to
_user
)
2447 def bridge_set_gcint(self
, bridge
, gcint
):
2448 raise Exception('set_gcint not implemented')
2451 def bridge_set_hello(bridge
, hello
):
2452 if not LinkUtils
.bridge_utils_is_installed
:
2454 utils
.exec_command('%s sethello %s %s' % (utils
.brctl_cmd
, bridge
, hello
))
2456 def bridge_get_hello(self
, bridge
):
2457 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/hello_time'
2458 % bridge
, self
._conv
_value
_to
_user
)
2461 def bridge_set_maxage(bridge
, maxage
):
2462 if not LinkUtils
.bridge_utils_is_installed
:
2464 utils
.exec_command('%s setmaxage %s %s' % (utils
.brctl_cmd
, bridge
, maxage
))
2466 def bridge_get_maxage(self
, bridge
):
2467 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/max_age'
2468 % bridge
, self
._conv
_value
_to
_user
)
2471 def bridge_set_pathcost(bridge
, port
, pathcost
):
2472 if not LinkUtils
.bridge_utils_is_installed
:
2474 utils
.exec_command('%s setpathcost %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, pathcost
))
2476 def bridge_get_pathcost(self
, bridge
, port
):
2477 return self
.read_file_oneline('/sys/class/net/%s/brport/path_cost'
2481 def bridge_set_portprio(bridge
, port
, prio
):
2482 if not LinkUtils
.bridge_utils_is_installed
:
2484 utils
.exec_command('%s setportprio %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, prio
))
2486 def bridge_get_portprio(self
, bridge
, port
):
2487 return self
.read_file_oneline('/sys/class/net/%s/brport/priority'
2491 def bridge_set_hashmax(bridge
, hashmax
):
2492 if not LinkUtils
.bridge_utils_is_installed
:
2494 utils
.exec_command('%s sethashmax %s %s' % (utils
.brctl_cmd
, bridge
, hashmax
))
2496 def bridge_get_hashmax(self
, bridge
):
2497 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_max'
2501 def bridge_set_hashel(bridge
, hashel
):
2502 if not LinkUtils
.bridge_utils_is_installed
:
2504 utils
.exec_command('%s sethashel %s %s' % (utils
.brctl_cmd
, bridge
, hashel
))
2506 def bridge_get_hashel(self
, bridge
):
2507 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_elasticity'
2511 def bridge_set_mclmc(bridge
, mclmc
):
2512 if not LinkUtils
.bridge_utils_is_installed
:
2514 utils
.exec_command('%s setmclmc %s %s' % (utils
.brctl_cmd
, bridge
, mclmc
))
2516 def bridge_get_mclmc(self
, bridge
):
2517 return self
.read_file_oneline(
2518 '/sys/class/net/%s/bridge/multicast_last_member_count'
2522 def bridge_set_mcrouter(bridge
, mcrouter
):
2523 if not LinkUtils
.bridge_utils_is_installed
:
2525 utils
.exec_command('%s setmcrouter %s %s' % (utils
.brctl_cmd
, bridge
, mcrouter
))
2527 def bridge_get_mcrouter(self
, bridge
):
2528 return self
.read_file_oneline(
2529 '/sys/class/net/%s/bridge/multicast_router' % bridge
)
2532 def bridge_set_mcsnoop(bridge
, mcsnoop
):
2533 if not LinkUtils
.bridge_utils_is_installed
:
2535 utils
.exec_command('%s setmcsnoop %s %s' % (utils
.brctl_cmd
, bridge
, mcsnoop
))
2537 def bridge_get_mcsnoop(self
, bridge
):
2538 return self
.read_file_oneline(
2539 '/sys/class/net/%s/bridge/multicast_snooping' % bridge
)
2542 def bridge_set_mcsqc(bridge
, mcsqc
):
2543 if not LinkUtils
.bridge_utils_is_installed
:
2545 utils
.exec_command('%s setmcsqc %s %s' % (utils
.brctl_cmd
, bridge
, mcsqc
))
2547 def bridge_get_mcsqc(self
, bridge
):
2548 return self
.read_file_oneline(
2549 '/sys/class/net/%s/bridge/multicast_startup_query_count'
2553 def bridge_set_mcqifaddr(bridge
, mcqifaddr
):
2554 if not LinkUtils
.bridge_utils_is_installed
:
2556 utils
.exec_command('%s setmcqifaddr %s %s' % (utils
.brctl_cmd
, bridge
, mcqifaddr
))
2558 def bridge_get_mcqifaddr(self
, bridge
):
2559 return self
.read_file_oneline(
2560 '/sys/class/net/%s/bridge/multicast_startup_query_use_ifaddr'
2564 def bridge_set_mcquerier(bridge
, mcquerier
):
2565 if not LinkUtils
.bridge_utils_is_installed
:
2567 utils
.exec_command('%s setmcquerier %s %s' % (utils
.brctl_cmd
, bridge
, mcquerier
))
2569 def bridge_get_mcquerier(self
, bridge
):
2570 return self
.read_file_oneline(
2571 '/sys/class/net/%s/bridge/multicast_querier' % bridge
)
2573 def bridge_set_mcqv4src(self
, bridge
, vlan
, mcquerier
):
2577 self
.logger
.info('%s: set mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2579 if vlan
== 0 or vlan
> 4095:
2580 self
.logger
.warn('mcqv4src vlan \'%d\' invalid range' % vlan
)
2583 ip
= mcquerier
.split('.')
2585 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2588 if not k
.isdigit() or int(k
, 10) < 0 or int(k
, 10) > 255:
2589 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2592 if not LinkUtils
.bridge_utils_is_installed
:
2595 utils
.exec_command('%s setmcqv4src %s %d %s' %
2596 (utils
.brctl_cmd
, bridge
, vlan
, mcquerier
))
2598 def bridge_del_mcqv4src(self
, bridge
, vlan
):
2599 if not LinkUtils
.bridge_utils_is_installed
:
2604 self
.logger
.info('%s: del mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2606 utils
.exec_command('%s delmcqv4src %s %d' % (utils
.brctl_cmd
, bridge
, vlan
))
2608 def bridge_get_mcqv4src(self
, bridge
, vlan
=None):
2609 if not LinkUtils
.bridge_utils_is_installed
:
2611 if not self
.supported_command
['showmcqv4src']:
2615 mcqout
= utils
.exec_command('%s showmcqv4src %s' %
2616 (utils
.brctl_cmd
, bridge
))
2617 except Exception as e
:
2619 if 'never heard' in s
:
2620 msg
= ('%s showmcqv4src: skipping unsupported command'
2622 self
.logger
.info(msg
)
2623 self
.supported_command
['showmcqv4src'] = False
2628 mcqlines
= mcqout
.splitlines()
2629 for l
in mcqlines
[1:]:
2631 k
, d
, v
= l
.split('\t')
2636 return mcqv4src
.get(vlan
)
2639 def bridge_get_mcqv4src_sysfs(self
, bridge
, vlan
=None):
2640 if not LinkUtils
.bridge_utils_is_installed
:
2642 if not self
.supported_command
['showmcqv4src']:
2644 if ifupdownflags
.flags
.PERFMODE
:
2648 filename
= '/sys/class/net/%s/bridge/multicast_v4_queriers' % bridge
2649 if os
.path
.exists(filename
):
2650 for line
in self
.read_file(filename
) or []:
2651 vlan_id
, ip
= line
.split('=')
2652 mcqv4src
[vlan_id
] = ip
.strip()
2653 except Exception as e
:
2655 msg
= ('%s showmcqv4src: skipping unsupported command'
2657 self
.logger
.info(msg
)
2658 self
.supported_command
['showmcqv4src'] = False
2661 return mcqv4src
.get(vlan
)
2665 def bridge_set_mclmi(bridge
, mclmi
):
2666 if not LinkUtils
.bridge_utils_is_installed
:
2668 utils
.exec_command('%s setmclmi %s %s' % (utils
.brctl_cmd
, bridge
, mclmi
))
2670 def bridge_get_mclmi(self
, bridge
):
2671 return self
.read_file_oneline(
2672 '/sys/class/net/%s/bridge/multicast_last_member_interval'
2676 def bridge_set_mcmi(bridge
, mcmi
):
2677 if not LinkUtils
.bridge_utils_is_installed
:
2679 utils
.exec_command('%s setmcmi %s %s' % (utils
.brctl_cmd
, bridge
, mcmi
))
2681 def bridge_get_mcmi(self
, bridge
):
2682 return self
.read_file_oneline(
2683 '/sys/class/net/%s/bridge/multicast_membership_interval'
2687 def bridge_exists(bridge
):
2688 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
2691 def is_bridge_port(ifacename
):
2692 return os
.path
.exists('/sys/class/net/%s/brport' % ifacename
)
2695 def bridge_port_exists(bridge
, bridgeportname
):
2697 return os
.path
.exists('/sys/class/net/%s/brif/%s' % (bridge
, bridgeportname
))
2702 def get_bridge_ports(bridgename
):
2704 return os
.listdir('/sys/class/net/%s/brif/' % bridgename
)
2708 def reset_addr_cache(self
, ifname
):
2710 linkCache
.links
[ifname
]['addrs'] = {}
2711 self
.logger
.debug('%s: reset address cache' % ifname
)
2715 def get_ipv6_addrgen_mode(self
, ifname
):
2717 return self
._cache
_get
('link', [ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
]
2719 # default to 0 (eui64)
2722 def ipv6_addrgen(self
, ifname
, addrgen
, link_created
):
2724 # IFLA_INET6_ADDR_GEN_MODE values:
2727 if self
._link
_cache
_get
([ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
] == addrgen
:
2728 self
.logger
.debug('%s: ipv6 addrgen already %s' % (ifname
, 'off' if addrgen
else 'on'))
2731 disabled_ipv6
= self
.read_file_oneline('/proc/sys/net/ipv6/conf/%s/disable_ipv6' % ifname
)
2732 if not disabled_ipv6
or int(disabled_ipv6
) == 1:
2733 self
.logger
.info('%s: cannot set addrgen: ipv6 is disabled on this device' % ifname
)
2736 if int(self
._link
_cache
_get
([ifname
, 'mtu'])) < 1280:
2737 self
.logger
.info('%s: ipv6 addrgen is disabled on device with MTU '
2738 'lower than 1280: cannot set addrgen %s' % (ifname
, 'off' if addrgen
else 'on'))
2740 except (KeyError, TypeError):
2741 self
.logger
.debug('%s: ipv6 addrgen probably not supported or disabled on this device' % ifname
)
2746 if not link_created
:
2747 # When setting addrgenmode it is necessary to flap the macvlan
2748 # device. After flapping the device we also need to re-add all
2749 # the user configuration. The best way to add the user config
2750 # is to flush our internal address cache
2751 self
.reset_addr_cache(ifname
)
2753 cmd
= 'link set dev %s addrgenmode %s' % (ifname
, 'none' if addrgen
else 'eui64')
2755 is_link_up
= self
.is_link_up(ifname
)
2758 self
.link_down(ifname
)
2760 if LinkUtils
.ipbatch
:
2761 self
.add_to_batch(cmd
)
2763 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
2766 self
.link_up(ifname
)