3 # Copyright 2016-2017 Cumulus Networks, Inc. All rights reserved.
4 # Author: Julien Fortin, julien@cumulusnetworks.com
11 from collections
import OrderedDict
14 import ifupdown2
.nlmanager
.nlpacket
15 import ifupdown2
.ifupdown
.ifupdownflags
as ifupdownflags
17 from ifupdown2
.ifupdownaddons
.cache
import *
18 from ifupdown2
.ifupdownaddons
.utilsbase
import utilsBase
20 from ifupdown2
.nlmanager
.nlmanager
import Link
, Address
, Route
, NetlinkPacket
22 import nlmanager
.nlpacket
23 import ifupdown
.ifupdownflags
as ifupdownflags
25 from ifupdownaddons
.cache
import *
26 from ifupdownaddons
.utilsbase
import utilsBase
28 from nlmanager
.nlmanager
import Link
, Address
, Route
, NetlinkPacket
31 class Netlink(utilsBase
):
34 def __init__(self
, *args
, **kargs
):
35 utilsBase
.__init
__(self
, *args
, **kargs
)
37 sys
.path
.insert(0, '/usr/share/ifupdown2/')
39 from ifupdown2
.nlmanager
.nlmanager
import NetlinkManager
40 # Override the nlmanager's mac_int_to_str function to print the MACs
41 # like xx:xx:xx:xx:xx:xx instead of xxxx.xxxx.xxxx
42 ifupdown2
.nlmanager
.nlpacket
.mac_int_to_str
= self
.mac_int_to_str
44 from nlmanager
.nlmanager
import NetlinkManager
45 # Override the nlmanager's mac_int_to_str function to print the MACs
46 # like xx:xx:xx:xx:xx:xx instead of xxxx.xxxx.xxxx
47 nlmanager
.nlpacket
.mac_int_to_str
= self
.mac_int_to_str
49 # this should force the use of the local nlmanager
50 self
._nlmanager
_api
= NetlinkManager(log_level
=logging
.WARNING
)
52 self
.link_kind_handlers
= {
53 'vlan': self
._link
_dump
_info
_data
_vlan
,
54 'vrf': self
._link
_dump
_info
_data
_vrf
,
55 'vxlan': self
._link
_dump
_info
_data
_vxlan
,
56 'bond': self
._link
_dump
_info
_data
_bond
,
57 'bridge': self
._link
_dump
_info
_data
_bridge
,
58 'gre': self
._link
_dump
_info
_data
_gre
_tunnel
,
59 'gretap': self
._link
_dump
_info
_data
_gre
_tunnel
,
60 "ip6gre": self
._link
_dump
_info
_data
_gre
_tunnel
,
61 "ip6gretap": self
._link
_dump
_info
_data
_gre
_tunnel
,
62 "ip6erspan": self
._link
_dump
_info
_data
_gre
_tunnel
,
63 'ipip': self
._link
_dump
_info
_data
_iptun
_tunnel
,
64 'sit': self
._link
_dump
_info
_data
_iptun
_tunnel
,
65 'ip6tnl': self
._link
_dump
_info
_data
_iptun
_tunnel
,
66 'vti': self
._link
_dump
_info
_data
_vti
_tunnel
,
67 'vti6': self
._link
_dump
_info
_data
_vti
_tunnel
,
68 'xfrm': self
._link
_dump
_info
_data
_xfrm
71 except Exception as e
:
72 self
.logger
.error('cannot initialize ifupdown2\'s '
73 'netlink manager: %s' % str(e
))
79 /include/uapi/linux/in.h
81 #define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
82 #define IN_MULTICAST(a) IN_CLASSD(a)
84 return (int(a
) & 0xf0000000) == 0xe0000000
87 def mac_int_to_str(mac_int
):
89 Return an integer in MAC string format: xx:xx:xx:xx:xx:xx
91 return ':'.join(("%012x" % mac_int
)[i
:i
+ 2] for i
in range(0, 12, 2))
93 def get_iface_index(self
, ifacename
):
94 if ifupdownflags
.flags
.DRYRUN
: return
96 return self
._nlmanager
_api
.get_iface_index(ifacename
)
97 except Exception as e
:
98 raise Exception('%s: netlink: %s: cannot get ifindex: %s'
99 % (ifacename
, ifacename
, str(e
)))
101 def get_iface_name(self
, ifindex
):
102 if ifupdownflags
.flags
.DRYRUN
: return
104 return self
._nlmanager
_api
.get_iface_name(ifindex
)
105 except Exception as e
:
106 raise Exception('netlink: cannot get ifname for index %s: %s' % (ifindex
, str(e
)))
108 def get_bridge_vlan(self
, ifname
):
109 self
.logger
.info('%s: netlink: /sbin/bridge -d -c -json vlan show' % ifname
)
110 if ifupdownflags
.flags
.DRYRUN
: return
112 return self
._nlmanager
_api
.vlan_get()
113 except Exception as e
:
114 raise Exception('netlink: get bridge vlan: %s' % str(e
))
116 def bridge_set_vlan_filtering(self
, ifname
, vlan_filtering
):
117 self
.logger
.info('%s: netlink: ip link set dev %s type bridge vlan_filtering %s'
118 % (ifname
, ifname
, vlan_filtering
))
119 if ifupdownflags
.flags
.DRYRUN
: return
121 ifla_info_data
= {Link
.IFLA_BR_VLAN_FILTERING
: int(vlan_filtering
)}
122 return self
._nlmanager
_api
.link_set_attrs(ifname
, 'bridge', ifla_info_data
=ifla_info_data
)
123 except Exception as e
:
124 raise Exception('%s: cannot set %s vlan_filtering %s' % (ifname
, ifname
, vlan_filtering
))
126 def link_add_set(self
,
127 ifname
=None, ifindex
=0,
128 kind
=None, slave_kind
=None,
131 ifla_info_slave_data
={},
133 action
= 'set' if ifindex
or link_exists
else 'add'
136 self
.logger
.info('%s: netlink: ip link set dev %s: %s slave attributes' % (ifname
, ifname
, slave_kind
))
138 self
.logger
.info('%s: netlink: ip link %s %s type %s with attributes' % (ifname
, action
, ifname
, kind
))
140 self
.logger
.debug('%s: ifla attributes a %s' % (ifname
, ifla
))
142 self
.logger
.debug('%s: ifla_info_data %s' % (ifname
, ifla_info_data
))
143 if ifla_info_slave_data
:
144 self
.logger
.debug('%s: ifla_info_slave_data %s' % (ifname
, ifla_info_slave_data
))
146 if ifupdownflags
.flags
.DRYRUN
: return
148 self
._nlmanager
_api
.link_add_set(ifname
=ifname
,
151 slave_kind
=slave_kind
,
153 ifla_info_data
=ifla_info_data
,
154 ifla_info_slave_data
=ifla_info_slave_data
)
155 except Exception as e
:
156 if kind
and not slave_kind
:
158 elif kind
and slave_kind
:
159 kind_str
= '%s (%s slave)' % (kind
, slave_kind
)
161 kind_str
= '(%s slave)' % slave_kind
163 raise Exception('netlink: cannot %s %s %s with options: %s' % (action
, kind_str
, ifname
, str(e
)))
165 def link_del(self
, ifname
):
166 self
.logger
.info('%s: netlink: ip link del %s' % (ifname
, ifname
))
167 if ifupdownflags
.flags
.DRYRUN
: return
169 self
._nlmanager
_api
.link_del(ifname
=ifname
)
170 except Exception as e
:
171 raise Exception('netlink: cannot delete link %s: %s' % (ifname
, str(e
)))
173 def link_set_master(self
, ifacename
, master_dev
, state
=None):
174 self
.logger
.info('%s: netlink: ip link set dev %s master %s %s'
175 % (ifacename
, ifacename
, master_dev
,
176 state
if state
else ''))
177 if ifupdownflags
.flags
.DRYRUN
: return
179 master
= 0 if not master_dev
else self
.get_iface_index(master_dev
)
180 return self
._nlmanager
_api
.link_set_master(ifacename
,
181 master_ifindex
=master
,
183 except Exception as e
:
184 raise Exception('netlink: %s: cannot set %s master %s: %s'
185 % (ifacename
, ifacename
, master_dev
, str(e
)))
187 def link_set_nomaster(self
, ifacename
, state
=None):
188 self
.logger
.info('%s: netlink: ip link set dev %s nomaster %s'
189 % (ifacename
, ifacename
, state
if state
else ''))
190 if ifupdownflags
.flags
.DRYRUN
: return
192 return self
._nlmanager
_api
.link_set_master(ifacename
,
195 except Exception as e
:
196 raise Exception('netlink: %s: cannot set %s nomaster: %s'
197 % (ifacename
, ifacename
, str(e
)))
199 def link_add_vlan(self
, vlanrawdevice
, ifacename
, vlanid
, vlan_protocol
):
201 self
.logger
.info('%s: netlink: ip link add link %s name %s type vlan id %s protocol %s'
202 % (ifacename
, vlanrawdevice
, ifacename
, vlanid
, vlan_protocol
))
205 self
.logger
.info('%s: netlink: ip link add link %s name %s type vlan id %s'
206 % (ifacename
, vlanrawdevice
, ifacename
, vlanid
))
207 if ifupdownflags
.flags
.DRYRUN
: return
208 ifindex
= self
.get_iface_index(vlanrawdevice
)
210 return self
._nlmanager
_api
.link_add_vlan(ifindex
, ifacename
, vlanid
, vlan_protocol
)
211 except Exception as e
:
212 raise Exception('netlink: %s: cannot create vlan %s: %s'
213 % (vlanrawdevice
, vlanid
, str(e
)))
215 def link_add_macvlan(self
, ifacename
, macvlan_ifacename
):
216 self
.logger
.info('%s: netlink: ip link add link %s name %s type macvlan mode private'
217 % (ifacename
, ifacename
, macvlan_ifacename
))
218 if ifupdownflags
.flags
.DRYRUN
: return
219 ifindex
= self
.get_iface_index(ifacename
)
221 return self
._nlmanager
_api
.link_add_macvlan(ifindex
, macvlan_ifacename
)
222 except Exception as e
:
223 raise Exception('netlink: %s: cannot create macvlan %s: %s'
224 % (ifacename
, macvlan_ifacename
, str(e
)))
226 def link_add_xfrm(self
, ifacename
, xfrm_ifacename
, xfrm_id
):
227 self
.logger
.info('%s: netlink: ip link add %s type xfrm dev %s if_id %s'
228 % (xfrm_ifacename
, xfrm_ifacename
, ifacename
, xfrm_id
))
229 if ifupdownflags
.flags
.DRYRUN
: return
230 ifindex
= self
.get_iface_index(ifacename
)
232 return self
._nlmanager
_api
.link_add_xfrm(ifindex
, xfrm_ifacename
, xfrm_id
)
233 except Exception as e
:
234 raise Exception('netlink: %s: cannot create xfrm %s id %s: %s'
235 % (ifacename
, xfrm_ifacename
, xfrm_id
, str(e
)))
237 def link_set_updown(self
, ifacename
, state
):
238 self
.logger
.info('%s: netlink: ip link set dev %s %s'
239 % (ifacename
, ifacename
, state
))
240 if ifupdownflags
.flags
.DRYRUN
: return
242 return self
._nlmanager
_api
.link_set_updown(ifacename
, state
)
243 except Exception as e
:
244 raise Exception('netlink: cannot set link %s %s: %s'
245 % (ifacename
, state
, str(e
)))
247 def link_set_protodown(self
, ifacename
, state
):
248 self
.logger
.info('%s: netlink: set link %s protodown %s'
249 % (ifacename
, ifacename
, state
))
250 if ifupdownflags
.flags
.DRYRUN
: return
252 return self
._nlmanager
_api
.link_set_protodown(ifacename
, state
)
253 except Exception as e
:
254 raise Exception('netlink: cannot set link %s protodown %s: %s'
255 % (ifacename
, state
, str(e
)))
257 def link_add_bridge(self
, ifname
):
258 self
.logger
.info('%s: netlink: ip link add %s type bridge' % (ifname
, ifname
))
259 if ifupdownflags
.flags
.DRYRUN
: return
261 return self
._nlmanager
_api
.link_add_bridge(ifname
)
262 except Exception as e
:
263 raise Exception('netlink: cannot create bridge %s: %s' % (ifname
, str(e
)))
265 def link_add_bridge_vlan(self
, ifacename
, vlanid
):
266 self
.logger
.info('%s: netlink: bridge vlan add vid %s dev %s'
267 % (ifacename
, vlanid
, ifacename
))
268 if ifupdownflags
.flags
.DRYRUN
: return
269 ifindex
= self
.get_iface_index(ifacename
)
271 return self
._nlmanager
_api
.link_add_bridge_vlan(ifindex
, vlanid
)
272 except Exception as e
:
273 raise Exception('netlink: %s: cannot create bridge vlan %s: %s'
274 % (ifacename
, vlanid
, str(e
)))
276 def link_del_bridge_vlan(self
, ifacename
, vlanid
):
277 self
.logger
.info('%s: netlink: bridge vlan del vid %s dev %s'
278 % (ifacename
, vlanid
, ifacename
))
279 if ifupdownflags
.flags
.DRYRUN
: return
280 ifindex
= self
.get_iface_index(ifacename
)
282 return self
._nlmanager
_api
.link_del_bridge_vlan(ifindex
, vlanid
)
283 except Exception as e
:
284 raise Exception('netlink: %s: cannot remove bridge vlan %s: %s'
285 % (ifacename
, vlanid
, str(e
)))
287 def link_add_vxlan(self
, ifacename
, vxlanid
, local
=None, dstport
=VXLAN_UDP_PORT
,
288 group
=None, learning
=True, ageing
=None, physdev
=None, ttl
=None):
289 cmd
= 'ip link add %s type vxlan id %s dstport %s' % (ifacename
,
292 cmd
+= ' local %s' % local
if local
else ''
293 cmd
+= ' ageing %s' % ageing
if ageing
else ''
294 cmd
+= ' remote %s' % group
if group
else ' noremote'
295 cmd
+= ' nolearning' if not learning
else ''
296 cmd
+= ' dev %s' % physdev
if physdev
else ''
299 cmd
+= ' ttl %s' % ttl
301 self
.logger
.info('%s: netlink: %s' % (ifacename
, cmd
))
302 if ifupdownflags
.flags
.DRYRUN
: return
305 physdev
= self
.get_iface_index(physdev
)
306 return self
._nlmanager
_api
.link_add_vxlan(ifacename
,
315 except Exception as e
:
316 raise Exception('netlink: %s: cannot create vxlan %s: %s'
317 % (ifacename
, vxlanid
, str(e
)))
320 def _link_dump_attr(link
, ifla_attributes
, dump
):
321 for obj
in ifla_attributes
:
322 attr
= link
.attributes
.get(obj
['attr'])
324 dump
[obj
['name']] = attr
.get_pretty_value(obj
=obj
.get('func'))
327 def _link_dump_linkdata_attr(linkdata
, ifla_linkdata_attr
, dump
):
328 for obj
in ifla_linkdata_attr
:
331 func
= obj
.get('func')
332 value
= linkdata
.get(attr
)
337 if value
or obj
['accept_none']:
338 dump
[obj
['name']] = value
342 'attr': Link
.IFLA_LINK
,
344 'func': lambda x
: netlink
.get_iface_name(x
) if x
> 0 else None
347 'attr': Link
.IFLA_MASTER
,
349 'func': lambda x
: netlink
.get_iface_name(x
) if x
> 0 else None
352 'attr': Link
.IFLA_IFNAME
,
357 'attr': Link
.IFLA_MTU
,
362 'attr': Link
.IFLA_OPERSTATE
,
364 'func': lambda x
: '0%x' % int(x
) if x
> len(Link
.oper_to_string
) else Link
.oper_to_string
[x
][8:]
367 'attr': Link
.IFLA_AF_SPEC
,
373 ifla_address
= {'attr': Link
.IFLA_ADDRESS
, 'name': 'hwaddress', 'func': str}
375 ifla_vxlan_attributes
= [
377 'attr': Link
.IFLA_VXLAN_LOCAL
,
383 'attr': Link
.IFLA_VXLAN_LOCAL6
,
389 'attr': Link
.IFLA_VXLAN_GROUP
,
391 'func': lambda x
: str(x
) if not Netlink
.IN_MULTICAST(x
) else None,
395 'attr': Link
.IFLA_VXLAN_GROUP6
,
397 'func': lambda x
: str(x
) if not Netlink
.IN_MULTICAST(x
) else None,
401 'attr': Link
.IFLA_VXLAN_LEARNING
,
403 'func': lambda x
: 'on' if x
else 'off',
408 def _link_dump_info_data_vlan(self
, ifname
, linkdata
):
410 'vlanid': str(linkdata
.get(Link
.IFLA_VLAN_ID
, '')),
411 'vlan_protocol': linkdata
.get(Link
.IFLA_VLAN_PROTOCOL
)
414 def _link_dump_info_data_vrf(self
, ifname
, linkdata
):
415 vrf_info
= {'table': str(linkdata
.get(Link
.IFLA_VRF_TABLE
, ''))}
417 # to remove later when moved to a true netlink cache
418 linkCache
.vrfs
[ifname
] = vrf_info
421 def _link_dump_info_data_vxlan(self
, ifname
, linkdata
):
425 ('vxlanid', str(linkdata
.get(Link
.IFLA_VXLAN_ID
, ''))),
426 ('ageing', str(linkdata
.get(Link
.IFLA_VXLAN_AGEING
, ''))),
427 (Link
.IFLA_VXLAN_PORT
, linkdata
.get(Link
.IFLA_VXLAN_PORT
))
429 linkdata
[attr
] = value
430 self
._link
_dump
_linkdata
_attr
(linkdata
, self
.ifla_vxlan_attributes
, linkdata
)
433 ifla_bond_attributes
= (
435 Link
.IFLA_BOND_MIIMON
,
436 Link
.IFLA_BOND_USE_CARRIER
,
437 Link
.IFLA_BOND_AD_LACP_RATE
,
438 Link
.IFLA_BOND_XMIT_HASH_POLICY
,
439 Link
.IFLA_BOND_MIN_LINKS
,
440 Link
.IFLA_BOND_NUM_PEER_NOTIF
,
441 Link
.IFLA_BOND_AD_ACTOR_SYSTEM
,
442 Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
,
443 Link
.IFLA_BOND_AD_LACP_BYPASS
,
444 Link
.IFLA_BOND_UPDELAY
,
445 Link
.IFLA_BOND_DOWNDELAY
,
448 def _link_dump_info_data_bond(self
, ifname
, linkdata
):
450 for nl_attr
in self
.ifla_bond_attributes
:
452 linkinfo
[nl_attr
] = linkdata
.get(nl_attr
)
453 except Exception as e
:
454 self
.logger
.debug('%s: parsing bond IFLA_INFO_DATA (%s): %s'
455 % (ifname
, nl_attr
, str(e
)))
458 # this dict contains the netlink attribute, cache key,
459 # and a callable to translate the netlink value into
460 # whatever value we need to store in the old cache to
461 # make sure we don't break anything
462 ifla_bridge_attributes
= (
463 (Link
.IFLA_BR_UNSPEC
, Link
.IFLA_BR_UNSPEC
, None),
464 (Link
.IFLA_BR_FORWARD_DELAY
, "fd", lambda x
: str(x
/ 100)),
465 (Link
.IFLA_BR_HELLO_TIME
, "hello", lambda x
: str(x
/ 100)),
466 (Link
.IFLA_BR_MAX_AGE
, "maxage", lambda x
: str(x
/ 100)),
467 (Link
.IFLA_BR_AGEING_TIME
, "ageing", lambda x
: str(x
/ 100)),
468 (Link
.IFLA_BR_STP_STATE
, "stp", lambda x
: 'yes' if x
else 'no'),
469 (Link
.IFLA_BR_PRIORITY
, "bridgeprio", str),
470 (Link
.IFLA_BR_VLAN_FILTERING
, 'vlan_filtering', str),
471 (Link
.IFLA_BR_VLAN_PROTOCOL
, "vlan-protocol", str),
472 (Link
.IFLA_BR_GROUP_FWD_MASK
, Link
.IFLA_BR_GROUP_FWD_MASK
, None),
473 (Link
.IFLA_BR_ROOT_ID
, Link
.IFLA_BR_ROOT_ID
, None),
474 (Link
.IFLA_BR_BRIDGE_ID
, Link
.IFLA_BR_BRIDGE_ID
, None),
475 (Link
.IFLA_BR_ROOT_PORT
, Link
.IFLA_BR_ROOT_PORT
, None),
476 (Link
.IFLA_BR_ROOT_PATH_COST
, Link
.IFLA_BR_ROOT_PATH_COST
, None),
477 (Link
.IFLA_BR_TOPOLOGY_CHANGE
, Link
.IFLA_BR_TOPOLOGY_CHANGE
, None),
478 (Link
.IFLA_BR_TOPOLOGY_CHANGE_DETECTED
, Link
.IFLA_BR_TOPOLOGY_CHANGE_DETECTED
, None),
479 (Link
.IFLA_BR_HELLO_TIMER
, Link
.IFLA_BR_HELLO_TIMER
, None),
480 (Link
.IFLA_BR_TCN_TIMER
, Link
.IFLA_BR_TCN_TIMER
, None),
481 (Link
.IFLA_BR_TOPOLOGY_CHANGE_TIMER
, Link
.IFLA_BR_TOPOLOGY_CHANGE_TIMER
, None),
482 (Link
.IFLA_BR_GC_TIMER
, Link
.IFLA_BR_GC_TIMER
, None),
483 (Link
.IFLA_BR_GROUP_ADDR
, Link
.IFLA_BR_GROUP_ADDR
, None),
484 (Link
.IFLA_BR_FDB_FLUSH
, Link
.IFLA_BR_FDB_FLUSH
, None),
485 (Link
.IFLA_BR_MCAST_ROUTER
, "mcrouter", str),
486 (Link
.IFLA_BR_MCAST_SNOOPING
, "mcsnoop", str),
487 (Link
.IFLA_BR_MCAST_QUERY_USE_IFADDR
, "mcqifaddr", str),
488 (Link
.IFLA_BR_MCAST_QUERIER
, "mcquerier", str),
489 (Link
.IFLA_BR_MCAST_HASH_ELASTICITY
, "hashel", str),
490 (Link
.IFLA_BR_MCAST_HASH_MAX
, "hashmax", str),
491 (Link
.IFLA_BR_MCAST_LAST_MEMBER_CNT
, "mclmc", str),
492 (Link
.IFLA_BR_MCAST_STARTUP_QUERY_CNT
, "mcsqc", str),
493 (Link
.IFLA_BR_MCAST_LAST_MEMBER_INTVL
, "mclmi", lambda x
: str(x
/ 100)),
494 (Link
.IFLA_BR_MCAST_MEMBERSHIP_INTVL
, "mcmi", lambda x
: str(x
/ 100)),
495 (Link
.IFLA_BR_MCAST_QUERIER_INTVL
, "mcqpi", lambda x
: str(x
/ 100)),
496 (Link
.IFLA_BR_MCAST_QUERY_INTVL
, "mcqi", lambda x
: str(x
/ 100)),
497 (Link
.IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
, "mcqri", lambda x
: str(x
/ 100)),
498 (Link
.IFLA_BR_MCAST_STARTUP_QUERY_INTVL
, "mcsqi", lambda x
: str(x
/ 100)),
499 (Link
.IFLA_BR_NF_CALL_IPTABLES
, Link
.IFLA_BR_NF_CALL_IPTABLES
, None),
500 (Link
.IFLA_BR_NF_CALL_IP6TABLES
, Link
.IFLA_BR_NF_CALL_IP6TABLES
, None),
501 (Link
.IFLA_BR_NF_CALL_ARPTABLES
, Link
.IFLA_BR_NF_CALL_ARPTABLES
, None),
502 (Link
.IFLA_BR_VLAN_DEFAULT_PVID
, Link
.IFLA_BR_VLAN_DEFAULT_PVID
, None),
503 (Link
.IFLA_BR_PAD
, Link
.IFLA_BR_PAD
, None),
504 (Link
.IFLA_BR_VLAN_STATS_ENABLED
, "vlan-stats", str),
505 (Link
.IFLA_BR_MCAST_STATS_ENABLED
, "mcstats", str),
506 (Link
.IFLA_BR_MCAST_IGMP_VERSION
, "igmp-version", str),
507 (Link
.IFLA_BR_MCAST_MLD_VERSION
, "mld-version", str)
510 def _link_dump_info_data_bridge(self
, ifname
, linkdata
):
512 for nl_attr
, cache_key
, func
in self
.ifla_bridge_attributes
:
515 linkinfo
[cache_key
] = func(linkdata
.get(nl_attr
))
517 linkinfo
[cache_key
] = linkdata
.get(nl_attr
)
519 # we also store the value in pure netlink,
520 # to make the transition easier in the future
521 linkinfo
[nl_attr
] = linkdata
.get(nl_attr
)
522 except Exception as e
:
523 self
.logger
.error('%s: parsing birdge IFLA_INFO_DATA %s: %s'
524 % (ifname
, nl_attr
, str(e
)))
527 def _link_dump_info_slave_data_bridge(self
, ifname
, info_slave_data
):
528 return info_slave_data
530 def _link_dump_info_data_gre_tunnel(self
, ifname
, info_slave_data
):
531 tunnel_link_ifindex
= info_slave_data
.get(Link
.IFLA_GRE_LINK
)
534 "endpoint": str(info_slave_data
.get(Link
.IFLA_GRE_REMOTE
)),
535 "local": str(info_slave_data
.get(Link
.IFLA_GRE_LOCAL
)),
536 "ttl": str(info_slave_data
.get(Link
.IFLA_GRE_TTL
)),
537 "tunnel-physdev": self
.get_iface_name(tunnel_link_ifindex
) if tunnel_link_ifindex
else ""
540 def _link_dump_info_data_iptun_tunnel(self
, ifname
, info_slave_data
):
541 tunnel_link_ifindex
= info_slave_data
.get(Link
.IFLA_IPTUN_LINK
)
544 "endpoint": str(info_slave_data
.get(Link
.IFLA_IPTUN_REMOTE
)),
545 "local": str(info_slave_data
.get(Link
.IFLA_IPTUN_LOCAL
)),
546 "ttl": str(info_slave_data
.get(Link
.IFLA_IPTUN_TTL
)),
547 "tunnel-physdev": self
.get_iface_name(tunnel_link_ifindex
) if tunnel_link_ifindex
else ""
550 def _link_dump_info_data_vti_tunnel(self
, ifname
, info_slave_data
):
551 tunnel_link_ifindex
= info_slave_data
.get(Link
.IFLA_VTI_LINK
)
554 "endpoint": str(info_slave_data
.get(Link
.IFLA_VTI_REMOTE
)),
555 "local": str(info_slave_data
.get(Link
.IFLA_VTI_LOCAL
)),
556 "tunnel-physdev": self
.get_iface_name(tunnel_link_ifindex
) if tunnel_link_ifindex
else ""
559 def _link_dump_info_data_xfrm(self
, ifname
, linkdata
):
560 xfrm_physdev_link_ifindex
= linkdata
.get(Link
.IFLA_XFRM_LINK
)
563 'xfrmid': str(linkdata
.get(Link
.IFLA_XFRM_IF_ID
, '')),
564 'xfrm-physdev': self
.get_iface_name(xfrm_physdev_link_ifindex
) if xfrm_physdev_link_ifindex
else ""
567 def _link_dump_linkinfo(self
, link
, dump
):
568 linkinfo
= link
.attributes
[Link
.IFLA_LINKINFO
].get_pretty_value(dict)
571 info_kind
= linkinfo
.get(Link
.IFLA_INFO_KIND
)
572 info_data
= linkinfo
.get(Link
.IFLA_INFO_DATA
)
574 info_slave_kind
= linkinfo
.get(Link
.IFLA_INFO_SLAVE_KIND
)
575 info_slave_data
= linkinfo
.get(Link
.IFLA_INFO_SLAVE_DATA
)
577 dump
['kind'] = info_kind
578 dump
['slave_kind'] = info_slave_kind
581 link_kind_handler
= self
.link_kind_handlers
.get(info_kind
)
582 if callable(link_kind_handler
):
583 dump
['linkinfo'] = link_kind_handler(dump
['ifname'], info_data
)
586 dump
['info_slave_data'] = info_slave_data
588 def link_dump(self
, ifname
=None):
590 self
.logger
.info('netlink: ip link show dev %s' % ifname
)
592 self
.logger
.info('netlink: ip link show')
594 if ifupdownflags
.flags
.DRYRUN
: return {}
599 links_dump
= self
._nlmanager
_api
.link_dump(ifname
)
600 except Exception as e
:
601 raise Exception('netlink: link dump failed: %s' % str(e
))
603 for link
in links_dump
:
608 for flag
, string
in Link
.flag_to_string
.items():
609 if link
.flags
& flag
:
610 flags
.append(string
[4:])
612 dump
['flags'] = flags
613 dump
['ifflag'] = 'UP' if 'UP' in flags
else 'DOWN'
614 dump
['ifindex'] = str(link
.ifindex
)
616 if link
.device_type
== Link
.ARPHRD_ETHER
:
617 self
._link
_dump
_attr
(link
, [self
.ifla_address
], dump
)
619 self
._link
_dump
_attr
(link
, self
.ifla_attributes
, dump
)
621 if Link
.IFLA_LINKINFO
in link
.attributes
:
622 self
._link
_dump
_linkinfo
(link
, dump
)
624 links
[dump
['ifname']] = dump
625 except Exception as e
:
626 self
.logger
.warning('netlink: ip link show: %s' % str(e
))
629 def _addr_dump_extract_ifname(self
, addr_packet
):
630 addr_ifname_attr
= addr_packet
.attributes
.get(Address
.IFA_LABEL
)
633 return addr_ifname_attr
.get_pretty_value(str)
635 return self
.get_iface_name(addr_packet
.ifindex
)
638 def _addr_filter(addr_ifname
, addr
):
639 return addr_ifname
== 'lo' and addr
in ['127.0.0.1/8', '::1/128', '0.0.0.0']
641 def _addr_dump_entry(self
, ifaces
, addr_packet
, addr_ifname
, ifa_attr
):
642 attribute
= addr_packet
.attributes
.get(ifa_attr
)
645 address
= attribute
.get_pretty_value(str)
647 if hasattr(addr_packet
, 'prefixlen'):
648 address
= '%s/%d' % (address
, addr_packet
.prefixlen
)
650 if self
._addr
_filter
(addr_ifname
, address
):
653 addr_family
= NetlinkPacket
.af_family_to_string
.get(addr_packet
.family
)
657 ifaces
[addr_ifname
]['addrs'][address
] = {
659 'scope': addr_packet
.scope
662 ifa_address_attributes
= [
665 Address
.IFA_BROADCAST
,
667 Address
.IFA_MULTICAST
670 def addr_dump(self
, ifname
=None):
672 self
.logger
.info('netlink: ip addr show dev %s' % ifname
)
674 self
.logger
.info('netlink: ip addr show')
677 addr_dump
= self
._nlmanager
_api
.addr_dump()
679 for addr_packet
in addr_dump
:
680 addr_ifname
= self
._addr
_dump
_extract
_ifname
(addr_packet
)
682 if addr_packet
.family
not in [socket
.AF_INET
, socket
.AF_INET6
]:
685 if ifname
and ifname
!= addr_ifname
:
688 if addr_ifname
not in ifaces
:
689 ifaces
[addr_ifname
] = {'addrs': OrderedDict({})}
691 for ifa_attr
in self
.ifa_address_attributes
:
692 self
._addr
_dump
_entry
(ifaces
, addr_packet
, addr_ifname
, ifa_attr
)
695 return {ifname
: ifaces
.get(ifname
, {})}