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):
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
))
1106 self
.link_up(ifacename
)
1107 self
._cache
_update
([ifacename
, 'hwaddress'], hwaddress
)
1110 def link_set_mtu(self
, ifacename
, mtu
):
1111 if ifupdownflags
.flags
.DRYRUN
:
1113 if not mtu
or not ifacename
: return
1114 self
.write_file('/sys/class/net/%s/mtu' % ifacename
, mtu
)
1115 self
._cache
_update
([ifacename
, 'mtu'], mtu
)
1117 def link_set_alias(self
, ifacename
, alias
):
1118 self
.write_file('/sys/class/net/%s/ifalias' % ifacename
,
1119 '\n' if not alias
else alias
)
1121 def link_get_alias(self
, ifacename
):
1122 return self
.read_file_oneline('/sys/class/net/%s/ifalias'
1125 def link_isloopback(self
, ifacename
):
1126 flags
= self
._cache
_get
('link', [ifacename
, 'flags'])
1129 if 'LOOPBACK' in flags
:
1133 def link_get_status(self
, ifacename
):
1134 return self
._cache
_get
('link', [ifacename
, 'ifflag'], refresh
=True)
1137 def route_add_gateway(ifacename
, gateway
, vrf
=None, metric
=None, onlink
=True):
1141 cmd
= '%s route add default via %s proto kernel' % (utils
.ip_cmd
,
1144 cmd
= ('%s route add table %s default via %s proto kernel' %
1145 (utils
.ip_cmd
, vrf
, gateway
))
1148 cmd
+= ' metric %s' % metric
1149 cmd
+= ' dev %s' % ifacename
1154 utils
.exec_command(cmd
)
1157 def route_del_gateway(ifacename
, gateway
, vrf
=None, metric
=None):
1162 cmd
= ('%s route del default via %s proto kernel' %
1163 (utils
.ip_cmd
, gateway
))
1165 cmd
= ('%s route del table %s default via %s proto kernel' %
1166 (utils
.ip_cmd
, vrf
, gateway
))
1168 cmd
+= ' metric %s' % metric
1169 cmd
+= ' dev %s' % ifacename
1170 utils
.exec_command(cmd
)
1173 def _get_vrf_id(ifacename
):
1175 return linkCache
.vrfs
[ifacename
]['table']
1177 dump
= netlink
.link_dump(ifacename
)
1179 [linkCache
.update_attrdict([ifname
], linkattrs
)
1180 for ifname
, linkattrs
in dump
.items()]
1182 if dump
and dump
.get(ifacename
, {}).get('kind') == 'vrf':
1183 vrf_table
= dump
.get(ifacename
, {}).get('linkinfo', {}).get('table')
1184 linkCache
.vrfs
[ifacename
] = {'table': vrf_table
}
1189 def fix_ipv6_route_metric(self
, ifaceobj
, macvlan_ifacename
, ips
):
1192 if ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
:
1194 for upper_iface
in ifaceobj
.upperifaces
:
1195 vrf_table
= self
._get
_vrf
_id
(upper_iface
)
1203 ip_network_obj
= IPNetwork(ip
)
1205 if type(ip_network_obj
) == IPv6Network
:
1206 route_prefix
= '%s/%d' % (ip_network_obj
.network
, ip_network_obj
.prefixlen
)
1209 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1210 LinkUtils
.add_to_batch('route del %s table %s dev %s' % (route_prefix
, vrf_table
, macvlan_ifacename
))
1212 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'table', vrf_table
, 'dev', macvlan_ifacename
])
1214 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1215 LinkUtils
.add_to_batch('route del %s dev %s' % (route_prefix
, macvlan_ifacename
))
1217 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'del', route_prefix
, 'dev', macvlan_ifacename
])
1218 ip_route_del
.append((route_prefix
, vrf_table
))
1220 for ip
, vrf_table
in ip_route_del
:
1222 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1223 LinkUtils
.add_to_batch('route add %s table %s dev %s proto kernel metric 9999' % (ip
, vrf_table
, macvlan_ifacename
))
1225 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'table', vrf_table
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1227 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1228 LinkUtils
.add_to_batch('route add %s dev %s proto kernel metric 9999' % (ip
, macvlan_ifacename
))
1230 utils
.exec_commandl([utils
.ip_cmd
, 'route', 'add', ip
, 'dev', macvlan_ifacename
, 'proto', 'kernel' 'metric', '9999'])
1232 def link_create_vlan(self
, vlan_device_name
, vlan_raw_device
, vlanid
):
1233 if self
.link_exists(vlan_device_name
):
1235 utils
.exec_command('%s link add link %s name %s type vlan id %d' %
1237 vlan_raw_device
, vlan_device_name
, vlanid
))
1238 self
._cache
_update
([vlan_device_name
], {})
1240 def link_create_vlan_from_name(self
, vlan_device_name
):
1241 v
= vlan_device_name
.split('.')
1243 self
.logger
.warn('invalid vlan device name %s' % vlan_device_name
)
1245 self
.link_create_vlan(vlan_device_name
, v
[0], v
[1])
1247 def link_create_macvlan(self
, name
, linkdev
, mode
='private'):
1248 if self
.link_exists(name
):
1250 cmd
= ('link add link %s' % linkdev
+
1252 ' type macvlan mode %s' % mode
)
1253 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1254 self
.add_to_batch(cmd
)
1256 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1257 self
._cache
_update
([name
], {})
1259 def get_vxlan_peers(self
, dev
, svcnodeip
):
1260 cmd
= '%s fdb show brport %s' % (utils
.bridge_cmd
,
1264 ps
= subprocess
.Popen(shlex
.split(cmd
), stdout
=subprocess
.PIPE
, close_fds
=False)
1265 utils
.enable_subprocess_signal_forwarding(ps
, signal
.SIGINT
)
1266 output
= subprocess
.check_output(('grep', '00:00:00:00:00:00'), stdin
=ps
.stdout
)
1268 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1270 ppat
= re
.compile('\s+dst\s+(\d+.\d+.\d+.\d+)\s+')
1271 for l
in output
.split('\n'):
1273 if m
and m
.group(1) != svcnodeip
:
1274 cur_peers
.append(m
.group(1))
1276 self
.logger
.warn('error parsing ip link output')
1277 except subprocess
.CalledProcessError
as e
:
1278 if e
.returncode
!= 1:
1279 self
.logger
.error(str(e
))
1281 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
1285 def tunnel_create(self
, tunnelname
, mode
, attrs
={}):
1286 """ generic link_create function """
1287 if self
.link_exists(tunnelname
):
1294 if mode
in ['gretap']:
1295 cmd
+= ' link add %s type %s' % (tunnelname
, mode
)
1297 cmd
+= ' tunnel add %s mode %s' % (tunnelname
, mode
)
1300 for k
, v
in attrs
.iteritems():
1304 if self
.ipbatch
and not self
.ipbatch_pause
:
1305 self
.add_to_batch(cmd
)
1307 utils
.exec_command('ip %s' % cmd
)
1308 self
._cache
_update
([tunnelname
], {})
1310 def tunnel_change(self
, tunnelname
, attrs
={}):
1311 """ tunnel change function """
1312 if not self
.link_exists(tunnelname
):
1314 cmd
= 'tunnel change'
1315 cmd
+= ' %s' %(tunnelname)
1317 for k
, v
in attrs
.iteritems():
1321 if self
.ipbatch
and not self
.ipbatch_pause
:
1322 self
.add_to_batch(cmd
)
1324 utils
.exec_command('ip %s' % cmd
)
1326 def link_create_vxlan(self
, name
, vxlanid
,
1334 if svcnodeip
and remoteips
:
1335 raise Exception("svcnodeip and remoteip is mutually exclusive")
1338 args
+= ' remote %s' % svcnodeip
1340 args
+= ' ageing %s' % ageing
1341 if learning
== 'off':
1342 args
+= ' nolearning'
1344 args
+= ' ttl %s' % ttl
1346 if self
.link_exists(name
):
1347 cmd
= 'link set dev %s type vxlan dstport %d' % (name
, LinkUtils
.VXLAN_UDP_PORT
)
1348 vxlanattrs
= self
.get_vxlandev_attrs(name
)
1349 # on ifreload do not overwrite anycast_ip to individual ip if clagd
1352 running_localtunnelip
= vxlanattrs
.get('local')
1353 if anycastip
and running_localtunnelip
and anycastip
== running_localtunnelip
:
1354 localtunnelip
= running_localtunnelip
1355 running_svcnode
= vxlanattrs
.get('svcnode')
1356 if running_svcnode
and not svcnodeip
:
1359 cmd
= 'link add dev %s type vxlan id %s dstport %d' % (name
, vxlanid
, LinkUtils
.VXLAN_UDP_PORT
)
1362 args
+= ' local %s' % localtunnelip
1365 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1366 self
.add_to_batch(cmd
)
1368 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1370 # XXX: update linkinfo correctly
1371 #self._cache_update([name], {})
1374 def link_exists(ifacename
):
1375 if ifupdownflags
.flags
.DRYRUN
:
1377 return os
.path
.exists('/sys/class/net/%s' % ifacename
)
1380 def link_exists_nodryrun(ifname
):
1381 return os
.path
.exists('/sys/class/net/%s' % ifname
)
1383 def link_get_ifindex(self
, ifacename
):
1384 if ifupdownflags
.flags
.DRYRUN
:
1386 return self
.read_file_oneline('/sys/class/net/%s/ifindex' % ifacename
)
1388 def is_vlan_device_by_name(self
, ifacename
):
1389 if re
.search(r
'\.', ifacename
):
1394 def link_add_macvlan(ifname
, macvlan_ifacename
, mode
):
1395 utils
.exec_commandl(['ip', 'link', 'add', 'link', ifname
, 'name', macvlan_ifacename
, 'type', 'macvlan', 'mode', mode
])
1398 def link_add_xfrm(ifname
, xfrm_name
, xfrm_id
):
1399 utils
.exec_commandl(['ip', 'link', 'add', xfrm_name
, 'type', 'xfrm', 'dev', ifname
, 'if_id', xfrm_id
])
1402 def route_add(route
):
1403 utils
.exec_command('%s route add %s' % (utils
.ip_cmd
,
1407 def route6_add(route
):
1408 utils
.exec_command('%s -6 route add %s' % (utils
.ip_cmd
,
1411 def get_vlandev_attrs(self
, ifacename
):
1412 return (self
._cache
_get
('link', [ifacename
, 'link']),
1413 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlanid']),
1414 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol']))
1416 def get_vlan_protocol(self
, ifacename
):
1417 return self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlan_protocol'])
1419 def get_vxlandev_attrs(self
, ifacename
):
1420 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1422 def get_vxlandev_learning(self
, ifacename
):
1423 return self
._cache
_get
('link', [ifacename
, 'linkinfo', Link
.IFLA_VXLAN_LEARNING
])
1425 def set_vxlandev_learning(self
, ifacename
, learn
):
1427 utils
.exec_command('%s link set dev %s type vxlan learning' %
1428 (utils
.ip_cmd
, ifacename
))
1429 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'on')
1431 utils
.exec_command('%s link set dev %s type vxlan nolearning' %
1432 (utils
.ip_cmd
, ifacename
))
1433 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'off')
1435 def link_get_linkinfo_attrs(self
, ifacename
):
1436 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
1438 def link_get_mtu(self
, ifacename
, refresh
=False):
1439 return self
._cache
_get
('link', [ifacename
, 'mtu'], refresh
=refresh
)
1441 def link_get_mtu_sysfs(self
, ifacename
):
1442 return self
.read_file_oneline('/sys/class/net/%s/mtu'
1445 def link_get_kind(self
, ifacename
):
1446 return self
._cache
_get
('link', [ifacename
, 'kind'])
1448 def link_get_slave_kind(self
, ifacename
):
1449 return self
._cache
_get
('link', [ifacename
, 'slave_kind'])
1451 def link_get_hwaddress(self
, ifacename
):
1452 address
= self
._cache
_get
('link', [ifacename
, 'hwaddress'])
1453 # newly created logical interface addresses dont end up in the cache
1454 # read hwaddress from sysfs file for these interfaces
1456 address
= self
.read_file_oneline('/sys/class/net/%s/address'
1460 def link_create(self
, ifacename
, t
, attrs
={}):
1461 """ generic link_create function """
1462 if self
.link_exists(ifacename
):
1465 cmd
+= ' name %s type %s' % (ifacename
, t
)
1467 for k
, v
in attrs
.iteritems():
1471 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1472 self
.add_to_batch(cmd
)
1474 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1475 self
._cache
_update
([ifacename
], {})
1477 def link_delete(self
, ifacename
):
1478 if not self
.link_exists(ifacename
):
1480 cmd
= 'link del %s' % ifacename
1481 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1482 self
.add_to_batch(cmd
)
1484 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
1485 self
._cache
_invalidate
()
1487 def link_get_master(self
, ifacename
):
1488 sysfs_master_path
= '/sys/class/net/%s/master' % ifacename
1489 if os
.path
.exists(sysfs_master_path
):
1490 link_path
= os
.readlink(sysfs_master_path
)
1492 return os
.path
.basename(link_path
)
1496 return self
._cache
_get
('link', [ifacename
, 'master'])
1498 def get_brport_peer_link(self
, bridgename
):
1500 return self
._cache
_get
('link', [bridgename
, 'info_slave_data', Link
.IFLA_BRPORT_PEER_LINK
])
1505 def bridge_port_vids_add(bridgeportname
, vids
):
1506 [utils
.exec_command('%s vlan add vid %s dev %s' %
1508 v
, bridgeportname
)) for v
in vids
]
1511 def bridge_port_vids_del(bridgeportname
, vids
):
1514 [utils
.exec_command('%s vlan del vid %s dev %s' %
1516 v
, bridgeportname
)) for v
in vids
]
1519 def bridge_port_vids_flush(bridgeportname
, vid
):
1520 utils
.exec_command('%s vlan del vid %s dev %s' %
1522 vid
, bridgeportname
))
1525 def bridge_port_vids_get(bridgeportname
):
1526 bridgeout
= utils
.exec_command('%s vlan show dev %s' %
1531 brvlanlines
= bridgeout
.readlines()[2:]
1532 vids
= [l
.strip() for l
in brvlanlines
]
1533 return [v
for v
in vids
if v
]
1536 def bridge_port_vids_get_all():
1538 bridgeout
= utils
.exec_command('%s -c vlan show'
1542 brvlanlines
= bridgeout
.splitlines()
1544 for l
in brvlanlines
[1:]:
1545 if l
and not l
.startswith(' ') and not l
.startswith('\t'):
1547 brportname
= attrs
[0].strip()
1548 brvlaninfo
[brportname
] = {'pvid': None, 'vlan': []}
1549 l
= ' '.join(attrs
[1:])
1550 if not brportname
or not l
:
1554 brvlaninfo
[brportname
]['pvid'] = l
.split()[0]
1555 elif 'Egress Untagged' not in l
:
1556 brvlaninfo
[brportname
]['vlan'].append(l
)
1559 def bridge_port_vids_get_all_json(self
):
1560 if not self
.supported_command
['%s -c -json vlan show'
1561 % utils
.bridge_cmd
]:
1565 bridgeout
= utils
.exec_command('%s -c -json vlan show'
1568 self
.supported_command
['%s -c -json vlan show'
1569 % utils
.bridge_cmd
] = False
1570 self
.logger
.info('%s -c -json vlan show: skipping unsupported command'
1573 return self
.get_bridge_vlan_nojson()
1574 except Exception as e
:
1575 self
.logger
.info('bridge: get_bridge_vlan_nojson: %s' % str(e
))
1578 if not bridgeout
: return brvlaninfo
1580 vlan_json
= json
.loads(bridgeout
, encoding
="utf-8")
1581 except Exception, e
:
1582 self
.logger
.info('json loads failed with (%s)' % str(e
))
1586 if isinstance(vlan_json
, list):
1587 # newer iproute2 version changed the bridge vlan show output
1588 # ifupdown2 relies on the previous format, we have the convert
1589 # data into old format
1590 bridge_port_vids
= dict()
1592 for intf
in vlan_json
:
1593 bridge_port_vids
[intf
["ifname"]] = intf
["vlans"]
1595 return bridge_port_vids
1597 # older iproute2 version have different ways to dump vlans
1598 # ifupdown2 prefers the following syntax:
1602 # "flags": ["PVID", "Egress Untagged"]
1607 # "flags": ["PVID", "Egress Untagged"]
1611 except Exception as e
:
1612 self
.logger
.debug("bridge vlan show: Unknown json output: %s" % str(e
))
1616 def get_bridge_vlan_nojson():
1618 bridgeout
= utils
.exec_commandl([utils
.bridge_cmd
, '-c', 'vlan', 'show'])
1620 output
= [line
.split('\n') for line
in bridgeout
.split('\n\n')]
1621 output
[0] = output
[0][1:]
1629 prefix
, vlan
= entry
.split('\t')
1631 current_swp
= prefix
1632 vlan_json
[prefix
] = []
1636 v
['vlan'] = int(vlan
)
1640 start
, end
= vlan
.split('-')
1642 end
= end
[0:end
.index(' ')]
1643 v
['vlan'] = int(start
)
1644 v
['vlanEnd'] = int(end
)
1646 v
['vlan'] = int(vlan
[0:vlan
.index(' ')])
1649 flags
.append('PVID')
1650 if 'Egress Untagged' in vlan
:
1651 flags
.append('Egress Untagged')
1655 vlan_json
[current_swp
].append(v
)
1658 def bridge_vlan_cache_get(self
, ifacename
, refresh
=False):
1659 if not self
.bridge_vlan_cache_fill_done
or refresh
:
1660 self
.bridge_vlan_cache
= self
.bridge_port_vids_get_all_json()
1661 self
.bridge_vlan_cache_fill_done
= True
1662 return self
.bridge_vlan_cache
.get(ifacename
, {})
1664 def bridge_vlan_get_pvid(self
, ifacename
, refresh
=False):
1667 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1668 v
= vinfo
.get('vlan')
1669 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1674 def bridge_vlan_get_vids(self
, ifacename
, refresh
=False):
1677 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1678 v
= vinfo
.get('vlan')
1679 ispvid
= True if 'PVID' in vinfo
.get('flags', []) else False
1681 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_vlan_get_vids_n_pvid(self
, ifacename
, refresh
=False):
1695 for vinfo
in self
.bridge_vlan_cache_get(ifacename
, refresh
):
1696 v
= vinfo
.get('vlan')
1697 ispvid
= True if 'PVID' in vinfo
.get('flags', []) else False
1699 pvid
= v
if 'PVID' in vinfo
.get('flags', []) else 0
1700 vEnd
= vinfo
.get('vlanEnd')
1702 vids
.extend(range(v
, vEnd
+ 1))
1707 def bridge_port_pvid_add(self
, bridgeportname
, pvid
):
1708 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1709 self
.add_to_batch('vlan add vid %s untagged pvid dev %s' %
1710 (pvid
, bridgeportname
))
1712 utils
.exec_command('%s vlan add vid %s untagged pvid dev %s' %
1714 pvid
, bridgeportname
))
1716 def bridge_port_pvid_del(self
, bridgeportname
, pvid
):
1717 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1718 self
.add_to_batch('vlan del vid %s untagged pvid dev %s' %
1719 (pvid
, bridgeportname
))
1721 utils
.exec_command('%s vlan del vid %s untagged pvid dev %s' %
1723 pvid
, bridgeportname
))
1725 def bridge_port_pvids_get(self
, bridgeportname
):
1726 return self
.read_file_oneline('/sys/class/net/%s/brport/pvid'
1729 def bridge_vids_add(self
, bridgeportname
, vids
, bridge
=True):
1730 target
= 'self' if bridge
else ''
1731 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1732 [self
.add_to_batch('vlan add vid %s dev %s %s' %
1733 (v
, bridgeportname
, target
)) for v
in vids
]
1735 [utils
.exec_command('%s vlan add vid %s dev %s %s' %
1737 v
, bridgeportname
, target
)) for v
in vids
]
1739 def bridge_vids_del(self
, bridgeportname
, vids
, bridge
=True):
1740 target
= 'self' if bridge
else ''
1741 if LinkUtils
.ipbatch
and not LinkUtils
.ipbatch_pause
:
1742 [self
.add_to_batch('vlan del vid %s dev %s %s' %
1743 (v
, bridgeportname
, target
)) for v
in vids
]
1745 [utils
.exec_command('%s vlan del vid %s dev %s %s' %
1747 v
, bridgeportname
, target
)) for v
in vids
]
1750 def bridge_fdb_add(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1751 target
= 'self' if bridge
else ''
1754 vlan_str
= 'vlan %s ' % vlan
1758 dst_str
= 'dst %s ' % remote
1760 utils
.exec_command('%s fdb replace %s dev %s %s %s %s' %
1762 address
, dev
, vlan_str
, target
, dst_str
))
1765 def bridge_fdb_append(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1766 target
= 'self' if bridge
else ''
1769 vlan_str
= 'vlan %s ' % vlan
1773 dst_str
= 'dst %s ' % remote
1775 utils
.exec_command('%s fdb append %s dev %s %s %s %s' %
1777 address
, dev
, vlan_str
, target
, dst_str
))
1780 def bridge_fdb_del(dev
, address
, vlan
=None, bridge
=True, remote
=None):
1781 target
= 'self' if bridge
else ''
1784 vlan_str
= 'vlan %s ' % vlan
1788 dst_str
= 'dst %s ' % remote
1789 utils
.exec_command('%s fdb del %s dev %s %s %s %s' %
1791 address
, dev
, vlan_str
, target
, dst_str
))
1793 def bridge_is_vlan_aware(self
, bridgename
):
1794 filename
= '/sys/class/net/%s/bridge/vlan_filtering' % bridgename
1795 if os
.path
.exists(filename
) and self
.read_file_oneline(filename
) == '1':
1800 def bridge_port_get_bridge_name(bridgeport
):
1801 filename
= '/sys/class/net/%s/brport/bridge' % bridgeport
1803 return os
.path
.basename(os
.readlink(filename
))
1808 def bridge_port_exists(bridge
, bridgeportname
):
1810 return os
.path
.exists('/sys/class/net/%s/brif/%s'
1811 % (bridge
, bridgeportname
))
1815 def bridge_fdb_show_dev(self
, dev
):
1818 output
= utils
.exec_command('%s fdb show dev %s'
1819 % (utils
.bridge_cmd
, dev
))
1821 for fdb_entry
in output
.splitlines():
1823 entries
= fdb_entry
.split()
1824 fdbs
.setdefault(entries
[2], []).append(entries
[0])
1826 self
.logger
.debug('%s: invalid fdb line \'%s\''
1833 def is_bridge(bridge
):
1834 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
1836 def is_link_up(self
, ifacename
):
1839 flags
= self
.read_file_oneline('/sys/class/net/%s/flags' % ifacename
)
1840 iflags
= int(flags
, 16)
1847 def ip_route_get_dev(self
, prefix
, vrf_master
=None):
1850 cmd
= '%s route get %s vrf %s' % (utils
.ip_cmd
, prefix
, vrf_master
)
1852 cmd
= '%s route get %s' % (utils
.ip_cmd
, prefix
)
1854 output
= utils
.exec_command(cmd
)
1856 rline
= output
.splitlines()[0]
1858 rattrs
= rline
.split()
1859 return rattrs
[rattrs
.index('dev') + 1]
1860 except Exception, e
:
1861 self
.logger
.debug('ip_route_get_dev: failed .. %s' % str(e
))
1865 def link_get_lowers(ifacename
):
1867 lowers
= glob
.glob("/sys/class/net/%s/lower_*" % ifacename
)
1870 return [os
.path
.basename(l
)[6:] for l
in lowers
]
1875 def link_get_uppers(ifacename
):
1877 uppers
= glob
.glob("/sys/class/net/%s/upper_*" % ifacename
)
1880 return [os
.path
.basename(u
)[6:] for u
in uppers
]
1884 def link_get_vrfs(self
):
1885 if not LinkUtils
._CACHE
_FILL
_DONE
:
1887 return linkCache
.vrfs
1890 def cache_get_info_slave(attrlist
):
1892 return linkCache
.get_attr(attrlist
)
1896 def get_brport_learning(self
, ifacename
):
1897 learn
= self
.read_file_oneline('/sys/class/net/%s/brport/learning'
1899 if learn
and learn
== '1':
1904 def get_brport_learning_bool(self
, ifacename
):
1905 return utils
.get_boolean_from_string(self
.read_file_oneline('/sys/class/net/%s/brport/learning' % ifacename
))
1907 def set_brport_learning(self
, ifacename
, learn
):
1909 return self
.write_file('/sys/class/net/%s/brport/learning'
1912 return self
.write_file('/sys/class/net/%s/brport/learning'
1915 #################################################################################
1916 ################################### BOND UTILS ##################################
1917 #################################################################################
1919 def _link_cache_get(self
, attrlist
, refresh
=False):
1920 return self
._cache
_get
('link', attrlist
, refresh
)
1922 def cache_delete(self
, attrlist
, value
=None):
1923 return self
._cache
_delete
(attrlist
, value
)
1925 def link_cache_get(self
, attrlist
, refresh
=False):
1926 return self
._link
_cache
_get
(attrlist
, refresh
)
1928 def link_cache_check(self
, attrlist
, value
, refresh
=False):
1929 return self
._link
_cache
_check
(attrlist
, value
, refresh
)
1931 def _link_cache_check(self
, attrlist
, value
, refresh
=False):
1933 return self
._link
_cache
_get
(attrlist
, refresh
) == value
1934 except Exception, e
:
1935 self
.logger
.debug('_cache_check(%s) : [%s]'
1936 % (str(attrlist
), str(e
)))
1941 Link
.IFLA_BOND_MODE
: 'mode',
1942 Link
.IFLA_BOND_MIIMON
: 'miimon',
1943 Link
.IFLA_BOND_USE_CARRIER
: 'use_carrier',
1944 Link
.IFLA_BOND_AD_LACP_RATE
: 'lacp_rate',
1945 Link
.IFLA_BOND_XMIT_HASH_POLICY
: 'xmit_hash_policy',
1946 Link
.IFLA_BOND_MIN_LINKS
: 'min_links',
1947 Link
.IFLA_BOND_NUM_PEER_NOTIF
: 'num_grat_arp',
1948 Link
.IFLA_BOND_AD_ACTOR_SYSTEM
: 'ad_actor_system',
1949 Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
: 'ad_actor_sys_prio',
1950 Link
.IFLA_BOND_AD_LACP_BYPASS
: 'lacp_bypass',
1951 Link
.IFLA_BOND_UPDELAY
: 'updelay',
1952 Link
.IFLA_BOND_DOWNDELAY
: 'downdelay',
1955 def bond_set_attrs_nl(self
, bondname
, ifla_info_data
):
1956 bond_attr_name
= 'None' # for log purpose (in case an exception raised)
1957 for nl_attr
, value
in ifla_info_data
.items():
1959 bond_attr_name
= self
.bondcmd_attrmap
[nl_attr
]
1960 file_path
= '/sys/class/net/%s/bonding/%s' % (bondname
, bond_attr_name
)
1961 if os
.path
.exists(file_path
):
1962 self
.write_file(file_path
, str(value
))
1963 except Exception as e
:
1964 exception_str
= '%s: %s %s: %s' % (bondname
, bond_attr_name
, value
, str(e
))
1965 if ifupdownflags
.flags
.FORCE
:
1966 self
.logger
.warning(exception_str
)
1968 self
.logger
.debug(exception_str
)
1970 def bond_set_attrs(self
, bondname
, attrdict
, prehook
):
1971 for attrname
, attrval
in attrdict
.items():
1972 if (self
._link
_cache
_check
([bondname
, 'linkinfo',
1973 attrname
], attrval
)):
1975 if (attrname
== 'mode'
1976 or attrname
== 'xmit_hash_policy'
1977 or attrname
== 'lacp_rate' or attrname
== 'min_links'):
1981 if ((attrname
not in ['lacp_rate',
1983 self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'], '802.3ad',
1985 self
.write_file('/sys/class/net/%s/bonding/%s'
1986 % (bondname
, attrname
), attrval
)
1987 except Exception, e
:
1988 if ifupdownflags
.flags
.FORCE
:
1989 self
.logger
.warn(str(e
))
1994 def bond_set_use_carrier(self
, bondname
, use_carrier
):
1995 if not use_carrier
or (use_carrier
!= '0' and use_carrier
!= '1'):
1997 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'use_carrier'],
2000 self
.write_file('/sys/class/net/%s' % bondname
+
2001 '/bonding/use_carrier', use_carrier
)
2002 self
._cache
_update
([bondname
, 'linkinfo',
2003 'use_carrier'], use_carrier
)
2005 def bond_get_use_carrier(self
, bondname
):
2006 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'use_carrier'])
2008 def bond_get_use_carrier_nl(self
, bondname
):
2009 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_USE_CARRIER
])
2011 def bond_set_xmit_hash_policy(self
, bondname
, hash_policy
, prehook
=None):
2012 valid_values
= ['layer2', 'layer3+4', 'layer2+3']
2015 if hash_policy
not in valid_values
:
2016 raise Exception('invalid hash policy value %s' % hash_policy
)
2017 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'xmit_hash_policy'],
2022 self
.write_file('/sys/class/net/%s' % bondname
+
2023 '/bonding/xmit_hash_policy', hash_policy
)
2024 self
._cache
_update
([bondname
, 'linkinfo', 'xmit_hash_policy'],
2027 def bond_get_xmit_hash_policy(self
, bondname
):
2028 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'xmit_hash_policy'])
2030 def bond_get_xmit_hash_policy_nl(self
, bondname
):
2031 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_XMIT_HASH_POLICY
])
2033 def bond_set_miimon(self
, bondname
, miimon
):
2034 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'miimon'],
2037 self
.write_file('/sys/class/net/%s' % bondname
+
2038 '/bonding/miimon', miimon
)
2039 self
._cache
_update
([bondname
, 'linkinfo', 'miimon'], miimon
)
2041 def bond_get_miimon(self
, bondname
):
2042 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'miimon'])
2044 def bond_get_miimon_nl(self
, bondname
):
2045 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIIMON
])
2047 def bond_set_mode(self
, bondname
, mode
, prehook
=None):
2048 valid_modes
= ['balance-rr', 'active-backup', 'balance-xor',
2049 'broadcast', '802.3ad', 'balance-tlb', 'balance-alb']
2052 if mode
not in valid_modes
:
2053 raise Exception('invalid mode %s' % mode
)
2054 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'mode'],
2059 self
.write_file('/sys/class/net/%s' % bondname
+ '/bonding/mode', mode
)
2060 self
._cache
_update
([bondname
, 'linkinfo', 'mode'], mode
)
2062 def bond_get_mode(self
, bondname
):
2063 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'mode'])
2065 def bond_get_mode_nl(self
, bondname
):
2066 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MODE
])
2068 def bond_set_lacp_rate(self
, bondname
, lacp_rate
, prehook
=None, posthook
=None):
2069 if not lacp_rate
or (lacp_rate
!= '0' and lacp_rate
!= '1'):
2071 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_rate'],
2077 self
.write_file('/sys/class/net/%s' % bondname
+
2078 '/bonding/lacp_rate', lacp_rate
)
2084 self
._cache
_update
([bondname
, 'linkinfo',
2085 'lacp_rate'], lacp_rate
)
2087 def bond_get_lacp_rate(self
, bondname
):
2088 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_rate'])
2090 def bond_get_lacp_rate_nl(self
, bondname
):
2091 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_RATE
])
2093 def bond_set_lacp_bypass_allow(self
, bondname
, allow
, prehook
=None, posthook
=None):
2094 if self
._link
_cache
_check
([bondname
, 'linkinfo', 'lacp_bypass'], allow
):
2099 self
.write_file('/sys/class/net/%s' % bondname
+
2100 '/bonding/lacp_bypass', allow
)
2106 self
._cache
_update
([bondname
, 'linkinfo',
2107 'lacp_bypass'], allow
)
2109 def bond_get_lacp_bypass_allow(self
, bondname
):
2110 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'lacp_bypass'])
2112 def bond_get_lacp_bypass_allow_nl(self
, bondname
):
2113 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_LACP_BYPASS
])
2115 def bond_set_min_links(self
, bondname
, min_links
, prehook
=None):
2116 if (self
._link
_cache
_check
([bondname
, 'linkinfo', 'min_links'],
2121 self
.write_file('/sys/class/net/%s/bonding/min_links' % bondname
,
2123 self
._cache
_update
([bondname
, 'linkinfo', 'min_links'], min_links
)
2125 def bond_get_min_links(self
, bondname
):
2126 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'min_links'])
2128 def get_min_links_nl(self
, bondname
):
2129 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_MIN_LINKS
])
2131 def bond_get_ad_actor_system(self
, bondname
):
2132 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_system'])
2134 def bond_get_ad_actor_system_nl(self
, bondname
):
2135 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYSTEM
])
2137 def bond_get_ad_actor_sys_prio(self
, bondname
):
2138 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'ad_actor_sys_prio'])
2140 def bond_get_ad_actor_sys_prio_nl(self
, bondname
):
2141 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
])
2143 def bond_get_num_unsol_na(self
, bondname
):
2144 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_unsol_na'])
2146 def bond_get_num_unsol_na_nl(self
, bondname
):
2147 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2149 def bond_get_num_grat_arp(self
, bondname
):
2150 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'num_grat_arp'])
2152 def bond_get_num_grat_arp_nl(self
, bondname
):
2153 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_NUM_PEER_NOTIF
])
2155 def bond_get_updelay(self
, bondname
):
2156 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'updelay'])
2158 def bond_get_updelay_nl(self
, bondname
):
2159 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_UPDELAY
])
2161 def bond_get_downdelay(self
, bondname
):
2162 return self
._link
_cache
_get
([bondname
, 'linkinfo', 'downdelay'])
2164 def bond_get_downdelay_nl(self
, bondname
):
2165 return self
._link
_cache
_get
([bondname
, 'linkinfo', Link
.IFLA_BOND_DOWNDELAY
])
2167 def bond_enslave_slave(self
, bondname
, slave
, prehook
=None, posthook
=None):
2168 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2169 if slaves
and slave
in slaves
:
2173 self
.write_file('/sys/class/net/%s' % bondname
+
2174 '/bonding/slaves', '+' + slave
)
2177 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slave
)
2179 def bond_remove_slave(self
, bondname
, slave
):
2180 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2181 if not slaves
or slave
not in slaves
:
2183 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2185 if not os
.path
.exists(sysfs_bond_path
):
2187 self
.write_file(sysfs_bond_path
, '-' + slave
)
2188 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'], slave
)
2190 def bond_remove_slaves_all(self
, bondname
):
2191 if not self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves']):
2194 sysfs_bond_path
= ('/sys/class/net/%s' % bondname
+
2197 with
open(sysfs_bond_path
, 'r') as f
:
2198 slaves
= f
.readline().strip().split()
2200 raise Exception('error reading slaves of bond %s (%s)' % (bondname
, str(e
)))
2201 for slave
in slaves
:
2202 self
.link_down(slave
)
2204 self
.bond_remove_slave(bondname
, slave
)
2205 except Exception, e
:
2206 if not ifupdownflags
.flags
.FORCE
:
2207 raise Exception('error removing slave %s from bond %s (%s)' % (slave
, bondname
, str(e
)))
2210 self
._cache
_delete
([bondname
, 'linkinfo', 'slaves'])
2213 def bond_load_bonding_module():
2214 return utils
.exec_command('%s -q bonding' % utils
.modprobe_cmd
)
2216 def create_bond(self
, bondname
):
2217 if self
.bond_exists(bondname
):
2219 # load_bonding_module() has already been run
2220 self
.write_file('/sys/class/net/bonding_masters', '+' + bondname
)
2221 self
._cache
_update
([bondname
], {})
2223 def delete_bond(self
, bondname
):
2224 if not os
.path
.exists('/sys/class/net/%s' % bondname
):
2226 self
.write_file('/sys/class/net/bonding_masters', '-' + bondname
)
2227 self
._cache
_delete
([bondname
])
2229 def bond_get_slaves(self
, bondname
):
2230 slaves
= self
._link
_cache
_get
([bondname
, 'linkinfo', 'slaves'])
2233 slavefile
= '/sys/class/net/%s/bonding/slaves' % bondname
2234 if os
.path
.exists(slavefile
):
2235 buf
= self
.read_file_oneline(slavefile
)
2237 slaves
= buf
.split()
2240 self
._cache
_update
([bondname
, 'linkinfo', 'slaves'], slaves
)
2243 def bond_slave_exists(self
, bond
, slave
):
2244 slaves
= self
.bond_get_slaves(bond
)
2247 return slave
in slaves
2250 def bond_exists(bondname
):
2251 return os
.path
.exists('/sys/class/net/%s/bonding' % bondname
)
2253 #################################################################################
2254 ################################## BRIDGE UTILS #################################
2255 #################################################################################
2257 def create_bridge(self
, bridgename
):
2258 if not LinkUtils
.bridge_utils_is_installed
:
2260 if self
.bridge_exists(bridgename
):
2262 utils
.exec_command('%s addbr %s' % (utils
.brctl_cmd
, bridgename
))
2263 self
._cache
_update
([bridgename
], {})
2265 def delete_bridge(self
, bridgename
):
2266 if not LinkUtils
.bridge_utils_is_installed
:
2268 if not self
.bridge_exists(bridgename
):
2270 utils
.exec_command('%s delbr %s' % (utils
.brctl_cmd
, bridgename
))
2271 self
._cache
_invalidate
()
2273 def add_bridge_port(self
, bridgename
, bridgeportname
):
2274 """ Add port to bridge """
2275 if not LinkUtils
.bridge_utils_is_installed
:
2277 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2278 if ports
and ports
.get(bridgeportname
):
2280 utils
.exec_command('%s addif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2281 self
._cache
_update
([bridgename
, 'linkinfo', 'ports', bridgeportname
], {})
2283 def delete_bridge_port(self
, bridgename
, bridgeportname
):
2284 """ Delete port from bridge """
2285 if not LinkUtils
.bridge_utils_is_installed
:
2287 ports
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports'])
2288 if not ports
or not ports
.get(bridgeportname
):
2290 utils
.exec_command('%s delif %s %s' % (utils
.brctl_cmd
, bridgename
, bridgeportname
))
2291 self
._cache
_delete
([bridgename
, 'linkinfo', 'ports', 'bridgeportname'])
2293 def set_bridgeport_attrs(self
, bridgename
, bridgeportname
, attrdict
):
2294 portattrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports', bridgeportname
])
2295 if portattrs
== None:
2297 for k
, v
in attrdict
.iteritems():
2298 if ifupdownflags
.flags
.CACHE
:
2299 curval
= portattrs
.get(k
)
2300 if curval
and curval
== v
:
2302 if k
== 'unicast-flood':
2303 self
.write_file('/sys/class/net/%s/brport/unicast_flood' % bridgeportname
, v
)
2304 elif k
== 'multicast-flood':
2305 self
.write_file('/sys/class/net/%s/brport/multicast_flood' % bridgeportname
, v
)
2306 elif k
== 'learning':
2307 self
.write_file('/sys/class/net/%s/brport/learning' % bridgeportname
, v
)
2308 elif k
== 'arp-nd-suppress':
2309 self
.write_file('/sys/class/net/%s/brport/neigh_suppress' % bridgeportname
, v
)
2311 if not LinkUtils
.bridge_utils_is_installed
:
2313 utils
.exec_command('%s set%s %s %s %s' % (utils
.brctl_cmd
, k
, bridgename
, bridgeportname
, v
))
2315 def set_bridgeport_attr(self
, bridgename
, bridgeportname
,
2317 if not LinkUtils
.bridge_utils_is_installed
:
2319 if self
._link
_cache
_check
([bridgename
, 'linkinfo', 'ports', bridgeportname
, attrname
], attrval
):
2321 utils
.exec_command('%s set%s %s %s %s' %
2328 def set_bridge_attrs(self
, bridgename
, attrdict
):
2329 for k
, v
in attrdict
.iteritems():
2332 if self
._link
_cache
_check
([bridgename
, 'linkinfo', k
], v
):
2335 if k
== 'igmp-version':
2336 self
.write_file('/sys/class/net/%s/bridge/'
2337 'multicast_igmp_version' % bridgename
, v
)
2338 elif k
== 'mld-version':
2339 self
.write_file('/sys/class/net/%s/bridge/'
2340 'multicast_mld_version' % bridgename
, v
)
2341 elif k
== 'vlan-protocol':
2342 self
.write_file('/sys/class/net/%s/bridge/'
2343 'vlan_protocol' % bridgename
,
2344 VlanProtocols
.ETHERTYPES_TO_ID
.get(v
.upper(),
2346 elif k
== 'vlan-stats':
2347 self
.write_file('/sys/class/net/%s/bridge/'
2348 'vlan_stats_enabled' % bridgename
, v
)
2349 elif k
== 'mcstats':
2350 self
.write_file('/sys/class/net/%s/bridge/'
2351 'multicast_stats_enabled' % bridgename
, v
)
2353 if not LinkUtils
.bridge_utils_is_installed
:
2355 cmd
= ('%s set%s %s %s' %
2356 (utils
.brctl_cmd
, k
, bridgename
, v
))
2357 utils
.exec_command(cmd
)
2358 except Exception, e
:
2359 self
.logger
.warn('%s: %s' % (bridgename
, str(e
)))
2362 def set_bridge_attr(self
, bridgename
, attrname
, attrval
):
2363 if self
._link
_cache
_check
([bridgename
, 'linkinfo', attrname
], attrval
):
2365 if attrname
== 'igmp-version':
2366 self
.write_file('/sys/class/net/%s/bridge/multicast_igmp_version'
2367 % bridgename
, attrval
)
2368 elif attrname
== 'mld-version':
2369 self
.write_file('/sys/class/net/%s/bridge/multicast_mld_version'
2370 % bridgename
, attrval
)
2371 elif attrname
== 'vlan-protocol':
2372 self
.write_file('/sys/class/net/%s/bridge/vlan_protocol'
2373 % bridgename
, VlanProtocols
.ETHERTYPES_TO_ID
[attrval
.upper()])
2374 elif attrname
== 'vlan-stats':
2375 self
.write_file('/sys/class/net/%s/bridge/vlan_stats_enabled'
2376 % bridgename
, attrval
)
2377 elif attrname
== 'mcstats':
2378 self
.write_file('/sys/class/net/%s/bridge/multicast_stats_enabled'
2379 % bridgename
, attrval
)
2381 if not LinkUtils
.bridge_utils_is_installed
:
2383 cmd
= '%s set%s %s %s' % (utils
.brctl_cmd
,
2384 attrname
, bridgename
, attrval
)
2385 utils
.exec_command(cmd
)
2387 def get_bridge_attrs(self
, bridgename
):
2388 attrs
= self
._link
_cache
_get
([bridgename
, 'linkinfo'])
2390 for key
, value
in attrs
.items():
2391 if type(key
) == str:
2392 no_ints_attrs
[key
] = value
2393 return no_ints_attrs
2395 def get_bridgeport_attrs(self
, bridgename
, bridgeportname
):
2396 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2399 def get_bridgeport_attr(self
, bridgename
, bridgeportname
, attrname
):
2400 return self
._link
_cache
_get
([bridgename
, 'linkinfo', 'ports',
2401 bridgeportname
, attrname
])
2404 def bridge_set_stp(bridge
, stp_state
):
2405 if not LinkUtils
.bridge_utils_is_installed
:
2407 utils
.exec_command('%s stp %s %s' % (utils
.brctl_cmd
, bridge
, stp_state
))
2409 def bridge_get_stp(self
, bridge
):
2410 sysfs_stpstate
= '/sys/class/net/%s/bridge/stp_state' % bridge
2411 if not os
.path
.exists(sysfs_stpstate
):
2413 stpstate
= self
.read_file_oneline(sysfs_stpstate
)
2417 if int(stpstate
) > 0:
2419 elif int(stpstate
) == 0:
2425 def _conv_value_to_user(s
):
2432 def read_value_from_sysfs(self
, filename
, preprocess_func
):
2433 value
= self
.read_file_oneline(filename
)
2436 return preprocess_func(value
)
2439 def bridge_set_ageing(bridge
, ageing
):
2440 if not LinkUtils
.bridge_utils_is_installed
:
2442 utils
.exec_command('%s setageing %s %s' % (utils
.brctl_cmd
, bridge
, ageing
))
2444 def bridge_get_ageing(self
, bridge
):
2445 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/ageing_time'
2446 % bridge
, self
._conv
_value
_to
_user
)
2449 def set_bridgeprio(bridge
, prio
):
2450 if not LinkUtils
.bridge_utils_is_installed
:
2452 utils
.exec_command('%s setbridgeprio %s %s' % (utils
.brctl_cmd
, bridge
, prio
))
2454 def get_bridgeprio(self
, bridge
):
2455 return self
.read_file_oneline(
2456 '/sys/class/net/%s/bridge/priority' % bridge
)
2459 def bridge_set_fd(bridge
, fd
):
2460 if not LinkUtils
.bridge_utils_is_installed
:
2462 utils
.exec_command('%s setfd %s %s' % (utils
.brctl_cmd
, bridge
, fd
))
2464 def bridge_get_fd(self
, bridge
):
2465 return self
.read_value_from_sysfs(
2466 '/sys/class/net/%s/bridge/forward_delay'
2467 % bridge
, self
._conv
_value
_to
_user
)
2469 def bridge_set_gcint(self
, bridge
, gcint
):
2470 raise Exception('set_gcint not implemented')
2473 def bridge_set_hello(bridge
, hello
):
2474 if not LinkUtils
.bridge_utils_is_installed
:
2476 utils
.exec_command('%s sethello %s %s' % (utils
.brctl_cmd
, bridge
, hello
))
2478 def bridge_get_hello(self
, bridge
):
2479 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/hello_time'
2480 % bridge
, self
._conv
_value
_to
_user
)
2483 def bridge_set_maxage(bridge
, maxage
):
2484 if not LinkUtils
.bridge_utils_is_installed
:
2486 utils
.exec_command('%s setmaxage %s %s' % (utils
.brctl_cmd
, bridge
, maxage
))
2488 def bridge_get_maxage(self
, bridge
):
2489 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/max_age'
2490 % bridge
, self
._conv
_value
_to
_user
)
2493 def bridge_set_pathcost(bridge
, port
, pathcost
):
2494 if not LinkUtils
.bridge_utils_is_installed
:
2496 utils
.exec_command('%s setpathcost %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, pathcost
))
2498 def bridge_get_pathcost(self
, bridge
, port
):
2499 return self
.read_file_oneline('/sys/class/net/%s/brport/path_cost'
2503 def bridge_set_portprio(bridge
, port
, prio
):
2504 if not LinkUtils
.bridge_utils_is_installed
:
2506 utils
.exec_command('%s setportprio %s %s %s' % (utils
.brctl_cmd
, bridge
, port
, prio
))
2508 def bridge_get_portprio(self
, bridge
, port
):
2509 return self
.read_file_oneline('/sys/class/net/%s/brport/priority'
2513 def bridge_set_hashmax(bridge
, hashmax
):
2514 if not LinkUtils
.bridge_utils_is_installed
:
2516 utils
.exec_command('%s sethashmax %s %s' % (utils
.brctl_cmd
, bridge
, hashmax
))
2518 def bridge_get_hashmax(self
, bridge
):
2519 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_max'
2523 def bridge_set_hashel(bridge
, hashel
):
2524 if not LinkUtils
.bridge_utils_is_installed
:
2526 utils
.exec_command('%s sethashel %s %s' % (utils
.brctl_cmd
, bridge
, hashel
))
2528 def bridge_get_hashel(self
, bridge
):
2529 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_elasticity'
2533 def bridge_set_mclmc(bridge
, mclmc
):
2534 if not LinkUtils
.bridge_utils_is_installed
:
2536 utils
.exec_command('%s setmclmc %s %s' % (utils
.brctl_cmd
, bridge
, mclmc
))
2538 def bridge_get_mclmc(self
, bridge
):
2539 return self
.read_file_oneline(
2540 '/sys/class/net/%s/bridge/multicast_last_member_count'
2544 def bridge_set_mcrouter(bridge
, mcrouter
):
2545 if not LinkUtils
.bridge_utils_is_installed
:
2547 utils
.exec_command('%s setmcrouter %s %s' % (utils
.brctl_cmd
, bridge
, mcrouter
))
2549 def bridge_get_mcrouter(self
, bridge
):
2550 return self
.read_file_oneline(
2551 '/sys/class/net/%s/bridge/multicast_router' % bridge
)
2554 def bridge_set_mcsnoop(bridge
, mcsnoop
):
2555 if not LinkUtils
.bridge_utils_is_installed
:
2557 utils
.exec_command('%s setmcsnoop %s %s' % (utils
.brctl_cmd
, bridge
, mcsnoop
))
2559 def bridge_get_mcsnoop(self
, bridge
):
2560 return self
.read_file_oneline(
2561 '/sys/class/net/%s/bridge/multicast_snooping' % bridge
)
2564 def bridge_set_mcsqc(bridge
, mcsqc
):
2565 if not LinkUtils
.bridge_utils_is_installed
:
2567 utils
.exec_command('%s setmcsqc %s %s' % (utils
.brctl_cmd
, bridge
, mcsqc
))
2569 def bridge_get_mcsqc(self
, bridge
):
2570 return self
.read_file_oneline(
2571 '/sys/class/net/%s/bridge/multicast_startup_query_count'
2575 def bridge_set_mcqifaddr(bridge
, mcqifaddr
):
2576 if not LinkUtils
.bridge_utils_is_installed
:
2578 utils
.exec_command('%s setmcqifaddr %s %s' % (utils
.brctl_cmd
, bridge
, mcqifaddr
))
2580 def bridge_get_mcqifaddr(self
, bridge
):
2581 return self
.read_file_oneline(
2582 '/sys/class/net/%s/bridge/multicast_startup_query_use_ifaddr'
2586 def bridge_set_mcquerier(bridge
, mcquerier
):
2587 if not LinkUtils
.bridge_utils_is_installed
:
2589 utils
.exec_command('%s setmcquerier %s %s' % (utils
.brctl_cmd
, bridge
, mcquerier
))
2591 def bridge_get_mcquerier(self
, bridge
):
2592 return self
.read_file_oneline(
2593 '/sys/class/net/%s/bridge/multicast_querier' % bridge
)
2595 def bridge_set_mcqv4src(self
, bridge
, vlan
, mcquerier
):
2599 self
.logger
.info('%s: set mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2601 if vlan
== 0 or vlan
> 4095:
2602 self
.logger
.warn('mcqv4src vlan \'%d\' invalid range' % vlan
)
2605 ip
= mcquerier
.split('.')
2607 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2610 if not k
.isdigit() or int(k
, 10) < 0 or int(k
, 10) > 255:
2611 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' % mcquerier
)
2614 if not LinkUtils
.bridge_utils_is_installed
:
2617 utils
.exec_command('%s setmcqv4src %s %d %s' %
2618 (utils
.brctl_cmd
, bridge
, vlan
, mcquerier
))
2620 def bridge_del_mcqv4src(self
, bridge
, vlan
):
2621 if not LinkUtils
.bridge_utils_is_installed
:
2626 self
.logger
.info('%s: del mcqv4src vlan: invalid parameter %s: %s' %(bridge
, vlan
, str(e
)))
2628 utils
.exec_command('%s delmcqv4src %s %d' % (utils
.brctl_cmd
, bridge
, vlan
))
2630 def bridge_get_mcqv4src(self
, bridge
, vlan
=None):
2631 if not LinkUtils
.bridge_utils_is_installed
:
2633 if not self
.supported_command
['showmcqv4src']:
2637 mcqout
= utils
.exec_command('%s showmcqv4src %s' %
2638 (utils
.brctl_cmd
, bridge
))
2639 except Exception as e
:
2641 if 'never heard' in s
:
2642 msg
= ('%s showmcqv4src: skipping unsupported command'
2644 self
.logger
.info(msg
)
2645 self
.supported_command
['showmcqv4src'] = False
2650 mcqlines
= mcqout
.splitlines()
2651 for l
in mcqlines
[1:]:
2653 k
, d
, v
= l
.split('\t')
2658 return mcqv4src
.get(vlan
)
2661 def bridge_get_mcqv4src_sysfs(self
, bridge
, vlan
=None):
2662 if not LinkUtils
.bridge_utils_is_installed
:
2664 if not self
.supported_command
['showmcqv4src']:
2666 if ifupdownflags
.flags
.PERFMODE
:
2670 filename
= '/sys/class/net/%s/bridge/multicast_v4_queriers' % bridge
2671 if os
.path
.exists(filename
):
2672 for line
in self
.read_file(filename
) or []:
2673 vlan_id
, ip
= line
.split('=')
2674 mcqv4src
[vlan_id
] = ip
.strip()
2675 except Exception as e
:
2677 msg
= ('%s showmcqv4src: skipping unsupported command'
2679 self
.logger
.info(msg
)
2680 self
.supported_command
['showmcqv4src'] = False
2683 return mcqv4src
.get(vlan
)
2687 def bridge_set_mclmi(bridge
, mclmi
):
2688 if not LinkUtils
.bridge_utils_is_installed
:
2690 utils
.exec_command('%s setmclmi %s %s' % (utils
.brctl_cmd
, bridge
, mclmi
))
2692 def bridge_get_mclmi(self
, bridge
):
2693 return self
.read_file_oneline(
2694 '/sys/class/net/%s/bridge/multicast_last_member_interval'
2698 def bridge_set_mcmi(bridge
, mcmi
):
2699 if not LinkUtils
.bridge_utils_is_installed
:
2701 utils
.exec_command('%s setmcmi %s %s' % (utils
.brctl_cmd
, bridge
, mcmi
))
2703 def bridge_get_mcmi(self
, bridge
):
2704 return self
.read_file_oneline(
2705 '/sys/class/net/%s/bridge/multicast_membership_interval'
2709 def bridge_exists(bridge
):
2710 return os
.path
.exists('/sys/class/net/%s/bridge' % bridge
)
2713 def is_bridge_port(ifacename
):
2714 return os
.path
.exists('/sys/class/net/%s/brport' % ifacename
)
2717 def bridge_port_exists(bridge
, bridgeportname
):
2719 return os
.path
.exists('/sys/class/net/%s/brif/%s' % (bridge
, bridgeportname
))
2724 def get_bridge_ports(bridgename
):
2726 return os
.listdir('/sys/class/net/%s/brif/' % bridgename
)
2730 def reset_addr_cache(self
, ifname
):
2732 linkCache
.links
[ifname
]['addrs'] = {}
2733 self
.logger
.debug('%s: reset address cache' % ifname
)
2737 def get_ipv6_addrgen_mode(self
, ifname
):
2739 return self
._cache
_get
('link', [ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
]
2741 # default to 0 (eui64)
2744 def ipv6_addrgen(self
, ifname
, addrgen
, link_created
):
2746 # IFLA_INET6_ADDR_GEN_MODE values:
2749 if self
._link
_cache
_get
([ifname
, 'af_spec', socket
.AF_INET6
])[Link
.IFLA_INET6_ADDR_GEN_MODE
] == addrgen
:
2750 self
.logger
.debug('%s: ipv6 addrgen already %s' % (ifname
, 'off' if addrgen
else 'on'))
2753 disabled_ipv6
= self
.read_file_oneline('/proc/sys/net/ipv6/conf/%s/disable_ipv6' % ifname
)
2754 if not disabled_ipv6
or int(disabled_ipv6
) == 1:
2755 self
.logger
.info('%s: cannot set addrgen: ipv6 is disabled on this device' % ifname
)
2758 if int(self
._link
_cache
_get
([ifname
, 'mtu'])) < 1280:
2759 self
.logger
.info('%s: ipv6 addrgen is disabled on device with MTU '
2760 'lower than 1280: cannot set addrgen %s' % (ifname
, 'off' if addrgen
else 'on'))
2762 except (KeyError, TypeError):
2763 self
.logger
.debug('%s: ipv6 addrgen probably not supported or disabled on this device' % ifname
)
2768 if not link_created
:
2769 # When setting addrgenmode it is necessary to flap the macvlan
2770 # device. After flapping the device we also need to re-add all
2771 # the user configuration. The best way to add the user config
2772 # is to flush our internal address cache
2773 self
.reset_addr_cache(ifname
)
2775 cmd
= 'link set dev %s addrgenmode %s' % (ifname
, Link
.ifla_inet6_addr_gen_mode_dict
.get(addrgen
))
2777 is_link_up
= self
.is_link_up(ifname
)
2780 self
.link_down(ifname
)
2782 #if LinkUtils.ipbatch:
2783 # self.add_to_batch(cmd)
2785 # because this command might fail on older kernel its better to not batch it
2786 utils
.exec_command('%s %s' % (utils
.ip_cmd
, cmd
))
2789 self
.link_up(ifname
)