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 string
import maketrans
17 from ipaddr
import IPNetwork
, IPv6Network
20 import ifupdown2
.ifupdown
.statemanager
as statemanager
21 import ifupdown2
.ifupdown
.ifupdownflags
as ifupdownflags
23 from ifupdown2
.nlmanager
.nlmanager
import Link
, Route
25 from ifupdown2
.ifupdown
.iface
import *
26 from ifupdown2
.ifupdown
.utils
import utils
27 from ifupdown2
.ifupdown
.netlink
import netlink
29 from ifupdown2
.ifupdownaddons
.utilsbase
import utilsBase
30 from ifupdown2
.ifupdownaddons
.cache
import linkCache
, MSTPAttrsCache
32 import ifupdown
.ifupdownflags
as ifupdownflags
33 import ifupdown
.statemanager
as statemanager
35 from nlmanager
.nlmanager
import Link
, Route
37 from ifupdown
.iface
import *
38 from ifupdown
.utils
import utils
39 from ifupdown
.netlink
import netlink
41 from ifupdownaddons
.utilsbase
import utilsBase
42 from ifupdownaddons
.cache
import linkCache
, MSTPAttrsCache
45 class LinkUtils(utilsBase
):
47 This class contains helper methods to cache and manipulate interfaces through
48 non-netlink APIs (sysfs, iproute2, brctl...)
50 _CACHE_FILL_DONE
= False
57 bridge_utils_is_installed
= os
.path
.exists(utils
.brctl_cmd
)
58 bridge_utils_missing_warning
= True
60 DEFAULT_IP_METRIC
= 1024
61 ADDR_METRIC_SUPPORT
= None
63 mac_translate_tab
= maketrans(":.-,", " ")
65 def __init__(self
, *args
, **kargs
):
66 utilsBase
.__init
__(self
, *args
, **kargs
)
68 self
.supported_command
= {
69 '%s -c -json vlan show' % utils
.bridge_cmd
: True,
72 self
.bridge_vlan_cache
= {}
73 self
.bridge_vlan_cache_fill_done
= False
75 if not ifupdownflags
.flags
.PERFMODE
and not LinkUtils
._CACHE
_FILL
_DONE
:
78 if LinkUtils
.ADDR_METRIC_SUPPORT
is None:
80 cmd
= [utils
.ip_cmd
, 'addr', 'help']
81 self
.logger
.info('executing %s addr help' % utils
.ip_cmd
)
83 process
= subprocess
.Popen(cmd
, stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
)
84 stdout
, stderr
= process
.communicate()
85 LinkUtils
.ADDR_METRIC_SUPPORT
= '[ metric METRIC ]' in stderr
or ''
86 self
.logger
.info('address metric support: %s' % ('OK' if LinkUtils
.ADDR_METRIC_SUPPORT
else 'KO'))
88 LinkUtils
.ADDR_METRIC_SUPPORT
= False
89 self
.logger
.info('address metric support: KO')
92 def mac_str_to_int(cls
, mac
):
95 for n
in mac
.translate(cls
.mac_translate_tab
).split():
100 def addr_metric_support(cls
):
101 return cls
.ADDR_METRIC_SUPPORT
104 def get_default_ip_metric(cls
):
105 return cls
.DEFAULT_IP_METRIC
109 LinkUtils
._CACHE
_FILL
_DONE
= False
110 LinkUtils
.ipbatchbuf
= ''
111 LinkUtils
.ipbatch
= False
112 LinkUtils
.ipbatch_pause
= False
114 def _fill_cache(self
):
115 if not LinkUtils
._CACHE
_FILL
_DONE
:
118 LinkUtils
._CACHE
_FILL
_DONE
= True
123 def _get_vland_id(citems
, i
, warn
):
126 index
= sub
.index('id')
128 return sub
[index
+ 1]
131 raise Exception('invalid use of \'vlan\' keyword')
134 def _link_fill(self
, ifacename
=None, refresh
=False):
135 """ fills cache with link information
137 if ifacename argument given, fill cache for ifacename, else
138 fill cache for all interfaces in the system
141 if LinkUtils
._CACHE
_FILL
_DONE
and not refresh
:
144 # if ifacename already present, return
145 if (ifacename
and not refresh
and
146 linkCache
.get_attr([ifacename
, 'ifflag'])):
153 [linkCache
.update_attrdict([ifname
], linkattrs
)
154 for ifname
, linkattrs
in netlink
.link_dump(ifacename
).items()]
155 except Exception as e
:
156 self
.logger
.info('%s' % str(e
))
157 # this netlink call replaces the call to _link_fill_iproute2_cmd()
158 # We shouldn't have netlink calls in the iproute2 module, this will
159 # be removed in the future. We plan to release, a flexible backend
160 # (netlink+iproute2) by default we will use netlink backend but with
161 # a CLI arg we can switch to iproute2 backend.
162 # Until we decide to create this "backend" switch capability,
163 # we have to put the netlink call inside the iproute2 module.
165 self
._link
_fill
_iproute
2_cmd
(ifacename
, refresh
)
167 self
._fill
_bond
_info
(ifacename
)
168 self
._fill
_bridge
_info
(ifacename
)
170 def _fill_bridge_info(self
, ifacename
):
176 cache_dict
= {ifacename
: linkCache
.links
.get(ifacename
, {})}
178 cache_dict
= linkCache
.links
180 for ifname
, obj
in cache_dict
.items():
181 slave_kind
= obj
.get('slave_kind')
182 if not slave_kind
and slave_kind
!= 'bridge':
185 info_slave_data
= obj
.get('info_slave_data')
186 if not info_slave_data
:
189 ifla_master
= obj
.get('master')
191 raise Exception('No master associated with bridge port %s' % ifname
)
194 Link
.IFLA_BRPORT_STATE
,
195 Link
.IFLA_BRPORT_COST
,
196 Link
.IFLA_BRPORT_PRIORITY
,
198 if nl_attr
not in info_slave_data
and LinkUtils
.bridge_utils_is_installed
:
199 self
._fill
_bridge
_info
_brctl
()
203 'pathcost': str(info_slave_data
.get(Link
.IFLA_BRPORT_COST
, 0)),
204 'fdelay': format(float(info_slave_data
.get(Link
.IFLA_BRPORT_FORWARD_DELAY_TIMER
, 0) / 100), '.2f'),
205 'portmcrouter': str(info_slave_data
.get(Link
.IFLA_BRPORT_MULTICAST_ROUTER
, 0)),
206 'portmcfl': str(info_slave_data
.get(Link
.IFLA_BRPORT_FAST_LEAVE
, 0)),
207 'portprio': str(info_slave_data
.get(Link
.IFLA_BRPORT_PRIORITY
, 0)),
208 'unicast-flood': str(info_slave_data
.get(Link
.IFLA_BRPORT_UNICAST_FLOOD
, 0)),
209 'multicast-flood': str(info_slave_data
.get(Link
.IFLA_BRPORT_MCAST_FLOOD
, 0)),
210 'learning': str(info_slave_data
.get(Link
.IFLA_BRPORT_LEARNING
, 0)),
211 'arp-nd-suppress': str(info_slave_data
.get(Link
.IFLA_BRPORT_ARP_SUPPRESS
, 0))
214 if ifla_master
in brports
:
215 brports
[ifla_master
][ifname
] = brport_attrs
217 brports
[ifla_master
] = {ifname
: brport_attrs
}
219 linkCache
.update_attrdict([ifla_master
, 'linkinfo', 'ports'], brports
[ifla_master
])
221 if LinkUtils
.bridge_utils_is_installed
:
222 self
._fill
_bridge
_info
_brctl
()
224 def _fill_bridge_info_brctl(self
):
225 brctlout
= utils
.exec_command('%s show' % utils
.brctl_cmd
)
229 for bline
in brctlout
.splitlines()[1:]:
230 bitems
= bline
.split()
234 linkCache
.update_attrdict([bitems
[0], 'linkinfo'],
237 linkCache
.update_attrdict([bitems
[0]],
238 {'linkinfo': {'stp': bitems
[2]}})
239 self
._bridge
_attrs
_fill
(bitems
[0])
241 def _bridge_attrs_fill(self
, bridgename
):
246 # Get all bridge attributes
247 # battrs['pathcost'] = broutlines[3].split('path cost')[1].strip()
250 battrs
['maxage'] = self
.read_file_oneline(
251 '/sys/class/net/%s/bridge/max_age' % bridgename
)
257 battrs
['hello'] = self
.read_file_oneline(
258 '/sys/class/net/%s/bridge/hello_time' % bridgename
)
263 battrs
['fd'] = self
.read_file_oneline(
264 '/sys/class/net/%s/bridge/forward_delay' % bridgename
)
269 battrs
['ageing'] = self
.read_file_oneline(
270 '/sys/class/net/%s/bridge/ageing_time' % bridgename
)
275 battrs
['mcrouter'] = self
.read_file_oneline(
276 '/sys/class/net/%s/bridge/multicast_router' % bridgename
)
281 battrs
['bridgeprio'] = self
.read_file_oneline(
282 '/sys/class/net/%s/bridge/priority' % bridgename
)
287 battrs
['vlan-protocol'] = VlanProtocols
.ID_TO_ETHERTYPES
[
288 self
.read_file_oneline(
289 '/sys/class/net/%s/bridge/vlan_protocol' % bridgename
)]
294 battrs
.update(self
._bridge
_get
_mcattrs
_from
_sysfs
(bridgename
))
298 # XXX: comment this out until mc attributes become available
301 # battrs['mciqc'] = broutlines[11].split('mc init query count')[1].strip()
302 # battrs['mclmt'] = broutlines[13].split('mc last member timer')[1].split()[0].strip()
304 self
.logger
.warn('%s: error while processing bridge attributes: %s' % (bridgename
, str(e
)))
307 linkCache
.update_attrdict([bridgename
, 'linkinfo'], battrs
)
309 names
= [os
.path
.basename(x
) for x
in glob
.glob("/sys/class/net/%s/brif/*" % bridgename
)]
314 bportattrs
['pathcost'] = self
.read_file_oneline(
315 '/sys/class/net/%s/brport/path_cost' % pname
)
316 bportattrs
['fdelay'] = self
.read_file_oneline(
317 '/sys/class/net/%s/brport/forward_delay_timer' % pname
)
318 bportattrs
['portmcrouter'] = self
.read_file_oneline(
319 '/sys/class/net/%s/brport/multicast_router' % pname
)
320 bportattrs
['portmcfl'] = self
.read_file_oneline(
321 '/sys/class/net/%s/brport/multicast_fast_leave' % pname
)
322 bportattrs
['portprio'] = self
.read_file_oneline(
323 '/sys/class/net/%s/brport/priority' % pname
)
324 bportattrs
['unicast-flood'] = self
.read_file_oneline(
325 '/sys/class/net/%s/brport/unicast_flood' % pname
)
326 bportattrs
['multicast-flood'] = self
.read_file_oneline(
327 '/sys/class/net/%s/brport/multicast_flood' % pname
)
328 bportattrs
['learning'] = self
.read_file_oneline(
329 '/sys/class/net/%s/brport/learning' % pname
)
330 bportattrs
['arp-nd-suppress'] = self
.read_file_oneline(
331 '/sys/class/net/%s/brport/neigh_suppress' % pname
)
333 #bportattrs['mcrouters'] = self.read_file_oneline(
334 # '/sys/class/net/%s/brport/multicast_router' % pname)
335 #bportattrs['mc fast leave'] = self.read_file_oneline(
336 # '/sys/class/net/%s/brport/multicast_fast_leave' % pname)
339 self
.logger
.warn('%s: error while processing bridge attributes: %s' % (bridgename
, str(e
)))
340 bports
[pname
] = bportattrs
341 linkCache
.update_attrdict([bridgename
, 'linkinfo', 'ports'], bports
)
343 _bridge_sysfs_mcattrs
= {
344 'mclmc': 'multicast_last_member_count',
345 'mcrouter': 'multicast_router',
346 'mcsnoop': 'multicast_snooping',
347 'mcsqc': 'multicast_startup_query_count',
348 'mcqifaddr': 'multicast_query_use_ifaddr',
349 'mcquerier': 'multicast_querier',
350 'hashel': 'hash_elasticity',
351 'hashmax': 'hash_max',
352 'mclmi': 'multicast_last_member_interval',
353 'mcmi': 'multicast_membership_interval',
354 'mcqpi': 'multicast_querier_interval',
355 'mcqi': 'multicast_query_interval',
356 'mcqri': 'multicast_query_response_interval',
357 'mcsqi': 'multicast_startup_query_interval',
358 'igmp-version': 'multicast_igmp_version',
359 'mld-version': 'multicast_mld_version',
360 'vlan-stats': 'vlan_stats_enabled',
361 'mcstats': 'multicast_stats_enabled',
364 def _bridge_get_mcattrs_from_sysfs(self
, bridgename
):
365 mcattrsdivby100
= ['mclmi', 'mcmi', 'mcqpi', 'mcqi', 'mcqri', 'mcsqi']
368 for m
, s
in self
._bridge
_sysfs
_mcattrs
.items():
369 n
= self
.read_file_oneline('/sys/class/net/%s/bridge/%s' % (bridgename
, s
))
370 if m
in mcattrsdivby100
:
375 self
.logger
.warn('error getting mc attr %s (%s)' % (m
, str(e
)))
381 def _fill_bond_info(self
, ifacename
):
382 bonding_masters
= self
.read_file_oneline('/sys/class/net/bonding_masters')
383 if not bonding_masters
:
386 bond_masters_list
= bonding_masters
.split()
389 if ifacename
in bond_masters_list
:
390 bond_masters_list
= [ifacename
]
392 # we want to refresh this interface only if it's a bond master
395 for bondname
in bond_masters_list
:
397 if bondname
not in linkCache
.links
:
398 linkCache
.set_attr([bondname
], {'linkinfo': {}})
399 linkCache
.set_attr([bondname
, 'linkinfo', 'slaves'],
400 self
.read_file_oneline('/sys/class/net/%s/bonding/slaves'
403 # if some attribute are missing we try to get the bond attributes via sysfs
404 bond_linkinfo
= linkCache
.links
[bondname
]['linkinfo']
405 for attr
in [Link
.IFLA_BOND_MODE
, Link
.IFLA_BOND_XMIT_HASH_POLICY
, Link
.IFLA_BOND_MIN_LINKS
]:
406 if attr
not in bond_linkinfo
:
407 self
._fill
_bond
_info
_sysfs
(bondname
)
408 # after we fill in the cache we can continue to the next bond
411 self
._fill
_bond
_info
_sysfs
(bondname
)
413 except Exception as e
:
414 self
.logger
.debug('LinkUtils: bond cache error: %s' % str(e
))
416 def _fill_bond_info_sysfs(self
, bondname
):
418 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_MIN_LINKS
],
419 self
.read_file_oneline(
420 '/sys/class/net/%s/bonding/min_links'
422 except Exception as e
:
423 self
.logger
.debug(str(e
))
426 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_MODE
],
427 self
.read_file_oneline('/sys/class/net/%s/bonding/mode'
428 % bondname
).split()[0])
429 except Exception as e
:
430 self
.logger
.debug(str(e
))
432 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_XMIT_HASH_POLICY
],
433 self
.read_file_oneline(
434 '/sys/class/net/%s/bonding/xmit_hash_policy'
435 % bondname
).split()[0])
436 except Exception as e
:
437 self
.logger
.debug(str(e
))
439 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_RATE
],
440 self
.read_file_oneline('/sys/class/net/%s/bonding/lacp_rate'
441 % bondname
).split()[1])
442 except Exception as e
:
443 self
.logger
.debug(str(e
))
445 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
],
446 self
.read_file_oneline('/sys/class/net/%s/bonding/ad_actor_sys_prio'
448 except Exception as e
:
449 self
.logger
.debug(str(e
))
451 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYSTEM
],
452 self
.read_file_oneline('/sys/class/net/%s/bonding/ad_actor_system'
454 except Exception as e
:
455 self
.logger
.debug(str(e
))
457 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_BYPASS
],
458 self
.read_file_oneline('/sys/class/net/%s/bonding/lacp_bypass'
459 % bondname
).split()[1])
460 except Exception as e
:
461 self
.logger
.debug(str(e
))
463 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_UPDELAY
],
464 self
.read_file_oneline('/sys/class/net/%s/bonding/updelay'
466 except Exception as e
:
467 self
.logger
.debug(str(e
))
469 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_DOWNDELAY
],
470 self
.read_file_oneline('/sys/class/net/%s/bonding/downdelay'
472 except Exception as e
:
473 self
.logger
.debug(str(e
))
476 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_USE_CARRIER
],
477 self
.read_file_oneline('/sys/class/net/%s/bonding/use_carrier' % bondname
))
478 except Exception as e
:
479 self
.logger
.debug(str(e
))
482 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_MIIMON
],
483 self
.read_file_oneline('/sys/class/net/%s/bonding/miimon' % 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_unsol_na' % bondname
))
490 except Exception as e
:
491 self
.logger
.debug(str(e
))
494 linkCache
.set_attr([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
],
495 self
.read_file_oneline('/sys/class/net/%s/bonding/num_grat_arp' % bondname
))
496 except Exception as e
:
497 self
.logger
.debug(str(e
))
500 def _link_fill_iproute2_cmd(self
, ifacename
=None, refresh
=False):
503 if LinkUtils
._CACHE
_FILL
_DONE
and not refresh
:
506 # if ifacename already present, return
507 if (ifacename
and not refresh
and
508 linkCache
.get_attr([ifacename
, 'ifflag'])):
512 cmdout
= self
.link_show(ifacename
=ifacename
)
515 for c
in cmdout
.splitlines():
517 ifnamenlink
= citems
[1].split('@')
518 if len(ifnamenlink
) > 1:
519 ifname
= ifnamenlink
[0]
520 iflink
= ifnamenlink
[1].strip(':')
522 ifname
= ifnamenlink
[0].strip(':')
525 linkattrs
['link'] = iflink
526 linkattrs
['ifindex'] = citems
[0].strip(':')
527 flags
= citems
[2].strip('<>').split(',')
528 linkattrs
['flags'] = flags
529 linkattrs
['ifflag'] = 'UP' if 'UP' in flags
else 'DOWN'
530 for i
in range(0, len(citems
)):
532 if citems
[i
] == 'mtu':
533 linkattrs
['mtu'] = citems
[i
+ 1]
534 elif citems
[i
] == 'state':
535 linkattrs
['state'] = citems
[i
+ 1]
536 elif citems
[i
] == 'link/ether':
537 linkattrs
['hwaddress'] = citems
[i
+ 1]
538 elif citems
[i
] in ['link/gre', 'link/ipip', 'link/sit', 'link/gre6', 'link/tunnel6', 'gretap']:
539 linkattrs
['kind'] = 'tunnel'
540 tunattrs
= {'mode': citems
[i
].split('/')[-1],
545 for j
in range(i
, len(citems
)):
546 if citems
[j
] == 'local':
547 tunattrs
['local'] = citems
[j
+ 1]
548 elif citems
[j
] == 'remote':
549 tunattrs
['endpoint'] = citems
[j
+ 1]
550 elif citems
[j
] == 'ttl':
551 tunattrs
['ttl'] = citems
[j
+ 1]
552 elif citems
[j
] == 'dev':
553 tunattrs
['physdev'] = citems
[j
+ 1]
554 elif citems
[j
] in ['vti', 'vti6', 'ip6gre', 'ipip6', 'ip6ip6']:
555 tunattrs
['mode'] = citems
[j
]
556 linkattrs
['linkinfo'] = tunattrs
558 elif citems
[i
] == 'link/ppp':
559 linkattrs
['kind'] = 'ppp'
560 elif citems
[i
] == 'vlan':
561 vlanid
= self
._get
_vland
_id
(citems
, i
, warn
)
563 linkattrs
['linkinfo'] = {'vlanid': vlanid
}
564 linkattrs
['kind'] = 'vlan'
565 elif citems
[i
] == 'dummy':
566 linkattrs
['kind'] = 'dummy'
567 elif citems
[i
] == 'vxlan' and citems
[i
+ 1] == 'id':
568 linkattrs
['kind'] = 'vxlan'
569 vattrs
= {'vxlanid': citems
[i
+ 2],
572 'ageing': citems
[i
+ 2],
574 for j
in range(i
+ 2, len(citems
)):
575 if citems
[j
] == 'local':
576 vattrs
['local'] = citems
[j
+ 1]
577 elif citems
[j
] == 'remote':
578 vattrs
['svcnode'] = citems
[j
+ 1]
579 elif citems
[j
] == 'ageing':
580 vattrs
['ageing'] = citems
[j
+ 1]
581 elif citems
[j
] == 'nolearning':
582 vattrs
['learning'] = 'off'
583 elif citems
[j
] == 'dev':
584 vattrs
['physdev'] = citems
[j
+ 1]
585 linkattrs
['linkinfo'] = vattrs
587 elif citems
[i
] == 'vrf' and citems
[i
+ 1] == 'table':
588 vattrs
= {'table': citems
[i
+ 2]}
589 linkattrs
['linkinfo'] = vattrs
590 linkattrs
['kind'] = 'vrf'
591 linkCache
.vrfs
[ifname
] = vattrs
593 elif citems
[i
] == 'veth':
594 linkattrs
['kind'] = 'veth'
595 elif citems
[i
] == 'vrf_slave':
596 linkattrs
['slave_kind'] = 'vrf_slave'
598 elif citems
[i
] == 'macvlan' and citems
[i
+ 1] == 'mode':
599 linkattrs
['kind'] = 'macvlan'
600 elif citems
[i
] == 'xfrm':
601 linkattrs
['kind'] = 'xfrm'
602 except Exception as e
:
604 self
.logger
.debug('%s: parsing error: id, mtu, state, '
605 'link/ether, vlan, dummy, vxlan, local, '
606 'remote, ageing, nolearning, vrf, table, '
607 'vrf_slave are reserved keywords: %s' %
610 # linkattrs['alias'] = self.read_file_oneline(
611 # '/sys/class/net/%s/ifalias' %ifname)
612 linkout
[ifname
] = linkattrs
613 [linkCache
.update_attrdict([ifname
], linkattrs
)
614 for ifname
, linkattrs
in linkout
.items()]
617 def _addr_filter(ifname
, addr
, scope
=None):
618 default_addrs
= ['127.0.0.1/8', '::1/128', '0.0.0.0']
619 if ifname
== 'lo' and addr
in default_addrs
:
621 if scope
and scope
== 'link':
625 def _addr_fill(self
, ifacename
=None, refresh
=False):
626 """ fills cache with address information
628 if ifacename argument given, fill cache for ifacename, else
629 fill cache for all interfaces in the system
631 if LinkUtils
._CACHE
_FILL
_DONE
and not refresh
:
634 # Check if ifacename is already full, in which case, return
635 if ifacename
and not refresh
:
636 linkCache
.get_attr([ifacename
, 'addrs'])
643 [linkCache
.update_attrdict([ifname
], linkattrs
)
644 for ifname
, linkattrs
in netlink
.addr_dump(ifname
=ifacename
).items()]
645 except Exception as e
:
646 self
.logger
.info(str(e
))
648 # this netlink call replaces the call to _addr_fill_iproute2_cmd()
649 # We shouldn't have netlink calls in the iproute2 module, this will
650 # be removed in the future. We plan to release, a flexible backend
651 # (netlink+iproute2) by default we will use netlink backend but with
652 # a CLI arg we can switch to iproute2 backend.
653 # Until we decide to create this "backend" switch capability,
654 # we have to put the netlink call inside the iproute2 module.
657 self
._addr
_fill
_iproute
2_cmd
(ifacename
, refresh
)
659 def _addr_fill_iproute2_cmd(self
, ifacename
=None, refresh
=False):
660 """ fills cache with address information
662 if ifacename argument given, fill cache for ifacename, else
663 fill cache for all interfaces in the system
666 if LinkUtils
._CACHE
_FILL
_DONE
and not refresh
:
669 # Check if ifacename is already full, in which case, return
670 if ifacename
and not refresh
:
671 linkCache
.get_attr([ifacename
, 'addrs'])
675 cmdout
= self
.addr_show(ifacename
=ifacename
)
678 for c
in cmdout
.splitlines():
680 ifnamenlink
= citems
[1].split('@')
681 if len(ifnamenlink
) > 1:
682 ifname
= ifnamenlink
[0]
684 ifname
= ifnamenlink
[0].strip(':')
685 if not linkout
.get(ifname
):
687 linkattrs
['addrs'] = OrderedDict({})
689 linkout
[ifname
].update(linkattrs
)
691 linkout
[ifname
] = linkattrs
692 if citems
[2] == 'inet':
693 if self
._addr
_filter
(ifname
, citems
[3], scope
=citems
[5]):
696 addrattrs
['scope'] = citems
[5]
697 addrattrs
['type'] = 'inet'
698 linkout
[ifname
]['addrs'][citems
[3]] = addrattrs
699 elif citems
[2] == 'inet6':
700 if self
._addr
_filter
(ifname
, citems
[3], scope
=citems
[5]):
702 if citems
[5] == 'link':
703 continue # skip 'link' addresses
705 addrattrs
['scope'] = citems
[5]
706 addrattrs
['type'] = 'inet6'
707 linkout
[ifname
]['addrs'][citems
[3]] = addrattrs
708 [linkCache
.update_attrdict([ifname
], linkattrs
)
709 for ifname
, linkattrs
in linkout
.items()]
711 def del_cache_entry(self
, ifname
):
713 del linkCache
.links
[ifname
]
717 def cache_get(self
, t
, attrlist
, refresh
=False):
718 return self
._cache
_get
(t
, attrlist
, refresh
)
720 def _cache_get(self
, t
, attrlist
, refresh
=False):
722 if ifupdownflags
.flags
.DRYRUN
:
724 if ifupdownflags
.flags
.CACHE
:
725 if self
._fill
_cache
():
726 # if we filled the cache, return new data
727 return linkCache
.get_attr(attrlist
)
729 return linkCache
.get_attr(attrlist
)
731 self
._link
_fill
(attrlist
[0], refresh
)
733 self
._addr
_fill
(attrlist
[0], refresh
)
735 self
._link
_fill
(attrlist
[0], refresh
)
736 self
._addr
_fill
(attrlist
[0], refresh
)
737 return linkCache
.get_attr(attrlist
)
739 self
.logger
.debug('_cache_get(%s) : [%s]' % (str(attrlist
), str(e
)))
742 def cache_check(self
, attrlist
, value
, refresh
=False):
743 return self
._cache
_check
('link', attrlist
, value
, refresh
=refresh
)
745 def _cache_check(self
, t
, attrlist
, value
, refresh
=False):
747 return self
._cache
_get
(t
, attrlist
, refresh
) == value
749 self
.logger
.debug('_cache_check(%s) : [%s]'
750 % (str(attrlist
), str(e
)))
753 def cache_update(self
, attrlist
, value
):
754 return self
._cache
_update
(attrlist
, value
)
757 def _cache_update(attrlist
, value
):
758 if ifupdownflags
.flags
.DRYRUN
:
761 if attrlist
[-1] == 'slaves':
762 linkCache
.append_to_attrlist(attrlist
, value
)
764 linkCache
.set_attr(attrlist
, value
)
769 def _cache_delete(attrlist
, value
=None):
770 if ifupdownflags
.flags
.DRYRUN
:
774 linkCache
.remove_from_attrlist(attrlist
, value
)
776 linkCache
.del_attr(attrlist
)
781 def _cache_invalidate():
782 linkCache
.invalidate()
783 LinkUtils
._CACHE
_FILL
_DONE
= False
787 LinkUtils
.ipbatcbuf
= ''
788 LinkUtils
.ipbatch
= True
789 LinkUtils
.ipbatch_pause
= False
792 def add_to_batch(cmd
):
793 LinkUtils
.ipbatchbuf
+= cmd
+ '\n'
797 LinkUtils
.ipbatch_pause
= True
801 LinkUtils
.ipbatch_pause
= False
803 def batch_commit(self
):
804 if not LinkUtils
.ipbatchbuf
:
805 LinkUtils
.ipbatchbuf
= ''
806 LinkUtils
.ipbatch
= False
807 LinkUtils
.ipbatch_pause
= False
810 utils
.exec_command('%s -force -batch -' % utils
.ip_cmd
,
811 stdin
=self
.ipbatchbuf
)
815 LinkUtils
.ipbatchbuf
= ''
816 LinkUtils
.ipbatch
= False
817 LinkUtils
.ipbatch_pause
= False
819 def bridge_batch_commit(self
):
820 if not LinkUtils
.ipbatchbuf
:
821 LinkUtils
.ipbatchbuf
= ''
822 LinkUtils
.ipbatch
= False
823 LinkUtils
.ipbatch_pause
= False
826 utils
.exec_command('%s -force -batch -'
827 % utils
.bridge_cmd
, stdin
=self
.ipbatchbuf
)
831 LinkUtils
.ipbatchbuf
= ''
832 LinkUtils
.ipbatch
= False
833 LinkUtils
.ipbatch_pause
= False
835 def addr_show(self
, ifacename
=None):
837 if not self
.link_exists(ifacename
):
839 return utils
.exec_commandl([utils
.ip_cmd
,
840 '-o', 'addr', 'show', 'dev', ifacename
])
842 return utils
.exec_commandl([utils
.ip_cmd
,
843 '-o', 'addr', 'show'])
846 def link_show(ifacename
=None):
848 return utils
.exec_commandl([utils
.ip_cmd
,
849 '-o', '-d', 'link', 'show', 'dev', ifacename
])
851 return utils
.exec_commandl([utils
.ip_cmd
,
852 '-o', '-d', 'link', 'show'])
854 def addr_add(self
, ifacename
, address
, broadcast
=None,
855 peer
=None, scope
=None, preferred_lifetime
=None, metric
=None):
858 cmd
= 'addr add %s' % address
860 cmd
+= ' broadcast %s' % broadcast
862 cmd
+= ' peer %s' % peer
864 cmd
+= ' scope %s' % scope
865 if preferred_lifetime
:
866 cmd
+= ' preferred_lft %s' % preferred_lifetime
867 cmd
+= ' dev %s' % ifacename
870 cmd
+= ' metric %s' % metric
872 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
873 self
.add_to_batch(cmd
)
875 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
876 self
._cache
_update
([ifacename
, 'addrs', address
], {})
878 def addr_del(self
, ifacename
, address
, broadcast
=None,
879 peer
=None, scope
=None):
880 """ Delete ipv4 address """
883 if not self
._cache
_get
('addr', [ifacename
, 'addrs', address
]):
885 cmd
= 'addr del %s' % address
887 cmd
+= ' broadcast %s' % broadcast
889 cmd
+= ' peer %s' % peer
891 cmd
+= ' scope %s' % scope
892 cmd
+= ' dev %s' % ifacename
893 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
894 self
._cache
_delete
([ifacename
, 'addrs', address
])
896 def addr_flush(self
, ifacename
):
897 cmd
= 'addr flush dev %s' % ifacename
898 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
899 self
.add_to_batch(cmd
)
901 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
902 self
._cache
_delete
([ifacename
, 'addrs'])
904 def del_addr_all(self
, ifacename
, skip_addrs
=[]):
907 runningaddrsdict
= self
.get_running_addrs(ifname
=ifacename
)
909 # XXX: ignore errors. Fix this to delete secondary addresses
911 [self
.addr_del(ifacename
, a
) for a
in
912 set(runningaddrsdict
.keys()).difference(skip_addrs
)]
917 def addr_get(self
, ifacename
, details
=True, refresh
=False):
918 addrs
= self
._cache
_get
('addr', [ifacename
, 'addrs'], refresh
=refresh
)
925 def get_running_addrs(self
, ifaceobj
=None, ifname
=None, details
=True, addr_virtual_ifaceobj
=None):
927 We now support addr with link scope. Since the kernel may add it's
928 own link address to some interfaces we need to filter them out and
929 make sure we only deal with the addresses set by ifupdown2.
931 To do so we look at the previous configuration made by ifupdown2
932 (with the help of the statemanager) together with the addresses
933 specified by the user in /etc/network/interfaces, these addresses
934 are then compared to the running state of the intf (ip addr show)
935 made via a netlink addr dump.
936 For each configured addresses of scope link, we check if it was
937 previously configured by ifupdown2 to create a final set of the
938 addresses watched by ifupdown2
940 if not ifaceobj
and not ifname
:
946 interface_name
= ifaceobj
.name
948 interface_name
= ifname
950 if addr_virtual_ifaceobj
:
951 for attr_name
in ["address-virtual", "vrrp"]:
952 for virtual
in addr_virtual_ifaceobj
.get_attr_value(attr_name
) or []:
953 for ip
in virtual
.split():
960 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(addr_virtual_ifaceobj
.name
)
961 for saved_ifaceobj
in saved_ifaceobjs
or []:
962 for virtual
in saved_ifaceobj
.get_attr_value(attr_name
) or []:
963 for ip
in virtual
.split():
971 for addr
in ifaceobj
.get_attr_value('address') or []:
972 config_addrs
.add(addr
)
974 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(interface_name
)
975 for saved_ifaceobj
in saved_ifaceobjs
or []:
976 for addr
in saved_ifaceobj
.get_attr_value('address') or []:
977 config_addrs
.add(addr
)
979 running_addrs
= OrderedDict()
980 cached_addrs
= self
.addr_get(interface_name
)
982 for addr
, addr_details
in cached_addrs
.items():
984 scope
= int(addr_details
['scope'])
988 addr_obj
= IPNetwork(addr
)
989 if isinstance(addr_obj
, IPv6Network
):
990 d
['family'] = 'inet6'
993 running_addrs
[addr
] = d
995 running_addrs
[addr
] = {}
997 if (scope
& Route
.RT_SCOPE_LINK
and addr
in config_addrs
) or not scope
& Route
.RT_SCOPE_LINK
:
998 running_addrs
[addr
] = addr_details
1003 return running_addrs
1004 return running_addrs
.keys()
1007 def compare_user_config_vs_running_state(running_addrs
, user_addrs
):
1011 for ip
in user_addrs
or []:
1014 if type(obj
) == IPv6Network
:
1020 for ip
in running_addrs
or []:
1021 running_ipobj
.append(IPNetwork(ip
))
1023 return running_ipobj
== (ip4
+ ip6
)
1025 def addr_add_multiple(self
, ifaceobj
, ifacename
, addrs
, purge_existing
=False, metric
=None):
1028 # if perfmode is not set and also if iface has no sibling
1029 # objects, purge addresses that are not present in the new
1031 runningaddrs
= self
.get_running_addrs(
1034 addr_virtual_ifaceobj
=ifaceobj
1036 addrs
= utils
.get_normalized_ip_addr(ifacename
, addrs
)
1038 if self
.compare_user_config_vs_running_state(runningaddrs
, addrs
):
1041 # if primary address is not same, there is no need to keep any.
1042 # reset all addresses
1043 if (addrs
and runningaddrs
and
1044 (addrs
[0] != runningaddrs
[0])):
1045 self
.del_addr_all(ifacename
)
1047 self
.del_addr_all(ifacename
, addrs
)
1048 except Exception, e
:
1049 self
.logger
.warning('%s: %s' % (ifacename
, str(e
)))
1052 self
.addr_add(ifacename
, a
, metric
=metric
)
1053 except Exception, e
:
1054 self
.logger
.error(str(e
))
1056 def _link_set_ifflag(self
, ifacename
, value
):
1057 # Dont look at the cache, the cache may have stale value
1058 # because link status can be changed by external
1059 # entity (One such entity is ifupdown main program)
1060 cmd
= 'link set dev %s %s' % (ifacename
, value
.lower())
1061 if LinkUtils
.ipbatch
:
1062 self
.add_to_batch(cmd
)
1064 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1066 def link_up(self
, ifacename
):
1067 self
._link
_set
_ifflag
(ifacename
, 'UP')
1069 def link_down(self
, ifacename
):
1070 self
._link
_set
_ifflag
(ifacename
, 'DOWN')
1072 def link_set(self
, ifacename
, key
, value
=None,
1073 force
=False, t
=None, state
=None):
1075 if (key
not in ['master', 'nomaster'] and
1076 self
._cache
_check
('link', [ifacename
, key
], value
)):
1078 cmd
= 'link set dev %s' % ifacename
1080 cmd
+= ' type %s' % t
1083 cmd
+= ' %s' % value
1085 cmd
+= ' %s' % state
1086 if LinkUtils
.ipbatch
:
1087 self
.add_to_batch(cmd
)
1089 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1090 if key
not in ['master', 'nomaster']:
1091 self
._cache
_update
([ifacename
, key
], value
)
1093 def link_set_hwaddress(self
, ifacename
, hwaddress
, force
=False, keep_down
=False):
1095 link_hwaddress
= self
.link_get_hwaddress(ifacename
)
1097 if self
.mac_str_to_int(link_hwaddress
) == self
.mac_str_to_int(hwaddress
):
1100 self
.link_down(ifacename
)
1101 cmd
= 'link set dev %s address %s' % (ifacename
, hwaddress
)
1102 if LinkUtils
.ipbatch
:
1103 self
.add_to_batch(cmd
)
1105 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1108 self
.link_up(ifacename
)
1109 self
._cache
_update
([ifacename
, 'hwaddress'], hwaddress
)
1112 def link_set_mtu(self
, ifacename
, mtu
):
1113 if ifupdownflags
.flags
.DRYRUN
:
1115 if not mtu
or not ifacename
: return
1116 self
.write_file('/sys/class/net/%s/mtu' % ifacename
, mtu
)
1117 self
._cache
_update
([ifacename
, 'mtu'], mtu
)
1119 def link_set_alias(self
, ifacename
, alias
):
1120 self
.write_file('/sys/class/net/%s/ifalias' % ifacename
,
1121 '\n' if not alias
else alias
)
1123 def link_get_alias(self
, ifacename
):
1124 return self
.read_file_oneline('/sys/class/net/%s/ifalias'
1127 def link_isloopback(self
, ifacename
):
1128 flags
= self
._cache
_get
('link', [ifacename
, 'flags'])
1131 if 'LOOPBACK' in flags
:
1135 def link_get_status(self
, ifacename
):
1136 return self
._cache
_get
('link', [ifacename
, 'ifflag'], refresh
=True)
1139 def route_add_gateway(ifacename
, gateway
, vrf
=None, metric
=None, onlink
=True):
1143 cmd
= '%s route add default via %s proto kernel' % (utils
.ip_cmd
,
1146 cmd
= ('%s route add table %s default via %s proto kernel' %
1147 (utils
.ip_cmd
, vrf
, gateway
))
1150 cmd
+= ' metric %s' % metric
1151 cmd
+= ' dev %s' % ifacename
1156 utils
.exec_command(cmd
)
1159 def route_del_gateway(ifacename
, gateway
, vrf
=None, metric
=None):
1164 cmd
= ('%s route del default via %s proto kernel' %
1165 (utils
.ip_cmd
, gateway
))
1167 cmd
= ('%s route del table %s default via %s proto kernel' %
1168 (utils
.ip_cmd
, vrf
, gateway
))
1170 cmd
+= ' metric %s' % metric
1171 cmd
+= ' dev %s' % ifacename
1172 utils
.exec_command(cmd
)
1175 def _get_vrf_id(ifacename
):
1177 return linkCache
.vrfs
[ifacename
]['table']
1179 dump
= netlink
.link_dump(ifacename
)
1181 [linkCache
.update_attrdict([ifname
], linkattrs
)
1182 for ifname
, linkattrs
in dump
.items()]
1184 if dump
and dump
.get(ifacename
, {}).get('kind') == 'vrf':
1185 vrf_table
= dump
.get(ifacename
, {}).get('linkinfo', {}).get('table')
1186 linkCache
.vrfs
[ifacename
] = {'table': vrf_table
}
1191 def fix_ipv6_route_metric(self
, ifaceobj
, macvlan_ifacename
, ips
):
1194 if ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
:
1196 for upper_iface
in ifaceobj
.upperifaces
:
1197 vrf_table
= self
._get
_vrf
_id
(upper_iface
)
1205 ip_network_obj
= IPNetwork(ip
)
1207 if type(ip_network_obj
) == IPv6Network
:
1208 route_prefix
= '%s/%d' % (ip_network_obj
.network
, ip_network_obj
.prefixlen
)
1211 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1212 LinkUtils
.add_to_batch('route del %s table %s dev %s' % (route_prefix
, vrf_table
, macvlan_ifacename
))
1214 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'table', vrf_table
, 'dev', macvlan_ifacename
])
1216 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1217 LinkUtils
.add_to_batch('route del %s dev %s' % (route_prefix
, macvlan_ifacename
))
1219 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'dev', macvlan_ifacename
])
1220 ip_route_del
.append((route_prefix
, vrf_table
))
1222 for ip
, vrf_table
in ip_route_del
:
1224 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1225 LinkUtils
.add_to_batch('route add %s table %s dev %s proto kernel metric 9999' % (ip
, vrf_table
, macvlan_ifacename
))
1227 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'table', vrf_table
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1229 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1230 LinkUtils
.add_to_batch('route add %s dev %s proto kernel metric 9999' % (ip
, macvlan_ifacename
))
1232 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1234 def link_create_vlan(self
, vlan_device_name
, vlan_raw_device
, vlanid
):
1235 if self
.link_exists(vlan_device_name
):
1237 utils
.exec_command('%s link add link %s name %s type vlan id %d' %
1239 vlan_raw_device
, vlan_device_name
, vlanid
))
1240 self
._cache
_update
([vlan_device_name
], {})
1242 def link_create_vlan_from_name(self
, vlan_device_name
):
1243 v
= vlan_device_name
.split('.')
1245 self
.logger
.warn('invalid vlan device name %s' % vlan_device_name
)
1247 self
.link_create_vlan(vlan_device_name
, v
[0], v
[1])
1249 def link_create_macvlan(self
, name
, linkdev
, mode
='private'):
1250 if self
.link_exists(name
):
1252 cmd
= ('link add link %s' % linkdev
+
1254 ' type macvlan mode %s' % mode
)
1255 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1256 self
.add_to_batch(cmd
)
1258 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1259 self
._cache
_update
([name
], {})
1261 def get_vxlan_peers(self
, dev
, svcnodeip
):
1262 cmd
= '%s fdb show brport %s' % (utils
.bridge_cmd
,
1266 ps
= subprocess
.Popen(shlex
.split(cmd
), stdout
=subprocess
.PIPE
, close_fds
=False)
1267 utils
.enable_subprocess_signal_forwarding(ps
, signal
.SIGINT
)
1268 output
= subprocess
.check_output(('grep', '00:00:00:00:00:00'), stdin
=ps
.stdout
)
1270 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1272 ppat
= re
.compile('\s+dst\s+(\d+.\d+.\d+.\d+)\s+')
1273 for l
in output
.split('\n'):
1275 if m
and m
.group(1) != svcnodeip
:
1276 cur_peers
.append(m
.group(1))
1278 self
.logger
.warn('error parsing ip link output')
1279 except subprocess
.CalledProcessError
as e
:
1280 if e
.returncode
!= 1:
1281 self
.logger
.error(str(e
))
1283 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1287 def tunnel_create(self
, tunnelname
, mode
, attrs
={}):
1288 """ generic link_create function """
1289 if self
.link_exists(tunnelname
):
1296 if mode
in ['gretap']:
1297 cmd
+= ' link add %s type %s' % (tunnelname
, mode
)
1299 cmd
+= ' tunnel add %s mode %s' % (tunnelname
, mode
)
1302 for k
, v
in attrs
.iteritems():
1306 if self
.ipbatch
and not self
.ipbatch_pause
:
1307 self
.add_to_batch(cmd
)
1309 utils
.exec_command('ip %s' % cmd
)
1310 self
._cache
_update
([tunnelname
], {})
1312 def tunnel_change(self
, tunnelname
, attrs
={}):
1313 """ tunnel change function """
1314 if not self
.link_exists(tunnelname
):
1316 cmd
= 'tunnel change'
1317 cmd
+= ' %s' %(tunnelname)
1319 for k
, v
in attrs
.iteritems():
1323 if self
.ipbatch
and not self
.ipbatch_pause
:
1324 self
.add_to_batch(cmd
)
1326 utils
.exec_command('ip %s' % cmd
)
1328 def link_create_vxlan(self
, name
, vxlanid
,
1336 if svcnodeip
and remoteips
:
1337 raise Exception("svcnodeip and remoteip is mutually exclusive")
1340 args
+= ' remote %s' % svcnodeip
1342 args
+= ' ageing %s' % ageing
1343 if learning
== 'off':
1344 args
+= ' nolearning'
1346 args
+= ' ttl %s' % ttl
1348 if self
.link_exists(name
):
1349 cmd
= 'link set dev %s type vxlan dstport %d' % (name
, LinkUtils
.VXLAN_UDP_PORT
)
1350 vxlanattrs
= self
.get_vxlandev_attrs(name
)
1351 # on ifreload do not overwrite anycast_ip to individual ip if clagd
1354 running_localtunnelip
= vxlanattrs
.get('local')
1355 if anycastip
and running_localtunnelip
and anycastip
== running_localtunnelip
:
1356 localtunnelip
= running_localtunnelip
1357 running_svcnode
= vxlanattrs
.get('svcnode')
1358 if running_svcnode
and not svcnodeip
:
1361 cmd
= 'link add dev %s type vxlan id %s dstport %d' % (name
, vxlanid
, LinkUtils
.VXLAN_UDP_PORT
)
1364 args
+= ' local %s' % localtunnelip
1367 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1368 self
.add_to_batch(cmd
)
1370 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1372 # XXX: update linkinfo correctly
1373 #self._cache_update([name], {})
1376 def link_exists(ifacename
):
1377 if ifupdownflags
.flags
.DRYRUN
:
1379 return os
.path
.exists('/sys/class/net/%s' % ifacename
)
1382 def link_exists_nodryrun(ifname
):
1383 return os
.path
.exists('/sys/class/net/%s' % ifname
)
1385 def link_get_ifindex(self
, ifacename
):
1386 if ifupdownflags
.flags
.DRYRUN
:
1388 return self
.read_file_oneline('/sys/class/net/%s/ifindex' % ifacename
)
1390 def is_vlan_device_by_name(self
, ifacename
):
1391 if re
.search(r
'\.', ifacename
):
1396 def link_add_macvlan(ifname
, macvlan_ifacename
, mode
):
1397 utils
.exec_commandl(['ip', 'link', 'add', 'link', ifname
, 'name', macvlan_ifacename
, 'type', 'macvlan', 'mode', mode
])
1400 def link_add_xfrm(ifname
, xfrm_name
, xfrm_id
):
1401 utils
.exec_commandl(['ip', 'link', 'add', xfrm_name
, 'type', 'xfrm', 'dev', ifname
, 'if_id', xfrm_id
])
1404 def route_add(route
):
1405 utils
.exec_command('%s route add %s' % (utils
.ip_cmd
,
1409 def route6_add(route
):
1410 utils
.exec_command('%s -6 route add %s' % (utils
.ip_cmd
,
1413 def get_vlandev_attrs(self
, ifacename
):
1414 return (self
._cache
_get
('link', [ifacename
, 'link']),
1415 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlanid']),
1416 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol']))
1418 def get_vlan_protocol(self
, ifacename
):
1419 return self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol'])
1421 def get_vxlandev_attrs(self
, ifacename
):
1422 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1424 def get_vxlandev_learning(self
, ifacename
):
1425 return self
._cache
_get
('link', [ifacename
, 'linkinfo', Link
.IFLA_VXLAN_LEARNING
])
1427 def set_vxlandev_learning(self
, ifacename
, learn
):
1429 utils
.exec_command('%s link set dev %s type vxlan learning' %
1430 (utils
.ip_cmd
, ifacename
))
1431 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'on')
1433 utils
.exec_command('%s link set dev %s type vxlan nolearning' %
1434 (utils
.ip_cmd
, ifacename
))
1435 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'off')
1437 def link_get_linkinfo_attrs(self
, ifacename
):
1438 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1440 def link_get_mtu(self
, ifacename
, refresh
=False):
1441 return self
._cache
_get
('link', [ifacename
, 'mtu'], refresh
=refresh
)
1443 def link_get_mtu_sysfs(self
, ifacename
):
1444 return self
.read_file_oneline('/sys/class/net/%s/mtu'
1447 def link_get_kind(self
, ifacename
):
1448 return self
._cache
_get
('link', [ifacename
, 'kind'])
1450 def link_get_slave_kind(self
, ifacename
):
1451 return self
._cache
_get
('link', [ifacename
, 'slave_kind'])
1453 def link_get_hwaddress(self
, ifacename
):
1454 address
= self
._cache
_get
('link', [ifacename
, 'hwaddress'])
1455 # newly created logical interface addresses dont end up in the cache
1456 # read hwaddress from sysfs file for these interfaces
1458 address
= self
.read_file_oneline('/sys/class/net/%s/address'
1462 def link_create(self
, ifacename
, t
, attrs
={}):
1463 """ generic link_create function """
1464 if self
.link_exists(ifacename
):
1467 cmd
+= ' name %s type %s' % (ifacename
, t
)
1469 for k
, v
in attrs
.iteritems():
1473 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1474 self
.add_to_batch(cmd
)
1476 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1477 self
._cache
_update
([ifacename
], {})
1479 def link_delete(self
, ifacename
):
1480 if not self
.link_exists(ifacename
):
1482 cmd
= 'link del %s' % ifacename
1483 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1484 self
.add_to_batch(cmd
)
1486 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1487 self
._cache
_invalidate
()
1489 def link_get_master(self
, ifacename
):
1490 sysfs_master_path
= '/sys/class/net/%s/master' % ifacename
1491 if os
.path
.exists(sysfs_master_path
):
1492 link_path
= os
.readlink(sysfs_master_path
)
1494 return os
.path
.basename(link_path
)
1498 return self
._cache
_get
('link', [ifacename
, 'master'])
1500 def get_brport_peer_link(self
, bridgename
):
1502 return self
._cache
_get
('link', [bridgename
, 'info_slave_data', Link
.IFLA_BRPORT_PEER_LINK
])
1507 def bridge_port_vids_add(bridgeportname
, vids
):
1508 [utils
.exec_command('%s vlan add vid %s dev %s' %
1510 v
, bridgeportname
)) for v
in vids
]
1513 def bridge_port_vids_del(bridgeportname
, vids
):
1516 [utils
.exec_command('%s vlan del vid %s dev %s' %
1518 v
, bridgeportname
)) for v
in vids
]
1521 def bridge_port_vids_flush(bridgeportname
, vid
):
1522 utils
.exec_command('%s vlan del vid %s dev %s' %
1524 vid
, bridgeportname
))
1527 def bridge_port_vids_get(bridgeportname
):
1528 bridgeout
= utils
.exec_command('%s vlan show dev %s' %
1533 brvlanlines
= bridgeout
.readlines()[2:]
1534 vids
= [l
.strip() for l
in brvlanlines
]
1535 return [v
for v
in vids
if v
]
1538 def bridge_port_vids_get_all():
1540 bridgeout
= utils
.exec_command('%s -c vlan show'
1544 brvlanlines
= bridgeout
.splitlines()
1546 for l
in brvlanlines
[1:]:
1547 if l
and not l
.startswith(' ') and not l
.startswith('\t'):
1549 brportname
= attrs
[0].strip()
1550 brvlaninfo
[brportname
] = {'pvid': None, 'vlan': []}
1551 l
= ' '.join(attrs
[1:])
1552 if not brportname
or not l
:
1556 brvlaninfo
[brportname
]['pvid'] = l
.split()[0]
1557 elif 'Egress Untagged' not in l
:
1558 brvlaninfo
[brportname
]['vlan'].append(l
)
1561 def bridge_port_vids_get_all_json(self
):
1562 if not self
.supported_command
['%s -c -json vlan show'
1563 % utils
.bridge_cmd
]:
1567 bridgeout
= utils
.exec_command('%s -c -json vlan show'
1570 self
.supported_command
['%s -c -json vlan show'
1571 % utils
.bridge_cmd
] = False
1572 self
.logger
.info('%s -c -json vlan show: skipping unsupported command'
1575 return self
.get_bridge_vlan_nojson()
1576 except Exception as e
:
1577 self
.logger
.info('bridge: get_bridge_vlan_nojson: %s' % str(e
))
1580 if not bridgeout
: return brvlaninfo
1582 vlan_json
= json
.loads(bridgeout
, encoding
="utf-8")
1583 except Exception, e
:
1584 self
.logger
.info('json loads failed with (%s)' % str(e
))
1588 if isinstance(vlan_json
, list):
1589 # newer iproute2 version changed the bridge vlan show output
1590 # ifupdown2 relies on the previous format, we have the convert
1591 # data into old format
1592 bridge_port_vids
= dict()
1594 for intf
in vlan_json
:
1595 bridge_port_vids
[intf
["ifname"]] = intf
["vlans"]
1597 return bridge_port_vids
1599 # older iproute2 version have different ways to dump vlans
1600 # ifupdown2 prefers the following syntax:
1604 # "flags": ["PVID", "Egress Untagged"]
1609 # "flags": ["PVID", "Egress Untagged"]
1613 except Exception as e
:
1614 self
.logger
.debug("bridge vlan show: Unknown json output: %s" % str(e
))
1618 def get_bridge_vlan_nojson():
1620 bridgeout
= utils
.exec_commandl([utils
.bridge_cmd
, '-c', 'vlan', 'show'])
1622 output
= [line
.split('\n') for line
in bridgeout
.split('\n\n')]
1623 output
[0] = output
[0][1:]
1631 prefix
, vlan
= entry
.split('\t')
1633 current_swp
= prefix
1634 vlan_json
[prefix
] = []
1638 v
['vlan'] = int(vlan
)
1642 start
, end
= vlan
.split('-')
1644 end
= end
[0:end
.index(' ')]
1645 v
['vlan'] = int(start
)
1646 v
['vlanEnd'] = int(end
)
1648 v
['vlan'] = int(vlan
[0:vlan
.index(' ')])
1651 flags
.append('PVID')
1652 if 'Egress Untagged' in vlan
:
1653 flags
.append('Egress Untagged')
1657 vlan_json
[current_swp
].append(v
)
1660 def bridge_vlan_cache_get(self
, ifacename
, refresh
=False):
1661 if not self
.bridge_vlan_cache_fill_done
or refresh
:
1662 self
.bridge_vlan_cache
= self
.bridge_port_vids_get_all_json()
1663 self
.bridge_vlan_cache_fill_done
= True
1664 return self
.bridge_vlan_cache
.get(ifacename
, {})
1666 def bridge_vlan_get_pvid(self
, ifacename
, refresh
=False):
1669 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1670 v
= vinfo
.get('vlan')
1671 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1676 def bridge_vlan_get_vids(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
1686 vEnd
= vinfo
.get('vlanEnd')
1688 vids
.extend(range(v
, vEnd
+ 1))
1693 def bridge_vlan_get_vids_n_pvid(self
, ifacename
, refresh
=False):
1697 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1698 v
= vinfo
.get('vlan')
1699 ispvid
= True if 'PVID' in vinfo
.get('flags', []) else False
1701 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1702 vEnd
= vinfo
.get('vlanEnd')
1704 vids
.extend(range(v
, vEnd
+ 1))
1709 def bridge_port_pvid_add(self
, bridgeportname
, pvid
):
1710 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1711 self
.add_to_batch('vlan add vid %s untagged pvid dev %s' %
1712 (pvid
, bridgeportname
))
1714 utils
.exec_command('%s vlan add vid %s untagged pvid dev %s' %
1716 pvid
, bridgeportname
))
1718 def bridge_port_pvid_del(self
, bridgeportname
, pvid
):
1719 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1720 self
.add_to_batch('vlan del vid %s untagged pvid dev %s' %
1721 (pvid
, bridgeportname
))
1723 utils
.exec_command('%s vlan del vid %s untagged pvid dev %s' %
1725 pvid
, bridgeportname
))
1727 def bridge_port_pvids_get(self
, bridgeportname
):
1728 return self
.read_file_oneline('/sys/class/net/%s/brport/pvid'
1731 def bridge_vids_add(self
, bridgeportname
, vids
, bridge
=True):
1732 target
= 'self' if bridge
else ''
1733 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1734 [self
.add_to_batch('vlan add vid %s dev %s %s' %
1735 (v
, bridgeportname
, target
)) for v
in vids
]
1737 [utils
.exec_command('%s vlan add vid %s dev %s %s' %
1739 v
, bridgeportname
, target
)) for v
in vids
]
1741 def bridge_vids_del(self
, bridgeportname
, vids
, bridge
=True):
1742 target
= 'self' if bridge
else ''
1743 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1744 [self
.add_to_batch('vlan del vid %s dev %s %s' %
1745 (v
, bridgeportname
, target
)) for v
in vids
]
1747 [utils
.exec_command('%s vlan del vid %s dev %s %s' %
1749 v
, bridgeportname
, target
)) for v
in vids
]
1752 def bridge_fdb_add(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1753 target
= 'self' if bridge
else ''
1756 vlan_str
= 'vlan %s ' % vlan
1760 dst_str
= 'dst %s ' % remote
1762 utils
.exec_command('%s fdb replace %s dev %s %s %s %s' %
1764 address
, dev
, vlan_str
, target
, dst_str
))
1767 def bridge_fdb_append(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1768 target
= 'self' if bridge
else ''
1771 vlan_str
= 'vlan %s ' % vlan
1775 dst_str
= 'dst %s ' % remote
1777 utils
.exec_command('%s fdb append %s dev %s %s %s %s' %
1779 address
, dev
, vlan_str
, target
, dst_str
))
1782 def bridge_fdb_del(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1783 target
= 'self' if bridge
else ''
1786 vlan_str
= 'vlan %s ' % vlan
1790 dst_str
= 'dst %s ' % remote
1791 utils
.exec_command('%s fdb del %s dev %s %s %s %s' %
1793 address
, dev
, vlan_str
, target
, dst_str
))
1795 def bridge_is_vlan_aware(self
, bridgename
):
1796 filename
= '/sys/class/net/%s/bridge/vlan_filtering' % bridgename
1797 if os
.path
.exists(filename
) and self
.read_file_oneline(filename
) == '1':
1802 def bridge_port_get_bridge_name(bridgeport
):
1803 filename
= '/sys/class/net/%s/brport/bridge' % bridgeport
1805 return os
.path
.basename(os
.readlink(filename
))
1810 def bridge_port_exists(bridge
, bridgeportname
):
1812 return os
.path
.exists('/sys/class/net/%s/brif/%s'
1813 % (bridge
, bridgeportname
))
1817 def bridge_fdb_show_dev(self
, dev
):
1820 output
= utils
.exec_command('%s fdb show dev %s'
1821 % (utils
.bridge_cmd
, dev
))
1823 for fdb_entry
in output
.splitlines():
1825 entries
= fdb_entry
.split()
1826 fdbs
.setdefault(entries
[2], []).append(entries
[0])
1828 self
.logger
.debug('%s: invalid fdb line \'%s\''
1835 def is_bridge(bridge
):
1836 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
1838 def is_link_up(self
, ifacename
):
1841 flags
= self
.read_file_oneline('/sys/class/net/%s/flags' % ifacename
)
1842 iflags
= int(flags
, 16)
1849 def ip_route_get_dev(self
, prefix
, vrf_master
=None):
1852 cmd
= '%s route get %s vrf %s' % (utils
.ip_cmd
, prefix
, vrf_master
)
1854 cmd
= '%s route get %s' % (utils
.ip_cmd
, prefix
)
1856 output
= utils
.exec_command(cmd
)
1858 rline
= output
.splitlines()[0]
1860 rattrs
= rline
.split()
1861 return rattrs
[rattrs
.index('dev') + 1]
1862 except Exception, e
:
1863 self
.logger
.debug('ip_route_get_dev: failed .. %s' % str(e
))
1867 def link_get_lowers(ifacename
):
1869 lowers
= glob
.glob("/sys/class/net/%s/lower_*" % ifacename
)
1872 return [os
.path
.basename(l
)[6:] for l
in lowers
]
1877 def link_get_uppers(ifacename
):
1879 uppers
= glob
.glob("/sys/class/net/%s/upper_*" % ifacename
)
1882 return [os
.path
.basename(u
)[6:] for u
in uppers
]
1886 def link_get_vrfs(self
):
1887 if not LinkUtils
._CACHE
_FILL
_DONE
:
1889 return linkCache
.vrfs
1892 def cache_get_info_slave(attrlist
):
1894 return linkCache
.get_attr(attrlist
)
1898 def get_brport_learning(self
, ifacename
):
1899 learn
= self
.read_file_oneline('/sys/class/net/%s/brport/learning'
1901 if learn
and learn
== '1':
1906 def get_brport_learning_bool(self
, ifacename
):
1907 return utils
.get_boolean_from_string(self
.read_file_oneline('/sys/class/net/%s/brport/learning' % ifacename
))
1909 def set_brport_learning(self
, ifacename
, learn
):
1911 return self
.write_file('/sys/class/net/%s/brport/learning'
1914 return self
.write_file('/sys/class/net/%s/brport/learning'
1917 #################################################################################
1918 ################################### BOND UTILS ##################################
1919 #################################################################################
1921 def _link_cache_get(self
, attrlist
, refresh
=False):
1922 return self
._cache
_get
('link', attrlist
, refresh
)
1924 def cache_delete(self
, attrlist
, value
=None):
1925 return self
._cache
_delete
(attrlist
, value
)
1927 def link_cache_get(self
, attrlist
, refresh
=False):
1928 return self
._link
_cache
_get
(attrlist
, refresh
)
1930 def link_cache_check(self
, attrlist
, value
, refresh
=False):
1931 return self
._link
_cache
_check
(attrlist
, value
, refresh
)
1933 def _link_cache_check(self
, attrlist
, value
, refresh
=False):
1935 return self
._link
_cache
_get
(attrlist
, refresh
) == value
1936 except Exception, e
:
1937 self
.logger
.debug('_cache_check(%s) : [%s]'
1938 % (str(attrlist
), str(e
)))
1943 Link
.IFLA_BOND_MODE
: 'mode',
1944 Link
.IFLA_BOND_MIIMON
: 'miimon',
1945 Link
.IFLA_BOND_USE_CARRIER
: 'use_carrier',
1946 Link
.IFLA_BOND_AD_LACP_RATE
: 'lacp_rate',
1947 Link
.IFLA_BOND_XMIT_HASH_POLICY
: 'xmit_hash_policy',
1948 Link
.IFLA_BOND_MIN_LINKS
: 'min_links',
1949 Link
.IFLA_BOND_NUM_PEER_NOTIF
: 'num_grat_arp',
1950 Link
.IFLA_BOND_AD_ACTOR_SYSTEM
: 'ad_actor_system',
1951 Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
: 'ad_actor_sys_prio',
1952 Link
.IFLA_BOND_AD_LACP_BYPASS
: 'lacp_bypass',
1953 Link
.IFLA_BOND_UPDELAY
: 'updelay',
1954 Link
.IFLA_BOND_DOWNDELAY
: 'downdelay',
1957 def bond_set_attrs_nl(self
, bondname
, ifla_info_data
):
1958 bond_attr_name
= 'None' # for log purpose (in case an exception raised)
1959 for nl_attr
, value
in ifla_info_data
.items():
1961 bond_attr_name
= self
.bondcmd_attrmap
[nl_attr
]
1962 file_path
= '/sys/class/net/%s/bonding/%s' % (bondname
, bond_attr_name
)
1963 if os
.path
.exists(file_path
):
1964 self
.write_file(file_path
, str(value
))
1965 except Exception as e
:
1966 exception_str
= '%s: %s %s: %s' % (bondname
, bond_attr_name
, value
, str(e
))
1967 if ifupdownflags
.flags
.FORCE
:
1968 self
.logger
.warning(exception_str
)
1970 self
.logger
.debug(exception_str
)
1972 def bond_set_attrs(self
, bondname
, attrdict
, prehook
):
1973 for attrname
, attrval
in attrdict
.items():
1974 if (self
._link
_cache
_check
([bondname
, 'linkinfo',
1975 attrname
], attrval
)):
1977 if (attrname
== 'mode'
1978 or attrname
== 'xmit_hash_policy'
1979 or attrname
== 'lacp_rate' or attrname
== 'min_links'):
1983 if ((attrname
not in ['lacp_rate',
1985 self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'], '802.3ad',
1987 self
.write_file('/sys/class/net/%s/bonding/%s'
1988 % (bondname
, attrname
), attrval
)
1989 except Exception, e
:
1990 if ifupdownflags
.flags
.FORCE
:
1991 self
.logger
.warn(str(e
))
1996 def bond_set_use_carrier(self
, bondname
, use_carrier
):
1997 if not use_carrier
or (use_carrier
!= '0' and use_carrier
!= '1'):
1999 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'use_carrier'],
2002 self
.write_file('/sys/class/net/%s' % bondname
+
2003 '/bonding/use_carrier', use_carrier
)
2004 self
._cache
_update
([bondname
, 'linkinfo',
2005 'use_carrier'], use_carrier
)
2007 def bond_get_use_carrier(self
, bondname
):
2008 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'use_carrier'])
2010 def bond_get_use_carrier_nl(self
, bondname
):
2011 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_USE_CARRIER
])
2013 def bond_set_xmit_hash_policy(self
, bondname
, hash_policy
, prehook
=None):
2014 valid_values
= ['layer2', 'layer3+4', 'layer2+3']
2017 if hash_policy
not in valid_values
:
2018 raise Exception('invalid hash policy value %s' % hash_policy
)
2019 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'xmit_hash_policy'],
2024 self
.write_file('/sys/class/net/%s' % bondname
+
2025 '/bonding/xmit_hash_policy', hash_policy
)
2026 self
._cache
_update
([bondname
, 'linkinfo', 'xmit_hash_policy'],
2029 def bond_get_xmit_hash_policy(self
, bondname
):
2030 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'xmit_hash_policy'])
2032 def bond_get_xmit_hash_policy_nl(self
, bondname
):
2033 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_XMIT_HASH_POLICY
])
2035 def bond_set_miimon(self
, bondname
, miimon
):
2036 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'miimon'],
2039 self
.write_file('/sys/class/net/%s' % bondname
+
2040 '/bonding/miimon', miimon
)
2041 self
._cache
_update
([bondname
, 'linkinfo', 'miimon'], miimon
)
2043 def bond_get_miimon(self
, bondname
):
2044 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'miimon'])
2046 def bond_get_miimon_nl(self
, bondname
):
2047 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIIMON
])
2049 def bond_set_mode(self
, bondname
, mode
, prehook
=None):
2050 valid_modes
= ['balance-rr', 'active-backup', 'balance-xor',
2051 'broadcast', '802.3ad', 'balance-tlb', 'balance-alb']
2054 if mode
not in valid_modes
:
2055 raise Exception('invalid mode %s' % mode
)
2056 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'],
2061 self
.write_file('/sys/class/net/%s' % bondname
+ '/bonding/mode', mode
)
2062 self
._cache
_update
([bondname
, 'linkinfo', 'mode'], mode
)
2064 def bond_get_mode(self
, bondname
):
2065 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'mode'])
2067 def bond_get_mode_nl(self
, bondname
):
2068 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MODE
])
2070 def bond_set_lacp_rate(self
, bondname
, lacp_rate
, prehook
=None, posthook
=None):
2071 if not lacp_rate
or (lacp_rate
!= '0' and lacp_rate
!= '1'):
2073 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_rate'],
2079 self
.write_file('/sys/class/net/%s' % bondname
+
2080 '/bonding/lacp_rate', lacp_rate
)
2086 self
._cache
_update
([bondname
, 'linkinfo',
2087 'lacp_rate'], lacp_rate
)
2089 def bond_get_lacp_rate(self
, bondname
):
2090 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_rate'])
2092 def bond_get_lacp_rate_nl(self
, bondname
):
2093 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_RATE
])
2095 def bond_set_lacp_bypass_allow(self
, bondname
, allow
, prehook
=None, posthook
=None):
2096 if self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_bypass'], allow
):
2101 self
.write_file('/sys/class/net/%s' % bondname
+
2102 '/bonding/lacp_bypass', allow
)
2108 self
._cache
_update
([bondname
, 'linkinfo',
2109 'lacp_bypass'], allow
)
2111 def bond_get_lacp_bypass_allow(self
, bondname
):
2112 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_bypass'])
2114 def bond_get_lacp_bypass_allow_nl(self
, bondname
):
2115 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_BYPASS
])
2117 def bond_set_min_links(self
, bondname
, min_links
, prehook
=None):
2118 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'min_links'],
2123 self
.write_file('/sys/class/net/%s/bonding/min_links' % bondname
,
2125 self
._cache
_update
([bondname
, 'linkinfo', 'min_links'], min_links
)
2127 def bond_get_min_links(self
, bondname
):
2128 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'min_links'])
2130 def get_min_links_nl(self
, bondname
):
2131 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIN_LINKS
])
2133 def bond_get_ad_actor_system(self
, bondname
):
2134 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_system'])
2136 def bond_get_ad_actor_system_nl(self
, bondname
):
2137 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYSTEM
])
2139 def bond_get_ad_actor_sys_prio(self
, bondname
):
2140 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_sys_prio'])
2142 def bond_get_ad_actor_sys_prio_nl(self
, bondname
):
2143 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
])
2145 def bond_get_num_unsol_na(self
, bondname
):
2146 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_unsol_na'])
2148 def bond_get_num_unsol_na_nl(self
, bondname
):
2149 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2151 def bond_get_num_grat_arp(self
, bondname
):
2152 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_grat_arp'])
2154 def bond_get_num_grat_arp_nl(self
, bondname
):
2155 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2157 def bond_get_updelay(self
, bondname
):
2158 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'updelay'])
2160 def bond_get_updelay_nl(self
, bondname
):
2161 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_UPDELAY
])
2163 def bond_get_downdelay(self
, bondname
):
2164 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'downdelay'])
2166 def bond_get_downdelay_nl(self
, bondname
):
2167 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_DOWNDELAY
])
2169 def bond_enslave_slave(self
, bondname
, slave
, prehook
=None, posthook
=None):
2170 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2171 if slaves
and slave
in slaves
:
2175 self
.write_file('/sys/class/net/%s' % bondname
+
2176 '/bonding/slaves', '+' + slave
)
2179 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slave
)
2181 def bond_remove_slave(self
, bondname
, slave
):
2182 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2183 if not slaves
or slave
not in slaves
:
2185 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2187 if not os
.path
.exists(sysfs_bond_path
):
2189 self
.write_file(sysfs_bond_path
, '-' + slave
)
2190 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'], slave
)
2192 def bond_remove_slaves_all(self
, bondname
):
2193 if not self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves']):
2196 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2199 with
open(sysfs_bond_path
, 'r') as f
:
2200 slaves
= f
.readline().strip().split()
2202 raise Exception('error reading slaves of bond %s (%s)' % (bondname
, str(e
)))
2203 for slave
in slaves
:
2204 self
.link_down(slave
)
2206 self
.bond_remove_slave(bondname
, slave
)
2207 except Exception, e
:
2208 if not ifupdownflags
.flags
.FORCE
:
2209 raise Exception('error removing slave %s from bond %s (%s)' % (slave
, bondname
, str(e
)))
2212 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'])
2215 def bond_load_bonding_module():
2216 return utils
.exec_command('%s -q bonding' % utils
.modprobe_cmd
)
2218 def create_bond(self
, bondname
):
2219 if self
.bond_exists(bondname
):
2221 # load_bonding_module() has already been run
2222 self
.write_file('/sys/class/net/bonding_masters', '+' + bondname
)
2223 self
._cache
_update
([bondname
], {})
2225 def delete_bond(self
, bondname
):
2226 if not os
.path
.exists('/sys/class/net/%s' % bondname
):
2228 self
.write_file('/sys/class/net/bonding_masters', '-' + bondname
)
2229 self
._cache
_delete
([bondname
])
2231 def bond_get_slaves(self
, bondname
):
2232 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2235 slavefile
= '/sys/class/net/%s/bonding/slaves' % bondname
2236 if os
.path
.exists(slavefile
):
2237 buf
= self
.read_file_oneline(slavefile
)
2239 slaves
= buf
.split()
2242 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slaves
)
2245 def bond_slave_exists(self
, bond
, slave
):
2246 slaves
= self
.bond_get_slaves(bond
)
2249 return slave
in slaves
2252 def bond_exists(bondname
):
2253 return os
.path
.exists('/sys/class/net/%s/bonding' % bondname
)
2255 #################################################################################
2256 ################################## BRIDGE UTILS #################################
2257 #################################################################################
2259 def create_bridge(self
, bridgename
):
2260 if not LinkUtils
.bridge_utils_is_installed
:
2262 if self
.bridge_exists(bridgename
):
2264 utils
.exec_command('%s addbr %s' % (utils
.brctl_cmd
, bridgename
))
2265 self
._cache
_update
([bridgename
], {})
2267 def delete_bridge(self
, bridgename
):
2268 if not LinkUtils
.bridge_utils_is_installed
:
2270 if not self
.bridge_exists(bridgename
):
2272 utils
.exec_command('%s delbr %s' % (utils
.brctl_cmd
, bridgename
))
2273 self
._cache
_invalidate
()
2275 def add_bridge_port(self
, bridgename
, bridgeportname
):
2276 """ Add port to bridge """
2277 if not LinkUtils
.bridge_utils_is_installed
:
2279 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2280 if ports
and ports
.get(bridgeportname
):
2282 utils
.exec_command('%s addif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2283 self
._cache
_update
([bridgename
, 'linkinfo', 'ports', bridgeportname
], {})
2285 def delete_bridge_port(self
, bridgename
, bridgeportname
):
2286 """ Delete port from bridge """
2287 if not LinkUtils
.bridge_utils_is_installed
:
2289 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2290 if not ports
or not ports
.get(bridgeportname
):
2292 utils
.exec_command('%s delif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2293 self
._cache
_delete
([bridgename
, 'linkinfo', 'ports', 'bridgeportname'])
2295 def set_bridgeport_attrs(self
, bridgename
, bridgeportname
, attrdict
):
2296 portattrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports', bridgeportname
])
2297 if portattrs
== None:
2299 for k
, v
in attrdict
.iteritems():
2300 if ifupdownflags
.flags
.CACHE
:
2301 curval
= portattrs
.get(k
)
2302 if curval
and curval
== v
:
2304 if k
== 'unicast-flood':
2305 self
.write_file('/sys/class/net/%s/brport/unicast_flood' % bridgeportname
, v
)
2306 elif k
== 'multicast-flood':
2307 self
.write_file('/sys/class/net/%s/brport/multicast_flood' % bridgeportname
, v
)
2308 elif k
== 'learning':
2309 self
.write_file('/sys/class/net/%s/brport/learning' % bridgeportname
, v
)
2310 elif k
== 'arp-nd-suppress':
2311 self
.write_file('/sys/class/net/%s/brport/neigh_suppress' % bridgeportname
, v
)
2313 if not LinkUtils
.bridge_utils_is_installed
:
2315 utils
.exec_command('%s set%s %s %s %s' % (utils
.brctl_cmd
, k
, bridgename
, bridgeportname
, v
))
2317 def set_bridgeport_attr(self
, bridgename
, bridgeportname
,
2319 if not LinkUtils
.bridge_utils_is_installed
:
2321 if self
._link
_cache
_check
([bridgename
, 'linkinfo', 'ports', bridgeportname
, attrname
], attrval
):
2323 utils
.exec_command('%s set%s %s %s %s' %
2330 def set_bridge_attrs(self
, bridgename
, attrdict
):
2331 for k
, v
in attrdict
.iteritems():
2334 if self
._link
_cache
_check
([bridgename
, 'linkinfo', k
], v
):
2337 if k
== 'igmp-version':
2338 self
.write_file('/sys/class/net/%s/bridge/'
2339 'multicast_igmp_version' % bridgename
, v
)
2340 elif k
== 'mld-version':
2341 self
.write_file('/sys/class/net/%s/bridge/'
2342 'multicast_mld_version' % bridgename
, v
)
2343 elif k
== 'vlan-protocol':
2344 self
.write_file('/sys/class/net/%s/bridge/'
2345 'vlan_protocol' % bridgename
,
2346 VlanProtocols
.ETHERTYPES_TO_ID
.get(v
.upper(),
2348 elif k
== 'vlan-stats':
2349 self
.write_file('/sys/class/net/%s/bridge/'
2350 'vlan_stats_enabled' % bridgename
, v
)
2351 elif k
== 'mcstats':
2352 self
.write_file('/sys/class/net/%s/bridge/'
2353 'multicast_stats_enabled' % bridgename
, v
)
2355 if not LinkUtils
.bridge_utils_is_installed
:
2357 cmd
= ('%s set%s %s %s' %
2358 (utils
.brctl_cmd
, k
, bridgename
, v
))
2359 utils
.exec_command(cmd
)
2360 except Exception, e
:
2361 self
.logger
.warn('%s: %s' % (bridgename
, str(e
)))
2364 def set_bridge_attr(self
, bridgename
, attrname
, attrval
):
2365 if self
._link
_cache
_check
([bridgename
, 'linkinfo', attrname
], attrval
):
2367 if attrname
== 'igmp-version':
2368 self
.write_file('/sys/class/net/%s/bridge/multicast_igmp_version'
2369 % bridgename
, attrval
)
2370 elif attrname
== 'mld-version':
2371 self
.write_file('/sys/class/net/%s/bridge/multicast_mld_version'
2372 % bridgename
, attrval
)
2373 elif attrname
== 'vlan-protocol':
2374 self
.write_file('/sys/class/net/%s/bridge/vlan_protocol'
2375 % bridgename
, VlanProtocols
.ETHERTYPES_TO_ID
[attrval
.upper()])
2376 elif attrname
== 'vlan-stats':
2377 self
.write_file('/sys/class/net/%s/bridge/vlan_stats_enabled'
2378 % bridgename
, attrval
)
2379 elif attrname
== 'mcstats':
2380 self
.write_file('/sys/class/net/%s/bridge/multicast_stats_enabled'
2381 % bridgename
, attrval
)
2383 if not LinkUtils
.bridge_utils_is_installed
:
2385 cmd
= '%s set%s %s %s' % (utils
.brctl_cmd
,
2386 attrname
, bridgename
, attrval
)
2387 utils
.exec_command(cmd
)
2389 def get_bridge_attrs(self
, bridgename
):
2390 attrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo'])
2392 for key
, value
in attrs
.items():
2393 if type(key
) == str:
2394 no_ints_attrs
[key
] = value
2395 return no_ints_attrs
2397 def get_bridgeport_attrs(self
, bridgename
, bridgeportname
):
2398 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2401 def get_bridgeport_attr(self
, bridgename
, bridgeportname
, attrname
):
2402 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2403 bridgeportname
, attrname
])
2406 def bridge_set_stp(bridge
, stp_state
):
2407 if not LinkUtils
.bridge_utils_is_installed
:
2409 utils
.exec_command('%s stp %s %s' % (utils
.brctl_cmd
, bridge
, stp_state
))
2411 def bridge_get_stp(self
, bridge
):
2412 sysfs_stpstate
= '/sys/class/net/%s/bridge/stp_state' % bridge
2413 if not os
.path
.exists(sysfs_stpstate
):
2415 stpstate
= self
.read_file_oneline(sysfs_stpstate
)
2419 if int(stpstate
) > 0:
2421 elif int(stpstate
) == 0:
2427 def _conv_value_to_user(s
):
2434 def read_value_from_sysfs(self
, filename
, preprocess_func
):
2435 value
= self
.read_file_oneline(filename
)
2438 return preprocess_func(value
)
2441 def bridge_set_ageing(bridge
, ageing
):
2442 if not LinkUtils
.bridge_utils_is_installed
:
2444 utils
.exec_command('%s setageing %s %s' % (utils
.brctl_cmd
, bridge
, ageing
))
2446 def bridge_get_ageing(self
, bridge
):
2447 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/ageing_time'
2448 % bridge
, self
._conv
_value
_to
_user
)
2451 def set_bridgeprio(bridge
, prio
):
2452 if not LinkUtils
.bridge_utils_is_installed
:
2454 utils
.exec_command('%s setbridgeprio %s %s' % (utils
.brctl_cmd
, bridge
, prio
))
2456 def get_bridgeprio(self
, bridge
):
2457 return self
.read_file_oneline(
2458 '/sys/class/net/%s/bridge/priority' % bridge
)
2461 def bridge_set_fd(bridge
, fd
):
2462 if not LinkUtils
.bridge_utils_is_installed
:
2464 utils
.exec_command('%s setfd %s %s' % (utils
.brctl_cmd
, bridge
, fd
))
2466 def bridge_get_fd(self
, bridge
):
2467 return self
.read_value_from_sysfs(
2468 '/sys/class/net/%s/bridge/forward_delay'
2469 % bridge
, self
._conv
_value
_to
_user
)
2471 def bridge_set_gcint(self
, bridge
, gcint
):
2472 raise Exception('set_gcint not implemented')
2475 def bridge_set_hello(bridge
, hello
):
2476 if not LinkUtils
.bridge_utils_is_installed
:
2478 utils
.exec_command('%s sethello %s %s' % (utils
.brctl_cmd
, bridge
, hello
))
2480 def bridge_get_hello(self
, bridge
):
2481 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/hello_time'
2482 % bridge
, self
._conv
_value
_to
_user
)
2485 def bridge_set_maxage(bridge
, maxage
):
2486 if not LinkUtils
.bridge_utils_is_installed
:
2488 utils
.exec_command('%s setmaxage %s %s' % (utils
.brctl_cmd
, bridge
, maxage
))
2490 def bridge_get_maxage(self
, bridge
):
2491 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/max_age'
2492 % bridge
, self
._conv
_value
_to
_user
)
2495 def bridge_set_pathcost(bridge
, port
, pathcost
):
2496 if not LinkUtils
.bridge_utils_is_installed
:
2498 utils
.exec_command('%s setpathcost %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, pathcost
))
2500 def bridge_get_pathcost(self
, bridge
, port
):
2501 return self
.read_file_oneline('/sys/class/net/%s/brport/path_cost'
2505 def bridge_set_portprio(bridge
, port
, prio
):
2506 if not LinkUtils
.bridge_utils_is_installed
:
2508 utils
.exec_command('%s setportprio %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, prio
))
2510 def bridge_get_portprio(self
, bridge
, port
):
2511 return self
.read_file_oneline('/sys/class/net/%s/brport/priority'
2515 def bridge_set_hashmax(bridge
, hashmax
):
2516 if not LinkUtils
.bridge_utils_is_installed
:
2518 utils
.exec_command('%s sethashmax %s %s' % (utils
.brctl_cmd
, bridge
, hashmax
))
2520 def bridge_get_hashmax(self
, bridge
):
2521 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_max'
2525 def bridge_set_hashel(bridge
, hashel
):
2526 if not LinkUtils
.bridge_utils_is_installed
:
2528 utils
.exec_command('%s sethashel %s %s' % (utils
.brctl_cmd
, bridge
, hashel
))
2530 def bridge_get_hashel(self
, bridge
):
2531 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_elasticity'
2535 def bridge_set_mclmc(bridge
, mclmc
):
2536 if not LinkUtils
.bridge_utils_is_installed
:
2538 utils
.exec_command('%s setmclmc %s %s' % (utils
.brctl_cmd
, bridge
, mclmc
))
2540 def bridge_get_mclmc(self
, bridge
):
2541 return self
.read_file_oneline(
2542 '/sys/class/net/%s/bridge/multicast_last_member_count'
2546 def bridge_set_mcrouter(bridge
, mcrouter
):
2547 if not LinkUtils
.bridge_utils_is_installed
:
2549 utils
.exec_command('%s setmcrouter %s %s' % (utils
.brctl_cmd
, bridge
, mcrouter
))
2551 def bridge_get_mcrouter(self
, bridge
):
2552 return self
.read_file_oneline(
2553 '/sys/class/net/%s/bridge/multicast_router' % bridge
)
2556 def bridge_set_mcsnoop(bridge
, mcsnoop
):
2557 if not LinkUtils
.bridge_utils_is_installed
:
2559 utils
.exec_command('%s setmcsnoop %s %s' % (utils
.brctl_cmd
, bridge
, mcsnoop
))
2561 def bridge_get_mcsnoop(self
, bridge
):
2562 return self
.read_file_oneline(
2563 '/sys/class/net/%s/bridge/multicast_snooping' % bridge
)
2566 def bridge_set_mcsqc(bridge
, mcsqc
):
2567 if not LinkUtils
.bridge_utils_is_installed
:
2569 utils
.exec_command('%s setmcsqc %s %s' % (utils
.brctl_cmd
, bridge
, mcsqc
))
2571 def bridge_get_mcsqc(self
, bridge
):
2572 return self
.read_file_oneline(
2573 '/sys/class/net/%s/bridge/multicast_startup_query_count'
2577 def bridge_set_mcqifaddr(bridge
, mcqifaddr
):
2578 if not LinkUtils
.bridge_utils_is_installed
:
2580 utils
.exec_command('%s setmcqifaddr %s %s' % (utils
.brctl_cmd
, bridge
, mcqifaddr
))
2582 def bridge_get_mcqifaddr(self
, bridge
):
2583 return self
.read_file_oneline(
2584 '/sys/class/net/%s/bridge/multicast_startup_query_use_ifaddr'
2588 def bridge_set_mcquerier(bridge
, mcquerier
):
2589 if not LinkUtils
.bridge_utils_is_installed
:
2591 utils
.exec_command('%s setmcquerier %s %s' % (utils
.brctl_cmd
, bridge
, mcquerier
))
2593 def bridge_get_mcquerier(self
, bridge
):
2594 return self
.read_file_oneline(
2595 '/sys/class/net/%s/bridge/multicast_querier' % bridge
)
2597 def bridge_set_mcqv4src(self
, bridge
, vlan
, mcquerier
):
2601 self
.logger
.info('%s: set mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2603 if vlan
== 0 or vlan
> 4095:
2604 self
.logger
.warn('mcqv4src vlan \'%d\' invalid range' % vlan
)
2607 ip
= mcquerier
.split('.')
2609 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2612 if not k
.isdigit() or int(k
, 10) < 0 or int(k
, 10) > 255:
2613 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2616 if not LinkUtils
.bridge_utils_is_installed
:
2619 utils
.exec_command('%s setmcqv4src %s %d %s' %
2620 (utils
.brctl_cmd
, bridge
, vlan
, mcquerier
))
2622 def bridge_del_mcqv4src(self
, bridge
, vlan
):
2623 if not LinkUtils
.bridge_utils_is_installed
:
2628 self
.logger
.info('%s: del mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2630 utils
.exec_command('%s delmcqv4src %s %d' % (utils
.brctl_cmd
, bridge
, vlan
))
2632 def bridge_get_mcqv4src(self
, bridge
, vlan
=None):
2633 if not LinkUtils
.bridge_utils_is_installed
:
2635 if not self
.supported_command
['showmcqv4src']:
2639 mcqout
= utils
.exec_command('%s showmcqv4src %s' %
2640 (utils
.brctl_cmd
, bridge
))
2641 except Exception as e
:
2643 if 'never heard' in s
:
2644 msg
= ('%s showmcqv4src: skipping unsupported command'
2646 self
.logger
.info(msg
)
2647 self
.supported_command
['showmcqv4src'] = False
2652 mcqlines
= mcqout
.splitlines()
2653 for l
in mcqlines
[1:]:
2655 k
, d
, v
= l
.split('\t')
2660 return mcqv4src
.get(vlan
)
2663 def bridge_get_mcqv4src_sysfs(self
, bridge
, vlan
=None):
2664 if not LinkUtils
.bridge_utils_is_installed
:
2666 if not self
.supported_command
['showmcqv4src']:
2668 if ifupdownflags
.flags
.PERFMODE
:
2672 filename
= '/sys/class/net/%s/bridge/multicast_v4_queriers' % bridge
2673 if os
.path
.exists(filename
):
2674 for line
in self
.read_file(filename
) or []:
2675 vlan_id
, ip
= line
.split('=')
2676 mcqv4src
[vlan_id
] = ip
.strip()
2677 except Exception as e
:
2679 msg
= ('%s showmcqv4src: skipping unsupported command'
2681 self
.logger
.info(msg
)
2682 self
.supported_command
['showmcqv4src'] = False
2685 return mcqv4src
.get(vlan
)
2689 def bridge_set_mclmi(bridge
, mclmi
):
2690 if not LinkUtils
.bridge_utils_is_installed
:
2692 utils
.exec_command('%s setmclmi %s %s' % (utils
.brctl_cmd
, bridge
, mclmi
))
2694 def bridge_get_mclmi(self
, bridge
):
2695 return self
.read_file_oneline(
2696 '/sys/class/net/%s/bridge/multicast_last_member_interval'
2700 def bridge_set_mcmi(bridge
, mcmi
):
2701 if not LinkUtils
.bridge_utils_is_installed
:
2703 utils
.exec_command('%s setmcmi %s %s' % (utils
.brctl_cmd
, bridge
, mcmi
))
2705 def bridge_get_mcmi(self
, bridge
):
2706 return self
.read_file_oneline(
2707 '/sys/class/net/%s/bridge/multicast_membership_interval'
2711 def bridge_exists(bridge
):
2712 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
2715 def is_bridge_port(ifacename
):
2716 return os
.path
.exists('/sys/class/net/%s/brport' % ifacename
)
2719 def bridge_port_exists(bridge
, bridgeportname
):
2721 return os
.path
.exists('/sys/class/net/%s/brif/%s' % (bridge
, bridgeportname
))
2726 def get_bridge_ports(bridgename
):
2728 return os
.listdir('/sys/class/net/%s/brif/' % bridgename
)
2732 def reset_addr_cache(self
, ifname
):
2734 linkCache
.links
[ifname
]['addrs'] = {}
2735 self
.logger
.debug('%s: reset address cache' % ifname
)
2739 def get_ipv6_addrgen_mode(self
, ifname
):
2741 return self
._cache
_get
('link', [ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
]
2743 # default to 0 (eui64)
2746 def ipv6_addrgen(self
, ifname
, addrgen
, link_created
):
2748 # IFLA_INET6_ADDR_GEN_MODE values:
2751 if self
._link
_cache
_get
([ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
] == addrgen
:
2752 self
.logger
.debug('%s: ipv6 addrgen already %s' % (ifname
, 'off' if addrgen
else 'on'))
2755 disabled_ipv6
= self
.read_file_oneline('/proc/sys/net/ipv6/conf/%s/disable_ipv6' % ifname
)
2756 if not disabled_ipv6
or int(disabled_ipv6
) == 1:
2757 self
.logger
.info('%s: cannot set addrgen: ipv6 is disabled on this device' % ifname
)
2760 if int(self
._link
_cache
_get
([ifname
, 'mtu'])) < 1280:
2761 self
.logger
.info('%s: ipv6 addrgen is disabled on device with MTU '
2762 'lower than 1280: cannot set addrgen %s' % (ifname
, 'off' if addrgen
else 'on'))
2764 except (KeyError, TypeError):
2765 self
.logger
.debug('%s: ipv6 addrgen probably not supported or disabled on this device' % ifname
)
2770 if not link_created
:
2771 # When setting addrgenmode it is necessary to flap the macvlan
2772 # device. After flapping the device we also need to re-add all
2773 # the user configuration. The best way to add the user config
2774 # is to flush our internal address cache
2775 self
.reset_addr_cache(ifname
)
2777 cmd
= 'link set dev %s addrgenmode %s' % (ifname
, Link
.ifla_inet6_addr_gen_mode_dict
.get(addrgen
))
2779 is_link_up
= self
.is_link_up(ifname
)
2782 self
.link_down(ifname
)
2784 #if LinkUtils.ipbatch:
2785 # self.add_to_batch(cmd)
2787 # because this command might fail on older kernel its better to not batch it
2788 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
2791 self
.link_up(ifname
)