]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdownaddons/iproute2.py
Fix ip addr parsing breakage on sid
[mirror_ifupdown2.git] / ifupdownaddons / iproute2.py
CommitLineData
15ef32ea
RP
1#!/usr/bin/python
2#
3# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6
7import os
8from collections import OrderedDict
9from utilsbase import *
10from cache import *
11
44533c72
WK
12VXLAN_UDP_PORT = 4789
13
15ef32ea
RP
14class iproute2(utilsBase):
15 """ This class contains helper methods to cache and interact with the
16 commands in the iproute2 package """
17
18 _cache_fill_done = False
19 ipbatchbuf = ''
20 ipbatch = False
21 ipbatch_pause = False
22
23 def __init__(self, *args, **kargs):
24 utilsBase.__init__(self, *args, **kargs)
25 if self.CACHE and not iproute2._cache_fill_done:
26 self._link_fill()
27 self._addr_fill()
28 iproute2._cache_fill_done = True
29
30 def _link_fill(self, ifacename=None, refresh=False):
31 """ fills cache with link information
32
33 if ifacename argument given, fill cache for ifacename, else
34 fill cache for all interfaces in the system
35 """
36
37 linkout = {}
38 if iproute2._cache_fill_done and not refresh: return
39 try:
40 # if ifacename already present, return
41 if (ifacename and not refresh and
42 linkCache.get_attr([ifacename, 'ifflag'])):
43 return
44 except:
45 pass
46 cmdout = self.link_show(ifacename=ifacename)
47 if not cmdout:
48 return
49 for c in cmdout.splitlines():
50 citems = c.split()
51 ifnamenlink = citems[1].split('@')
52 if len(ifnamenlink) > 1:
53 ifname = ifnamenlink[0]
54 iflink = ifnamenlink[1].strip(':')
55 else:
56 ifname = ifnamenlink[0].strip(':')
57 iflink = None
58 linkattrs = {}
59 linkattrs['link'] = iflink
60 linkattrs['ifindex'] = citems[0].strip(':')
61 flags = citems[2].strip('<>').split(',')
62 linkattrs['flags'] = flags
63 linkattrs['ifflag'] = 'UP' if 'UP' in flags else 'DOWN'
64 for i in range(0, len(citems)):
65 if citems[i] == 'mtu': linkattrs['mtu'] = citems[i+1]
66 elif citems[i] == 'state': linkattrs['state'] = citems[i+1]
67 elif citems[i] == 'link/ether': linkattrs['hwaddress'] = citems[i+1]
68 elif citems[i] == 'vlan' and citems[i+1] == 'id':
69 linkattrs['linkinfo'] = {'vlanid' : citems[i+2]}
70 elif citems[i] == 'vxlan' and citems[i+1] == 'id':
71 vattrs = {'vxlanid' : citems[i+2],
9e012f9e 72 'svcnode' : [],
44533c72 73 'remote' : [],
88a5c4c8 74 'ageing' : citems[i+2],
9e012f9e 75 'learning': 'on'}
15ef32ea
RP
76 for j in range(i+2, len(citems)):
77 if citems[j] == 'local':
78 vattrs['local'] = citems[j+1]
79 elif citems[j] == 'svcnode':
80 vattrs['svcnode'].append(citems[j+1])
88a5c4c8 81 elif citems[j] == 'ageing':
76cb1a63 82 vattrs['ageing'] = citems[j+1]
9e012f9e
RP
83 elif citems[j] == 'nolearning':
84 vattrs['learning'] = 'off'
44533c72
WK
85 # get vxlan peer nodes
86 peers = self.get_vxlan_peers(ifname)
87 if peers:
88 vattrs['remote'] = peers
15ef32ea
RP
89 linkattrs['linkinfo'] = vattrs
90 break
91 #linkattrs['alias'] = self.read_file_oneline(
92 # '/sys/class/net/%s/ifalias' %ifname)
93 linkout[ifname] = linkattrs
94 [linkCache.update_attrdict([ifname], linkattrs)
95 for ifname, linkattrs in linkout.items()]
96
97 def _addr_filter(self, addr, scope=None):
98 default_addrs = ['127.0.0.1/8', '::1/128' , '0.0.0.0']
99 if addr in default_addrs:
100 return True
101 if scope and scope == 'link':
102 return True
103 return False
104
105 def _addr_fill(self, ifacename=None, refresh=False):
106 """ fills cache with address information
107
108 if ifacename argument given, fill cache for ifacename, else
109 fill cache for all interfaces in the system
110 """
111
112 linkout = {}
113 if iproute2._cache_fill_done: return
114 try:
115 # Check if ifacename is already full, in which case, return
116 if ifacename:
117 linkCache.get_attr([ifacename, 'addrs'])
118 return
119 except:
120 pass
121 cmdout = self.addr_show(ifacename=ifacename)
122 if not cmdout:
123 return
124 for c in cmdout.splitlines():
125 citems = c.split()
126 ifnamenlink = citems[1].split('@')
127 if len(ifnamenlink) > 1:
128 ifname = ifnamenlink[0]
129 else:
130 ifname = ifnamenlink[0].strip(':')
c78cae3d
RP
131 if not linkout.get(ifname):
132 linkattrs = {}
133 linkattrs['addrs'] = OrderedDict({})
134 try:
135 linkout[ifname].update(linkattrs)
136 except KeyError:
137 linkout[ifname] = linkattrs
15ef32ea
RP
138 if citems[2] == 'inet':
139 if self._addr_filter(citems[3], scope=citems[5]):
140 continue
141 addrattrs = {}
142 addrattrs['scope'] = citems[5]
143 addrattrs['type'] = 'inet'
144 linkout[ifname]['addrs'][citems[3]] = addrattrs
145 elif citems[2] == 'inet6':
146 if self._addr_filter(citems[3], scope=citems[5]):
147 continue
148 if citems[5] == 'link': continue #skip 'link' addresses
149 addrattrs = {}
150 addrattrs['scope'] = citems[5]
151 addrattrs['type'] = 'inet6'
152 linkout[ifname]['addrs'][citems[3]] = addrattrs
15ef32ea
RP
153 [linkCache.update_attrdict([ifname], linkattrs)
154 for ifname, linkattrs in linkout.items()]
155
156 def _cache_get(self, type, attrlist, refresh=False):
157 try:
158 if self.DRYRUN:
159 return False
160 if self.CACHE:
161 if not iproute2._cache_fill_done:
162 self._link_fill()
163 self._addr_fill()
164 iproute2._cache_fill_done = True
165 return linkCache.get_attr(attrlist)
166 if not refresh:
167 return linkCache.get_attr(attrlist)
168 if type == 'link':
169 self._link_fill(attrlist[0], refresh)
170 elif type == 'addr':
171 self._addr_fill(attrlist[0], refresh)
172 else:
173 self._link_fill(attrlist[0], refresh)
174 self._addr_fill(attrlist[0], refresh)
175 return linkCache.get_attr(attrlist)
176 except Exception, e:
177 self.logger.debug('_cache_get(%s) : [%s]'
178 %(str(attrlist), str(e)))
179 pass
180 return None
181
182 def _cache_check(self, type, attrlist, value, refresh=False):
183 try:
184 attrvalue = self._cache_get(type, attrlist, refresh)
185 if attrvalue and attrvalue == value:
186 return True
187 except Exception, e:
188 self.logger.debug('_cache_check(%s) : [%s]'
189 %(str(attrlist), str(e)))
190 pass
191 return False
192
193 def _cache_update(self, attrlist, value):
194 if self.DRYRUN: return
195 try:
196 linkCache.add_attr(attrlist, value)
197 except:
198 pass
199
200 def _cache_delete(self, attrlist):
201 if self.DRYRUN: return
202 try:
203 linkCache.del_attr(attrlist)
204 except:
205 pass
206
207 def _cache_invalidate(self):
208 linkCache.invalidate()
209
210 def batch_start(self):
211 self.ipbatcbuf = ''
212 self.ipbatch = True
213 self.ipbatch_pause = False
214
215 def add_to_batch(self, cmd):
216 self.ipbatchbuf += cmd + '\n'
217
218 def batch_pause(self):
219 self.ipbatch_pause = True
220
221 def batch_resume(self):
222 self.ipbatch_pause = False
223
224 def batch_commit(self):
225 if not self.ipbatchbuf:
226 return
227 try:
228 self.exec_command_talk_stdin('ip -force -batch -',
229 stdinbuf=self.ipbatchbuf)
230 except Exception:
231 raise
232 finally:
233 self.ipbatchbuf = ''
234 self.ipbatch = False
235 self.ipbatch_pause = False
236
237 def addr_show(self, ifacename=None):
238 if ifacename:
239 if not self.link_exists(ifacename):
240 return
241 return self.exec_commandl(['ip','-o', 'addr', 'show', 'dev',
242 '%s' %ifacename])
243 else:
244 return self.exec_commandl(['ip', '-o', 'addr', 'show'])
245
246 def link_show(self, ifacename=None):
247 if ifacename:
248 return self.exec_commandl(['ip', '-o', '-d', 'link',
249 'show', 'dev', '%s' %ifacename])
250 else:
251 return self.exec_commandl(['ip', '-o', '-d', 'link', 'show'])
252
253 def addr_add(self, ifacename, address, broadcast=None,
254 peer=None, scope=None, preferred_lifetime=None):
255 if not address:
256 return
257 cmd = 'addr add %s' %address
258 if broadcast:
259 cmd += ' broadcast %s' %broadcast
260 if peer:
261 cmd += ' peer %s' %peer
262 if scope:
263 cmd += ' scope %s' %scope
264 if preferred_lifetime:
265 cmd += ' preferred_lft %s' %preferred_lifetime
266 cmd += ' dev %s' %ifacename
267 if self.ipbatch and not self.ipbatch_pause:
268 self.add_to_batch(cmd)
269 else:
270 self.exec_command('ip ' + cmd)
271 self._cache_update([ifacename, 'addrs', address], {})
272
273 def addr_del(self, ifacename, address, broadcast=None,
274 peer=None, scope=None):
275 """ Delete ipv4 address """
276 if not address:
277 return
278 if not self._cache_get('addr', [ifacename, 'addrs', address]):
279 return
280 cmd = 'addr del %s' %address
281 if broadcast:
282 cmd += 'broadcast %s' %broadcast
283 if peer:
284 cmd += 'peer %s' %peer
285 if scope:
286 cmd += 'scope %s' %scope
287 cmd += ' dev %s' %ifacename
288 self.exec_command('ip ' + cmd)
289 self._cache_delete([ifacename, 'addrs', address])
290
291 def addr_flush(self, ifacename):
292 cmd = 'addr flush dev %s' %ifacename
293 if self.ipbatch and not self.ipbatch_pause:
294 self.add_to_batch(cmd)
295 else:
296 self.exec_command('ip ' + cmd)
297 self._cache_delete([ifacename, 'addrs'])
298
299 def del_addr_all(self, ifacename, skip_addrs=[]):
300 if not skip_addrs: skip_addrs = []
301 runningaddrsdict = self.addr_get(ifacename)
302 try:
303 # XXX: ignore errors. Fix this to delete secondary addresses
304 # first
305 [self.addr_del(ifacename, a) for a in
306 set(runningaddrsdict.keys()).difference(skip_addrs)]
307 except:
308 # ignore errors
309 pass
310
311 def addr_get(self, ifacename, details=True):
312 addrs = self._cache_get('addr', [ifacename, 'addrs'])
313 if not addrs:
314 return None
315 if details:
316 return addrs
317 return addrs.keys()
318
319 def addr_add_multiple(self, ifacename, addrs, purge_existing=False):
320 # purges address
321 if purge_existing:
322 # if perfmode is not set and also if iface has no sibling
323 # objects, purge addresses that are not present in the new
324 # config
325 runningaddrs = self.addr_get(ifacename, details=False)
326 if addrs == runningaddrs:
327 return
328 try:
329 # if primary address is not same, there is no need to keep any.
330 # reset all addresses
331 if (addrs and runningaddrs and
332 (addrs[0] != runningaddrs[0])):
333 self.del_addr_all(ifacename)
334 else:
335 self.del_addr_all(ifacename, addrs)
336 except Exception, e:
337 self.log_warn(str(e))
338 for a in addrs:
339 try:
340 self.addr_add(ifacename, a)
341 except Exception, e:
342 self.logger.error(str(e))
343
344 def _link_set_ifflag(self, ifacename, value):
345 # Dont look at the cache, the cache may have stale value
346 # because link status can be changed by external
347 # entity (One such entity is ifupdown main program)
348 cmd = 'link set dev %s %s' %(ifacename, value.lower())
349 if self.ipbatch:
350 self.add_to_batch(cmd)
351 else:
352 self.exec_command('ip ' + cmd)
353
354 def link_up(self, ifacename):
355 self._link_set_ifflag(ifacename, 'UP')
356
357 def link_down(self, ifacename):
358 self._link_set_ifflag(ifacename, 'DOWN')
359
360 def link_set(self, ifacename, key, value=None, force=False):
361 if not force:
362 if (key not in ['master', 'nomaster'] and
363 self._cache_check('link', [ifacename, key], value)):
364 return
365 cmd = 'link set dev %s %s' %(ifacename, key)
366 if value:
367 cmd += ' %s' %value
368 if self.ipbatch:
369 self.add_to_batch(cmd)
370 else:
371 self.exec_command('ip ' + cmd)
372 if key not in ['master', 'nomaster']:
373 self._cache_update([ifacename, key], value)
374
375 def link_set_hwaddress(self, ifacename, hwaddress, force=False):
376 if not force:
377 if self._cache_check('link', [ifacename, 'hwaddress'], hwaddress):
61c4d724 378 return
15ef32ea
RP
379 self.link_down(ifacename)
380 cmd = 'link set dev %s address %s' %(ifacename, hwaddress)
381 if self.ipbatch:
382 self.add_to_batch(cmd)
383 else:
384 self.exec_command('ip ' + cmd)
385 self.link_up(ifacename)
386 self._cache_update([ifacename, 'hwaddress'], hwaddress)
387
388 def link_set_alias(self, ifacename, alias):
389 self.exec_commandl(['ip', 'link', 'set', 'dev',
390 ifacename, 'alias', alias])
391
392 def link_get_alias(self, ifacename):
393 return self.read_file_oneline('/sys/class/net/%s/ifalias'
394 %ifacename)
395
396 def link_isloopback(self, ifacename):
397 flags = self._cache_get('link', [ifacename, 'flags'])
398 if not flags:
399 return
400 if 'LOOPBACK' in flags:
401 return True
402 return False
403
404 def link_get_status(self, ifacename):
405 return self._cache_get('link', [ifacename, 'ifflag'], refresh=True)
406
407 def route_add_gateway(self, ifacename, gateway, metric=None):
408 if not gateway:
409 return
410 cmd = 'ip route add default via %s' %gateway
411 # Add metric
412 if metric:
413 cmd += 'metric %s' %metric
414 cmd += ' dev %s' %ifacename
415 self.exec_command(cmd)
416
417 def route_del_gateway(self, ifacename, gateway, metric=None):
418 # delete default gw
419 if not gateway:
420 return
421 cmd = 'ip route del default via %s' %gateway
422 if metric:
423 cmd += ' metric %s' %metric
424 cmd += ' dev %s' %ifacename
425 self.exec_command(cmd)
426
427 def route6_add_gateway(self, ifacename, gateway):
428 if not gateway:
429 return
430 return self.exec_command('ip -6 route add default via %s' %gateway +
431 ' dev %s' %ifacename)
432
433 def route6_del_gateway(self, ifacename, gateway):
434 if not gateway:
435 return
436 return self.exec_command('ip -6 route del default via %s' %gateway +
437 'dev %s' %ifacename)
438
439 def link_create_vlan(self, vlan_device_name, vlan_raw_device, vlanid):
440 if self.link_exists(vlan_device_name):
441 return
442 self.exec_command('ip link add link %s' %vlan_raw_device +
443 ' name %s' %vlan_device_name +
444 ' type vlan id %d' %vlanid)
445 self._cache_update([vlan_device_name], {})
446
447 def link_create_vlan_from_name(self, vlan_device_name):
448 v = vlan_device_name.split('.')
449 if len(v) != 2:
450 self.logger.warn('invalid vlan device name %s' %vlan_device_name)
451 return
452 self.link_create_vlan(vlan_device_name, v[0], v[1])
453
454 def link_create_macvlan(self, name, linkdev, mode='private'):
455 if self.link_exists(name):
456 return
457 cmd = ('link add link %s' %linkdev +
458 ' name %s' %name +
459 ' type macvlan mode %s' %mode)
460 if self.ipbatch and not self.ipbatch_pause:
461 self.add_to_batch(cmd)
462 else:
463 self.exec_command('ip %s' %cmd)
464 self._cache_update([name], {})
465
44533c72
WK
466 def get_vxlan_peers(self, dev):
467 cmd = 'bridge fdb show brport %s' % dev
468 cur_peers = []
469 try:
470 ps = subprocess.Popen((cmd).split(), stdout=subprocess.PIPE, close_fds=True)
471 output = subprocess.check_output(('grep', '00:00:00:00:00:00'), stdin=ps.stdout)
472 ps.wait()
473 try:
474 ppat = re.compile('\s+dst\s+(\d+.\d+.\d+.\d+)\s+')
475 for l in output.split('\n'):
476 m = ppat.search(l)
477 if m:
478 cur_peers.append(m.group(1))
479 except:
480 self.logger.warn('error parsing ip link output')
481 pass
482 except subprocess.CalledProcessError as e:
483 if e.returncode != 1:
484 self.logger.error(str(e))
485
486 return cur_peers
487
15ef32ea
RP
488 def link_create_vxlan(self, name, vxlanid,
489 localtunnelip=None,
490 svcnodeips=None,
44533c72 491 remoteips=None,
88a5c4c8
ST
492 learning='on',
493 ageing=None):
44533c72
WK
494 if svcnodeips and remoteips:
495 raise Exception("svcnodeip and remoteip is mutually exclusive")
15ef32ea
RP
496 args = ''
497 if localtunnelip:
498 args += ' local %s' %localtunnelip
499 if svcnodeips:
500 for s in svcnodeips:
501 args += ' svcnode %s' %s
88a5c4c8
ST
502 if ageing:
503 args += ' ageing %s' %ageing
fce93c54 504 if learning == 'off':
9e012f9e 505 args += ' nolearning'
88a5c4c8 506
15ef32ea 507 if self.link_exists(name):
44533c72 508 cmd = 'link set dev %s type vxlan dstport %d' %(name, VXLAN_UDP_PORT)
15ef32ea 509 else:
44533c72 510 cmd = 'link add dev %s type vxlan id %s dstport %d' %(name, vxlanid, VXLAN_UDP_PORT)
15ef32ea
RP
511 cmd += args
512
513 if self.ipbatch and not self.ipbatch_pause:
514 self.add_to_batch(cmd)
515 else:
516 self.exec_command('ip %s' %cmd)
44533c72
WK
517
518 # figure out the diff for remotes and do the bridge fdb updates
519 cur_peers = set(self.get_vxlan_peers(name))
520 if remoteips:
521 new_peers = set(remoteips)
522 del_list = cur_peers.difference(new_peers)
523 add_list = new_peers.difference(cur_peers)
524 else:
525 del_list = cur_peers
526 add_list = []
527
528 try:
529 for addr in del_list:
530 self.bridge_fdb_del(name, '00:00:00:00:00:00', None, True, addr)
531 except:
532 pass
533
534 try:
535 for addr in add_list:
536 self.bridge_fdb_append(name, '00:00:00:00:00:00', None, True, addr)
537 except:
538 pass
539
15ef32ea
RP
540 # XXX: update linkinfo correctly
541 self._cache_update([name], {})
542
543 def link_exists(self, ifacename):
84ca006f
RP
544 if self.DRYRUN:
545 return True
15ef32ea
RP
546 return os.path.exists('/sys/class/net/%s' %ifacename)
547
548 def is_vlan_device_by_name(self, ifacename):
549 if re.search(r'\.', ifacename):
550 return True
551 return False
552
553 def route_add(self, route):
554 self.exec_command('ip route add ' + route)
555
556 def route6_add(self, route):
557 self.exec_command('ip -6 route add ' + route)
558
559 def get_vlandev_attrs(self, ifacename):
560 return (self._cache_get('link', [ifacename, 'linkinfo', 'link']),
561 self._cache_get('link', [ifacename, 'linkinfo', 'vlanid']))
562
9e012f9e
RP
563 def get_vxlandev_attrs(self, ifacename):
564 return self._cache_get('link', [ifacename, 'linkinfo'])
565
15ef32ea
RP
566 def link_get_mtu(self, ifacename):
567 return self._cache_get('link', [ifacename, 'mtu'])
568
569 def link_get_hwaddress(self, ifacename):
5828d8c5
RP
570 address = self._cache_get('link', [ifacename, 'hwaddress'])
571 # newly created logical interface addresses dont end up in the cache
572 # read hwaddress from sysfs file for these interfaces
573 if not address:
574 address = self.read_file_oneline('/sys/class/net/%s/address'
575 %ifacename)
576 return address
15ef32ea
RP
577
578 def link_create(self, ifacename, type, link=None):
579 if self.link_exists(ifacename):
580 return
581 cmd = 'link add'
582 if link:
583 cmd += ' link %s' %link
584 cmd += ' name %s type %s' %(ifacename, type)
585 if self.ipbatch and not self.ipbatch_pause:
586 self.add_to_batch(cmd)
587 else:
588 self.exec_command('ip %s' %cmd)
589 self._cache_update([ifacename], {})
590
591 def link_delete(self, ifacename):
592 if not self.link_exists(ifacename):
593 return
594 cmd = 'link del %s' %ifacename
595 if self.ipbatch and not self.ipbatch_pause:
596 self.add_to_batch(cmd)
597 else:
598 self.exec_command('ip %s' %cmd)
599 self._cache_invalidate()
600
601 def bridge_port_vids_add(self, bridgeportname, vids):
602 [self.exec_command('bridge vlan add vid %s dev %s'
603 %(v, bridgeportname)) for v in vids]
604
605 def bridge_port_vids_del(self, bridgeportname, vids):
606 if not vids:
607 return
608 [self.exec_command('bridge vlan del vid %s dev %s'
609 %(v, bridgeportname)) for v in vids]
610
611 def bridge_port_vids_flush(self, bridgeportname):
612 self.exec_command('bridge vlan del vid %s dev %s'
613 %(vid, bridgeportname))
614
615 def bridge_port_vids_get(self, bridgeportname):
616 self.exec_command('/bin/bridge vlan show %s' %bridgeportname)
617 bridgeout = self.exec_command('/bin/bridge vlan show dev %s'
618 %bridgeportname)
619 if not bridgeout: return []
620 brvlanlines = bridgeout.readlines()[2:]
621 vids = [l.strip() for l in brvlanlines]
622 return [vid for v in vids if vid]
623
624 def bridge_port_vids_get_all(self):
625 brvlaninfo = {}
626 bridgeout = self.exec_command('/bin/bridge vlan show')
627 if not bridgeout: return brvlaninfo
628 brvlanlines = bridgeout.splitlines()
629 brportname=None
630 for l in brvlanlines[1:]:
631 if l and l[0] not in [' ', '\t']:
632 brportname = None
633 l=l.strip()
634 if not l:
635 brportname=None
636 continue
637 if 'PVID' in l:
638 attrs = l.split()
639 brportname = attrs[0]
640 brvlaninfo[brportname] = {'pvid' : attrs[1],
641 'vlan' : []}
642 elif brportname:
643 if 'Egress Untagged' not in l:
644 brvlaninfo[brportname]['vlan'].append(l)
645 elif not brportname:
646 attrs = l.split()
647 if attrs[1] == 'None' or 'Egress Untagged' in attrs[1]:
648 continue
649 brportname = attrs[0]
650 brvlaninfo[brportname] = {'vlan' : [attrs[1]]}
651 return brvlaninfo
652
653 def bridge_port_pvid_add(self, bridgeportname, pvid):
654 self.exec_command('bridge vlan add vid %s untagged pvid dev %s'
655 %(pvid, bridgeportname))
656
657 def bridge_port_pvid_del(self, bridgeportname, pvid):
658 self.exec_command('bridge vlan del vid %s untagged pvid dev %s'
659 %(pvid, bridgeportname))
660
661 def bridge_port_pvids_get(self, bridgeportname):
662 return self.read_file_oneline('/sys/class/net/%s/brport/pvid'
663 %bridgeportname)
664
665 def bridge_vids_add(self, bridgeportname, vids, bridge=True):
666 target = 'self' if bridge else ''
667 [self.exec_command('bridge vlan add vid %s dev %s %s'
668 %(v, bridgeportname, target)) for v in vids]
669
670 def bridge_vids_del(self, bridgeportname, vids, bridge=True):
671 target = 'self' if bridge else ''
672 [self.exec_command('bridge vlan del vid %s dev %s %s'
673 %(v, bridgeportname, target)) for v in vids]
674
44533c72 675 def bridge_fdb_add(self, dev, address, vlan=None, bridge=True, remote=None):
e1601369 676 target = 'self' if bridge else ''
44533c72 677 vlan_str = ''
8e113d63 678 if vlan:
44533c72
WK
679 vlan_str = 'vlan %s ' % vlan
680
681 dst_str = ''
682 if remote:
683 dst_str = 'dst %s ' % remote
684
685 self.exec_command('bridge fdb replace %s dev %s %s %s %s'
686 %(address, dev, vlan_str, target, dst_str))
e1601369 687
44533c72 688 def bridge_fdb_append(self, dev, address, vlan=None, bridge=True, remote=None):
e1601369 689 target = 'self' if bridge else ''
44533c72 690 vlan_str = ''
8e113d63 691 if vlan:
44533c72
WK
692 vlan_str = 'vlan %s ' % vlan
693
694 dst_str = ''
695 if remote:
696 dst_str = 'dst %s ' % remote
697
698 self.exec_command('bridge fdb append %s dev %s %s %s %s'
699 %(address, dev, vlan_str, target, dst_str))
700
701 def bridge_fdb_del(self, dev, address, vlan=None, bridge=True, remote=None):
702 target = 'self' if bridge else ''
703 vlan_str = ''
704 if vlan:
705 vlan_str = 'vlan %s ' % vlan
706
707 dst_str = ''
708 if remote:
709 dst_str = 'dst %s ' % remote
710 self.exec_command('bridge fdb del %s dev %s %s %s %s'
711 %(address, dev, vlan_str, target, dst_str))
e1601369 712
15ef32ea
RP
713 def bridge_is_vlan_aware(self, bridgename):
714 filename = '/sys/class/net/%s/bridge/vlan_filtering' %bridgename
715 if os.path.exists(filename) and self.read_file_oneline(filename) == '1':
716 return True
717 return False
e1601369
RP
718
719 def bridge_port_get_bridge_name(self, bridgeport):
720 filename = '/sys/class/net/%s/brport/bridge' %bridgeport
721 try:
722 return os.path.basename(os.readlink(filename))
723 except:
724 return None
725
726 def bridge_port_exists(self, bridge, bridgeportname):
727 try:
728 return os.path.exists('/sys/class/net/%s/brif/%s'
729 %(bridge, bridgeportname))
730 except Exception:
731 return False
8e113d63
RP
732
733 def bridge_fdb_show_dev(self, dev):
734 try:
735 fdbs = {}
736 output = self.exec_command('bridge fdb show dev %s' %dev)
737 if output:
738 for fdb_entry in output.splitlines():
739 try:
740 entries = fdb_entry.split()
741 fdbs.setdefault(entries[2], []).append(entries[0])
742 except:
743 self.logger.debug('%s: invalid fdb line \'%s\''
744 %(dev, fdb_entry))
745 pass
746 return fdbs
747 except Exception:
748 return None
749
750 def is_bridge(self, bridge):
751 return os.path.exists('/sys/class/net/%s/bridge' %bridge)
c9bba753
RP
752
753 def is_link_up(self, ifacename):
754 ret = False
755 try:
756 flags = self.read_file_oneline('/sys/class/net/%s/flags' %ifacename)
757 iflags = int(flags, 16)
758 if (iflags & 0x0001):
759 ret = True
760 except:
761 ret = False
762 pass
763 return ret
f8858144
RP
764
765 def ip_route_get_dev(self, prefix):
766 try:
767 output = self.exec_command('ip route get %s' %prefix)
768 if output:
769 rline = output.splitlines()[0]
770 if rline:
771 rattrs = rline.split()
772 return rattrs[rattrs.index('dev') + 1]
773 except Exception, e:
774 self.logger.debug('ip_route_get_dev: failed .. %s' %str(e))
775 pass
776 return None