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
70 except Exception as e
:
71 self
.logger
.error('cannot initialize ifupdown2\'s '
72 'netlink manager: %s' % str(e
))
78 /include/uapi/linux/in.h
80 #define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
81 #define IN_MULTICAST(a) IN_CLASSD(a)
83 return (int(a
) & 0xf0000000) == 0xe0000000
86 def mac_int_to_str(mac_int
):
88 Return an integer in MAC string format: xx:xx:xx:xx:xx:xx
90 return ':'.join(("%012x" % mac_int
)[i
:i
+ 2] for i
in range(0, 12, 2))
92 def get_iface_index(self
, ifacename
):
93 if ifupdownflags
.flags
.DRYRUN
: return
95 return self
._nlmanager
_api
.get_iface_index(ifacename
)
96 except Exception as e
:
97 raise Exception('%s: netlink: %s: cannot get ifindex: %s'
98 % (ifacename
, ifacename
, str(e
)))
100 def get_iface_name(self
, ifindex
):
101 if ifupdownflags
.flags
.DRYRUN
: return
103 return self
._nlmanager
_api
.get_iface_name(ifindex
)
104 except Exception as e
:
105 raise Exception('netlink: cannot get ifname for index %s: %s' % (ifindex
, str(e
)))
107 def get_bridge_vlan(self
, ifname
):
108 self
.logger
.info('%s: netlink: /sbin/bridge -d -c -json vlan show' % ifname
)
109 if ifupdownflags
.flags
.DRYRUN
: return
111 return self
._nlmanager
_api
.vlan_get()
112 except Exception as e
:
113 raise Exception('netlink: get bridge vlan: %s' % str(e
))
115 def bridge_set_vlan_filtering(self
, ifname
, vlan_filtering
):
116 self
.logger
.info('%s: netlink: ip link set dev %s type bridge vlan_filtering %s'
117 % (ifname
, ifname
, vlan_filtering
))
118 if ifupdownflags
.flags
.DRYRUN
: return
120 ifla_info_data
= {Link
.IFLA_BR_VLAN_FILTERING
: int(vlan_filtering
)}
121 return self
._nlmanager
_api
.link_set_attrs(ifname
, 'bridge', ifla_info_data
=ifla_info_data
)
122 except Exception as e
:
123 raise Exception('%s: cannot set %s vlan_filtering %s' % (ifname
, ifname
, vlan_filtering
))
125 def link_add_set(self
,
126 ifname
=None, ifindex
=0,
127 kind
=None, slave_kind
=None,
130 ifla_info_slave_data
={},
132 action
= 'set' if ifindex
or link_exists
else 'add'
135 self
.logger
.info('%s: netlink: ip link set dev %s: %s slave attributes' % (ifname
, ifname
, slave_kind
))
137 self
.logger
.info('%s: netlink: ip link %s %s type %s with attributes' % (ifname
, action
, ifname
, kind
))
139 self
.logger
.debug('%s: ifla attributes a %s' % (ifname
, ifla
))
141 self
.logger
.debug('%s: ifla_info_data %s' % (ifname
, ifla_info_data
))
142 if ifla_info_slave_data
:
143 self
.logger
.debug('%s: ifla_info_slave_data %s' % (ifname
, ifla_info_slave_data
))
145 if ifupdownflags
.flags
.DRYRUN
: return
147 self
._nlmanager
_api
.link_add_set(ifname
=ifname
,
150 slave_kind
=slave_kind
,
152 ifla_info_data
=ifla_info_data
,
153 ifla_info_slave_data
=ifla_info_slave_data
)
154 except Exception as e
:
155 if kind
and not slave_kind
:
157 elif kind
and slave_kind
:
158 kind_str
= '%s (%s slave)' % (kind
, slave_kind
)
160 kind_str
= '(%s slave)' % slave_kind
162 raise Exception('netlink: cannot %s %s %s with options: %s' % (action
, kind_str
, ifname
, str(e
)))
164 def link_del(self
, ifname
):
165 self
.logger
.info('%s: netlink: ip link del %s' % (ifname
, ifname
))
166 if ifupdownflags
.flags
.DRYRUN
: return
168 self
._nlmanager
_api
.link_del(ifname
=ifname
)
169 except Exception as e
:
170 raise Exception('netlink: cannot delete link %s: %s' % (ifname
, str(e
)))
172 def link_set_master(self
, ifacename
, master_dev
, state
=None):
173 self
.logger
.info('%s: netlink: ip link set dev %s master %s %s'
174 % (ifacename
, ifacename
, master_dev
,
175 state
if state
else ''))
176 if ifupdownflags
.flags
.DRYRUN
: return
178 master
= 0 if not master_dev
else self
.get_iface_index(master_dev
)
179 return self
._nlmanager
_api
.link_set_master(ifacename
,
180 master_ifindex
=master
,
182 except Exception as e
:
183 raise Exception('netlink: %s: cannot set %s master %s: %s'
184 % (ifacename
, ifacename
, master_dev
, str(e
)))
186 def link_set_nomaster(self
, ifacename
, state
=None):
187 self
.logger
.info('%s: netlink: ip link set dev %s nomaster %s'
188 % (ifacename
, ifacename
, state
if state
else ''))
189 if ifupdownflags
.flags
.DRYRUN
: return
191 return self
._nlmanager
_api
.link_set_master(ifacename
,
194 except Exception as e
:
195 raise Exception('netlink: %s: cannot set %s nomaster: %s'
196 % (ifacename
, ifacename
, str(e
)))
198 def link_add_vlan(self
, vlanrawdevice
, ifacename
, vlanid
, vlan_protocol
):
200 self
.logger
.info('%s: netlink: ip link add link %s name %s type vlan id %s protocol %s'
201 % (ifacename
, vlanrawdevice
, ifacename
, vlanid
, vlan_protocol
))
204 self
.logger
.info('%s: netlink: ip link add link %s name %s type vlan id %s'
205 % (ifacename
, vlanrawdevice
, ifacename
, vlanid
))
206 if ifupdownflags
.flags
.DRYRUN
: return
207 ifindex
= self
.get_iface_index(vlanrawdevice
)
209 return self
._nlmanager
_api
.link_add_vlan(ifindex
, ifacename
, vlanid
, vlan_protocol
)
210 except Exception as e
:
211 raise Exception('netlink: %s: cannot create vlan %s: %s'
212 % (vlanrawdevice
, vlanid
, str(e
)))
214 def link_add_macvlan(self
, ifacename
, macvlan_ifacename
):
215 self
.logger
.info('%s: netlink: ip link add link %s name %s type macvlan mode private'
216 % (ifacename
, ifacename
, macvlan_ifacename
))
217 if ifupdownflags
.flags
.DRYRUN
: return
218 ifindex
= self
.get_iface_index(ifacename
)
220 return self
._nlmanager
_api
.link_add_macvlan(ifindex
, macvlan_ifacename
)
221 except Exception as e
:
222 raise Exception('netlink: %s: cannot create macvlan %s: %s'
223 % (ifacename
, macvlan_ifacename
, str(e
)))
225 def link_set_updown(self
, ifacename
, state
):
226 self
.logger
.info('%s: netlink: ip link set dev %s %s'
227 % (ifacename
, ifacename
, state
))
228 if ifupdownflags
.flags
.DRYRUN
: return
230 return self
._nlmanager
_api
.link_set_updown(ifacename
, state
)
231 except Exception as e
:
232 raise Exception('netlink: cannot set link %s %s: %s'
233 % (ifacename
, state
, str(e
)))
235 def link_set_protodown(self
, ifacename
, state
):
236 self
.logger
.info('%s: netlink: set link %s protodown %s'
237 % (ifacename
, ifacename
, state
))
238 if ifupdownflags
.flags
.DRYRUN
: return
240 return self
._nlmanager
_api
.link_set_protodown(ifacename
, state
)
241 except Exception as e
:
242 raise Exception('netlink: cannot set link %s protodown %s: %s'
243 % (ifacename
, state
, str(e
)))
245 def link_add_bridge(self
, ifname
):
246 self
.logger
.info('%s: netlink: ip link add %s type bridge' % (ifname
, ifname
))
247 if ifupdownflags
.flags
.DRYRUN
: return
249 return self
._nlmanager
_api
.link_add_bridge(ifname
)
250 except Exception as e
:
251 raise Exception('netlink: cannot create bridge %s: %s' % (ifname
, str(e
)))
253 def link_add_bridge_vlan(self
, ifacename
, vlanid
):
254 self
.logger
.info('%s: netlink: bridge vlan add vid %s dev %s'
255 % (ifacename
, vlanid
, ifacename
))
256 if ifupdownflags
.flags
.DRYRUN
: return
257 ifindex
= self
.get_iface_index(ifacename
)
259 return self
._nlmanager
_api
.link_add_bridge_vlan(ifindex
, vlanid
)
260 except Exception as e
:
261 raise Exception('netlink: %s: cannot create bridge vlan %s: %s'
262 % (ifacename
, vlanid
, str(e
)))
264 def link_del_bridge_vlan(self
, ifacename
, vlanid
):
265 self
.logger
.info('%s: netlink: bridge vlan del vid %s dev %s'
266 % (ifacename
, vlanid
, ifacename
))
267 if ifupdownflags
.flags
.DRYRUN
: return
268 ifindex
= self
.get_iface_index(ifacename
)
270 return self
._nlmanager
_api
.link_del_bridge_vlan(ifindex
, vlanid
)
271 except Exception as e
:
272 raise Exception('netlink: %s: cannot remove bridge vlan %s: %s'
273 % (ifacename
, vlanid
, str(e
)))
275 def link_add_vxlan(self
, ifacename
, vxlanid
, local
=None, dstport
=VXLAN_UDP_PORT
,
276 group
=None, learning
=True, ageing
=None, physdev
=None):
277 cmd
= 'ip link add %s type vxlan id %s dstport %s' % (ifacename
,
280 cmd
+= ' local %s' % local
if local
else ''
281 cmd
+= ' ageing %s' % ageing
if ageing
else ''
282 cmd
+= ' remote %s' % group
if group
else ' noremote'
283 cmd
+= ' nolearning' if not learning
else ''
284 cmd
+= ' dev %s' % physdev
if physdev
else ''
285 self
.logger
.info('%s: netlink: %s' % (ifacename
, cmd
))
286 if ifupdownflags
.flags
.DRYRUN
: return
289 physdev
= self
.get_iface_index(physdev
)
290 return self
._nlmanager
_api
.link_add_vxlan(ifacename
,
298 except Exception as e
:
299 raise Exception('netlink: %s: cannot create vxlan %s: %s'
300 % (ifacename
, vxlanid
, str(e
)))
303 def _link_dump_attr(link
, ifla_attributes
, dump
):
304 for obj
in ifla_attributes
:
305 attr
= link
.attributes
.get(obj
['attr'])
307 dump
[obj
['name']] = attr
.get_pretty_value(obj
=obj
.get('func'))
310 def _link_dump_linkdata_attr(linkdata
, ifla_linkdata_attr
, dump
):
311 for obj
in ifla_linkdata_attr
:
314 func
= obj
.get('func')
315 value
= linkdata
.get(attr
)
320 if value
or obj
['accept_none']:
321 dump
[obj
['name']] = value
325 'attr': Link
.IFLA_LINK
,
327 'func': lambda x
: netlink
.get_iface_name(x
) if x
> 0 else None
330 'attr': Link
.IFLA_MASTER
,
332 'func': lambda x
: netlink
.get_iface_name(x
) if x
> 0 else None
335 'attr': Link
.IFLA_IFNAME
,
340 'attr': Link
.IFLA_MTU
,
345 'attr': Link
.IFLA_OPERSTATE
,
347 'func': lambda x
: '0%x' % int(x
) if x
> len(Link
.oper_to_string
) else Link
.oper_to_string
[x
][8:]
350 'attr': Link
.IFLA_AF_SPEC
,
356 ifla_address
= {'attr': Link
.IFLA_ADDRESS
, 'name': 'hwaddress', 'func': str}
358 ifla_vxlan_attributes
= [
360 'attr': Link
.IFLA_VXLAN_LOCAL
,
366 'attr': Link
.IFLA_VXLAN_LOCAL6
,
372 'attr': Link
.IFLA_VXLAN_GROUP
,
374 'func': lambda x
: str(x
) if not Netlink
.IN_MULTICAST(x
) else None,
378 'attr': Link
.IFLA_VXLAN_GROUP6
,
380 'func': lambda x
: str(x
) if not Netlink
.IN_MULTICAST(x
) else None,
384 'attr': Link
.IFLA_VXLAN_LEARNING
,
386 'func': lambda x
: 'on' if x
else 'off',
391 def _link_dump_info_data_vlan(self
, ifname
, linkdata
):
393 'vlanid': str(linkdata
.get(Link
.IFLA_VLAN_ID
, '')),
394 'vlan_protocol': linkdata
.get(Link
.IFLA_VLAN_PROTOCOL
)
397 def _link_dump_info_data_vrf(self
, ifname
, linkdata
):
398 vrf_info
= {'table': str(linkdata
.get(Link
.IFLA_VRF_TABLE
, ''))}
400 # to remove later when moved to a true netlink cache
401 linkCache
.vrfs
[ifname
] = vrf_info
404 def _link_dump_info_data_vxlan(self
, ifname
, linkdata
):
408 ('vxlanid', str(linkdata
.get(Link
.IFLA_VXLAN_ID
, ''))),
409 ('ageing', str(linkdata
.get(Link
.IFLA_VXLAN_AGEING
, ''))),
410 (Link
.IFLA_VXLAN_PORT
, linkdata
.get(Link
.IFLA_VXLAN_PORT
))
412 linkdata
[attr
] = value
413 self
._link
_dump
_linkdata
_attr
(linkdata
, self
.ifla_vxlan_attributes
, linkdata
)
416 ifla_bond_attributes
= (
418 Link
.IFLA_BOND_MIIMON
,
419 Link
.IFLA_BOND_USE_CARRIER
,
420 Link
.IFLA_BOND_AD_LACP_RATE
,
421 Link
.IFLA_BOND_XMIT_HASH_POLICY
,
422 Link
.IFLA_BOND_MIN_LINKS
,
423 Link
.IFLA_BOND_NUM_PEER_NOTIF
,
424 Link
.IFLA_BOND_AD_ACTOR_SYSTEM
,
425 Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
,
426 Link
.IFLA_BOND_AD_LACP_BYPASS
,
427 Link
.IFLA_BOND_UPDELAY
,
428 Link
.IFLA_BOND_DOWNDELAY
,
431 def _link_dump_info_data_bond(self
, ifname
, linkdata
):
433 for nl_attr
in self
.ifla_bond_attributes
:
435 linkinfo
[nl_attr
] = linkdata
.get(nl_attr
)
436 except Exception as e
:
437 self
.logger
.debug('%s: parsing bond IFLA_INFO_DATA (%s): %s'
438 % (ifname
, nl_attr
, str(e
)))
441 # this dict contains the netlink attribute, cache key,
442 # and a callable to translate the netlink value into
443 # whatever value we need to store in the old cache to
444 # make sure we don't break anything
445 ifla_bridge_attributes
= (
446 (Link
.IFLA_BR_UNSPEC
, Link
.IFLA_BR_UNSPEC
, None),
447 (Link
.IFLA_BR_FORWARD_DELAY
, "fd", lambda x
: str(x
/ 100)),
448 (Link
.IFLA_BR_HELLO_TIME
, "hello", lambda x
: str(x
/ 100)),
449 (Link
.IFLA_BR_MAX_AGE
, "maxage", lambda x
: str(x
/ 100)),
450 (Link
.IFLA_BR_AGEING_TIME
, "ageing", lambda x
: str(x
/ 100)),
451 (Link
.IFLA_BR_STP_STATE
, "stp", lambda x
: 'yes' if x
else 'no'),
452 (Link
.IFLA_BR_PRIORITY
, "bridgeprio", str),
453 (Link
.IFLA_BR_VLAN_FILTERING
, 'vlan_filtering', str),
454 (Link
.IFLA_BR_VLAN_PROTOCOL
, "vlan-protocol", str),
455 (Link
.IFLA_BR_GROUP_FWD_MASK
, Link
.IFLA_BR_GROUP_FWD_MASK
, None),
456 (Link
.IFLA_BR_ROOT_ID
, Link
.IFLA_BR_ROOT_ID
, None),
457 (Link
.IFLA_BR_BRIDGE_ID
, Link
.IFLA_BR_BRIDGE_ID
, None),
458 (Link
.IFLA_BR_ROOT_PORT
, Link
.IFLA_BR_ROOT_PORT
, None),
459 (Link
.IFLA_BR_ROOT_PATH_COST
, Link
.IFLA_BR_ROOT_PATH_COST
, None),
460 (Link
.IFLA_BR_TOPOLOGY_CHANGE
, Link
.IFLA_BR_TOPOLOGY_CHANGE
, None),
461 (Link
.IFLA_BR_TOPOLOGY_CHANGE_DETECTED
, Link
.IFLA_BR_TOPOLOGY_CHANGE_DETECTED
, None),
462 (Link
.IFLA_BR_HELLO_TIMER
, Link
.IFLA_BR_HELLO_TIMER
, None),
463 (Link
.IFLA_BR_TCN_TIMER
, Link
.IFLA_BR_TCN_TIMER
, None),
464 (Link
.IFLA_BR_TOPOLOGY_CHANGE_TIMER
, Link
.IFLA_BR_TOPOLOGY_CHANGE_TIMER
, None),
465 (Link
.IFLA_BR_GC_TIMER
, Link
.IFLA_BR_GC_TIMER
, None),
466 (Link
.IFLA_BR_GROUP_ADDR
, Link
.IFLA_BR_GROUP_ADDR
, None),
467 (Link
.IFLA_BR_FDB_FLUSH
, Link
.IFLA_BR_FDB_FLUSH
, None),
468 (Link
.IFLA_BR_MCAST_ROUTER
, "mcrouter", str),
469 (Link
.IFLA_BR_MCAST_SNOOPING
, "mcsnoop", str),
470 (Link
.IFLA_BR_MCAST_QUERY_USE_IFADDR
, "mcqifaddr", str),
471 (Link
.IFLA_BR_MCAST_QUERIER
, "mcquerier", str),
472 (Link
.IFLA_BR_MCAST_HASH_ELASTICITY
, "hashel", str),
473 (Link
.IFLA_BR_MCAST_HASH_MAX
, "hashmax", str),
474 (Link
.IFLA_BR_MCAST_LAST_MEMBER_CNT
, "mclmc", str),
475 (Link
.IFLA_BR_MCAST_STARTUP_QUERY_CNT
, "mcsqc", str),
476 (Link
.IFLA_BR_MCAST_LAST_MEMBER_INTVL
, "mclmi", lambda x
: str(x
/ 100)),
477 (Link
.IFLA_BR_MCAST_MEMBERSHIP_INTVL
, "mcmi", lambda x
: str(x
/ 100)),
478 (Link
.IFLA_BR_MCAST_QUERIER_INTVL
, "mcqpi", lambda x
: str(x
/ 100)),
479 (Link
.IFLA_BR_MCAST_QUERY_INTVL
, "mcqi", lambda x
: str(x
/ 100)),
480 (Link
.IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
, "mcqri", lambda x
: str(x
/ 100)),
481 (Link
.IFLA_BR_MCAST_STARTUP_QUERY_INTVL
, "mcsqi", lambda x
: str(x
/ 100)),
482 (Link
.IFLA_BR_NF_CALL_IPTABLES
, Link
.IFLA_BR_NF_CALL_IPTABLES
, None),
483 (Link
.IFLA_BR_NF_CALL_IP6TABLES
, Link
.IFLA_BR_NF_CALL_IP6TABLES
, None),
484 (Link
.IFLA_BR_NF_CALL_ARPTABLES
, Link
.IFLA_BR_NF_CALL_ARPTABLES
, None),
485 (Link
.IFLA_BR_VLAN_DEFAULT_PVID
, Link
.IFLA_BR_VLAN_DEFAULT_PVID
, None),
486 (Link
.IFLA_BR_PAD
, Link
.IFLA_BR_PAD
, None),
487 (Link
.IFLA_BR_VLAN_STATS_ENABLED
, "vlan-stats", str),
488 (Link
.IFLA_BR_MCAST_STATS_ENABLED
, "mcstats", str),
489 (Link
.IFLA_BR_MCAST_IGMP_VERSION
, "igmp-version", str),
490 (Link
.IFLA_BR_MCAST_MLD_VERSION
, "mld-version", str)
493 def _link_dump_info_data_bridge(self
, ifname
, linkdata
):
495 for nl_attr
, cache_key
, func
in self
.ifla_bridge_attributes
:
498 linkinfo
[cache_key
] = func(linkdata
.get(nl_attr
))
500 linkinfo
[cache_key
] = linkdata
.get(nl_attr
)
502 # we also store the value in pure netlink,
503 # to make the transition easier in the future
504 linkinfo
[nl_attr
] = linkdata
.get(nl_attr
)
505 except Exception as e
:
506 self
.logger
.error('%s: parsing birdge IFLA_INFO_DATA %s: %s'
507 % (ifname
, nl_attr
, str(e
)))
510 def _link_dump_info_slave_data_bridge(self
, ifname
, info_slave_data
):
511 return info_slave_data
513 def _link_dump_info_data_gre_tunnel(self
, ifname
, info_slave_data
):
514 tunnel_link_ifindex
= info_slave_data
.get(Link
.IFLA_GRE_LINK
)
517 "endpoint": str(info_slave_data
.get(Link
.IFLA_GRE_REMOTE
)),
518 "local": str(info_slave_data
.get(Link
.IFLA_GRE_LOCAL
)),
519 "ttl": str(info_slave_data
.get(Link
.IFLA_GRE_TTL
)),
520 "tunnel-physdev": self
.get_iface_name(tunnel_link_ifindex
) if tunnel_link_ifindex
else ""
523 def _link_dump_info_data_iptun_tunnel(self
, ifname
, info_slave_data
):
524 tunnel_link_ifindex
= info_slave_data
.get(Link
.IFLA_IPTUN_LINK
)
527 "endpoint": str(info_slave_data
.get(Link
.IFLA_IPTUN_REMOTE
)),
528 "local": str(info_slave_data
.get(Link
.IFLA_IPTUN_LOCAL
)),
529 "ttl": str(info_slave_data
.get(Link
.IFLA_IPTUN_TTL
)),
530 "tunnel-physdev": self
.get_iface_name(tunnel_link_ifindex
) if tunnel_link_ifindex
else ""
533 def _link_dump_info_data_vti_tunnel(self
, ifname
, info_slave_data
):
534 tunnel_link_ifindex
= info_slave_data
.get(Link
.IFLA_VTI_LINK
)
537 "endpoint": str(info_slave_data
.get(Link
.IFLA_VTI_REMOTE
)),
538 "local": str(info_slave_data
.get(Link
.IFLA_VTI_LOCAL
)),
539 "tunnel-physdev": self
.get_iface_name(tunnel_link_ifindex
) if tunnel_link_ifindex
else ""
542 def _link_dump_linkinfo(self
, link
, dump
):
543 linkinfo
= link
.attributes
[Link
.IFLA_LINKINFO
].get_pretty_value(dict)
546 info_kind
= linkinfo
.get(Link
.IFLA_INFO_KIND
)
547 info_data
= linkinfo
.get(Link
.IFLA_INFO_DATA
)
549 info_slave_kind
= linkinfo
.get(Link
.IFLA_INFO_SLAVE_KIND
)
550 info_slave_data
= linkinfo
.get(Link
.IFLA_INFO_SLAVE_DATA
)
552 dump
['kind'] = info_kind
553 dump
['slave_kind'] = info_slave_kind
556 link_kind_handler
= self
.link_kind_handlers
.get(info_kind
)
557 if callable(link_kind_handler
):
558 dump
['linkinfo'] = link_kind_handler(dump
['ifname'], info_data
)
561 dump
['info_slave_data'] = info_slave_data
563 def link_dump(self
, ifname
=None):
565 self
.logger
.info('netlink: ip link show dev %s' % ifname
)
567 self
.logger
.info('netlink: ip link show')
569 if ifupdownflags
.flags
.DRYRUN
: return {}
574 links_dump
= self
._nlmanager
_api
.link_dump(ifname
)
575 except Exception as e
:
576 raise Exception('netlink: link dump failed: %s' % str(e
))
578 for link
in links_dump
:
583 for flag
, string
in Link
.flag_to_string
.items():
584 if link
.flags
& flag
:
585 flags
.append(string
[4:])
587 dump
['flags'] = flags
588 dump
['ifflag'] = 'UP' if 'UP' in flags
else 'DOWN'
589 dump
['ifindex'] = str(link
.ifindex
)
591 if link
.device_type
== Link
.ARPHRD_ETHER
:
592 self
._link
_dump
_attr
(link
, [self
.ifla_address
], dump
)
594 self
._link
_dump
_attr
(link
, self
.ifla_attributes
, dump
)
596 if Link
.IFLA_LINKINFO
in link
.attributes
:
597 self
._link
_dump
_linkinfo
(link
, dump
)
599 links
[dump
['ifname']] = dump
600 except Exception as e
:
601 self
.logger
.warning('netlink: ip link show: %s' % str(e
))
604 def _addr_dump_extract_ifname(self
, addr_packet
):
605 addr_ifname_attr
= addr_packet
.attributes
.get(Address
.IFA_LABEL
)
608 return addr_ifname_attr
.get_pretty_value(str)
610 return self
.get_iface_name(addr_packet
.ifindex
)
613 def _addr_filter(addr_ifname
, addr
):
614 return addr_ifname
== 'lo' and addr
in ['127.0.0.1/8', '::1/128', '0.0.0.0']
616 def _addr_dump_entry(self
, ifaces
, addr_packet
, addr_ifname
, ifa_attr
):
617 attribute
= addr_packet
.attributes
.get(ifa_attr
)
620 address
= attribute
.get_pretty_value(str)
622 if hasattr(addr_packet
, 'prefixlen'):
623 address
= '%s/%d' % (address
, addr_packet
.prefixlen
)
625 if self
._addr
_filter
(addr_ifname
, address
):
628 addr_family
= NetlinkPacket
.af_family_to_string
.get(addr_packet
.family
)
632 ifaces
[addr_ifname
]['addrs'][address
] = {
634 'scope': addr_packet
.scope
637 ifa_address_attributes
= [
640 Address
.IFA_BROADCAST
,
642 Address
.IFA_MULTICAST
645 def addr_dump(self
, ifname
=None):
647 self
.logger
.info('netlink: ip addr show dev %s' % ifname
)
649 self
.logger
.info('netlink: ip addr show')
652 addr_dump
= self
._nlmanager
_api
.addr_dump()
654 for addr_packet
in addr_dump
:
655 addr_ifname
= self
._addr
_dump
_extract
_ifname
(addr_packet
)
657 if addr_packet
.family
not in [socket
.AF_INET
, socket
.AF_INET6
]:
660 if ifname
and ifname
!= addr_ifname
:
663 if addr_ifname
not in ifaces
:
664 ifaces
[addr_ifname
] = {'addrs': OrderedDict({})}
666 for ifa_attr
in self
.ifa_address_attributes
:
667 self
._addr
_dump
_entry
(ifaces
, addr_packet
, addr_ifname
, ifa_attr
)
670 return {ifname
: ifaces
.get(ifname
, {})}