]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdownaddons/iproute2.py
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
13 from ifupdown
.utils
import utils
14 from collections
import OrderedDict
15 from utilsbase
import *
16 from systemutils
import *
18 import ifupdown
.ifupdownflags
as ifupdownflags
22 class iproute2(utilsBase
):
23 """ This class contains helper methods to cache and interact with the
24 commands in the iproute2 package """
26 _cache_fill_done
= False
31 def __init__(self
, *args
, **kargs
):
32 utilsBase
.__init
__(self
, *args
, **kargs
)
33 if ifupdownflags
.flags
.CACHE
:
35 self
.supported_command
= {
36 '/sbin/bridge -c -json vlan show': True
39 def _fill_cache(self
):
40 if not iproute2
._cache_fill_done
:
43 iproute2
._cache_fill_done
= True
47 def _get_vland_id(self
, citems
, i
, warn
):
50 index
= sub
.index('id')
55 raise Exception('invalid use of \'vlan\' keyword')
58 def _link_fill(self
, ifacename
=None, refresh
=False):
59 """ fills cache with link information
61 if ifacename argument given, fill cache for ifacename, else
62 fill cache for all interfaces in the system
68 if iproute2
._cache_fill_done
and not refresh
: return
70 # if ifacename already present, return
71 if (ifacename
and not refresh
and
72 linkCache
.get_attr([ifacename
, 'ifflag'])):
76 cmdout
= self
.link_show(ifacename
=ifacename
)
79 # read vxrd.pid and cache the running state before going through
80 # every interface in the system
81 if systemUtils
.is_service_running(None, '/var/run/vxrd.pid'):
83 for c
in cmdout
.splitlines():
85 ifnamenlink
= citems
[1].split('@')
86 if len(ifnamenlink
) > 1:
87 ifname
= ifnamenlink
[0]
88 iflink
= ifnamenlink
[1].strip(':')
90 ifname
= ifnamenlink
[0].strip(':')
93 linkattrs
['link'] = iflink
94 linkattrs
['ifindex'] = citems
[0].strip(':')
95 flags
= citems
[2].strip('<>').split(',')
96 linkattrs
['flags'] = flags
97 linkattrs
['ifflag'] = 'UP' if 'UP' in flags
else 'DOWN'
98 for i
in range(0, len(citems
)):
100 if citems
[i
] == 'mtu':
101 linkattrs
['mtu'] = citems
[i
+ 1]
102 elif citems
[i
] == 'state':
103 linkattrs
['state'] = citems
[i
+ 1]
104 elif citems
[i
] == 'link/ether':
105 linkattrs
['hwaddress'] = citems
[i
+ 1]
106 elif citems
[i
] == 'vlan':
107 vlanid
= self
._get
_vland
_id
(citems
, i
, warn
)
109 linkattrs
['linkinfo'] = {'vlanid': vlanid
}
110 linkattrs
['kind'] = 'vlan'
111 elif citems
[i
] == 'dummy':
112 linkattrs
['kind'] = 'dummy'
113 elif citems
[i
] == 'vxlan' and citems
[i
+ 1] == 'id':
114 linkattrs
['kind'] = 'vxlan'
115 vattrs
= {'vxlanid': citems
[i
+ 2],
118 'ageing': citems
[i
+ 2],
120 for j
in range(i
+ 2, len(citems
)):
121 if citems
[j
] == 'local':
122 vattrs
['local'] = citems
[j
+ 1]
123 elif citems
[j
] == 'remote':
124 vattrs
['svcnode'] = citems
[j
+ 1]
125 elif citems
[j
] == 'ageing':
126 vattrs
['ageing'] = citems
[j
+ 1]
127 elif citems
[j
] == 'nolearning':
128 vattrs
['learning'] = 'off'
129 # get vxlan peer nodes if provisioned by user and not by vxrd
131 peers
= self
.get_vxlan_peers(ifname
, vattrs
['svcnode'])
133 vattrs
['remote'] = peers
134 linkattrs
['linkinfo'] = vattrs
136 elif citems
[i
] == 'vrf' and citems
[i
+ 1] == 'table':
137 vattrs
= {'table': citems
[i
+ 2]}
138 linkattrs
['linkinfo'] = vattrs
139 linkattrs
['kind'] = 'vrf'
140 linkCache
.vrfs
[ifname
] = vattrs
142 elif citems
[i
] == 'vrf_slave':
143 linkattrs
['kind'] = 'vrf_slave'
145 elif citems
[i
] == 'macvlan' and citems
[i
+ 1] == 'mode':
146 linkattrs
['kind'] = 'macvlan'
147 except Exception as e
:
149 self
.logger
.debug('%s: parsing error: id, mtu, state, link/ether, vlan, dummy, vxlan, local, remote, ageing, nolearning, vrf, table, vrf_slave are reserved keywords: %s' % (ifname
, str(e
)))
151 #linkattrs['alias'] = self.read_file_oneline(
152 # '/sys/class/net/%s/ifalias' %ifname)
153 linkout
[ifname
] = linkattrs
154 [linkCache
.update_attrdict([ifname
], linkattrs
)
155 for ifname
, linkattrs
in linkout
.items()]
157 def _addr_filter(self
, ifname
, addr
, scope
=None):
158 default_addrs
= ['127.0.0.1/8', '::1/128' , '0.0.0.0']
159 if ifname
== 'lo' and addr
in default_addrs
:
161 if scope
and scope
== 'link':
165 def _addr_fill(self
, ifacename
=None, refresh
=False):
166 """ fills cache with address information
168 if ifacename argument given, fill cache for ifacename, else
169 fill cache for all interfaces in the system
172 if iproute2
._cache_fill_done
and not refresh
: return
175 # Check if ifacename is already full, in which case, return
176 if ifacename
and not refresh
:
177 linkCache
.get_attr([ifacename
, 'addrs'])
181 cmdout
= self
.addr_show(ifacename
=ifacename
)
184 for c
in cmdout
.splitlines():
186 ifnamenlink
= citems
[1].split('@')
187 if len(ifnamenlink
) > 1:
188 ifname
= ifnamenlink
[0]
190 ifname
= ifnamenlink
[0].strip(':')
191 if not linkout
.get(ifname
):
193 linkattrs
['addrs'] = OrderedDict({})
195 linkout
[ifname
].update(linkattrs
)
197 linkout
[ifname
] = linkattrs
198 if citems
[2] == 'inet':
199 if self
._addr
_filter
(ifname
, citems
[3], scope
=citems
[5]):
202 addrattrs
['scope'] = citems
[5]
203 addrattrs
['type'] = 'inet'
204 linkout
[ifname
]['addrs'][citems
[3]] = addrattrs
205 elif citems
[2] == 'inet6':
206 if self
._addr
_filter
(ifname
, citems
[3], scope
=citems
[5]):
208 if citems
[5] == 'link': continue #skip 'link' addresses
210 addrattrs
['scope'] = citems
[5]
211 addrattrs
['type'] = 'inet6'
212 linkout
[ifname
]['addrs'][citems
[3]] = addrattrs
213 [linkCache
.update_attrdict([ifname
], linkattrs
)
214 for ifname
, linkattrs
in linkout
.items()]
216 def _cache_get(self
, type, attrlist
, refresh
=False):
218 if ifupdownflags
.flags
.DRYRUN
:
220 if ifupdownflags
.flags
.CACHE
:
221 if self
._fill
_cache
():
222 # if we filled the cache, return new data
223 return linkCache
.get_attr(attrlist
)
225 return linkCache
.get_attr(attrlist
)
227 self
._link
_fill
(attrlist
[0], refresh
)
229 self
._addr
_fill
(attrlist
[0], refresh
)
231 self
._link
_fill
(attrlist
[0], refresh
)
232 self
._addr
_fill
(attrlist
[0], refresh
)
233 return linkCache
.get_attr(attrlist
)
235 self
.logger
.debug('_cache_get(%s) : [%s]'
236 %(str(attrlist
), str(e
)))
240 def _cache_check(self
, type, attrlist
, value
, refresh
=False):
242 attrvalue
= self
._cache
_get
(type, attrlist
, refresh
)
243 if attrvalue
and attrvalue
== value
:
246 self
.logger
.debug('_cache_check(%s) : [%s]'
247 %(str(attrlist
), str(e
)))
251 def _cache_update(self
, attrlist
, value
):
252 if ifupdownflags
.flags
.DRYRUN
: return
254 linkCache
.set_attr(attrlist
, value
)
258 def _cache_delete(self
, attrlist
):
259 if ifupdownflags
.flags
.DRYRUN
: return
261 linkCache
.del_attr(attrlist
)
265 def _cache_invalidate(self
):
266 linkCache
.invalidate()
267 iproute2
._cache_fill_done
= False
269 def batch_start(self
):
272 self
.ipbatch_pause
= False
274 def add_to_batch(self
, cmd
):
275 self
.ipbatchbuf
+= cmd
+ '\n'
277 def batch_pause(self
):
278 self
.ipbatch_pause
= True
280 def batch_resume(self
):
281 self
.ipbatch_pause
= False
283 def batch_commit(self
):
284 if not self
.ipbatchbuf
:
287 self
.ipbatch_pause
= False
290 utils
.exec_command('ip -force -batch -', stdin
=self
.ipbatchbuf
)
296 self
.ipbatch_pause
= False
298 def bridge_batch_commit(self
):
299 if not self
.ipbatchbuf
:
302 self
.ipbatch_pause
= False
305 utils
.exec_command('bridge -force -batch -', stdin
=self
.ipbatchbuf
)
311 self
.ipbatch_pause
= False
313 def addr_show(self
, ifacename
=None):
315 if not self
.link_exists(ifacename
):
317 return utils
.exec_commandl(['ip', '-o', 'addr', 'show', 'dev',
320 return utils
.exec_commandl(['ip', '-o', 'addr', 'show'])
322 def link_show(self
, ifacename
=None):
324 return utils
.exec_commandl(['ip', '-o', '-d', 'link', 'show', 'dev',
327 return utils
.exec_commandl(['ip', '-o', '-d', 'link', 'show'])
329 def addr_add(self
, ifacename
, address
, broadcast
=None,
330 peer
=None, scope
=None, preferred_lifetime
=None):
333 cmd
= 'addr add %s' %address
335 cmd
+= ' broadcast %s' %broadcast
337 cmd
+= ' peer %s' %peer
339 cmd
+= ' scope %s' %scope
340 if preferred_lifetime
:
341 cmd
+= ' preferred_lft %s' %preferred_lifetime
342 cmd
+= ' dev %s' %ifacename
343 if self
.ipbatch
and not self
.ipbatch_pause
:
344 self
.add_to_batch(cmd
)
346 utils
.exec_command('ip %s' % cmd
)
347 self
._cache
_update
([ifacename
, 'addrs', address
], {})
349 def addr_del(self
, ifacename
, address
, broadcast
=None,
350 peer
=None, scope
=None):
351 """ Delete ipv4 address """
354 if not self
._cache
_get
('addr', [ifacename
, 'addrs', address
]):
356 cmd
= 'addr del %s' %address
358 cmd
+= 'broadcast %s' %broadcast
360 cmd
+= 'peer %s' %peer
362 cmd
+= 'scope %s' %scope
363 cmd
+= ' dev %s' %ifacename
364 utils
.exec_command('ip %s' % cmd
)
365 self
._cache
_delete
([ifacename
, 'addrs', address
])
367 def addr_flush(self
, ifacename
):
368 cmd
= 'addr flush dev %s' %ifacename
369 if self
.ipbatch
and not self
.ipbatch_pause
:
370 self
.add_to_batch(cmd
)
372 utils
.exec_command('ip %s' % cmd
)
373 self
._cache
_delete
([ifacename
, 'addrs'])
375 def del_addr_all(self
, ifacename
, skip_addrs
=[]):
376 if not skip_addrs
: skip_addrs
= []
377 runningaddrsdict
= self
.addr_get(ifacename
)
379 # XXX: ignore errors. Fix this to delete secondary addresses
381 [self
.addr_del(ifacename
, a
) for a
in
382 set(runningaddrsdict
.keys()).difference(skip_addrs
)]
387 def addr_get(self
, ifacename
, details
=True, refresh
=False):
388 addrs
= self
._cache
_get
('addr', [ifacename
, 'addrs'],
396 def addr_add_multiple(self
, ifacename
, addrs
, purge_existing
=False):
399 # if perfmode is not set and also if iface has no sibling
400 # objects, purge addresses that are not present in the new
402 runningaddrs
= self
.addr_get(ifacename
, details
=False)
403 if addrs
== runningaddrs
:
406 # if primary address is not same, there is no need to keep any.
407 # reset all addresses
408 if (addrs
and runningaddrs
and
409 (addrs
[0] != runningaddrs
[0])):
410 self
.del_addr_all(ifacename
)
412 self
.del_addr_all(ifacename
, addrs
)
414 self
.log_warn(str(e
))
417 self
.addr_add(ifacename
, a
)
419 self
.logger
.error(str(e
))
421 def _link_set_ifflag(self
, ifacename
, value
):
422 # Dont look at the cache, the cache may have stale value
423 # because link status can be changed by external
424 # entity (One such entity is ifupdown main program)
425 cmd
= 'link set dev %s %s' %(ifacename
, value
.lower())
427 self
.add_to_batch(cmd
)
429 utils
.exec_command('ip %s' % cmd
)
431 def link_up(self
, ifacename
):
432 self
._link
_set
_ifflag
(ifacename
, 'UP')
434 def link_down(self
, ifacename
):
435 self
._link
_set
_ifflag
(ifacename
, 'DOWN')
437 def link_set(self
, ifacename
, key
, value
=None,
438 force
=False, type=None, state
=None):
440 if (key
not in ['master', 'nomaster'] and
441 self
._cache
_check
('link', [ifacename
, key
], value
)):
443 cmd
= 'link set dev %s' %ifacename
445 cmd
+= ' type %s' %type
452 self
.add_to_batch(cmd
)
454 utils
.exec_command('ip %s' % cmd
)
455 if key
not in ['master', 'nomaster']:
456 self
._cache
_update
([ifacename
, key
], value
)
458 def link_set_hwaddress(self
, ifacename
, hwaddress
, force
=False):
460 if self
._cache
_check
('link', [ifacename
, 'hwaddress'], hwaddress
):
462 self
.link_down(ifacename
)
463 cmd
= 'link set dev %s address %s' %(ifacename
, hwaddress
)
465 self
.add_to_batch(cmd
)
467 utils
.exec_command('ip %s' % cmd
)
468 self
.link_up(ifacename
)
469 self
._cache
_update
([ifacename
, 'hwaddress'], hwaddress
)
471 def link_set_mtu(self
, ifacename
, mtu
):
472 if ifupdownflags
.flags
.DRYRUN
:
474 if not mtu
or not ifacename
: return
475 with
open('/sys/class/net/%s/mtu' % ifacename
, 'w') as f
:
477 self
._cache
_update
([ifacename
, 'mtu'], mtu
)
479 def link_set_alias(self
, ifacename
, alias
):
481 utils
.exec_user_command('echo "" > /sys/class/net/%s/ifalias'
484 self
.write_file('/sys/class/net/%s/ifalias' % ifacename
, alias
)
486 def link_get_alias(self
, ifacename
):
487 return self
.read_file_oneline('/sys/class/net/%s/ifalias'
490 def link_isloopback(self
, ifacename
):
491 flags
= self
._cache
_get
('link', [ifacename
, 'flags'])
494 if 'LOOPBACK' in flags
:
498 def link_get_status(self
, ifacename
):
499 return self
._cache
_get
('link', [ifacename
, 'ifflag'], refresh
=True)
501 def route_add_gateway(self
, ifacename
, gateway
, vrf
=None, metric
=None):
505 cmd
= 'ip route add default via %s' %gateway
507 cmd
= 'ip route add table %s default via %s' %(vrf
, gateway
)
510 cmd
+= 'metric %s' %metric
511 cmd
+= ' dev %s' %ifacename
512 utils
.exec_command(cmd
)
514 def route_del_gateway(self
, ifacename
, gateway
, vrf
=None, metric
=None):
519 cmd
= 'ip route del default via %s' %gateway
521 cmd
= 'ip route del table %s default via %s' %(vrf
, gateway
)
523 cmd
+= ' metric %s' %metric
524 cmd
+= ' dev %s' %ifacename
525 utils
.exec_command(cmd
)
527 def route6_add_gateway(self
, ifacename
, gateway
):
530 return utils
.exec_command('ip -6 route add default via %s dev %s' %
531 (gateway
, ifacename
))
533 def route6_del_gateway(self
, ifacename
, gateway
):
536 return utils
.exec_command('ip -6 route del default via %s dev %s' %
537 (gateway
, ifacename
))
539 def link_create_vlan(self
, vlan_device_name
, vlan_raw_device
, vlanid
):
540 if self
.link_exists(vlan_device_name
):
542 utils
.exec_command('ip link add link %s name %s type vlan id %d' %
543 (vlan_raw_device
, vlan_device_name
, vlanid
))
544 self
._cache
_update
([vlan_device_name
], {})
546 def link_create_vlan_from_name(self
, vlan_device_name
):
547 v
= vlan_device_name
.split('.')
549 self
.logger
.warn('invalid vlan device name %s' %vlan_device_name
)
551 self
.link_create_vlan(vlan_device_name
, v
[0], v
[1])
553 def link_create_macvlan(self
, name
, linkdev
, mode
='private'):
554 if self
.link_exists(name
):
556 cmd
= ('link add link %s' %linkdev
+
558 ' type macvlan mode %s' %mode
)
559 if self
.ipbatch
and not self
.ipbatch_pause
:
560 self
.add_to_batch(cmd
)
562 utils
.exec_command('ip %s' % cmd
)
563 self
._cache
_update
([name
], {})
565 def get_vxlan_peers(self
, dev
, svcnodeip
):
566 cmd
= 'bridge fdb show brport %s' % dev
569 ps
= subprocess
.Popen(shlex
.split(cmd
), stdout
=subprocess
.PIPE
, close_fds
=False)
570 utils
.enable_subprocess_signal_forwarding(ps
, signal
.SIGINT
)
571 output
= subprocess
.check_output(('grep', '00:00:00:00:00:00'), stdin
=ps
.stdout
)
573 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
575 ppat
= re
.compile('\s+dst\s+(\d+.\d+.\d+.\d+)\s+')
576 for l
in output
.split('\n'):
578 if m
and m
.group(1) != svcnodeip
:
579 cur_peers
.append(m
.group(1))
581 self
.logger
.warn('error parsing ip link output')
583 except subprocess
.CalledProcessError
as e
:
584 if e
.returncode
!= 1:
585 self
.logger
.error(str(e
))
587 utils
.disable_subprocess_signal_forwarding(signal
.SIGINT
)
591 def link_create_vxlan(self
, name
, vxlanid
,
598 if svcnodeip
and remoteips
:
599 raise Exception("svcnodeip and remoteip is mutually exclusive")
602 args
+= ' remote %s' %svcnodeip
604 args
+= ' ageing %s' %ageing
605 if learning
== 'off':
606 args
+= ' nolearning'
608 if self
.link_exists(name
):
609 cmd
= 'link set dev %s type vxlan dstport %d' %(name
, VXLAN_UDP_PORT
)
610 vxlanattrs
= self
.get_vxlandev_attrs(name
)
611 # on ifreload do not overwrite anycast_ip to individual ip if clagd
614 running_localtunnelip
= vxlanattrs
.get('local')
615 if anycastip
and running_localtunnelip
and anycastip
== running_localtunnelip
:
616 localtunnelip
= running_localtunnelip
617 running_svcnode
= vxlanattrs
.get('svcnode')
618 if running_svcnode
and not svcnodeip
:
621 cmd
= 'link add dev %s type vxlan id %s dstport %d' %(name
, vxlanid
, VXLAN_UDP_PORT
)
624 args
+= ' local %s' %localtunnelip
627 if self
.ipbatch
and not self
.ipbatch_pause
:
628 self
.add_to_batch(cmd
)
630 utils
.exec_command('ip %s' % cmd
)
632 # XXX: update linkinfo correctly
633 self
._cache
_update
([name
], {})
635 def link_exists(self
, ifacename
):
636 if ifupdownflags
.flags
.DRYRUN
:
638 return os
.path
.exists('/sys/class/net/%s' %ifacename
)
640 def link_get_ifindex(self
, ifacename
):
641 if ifupdownflags
.flags
.DRYRUN
:
643 return self
.read_file_oneline('/sys/class/net/%s/ifindex' %ifacename
)
645 def is_vlan_device_by_name(self
, ifacename
):
646 if re
.search(r
'\.', ifacename
):
650 def route_add(self
, route
):
651 utils
.exec_command('ip route add %s' % route
)
653 def route6_add(self
, route
):
654 utils
.exec_command('ip -6 route add %s' % route
)
656 def get_vlandev_attrs(self
, ifacename
):
657 return (self
._cache
_get
('link', [ifacename
, 'link']),
658 self
._cache
_get
('link', [ifacename
, 'linkinfo', 'vlanid']))
660 def get_vxlandev_attrs(self
, ifacename
):
661 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
663 def get_vxlandev_learning(self
, ifacename
):
664 return self
._cache
_get
('link', [ifacename
, 'linkinfo', 'learning'])
666 def set_vxlandev_learning(self
, ifacename
, learn
):
668 utils
.exec_command('ip link set dev %s type vxlan learning' %ifacename
)
669 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'on')
671 utils
.exec_command('ip link set dev %s type vxlan nolearning' %ifacename
)
672 self
._cache
_update
([ifacename
, 'linkinfo', 'learning'], 'off')
674 def link_get_linkinfo_attrs(self
, ifacename
):
675 return self
._cache
_get
('link', [ifacename
, 'linkinfo'])
677 def link_get_mtu(self
, ifacename
, refresh
=False):
678 return self
._cache
_get
('link', [ifacename
, 'mtu'], refresh
=refresh
)
680 def link_get_mtu_sysfs(self
, ifacename
):
681 return self
.read_file_oneline('/sys/class/net/%s/mtu'
684 def link_get_kind(self
, ifacename
):
685 return self
._cache
_get
('link', [ifacename
, 'kind'])
687 def link_get_hwaddress(self
, ifacename
):
688 address
= self
._cache
_get
('link', [ifacename
, 'hwaddress'])
689 # newly created logical interface addresses dont end up in the cache
690 # read hwaddress from sysfs file for these interfaces
692 address
= self
.read_file_oneline('/sys/class/net/%s/address'
696 def link_create(self
, ifacename
, type, attrs
={}):
697 """ generic link_create function """
698 if self
.link_exists(ifacename
):
701 cmd
+= ' name %s type %s' %(ifacename
, type)
703 for k
, v
in attrs
.iteritems():
707 if self
.ipbatch
and not self
.ipbatch_pause
:
708 self
.add_to_batch(cmd
)
710 utils
.exec_command('ip %s' % cmd
)
711 self
._cache
_update
([ifacename
], {})
713 def link_delete(self
, ifacename
):
714 if not self
.link_exists(ifacename
):
716 cmd
= 'link del %s' %ifacename
717 if self
.ipbatch
and not self
.ipbatch_pause
:
718 self
.add_to_batch(cmd
)
720 utils
.exec_command('ip %s' % cmd
)
721 self
._cache
_invalidate
()
723 def link_get_master(self
, ifacename
):
724 sysfs_master_path
= '/sys/class/net/%s/master' %ifacename
725 if os
.path
.exists(sysfs_master_path
):
726 link_path
= os
.readlink(sysfs_master_path
)
728 return os
.path
.basename(link_path
)
732 return self
._cache
_get
('link', [ifacename
, 'master'])
734 def bridge_port_vids_add(self
, bridgeportname
, vids
):
735 [utils
.exec_command('bridge vlan add vid %s dev %s' %
736 (v
, bridgeportname
)) for v
in vids
]
738 def bridge_port_vids_del(self
, bridgeportname
, vids
):
741 [utils
.exec_command('bridge vlan del vid %s dev %s' %
742 (v
, bridgeportname
)) for v
in vids
]
744 def bridge_port_vids_flush(self
, bridgeportname
, vid
):
745 utils
.exec_command('bridge vlan del vid %s dev %s' %
746 (vid
, bridgeportname
))
748 def bridge_port_vids_get(self
, bridgeportname
):
749 utils
.exec_command('/sbin/bridge vlan show %s' % bridgeportname
)
750 bridgeout
= utils
.exec_command('/sbin/bridge vlan show dev %s' %
752 if not bridgeout
: return []
753 brvlanlines
= bridgeout
.readlines()[2:]
754 vids
= [l
.strip() for l
in brvlanlines
]
755 return [v
for v
in vids
if v
]
757 def bridge_port_vids_get_all(self
):
759 bridgeout
= utils
.exec_command('/sbin/bridge -c vlan show')
760 if not bridgeout
: return brvlaninfo
761 brvlanlines
= bridgeout
.splitlines()
763 for l
in brvlanlines
[1:]:
764 if l
and not l
.startswith(' ') and not l
.startswith('\t'):
766 brportname
= attrs
[0].strip()
767 brvlaninfo
[brportname
] = {'pvid' : None, 'vlan' : []}
768 l
= ' '.join(attrs
[1:])
769 if not brportname
or not l
:
773 brvlaninfo
[brportname
]['pvid'] = l
.split()[0]
774 elif 'Egress Untagged' not in l
:
775 brvlaninfo
[brportname
]['vlan'].append(l
)
778 def bridge_port_vids_get_all_json(self
):
779 if not self
.supported_command
['/sbin/bridge -c -json vlan show']:
783 bridgeout
= utils
.exec_command('/sbin/bridge -c -json vlan show')
785 self
.supported_command
['/sbin/bridge -c -json vlan show'] = False
786 self
.logger
.info('/sbin/bridge -c -json vlan show: skipping unsupported command')
788 if not bridgeout
: return brvlaninfo
790 vlan_json_dict
= json
.loads(bridgeout
, encoding
="utf-8")
792 self
.logger
.info('json loads failed with (%s)' %str
(e
))
794 return vlan_json_dict
796 def bridge_port_pvid_add(self
, bridgeportname
, pvid
):
797 if self
.ipbatch
and not self
.ipbatch_pause
:
798 self
.add_to_batch('vlan add vid %s untagged pvid dev %s' %
799 (pvid
, bridgeportname
))
801 utils
.exec_command('bridge vlan add vid %s untagged pvid dev %s' %
802 (pvid
, bridgeportname
))
804 def bridge_port_pvid_del(self
, bridgeportname
, pvid
):
805 if self
.ipbatch
and not self
.ipbatch_pause
:
806 self
.add_to_batch('vlan del vid %s untagged pvid dev %s' %
807 (pvid
, bridgeportname
))
809 utils
.exec_command('bridge vlan del vid %s untagged pvid dev %s' %
810 (pvid
, bridgeportname
))
812 def bridge_port_pvids_get(self
, bridgeportname
):
813 return self
.read_file_oneline('/sys/class/net/%s/brport/pvid'
816 def bridge_vids_add(self
, bridgeportname
, vids
, bridge
=True):
817 target
= 'self' if bridge
else ''
818 if self
.ipbatch
and not self
.ipbatch_pause
:
819 [self
.add_to_batch('vlan add vid %s dev %s %s' %
820 (v
, bridgeportname
, target
)) for v
in vids
]
822 [utils
.exec_command('bridge vlan add vid %s dev %s %s' %
823 (v
, bridgeportname
, target
)) for v
in vids
]
825 def bridge_vids_del(self
, bridgeportname
, vids
, bridge
=True):
826 target
= 'self' if bridge
else ''
827 if self
.ipbatch
and not self
.ipbatch_pause
:
828 [self
.add_to_batch('vlan del vid %s dev %s %s' %
829 (v
, bridgeportname
, target
)) for v
in vids
]
831 [utils
.exec_command('bridge vlan del vid %s dev %s %s' %
832 (v
, bridgeportname
, target
)) for v
in vids
]
834 def bridge_fdb_add(self
, dev
, address
, vlan
=None, bridge
=True, remote
=None):
835 target
= 'self' if bridge
else ''
838 vlan_str
= 'vlan %s ' % vlan
842 dst_str
= 'dst %s ' % remote
844 utils
.exec_command('bridge fdb replace %s dev %s %s %s %s' %
845 (address
, dev
, vlan_str
, target
, dst_str
))
847 def bridge_fdb_append(self
, dev
, address
, vlan
=None, bridge
=True, remote
=None):
848 target
= 'self' if bridge
else ''
851 vlan_str
= 'vlan %s ' % vlan
855 dst_str
= 'dst %s ' % remote
857 utils
.exec_command('bridge fdb append %s dev %s %s %s %s' %
858 (address
, dev
, vlan_str
, target
, dst_str
))
860 def bridge_fdb_del(self
, dev
, address
, vlan
=None, bridge
=True, remote
=None):
861 target
= 'self' if bridge
else ''
864 vlan_str
= 'vlan %s ' % vlan
868 dst_str
= 'dst %s ' % remote
869 utils
.exec_command('bridge fdb del %s dev %s %s %s %s' %
870 (address
, dev
, vlan_str
, target
, dst_str
))
872 def bridge_is_vlan_aware(self
, bridgename
):
873 filename
= '/sys/class/net/%s/bridge/vlan_filtering' %bridgename
874 if os
.path
.exists(filename
) and self
.read_file_oneline(filename
) == '1':
878 def bridge_port_get_bridge_name(self
, bridgeport
):
879 filename
= '/sys/class/net/%s/brport/bridge' %bridgeport
881 return os
.path
.basename(os
.readlink(filename
))
885 def bridge_port_exists(self
, bridge
, bridgeportname
):
887 return os
.path
.exists('/sys/class/net/%s/brif/%s'
888 %(bridge
, bridgeportname
))
892 def bridge_fdb_show_dev(self
, dev
):
895 output
= utils
.exec_command('bridge fdb show dev %s' % dev
)
897 for fdb_entry
in output
.splitlines():
899 entries
= fdb_entry
.split()
900 fdbs
.setdefault(entries
[2], []).append(entries
[0])
902 self
.logger
.debug('%s: invalid fdb line \'%s\''
909 def is_bridge(self
, bridge
):
910 return os
.path
.exists('/sys/class/net/%s/bridge' %bridge
)
912 def is_link_up(self
, ifacename
):
915 flags
= self
.read_file_oneline('/sys/class/net/%s/flags' %ifacename
)
916 iflags
= int(flags
, 16)
917 if (iflags
& 0x0001):
924 def ip_route_get_dev(self
, prefix
):
926 output
= utils
.exec_command('ip route get %s' % prefix
)
928 rline
= output
.splitlines()[0]
930 rattrs
= rline
.split()
931 return rattrs
[rattrs
.index('dev') + 1]
933 self
.logger
.debug('ip_route_get_dev: failed .. %s' %str
(e
))
937 def link_get_lowers(self
, ifacename
):
939 lowers
= glob
.glob("/sys/class/net/%s/lower_*" %ifacename
)
942 return [os
.path
.basename(l
)[6:] for l
in lowers
]
946 def link_get_uppers(self
, ifacename
):
948 uppers
= glob
.glob("/sys/class/net/%s/upper_*" %ifacename
)
951 return [ os
.path
.basename(u
)[6:] for u
in uppers
]
955 def link_get_vrfs(self
):
957 return linkCache
.vrfs
959 def get_brport_learning(self
, ifacename
):
960 learn
= self
.read_file_oneline('/sys/class/net/%s/brport/learning'
962 if learn
and learn
== '1':
967 def set_brport_learning(self
, ifacename
, learn
):
969 return self
.write_file('/sys/class/net/%s/brport/learning'
972 return self
.write_file('/sys/class/net/%s/brport/learning'