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 del_cache_entry(self
, ifname
):
705 del linkCache
.links
[ifname
]
709 def cache_get(self
, t
, attrlist
, refresh
=False):
710 return self
._cache
_get
(t
, attrlist
, refresh
)
712 def _cache_get(self
, t
, attrlist
, refresh
=False):
714 if ifupdownflags
.flags
.DRYRUN
:
716 if ifupdownflags
.flags
.CACHE
:
717 if self
._fill
_cache
():
718 # if we filled the cache, return new data
719 return linkCache
.get_attr(attrlist
)
721 return linkCache
.get_attr(attrlist
)
723 self
._link
_fill
(attrlist
[0], refresh
)
725 self
._addr
_fill
(attrlist
[0], refresh
)
727 self
._link
_fill
(attrlist
[0], refresh
)
728 self
._addr
_fill
(attrlist
[0], refresh
)
729 return linkCache
.get_attr(attrlist
)
731 self
.logger
.debug('_cache_get(%s) : [%s]' % (str(attrlist
), str(e
)))
734 def cache_check(self
, attrlist
, value
, refresh
=False):
735 return self
._cache
_check
('link', attrlist
, value
, refresh
=refresh
)
737 def _cache_check(self
, t
, attrlist
, value
, refresh
=False):
739 return self
._cache
_get
(t
, attrlist
, refresh
) == value
741 self
.logger
.debug('_cache_check(%s) : [%s]'
742 % (str(attrlist
), str(e
)))
745 def cache_update(self
, attrlist
, value
):
746 return self
._cache
_update
(attrlist
, value
)
749 def _cache_update(attrlist
, value
):
750 if ifupdownflags
.flags
.DRYRUN
:
753 if attrlist
[-1] == 'slaves':
754 linkCache
.append_to_attrlist(attrlist
, value
)
756 linkCache
.set_attr(attrlist
, value
)
761 def _cache_delete(attrlist
, value
=None):
762 if ifupdownflags
.flags
.DRYRUN
:
766 linkCache
.remove_from_attrlist(attrlist
, value
)
768 linkCache
.del_attr(attrlist
)
773 def _cache_invalidate():
774 linkCache
.invalidate()
775 LinkUtils
._CACHE
_FILL
_DONE
= False
779 LinkUtils
.ipbatcbuf
= ''
780 LinkUtils
.ipbatch
= True
781 LinkUtils
.ipbatch_pause
= False
784 def add_to_batch(cmd
):
785 LinkUtils
.ipbatchbuf
+= cmd
+ '\n'
789 LinkUtils
.ipbatch_pause
= True
793 LinkUtils
.ipbatch_pause
= False
795 def batch_commit(self
):
796 if not LinkUtils
.ipbatchbuf
:
797 LinkUtils
.ipbatchbuf
= ''
798 LinkUtils
.ipbatch
= False
799 LinkUtils
.ipbatch_pause
= False
802 utils
.exec_command('%s -force -batch -' % utils
.ip_cmd
,
803 stdin
=self
.ipbatchbuf
)
807 LinkUtils
.ipbatchbuf
= ''
808 LinkUtils
.ipbatch
= False
809 LinkUtils
.ipbatch_pause
= False
811 def bridge_batch_commit(self
):
812 if not LinkUtils
.ipbatchbuf
:
813 LinkUtils
.ipbatchbuf
= ''
814 LinkUtils
.ipbatch
= False
815 LinkUtils
.ipbatch_pause
= False
818 utils
.exec_command('%s -force -batch -'
819 % utils
.bridge_cmd
, stdin
=self
.ipbatchbuf
)
823 LinkUtils
.ipbatchbuf
= ''
824 LinkUtils
.ipbatch
= False
825 LinkUtils
.ipbatch_pause
= False
827 def addr_show(self
, ifacename
=None):
829 if not self
.link_exists(ifacename
):
831 return utils
.exec_commandl([utils
.ip_cmd
,
832 '-o', 'addr', 'show', 'dev', ifacename
])
834 return utils
.exec_commandl([utils
.ip_cmd
,
835 '-o', 'addr', 'show'])
838 def link_show(ifacename
=None):
840 return utils
.exec_commandl([utils
.ip_cmd
,
841 '-o', '-d', 'link', 'show', 'dev', ifacename
])
843 return utils
.exec_commandl([utils
.ip_cmd
,
844 '-o', '-d', 'link', 'show'])
846 def addr_add(self
, ifacename
, address
, broadcast
=None,
847 peer
=None, scope
=None, preferred_lifetime
=None, metric
=None):
850 cmd
= 'addr add %s' % address
852 cmd
+= ' broadcast %s' % broadcast
854 cmd
+= ' peer %s' % peer
856 cmd
+= ' scope %s' % scope
857 if preferred_lifetime
:
858 cmd
+= ' preferred_lft %s' % preferred_lifetime
859 cmd
+= ' dev %s' % ifacename
862 cmd
+= ' metric %s' % metric
864 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
865 self
.add_to_batch(cmd
)
867 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
868 self
._cache
_update
([ifacename
, 'addrs', address
], {})
870 def addr_del(self
, ifacename
, address
, broadcast
=None,
871 peer
=None, scope
=None):
872 """ Delete ipv4 address """
875 if not self
._cache
_get
('addr', [ifacename
, 'addrs', address
]):
877 cmd
= 'addr del %s' % address
879 cmd
+= 'broadcast %s' % broadcast
881 cmd
+= 'peer %s' % peer
883 cmd
+= 'scope %s' % scope
884 cmd
+= ' dev %s' % ifacename
885 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
886 self
._cache
_delete
([ifacename
, 'addrs', address
])
888 def addr_flush(self
, ifacename
):
889 cmd
= 'addr flush dev %s' % ifacename
890 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
891 self
.add_to_batch(cmd
)
893 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
894 self
._cache
_delete
([ifacename
, 'addrs'])
896 def del_addr_all(self
, ifacename
, skip_addrs
=[]):
899 runningaddrsdict
= self
.get_running_addrs(ifname
=ifacename
)
901 # XXX: ignore errors. Fix this to delete secondary addresses
903 [self
.addr_del(ifacename
, a
) for a
in
904 set(runningaddrsdict
.keys()).difference(skip_addrs
)]
909 def addr_get(self
, ifacename
, details
=True, refresh
=False):
910 addrs
= self
._cache
_get
('addr', [ifacename
, 'addrs'], refresh
=refresh
)
917 def get_running_addrs(self
, ifaceobj
=None, ifname
=None, details
=True, addr_virtual_ifaceobj
=None):
919 We now support addr with link scope. Since the kernel may add it's
920 own link address to some interfaces we need to filter them out and
921 make sure we only deal with the addresses set by ifupdown2.
923 To do so we look at the previous configuration made by ifupdown2
924 (with the help of the statemanager) together with the addresses
925 specified by the user in /etc/network/interfaces, these addresses
926 are then compared to the running state of the intf (ip addr show)
927 made via a netlink addr dump.
928 For each configured addresses of scope link, we check if it was
929 previously configured by ifupdown2 to create a final set of the
930 addresses watched by ifupdown2
932 if not ifaceobj
and not ifname
:
938 interface_name
= ifaceobj
.name
940 interface_name
= ifname
942 if addr_virtual_ifaceobj
:
943 for attr_name
in ["address-virtual", "vrrp"]:
944 for virtual
in addr_virtual_ifaceobj
.get_attr_value(attr_name
) or []:
945 for ip
in virtual
.split():
952 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(addr_virtual_ifaceobj
.name
)
953 for saved_ifaceobj
in saved_ifaceobjs
or []:
954 for virtual
in saved_ifaceobj
.get_attr_value(attr_name
) or []:
955 for ip
in virtual
.split():
963 for addr
in ifaceobj
.get_attr_value('address') or []:
964 config_addrs
.add(addr
)
966 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(interface_name
)
967 for saved_ifaceobj
in saved_ifaceobjs
or []:
968 for addr
in saved_ifaceobj
.get_attr_value('address') or []:
969 config_addrs
.add(addr
)
971 running_addrs
= OrderedDict()
972 cached_addrs
= self
.addr_get(interface_name
)
974 for addr
, addr_details
in cached_addrs
.items():
976 scope
= int(addr_details
['scope'])
980 addr_obj
= IPNetwork(addr
)
981 if isinstance(addr_obj
, IPv6Network
):
982 d
['family'] = 'inet6'
985 running_addrs
[addr
] = d
987 running_addrs
[addr
] = {}
989 if (scope
& Route
.RT_SCOPE_LINK
and addr
in config_addrs
) or not scope
& Route
.RT_SCOPE_LINK
:
990 running_addrs
[addr
] = addr_details
996 return running_addrs
.keys()
999 def compare_user_config_vs_running_state(running_addrs
, user_addrs
):
1003 for ip
in user_addrs
or []:
1006 if type(obj
) == IPv6Network
:
1012 for ip
in running_addrs
or []:
1013 running_ipobj
.append(IPNetwork(ip
))
1015 return running_ipobj
== (ip4
+ ip6
)
1017 def addr_add_multiple(self
, ifaceobj
, ifacename
, addrs
, purge_existing
=False, metric
=None):
1020 # if perfmode is not set and also if iface has no sibling
1021 # objects, purge addresses that are not present in the new
1023 runningaddrs
= self
.get_running_addrs(
1026 addr_virtual_ifaceobj
=ifaceobj
1028 addrs
= utils
.get_normalized_ip_addr(ifacename
, addrs
)
1030 if self
.compare_user_config_vs_running_state(runningaddrs
, addrs
):
1033 # if primary address is not same, there is no need to keep any.
1034 # reset all addresses
1035 if (addrs
and runningaddrs
and
1036 (addrs
[0] != runningaddrs
[0])):
1037 self
.del_addr_all(ifacename
)
1039 self
.del_addr_all(ifacename
, addrs
)
1040 except Exception, e
:
1041 self
.logger
.warning('%s: %s' % (ifacename
, str(e
)))
1044 self
.addr_add(ifacename
, a
, metric
=metric
)
1045 except Exception, e
:
1046 self
.logger
.error(str(e
))
1048 def _link_set_ifflag(self
, ifacename
, value
):
1049 # Dont look at the cache, the cache may have stale value
1050 # because link status can be changed by external
1051 # entity (One such entity is ifupdown main program)
1052 cmd
= 'link set dev %s %s' % (ifacename
, value
.lower())
1053 if LinkUtils
.ipbatch
:
1054 self
.add_to_batch(cmd
)
1056 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1058 def link_up(self
, ifacename
):
1059 self
._link
_set
_ifflag
(ifacename
, 'UP')
1061 def link_down(self
, ifacename
):
1062 self
._link
_set
_ifflag
(ifacename
, 'DOWN')
1064 def link_set(self
, ifacename
, key
, value
=None,
1065 force
=False, t
=None, state
=None):
1067 if (key
not in ['master', 'nomaster'] and
1068 self
._cache
_check
('link', [ifacename
, key
], value
)):
1070 cmd
= 'link set dev %s' % ifacename
1072 cmd
+= ' type %s' % t
1075 cmd
+= ' %s' % value
1077 cmd
+= ' %s' % state
1078 if LinkUtils
.ipbatch
:
1079 self
.add_to_batch(cmd
)
1081 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1082 if key
not in ['master', 'nomaster']:
1083 self
._cache
_update
([ifacename
, key
], value
)
1085 def link_set_hwaddress(self
, ifacename
, hwaddress
, force
=False):
1087 if self
._cache
_check
('link', [ifacename
, 'hwaddress'], hwaddress
):
1089 self
.link_down(ifacename
)
1090 cmd
= 'link set dev %s address %s' % (ifacename
, hwaddress
)
1091 if LinkUtils
.ipbatch
:
1092 self
.add_to_batch(cmd
)
1094 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1095 self
.link_up(ifacename
)
1096 self
._cache
_update
([ifacename
, 'hwaddress'], hwaddress
)
1098 def link_set_mtu(self
, ifacename
, mtu
):
1099 if ifupdownflags
.flags
.DRYRUN
:
1101 if not mtu
or not ifacename
: return
1102 self
.write_file('/sys/class/net/%s/mtu' % ifacename
, mtu
)
1103 self
._cache
_update
([ifacename
, 'mtu'], mtu
)
1105 def link_set_alias(self
, ifacename
, alias
):
1106 self
.write_file('/sys/class/net/%s/ifalias' % ifacename
,
1107 '\n' if not alias
else alias
)
1109 def link_get_alias(self
, ifacename
):
1110 return self
.read_file_oneline('/sys/class/net/%s/ifalias'
1113 def link_isloopback(self
, ifacename
):
1114 flags
= self
._cache
_get
('link', [ifacename
, 'flags'])
1117 if 'LOOPBACK' in flags
:
1121 def link_get_status(self
, ifacename
):
1122 return self
._cache
_get
('link', [ifacename
, 'ifflag'], refresh
=True)
1125 def route_add_gateway(ifacename
, gateway
, vrf
=None, metric
=None, onlink
=True):
1129 cmd
= '%s route add default via %s proto kernel' % (utils
.ip_cmd
,
1132 cmd
= ('%s route add table %s default via %s proto kernel' %
1133 (utils
.ip_cmd
, vrf
, gateway
))
1136 cmd
+= 'metric %s' % metric
1137 cmd
+= ' dev %s' % ifacename
1142 utils
.exec_command(cmd
)
1145 def route_del_gateway(ifacename
, gateway
, vrf
=None, metric
=None):
1150 cmd
= ('%s route del default via %s proto kernel' %
1151 (utils
.ip_cmd
, gateway
))
1153 cmd
= ('%s route del table %s default via %s proto kernel' %
1154 (utils
.ip_cmd
, vrf
, gateway
))
1156 cmd
+= ' metric %s' % metric
1157 cmd
+= ' dev %s' % ifacename
1158 utils
.exec_command(cmd
)
1161 def _get_vrf_id(ifacename
):
1163 return linkCache
.vrfs
[ifacename
]['table']
1165 dump
= netlink
.link_dump(ifacename
)
1167 [linkCache
.update_attrdict([ifname
], linkattrs
)
1168 for ifname
, linkattrs
in dump
.items()]
1170 if dump
and dump
.get(ifacename
, {}).get('kind') == 'vrf':
1171 vrf_table
= dump
.get(ifacename
, {}).get('linkinfo', {}).get('table')
1172 linkCache
.vrfs
[ifacename
] = {'table': vrf_table
}
1177 def fix_ipv6_route_metric(self
, ifaceobj
, macvlan_ifacename
, ips
):
1180 if ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
:
1182 for upper_iface
in ifaceobj
.upperifaces
:
1183 vrf_table
= self
._get
_vrf
_id
(upper_iface
)
1191 ip_network_obj
= IPNetwork(ip
)
1193 if type(ip_network_obj
) == IPv6Network
:
1194 route_prefix
= '%s/%d' % (ip_network_obj
.network
, ip_network_obj
.prefixlen
)
1197 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1198 LinkUtils
.add_to_batch('route del %s table %s dev %s' % (route_prefix
, vrf_table
, macvlan_ifacename
))
1200 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'table', vrf_table
, 'dev', macvlan_ifacename
])
1202 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1203 LinkUtils
.add_to_batch('route del %s dev %s' % (route_prefix
, macvlan_ifacename
))
1205 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'dev', macvlan_ifacename
])
1206 ip_route_del
.append((route_prefix
, vrf_table
))
1208 for ip
, vrf_table
in ip_route_del
:
1210 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1211 LinkUtils
.add_to_batch('route add %s table %s dev %s proto kernel metric 9999' % (ip
, vrf_table
, macvlan_ifacename
))
1213 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'table', vrf_table
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1215 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1216 LinkUtils
.add_to_batch('route add %s dev %s proto kernel metric 9999' % (ip
, macvlan_ifacename
))
1218 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1220 def link_create_vlan(self
, vlan_device_name
, vlan_raw_device
, vlanid
):
1221 if self
.link_exists(vlan_device_name
):
1223 utils
.exec_command('%s link add link %s name %s type vlan id %d' %
1225 vlan_raw_device
, vlan_device_name
, vlanid
))
1226 self
._cache
_update
([vlan_device_name
], {})
1228 def link_create_vlan_from_name(self
, vlan_device_name
):
1229 v
= vlan_device_name
.split('.')
1231 self
.logger
.warn('invalid vlan device name %s' % vlan_device_name
)
1233 self
.link_create_vlan(vlan_device_name
, v
[0], v
[1])
1235 def link_create_macvlan(self
, name
, linkdev
, mode
='private'):
1236 if self
.link_exists(name
):
1238 cmd
= ('link add link %s' % linkdev
+
1240 ' type macvlan mode %s' % mode
)
1241 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1242 self
.add_to_batch(cmd
)
1244 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1245 self
._cache
_update
([name
], {})
1247 def get_vxlan_peers(self
, dev
, svcnodeip
):
1248 cmd
= '%s fdb show brport %s' % (utils
.bridge_cmd
,
1252 ps
= subprocess
.Popen(shlex
.split(cmd
), stdout
=subprocess
.PIPE
, close_fds
=False)
1253 utils
.enable_subprocess_signal_forwarding(ps
, signal
.SIGINT
)
1254 output
= subprocess
.check_output(('grep', '00:00:00:00:00:00'), stdin
=ps
.stdout
)
1256 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1258 ppat
= re
.compile('\s+dst\s+(\d+.\d+.\d+.\d+)\s+')
1259 for l
in output
.split('\n'):
1261 if m
and m
.group(1) != svcnodeip
:
1262 cur_peers
.append(m
.group(1))
1264 self
.logger
.warn('error parsing ip link output')
1265 except subprocess
.CalledProcessError
as e
:
1266 if e
.returncode
!= 1:
1267 self
.logger
.error(str(e
))
1269 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1273 def tunnel_create(self
, tunnelname
, mode
, attrs
={}):
1274 """ generic link_create function """
1275 if self
.link_exists(tunnelname
):
1282 if mode
in ['gretap']:
1283 cmd
+= 'link add %s type %s' % (tunnelname
, mode
)
1285 cmd
+= 'tunnel add %s mode %s' % (tunnelname
, mode
)
1288 for k
, v
in attrs
.iteritems():
1292 if self
.ipbatch
and not self
.ipbatch_pause
:
1293 self
.add_to_batch(cmd
)
1295 utils
.exec_command('ip %s' % cmd
)
1296 self
._cache
_update
([tunnelname
], {})
1298 def tunnel_change(self
, tunnelname
, attrs
={}):
1299 """ tunnel change function """
1300 if not self
.link_exists(tunnelname
):
1302 cmd
= 'tunnel change'
1303 cmd
+= ' %s' %(tunnelname)
1305 for k
, v
in attrs
.iteritems():
1309 if self
.ipbatch
and not self
.ipbatch_pause
:
1310 self
.add_to_batch(cmd
)
1312 utils
.exec_command('ip %s' % cmd
)
1314 def link_create_vxlan(self
, name
, vxlanid
,
1322 if svcnodeip
and remoteips
:
1323 raise Exception("svcnodeip and remoteip is mutually exclusive")
1326 args
+= ' remote %s' % svcnodeip
1328 args
+= ' ageing %s' % ageing
1329 if learning
== 'off':
1330 args
+= ' nolearning'
1332 args
+= ' ttl %s' % ttl
1334 if self
.link_exists(name
):
1335 cmd
= 'link set dev %s type vxlan dstport %d' % (name
, LinkUtils
.VXLAN_UDP_PORT
)
1336 vxlanattrs
= self
.get_vxlandev_attrs(name
)
1337 # on ifreload do not overwrite anycast_ip to individual ip if clagd
1340 running_localtunnelip
= vxlanattrs
.get('local')
1341 if anycastip
and running_localtunnelip
and anycastip
== running_localtunnelip
:
1342 localtunnelip
= running_localtunnelip
1343 running_svcnode
= vxlanattrs
.get('svcnode')
1344 if running_svcnode
and not svcnodeip
:
1347 cmd
= 'link add dev %s type vxlan id %s dstport %d' % (name
, vxlanid
, LinkUtils
.VXLAN_UDP_PORT
)
1350 args
+= ' local %s' % localtunnelip
1353 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1354 self
.add_to_batch(cmd
)
1356 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1358 # XXX: update linkinfo correctly
1359 #self._cache_update([name], {})
1362 def link_exists(ifacename
):
1363 if ifupdownflags
.flags
.DRYRUN
:
1365 return os
.path
.exists('/sys/class/net/%s' % ifacename
)
1368 def link_exists_nodryrun(ifname
):
1369 return os
.path
.exists('/sys/class/net/%s' % ifname
)
1371 def link_get_ifindex(self
, ifacename
):
1372 if ifupdownflags
.flags
.DRYRUN
:
1374 return self
.read_file_oneline('/sys/class/net/%s/ifindex' % ifacename
)
1376 def is_vlan_device_by_name(self
, ifacename
):
1377 if re
.search(r
'\.', ifacename
):
1382 def link_add_macvlan(ifname
, macvlan_ifacename
, mode
):
1383 utils
.exec_commandl(['ip', 'link', 'add', 'link', ifname
, 'name', macvlan_ifacename
, 'type', 'macvlan', 'mode', mode
])
1386 def route_add(route
):
1387 utils
.exec_command('%s route add %s' % (utils
.ip_cmd
,
1391 def route6_add(route
):
1392 utils
.exec_command('%s -6 route add %s' % (utils
.ip_cmd
,
1395 def get_vlandev_attrs(self
, ifacename
):
1396 return (self
._cache
_get
('link', [ifacename
, 'link']),
1397 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlanid']),
1398 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol']))
1400 def get_vlan_protocol(self
, ifacename
):
1401 return self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol'])
1403 def get_vxlandev_attrs(self
, ifacename
):
1404 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1406 def get_vxlandev_learning(self
, ifacename
):
1407 return self
._cache
_get
('link', [ifacename
, 'linkinfo', Link
.IFLA_VXLAN_LEARNING
])
1409 def set_vxlandev_learning(self
, ifacename
, learn
):
1411 utils
.exec_command('%s link set dev %s type vxlan learning' %
1412 (utils
.ip_cmd
, ifacename
))
1413 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'on')
1415 utils
.exec_command('%s link set dev %s type vxlan nolearning' %
1416 (utils
.ip_cmd
, ifacename
))
1417 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'off')
1419 def link_get_linkinfo_attrs(self
, ifacename
):
1420 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1422 def link_get_mtu(self
, ifacename
, refresh
=False):
1423 return self
._cache
_get
('link', [ifacename
, 'mtu'], refresh
=refresh
)
1425 def link_get_mtu_sysfs(self
, ifacename
):
1426 return self
.read_file_oneline('/sys/class/net/%s/mtu'
1429 def link_get_kind(self
, ifacename
):
1430 return self
._cache
_get
('link', [ifacename
, 'kind'])
1432 def link_get_slave_kind(self
, ifacename
):
1433 return self
._cache
_get
('link', [ifacename
, 'slave_kind'])
1435 def link_get_hwaddress(self
, ifacename
):
1436 address
= self
._cache
_get
('link', [ifacename
, 'hwaddress'])
1437 # newly created logical interface addresses dont end up in the cache
1438 # read hwaddress from sysfs file for these interfaces
1440 address
= self
.read_file_oneline('/sys/class/net/%s/address'
1444 def link_create(self
, ifacename
, t
, attrs
={}):
1445 """ generic link_create function """
1446 if self
.link_exists(ifacename
):
1449 cmd
+= ' name %s type %s' % (ifacename
, t
)
1451 for k
, v
in attrs
.iteritems():
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
_update
([ifacename
], {})
1461 def link_delete(self
, ifacename
):
1462 if not self
.link_exists(ifacename
):
1464 cmd
= 'link del %s' % ifacename
1465 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1466 self
.add_to_batch(cmd
)
1468 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1469 self
._cache
_invalidate
()
1471 def link_get_master(self
, ifacename
):
1472 sysfs_master_path
= '/sys/class/net/%s/master' % ifacename
1473 if os
.path
.exists(sysfs_master_path
):
1474 link_path
= os
.readlink(sysfs_master_path
)
1476 return os
.path
.basename(link_path
)
1480 return self
._cache
_get
('link', [ifacename
, 'master'])
1482 def get_brport_peer_link(self
, bridgename
):
1484 return self
._cache
_get
('link', [bridgename
, 'info_slave_data', Link
.IFLA_BRPORT_PEER_LINK
])
1489 def bridge_port_vids_add(bridgeportname
, vids
):
1490 [utils
.exec_command('%s vlan add vid %s dev %s' %
1492 v
, bridgeportname
)) for v
in vids
]
1495 def bridge_port_vids_del(bridgeportname
, vids
):
1498 [utils
.exec_command('%s vlan del vid %s dev %s' %
1500 v
, bridgeportname
)) for v
in vids
]
1503 def bridge_port_vids_flush(bridgeportname
, vid
):
1504 utils
.exec_command('%s vlan del vid %s dev %s' %
1506 vid
, bridgeportname
))
1509 def bridge_port_vids_get(bridgeportname
):
1510 bridgeout
= utils
.exec_command('%s vlan show dev %s' %
1515 brvlanlines
= bridgeout
.readlines()[2:]
1516 vids
= [l
.strip() for l
in brvlanlines
]
1517 return [v
for v
in vids
if v
]
1520 def bridge_port_vids_get_all():
1522 bridgeout
= utils
.exec_command('%s -c vlan show'
1526 brvlanlines
= bridgeout
.splitlines()
1528 for l
in brvlanlines
[1:]:
1529 if l
and not l
.startswith(' ') and not l
.startswith('\t'):
1531 brportname
= attrs
[0].strip()
1532 brvlaninfo
[brportname
] = {'pvid': None, 'vlan': []}
1533 l
= ' '.join(attrs
[1:])
1534 if not brportname
or not l
:
1538 brvlaninfo
[brportname
]['pvid'] = l
.split()[0]
1539 elif 'Egress Untagged' not in l
:
1540 brvlaninfo
[brportname
]['vlan'].append(l
)
1543 def bridge_port_vids_get_all_json(self
):
1544 if not self
.supported_command
['%s -c -json vlan show'
1545 % utils
.bridge_cmd
]:
1549 bridgeout
= utils
.exec_command('%s -c -json vlan show'
1552 self
.supported_command
['%s -c -json vlan show'
1553 % utils
.bridge_cmd
] = False
1554 self
.logger
.info('%s -c -json vlan show: skipping unsupported command'
1557 return self
.get_bridge_vlan_nojson()
1558 except Exception as e
:
1559 self
.logger
.info('bridge: get_bridge_vlan_nojson: %s' % str(e
))
1562 if not bridgeout
: return brvlaninfo
1564 vlan_json
= json
.loads(bridgeout
, encoding
="utf-8")
1565 except Exception, e
:
1566 self
.logger
.info('json loads failed with (%s)' % str(e
))
1570 if isinstance(vlan_json
, list):
1571 # newer iproute2 version changed the bridge vlan show output
1572 # ifupdown2 relies on the previous format, we have the convert
1573 # data into old format
1574 bridge_port_vids
= dict()
1576 for intf
in vlan_json
:
1577 bridge_port_vids
[intf
["ifname"]] = intf
["vlans"]
1579 return bridge_port_vids
1581 # older iproute2 version have different ways to dump vlans
1582 # ifupdown2 prefers the following syntax:
1586 # "flags": ["PVID", "Egress Untagged"]
1591 # "flags": ["PVID", "Egress Untagged"]
1595 except Exception as e
:
1596 self
.logger
.debug("bridge vlan show: Unknown json output: %s" % str(e
))
1600 def get_bridge_vlan_nojson():
1602 bridgeout
= utils
.exec_commandl([utils
.bridge_cmd
, '-c', 'vlan', 'show'])
1604 output
= [line
.split('\n') for line
in bridgeout
.split('\n\n')]
1605 output
[0] = output
[0][1:]
1613 prefix
, vlan
= entry
.split('\t')
1615 current_swp
= prefix
1616 vlan_json
[prefix
] = []
1620 v
['vlan'] = int(vlan
)
1624 start
, end
= vlan
.split('-')
1626 end
= end
[0:end
.index(' ')]
1627 v
['vlan'] = int(start
)
1628 v
['vlanEnd'] = int(end
)
1630 v
['vlan'] = int(vlan
[0:vlan
.index(' ')])
1633 flags
.append('PVID')
1634 if 'Egress Untagged' in vlan
:
1635 flags
.append('Egress Untagged')
1639 vlan_json
[current_swp
].append(v
)
1642 def bridge_vlan_cache_get(self
, ifacename
, refresh
=False):
1643 if not self
.bridge_vlan_cache_fill_done
or refresh
:
1644 self
.bridge_vlan_cache
= self
.bridge_port_vids_get_all_json()
1645 self
.bridge_vlan_cache_fill_done
= True
1646 return self
.bridge_vlan_cache
.get(ifacename
, {})
1648 def bridge_vlan_get_pvid(self
, ifacename
, refresh
=False):
1651 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1652 v
= vinfo
.get('vlan')
1653 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1658 def bridge_vlan_get_vids(self
, ifacename
, refresh
=False):
1661 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1662 v
= vinfo
.get('vlan')
1663 ispvid
= True if 'PVID' in vinfo
.get('flags', []) else False
1665 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1668 vEnd
= vinfo
.get('vlanEnd')
1670 vids
.extend(range(v
, vEnd
+ 1))
1675 def bridge_vlan_get_vids_n_pvid(self
, ifacename
, refresh
=False):
1679 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1680 v
= vinfo
.get('vlan')
1681 ispvid
= True if 'PVID' in vinfo
.get('flags', []) else False
1683 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1684 vEnd
= vinfo
.get('vlanEnd')
1686 vids
.extend(range(v
, vEnd
+ 1))
1691 def bridge_port_pvid_add(self
, bridgeportname
, pvid
):
1692 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1693 self
.add_to_batch('vlan add vid %s untagged pvid dev %s' %
1694 (pvid
, bridgeportname
))
1696 utils
.exec_command('%s vlan add vid %s untagged pvid dev %s' %
1698 pvid
, bridgeportname
))
1700 def bridge_port_pvid_del(self
, bridgeportname
, pvid
):
1701 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1702 self
.add_to_batch('vlan del vid %s untagged pvid dev %s' %
1703 (pvid
, bridgeportname
))
1705 utils
.exec_command('%s vlan del vid %s untagged pvid dev %s' %
1707 pvid
, bridgeportname
))
1709 def bridge_port_pvids_get(self
, bridgeportname
):
1710 return self
.read_file_oneline('/sys/class/net/%s/brport/pvid'
1713 def bridge_vids_add(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 add vid %s dev %s %s' %
1717 (v
, bridgeportname
, target
)) for v
in vids
]
1719 [utils
.exec_command('%s vlan add vid %s dev %s %s' %
1721 v
, bridgeportname
, target
)) for v
in vids
]
1723 def bridge_vids_del(self
, bridgeportname
, vids
, bridge
=True):
1724 target
= 'self' if bridge
else ''
1725 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1726 [self
.add_to_batch('vlan del vid %s dev %s %s' %
1727 (v
, bridgeportname
, target
)) for v
in vids
]
1729 [utils
.exec_command('%s vlan del vid %s dev %s %s' %
1731 v
, bridgeportname
, target
)) for v
in vids
]
1734 def bridge_fdb_add(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1735 target
= 'self' if bridge
else ''
1738 vlan_str
= 'vlan %s ' % vlan
1742 dst_str
= 'dst %s ' % remote
1744 utils
.exec_command('%s fdb replace %s dev %s %s %s %s' %
1746 address
, dev
, vlan_str
, target
, dst_str
))
1749 def bridge_fdb_append(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1750 target
= 'self' if bridge
else ''
1753 vlan_str
= 'vlan %s ' % vlan
1757 dst_str
= 'dst %s ' % remote
1759 utils
.exec_command('%s fdb append %s dev %s %s %s %s' %
1761 address
, dev
, vlan_str
, target
, dst_str
))
1764 def bridge_fdb_del(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1765 target
= 'self' if bridge
else ''
1768 vlan_str
= 'vlan %s ' % vlan
1772 dst_str
= 'dst %s ' % remote
1773 utils
.exec_command('%s fdb del %s dev %s %s %s %s' %
1775 address
, dev
, vlan_str
, target
, dst_str
))
1777 def bridge_is_vlan_aware(self
, bridgename
):
1778 filename
= '/sys/class/net/%s/bridge/vlan_filtering' % bridgename
1779 if os
.path
.exists(filename
) and self
.read_file_oneline(filename
) == '1':
1784 def bridge_port_get_bridge_name(bridgeport
):
1785 filename
= '/sys/class/net/%s/brport/bridge' % bridgeport
1787 return os
.path
.basename(os
.readlink(filename
))
1792 def bridge_port_exists(bridge
, bridgeportname
):
1794 return os
.path
.exists('/sys/class/net/%s/brif/%s'
1795 % (bridge
, bridgeportname
))
1799 def bridge_fdb_show_dev(self
, dev
):
1802 output
= utils
.exec_command('%s fdb show dev %s'
1803 % (utils
.bridge_cmd
, dev
))
1805 for fdb_entry
in output
.splitlines():
1807 entries
= fdb_entry
.split()
1808 fdbs
.setdefault(entries
[2], []).append(entries
[0])
1810 self
.logger
.debug('%s: invalid fdb line \'%s\''
1817 def is_bridge(bridge
):
1818 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
1820 def is_link_up(self
, ifacename
):
1823 flags
= self
.read_file_oneline('/sys/class/net/%s/flags' % ifacename
)
1824 iflags
= int(flags
, 16)
1831 def ip_route_get_dev(self
, prefix
, vrf_master
=None):
1834 cmd
= '%s route get %s vrf %s' % (utils
.ip_cmd
, prefix
, vrf_master
)
1836 cmd
= '%s route get %s' % (utils
.ip_cmd
, prefix
)
1838 output
= utils
.exec_command(cmd
)
1840 rline
= output
.splitlines()[0]
1842 rattrs
= rline
.split()
1843 return rattrs
[rattrs
.index('dev') + 1]
1844 except Exception, e
:
1845 self
.logger
.debug('ip_route_get_dev: failed .. %s' % str(e
))
1849 def link_get_lowers(ifacename
):
1851 lowers
= glob
.glob("/sys/class/net/%s/lower_*" % ifacename
)
1854 return [os
.path
.basename(l
)[6:] for l
in lowers
]
1859 def link_get_uppers(ifacename
):
1861 uppers
= glob
.glob("/sys/class/net/%s/upper_*" % ifacename
)
1864 return [os
.path
.basename(u
)[6:] for u
in uppers
]
1868 def link_get_vrfs(self
):
1869 if not LinkUtils
._CACHE
_FILL
_DONE
:
1871 return linkCache
.vrfs
1874 def cache_get_info_slave(attrlist
):
1876 return linkCache
.get_attr(attrlist
)
1880 def get_brport_learning(self
, ifacename
):
1881 learn
= self
.read_file_oneline('/sys/class/net/%s/brport/learning'
1883 if learn
and learn
== '1':
1888 def get_brport_learning_bool(self
, ifacename
):
1889 return utils
.get_boolean_from_string(self
.read_file_oneline('/sys/class/net/%s/brport/learning' % ifacename
))
1891 def set_brport_learning(self
, ifacename
, learn
):
1893 return self
.write_file('/sys/class/net/%s/brport/learning'
1896 return self
.write_file('/sys/class/net/%s/brport/learning'
1899 #################################################################################
1900 ################################### BOND UTILS ##################################
1901 #################################################################################
1903 def _link_cache_get(self
, attrlist
, refresh
=False):
1904 return self
._cache
_get
('link', attrlist
, refresh
)
1906 def cache_delete(self
, attrlist
, value
=None):
1907 return self
._cache
_delete
(attrlist
, value
)
1909 def link_cache_get(self
, attrlist
, refresh
=False):
1910 return self
._link
_cache
_get
(attrlist
, refresh
)
1912 def link_cache_check(self
, attrlist
, value
, refresh
=False):
1913 return self
._link
_cache
_check
(attrlist
, value
, refresh
)
1915 def _link_cache_check(self
, attrlist
, value
, refresh
=False):
1917 return self
._link
_cache
_get
(attrlist
, refresh
) == value
1918 except Exception, e
:
1919 self
.logger
.debug('_cache_check(%s) : [%s]'
1920 % (str(attrlist
), str(e
)))
1925 Link
.IFLA_BOND_MODE
: 'mode',
1926 Link
.IFLA_BOND_MIIMON
: 'miimon',
1927 Link
.IFLA_BOND_USE_CARRIER
: 'use_carrier',
1928 Link
.IFLA_BOND_AD_LACP_RATE
: 'lacp_rate',
1929 Link
.IFLA_BOND_XMIT_HASH_POLICY
: 'xmit_hash_policy',
1930 Link
.IFLA_BOND_MIN_LINKS
: 'min_links',
1931 Link
.IFLA_BOND_NUM_PEER_NOTIF
: 'num_grat_arp',
1932 Link
.IFLA_BOND_AD_ACTOR_SYSTEM
: 'ad_actor_system',
1933 Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
: 'ad_actor_sys_prio',
1934 Link
.IFLA_BOND_AD_LACP_BYPASS
: 'lacp_bypass',
1935 Link
.IFLA_BOND_UPDELAY
: 'updelay',
1936 Link
.IFLA_BOND_DOWNDELAY
: 'downdelay',
1939 def bond_set_attrs_nl(self
, bondname
, ifla_info_data
):
1940 bond_attr_name
= 'None' # for log purpose (in case an exception raised)
1941 for nl_attr
, value
in ifla_info_data
.items():
1943 bond_attr_name
= self
.bondcmd_attrmap
[nl_attr
]
1944 file_path
= '/sys/class/net/%s/bonding/%s' % (bondname
, bond_attr_name
)
1945 if os
.path
.exists(file_path
):
1946 self
.write_file(file_path
, str(value
))
1947 except Exception as e
:
1948 exception_str
= '%s: %s %s: %s' % (bondname
, bond_attr_name
, value
, str(e
))
1949 if ifupdownflags
.flags
.FORCE
:
1950 self
.logger
.warning(exception_str
)
1952 self
.logger
.debug(exception_str
)
1954 def bond_set_attrs(self
, bondname
, attrdict
, prehook
):
1955 for attrname
, attrval
in attrdict
.items():
1956 if (self
._link
_cache
_check
([bondname
, 'linkinfo',
1957 attrname
], attrval
)):
1959 if (attrname
== 'mode'
1960 or attrname
== 'xmit_hash_policy'
1961 or attrname
== 'lacp_rate' or attrname
== 'min_links'):
1965 if ((attrname
not in ['lacp_rate',
1967 self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'], '802.3ad',
1969 self
.write_file('/sys/class/net/%s/bonding/%s'
1970 % (bondname
, attrname
), attrval
)
1971 except Exception, e
:
1972 if ifupdownflags
.flags
.FORCE
:
1973 self
.logger
.warn(str(e
))
1978 def bond_set_use_carrier(self
, bondname
, use_carrier
):
1979 if not use_carrier
or (use_carrier
!= '0' and use_carrier
!= '1'):
1981 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'use_carrier'],
1984 self
.write_file('/sys/class/net/%s' % bondname
+
1985 '/bonding/use_carrier', use_carrier
)
1986 self
._cache
_update
([bondname
, 'linkinfo',
1987 'use_carrier'], use_carrier
)
1989 def bond_get_use_carrier(self
, bondname
):
1990 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'use_carrier'])
1992 def bond_get_use_carrier_nl(self
, bondname
):
1993 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_USE_CARRIER
])
1995 def bond_set_xmit_hash_policy(self
, bondname
, hash_policy
, prehook
=None):
1996 valid_values
= ['layer2', 'layer3+4', 'layer2+3']
1999 if hash_policy
not in valid_values
:
2000 raise Exception('invalid hash policy value %s' % hash_policy
)
2001 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'xmit_hash_policy'],
2006 self
.write_file('/sys/class/net/%s' % bondname
+
2007 '/bonding/xmit_hash_policy', hash_policy
)
2008 self
._cache
_update
([bondname
, 'linkinfo', 'xmit_hash_policy'],
2011 def bond_get_xmit_hash_policy(self
, bondname
):
2012 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'xmit_hash_policy'])
2014 def bond_get_xmit_hash_policy_nl(self
, bondname
):
2015 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_XMIT_HASH_POLICY
])
2017 def bond_set_miimon(self
, bondname
, miimon
):
2018 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'miimon'],
2021 self
.write_file('/sys/class/net/%s' % bondname
+
2022 '/bonding/miimon', miimon
)
2023 self
._cache
_update
([bondname
, 'linkinfo', 'miimon'], miimon
)
2025 def bond_get_miimon(self
, bondname
):
2026 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'miimon'])
2028 def bond_get_miimon_nl(self
, bondname
):
2029 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIIMON
])
2031 def bond_set_mode(self
, bondname
, mode
, prehook
=None):
2032 valid_modes
= ['balance-rr', 'active-backup', 'balance-xor',
2033 'broadcast', '802.3ad', 'balance-tlb', 'balance-alb']
2036 if mode
not in valid_modes
:
2037 raise Exception('invalid mode %s' % mode
)
2038 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'],
2043 self
.write_file('/sys/class/net/%s' % bondname
+ '/bonding/mode', mode
)
2044 self
._cache
_update
([bondname
, 'linkinfo', 'mode'], mode
)
2046 def bond_get_mode(self
, bondname
):
2047 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'mode'])
2049 def bond_get_mode_nl(self
, bondname
):
2050 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MODE
])
2052 def bond_set_lacp_rate(self
, bondname
, lacp_rate
, prehook
=None, posthook
=None):
2053 if not lacp_rate
or (lacp_rate
!= '0' and lacp_rate
!= '1'):
2055 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_rate'],
2061 self
.write_file('/sys/class/net/%s' % bondname
+
2062 '/bonding/lacp_rate', lacp_rate
)
2068 self
._cache
_update
([bondname
, 'linkinfo',
2069 'lacp_rate'], lacp_rate
)
2071 def bond_get_lacp_rate(self
, bondname
):
2072 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_rate'])
2074 def bond_get_lacp_rate_nl(self
, bondname
):
2075 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_RATE
])
2077 def bond_set_lacp_bypass_allow(self
, bondname
, allow
, prehook
=None, posthook
=None):
2078 if self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_bypass'], allow
):
2083 self
.write_file('/sys/class/net/%s' % bondname
+
2084 '/bonding/lacp_bypass', allow
)
2090 self
._cache
_update
([bondname
, 'linkinfo',
2091 'lacp_bypass'], allow
)
2093 def bond_get_lacp_bypass_allow(self
, bondname
):
2094 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_bypass'])
2096 def bond_get_lacp_bypass_allow_nl(self
, bondname
):
2097 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_BYPASS
])
2099 def bond_set_min_links(self
, bondname
, min_links
, prehook
=None):
2100 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'min_links'],
2105 self
.write_file('/sys/class/net/%s/bonding/min_links' % bondname
,
2107 self
._cache
_update
([bondname
, 'linkinfo', 'min_links'], min_links
)
2109 def bond_get_min_links(self
, bondname
):
2110 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'min_links'])
2112 def get_min_links_nl(self
, bondname
):
2113 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIN_LINKS
])
2115 def bond_get_ad_actor_system(self
, bondname
):
2116 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_system'])
2118 def bond_get_ad_actor_system_nl(self
, bondname
):
2119 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYSTEM
])
2121 def bond_get_ad_actor_sys_prio(self
, bondname
):
2122 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_sys_prio'])
2124 def bond_get_ad_actor_sys_prio_nl(self
, bondname
):
2125 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
])
2127 def bond_get_num_unsol_na(self
, bondname
):
2128 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_unsol_na'])
2130 def bond_get_num_unsol_na_nl(self
, bondname
):
2131 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2133 def bond_get_num_grat_arp(self
, bondname
):
2134 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_grat_arp'])
2136 def bond_get_num_grat_arp_nl(self
, bondname
):
2137 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2139 def bond_get_updelay(self
, bondname
):
2140 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'updelay'])
2142 def bond_get_updelay_nl(self
, bondname
):
2143 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_UPDELAY
])
2145 def bond_get_downdelay(self
, bondname
):
2146 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'downdelay'])
2148 def bond_get_downdelay_nl(self
, bondname
):
2149 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_DOWNDELAY
])
2151 def bond_enslave_slave(self
, bondname
, slave
, prehook
=None, posthook
=None):
2152 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2153 if slaves
and slave
in slaves
:
2157 self
.write_file('/sys/class/net/%s' % bondname
+
2158 '/bonding/slaves', '+' + slave
)
2161 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slave
)
2163 def bond_remove_slave(self
, bondname
, slave
):
2164 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2165 if not slaves
or slave
not in slaves
:
2167 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2169 if not os
.path
.exists(sysfs_bond_path
):
2171 self
.write_file(sysfs_bond_path
, '-' + slave
)
2172 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'], slave
)
2174 def bond_remove_slaves_all(self
, bondname
):
2175 if not self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves']):
2178 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2181 with
open(sysfs_bond_path
, 'r') as f
:
2182 slaves
= f
.readline().strip().split()
2184 raise Exception('error reading slaves of bond %s (%s)' % (bondname
, str(e
)))
2185 for slave
in slaves
:
2186 self
.link_down(slave
)
2188 self
.bond_remove_slave(bondname
, slave
)
2189 except Exception, e
:
2190 if not ifupdownflags
.flags
.FORCE
:
2191 raise Exception('error removing slave %s from bond %s (%s)' % (slave
, bondname
, str(e
)))
2194 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'])
2197 def bond_load_bonding_module():
2198 return utils
.exec_command('%s -q bonding' % utils
.modprobe_cmd
)
2200 def create_bond(self
, bondname
):
2201 if self
.bond_exists(bondname
):
2203 # load_bonding_module() has already been run
2204 self
.write_file('/sys/class/net/bonding_masters', '+' + bondname
)
2205 self
._cache
_update
([bondname
], {})
2207 def delete_bond(self
, bondname
):
2208 if not os
.path
.exists('/sys/class/net/%s' % bondname
):
2210 self
.write_file('/sys/class/net/bonding_masters', '-' + bondname
)
2211 self
._cache
_delete
([bondname
])
2213 def bond_get_slaves(self
, bondname
):
2214 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2217 slavefile
= '/sys/class/net/%s/bonding/slaves' % bondname
2218 if os
.path
.exists(slavefile
):
2219 buf
= self
.read_file_oneline(slavefile
)
2221 slaves
= buf
.split()
2224 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slaves
)
2227 def bond_slave_exists(self
, bond
, slave
):
2228 slaves
= self
.bond_get_slaves(bond
)
2231 return slave
in slaves
2234 def bond_exists(bondname
):
2235 return os
.path
.exists('/sys/class/net/%s/bonding' % bondname
)
2237 #################################################################################
2238 ################################## BRIDGE UTILS #################################
2239 #################################################################################
2241 def create_bridge(self
, bridgename
):
2242 if not LinkUtils
.bridge_utils_is_installed
:
2244 if self
.bridge_exists(bridgename
):
2246 utils
.exec_command('%s addbr %s' % (utils
.brctl_cmd
, bridgename
))
2247 self
._cache
_update
([bridgename
], {})
2249 def delete_bridge(self
, bridgename
):
2250 if not LinkUtils
.bridge_utils_is_installed
:
2252 if not self
.bridge_exists(bridgename
):
2254 utils
.exec_command('%s delbr %s' % (utils
.brctl_cmd
, bridgename
))
2255 self
._cache
_invalidate
()
2257 def add_bridge_port(self
, bridgename
, bridgeportname
):
2258 """ Add port to bridge """
2259 if not LinkUtils
.bridge_utils_is_installed
:
2261 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2262 if ports
and ports
.get(bridgeportname
):
2264 utils
.exec_command('%s addif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2265 self
._cache
_update
([bridgename
, 'linkinfo', 'ports', bridgeportname
], {})
2267 def delete_bridge_port(self
, bridgename
, bridgeportname
):
2268 """ Delete port from bridge """
2269 if not LinkUtils
.bridge_utils_is_installed
:
2271 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2272 if not ports
or not ports
.get(bridgeportname
):
2274 utils
.exec_command('%s delif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2275 self
._cache
_delete
([bridgename
, 'linkinfo', 'ports', 'bridgeportname'])
2277 def set_bridgeport_attrs(self
, bridgename
, bridgeportname
, attrdict
):
2278 portattrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports', bridgeportname
])
2279 if portattrs
== None:
2281 for k
, v
in attrdict
.iteritems():
2282 if ifupdownflags
.flags
.CACHE
:
2283 curval
= portattrs
.get(k
)
2284 if curval
and curval
== v
:
2286 if k
== 'unicast-flood':
2287 self
.write_file('/sys/class/net/%s/brport/unicast_flood' % bridgeportname
, v
)
2288 elif k
== 'multicast-flood':
2289 self
.write_file('/sys/class/net/%s/brport/multicast_flood' % bridgeportname
, v
)
2290 elif k
== 'learning':
2291 self
.write_file('/sys/class/net/%s/brport/learning' % bridgeportname
, v
)
2292 elif k
== 'arp-nd-suppress':
2293 self
.write_file('/sys/class/net/%s/brport/neigh_suppress' % bridgeportname
, v
)
2295 if not LinkUtils
.bridge_utils_is_installed
:
2297 utils
.exec_command('%s set%s %s %s %s' % (utils
.brctl_cmd
, k
, bridgename
, bridgeportname
, v
))
2299 def set_bridgeport_attr(self
, bridgename
, bridgeportname
,
2301 if not LinkUtils
.bridge_utils_is_installed
:
2303 if self
._link
_cache
_check
([bridgename
, 'linkinfo', 'ports', bridgeportname
, attrname
], attrval
):
2305 utils
.exec_command('%s set%s %s %s %s' %
2312 def set_bridge_attrs(self
, bridgename
, attrdict
):
2313 for k
, v
in attrdict
.iteritems():
2316 if self
._link
_cache
_check
([bridgename
, 'linkinfo', k
], v
):
2319 if k
== 'igmp-version':
2320 self
.write_file('/sys/class/net/%s/bridge/'
2321 'multicast_igmp_version' % bridgename
, v
)
2322 elif k
== 'mld-version':
2323 self
.write_file('/sys/class/net/%s/bridge/'
2324 'multicast_mld_version' % bridgename
, v
)
2325 elif k
== 'vlan-protocol':
2326 self
.write_file('/sys/class/net/%s/bridge/'
2327 'vlan_protocol' % bridgename
,
2328 VlanProtocols
.ETHERTYPES_TO_ID
.get(v
.upper(),
2330 elif k
== 'vlan-stats':
2331 self
.write_file('/sys/class/net/%s/bridge/'
2332 'vlan_stats_enabled' % bridgename
, v
)
2333 elif k
== 'mcstats':
2334 self
.write_file('/sys/class/net/%s/bridge/'
2335 'multicast_stats_enabled' % bridgename
, v
)
2337 if not LinkUtils
.bridge_utils_is_installed
:
2339 cmd
= ('%s set%s %s %s' %
2340 (utils
.brctl_cmd
, k
, bridgename
, v
))
2341 utils
.exec_command(cmd
)
2342 except Exception, e
:
2343 self
.logger
.warn('%s: %s' % (bridgename
, str(e
)))
2346 def set_bridge_attr(self
, bridgename
, attrname
, attrval
):
2347 if self
._link
_cache
_check
([bridgename
, 'linkinfo', attrname
], attrval
):
2349 if attrname
== 'igmp-version':
2350 self
.write_file('/sys/class/net/%s/bridge/multicast_igmp_version'
2351 % bridgename
, attrval
)
2352 elif attrname
== 'mld-version':
2353 self
.write_file('/sys/class/net/%s/bridge/multicast_mld_version'
2354 % bridgename
, attrval
)
2355 elif attrname
== 'vlan-protocol':
2356 self
.write_file('/sys/class/net/%s/bridge/vlan_protocol'
2357 % bridgename
, VlanProtocols
.ETHERTYPES_TO_ID
[attrval
.upper()])
2358 elif attrname
== 'vlan-stats':
2359 self
.write_file('/sys/class/net/%s/bridge/vlan_stats_enabled'
2360 % bridgename
, attrval
)
2361 elif attrname
== 'mcstats':
2362 self
.write_file('/sys/class/net/%s/bridge/multicast_stats_enabled'
2363 % bridgename
, attrval
)
2365 if not LinkUtils
.bridge_utils_is_installed
:
2367 cmd
= '%s set%s %s %s' % (utils
.brctl_cmd
,
2368 attrname
, bridgename
, attrval
)
2369 utils
.exec_command(cmd
)
2371 def get_bridge_attrs(self
, bridgename
):
2372 attrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo'])
2374 for key
, value
in attrs
.items():
2375 if type(key
) == str:
2376 no_ints_attrs
[key
] = value
2377 return no_ints_attrs
2379 def get_bridgeport_attrs(self
, bridgename
, bridgeportname
):
2380 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2383 def get_bridgeport_attr(self
, bridgename
, bridgeportname
, attrname
):
2384 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2385 bridgeportname
, attrname
])
2388 def bridge_set_stp(bridge
, stp_state
):
2389 if not LinkUtils
.bridge_utils_is_installed
:
2391 utils
.exec_command('%s stp %s %s' % (utils
.brctl_cmd
, bridge
, stp_state
))
2393 def bridge_get_stp(self
, bridge
):
2394 sysfs_stpstate
= '/sys/class/net/%s/bridge/stp_state' % bridge
2395 if not os
.path
.exists(sysfs_stpstate
):
2397 stpstate
= self
.read_file_oneline(sysfs_stpstate
)
2401 if int(stpstate
) > 0:
2403 elif int(stpstate
) == 0:
2409 def _conv_value_to_user(s
):
2416 def read_value_from_sysfs(self
, filename
, preprocess_func
):
2417 value
= self
.read_file_oneline(filename
)
2420 return preprocess_func(value
)
2423 def bridge_set_ageing(bridge
, ageing
):
2424 if not LinkUtils
.bridge_utils_is_installed
:
2426 utils
.exec_command('%s setageing %s %s' % (utils
.brctl_cmd
, bridge
, ageing
))
2428 def bridge_get_ageing(self
, bridge
):
2429 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/ageing_time'
2430 % bridge
, self
._conv
_value
_to
_user
)
2433 def set_bridgeprio(bridge
, prio
):
2434 if not LinkUtils
.bridge_utils_is_installed
:
2436 utils
.exec_command('%s setbridgeprio %s %s' % (utils
.brctl_cmd
, bridge
, prio
))
2438 def get_bridgeprio(self
, bridge
):
2439 return self
.read_file_oneline(
2440 '/sys/class/net/%s/bridge/priority' % bridge
)
2443 def bridge_set_fd(bridge
, fd
):
2444 if not LinkUtils
.bridge_utils_is_installed
:
2446 utils
.exec_command('%s setfd %s %s' % (utils
.brctl_cmd
, bridge
, fd
))
2448 def bridge_get_fd(self
, bridge
):
2449 return self
.read_value_from_sysfs(
2450 '/sys/class/net/%s/bridge/forward_delay'
2451 % bridge
, self
._conv
_value
_to
_user
)
2453 def bridge_set_gcint(self
, bridge
, gcint
):
2454 raise Exception('set_gcint not implemented')
2457 def bridge_set_hello(bridge
, hello
):
2458 if not LinkUtils
.bridge_utils_is_installed
:
2460 utils
.exec_command('%s sethello %s %s' % (utils
.brctl_cmd
, bridge
, hello
))
2462 def bridge_get_hello(self
, bridge
):
2463 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/hello_time'
2464 % bridge
, self
._conv
_value
_to
_user
)
2467 def bridge_set_maxage(bridge
, maxage
):
2468 if not LinkUtils
.bridge_utils_is_installed
:
2470 utils
.exec_command('%s setmaxage %s %s' % (utils
.brctl_cmd
, bridge
, maxage
))
2472 def bridge_get_maxage(self
, bridge
):
2473 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/max_age'
2474 % bridge
, self
._conv
_value
_to
_user
)
2477 def bridge_set_pathcost(bridge
, port
, pathcost
):
2478 if not LinkUtils
.bridge_utils_is_installed
:
2480 utils
.exec_command('%s setpathcost %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, pathcost
))
2482 def bridge_get_pathcost(self
, bridge
, port
):
2483 return self
.read_file_oneline('/sys/class/net/%s/brport/path_cost'
2487 def bridge_set_portprio(bridge
, port
, prio
):
2488 if not LinkUtils
.bridge_utils_is_installed
:
2490 utils
.exec_command('%s setportprio %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, prio
))
2492 def bridge_get_portprio(self
, bridge
, port
):
2493 return self
.read_file_oneline('/sys/class/net/%s/brport/priority'
2497 def bridge_set_hashmax(bridge
, hashmax
):
2498 if not LinkUtils
.bridge_utils_is_installed
:
2500 utils
.exec_command('%s sethashmax %s %s' % (utils
.brctl_cmd
, bridge
, hashmax
))
2502 def bridge_get_hashmax(self
, bridge
):
2503 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_max'
2507 def bridge_set_hashel(bridge
, hashel
):
2508 if not LinkUtils
.bridge_utils_is_installed
:
2510 utils
.exec_command('%s sethashel %s %s' % (utils
.brctl_cmd
, bridge
, hashel
))
2512 def bridge_get_hashel(self
, bridge
):
2513 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_elasticity'
2517 def bridge_set_mclmc(bridge
, mclmc
):
2518 if not LinkUtils
.bridge_utils_is_installed
:
2520 utils
.exec_command('%s setmclmc %s %s' % (utils
.brctl_cmd
, bridge
, mclmc
))
2522 def bridge_get_mclmc(self
, bridge
):
2523 return self
.read_file_oneline(
2524 '/sys/class/net/%s/bridge/multicast_last_member_count'
2528 def bridge_set_mcrouter(bridge
, mcrouter
):
2529 if not LinkUtils
.bridge_utils_is_installed
:
2531 utils
.exec_command('%s setmcrouter %s %s' % (utils
.brctl_cmd
, bridge
, mcrouter
))
2533 def bridge_get_mcrouter(self
, bridge
):
2534 return self
.read_file_oneline(
2535 '/sys/class/net/%s/bridge/multicast_router' % bridge
)
2538 def bridge_set_mcsnoop(bridge
, mcsnoop
):
2539 if not LinkUtils
.bridge_utils_is_installed
:
2541 utils
.exec_command('%s setmcsnoop %s %s' % (utils
.brctl_cmd
, bridge
, mcsnoop
))
2543 def bridge_get_mcsnoop(self
, bridge
):
2544 return self
.read_file_oneline(
2545 '/sys/class/net/%s/bridge/multicast_snooping' % bridge
)
2548 def bridge_set_mcsqc(bridge
, mcsqc
):
2549 if not LinkUtils
.bridge_utils_is_installed
:
2551 utils
.exec_command('%s setmcsqc %s %s' % (utils
.brctl_cmd
, bridge
, mcsqc
))
2553 def bridge_get_mcsqc(self
, bridge
):
2554 return self
.read_file_oneline(
2555 '/sys/class/net/%s/bridge/multicast_startup_query_count'
2559 def bridge_set_mcqifaddr(bridge
, mcqifaddr
):
2560 if not LinkUtils
.bridge_utils_is_installed
:
2562 utils
.exec_command('%s setmcqifaddr %s %s' % (utils
.brctl_cmd
, bridge
, mcqifaddr
))
2564 def bridge_get_mcqifaddr(self
, bridge
):
2565 return self
.read_file_oneline(
2566 '/sys/class/net/%s/bridge/multicast_startup_query_use_ifaddr'
2570 def bridge_set_mcquerier(bridge
, mcquerier
):
2571 if not LinkUtils
.bridge_utils_is_installed
:
2573 utils
.exec_command('%s setmcquerier %s %s' % (utils
.brctl_cmd
, bridge
, mcquerier
))
2575 def bridge_get_mcquerier(self
, bridge
):
2576 return self
.read_file_oneline(
2577 '/sys/class/net/%s/bridge/multicast_querier' % bridge
)
2579 def bridge_set_mcqv4src(self
, bridge
, vlan
, mcquerier
):
2583 self
.logger
.info('%s: set mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2585 if vlan
== 0 or vlan
> 4095:
2586 self
.logger
.warn('mcqv4src vlan \'%d\' invalid range' % vlan
)
2589 ip
= mcquerier
.split('.')
2591 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2594 if not k
.isdigit() or int(k
, 10) < 0 or int(k
, 10) > 255:
2595 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2598 if not LinkUtils
.bridge_utils_is_installed
:
2601 utils
.exec_command('%s setmcqv4src %s %d %s' %
2602 (utils
.brctl_cmd
, bridge
, vlan
, mcquerier
))
2604 def bridge_del_mcqv4src(self
, bridge
, vlan
):
2605 if not LinkUtils
.bridge_utils_is_installed
:
2610 self
.logger
.info('%s: del mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2612 utils
.exec_command('%s delmcqv4src %s %d' % (utils
.brctl_cmd
, bridge
, vlan
))
2614 def bridge_get_mcqv4src(self
, bridge
, vlan
=None):
2615 if not LinkUtils
.bridge_utils_is_installed
:
2617 if not self
.supported_command
['showmcqv4src']:
2621 mcqout
= utils
.exec_command('%s showmcqv4src %s' %
2622 (utils
.brctl_cmd
, bridge
))
2623 except Exception as e
:
2625 if 'never heard' in s
:
2626 msg
= ('%s showmcqv4src: skipping unsupported command'
2628 self
.logger
.info(msg
)
2629 self
.supported_command
['showmcqv4src'] = False
2634 mcqlines
= mcqout
.splitlines()
2635 for l
in mcqlines
[1:]:
2637 k
, d
, v
= l
.split('\t')
2642 return mcqv4src
.get(vlan
)
2645 def bridge_get_mcqv4src_sysfs(self
, bridge
, vlan
=None):
2646 if not LinkUtils
.bridge_utils_is_installed
:
2648 if not self
.supported_command
['showmcqv4src']:
2650 if ifupdownflags
.flags
.PERFMODE
:
2654 filename
= '/sys/class/net/%s/bridge/multicast_v4_queriers' % bridge
2655 if os
.path
.exists(filename
):
2656 for line
in self
.read_file(filename
) or []:
2657 vlan_id
, ip
= line
.split('=')
2658 mcqv4src
[vlan_id
] = ip
.strip()
2659 except Exception as e
:
2661 msg
= ('%s showmcqv4src: skipping unsupported command'
2663 self
.logger
.info(msg
)
2664 self
.supported_command
['showmcqv4src'] = False
2667 return mcqv4src
.get(vlan
)
2671 def bridge_set_mclmi(bridge
, mclmi
):
2672 if not LinkUtils
.bridge_utils_is_installed
:
2674 utils
.exec_command('%s setmclmi %s %s' % (utils
.brctl_cmd
, bridge
, mclmi
))
2676 def bridge_get_mclmi(self
, bridge
):
2677 return self
.read_file_oneline(
2678 '/sys/class/net/%s/bridge/multicast_last_member_interval'
2682 def bridge_set_mcmi(bridge
, mcmi
):
2683 if not LinkUtils
.bridge_utils_is_installed
:
2685 utils
.exec_command('%s setmcmi %s %s' % (utils
.brctl_cmd
, bridge
, mcmi
))
2687 def bridge_get_mcmi(self
, bridge
):
2688 return self
.read_file_oneline(
2689 '/sys/class/net/%s/bridge/multicast_membership_interval'
2693 def bridge_exists(bridge
):
2694 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
2697 def is_bridge_port(ifacename
):
2698 return os
.path
.exists('/sys/class/net/%s/brport' % ifacename
)
2701 def bridge_port_exists(bridge
, bridgeportname
):
2703 return os
.path
.exists('/sys/class/net/%s/brif/%s' % (bridge
, bridgeportname
))
2708 def get_bridge_ports(bridgename
):
2710 return os
.listdir('/sys/class/net/%s/brif/' % bridgename
)
2714 def reset_addr_cache(self
, ifname
):
2716 linkCache
.links
[ifname
]['addrs'] = {}
2717 self
.logger
.debug('%s: reset address cache' % ifname
)
2721 def get_ipv6_addrgen_mode(self
, ifname
):
2723 return self
._cache
_get
('link', [ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
]
2725 # default to 0 (eui64)
2728 def ipv6_addrgen(self
, ifname
, addrgen
, link_created
):
2730 # IFLA_INET6_ADDR_GEN_MODE values:
2733 if self
._link
_cache
_get
([ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
] == addrgen
:
2734 self
.logger
.debug('%s: ipv6 addrgen already %s' % (ifname
, 'off' if addrgen
else 'on'))
2737 disabled_ipv6
= self
.read_file_oneline('/proc/sys/net/ipv6/conf/%s/disable_ipv6' % ifname
)
2738 if not disabled_ipv6
or int(disabled_ipv6
) == 1:
2739 self
.logger
.info('%s: cannot set addrgen: ipv6 is disabled on this device' % ifname
)
2742 if int(self
._link
_cache
_get
([ifname
, 'mtu'])) < 1280:
2743 self
.logger
.info('%s: ipv6 addrgen is disabled on device with MTU '
2744 'lower than 1280: cannot set addrgen %s' % (ifname
, 'off' if addrgen
else 'on'))
2746 except (KeyError, TypeError):
2747 self
.logger
.debug('%s: ipv6 addrgen probably not supported or disabled on this device' % ifname
)
2752 if not link_created
:
2753 # When setting addrgenmode it is necessary to flap the macvlan
2754 # device. After flapping the device we also need to re-add all
2755 # the user configuration. The best way to add the user config
2756 # is to flush our internal address cache
2757 self
.reset_addr_cache(ifname
)
2759 cmd
= 'link set dev %s addrgenmode %s' % (ifname
, Link
.ifla_inet6_addr_gen_mode_dict
.get(addrgen
))
2761 is_link_up
= self
.is_link_up(ifname
)
2764 self
.link_down(ifname
)
2766 #if LinkUtils.ipbatch:
2767 # self.add_to_batch(cmd)
2769 # because this command might fail on older kernel its better to not batch it
2770 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
2773 self
.link_up(ifname
)