1 # Copyright (c) 2009-2013, Exa Networks Limited
2 # Copyright (c) 2009-2013, Thomas Mangin
3 # Copyright (c) 2015-2017 Cumulus Networks, Inc.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
9 # Redistributions of source code must retain the above copyright notice, this
10 # list of conditions and the following disclaimer.
12 # Redistributions in binary form must reproduce the above copyright notice,
13 # this list of conditions and the following disclaimer in the documentation
14 # and/or other materials provided with the distribution.
16 # The names of the Exa Networks Limited, Cumulus Networks, Inc. nor the names
17 # of its contributors may be used to endorse or promote products derived from
18 # this software without specific prior written permission.
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26 # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 from ipaddr
import IPv4Address
, IPv6Address
, IPAddress
34 from binascii
import hexlify
35 from pprint
import pformat
36 from socket
import AF_UNSPEC
, AF_INET
, AF_INET6
, AF_BRIDGE
, htons
37 from string
import printable
38 from struct
import pack
, unpack
, calcsize
40 log
= logging
.getLogger(__name__
)
41 SYSLOG_EXTRA_DEBUG
= 5
44 # Interface name buffer size #define IFNAMSIZ 16 (kernel source)
45 IF_NAME_SIZE
= 15 # 15 because python doesn't have \0
47 # Netlink message types
53 RTM_NEWLINK
= 0x10 # Create a new network interface
54 RTM_DELLINK
= 0x11 # Destroy a network interface
55 RTM_GETLINK
= 0x12 # Retrieve information about a network interface(ifinfomsg)
74 # Netlink message flags
75 NLM_F_REQUEST
= 0x01 # It is query message.
76 NLM_F_MULTI
= 0x02 # Multipart message, terminated by NLMSG_DONE
77 NLM_F_ACK
= 0x04 # Reply with ack, with zero or error code
78 NLM_F_ECHO
= 0x08 # Echo this query
80 # Modifiers to GET query
81 NLM_F_ROOT
= 0x100 # specify tree root
82 NLM_F_MATCH
= 0x200 # return all matching
83 NLM_F_DUMP
= NLM_F_ROOT | NLM_F_MATCH
84 NLM_F_ATOMIC
= 0x400 # atomic GET
86 # Modifiers to NEW query
87 NLM_F_REPLACE
= 0x100 # Override existing
88 NLM_F_EXCL
= 0x200 # Do not touch, if it exists
89 NLM_F_CREATE
= 0x400 # Create, if it does not exist
90 NLM_F_APPEND
= 0x800 # Add to end of list
93 NLA_F_NET_BYTEORDER
= 0x4000
94 NLA_TYPE_MASK
= ~
(NLA_F_NESTED | NLA_F_NET_BYTEORDER
)
101 RTMGRP_IPV4_IFADDR
= 0x10
102 RTMGRP_IPV4_MROUTE
= 0x20
103 RTMGRP_IPV4_ROUTE
= 0x40
104 RTMGRP_IPV4_RULE
= 0x80
105 RTMGRP_IPV6_IFADDR
= 0x100
106 RTMGRP_IPV6_MROUTE
= 0x200
107 RTMGRP_IPV6_ROUTE
= 0x400
108 RTMGRP_IPV6_IFINFO
= 0x800
109 RTMGRP_DECnet_IFADDR
= 0x1000
110 RTMGRP_DECnet_ROUTE
= 0x4000
111 RTMGRP_IPV6_PREFIX
= 0x20000
113 RTMGRP_ALL
= (RTMGRP_LINK | RTMGRP_NOTIFY | RTMGRP_NEIGH | RTMGRP_TC |
114 RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_MROUTE | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_RULE |
115 RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_MROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFINFO |
116 RTMGRP_DECnet_IFADDR | RTMGRP_DECnet_ROUTE |
127 value_to_bool_dict
= {
145 def set_log_level(level
):
149 def zfilled_hex(value
, digits
):
150 return '0x' + hex(value
)[2:].zfill(digits
)
153 def remove_trailing_null(line
):
155 Remove the last character if it is a NULL...having that NULL
156 causes python to print a garbage character
159 if ord(line
[-1]) == 0:
165 def mac_int_to_str(mac_int
):
167 Return an integer in MAC string format
170 # [2:] to remove the leading 0x, then fill out to 12 zeroes, then uppercase
171 all_caps
= hex(int(mac_int
))[2:].zfill(12).upper()
173 if all_caps
[-1] == 'L':
174 all_caps
= all_caps
[:-1]
175 all_caps
= all_caps
.zfill(12).upper()
177 return "%s.%s.%s" % (all_caps
[0:4], all_caps
[4:8], all_caps
[8:12])
180 def data_to_color_text(line_number
, color
, data
, extra
=''):
181 (c1
, c2
, c3
, c4
) = unpack('BBBB', data
[0:4])
184 for c
in (c1
, c2
, c3
, c4
):
187 if char_c
in printable
[:-5]:
188 in_ascii
.append(char_c
)
193 return ' %2d: \033[%dm0x%02x%02x%02x%02x\033[0m %s %s' % (line_number
, color
, c1
, c2
, c3
, c4
, ''.join(in_ascii
), extra
)
195 return ' %2d: 0x%02x%02x%02x%02x %s %s' % (line_number
, c1
, c2
, c3
, c4
, ''.join(in_ascii
), extra
)
198 def padded_length(length
):
199 return int((length
+ 3) / 4) * 4
202 class Attribute(object):
204 def __init__(self
, atype
, string
, logger
):
207 self
.HEADER_PACK
= '=HH'
208 self
.HEADER_LEN
= calcsize(self
.HEADER_PACK
)
213 self
.net_byteorder
= False
219 def set_value(self
, value
):
222 def set_nested(self
, nested
):
225 def set_net_byteorder(self
, net_byteorder
):
226 self
.net_byteorder
= net_byteorder
228 def pad_bytes_needed(self
, length
):
230 Return the number of bytes that should be added to align on a 4-byte boundry
232 remainder
= length
% 4
239 def pad(self
, length
, raw
):
240 pad
= self
.pad_bytes_needed(length
)
250 raise Exception('Please define an encode() method in your child attribute class, or do not use AttributeGeneric')
252 length
= self
.HEADER_LEN
+ self
.LEN
253 attr_type_with_flags
= self
.atype
256 attr_type_with_flags
= attr_type_with_flags | NLA_F_NESTED
258 if self
.net_byteorder
:
259 attr_type_with_flags
= attr_type_with_flags | NLA_F_NET_BYTEORDER
261 raw
= pack(self
.HEADER_PACK
, length
, attr_type_with_flags
) + pack(self
.PACK
, self
.value
)
262 raw
= self
.pad(length
, raw
)
265 def decode_length_type(self
, data
):
267 The first two bytes of an attribute are the length, the next two bytes are the type
270 prev_atype
= self
.atype
271 (data1
, data2
) = unpack(self
.HEADER_PACK
, data
[:self
.HEADER_LEN
])
272 self
.length
= int(data1
)
273 self
.atype
= int(data2
)
274 self
.attr_end
= padded_length(self
.length
)
276 self
.nested
= True if self
.atype
& NLA_F_NESTED
else False
277 self
.net_byteorder
= True if self
.atype
& NLA_F_NET_BYTEORDER
else False
278 self
.atype
= self
.atype
& NLA_TYPE_MASK
280 # Should never happen
281 assert self
.atype
== prev_atype
, "This object changes attribute type from %d to %d, this is bad" % (prev_atype
, self
.atype
)
283 def dump_first_line(self
, dump_buffer
, line_number
, color
):
285 Add the "Length....Type..." line to the dump buffer
287 if self
.attr_end
== self
.length
:
290 padded_to
= ' padded to %d, ' % self
.attr_end
292 extra
= 'Length %s (%d)%sType %s%s%s (%d) %s' % \
293 (zfilled_hex(self
.length
, 4), self
.length
,
295 zfilled_hex(self
.atype
, 4),
296 " (NLA_F_NESTED set)" if self
.nested
else "",
297 " (NLA_F_NET_BYTEORDER set)" if self
.net_byteorder
else "",
301 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[0:4], extra
))
302 return line_number
+ 1
304 def dump_lines(self
, dump_buffer
, line_number
, color
):
305 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
307 for x
in xrange(1, self
.attr_end
/4):
310 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[start
:end
], ''))
315 def get_pretty_value(self
, obj
=None):
316 if obj
and callable(obj
):
317 return obj(self
.value
)
321 class AttributeFourByteList(Attribute
):
323 def __init__(self
, atype
, string
, family
, logger
):
324 Attribute
.__init
__(self
, atype
, string
, logger
)
326 def decode(self
, parent_msg
, data
):
327 self
.decode_length_type(data
)
328 wordcount
= (self
.attr_end
- 4)/4
329 self
.PACK
= '=%dL' % wordcount
330 self
.LEN
= calcsize(self
.PACK
)
333 self
.value
= unpack(self
.PACK
, self
.data
[4:])
335 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:])))
338 def dump_lines(self
, dump_buffer
, line_number
, color
):
339 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
341 for val
in self
.value
:
342 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4*idx
:4*(idx
+1)], val
))
348 class AttributeFourByteValue(Attribute
):
350 def __init__(self
, atype
, string
, family
, logger
):
351 Attribute
.__init
__(self
, atype
, string
, logger
)
353 self
.LEN
= calcsize(self
.PACK
)
355 def decode(self
, parent_msg
, data
):
356 self
.decode_length_type(data
)
357 assert self
.attr_end
== 8, "Attribute length for %s must be 8, it is %d" % (self
, self
.attr_end
)
360 self
.value
= int(unpack(self
.PACK
, self
.data
[4:])[0])
362 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:])))
365 def dump_lines(self
, dump_buffer
, line_number
, color
):
366 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
367 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8], self
.value
))
368 return line_number
+ 1
371 class AttributeTwoByteValue(Attribute
):
373 def __init__(self
, atype
, string
, family
, logger
):
374 Attribute
.__init
__(self
, atype
, string
, logger
)
376 self
.LEN
= calcsize(self
.PACK
)
378 def decode(self
, parent_msg
, data
):
379 self
.decode_length_type(data
)
380 assert self
.attr_end
== 8, "Attribute length for %s must be 8, it is %d" % (self
, self
.attr_end
)
383 self
.value
= int(unpack(self
.PACK
, self
.data
[4:8])[0])
385 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:6])))
389 length
= self
.HEADER_LEN
+ self
.LEN
390 raw
= pack(self
.HEADER_PACK
, length
-2, self
.atype
) + pack(self
.PACK
, self
.value
)
391 raw
= self
.pad(length
, raw
)
394 def dump_lines(self
, dump_buffer
, line_number
, color
):
395 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
396 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8], self
.value
))
397 return line_number
+ 1
400 class AttributeString(Attribute
):
402 def __init__(self
, atype
, string
, family
, logger
):
403 Attribute
.__init
__(self
, atype
, string
, logger
)
408 # some interface names come from JSON as unicode strings
409 # and cannot be packed as is so we must convert them to strings
410 if isinstance(self
.value
, unicode):
411 self
.value
= str(self
.value
)
412 self
.PACK
= '%ds' % len(self
.value
)
413 self
.LEN
= calcsize(self
.PACK
)
415 length
= self
.HEADER_LEN
+ self
.LEN
416 raw
= pack(self
.HEADER_PACK
, length
, self
.atype
) + pack(self
.PACK
, self
.value
)
417 raw
= self
.pad(length
, raw
)
420 def decode(self
, parent_msg
, data
):
421 self
.decode_length_type(data
)
422 self
.PACK
= '%ds' % (self
.length
- 4)
423 self
.LEN
= calcsize(self
.PACK
)
426 self
.value
= remove_trailing_null(unpack(self
.PACK
, self
.data
[4:self
.length
])[0])
428 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:self
.length
])))
432 class AttributeStringInterfaceName(AttributeString
):
434 def __init__(self
, atype
, string
, family
, logger
):
435 AttributeString
.__init
__(self
, atype
, string
, family
, logger
)
437 def set_value(self
, value
):
438 if value
and len(value
) > IF_NAME_SIZE
:
439 raise Exception('interface name exceeds max length of %d' % IF_NAME_SIZE
)
443 class AttributeIPAddress(Attribute
):
445 def __init__(self
, atype
, string
, family
, logger
):
446 Attribute
.__init
__(self
, atype
, string
, logger
)
447 self
.value_int
= None
448 self
.value_int_str
= None
451 if self
.family
== AF_INET
:
454 elif self
.family
== AF_INET6
:
457 elif self
.family
== AF_BRIDGE
:
461 raise Exception("%s is not a supported address family" % self
.family
)
463 self
.LEN
= calcsize(self
.PACK
)
465 def set_value(self
, value
):
469 self
.value
= IPAddress(value
)
471 def decode(self
, parent_msg
, data
):
472 self
.decode_length_type(data
)
475 if self
.family
== AF_INET
:
476 self
.value
= IPv4Address(unpack(self
.PACK
, self
.data
[4:])[0])
478 elif self
.family
== AF_INET6
:
479 (data1
, data2
) = unpack(self
.PACK
, self
.data
[4:])
480 self
.value
= IPv6Address(data1
<< 64 | data2
)
482 elif self
.family
== AF_BRIDGE
:
483 self
.value
= IPv4Address(unpack(self
.PACK
, self
.data
[4:])[0])
485 self
.value_int
= int(self
.value
)
486 self
.value_int_str
= str(self
.value_int
)
490 self
.value_int
= None
491 self
.value_int_str
= None
492 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:])))
496 length
= self
.HEADER_LEN
+ self
.LEN
498 if self
.family
not in [AF_INET
, AF_INET6
, AF_BRIDGE
]:
499 raise Exception("%s is not a supported address family" % self
.family
)
501 raw
= pack(self
.HEADER_PACK
, length
, self
.atype
) + self
.value
.packed
502 raw
= self
.pad(length
, raw
)
505 def dump_lines(self
, dump_buffer
, line_number
, color
):
506 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
508 if self
.family
== AF_INET
:
509 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8], self
.value
))
512 elif self
.family
== AF_INET6
:
514 for x
in xrange(1, self
.attr_end
/4):
517 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[start
:end
], self
.value
))
520 elif self
.family
== AF_BRIDGE
:
521 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8], self
.value
))
527 class AttributeMACAddress(Attribute
):
529 def __init__(self
, atype
, string
, family
, logger
):
530 Attribute
.__init
__(self
, atype
, string
, logger
)
532 self
.LEN
= calcsize(self
.PACK
)
534 def decode(self
, parent_msg
, data
):
535 self
.decode_length_type(data
)
537 # IFLA_ADDRESS and IFLA_BROADCAST attributes for all interfaces has been a
538 # 6-byte MAC address. But the GRE interface uses a 4-byte IP address and
539 # GREv6 uses a 16-byte IPv6 address for this attribute.
541 # GRE interface uses a 4-byte IP address for this attribute
543 self
.value
= IPv4Address(unpack('>L', self
.data
[4:])[0])
544 self
.value_int
= int(self
.value
)
545 self
.value_int_str
= str(self
.value_int
)
547 elif self
.length
== 10:
548 (data1
, data2
) = unpack(self
.PACK
, self
.data
[4:])
549 self
.value
= mac_int_to_str(data1
<< 16 | data2
)
550 # GREv6 interface uses a 16-byte IP address for this attribute
551 elif self
.length
== 20:
552 self
.value
= IPv6Address(unpack('>L', self
.data
[16:])[0])
553 self
.value_int
= int(self
.value
)
554 self
.value_int_str
= str(self
.value_int
)
556 raise Exception("Length of MACAddress attribute not supported: %d" % self
.length
)
559 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:])))
563 length
= self
.HEADER_LEN
+ self
.LEN
564 mac_raw
= int(self
.value
.replace('.', '').replace(':', ''), 16)
565 raw
= pack(self
.HEADER_PACK
, length
-2, self
.atype
) + pack(self
.PACK
, mac_raw
>> 16, mac_raw
& 0x0000FFFF)
566 raw
= self
.pad(length
, raw
)
569 def dump_lines(self
, dump_buffer
, line_number
, color
):
570 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
571 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8], self
.value
))
573 if len(self
.data
) >= 12:
574 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[8:12]))
579 class AttributeMplsLabel(Attribute
):
581 def __init__(self
, atype
, string
, family
, logger
):
582 Attribute
.__init
__(self
, atype
, string
, logger
)
583 self
.value_int
= None
584 self
.value_int_str
= None
588 def decode(self
, parent_msg
, data
):
589 self
.decode_length_type(data
)
592 (label_high
, label_low_tc_s
, self
.ttl
) = unpack(self
.PACK
, self
.data
[4:])
593 self
.s_bit
= label_low_tc_s
& 0x1
594 self
.traffic_class
= ((label_low_tc_s
& 0xf) >> 1)
595 self
.label
= (label_high
<< 4) |
(label_low_tc_s
>> 4)
596 self
.value
= self
.label
597 self
.value_int
= self
.value
598 self
.value_int_str
= str(self
.value_int
)
602 self
.value_int
= None
603 self
.value_int_str
= None
604 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:])))
607 def dump_lines(self
, dump_buffer
, line_number
, color
):
608 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
609 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8],
610 'label %s, TC %s, bottom-of-stack %s, TTL %d' %
611 (self
.label
, self
.traffic_class
, self
.s_bit
, self
.ttl
)))
617 class AttributeGeneric(Attribute
):
619 def __init__(self
, atype
, string
, family
, logger
):
620 Attribute
.__init
__(self
, atype
, string
, logger
)
624 def decode(self
, parent_msg
, data
):
625 self
.decode_length_type(data
)
626 wordcount
= (self
.attr_end
- 4)/4
627 self
.PACK
= '=%dL' % wordcount
628 self
.LEN
= calcsize(self
.PACK
)
631 self
.value
= ''.join(map(str, unpack(self
.PACK
, self
.data
[4:])))
633 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:])))
637 class AttributeOneByteValue(AttributeGeneric
):
639 def __init__(self
, atype
, string
, family
, logger
):
640 AttributeGeneric
.__init
__(self
, atype
, string
, family
, logger
)
642 self
.LEN
= calcsize(self
.PACK
)
644 def decode(self
, parent_msg
, data
):
645 self
.decode_length_type(data
)
646 assert self
.attr_end
== 8, "Attribute length for %s must be 8, it is %d" % (self
, self
.attr_end
)
649 self
.value
= int(unpack(self
.PACK
, self
.data
[4:8])[0])
651 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:5])))
655 length
= self
.HEADER_LEN
+ self
.LEN
656 raw
= pack(self
.HEADER_PACK
, length
-3, self
.atype
) + pack(self
.PACK
, self
.value
)
657 raw
= self
.pad(length
, raw
)
660 def dump_lines(self
, dump_buffer
, line_number
, color
):
661 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
662 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8], self
.value
))
663 return line_number
+ 1
666 class AttributeIFLA_AF_SPEC(Attribute
):
668 value will be a dictionary such as:
670 Link.IFLA_BRIDGE_FLAGS: flags,
671 Link.IFLA_BRIDGE_VLAN_INFO: (vflags, vlanid)
674 def __init__(self
, atype
, string
, family
, logger
):
675 Attribute
.__init
__(self
, atype
, string
, logger
)
679 pack_layout
= [self
.HEADER_PACK
]
680 payload
= [0, self
.atype | NLA_F_NESTED
]
681 attr_length_index
= 0
683 # For now this assumes that all data will be packed in the native endian
684 # order (=). If a field is added that needs to be packed via network
685 # order (>) then some smarts will need to be added to split the pack_layout
686 # string at the >, split the payload and make the needed pack() calls.
688 # Until we cross that bridge though we will keep things nice and simple and
689 # pack everything via a single pack() call.
692 for (sub_attr_type
, sub_attr_value
) in self
.value
.iteritems():
694 if sub_attr_type
== Link
.IFLA_BRIDGE_FLAGS
:
695 sub_attr_to_add
.append((sub_attr_type
, sub_attr_value
))
697 elif sub_attr_type
== Link
.IFLA_BRIDGE_VLAN_INFO
:
698 for (vlan_flag
, vlan_id
) in sub_attr_value
:
699 sub_attr_to_add
.append((sub_attr_type
, (vlan_flag
, vlan_id
)))
702 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_AF_SPEC sub-attribute type %d' % sub_attr_type
)
705 for (sub_attr_type
, sub_attr_value
) in sub_attr_to_add
:
706 sub_attr_pack_layout
= ['=', 'HH']
707 sub_attr_payload
= [0, sub_attr_type
]
708 sub_attr_length_index
= 0
710 if sub_attr_type
== Link
.IFLA_BRIDGE_FLAGS
:
711 sub_attr_pack_layout
.append('H')
712 sub_attr_payload
.append(sub_attr_value
)
714 elif sub_attr_type
== Link
.IFLA_BRIDGE_VLAN_INFO
:
715 sub_attr_pack_layout
.append('HH')
716 sub_attr_payload
.append(sub_attr_value
[0])
717 sub_attr_payload
.append(sub_attr_value
[1])
719 sub_attr_length
= calcsize(''.join(sub_attr_pack_layout
))
720 sub_attr_payload
[sub_attr_length_index
] = sub_attr_length
723 for x
in xrange(self
.pad_bytes_needed(sub_attr_length
)):
724 sub_attr_pack_layout
.append('x')
726 # The [1:] is to remove the leading = so that when we do the ''.join() later
727 # we do not end up with an = in the middle of the pack layout string. There
728 # will be an = at the beginning via self.HEADER_PACK
729 sub_attr_pack_layout
= sub_attr_pack_layout
[1:]
731 # Now extend the ovarall attribute pack_layout/payload to include this sub-attribute
732 pack_layout
.extend(sub_attr_pack_layout
)
733 payload
.extend(sub_attr_payload
)
735 pack_layout
= ''.join(pack_layout
)
737 # Fill in the length field
738 length
= calcsize(pack_layout
)
739 payload
[attr_length_index
] = length
741 raw
= pack(pack_layout
, *payload
)
742 raw
= self
.pad(length
, raw
)
745 def decode(self
, parent_msg
, data
):
747 value is a dictionary such as:
749 Link.IFLA_BRIDGE_FLAGS: flags,
750 Link.IFLA_BRIDGE_VLAN_INFO: (vflags, vlanid)
754 The encoding of the IFLA_AF_SPEC attribute varies depending on the family
755 used for the request (RTM_GETLINK) message. For AF_UNSPEC the encoding
756 has another level of nesting for each address family with the type encoded
758 af_spec = nla_nest_start(skb, IFLA_AF_SPEC)
760 af = nla_nest_start(skb, af_ops->family)
761 af_ops->fill_link_af(skb, dev, ext_filter_mask)
765 This allows the parser to find the address family by looking at the first
768 Whereas AF_BRIDGE encoding is just:
769 af_spec = nla_nest_start(skb, IFLA_AF_SPEC)
770 br_fill_ifvlaninfo{_compressed}(skb, vg)
773 which means the parser can not use the attribute itself to know the family
774 to which the attribute belongs.
776 /include/uapi/linux/if_link.h
779 * Contains nested attributes for address family specific attributes.
780 * Each address family may create a attribute with the address family
781 * number as type and create its own attribute structure in it.
786 * [IFLA_INET_CONF] = ...,
789 * [IFLA_INET6_FLAGS] = ...,
790 * [IFLA_INET6_CONF] = ...,
796 self
.decode_length_type(data
)
799 # opti for now, since we only support AF_BRIDGE
800 if self
.family
!= AF_BRIDGE
:
806 (sub_attr_length
, sub_attr_type
) = unpack('=HH', data
[:4])
807 sub_attr_end
= padded_length(sub_attr_length
)
809 if not sub_attr_length
:
810 self
.log
.error('parsed a zero length sub-attr')
813 sub_attr_data
= data
[4:sub_attr_end
]
815 if self
.family
== AF_BRIDGE
:
816 if sub_attr_type
== Link
.IFLA_BRIDGE_FLAGS
:
817 self
.value
[Link
.IFLA_BRIDGE_FLAGS
] = unpack("=H", sub_attr_data
[0:2])[0]
819 elif sub_attr_type
== Link
.IFLA_BRIDGE_VLAN_INFO
:
820 if Link
.IFLA_BRIDGE_VLAN_INFO
not in self
.value
:
821 self
.value
[Link
.IFLA_BRIDGE_VLAN_INFO
] = []
822 self
.value
[Link
.IFLA_BRIDGE_VLAN_INFO
].append(tuple(unpack("=HH", sub_attr_data
[0:4])))
825 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_AF_SPEC sub-attribute '
826 'type %s (%d), length %d, padded to %d' %
827 (parent_msg
.get_ifla_bridge_af_spec_to_string(sub_attr_type
),
828 sub_attr_type
, sub_attr_length
, sub_attr_end
))
830 elif self
.family
== AF_UNSPEC
:
831 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_AF_SPEC sub-attribute '
832 'type AF_UNSPEC (0), length %d, padded to %d'
833 % (sub_attr_length
, sub_attr_end
))
836 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_AF_SPEC sub-attribute '
837 'family %d, length %d, padded to %d'
838 % (self
.family
, sub_attr_length
, sub_attr_end
))
840 data
= data
[sub_attr_end
:]
842 def dump_lines(self
, dump_buffer
, line_number
, color
):
843 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
846 next_sub_attr_line
= 0
849 for x
in xrange(1, self
.attr_end
/4):
853 if line_number
== next_sub_attr_line
:
857 sub_attr_line
= False
859 (sub_attr_length
, sub_attr_type
) = unpack('=HH', self
.data
[start
:start
+4])
860 sub_attr_end
= padded_length(sub_attr_length
)
862 next_sub_attr_line
= line_number
+ (sub_attr_end
/4)
864 if sub_attr_end
== sub_attr_length
:
867 padded_to
= ' padded to %d, ' % sub_attr_end
869 if self
.family
== AF_BRIDGE
:
870 extra
= 'Nested Attribute - Length %s (%d)%s Type %s (%d) %s' % \
871 (zfilled_hex(sub_attr_length
, 4), sub_attr_length
,
873 zfilled_hex(sub_attr_type
, 4), sub_attr_type
,
874 Link
.ifla_bridge_af_spec_to_string
.get(sub_attr_type
))
878 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[start
:end
], extra
))
883 def get_pretty_value(self
, obj
=None):
885 if obj
and callable(obj
):
886 return obj(self
.value
)
888 # We do this so we can print a more human readable dictionary
889 # with the names of the nested keys instead of their numbers
892 for (sub_key
, sub_value
) in self
.value
.iteritems():
893 sub_key_pretty
= "(%2d) %s" % (sub_key
, Link
.ifla_bridge_af_spec_to_string
.get(sub_key
))
894 value_pretty
[sub_key_pretty
] = sub_value
900 class AttributeRTA_MULTIPATH(Attribute
):
902 /* RTA_MULTIPATH --- array of struct rtnexthop.
904 * "struct rtnexthop" describes all necessary nexthop information,
905 * i.e. parameters of path to a destination via this nexthop.
907 * At the moment it is impossible to set different prefsrc, mtu, window
908 * and rtt for different paths from multipath.
912 unsigned short rtnh_len;
913 unsigned char rtnh_flags;
914 unsigned char rtnh_hops;
919 def __init__(self
, atype
, string
, family
, logger
):
920 Attribute
.__init
__(self
, atype
, string
, logger
)
924 self
.RTNH_PACK
= '=HBBL' # rtnh_len, flags, hops, ifindex
925 self
.RTNH_LEN
= calcsize(self
.RTNH_PACK
)
931 # Calculate the length
932 if self
.family
== AF_INET
:
933 ip_len
= self
.IPV4_LEN
934 elif self
.family
== AF_INET6
:
935 ip_len
= self
.IPV6_LEN
938 length
= self
.HEADER_LEN
+ ((self
.RTNH_LEN
+ self
.HEADER_LEN
+ ip_len
) * len(self
.value
))
939 raw
= pack(self
.HEADER_PACK
, length
, self
.atype
)
943 rtnh_len
= self
.RTNH_LEN
+ self
.HEADER_LEN
+ ip_len
945 for (nexthop
, rtnh_ifindex
) in self
.value
:
948 raw
+= pack(self
.RTNH_PACK
, rtnh_len
, rtnh_flags
, rtnh_hops
, rtnh_ifindex
)
951 raw
+= pack(self
.HEADER_PACK
, self
.HEADER_LEN
+ ip_len
, Route
.RTA_GATEWAY
)
953 if self
.family
== AF_INET
:
954 raw
+= pack('>L', nexthop
)
955 elif self
.family
== AF_INET6
:
956 raw
+= pack('>QQ', nexthop
>> 64, nexthop
& 0x0000000000000000FFFFFFFFFFFFFFFF)
958 raw
= self
.pad(length
, raw
)
961 def decode(self
, parent_msg
, data
):
962 self
.decode_length_type(data
)
968 (rtnh_len
, rtnh_flags
, rtnh_hops
, rtnh_ifindex
) = unpack(self
.RTNH_PACK
, data
[:self
.RTNH_LEN
])
969 data
= data
[self
.RTNH_LEN
:]
971 (attr_type
, attr_length
) = unpack(self
.HEADER_PACK
, self
.data
[:self
.HEADER_LEN
])
972 data
= data
[self
.HEADER_LEN
:]
974 if self
.family
== AF_INET
:
975 if len(data
) < self
.IPV4_LEN
:
977 nexthop
= IPv4Address(unpack('>L', data
[:self
.IPV4_LEN
])[0])
978 self
.value
.append((nexthop
, rtnh_ifindex
, rtnh_flags
, rtnh_hops
))
980 elif self
.family
== AF_INET6
:
981 if len(data
) < self
.IPV6_LEN
:
983 (data1
, data2
) = unpack('>QQ', data
[:self
.IPV6_LEN
])
984 nexthop
= IPv6Address(data1
<< 64 | data2
)
985 self
.value
.append((nexthop
, rtnh_ifindex
, rtnh_flags
, rtnh_hops
))
987 data
= data
[(rtnh_len
-self
.RTNH_LEN
-self
.HEADER_LEN
):]
989 self
.value
= tuple(self
.value
)
992 class AttributeIFLA_LINKINFO(Attribute
):
994 value is a dictionary such as:
997 Link.IFLA_INFO_KIND : 'vlan',
998 Link.IFLA_INFO_DATA : {
999 Link.IFLA_VLAN_ID : vlanid,
1003 def __init__(self
, atype
, string
, family
, logger
):
1004 Attribute
.__init
__(self
, atype
, string
, logger
)
1007 pack_layout
= [self
.HEADER_PACK
]
1008 payload
= [0, self
.atype | NLA_F_NESTED
]
1009 attr_length_index
= 0
1011 kind
= self
.value
.get(Link
.IFLA_INFO_KIND
)
1012 slave_kind
= self
.value
.get(Link
.IFLA_INFO_SLAVE_KIND
)
1014 if not slave_kind
and kind
not in ('vlan', 'macvlan', 'vxlan', 'bond', 'bridge'):
1015 raise Exception('Unsupported IFLA_INFO_KIND %s' % kind
)
1016 elif not kind
and slave_kind
!= 'bridge':
1017 # only support brport for now.
1018 raise Exception('Unsupported IFLA_INFO_SLAVE_KIND %s' % slave_kind
)
1020 # For now this assumes that all data will be packed in the native endian
1021 # order (=). If a field is added that needs to be packed via network
1022 # order (>) then some smarts will need to be added to split the pack_layout
1023 # string at the >, split the payload and make the needed pack() calls.
1025 # Until we cross that bridge though we will keep things nice and simple and
1026 # pack everything via a single pack() call.
1027 for (sub_attr_type
, sub_attr_value
) in self
.value
.iteritems():
1028 sub_attr_pack_layout
= ['=', 'HH']
1029 sub_attr_payload
= [0, sub_attr_type
]
1030 sub_attr_length_index
= 0
1032 if sub_attr_type
== Link
.IFLA_INFO_KIND
:
1033 sub_attr_pack_layout
.append('%ds' % len(sub_attr_value
))
1034 sub_attr_payload
.append(sub_attr_value
)
1036 elif sub_attr_type
== Link
.IFLA_INFO_DATA
:
1038 sub_attr_payload
= [0, sub_attr_type | NLA_F_NESTED
]
1040 for (info_data_type
, info_data_value
) in sub_attr_value
.iteritems():
1043 if info_data_type
== Link
.IFLA_VLAN_ID
:
1044 sub_attr_pack_layout
.append('HH')
1045 sub_attr_payload
.append(6) # length
1046 sub_attr_payload
.append(info_data_type
)
1049 sub_attr_pack_layout
.append('H')
1050 sub_attr_payload
.append(info_data_value
)
1053 sub_attr_pack_layout
.extend('xx')
1055 elif info_data_type
== Link
.IFLA_VLAN_PROTOCOL
:
1056 sub_attr_pack_layout
.append('HH')
1057 sub_attr_payload
.append(6) # length
1058 sub_attr_payload
.append(info_data_type
)
1061 vlan_protocol
= Link
.ifla_vlan_protocol_dict
.get(info_data_value
)
1062 if not vlan_protocol
:
1063 raise NotImplementedError('vlan protocol %s not implemented' % info_data_value
)
1065 sub_attr_pack_layout
.append('H')
1066 sub_attr_payload
.append(htons(vlan_protocol
))
1069 sub_attr_pack_layout
.extend('xx')
1071 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA vlan sub-attribute type %d' % info_data_type
)
1073 elif kind
== 'macvlan':
1074 if info_data_type
== Link
.IFLA_MACVLAN_MODE
:
1075 sub_attr_pack_layout
.append('HH')
1076 sub_attr_payload
.append(8) # length
1077 sub_attr_payload
.append(info_data_type
)
1080 sub_attr_pack_layout
.append('L')
1081 sub_attr_payload
.append(info_data_value
)
1084 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA macvlan sub-attribute type %d' % info_data_type
)
1086 elif kind
== 'vxlan':
1087 if info_data_type
in (Link
.IFLA_VXLAN_ID
,
1088 Link
.IFLA_VXLAN_LINK
,
1089 Link
.IFLA_VXLAN_AGEING
,
1090 Link
.IFLA_VXLAN_LIMIT
,
1091 Link
.IFLA_VXLAN_PORT_RANGE
):
1092 sub_attr_pack_layout
.append('HH')
1093 sub_attr_payload
.append(8) # length
1094 sub_attr_payload
.append(info_data_type
)
1096 sub_attr_pack_layout
.append('L')
1097 sub_attr_payload
.append(info_data_value
)
1099 elif info_data_type
in (Link
.IFLA_VXLAN_GROUP
,
1100 Link
.IFLA_VXLAN_LOCAL
):
1101 sub_attr_pack_layout
.append('HH')
1102 sub_attr_payload
.append(8) # length
1103 sub_attr_payload
.append(info_data_type
)
1105 sub_attr_pack_layout
.append('L')
1107 reorder
= unpack('<L', IPv4Address(info_data_value
).packed
)[0]
1108 sub_attr_payload
.append(IPv4Address(reorder
))
1110 elif info_data_type
in (Link
.IFLA_VXLAN_PORT
,):
1111 sub_attr_pack_layout
.append('HH')
1112 sub_attr_payload
.append(6)
1113 sub_attr_payload
.append(info_data_type
)
1115 sub_attr_pack_layout
.append('H')
1118 swaped
= pack(">H", info_data_value
)
1119 sub_attr_payload
.append(unpack("<H", swaped
)[0])
1121 sub_attr_pack_layout
.extend('xx')
1123 elif info_data_type
in (Link
.IFLA_VXLAN_TTL
,
1124 Link
.IFLA_VXLAN_TOS
,
1125 Link
.IFLA_VXLAN_LEARNING
,
1126 Link
.IFLA_VXLAN_PROXY
,
1127 Link
.IFLA_VXLAN_RSC
,
1128 Link
.IFLA_VXLAN_L2MISS
,
1129 Link
.IFLA_VXLAN_L3MISS
,
1130 Link
.IFLA_VXLAN_UDP_CSUM
,
1131 Link
.IFLA_VXLAN_UDP_ZERO_CSUM6_TX
,
1132 Link
.IFLA_VXLAN_UDP_ZERO_CSUM6_RX
,
1133 Link
.IFLA_VXLAN_REMCSUM_TX
,
1134 Link
.IFLA_VXLAN_REMCSUM_RX
,
1135 Link
.IFLA_VXLAN_REPLICATION_TYPE
):
1136 sub_attr_pack_layout
.append('HH')
1137 sub_attr_payload
.append(6)
1138 sub_attr_payload
.append(info_data_type
)
1140 sub_attr_pack_layout
.append('B')
1141 sub_attr_payload
.append(info_data_value
)
1142 sub_attr_pack_layout
.extend('xxx')
1145 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA vxlan sub-attribute type %d' % info_data_type
)
1147 elif kind
== 'bond':
1148 if info_data_type
in (Link
.IFLA_BOND_AD_ACTOR_SYSTEM
, ):
1149 sub_attr_pack_layout
.append('HH')
1150 sub_attr_payload
.append(10) # length
1151 sub_attr_payload
.append(info_data_type
)
1153 sub_attr_pack_layout
.append('6B')
1154 for mbyte
in info_data_value
.replace('.', ' ').replace(':', ' ').split():
1155 sub_attr_payload
.append(int(mbyte
, 16))
1156 sub_attr_pack_layout
.extend('xx')
1158 elif info_data_type
== Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
:
1159 sub_attr_pack_layout
.append('HH')
1160 sub_attr_payload
.append(6) # length
1161 sub_attr_payload
.append(info_data_type
)
1164 sub_attr_pack_layout
.append('H')
1165 sub_attr_payload
.append(int(info_data_value
))
1168 sub_attr_pack_layout
.extend('xx')
1170 elif info_data_type
== Link
.IFLA_BOND_NUM_PEER_NOTIF
:
1171 sub_attr_pack_layout
.append('HH')
1172 sub_attr_payload
.append(5) # length
1173 sub_attr_payload
.append(info_data_type
)
1176 sub_attr_pack_layout
.append('B')
1177 sub_attr_payload
.append(int(info_data_value
))
1180 sub_attr_pack_layout
.extend('xxx')
1183 elif info_data_type
in (Link
.IFLA_BOND_AD_LACP_RATE
,
1184 Link
.IFLA_BOND_AD_LACP_BYPASS
,
1185 Link
.IFLA_BOND_USE_CARRIER
):
1186 # converts yes/no/on/off/0/1 strings to boolean value
1187 bool_value
= self
.get_bool_value(info_data_value
)
1189 sub_attr_pack_layout
.append('HH')
1190 sub_attr_payload
.append(5) # length
1191 sub_attr_payload
.append(info_data_type
)
1194 sub_attr_pack_layout
.append('B')
1195 sub_attr_payload
.append(bool_value
)
1198 sub_attr_pack_layout
.extend('xxx')
1200 elif info_data_type
== Link
.IFLA_BOND_XMIT_HASH_POLICY
:
1201 index
= self
.get_index(Link
.ifla_bond_xmit_hash_policy_tbl
,
1202 'bond xmit hash policy',
1205 sub_attr_pack_layout
.append('HH')
1206 sub_attr_payload
.append(5) # length
1207 sub_attr_payload
.append(info_data_type
)
1210 sub_attr_pack_layout
.append('B')
1211 sub_attr_payload
.append(index
)
1214 sub_attr_pack_layout
.extend('xxx')
1216 elif info_data_type
== Link
.IFLA_BOND_MODE
:
1217 index
= self
.get_index(Link
.ifla_bond_mode_tbl
,
1221 sub_attr_pack_layout
.append('HH')
1222 sub_attr_payload
.append(5) # length
1223 sub_attr_payload
.append(info_data_type
)
1226 sub_attr_pack_layout
.append('B')
1227 sub_attr_payload
.append(index
)
1230 sub_attr_pack_layout
.extend('xxx')
1232 elif info_data_type
in (Link
.IFLA_BOND_MIIMON
,
1233 Link
.IFLA_BOND_UPDELAY
,
1234 Link
.IFLA_BOND_DOWNDELAY
,
1235 Link
.IFLA_BOND_MIN_LINKS
):
1236 sub_attr_pack_layout
.append('HH')
1237 sub_attr_payload
.append(8) # length
1238 sub_attr_payload
.append(info_data_type
)
1240 sub_attr_pack_layout
.append('L')
1241 sub_attr_payload
.append(int(info_data_value
))
1244 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA bond sub-attribute type %d' % info_data_type
)
1246 elif kind
== 'bridge':
1247 if info_data_type
== Link
.IFLA_BR_VLAN_PROTOCOL
:
1248 sub_attr_pack_layout
.append('HH')
1249 sub_attr_payload
.append(6) # length
1250 sub_attr_payload
.append(info_data_type
)
1253 vlan_protocol
= Link
.ifla_vlan_protocol_dict
.get(info_data_value
)
1254 if not vlan_protocol
:
1255 raise NotImplementedError('vlan protocol %s not implemented' % info_data_value
)
1257 sub_attr_pack_layout
.append('H')
1258 sub_attr_payload
.append(htons(vlan_protocol
))
1261 sub_attr_pack_layout
.extend('xx')
1264 elif info_data_type
in (Link
.IFLA_BR_VLAN_FILTERING
,
1265 Link
.IFLA_BR_TOPOLOGY_CHANGE
,
1266 Link
.IFLA_BR_TOPOLOGY_CHANGE_DETECTED
,
1267 Link
.IFLA_BR_MCAST_ROUTER
,
1268 Link
.IFLA_BR_MCAST_SNOOPING
,
1269 Link
.IFLA_BR_MCAST_QUERY_USE_IFADDR
,
1270 Link
.IFLA_BR_MCAST_QUERIER
,
1271 Link
.IFLA_BR_NF_CALL_IPTABLES
,
1272 Link
.IFLA_BR_NF_CALL_IP6TABLES
,
1273 Link
.IFLA_BR_NF_CALL_ARPTABLES
,
1274 Link
.IFLA_BR_VLAN_STATS_ENABLED
,
1275 Link
.IFLA_BR_MCAST_STATS_ENABLED
,
1276 Link
.IFLA_BR_MCAST_IGMP_VERSION
,
1277 Link
.IFLA_BR_MCAST_MLD_VERSION
):
1278 sub_attr_pack_layout
.append('HH')
1279 sub_attr_payload
.append(5) # length
1280 sub_attr_payload
.append(info_data_type
)
1283 sub_attr_pack_layout
.append('B')
1284 sub_attr_payload
.append(int(info_data_value
))
1287 sub_attr_pack_layout
.extend('xxx')
1290 elif info_data_type
in (Link
.IFLA_BR_PRIORITY
,
1291 Link
.IFLA_BR_GROUP_FWD_MASK
,
1292 Link
.IFLA_BR_ROOT_PORT
,
1293 Link
.IFLA_BR_VLAN_DEFAULT_PVID
):
1294 sub_attr_pack_layout
.append('HH')
1295 sub_attr_payload
.append(6) # length
1296 sub_attr_payload
.append(info_data_type
)
1299 sub_attr_pack_layout
.append('H')
1300 sub_attr_payload
.append(int(info_data_value
))
1303 sub_attr_pack_layout
.extend('xx')
1306 elif info_data_type
in (Link
.IFLA_BR_FORWARD_DELAY
,
1307 Link
.IFLA_BR_HELLO_TIME
,
1308 Link
.IFLA_BR_MAX_AGE
,
1309 Link
.IFLA_BR_AGEING_TIME
,
1310 Link
.IFLA_BR_STP_STATE
,
1311 Link
.IFLA_BR_ROOT_PATH_COST
,
1312 Link
.IFLA_BR_MCAST_QUERIER
,
1313 Link
.IFLA_BR_MCAST_HASH_ELASTICITY
,
1314 Link
.IFLA_BR_MCAST_HASH_MAX
,
1315 Link
.IFLA_BR_MCAST_LAST_MEMBER_CNT
,
1316 Link
.IFLA_BR_MCAST_STARTUP_QUERY_CNT
):
1317 sub_attr_pack_layout
.append('HH')
1318 sub_attr_payload
.append(8) # length
1319 sub_attr_payload
.append(info_data_type
)
1321 sub_attr_pack_layout
.append('L')
1322 sub_attr_payload
.append(int(info_data_value
))
1325 elif info_data_type
in (Link
.IFLA_BR_MCAST_LAST_MEMBER_INTVL
,
1326 Link
.IFLA_BR_MCAST_MEMBERSHIP_INTVL
,
1327 Link
.IFLA_BR_MCAST_QUERIER_INTVL
,
1328 Link
.IFLA_BR_MCAST_QUERY_INTVL
,
1329 Link
.IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
,
1330 Link
.IFLA_BR_MCAST_STARTUP_QUERY_INTVL
):
1331 sub_attr_pack_layout
.append('HH')
1332 sub_attr_payload
.append(12) # length
1333 sub_attr_payload
.append(info_data_type
)
1335 sub_attr_pack_layout
.append('Q')
1336 sub_attr_payload
.append(int(info_data_value
))
1339 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA bridge sub-attribute type %d' % info_data_type
)
1341 elif sub_attr_type
== Link
.IFLA_INFO_SLAVE_DATA
:
1343 sub_attr_payload
= [0, sub_attr_type | NLA_F_NESTED
]
1345 for (info_slave_data_type
, info_slave_data_value
) in sub_attr_value
.iteritems():
1347 if slave_kind
== 'bridge':
1350 if info_slave_data_type
in (Link
.IFLA_BRPORT_STATE
,
1351 Link
.IFLA_BRPORT_MODE
,
1352 Link
.IFLA_BRPORT_GUARD
,
1353 Link
.IFLA_BRPORT_PROTECT
,
1354 Link
.IFLA_BRPORT_FAST_LEAVE
,
1355 Link
.IFLA_BRPORT_LEARNING
,
1356 Link
.IFLA_BRPORT_UNICAST_FLOOD
,
1357 Link
.IFLA_BRPORT_PROXYARP
,
1358 Link
.IFLA_BRPORT_LEARNING_SYNC
,
1359 Link
.IFLA_BRPORT_PROXYARP_WIFI
,
1360 Link
.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
,
1361 Link
.IFLA_BRPORT_CONFIG_PENDING
,
1362 Link
.IFLA_BRPORT_MULTICAST_ROUTER
,
1363 Link
.IFLA_BRPORT_MCAST_FLOOD
,
1364 Link
.IFLA_BRPORT_MCAST_TO_UCAST
,
1365 Link
.IFLA_BRPORT_VLAN_TUNNEL
,
1366 Link
.IFLA_BRPORT_BCAST_FLOOD
,
1367 Link
.IFLA_BRPORT_PEER_LINK
,
1368 Link
.IFLA_BRPORT_DUAL_LINK
,
1369 Link
.IFLA_BRPORT_ARP_SUPPRESS
,
1370 Link
.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
):
1371 sub_attr_pack_layout
.append('HH')
1372 sub_attr_payload
.append(5) # length
1373 sub_attr_payload
.append(info_slave_data_type
)
1376 sub_attr_pack_layout
.append('B')
1377 sub_attr_payload
.append(int(info_slave_data_value
))
1380 sub_attr_pack_layout
.extend('xxx')
1383 elif info_slave_data_type
in (Link
.IFLA_BRPORT_PRIORITY
,
1384 Link
.IFLA_BRPORT_DESIGNATED_PORT
,
1385 Link
.IFLA_BRPORT_DESIGNATED_COST
,
1386 Link
.IFLA_BRPORT_ID
,
1387 Link
.IFLA_BRPORT_NO
,
1388 Link
.IFLA_BRPORT_GROUP_FWD_MASK
,
1389 Link
.IFLA_BRPORT_GROUP_FWD_MASKHI
):
1390 sub_attr_pack_layout
.append('HH')
1391 sub_attr_payload
.append(6) # length
1392 sub_attr_payload
.append(info_slave_data_type
)
1395 sub_attr_pack_layout
.append('H')
1396 sub_attr_payload
.append(int(info_slave_data_value
))
1399 sub_attr_pack_layout
.extend('xx')
1402 elif info_slave_data_type
== Link
.IFLA_BRPORT_COST
:
1403 sub_attr_pack_layout
.append('HH')
1404 sub_attr_payload
.append(8) # length
1405 sub_attr_payload
.append(info_slave_data_type
)
1407 sub_attr_pack_layout
.append('L')
1408 sub_attr_payload
.append(int(info_slave_data_value
))
1411 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_SLAVE_DATA bond sub-attribute type %d' % info_slave_data_type
)
1414 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_LINKINFO kind %s' % slave_kind
)
1417 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_LINKINFO sub-attribute type %d' % sub_attr_type
)
1420 sub_attr_length
= calcsize(''.join(sub_attr_pack_layout
))
1421 sub_attr_payload
[sub_attr_length_index
] = sub_attr_length
1424 for x
in xrange(self
.pad_bytes_needed(sub_attr_length
)):
1425 sub_attr_pack_layout
.append('x')
1427 # The [1:] is to remove the leading = so that when we do the ''.join() later
1428 # we do not end up with an = in the middle of the pack layout string. There
1429 # will be an = at the beginning via self.HEADER_PACK
1430 sub_attr_pack_layout
= sub_attr_pack_layout
[1:]
1432 # Now extend the ovarall attribute pack_layout/payload to include this sub-attribute
1433 pack_layout
.extend(sub_attr_pack_layout
)
1434 payload
.extend(sub_attr_payload
)
1436 pack_layout
= ''.join(pack_layout
)
1438 # Fill in the length field
1439 length
= calcsize(pack_layout
)
1440 payload
[attr_length_index
] = length
1442 raw
= pack(pack_layout
, *payload
)
1443 raw
= self
.pad(length
, raw
)
1446 def get_bool_value(self
, value
, default
=None):
1448 return value_to_bool_dict
[value
]
1450 self
.log
.debug('%s: unsupported boolean value' % value
)
1453 def get_index(self
, tbl
, attr
, value
, default
=None):
1457 self
.log
.debug('unsupported %s value %s (%s)' % (attr
, value
, tbl
.keys()))
1460 def decode(self
, parent_msg
, data
):
1462 value is a dictionary such as:
1465 Link.IFLA_INFO_KIND : 'vlan',
1466 Link.IFLA_INFO_DATA : {
1467 Link.IFLA_VLAN_ID : vlanid,
1471 self
.decode_length_type(data
)
1474 data
= self
.data
[4:]
1476 # IFLA_MACVLAN_MODE and IFLA_VLAN_ID both have a value of 1 and both are
1477 # valid IFLA_INFO_DATA entries :( The sender must TX IFLA_INFO_KIND
1478 # first in order for us to know if "1" is IFLA_MACVLAN_MODE vs IFLA_VLAN_ID.
1481 (sub_attr_length
, sub_attr_type
) = unpack('=HH', data
[:4])
1482 sub_attr_end
= padded_length(sub_attr_length
)
1484 if not sub_attr_length
:
1485 self
.log
.error('parsed a zero length sub-attr')
1488 if sub_attr_type
in (Link
.IFLA_INFO_KIND
, Link
.IFLA_INFO_SLAVE_KIND
):
1489 self
.value
[sub_attr_type
] = remove_trailing_null(unpack('%ds' % (sub_attr_length
- 4), data
[4:sub_attr_length
])[0])
1491 elif sub_attr_type
== Link
.IFLA_INFO_SLAVE_DATA
:
1492 sub_attr_data
= data
[4:sub_attr_end
]
1494 ifla_info_slave_data
= dict()
1495 ifla_info_slave_kind
= self
.value
.get(Link
.IFLA_INFO_SLAVE_KIND
)
1497 if not ifla_info_slave_kind
:
1498 self
.log
.warning('IFLA_INFO_SLAVE_KIND is not known...we cannot parse IFLA_INFO_SLAVE_DATA')
1500 while sub_attr_data
:
1501 (info_data_length
, info_data_type
) = unpack('=HH', sub_attr_data
[:4])
1502 info_data_end
= padded_length(info_data_length
)
1504 if ifla_info_slave_kind
== 'bridge':
1506 if info_data_type
in (Link
.IFLA_BRPORT_STATE
,
1507 Link
.IFLA_BRPORT_MODE
,
1508 Link
.IFLA_BRPORT_GUARD
,
1509 Link
.IFLA_BRPORT_PROTECT
,
1510 Link
.IFLA_BRPORT_FAST_LEAVE
,
1511 Link
.IFLA_BRPORT_LEARNING
,
1512 Link
.IFLA_BRPORT_UNICAST_FLOOD
,
1513 Link
.IFLA_BRPORT_PROXYARP
,
1514 Link
.IFLA_BRPORT_LEARNING_SYNC
,
1515 Link
.IFLA_BRPORT_PROXYARP_WIFI
,
1516 Link
.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
,
1517 Link
.IFLA_BRPORT_CONFIG_PENDING
,
1518 Link
.IFLA_BRPORT_MULTICAST_ROUTER
,
1519 Link
.IFLA_BRPORT_MCAST_FLOOD
,
1520 Link
.IFLA_BRPORT_MCAST_TO_UCAST
,
1521 Link
.IFLA_BRPORT_VLAN_TUNNEL
,
1522 Link
.IFLA_BRPORT_PEER_LINK
,
1523 Link
.IFLA_BRPORT_DUAL_LINK
,
1524 Link
.IFLA_BRPORT_ARP_SUPPRESS
,
1525 Link
.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
):
1526 ifla_info_slave_data
[info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1529 elif info_data_type
in (Link
.IFLA_BRPORT_PRIORITY
,
1530 Link
.IFLA_BRPORT_DESIGNATED_PORT
,
1531 Link
.IFLA_BRPORT_DESIGNATED_COST
,
1532 Link
.IFLA_BRPORT_ID
,
1533 Link
.IFLA_BRPORT_NO
,
1534 Link
.IFLA_BRPORT_GROUP_FWD_MASK
,
1535 Link
.IFLA_BRPORT_GROUP_FWD_MASKHI
):
1536 ifla_info_slave_data
[info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1539 elif info_data_type
== Link
.IFLA_BRPORT_COST
:
1540 ifla_info_slave_data
[info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1542 elif ifla_info_slave_kind
== 'bond':
1545 if info_data_type
in (
1546 Link
.IFLA_BOND_SLAVE_STATE
,
1547 Link
.IFLA_BOND_SLAVE_MII_STATUS
,
1548 Link
.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
,
1549 Link
.IFLA_BOND_SLAVE_AD_RX_BYPASS
,
1551 ifla_info_slave_data
[info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1554 elif info_data_type
in (
1555 Link
.IFLA_BOND_SLAVE_QUEUE_ID
,
1556 Link
.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
1558 ifla_info_slave_data
[info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1561 elif info_data_type
== (
1562 Link
.IFLA_BOND_SLAVE_PERM_HWADDR
,
1563 Link
.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT
1565 ifla_info_slave_data
[info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1567 except Exception as e
:
1568 self
.log
.debug('%s: attribute %s: %s'
1569 % (self
.value
[Link
.IFLA_INFO_SLAVE_KIND
],
1572 sub_attr_data
= sub_attr_data
[info_data_end
:]
1574 self
.value
[Link
.IFLA_INFO_SLAVE_DATA
] = ifla_info_slave_data
1576 elif sub_attr_type
== Link
.IFLA_INFO_DATA
:
1577 sub_attr_data
= data
[4:sub_attr_end
]
1578 self
.value
[Link
.IFLA_INFO_DATA
] = {}
1580 ifla_info_kind
= self
.value
.get(Link
.IFLA_INFO_KIND
)
1581 if not ifla_info_kind
:
1582 self
.log
.warning('IFLA_INFO_KIND is not known...we cannot parse IFLA_INFO_DATA')
1584 while sub_attr_data
:
1585 (info_data_length
, info_data_type
) = unpack('=HH', sub_attr_data
[:4])
1586 info_data_end
= padded_length(info_data_length
)
1588 if ifla_info_kind
== 'vlan':
1589 if info_data_type
== Link
.IFLA_VLAN_ID
:
1590 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1592 elif info_data_type
== Link
.IFLA_VLAN_PROTOCOL
:
1593 hex_value
= '0x%s' % sub_attr_data
[4:6].encode('hex')
1594 vlan_protocol
= Link
.ifla_vlan_protocol_dict
.get(int(hex_value
, base
=16))
1597 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = vlan_protocol
1599 self
.log
.warning('IFLA_VLAN_PROTOCOL: cannot decode vlan protocol %s' % hex_value
)
1602 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND vlan type %s (%d), length %d, padded to %d' %
1603 (parent_msg
.get_ifla_vlan_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1605 elif ifla_info_kind
== 'macvlan':
1606 if info_data_type
== Link
.IFLA_MACVLAN_MODE
:
1607 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1609 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND macvlan type %s (%d), length %d, padded to %d' %
1610 (parent_msg
.get_ifla_macvlan_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1612 elif ifla_info_kind
== 'vxlan':
1615 if info_data_type
in (Link
.IFLA_VXLAN_GROUP
,
1616 Link
.IFLA_VXLAN_LOCAL
):
1617 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = IPv4Address(unpack('>L', sub_attr_data
[4:8])[0])
1620 elif info_data_type
in (Link
.IFLA_VXLAN_ID
,
1621 Link
.IFLA_VXLAN_LINK
,
1622 Link
.IFLA_VXLAN_AGEING
,
1623 Link
.IFLA_VXLAN_LIMIT
,
1624 Link
.IFLA_VXLAN_PORT_RANGE
):
1625 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1628 elif info_data_type
in (Link
.IFLA_VXLAN_PORT
, ):
1629 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('!H', sub_attr_data
[4:6])[0]
1630 # The form '!' is available for those poor souls who claim they can't
1631 # remember whether network byte order is big-endian or little-endian.
1634 elif info_data_type
in (Link
.IFLA_VXLAN_TTL
,
1635 Link
.IFLA_VXLAN_TOS
,
1636 Link
.IFLA_VXLAN_LEARNING
,
1637 Link
.IFLA_VXLAN_PROXY
,
1638 Link
.IFLA_VXLAN_RSC
,
1639 Link
.IFLA_VXLAN_L2MISS
,
1640 Link
.IFLA_VXLAN_L3MISS
,
1641 Link
.IFLA_VXLAN_UDP_CSUM
,
1642 Link
.IFLA_VXLAN_UDP_ZERO_CSUM6_TX
,
1643 Link
.IFLA_VXLAN_UDP_ZERO_CSUM6_RX
,
1644 Link
.IFLA_VXLAN_REMCSUM_TX
,
1645 Link
.IFLA_VXLAN_REMCSUM_RX
,
1646 Link
.IFLA_VXLAN_REPLICATION_TYPE
):
1647 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1650 # sub_attr_end = padded_length(sub_attr_length)
1651 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND vxlan type %s (%d), length %d, padded to %d' %
1652 (parent_msg
.get_ifla_vxlan_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1654 elif ifla_info_kind
== 'bond':
1656 if info_data_type
in (Link
.IFLA_BOND_AD_INFO
, ):
1657 ad_attr_data
= sub_attr_data
[4:info_data_end
]
1658 self
.value
[Link
.IFLA_INFO_DATA
][Link
.IFLA_BOND_AD_INFO
] = {}
1661 (ad_data_length
, ad_data_type
) = unpack('=HH', ad_attr_data
[:4])
1662 ad_data_end
= padded_length(ad_data_length
)
1664 if ad_data_type
in (Link
.IFLA_BOND_AD_INFO_PARTNER_MAC
,):
1665 (data1
, data2
) = unpack('>LHxx', ad_attr_data
[4:12])
1666 self
.value
[Link
.IFLA_INFO_DATA
][Link
.IFLA_BOND_AD_INFO
][ad_data_type
] = mac_int_to_str(data1
<< 16 | data2
)
1668 ad_attr_data
= ad_attr_data
[ad_data_end
:]
1671 elif info_data_type
in (Link
.IFLA_BOND_MODE
,
1672 Link
.IFLA_BOND_USE_CARRIER
,
1673 Link
.IFLA_BOND_AD_LACP_RATE
,
1674 Link
.IFLA_BOND_AD_LACP_BYPASS
,
1675 Link
.IFLA_BOND_XMIT_HASH_POLICY
,
1676 Link
.IFLA_BOND_NUM_PEER_NOTIF
):
1677 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1680 elif info_data_type
== Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
:
1681 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1684 elif info_data_type
in (Link
.IFLA_BOND_MIIMON
,
1685 Link
.IFLA_BOND_UPDELAY
,
1686 Link
.IFLA_BOND_DOWNDELAY
,
1687 Link
.IFLA_BOND_MIN_LINKS
):
1688 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1691 elif info_data_type
in (Link
.IFLA_BOND_AD_ACTOR_SYSTEM
, ):
1692 (data1
, data2
) = unpack('>LHxx', sub_attr_data
[4:12])
1693 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = mac_int_to_str(data1
<< 16 | data2
)
1696 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND bond type %s (%d), length %d, padded to %d' %
1697 (parent_msg
.get_ifla_bond_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1699 elif ifla_info_kind
== 'bridge':
1701 if info_data_type
in (Link
.IFLA_BR_AGEING_TIME
,
1702 Link
.IFLA_BR_FORWARD_DELAY
,
1703 Link
.IFLA_BR_HELLO_TIME
,
1704 Link
.IFLA_BR_MAX_AGE
,
1705 Link
.IFLA_BR_STP_STATE
,
1706 Link
.IFLA_BR_ROOT_PATH_COST
,
1707 Link
.IFLA_BR_MCAST_HASH_ELASTICITY
,
1708 Link
.IFLA_BR_MCAST_HASH_MAX
,
1709 Link
.IFLA_BR_MCAST_LAST_MEMBER_CNT
,
1710 Link
.IFLA_BR_MCAST_STARTUP_QUERY_CNT
):
1711 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1714 elif info_data_type
in (Link
.IFLA_BR_PRIORITY
,
1715 Link
.IFLA_BR_GROUP_FWD_MASK
,
1716 Link
.IFLA_BR_ROOT_PORT
,
1717 Link
.IFLA_BR_VLAN_DEFAULT_PVID
):
1718 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1720 elif info_data_type
== Link
.IFLA_BR_VLAN_PROTOCOL
:
1721 hex_value
= '0x%s' % sub_attr_data
[4:6].encode('hex')
1722 vlan_protocol
= Link
.ifla_vlan_protocol_dict
.get(int(hex_value
, base
=16))
1725 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = vlan_protocol
1727 self
.log
.warning('IFLA_VLAN_PROTOCOL: cannot decode vlan protocol %s' % hex_value
)
1730 elif info_data_type
in (Link
.IFLA_BR_MCAST_MEMBERSHIP_INTVL
,
1731 Link
.IFLA_BR_MCAST_QUERIER_INTVL
,
1732 Link
.IFLA_BR_MCAST_LAST_MEMBER_INTVL
,
1733 Link
.IFLA_BR_MCAST_MEMBERSHIP_INTVL
,
1734 Link
.IFLA_BR_MCAST_QUERIER_INTVL
,
1735 Link
.IFLA_BR_MCAST_QUERY_INTVL
,
1736 Link
.IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
,
1737 Link
.IFLA_BR_MCAST_STARTUP_QUERY_INTVL
):
1738 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=Q', sub_attr_data
[4:12])[0]
1741 elif info_data_type
in (Link
.IFLA_BR_VLAN_FILTERING
,
1742 Link
.IFLA_BR_TOPOLOGY_CHANGE
,
1743 Link
.IFLA_BR_TOPOLOGY_CHANGE_DETECTED
,
1744 Link
.IFLA_BR_MCAST_ROUTER
,
1745 Link
.IFLA_BR_MCAST_SNOOPING
,
1746 Link
.IFLA_BR_MCAST_QUERY_USE_IFADDR
,
1747 Link
.IFLA_BR_MCAST_QUERIER
,
1748 Link
.IFLA_BR_NF_CALL_IPTABLES
,
1749 Link
.IFLA_BR_NF_CALL_IP6TABLES
,
1750 Link
.IFLA_BR_NF_CALL_ARPTABLES
,
1751 Link
.IFLA_BR_VLAN_STATS_ENABLED
,
1752 Link
.IFLA_BR_MCAST_STATS_ENABLED
,
1753 Link
.IFLA_BR_MCAST_IGMP_VERSION
,
1754 Link
.IFLA_BR_MCAST_MLD_VERSION
):
1755 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1757 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND bridge type %s (%d), length %d, padded to %d' %
1758 (parent_msg
.get_ifla_br_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1760 elif ifla_info_kind
== 'vrf':
1762 if info_data_type
in (Link
.IFLA_VRF_TABLE
,):
1763 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1767 self
.log
.log(SYSLOG_EXTRA_DEBUG
, "Add support for decoding IFLA_INFO_KIND %s (%d), length %d, padded to %d" %
1768 (ifla_info_kind
, info_data_type
, info_data_length
, info_data_end
))
1770 except Exception as e
:
1771 self
.log
.debug('%s: attribute %s: %s'
1772 % (self
.value
[Link
.IFLA_INFO_KIND
],
1775 sub_attr_data
= sub_attr_data
[info_data_end
:]
1778 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_LINKINFO sub-attribute type %s (%d), length %d, padded to %d' %
1779 (parent_msg
.get_ifla_info_string(sub_attr_type
), sub_attr_type
, sub_attr_length
, sub_attr_end
))
1781 data
= data
[sub_attr_end
:]
1783 # self.log.info('IFLA_LINKINFO values %s' % pformat(self.value))
1785 def dump_lines(self
, dump_buffer
, line_number
, color
):
1786 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
1789 next_sub_attr_line
= 0
1790 sub_attr_line
= True
1792 for x
in xrange(1, self
.attr_end
/4):
1796 if line_number
== next_sub_attr_line
:
1797 sub_attr_line
= True
1800 sub_attr_line
= False
1802 (sub_attr_length
, sub_attr_type
) = unpack('=HH', self
.data
[start
:start
+4])
1803 sub_attr_end
= padded_length(sub_attr_length
)
1805 next_sub_attr_line
= line_number
+ (sub_attr_end
/4)
1807 if sub_attr_end
== sub_attr_length
:
1810 padded_to
= ' padded to %d, ' % sub_attr_end
1812 extra
= 'Nested Attribute - Length %s (%d)%s Type %s (%d) %s' % \
1813 (zfilled_hex(sub_attr_length
, 4), sub_attr_length
,
1815 zfilled_hex(sub_attr_type
, 4), sub_attr_type
,
1816 Link
.ifla_info_to_string
.get(sub_attr_type
))
1820 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[start
:end
], extra
))
1825 def get_pretty_value(self
, obj
=None):
1827 if obj
and callable(obj
):
1828 return obj(self
.value
)
1830 value_pretty
= self
.value
1831 ifla_info_kind
= self
.value
.get(Link
.IFLA_INFO_KIND
)
1832 ifla_info_slave_kind
= self
.value
.get(Link
.IFLA_INFO_SLAVE_KIND
)
1836 # We do this so we can print a more human readable dictionary
1837 # with the names of the nested keys instead of their numbers
1839 # Most of these are placeholders...we need to add support
1840 # for more human readable dictionaries for bond, bridge, etc
1841 kind_dict
[Link
.IFLA_INFO_DATA
] = {
1842 'bond': Link
.ifla_bond_to_string
,
1843 'vlan': Link
.ifla_vlan_to_string
,
1844 'vxlan': Link
.ifla_vxlan_to_string
,
1845 'bridge': Link
.ifla_br_to_string
,
1846 'macvlan': Link
.ifla_macvlan_to_string
1847 }.get(ifla_info_kind
, {})
1849 kind_dict
[Link
.IFLA_INFO_SLAVE_DATA
] = {
1850 'bridge': Link
.ifla_brport_to_string
,
1851 'bond': Link
.ifla_bond_slave_to_string
1852 }.get(ifla_info_slave_kind
, {})
1854 if ifla_info_kind
or ifla_info_slave_kind
:
1857 for (sub_key
, sub_value
) in self
.value
.iteritems():
1858 sub_key_pretty
= "(%2d) %s" % (sub_key
, Link
.ifla_info_to_string
.get(sub_key
, 'UNKNOWN'))
1859 sub_value_pretty
= sub_value
1861 if sub_key
in (Link
.IFLA_INFO_DATA
, Link
.IFLA_INFO_SLAVE_DATA
):
1862 kind_to_string_dict
= kind_dict
.get(sub_key
, {})
1863 sub_value_pretty
= {}
1865 for (sub_sub_key
, sub_sub_value
) in sub_value
.iteritems():
1866 sub_sub_key_pretty
= "(%2d) %s" % (sub_sub_key
, kind_to_string_dict
.get(sub_sub_key
, 'UNKNOWN'))
1867 sub_value_pretty
[sub_sub_key_pretty
] = sub_sub_value
1869 value_pretty
[sub_key_pretty
] = sub_value_pretty
1874 class AttributeIFLA_PROTINFO(Attribute
):
1876 IFLA_PROTINFO nested attributes.
1878 def __init__(self
, atype
, string
, family
, logger
):
1879 Attribute
.__init
__(self
, atype
, string
, logger
)
1880 self
.family
= family
1883 pack_layout
= [self
.HEADER_PACK
]
1884 payload
= [0, self
.atype | NLA_F_NESTED
]
1885 attr_length_index
= 0
1887 if self
.family
not in (AF_BRIDGE
,):
1888 raise Exception('Unsupported IFLA_PROTINFO family %d' % self
.family
)
1890 # For now this assumes that all data will be packed in the native endian
1891 # order (=). If a field is added that needs to be packed via network
1892 # order (>) then some smarts will need to be added to split the pack_layout
1893 # string at the >, split the payload and make the needed pack() calls.
1895 # Until we cross that bridge though we will keep things nice and simple and
1896 # pack everything via a single pack() call.
1897 for (sub_attr_type
, sub_attr_value
) in self
.value
.iteritems():
1898 sub_attr_pack_layout
= ['=', 'HH']
1899 sub_attr_payload
= [0, sub_attr_type
]
1900 sub_attr_length_index
= 0
1902 if self
.family
== AF_BRIDGE
:
1904 if sub_attr_type
in (Link
.IFLA_BRPORT_STATE
,
1905 Link
.IFLA_BRPORT_MODE
,
1906 Link
.IFLA_BRPORT_GUARD
,
1907 Link
.IFLA_BRPORT_PROTECT
,
1908 Link
.IFLA_BRPORT_FAST_LEAVE
,
1909 Link
.IFLA_BRPORT_LEARNING
,
1910 Link
.IFLA_BRPORT_UNICAST_FLOOD
,
1911 Link
.IFLA_BRPORT_PROXYARP
,
1912 Link
.IFLA_BRPORT_LEARNING_SYNC
,
1913 Link
.IFLA_BRPORT_PROXYARP_WIFI
,
1914 Link
.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
,
1915 Link
.IFLA_BRPORT_CONFIG_PENDING
,
1916 Link
.IFLA_BRPORT_FLUSH
,
1917 Link
.IFLA_BRPORT_MULTICAST_ROUTER
,
1918 Link
.IFLA_BRPORT_PEER_LINK
,
1919 Link
.IFLA_BRPORT_DUAL_LINK
,
1920 Link
.IFLA_BRPORT_ARP_SUPPRESS
,
1921 Link
.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
):
1922 sub_attr_pack_layout
.append('B')
1923 sub_attr_payload
.append(sub_attr_value
)
1924 sub_attr_pack_layout
.extend('xxx')
1927 elif sub_attr_type
in (Link
.IFLA_BRPORT_PRIORITY
,
1928 Link
.IFLA_BRPORT_DESIGNATED_PORT
,
1929 Link
.IFLA_BRPORT_DESIGNATED_COST
,
1930 Link
.IFLA_BRPORT_ID
,
1931 Link
.IFLA_BRPORT_NO
):
1932 sub_attr_pack_layout
.append('H')
1933 sub_attr_payload
.append(sub_attr_value
)
1934 sub_attr_pack_layout
.extend('xx')
1937 elif sub_attr_type
in (Link
.IFLA_BRPORT_COST
,):
1938 sub_attr_pack_layout
.append('L')
1939 sub_attr_payload
.append(sub_attr_value
)
1942 elif sub_attr_type
in (Link
.IFLA_BRPORT_MESSAGE_AGE_TIMER
,
1943 Link
.IFLA_BRPORT_FORWARD_DELAY_TIMER
,
1944 Link
.IFLA_BRPORT_HOLD_TIMER
):
1945 sub_attr_pack_layout
.append('Q')
1946 sub_attr_payload
.append(sub_attr_value
)
1949 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_PROTINFO sub-attribute type %d' % sub_attr_type
)
1951 sub_attr_length
= calcsize(''.join(sub_attr_pack_layout
))
1952 sub_attr_payload
[sub_attr_length_index
] = sub_attr_length
1955 for x
in xrange(self
.pad_bytes_needed(sub_attr_length
)):
1956 sub_attr_pack_layout
.append('x')
1958 # The [1:] is to remove the leading = so that when we do the ''.join() later
1959 # we do not end up with an = in the middle of the pack layout string. There
1960 # will be an = at the beginning via self.HEADER_PACK
1961 sub_attr_pack_layout
= sub_attr_pack_layout
[1:]
1963 # Now extend the ovarall attribute pack_layout/payload to include this sub-attribute
1964 pack_layout
.extend(sub_attr_pack_layout
)
1965 payload
.extend(sub_attr_payload
)
1967 pack_layout
= ''.join(pack_layout
)
1969 # Fill in the length field
1970 length
= calcsize(pack_layout
)
1971 payload
[attr_length_index
] = length
1973 raw
= pack(pack_layout
, *payload
)
1974 raw
= self
.pad(length
, raw
)
1977 def decode(self
, parent_msg
, data
):
1979 value is a dictionary such as:
1981 Link.IFLA_BRPORT_STATE : 3,
1982 Link.IFLA_BRPORT_PRIORITY : 8
1983 Link.IFLA_BRPORT_COST : 2
1987 self
.decode_length_type(data
)
1990 data
= self
.data
[4:]
1993 (sub_attr_length
, sub_attr_type
) = unpack('=HH', data
[:4])
1994 sub_attr_end
= padded_length(sub_attr_length
)
1996 if not sub_attr_length
:
1997 self
.log
.error('parsed a zero length sub-attr')
2000 if self
.family
== AF_BRIDGE
:
2003 if sub_attr_type
in (Link
.IFLA_BRPORT_STATE
,
2004 Link
.IFLA_BRPORT_MODE
,
2005 Link
.IFLA_BRPORT_GUARD
,
2006 Link
.IFLA_BRPORT_PROTECT
,
2007 Link
.IFLA_BRPORT_FAST_LEAVE
,
2008 Link
.IFLA_BRPORT_LEARNING
,
2009 Link
.IFLA_BRPORT_UNICAST_FLOOD
,
2010 Link
.IFLA_BRPORT_PROXYARP
,
2011 Link
.IFLA_BRPORT_LEARNING_SYNC
,
2012 Link
.IFLA_BRPORT_PROXYARP_WIFI
,
2013 Link
.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
,
2014 Link
.IFLA_BRPORT_CONFIG_PENDING
,
2015 Link
.IFLA_BRPORT_FLUSH
,
2016 Link
.IFLA_BRPORT_MULTICAST_ROUTER
,
2017 Link
.IFLA_BRPORT_PEER_LINK
,
2018 Link
.IFLA_BRPORT_DUAL_LINK
,
2019 Link
.IFLA_BRPORT_ARP_SUPPRESS
,
2020 Link
.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
):
2021 self
.value
[sub_attr_type
] = unpack('=B', data
[4])[0]
2024 elif sub_attr_type
in (Link
.IFLA_BRPORT_PRIORITY
,
2025 Link
.IFLA_BRPORT_DESIGNATED_PORT
,
2026 Link
.IFLA_BRPORT_DESIGNATED_COST
,
2027 Link
.IFLA_BRPORT_ID
,
2028 Link
.IFLA_BRPORT_NO
):
2029 self
.value
[sub_attr_type
] = unpack('=H', data
[4:6])[0]
2032 elif sub_attr_type
in (Link
.IFLA_BRPORT_COST
,):
2033 self
.value
[sub_attr_type
] = unpack('=L', data
[4:8])[0]
2036 elif sub_attr_type
in (Link
.IFLA_BRPORT_MESSAGE_AGE_TIMER
,
2037 Link
.IFLA_BRPORT_FORWARD_DELAY_TIMER
,
2038 Link
.IFLA_BRPORT_HOLD_TIMER
):
2039 self
.value
[sub_attr_type
] = unpack('=Q', data
[4:12])[0]
2042 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_PROTINFO sub-attribute type %s (%d), length %d, padded to %d' %
2043 (parent_msg
.get_ifla_brport_string(sub_attr_type
), sub_attr_type
, sub_attr_length
, sub_attr_end
))
2045 data
= data
[sub_attr_end
:]
2047 def dump_lines(self
, dump_buffer
, line_number
, color
):
2048 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
2051 next_sub_attr_line
= 0
2052 sub_attr_line
= True
2054 for x
in xrange(1, self
.attr_end
/4):
2058 if line_number
== next_sub_attr_line
:
2059 sub_attr_line
= True
2062 sub_attr_line
= False
2064 (sub_attr_length
, sub_attr_type
) = unpack('=HH', self
.data
[start
:start
+4])
2065 sub_attr_end
= padded_length(sub_attr_length
)
2067 next_sub_attr_line
= line_number
+ (sub_attr_end
/4)
2069 if sub_attr_end
== sub_attr_length
:
2072 padded_to
= ' padded to %d, ' % sub_attr_end
2074 extra
= 'Nested Attribute - Length %s (%d)%s Type %s (%d) %s' % \
2075 (zfilled_hex(sub_attr_length
, 4), sub_attr_length
,
2077 zfilled_hex(sub_attr_type
, 4), sub_attr_type
,
2078 Link
.ifla_brport_to_string
.get(sub_attr_type
))
2082 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[start
:end
], extra
))
2087 def get_pretty_value(self
, obj
=None):
2089 if obj
and callable(obj
):
2090 return obj(self
.value
)
2094 for (sub_key
, sub_value
) in self
.value
.iteritems():
2095 sub_key_pretty
= "(%2d) %s" % (sub_key
, Link
.ifla_brport_to_string
.get(sub_key
, 'UNKNOWN'))
2096 sub_value_pretty
= sub_value
2097 value_pretty
[sub_key_pretty
] = sub_value_pretty
2103 class NetlinkPacket(object):
2108 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2109 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2111 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2113 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2115 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2116 | Process ID (PID) |
2117 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2120 header_PACK
= 'IHHII'
2121 header_LEN
= calcsize(header_PACK
)
2123 # Netlink packet types
2124 # /usr/include/linux/rtnetlink.h
2126 NLMSG_NOOP
: 'NLMSG_NOOP',
2127 NLMSG_ERROR
: 'NLMSG_ERROR',
2128 NLMSG_DONE
: 'NLMSG_DONE',
2129 NLMSG_OVERRUN
: 'NLMSG_OVERRUN',
2130 RTM_NEWLINK
: 'RTM_NEWLINK',
2131 RTM_DELLINK
: 'RTM_DELLINK',
2132 RTM_GETLINK
: 'RTM_GETLINK',
2133 RTM_SETLINK
: 'RTM_SETLINK',
2134 RTM_NEWADDR
: 'RTM_NEWADDR',
2135 RTM_DELADDR
: 'RTM_DELADDR',
2136 RTM_GETADDR
: 'RTM_GETADDR',
2137 RTM_NEWNEIGH
: 'RTM_NEWNEIGH',
2138 RTM_DELNEIGH
: 'RTM_DELNEIGH',
2139 RTM_GETNEIGH
: 'RTM_GETNEIGH',
2140 RTM_NEWROUTE
: 'RTM_NEWROUTE',
2141 RTM_DELROUTE
: 'RTM_DELROUTE',
2142 RTM_GETROUTE
: 'RTM_GETROUTE',
2143 RTM_NEWQDISC
: 'RTM_NEWQDISC',
2144 RTM_DELQDISC
: 'RTM_DELQDISC',
2145 RTM_GETQDISC
: 'RTM_GETQDISC'
2148 af_family_to_string
= {
2153 def __init__(self
, msgtype
, debug
, owner_logger
=None, use_color
=True):
2154 self
.msgtype
= msgtype
2155 self
.attributes
= {}
2156 self
.dump_buffer
= ['']
2157 self
.line_number
= 1
2160 self
.use_color
= use_color
2164 self
.log
= owner_logger
2169 return self
.get_type_string()
2171 def get_string(self
, to_string
, index
):
2173 Used to do lookups in all of the various FOO_to_string dictionaries
2174 but returns 'UNKNOWN' if the key is bogus
2176 if index
in to_string
:
2177 return to_string
[index
]
2180 def get_type_string(self
, msgtype
=None):
2182 msgtype
= self
.msgtype
2183 return self
.get_string(self
.type_to_string
, msgtype
)
2185 def get_flags_string(self
):
2188 for (flag
, flag_string
) in self
.flag_to_string
.iteritems():
2189 if self
.flags
& flag
:
2190 foo
.append(flag_string
)
2192 return ', '.join(foo
)
2194 def decode_packet(self
, length
, flags
, seq
, pid
, data
):
2195 self
.length
= length
2199 self
.header_data
= data
[0:self
.header_LEN
]
2200 self
.msg_data
= data
[self
.header_LEN
:length
]
2202 self
.decode_netlink_header()
2203 self
.decode_service_header()
2205 # NLMSG_ERROR is special case, it does not have attributes to decode
2206 if self
.msgtype
!= NLMSG_ERROR
:
2207 self
.decode_attributes()
2209 def get_netlink_header_flags_string(self
, msg_type
, flags
):
2212 if flags
& NLM_F_REQUEST
:
2213 foo
.append('NLM_F_REQUEST')
2215 if flags
& NLM_F_MULTI
:
2216 foo
.append('NLM_F_MULTI')
2218 if flags
& NLM_F_ACK
:
2219 foo
.append('NLM_F_ACK')
2221 if flags
& NLM_F_ECHO
:
2222 foo
.append('NLM_F_ECHO')
2224 # Modifiers to GET query
2225 if msg_type
in (RTM_GETLINK
, RTM_GETADDR
, RTM_GETNEIGH
, RTM_GETROUTE
, RTM_GETQDISC
):
2226 if flags
& NLM_F_DUMP
:
2227 foo
.append('NLM_F_DUMP')
2229 if flags
& NLM_F_MATCH
:
2230 foo
.append('NLM_F_MATCH')
2232 if flags
& NLM_F_ROOT
:
2233 foo
.append('NLM_F_ROOT')
2235 if flags
& NLM_F_ATOMIC
:
2236 foo
.append('NLM_F_ATOMIC')
2238 # Modifiers to NEW query
2239 elif msg_type
in (RTM_NEWLINK
, RTM_NEWADDR
, RTM_NEWNEIGH
, RTM_NEWROUTE
, RTM_NEWQDISC
):
2240 if flags
& NLM_F_REPLACE
:
2241 foo
.append('NLM_F_REPLACE')
2243 if flags
& NLM_F_EXCL
:
2244 foo
.append('NLM_F_EXCL')
2246 if flags
& NLM_F_CREATE
:
2247 foo
.append('NLM_F_CREATE')
2249 if flags
& NLM_F_APPEND
:
2250 foo
.append('NLM_F_APPEND')
2252 return ', '.join(foo
)
2254 # When we first RXed the netlink message we had to decode the header to
2255 # determine what type of netlink message we were dealing with. So the
2256 # header has actually already been decoded...what we do here is
2257 # populate the dump_buffer lines with the header content.
2258 def decode_netlink_header(self
):
2263 header_data
= self
.header_data
2265 # Print the netlink header in red
2266 netlink_header_length
= 16
2267 color
= red
if self
.use_color
else None
2268 color_start
= "\033[%dm" % color
if color
else ""
2269 color_end
= "\033[0m" if color
else ""
2270 self
.dump_buffer
.append(" %sNetlink Header%s" % (color_start
, color_end
))
2272 for x
in range(0, netlink_header_length
/4):
2276 if self
.line_number
== 1:
2277 data
= unpack('=L', header_data
[start
:end
])[0]
2278 extra
= "Length %s (%d)" % (zfilled_hex(data
, 8), data
)
2280 elif self
.line_number
== 2:
2281 (data1
, data2
) = unpack('HH', header_data
[start
:end
])
2282 extra
= "Type %s (%d - %s), Flags %s (%s)" % \
2283 (zfilled_hex(data1
, 4), data1
, self
.get_type_string(data1
),
2284 zfilled_hex(data2
, 4), self
.get_netlink_header_flags_string(data1
, data2
))
2286 elif self
.line_number
== 3:
2287 data
= unpack('=L', header_data
[start
:end
])[0]
2288 extra
= "Sequence Number %s (%d)" % (zfilled_hex(data
, 8), data
)
2290 elif self
.line_number
== 4:
2291 data
= unpack('=L', header_data
[start
:end
])[0]
2292 extra
= "Process ID %s (%d)" % (zfilled_hex(data
, 8), data
)
2294 extra
= "Unexpected line number %d" % self
.line_number
2296 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, header_data
[start
:end
], extra
))
2297 self
.line_number
+= 1
2299 def decode_attributes(self
):
2301 Decode the attributes and populate the dump_buffer
2305 self
.dump_buffer
.append(" Attributes")
2306 color
= green
if self
.use_color
else None
2308 data
= self
.msg_data
[self
.LEN
:]
2311 (length
, attr_type
) = unpack('=HH', data
[:4])
2313 # If this is zero we will stay in this loop for forever
2315 self
.log
.error('Length is zero')
2318 if len(data
) < length
:
2319 self
.log
.error("Buffer underrun %d < %d" % (len(data
), length
))
2322 attr
= self
.add_attribute(attr_type
, None)
2324 # Find the end of 'data' for this attribute and decode our section
2325 # of 'data'. attributes are padded for alignment thus the attr_end.
2327 # How the attribute is decoded/unpacked is specific per AttributeXXXX class.
2328 attr_end
= padded_length(length
)
2329 attr
.decode(self
, data
[0:attr_end
])
2332 self
.line_number
= attr
.dump_lines(self
.dump_buffer
, self
.line_number
, color
)
2334 # Alternate back and forth between green and blue
2341 data
= data
[attr_end
:]
2343 def add_attribute(self
, attr_type
, value
):
2344 nested
= True if attr_type
& NLA_F_NESTED
else False
2345 net_byteorder
= True if attr_type
& NLA_F_NET_BYTEORDER
else False
2346 attr_type
= attr_type
& NLA_TYPE_MASK
2348 # Given an attr_type (say RTA_DST) find the type of AttributeXXXX class
2349 # that we will use to store this attribute...AttributeIPAddress in the
2351 if attr_type
in self
.attribute_to_class
:
2352 (attr_string
, attr_class
) = self
.attribute_to_class
[attr_type
]
2355 attribute_to_class is a dictionary where the key is the attr_type, it doesn't
2356 take the family into account. For now we'll handle this as a special case for
2357 MPLS but long term we may need to make key a tuple of the attr_type and family.
2359 if attr_type
== Route
.RTA_DST
and self
.family
== AF_MPLS
:
2360 attr_string
= 'RTA_DST'
2361 attr_class
= AttributeMplsLabel
2364 attr_string
= "UNKNOWN_ATTRIBUTE_%d" % attr_type
2365 attr_class
= AttributeGeneric
2366 self
.log
.debug("Attribute %d is not defined in %s.attribute_to_class, assuming AttributeGeneric" %
2367 (attr_type
, self
.__class
__.__name
__))
2369 attr
= attr_class(attr_type
, attr_string
, self
.family
, self
.log
)
2371 attr
.set_value(value
)
2372 attr
.set_nested(nested
)
2373 attr
.set_net_byteorder(net_byteorder
)
2375 # self.attributes is a dictionary keyed by the attribute type where
2376 # the value is an instance of the corresponding AttributeXXXX class.
2377 self
.attributes
[attr_type
] = attr
2381 def get_attribute_value(self
, attr_type
, default
=None):
2382 if attr_type
not in self
.attributes
:
2385 return self
.attributes
[attr_type
].value
2387 def get_attr_string(self
, attr_type
):
2389 Example: If attr_type is Address.IFA_CACHEINFO return the string 'IFA_CACHEINFO'
2391 if attr_type
in self
.attribute_to_class
:
2392 (attr_string
, attr_class
) = self
.attribute_to_class
[attr_type
]
2394 return str(attr_type
)
2396 def build_message(self
, seq
, pid
):
2401 for attr
in self
.attributes
.itervalues():
2402 attrs
+= attr
.encode()
2404 self
.length
= self
.header_LEN
+ len(self
.body
) + len(attrs
)
2405 self
.header_data
= pack(self
.header_PACK
, self
.length
, self
.msgtype
, self
.flags
, self
.seq
, self
.pid
)
2406 self
.msg_data
= self
.body
+ attrs
2407 self
.message
= self
.header_data
+ self
.msg_data
2410 self
.decode_netlink_header()
2411 self
.decode_service_header()
2412 self
.decode_attributes()
2413 self
.dump("TXed %s, length %d, seq %d, pid %d, flags 0x%x (%s)" %
2414 (self
, self
.length
, self
.seq
, self
.pid
, self
.flags
,
2415 self
.get_netlink_header_flags_string(self
.msgtype
, self
.flags
)))
2417 def pretty_display_dict(self
, dic
, level
):
2418 for k
,v
in dic
.iteritems():
2419 if isinstance(v
, dict):
2420 self
.log
.debug(' '*level
+ str(k
) + ':')
2421 self
.pretty_display_dict(v
, level
+5)
2423 self
.log
.debug(' '*level
+ str(k
) + ': ' + str(v
))
2425 # Print the netlink message in hex. This is only used for debugging.
2426 def dump(self
, desc
=None):
2430 desc
= "RXed %s, length %d, seq %d, pid %d, flags 0x%x" % (self
, self
.length
, self
.seq
, self
.pid
, self
.flags
)
2432 for (attr_type
, attr_obj
) in self
.attributes
.iteritems():
2433 key_string
= "(%2d) %s" % (attr_type
, self
.get_attr_string(attr_type
))
2434 attr_string
[key_string
] = attr_obj
.get_pretty_value()
2437 self
.log
.debug("%s\n%s\n\nAttributes Summary\n%s\n" %
2438 (desc
, '\n'.join(self
.dump_buffer
), pformat(attr_string
)))
2440 # Assume if we are not allowing color output we also don't want embedded
2441 # newline characters in the output. Output each line individually.
2442 self
.log
.debug(desc
)
2443 for line
in self
.dump_buffer
:
2444 self
.log
.debug(line
)
2446 self
.log
.debug("Attributes Summary")
2447 self
.pretty_display_dict(attr_string
, 1)
2450 class Address(NetlinkPacket
):
2454 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2455 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2456 | Family | Length | Flags | Scope |
2457 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2459 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2462 # Address attributes
2463 # /usr/include/linux/if_addr.h
2468 IFA_BROADCAST
= 0x04
2470 IFA_CACHEINFO
= 0x06
2471 IFA_MULTICAST
= 0x07
2474 attribute_to_class
= {
2475 IFA_UNSPEC
: ('IFA_UNSPEC', AttributeGeneric
),
2476 IFA_ADDRESS
: ('IFA_ADDRESS', AttributeIPAddress
),
2477 IFA_LOCAL
: ('IFA_LOCAL', AttributeIPAddress
),
2478 IFA_LABEL
: ('IFA_LABEL', AttributeString
),
2479 IFA_BROADCAST
: ('IFA_BROADCAST', AttributeIPAddress
),
2480 IFA_ANYCAST
: ('IFA_ANYCAST', AttributeIPAddress
),
2481 IFA_CACHEINFO
: ('IFA_CACHEINFO', AttributeGeneric
),
2482 IFA_MULTICAST
: ('IFA_MULTICAST', AttributeIPAddress
),
2483 IFA_FLAGS
: ('IFA_FLAGS', AttributeGeneric
)
2487 # /usr/include/linux/if_addr.h
2488 IFA_F_SECONDARY
= 0x01
2490 IFA_F_OPTIMISTIC
= 0x04
2491 IFA_F_DADFAILED
= 0x08
2492 IFA_F_HOMEADDRESS
= 0x10
2493 IFA_F_DEPRECATED
= 0x20
2494 IFA_F_TENTATIVE
= 0x40
2495 IFA_F_PERMANENT
= 0x80
2498 IFA_F_SECONDARY
: 'IFA_F_SECONDARY',
2499 IFA_F_NODAD
: 'IFA_F_NODAD',
2500 IFA_F_OPTIMISTIC
: 'IFA_F_OPTIMISTIC',
2501 IFA_F_DADFAILED
: 'IFA_F_DADFAILED',
2502 IFA_F_HOMEADDRESS
: 'IFA_F_HOMEADDRESS',
2503 IFA_F_DEPRECATED
: 'IFA_F_DEPRECATED',
2504 IFA_F_TENTATIVE
: 'IFA_F_TENTATIVE',
2505 IFA_F_PERMANENT
: 'IFA_F_PERMANENT'
2508 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
2509 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
2511 self
.LEN
= calcsize(self
.PACK
)
2513 def decode_service_header(self
):
2515 # Nothing to do if the message did not contain a service header
2516 if self
.length
== self
.header_LEN
:
2519 (self
.family
, self
.prefixlen
, self
.flags
, self
.scope
,
2521 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
2524 color
= yellow
if self
.use_color
else None
2525 color_start
= "\033[%dm" % color
if color
else ""
2526 color_end
= "\033[0m" if color
else ""
2527 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
2529 for x
in range(0, self
.LEN
/4):
2530 if self
.line_number
== 5:
2531 extra
= "Family %s (%d), Length %s (%d), Flags %s, Scope %s (%d)" % \
2532 (zfilled_hex(self
.family
, 2), self
.family
,
2533 zfilled_hex(self
.prefixlen
, 2), self
.prefixlen
,
2534 zfilled_hex(self
.flags
, 2),
2535 zfilled_hex(self
.scope
, 2), self
.scope
)
2536 elif self
.line_number
== 6:
2537 extra
= "Interface Index %s (%d)" % (zfilled_hex(self
.ifindex
, 8), self
.ifindex
)
2539 extra
= "Unexpected line number %d" % self
.line_number
2543 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
2544 self
.line_number
+= 1
2547 class Error(NetlinkPacket
):
2550 # /include/netlink/errno.h
2561 NLE_OPNOTSUPP
= 0x0A
2562 NLE_AF_NOSUPPORT
= 0x0B
2563 NLE_OBJ_NOTFOUND
= 0x0C
2565 NLE_MISSING_ATTR
= 0x0E
2566 NLE_AF_MISMATCH
= 0x0F
2567 NLE_SEQ_MISMATCH
= 0x10
2568 NLE_MSG_OVERFLOW
= 0x11
2569 NLE_MSG_TRUNC
= 0x12
2571 NLE_SRCRT_NOSUPPORT
= 0x14
2572 NLE_MSG_TOOSHORT
= 0x15
2573 NLE_MSGTYPE_NOSUPPORT
= 0x16
2574 NLE_OBJ_MISMATCH
= 0x17
2577 NLE_PROTO_MISMATCH
= 0x1A
2580 NLE_PKTLOC_FILE
= 0x1D
2581 NLE_PARSE_ERR
= 0x1E
2583 NLE_IMMUTABLE
= 0x20
2584 NLE_DUMP_INTR
= 0x21
2587 NLE_SUCCESS
: 'NLE_SUCCESS',
2588 NLE_FAILURE
: 'NLE_FAILURE',
2589 NLE_INTR
: 'NLE_INTR',
2590 NLE_BAD_SOCK
: 'NLE_BAD_SOCK',
2591 NLE_AGAIN
: 'NLE_AGAIN',
2592 NLE_NOMEM
: 'NLE_NOMEM',
2593 NLE_EXIST
: 'NLE_EXIST',
2594 NLE_INVAL
: 'NLE_INVAL',
2595 NLE_RANGE
: 'NLE_RANGE',
2596 NLE_MSGSIZE
: 'NLE_MSGSIZE',
2597 NLE_OPNOTSUPP
: 'NLE_OPNOTSUPP',
2598 NLE_AF_NOSUPPORT
: 'NLE_AF_NOSUPPORT',
2599 NLE_OBJ_NOTFOUND
: 'NLE_OBJ_NOTFOUND',
2600 NLE_NOATTR
: 'NLE_NOATTR',
2601 NLE_MISSING_ATTR
: 'NLE_MISSING_ATTR',
2602 NLE_AF_MISMATCH
: 'NLE_AF_MISMATCH',
2603 NLE_SEQ_MISMATCH
: 'NLE_SEQ_MISMATCH',
2604 NLE_MSG_OVERFLOW
: 'NLE_MSG_OVERFLOW',
2605 NLE_MSG_TRUNC
: 'NLE_MSG_TRUNC',
2606 NLE_NOADDR
: 'NLE_NOADDR',
2607 NLE_SRCRT_NOSUPPORT
: 'NLE_SRCRT_NOSUPPORT',
2608 NLE_MSG_TOOSHORT
: 'NLE_MSG_TOOSHORT',
2609 NLE_MSGTYPE_NOSUPPORT
: 'NLE_MSGTYPE_NOSUPPORT',
2610 NLE_OBJ_MISMATCH
: 'NLE_OBJ_MISMATCH',
2611 NLE_NOCACHE
: 'NLE_NOCACHE',
2612 NLE_BUSY
: 'NLE_BUSY',
2613 NLE_PROTO_MISMATCH
: 'NLE_PROTO_MISMATCH',
2614 NLE_NOACCESS
: 'NLE_NOACCESS',
2615 NLE_PERM
: 'NLE_PERM',
2616 NLE_PKTLOC_FILE
: 'NLE_PKTLOC_FILE',
2617 NLE_PARSE_ERR
: 'NLE_PARSE_ERR',
2618 NLE_NODEV
: 'NLE_NODEV',
2619 NLE_IMMUTABLE
: 'NLE_IMMUTABLE',
2620 NLE_DUMP_INTR
: 'NLE_DUMP_INTR'
2623 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
2624 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
2625 self
.PACK
= '=iLHHLL'
2626 self
.LEN
= calcsize(self
.PACK
)
2628 def decode_service_header(self
):
2630 # Nothing to do if the message did not contain a service header
2631 if self
.length
== self
.header_LEN
:
2634 (self
.negative_errno
, self
.bad_msg_len
, self
.bad_msg_type
,
2635 self
.bad_msg_flag
, self
.bad_msg_seq
, self
.bad_msg_pid
) =\
2636 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
2639 color
= yellow
if self
.use_color
else None
2640 color_start
= "\033[%dm" % color
if color
else ""
2641 color_end
= "\033[0m" if color
else ""
2642 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
2644 for x
in range(0, self
.LEN
/4):
2646 if self
.line_number
== 5:
2647 extra
= "Error Number %s is %s" % (self
.negative_errno
, self
.error_to_string
.get(abs(self
.negative_errno
)))
2648 # zfilled_hex(self.negative_errno, 2)
2650 elif self
.line_number
== 6:
2651 extra
= "Length %s (%d)" % (zfilled_hex(self
.bad_msg_len
, 8), self
.bad_msg_len
)
2653 elif self
.line_number
== 7:
2654 extra
= "Type %s (%d - %s), Flags %s (%s)" % \
2655 (zfilled_hex(self
.bad_msg_type
, 4), self
.bad_msg_type
, self
.get_type_string(self
.bad_msg_type
),
2656 zfilled_hex(self
.bad_msg_flag
, 4), self
.get_netlink_header_flags_string(self
.bad_msg_type
, self
.bad_msg_flag
))
2658 elif self
.line_number
== 8:
2659 extra
= "Sequence Number %s (%d)" % (zfilled_hex(self
.bad_msg_seq
, 8), self
.bad_msg_seq
)
2661 elif self
.line_number
== 9:
2662 extra
= "Process ID %s (%d)" % (zfilled_hex(self
.bad_msg_pid
, 8), self
.bad_msg_pid
)
2665 extra
= "Unexpected line number %d" % self
.line_number
2669 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
2670 self
.line_number
+= 1
2673 class Link(NetlinkPacket
):
2678 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2679 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2680 | Family | Reserved | Device Type |
2681 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2683 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2685 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2687 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2691 # /usr/include/linux/if_link.h
2711 IFLA_NET_NS_PID
= 19
2714 IFLA_VFINFO_LIST
= 22
2722 IFLA_PROMISCUITY
= 30
2723 IFLA_NUM_TX_QUEUES
= 31
2724 IFLA_NUM_RX_QUEUES
= 32
2726 IFLA_PHYS_PORT_ID
= 34
2727 IFLA_CARRIER_CHANGES
= 35
2728 IFLA_PHYS_SWITCH_ID
= 36
2729 IFLA_LINK_NETNSID
= 37
2730 IFLA_PHYS_PORT_NAME
= 38
2731 IFLA_PROTO_DOWN
= 39
2732 IFLA_GSO_MAX_SEGS
= 40
2733 IFLA_GSO_MAX_SIZE
= 41
2735 attribute_to_class
= {
2736 IFLA_UNSPEC
: ('IFLA_UNSPEC', AttributeGeneric
),
2737 IFLA_ADDRESS
: ('IFLA_ADDRESS', AttributeMACAddress
),
2738 IFLA_BROADCAST
: ('IFLA_BROADCAST', AttributeMACAddress
),
2739 IFLA_IFNAME
: ('IFLA_IFNAME', AttributeStringInterfaceName
),
2740 IFLA_MTU
: ('IFLA_MTU', AttributeFourByteValue
),
2741 IFLA_LINK
: ('IFLA_LINK', AttributeFourByteValue
),
2742 IFLA_QDISC
: ('IFLA_QDISC', AttributeString
),
2743 IFLA_STATS
: ('IFLA_STATS', AttributeGeneric
),
2744 IFLA_COST
: ('IFLA_COST', AttributeGeneric
),
2745 IFLA_PRIORITY
: ('IFLA_PRIORITY', AttributeGeneric
),
2746 IFLA_MASTER
: ('IFLA_MASTER', AttributeFourByteValue
),
2747 IFLA_WIRELESS
: ('IFLA_WIRELESS', AttributeGeneric
),
2748 IFLA_PROTINFO
: ('IFLA_PROTINFO', AttributeIFLA_PROTINFO
),
2749 IFLA_TXQLEN
: ('IFLA_TXQLEN', AttributeFourByteValue
),
2750 IFLA_MAP
: ('IFLA_MAP', AttributeGeneric
),
2751 IFLA_WEIGHT
: ('IFLA_WEIGHT', AttributeGeneric
),
2752 IFLA_OPERSTATE
: ('IFLA_OPERSTATE', AttributeOneByteValue
),
2753 IFLA_LINKMODE
: ('IFLA_LINKMODE', AttributeOneByteValue
),
2754 IFLA_LINKINFO
: ('IFLA_LINKINFO', AttributeIFLA_LINKINFO
),
2755 IFLA_NET_NS_PID
: ('IFLA_NET_NS_PID', AttributeGeneric
),
2756 IFLA_IFALIAS
: ('IFLA_IFALIAS', AttributeGeneric
),
2757 IFLA_NUM_VF
: ('IFLA_NUM_VF', AttributeGeneric
),
2758 IFLA_VFINFO_LIST
: ('IFLA_VFINFO_LIST', AttributeGeneric
),
2759 IFLA_STATS64
: ('IFLA_STATS64', AttributeGeneric
),
2760 IFLA_VF_PORTS
: ('IFLA_VF_PORTS', AttributeGeneric
),
2761 IFLA_PORT_SELF
: ('IFLA_PORT_SELF', AttributeGeneric
),
2762 IFLA_AF_SPEC
: ('IFLA_AF_SPEC', AttributeIFLA_AF_SPEC
),
2763 IFLA_GROUP
: ('IFLA_GROUP', AttributeFourByteValue
),
2764 IFLA_NET_NS_FD
: ('IFLA_NET_NS_FD', AttributeGeneric
),
2765 IFLA_EXT_MASK
: ('IFLA_EXT_MASK', AttributeFourByteValue
),
2766 IFLA_PROMISCUITY
: ('IFLA_PROMISCUITY', AttributeGeneric
),
2767 IFLA_NUM_TX_QUEUES
: ('IFLA_NUM_TX_QUEUES', AttributeGeneric
),
2768 IFLA_NUM_RX_QUEUES
: ('IFLA_NUM_RX_QUEUES', AttributeGeneric
),
2769 IFLA_CARRIER
: ('IFLA_CARRIER', AttributeGeneric
),
2770 IFLA_PHYS_PORT_ID
: ('IFLA_PHYS_PORT_ID', AttributeGeneric
),
2771 IFLA_CARRIER_CHANGES
: ('IFLA_CARRIER_CHANGES', AttributeGeneric
),
2772 IFLA_PHYS_SWITCH_ID
: ('IFLA_PHYS_SWITCH_ID', AttributeGeneric
),
2773 IFLA_LINK_NETNSID
: ('IFLA_LINK_NETNSID', AttributeGeneric
),
2774 IFLA_PHYS_PORT_NAME
: ('IFLA_PHYS_PORT_NAME', AttributeGeneric
),
2775 IFLA_PROTO_DOWN
: ('IFLA_PROTO_DOWN', AttributeOneByteValue
),
2776 IFLA_GSO_MAX_SEGS
: ('IFLA_GSO_MAX_SEGS', AttributeFourByteValue
),
2777 IFLA_GSO_MAX_SIZE
: ('IFLA_GSO_MAX_SIZE', AttributeFourByteValue
)
2781 # /usr/include/linux/if.h
2782 IFF_UP
= 0x0001 # Interface is administratively up.
2783 IFF_BROADCAST
= 0x0002 # Valid broadcast address set.
2784 IFF_DEBUG
= 0x0004 # Internal debugging flag.
2785 IFF_LOOPBACK
= 0x0008 # Interface is a loopback interface.
2786 IFF_POINTOPOINT
= 0x0010 # Interface is a point-to-point link.
2787 IFF_NOTRAILERS
= 0x0020 # Avoid use of trailers.
2788 IFF_RUNNING
= 0x0040 # Interface is operationally up.
2789 IFF_NOARP
= 0x0080 # No ARP protocol needed for this interface.
2790 IFF_PROMISC
= 0x0100 # Interface is in promiscuous mode.
2791 IFF_ALLMULTI
= 0x0200 # Receive all multicast packets.
2792 IFF_MASTER
= 0x0400 # Master of a load balancing bundle.
2793 IFF_SLAVE
= 0x0800 # Slave of a load balancing bundle.
2794 IFF_MULTICAST
= 0x1000 # Supports multicast.
2795 IFF_PORTSEL
= 0x2000 # Is able to select media type via ifmap.
2796 IFF_AUTOMEDIA
= 0x4000 # Auto media selection active.
2797 IFF_DYNAMIC
= 0x8000 # Interface was dynamically created.
2798 IFF_LOWER_UP
= 0x10000 # driver signals L1 up
2799 IFF_DORMANT
= 0x20000 # driver signals dormant
2800 IFF_ECHO
= 0x40000 # echo sent packet
2801 IFF_PROTO_DOWN
= 0x1000000 # protocol is down on the interface
2805 IFF_BROADCAST
: 'IFF_BROADCAST',
2806 IFF_DEBUG
: 'IFF_DEBUG',
2807 IFF_LOOPBACK
: 'IFF_LOOPBACK',
2808 IFF_POINTOPOINT
: 'IFF_POINTOPOINT',
2809 IFF_NOTRAILERS
: 'IFF_NOTRAILERS',
2810 IFF_RUNNING
: 'IFF_RUNNING',
2811 IFF_NOARP
: 'IFF_NOARP',
2812 IFF_PROMISC
: 'IFF_PROMISC',
2813 IFF_ALLMULTI
: 'IFF_ALLMULTI',
2814 IFF_MASTER
: 'IFF_MASTER',
2815 IFF_SLAVE
: 'IFF_SLAVE',
2816 IFF_MULTICAST
: 'IFF_MULTICAST',
2817 IFF_PORTSEL
: 'IFF_PORTSEL',
2818 IFF_AUTOMEDIA
: 'IFF_AUTOMEDIA',
2819 IFF_DYNAMIC
: 'IFF_DYNAMIC',
2820 IFF_LOWER_UP
: 'IFF_LOWER_UP',
2821 IFF_DORMANT
: 'IFF_DORMANT',
2822 IFF_ECHO
: 'IFF_ECHO',
2823 IFF_PROTO_DOWN
: 'IFF_PROTO_DOWN'
2826 # RFC 2863 operational status
2828 IF_OPER_NOTPRESENT
= 1
2830 IF_OPER_LOWERLAYERDOWN
= 3
2836 IF_OPER_UNKNOWN
: 'IF_OPER_UNKNOWN',
2837 IF_OPER_NOTPRESENT
: 'IF_OPER_NOTPRESENT',
2838 IF_OPER_DOWN
: 'IF_OPER_DOWN',
2839 IF_OPER_LOWERLAYERDOWN
: 'IF_OPER_LOWERLAYERDOWN',
2840 IF_OPER_TESTING
: 'IF_OPER_TESTING',
2841 IF_OPER_DORMANT
: 'IF_OPER_DORMANT',
2842 IF_OPER_UP
: 'IF_OPER_UP'
2846 # /usr/include/linux/if_arp.h
2847 # ARP protocol HARDWARE identifiers
2848 ARPHRD_NETROM
= 0 # from KA9Q: NET/ROM pseudo
2849 ARPHRD_ETHER
= 1 # Ethernet 10Mbps
2850 ARPHRD_EETHER
= 2 # Experimental Ethernet
2851 ARPHRD_AX25
= 3 # AX.25 Level 2
2852 ARPHRD_PRONET
= 4 # PROnet token ring
2853 ARPHRD_CHAOS
= 5 # Chaosnet
2854 ARPHRD_IEEE802
= 6 # IEEE 802.2 Ethernet/TR/TB
2855 ARPHRD_ARCNET
= 7 # ARCnet
2856 ARPHRD_APPLETLK
= 8 # APPLEtalk
2857 ARPHRD_DLCI
= 15 # Frame Relay DLCI
2858 ARPHRD_ATM
= 19 # ATM
2859 ARPHRD_METRICOM
= 23 # Metricom STRIP (new IANA id)
2860 ARPHRD_IEEE1394
= 24 # IEEE 1394 IPv4 - RFC 2734
2861 ARPHRD_EUI64
= 27 # EUI-64
2862 ARPHRD_INFINIBAND
= 32 # InfiniBand
2863 # Dummy types for non ARP hardware
2868 ARPHRD_RSRVD
= 260 # Notional KISS type
2871 ARPHRD_X25
= 271 # CCITT X.25
2872 ARPHRD_HWX25
= 272 # Boards with X.25 in firmware
2873 ARPHRD_CAN
= 280 # Controller Area Network
2875 ARPHRD_CISCO
= 513 # Cisco HDLC
2876 ARPHRD_HDLC
= ARPHRD_CISCO
2877 ARPHRD_LAPB
= 516 # LAPB
2878 ARPHRD_DDCMP
= 517 # Digital's DDCMP protocol
2879 ARPHRD_RAWHDLC
= 518 # Raw HDLC
2880 ARPHRD_TUNNEL
= 768 # IPIP tunnel
2881 ARPHRD_TUNNEL6
= 769 # IP6IP6 tunnel
2882 ARPHRD_FRAD
= 770 # Frame Relay Access Device
2883 ARPHRD_SKIP
= 771 # SKIP vif
2884 ARPHRD_LOOPBACK
= 772 # Loopback device
2885 ARPHRD_LOCALTLK
= 773 # Localtalk device
2886 ARPHRD_FDDI
= 774 # Fiber Distributed Data Interface
2887 ARPHRD_BIF
= 775 # AP1000 BIF
2888 ARPHRD_SIT
= 776 # sit0 device - IPv6-in-IPv4
2889 ARPHRD_IPDDP
= 777 # IP over DDP tunneller
2890 ARPHRD_IPGRE
= 778 # GRE over IP
2891 ARPHRD_PIMREG
= 779 # PIMSM register interface
2892 ARPHRD_HIPPI
= 780 # High Performance Parallel Interface
2893 ARPHRD_ASH
= 781 # Nexus 64Mbps Ash
2894 ARPHRD_ECONET
= 782 # Acorn Econet
2895 ARPHRD_IRDA
= 783 # Linux-IrDA
2896 ARPHRD_FCPP
= 784 # Point to point fibrechannel
2897 ARPHRD_FCAL
= 785 # Fibrechannel arbitrated loop
2898 ARPHRD_FCPL
= 786 # Fibrechannel public loop
2899 ARPHRD_FCFABRIC
= 787 # Fibrechannel fabric
2900 # 787->799 reserved for fibrechannel media types
2901 ARPHRD_IEEE802_TR
= 800 # Magic type ident for TR
2902 ARPHRD_IEEE80211
= 801 # IEEE 802.11
2903 ARPHRD_IEEE80211_PRISM
= 802 # IEEE 802.11 + Prism2 header
2904 ARPHRD_IEEE80211_RADIOTAP
= 803 # IEEE 802.11 + radiotap header
2905 ARPHRD_IEEE802154
= 804
2906 ARPHRD_PHONET
= 820 # PhoNet media type
2907 ARPHRD_PHONET_PIPE
= 821 # PhoNet pipe header
2908 ARPHRD_CAIF
= 822 # CAIF media type
2909 ARPHRD_VOID
= 0xFFFF # Void type, nothing is known
2910 ARPHRD_NONE
= 0xFFFE # zero header length
2912 link_type_to_string
= {
2913 ARPHRD_NETROM
: 'ARPHRD_NETROM',
2914 ARPHRD_ETHER
: 'ARPHRD_ETHER',
2915 ARPHRD_EETHER
: 'ARPHRD_EETHER',
2916 ARPHRD_AX25
: 'ARPHRD_AX25',
2917 ARPHRD_PRONET
: 'ARPHRD_PRONET',
2918 ARPHRD_CHAOS
: 'ARPHRD_CHAOS',
2919 ARPHRD_IEEE802
: 'ARPHRD_IEEE802',
2920 ARPHRD_ARCNET
: 'ARPHRD_ARCNET',
2921 ARPHRD_APPLETLK
: 'ARPHRD_APPLETLK',
2922 ARPHRD_DLCI
: 'ARPHRD_DLCI',
2923 ARPHRD_ATM
: 'ARPHRD_ATM',
2924 ARPHRD_METRICOM
: 'ARPHRD_METRICOM',
2925 ARPHRD_IEEE1394
: 'ARPHRD_IEEE1394',
2926 ARPHRD_EUI64
: 'ARPHRD_EUI64',
2927 ARPHRD_INFINIBAND
: 'ARPHRD_INFINIBAND',
2928 ARPHRD_SLIP
: 'ARPHRD_SLIP',
2929 ARPHRD_CSLIP
: 'ARPHRD_CSLIP',
2930 ARPHRD_SLIP6
: 'ARPHRD_SLIP6',
2931 ARPHRD_CSLIP6
: 'ARPHRD_CSLIP6',
2932 ARPHRD_RSRVD
: 'ARPHRD_RSRVD',
2933 ARPHRD_ADAPT
: 'ARPHRD_ADAPT',
2934 ARPHRD_ROSE
: 'ARPHRD_ROSE',
2935 ARPHRD_X25
: 'ARPHRD_X25',
2936 ARPHRD_HWX25
: 'ARPHRD_HWX25',
2937 ARPHRD_CAN
: 'ARPHRD_CAN',
2938 ARPHRD_PPP
: 'ARPHRD_PPP',
2939 ARPHRD_CISCO
: 'ARPHRD_CISCO',
2940 ARPHRD_HDLC
: 'ARPHRD_HDLC',
2941 ARPHRD_LAPB
: 'ARPHRD_LAPB',
2942 ARPHRD_DDCMP
: 'ARPHRD_DDCMP',
2943 ARPHRD_RAWHDLC
: 'ARPHRD_RAWHDLC',
2944 ARPHRD_TUNNEL
: 'ARPHRD_TUNNEL',
2945 ARPHRD_TUNNEL6
: 'ARPHRD_TUNNEL6',
2946 ARPHRD_FRAD
: 'ARPHRD_FRAD',
2947 ARPHRD_SKIP
: 'ARPHRD_SKIP',
2948 ARPHRD_LOOPBACK
: 'ARPHRD_LOOPBACK',
2949 ARPHRD_LOCALTLK
: 'ARPHRD_LOCALTLK',
2950 ARPHRD_FDDI
: 'ARPHRD_FDDI',
2951 ARPHRD_BIF
: 'ARPHRD_BIF',
2952 ARPHRD_SIT
: 'ARPHRD_SIT',
2953 ARPHRD_IPDDP
: 'ARPHRD_IPDDP',
2954 ARPHRD_IPGRE
: 'ARPHRD_IPGRE',
2955 ARPHRD_PIMREG
: 'ARPHRD_PIMREG',
2956 ARPHRD_HIPPI
: 'ARPHRD_HIPPI',
2957 ARPHRD_ASH
: 'ARPHRD_ASH',
2958 ARPHRD_ECONET
: 'ARPHRD_ECONET',
2959 ARPHRD_IRDA
: 'ARPHRD_IRDA',
2960 ARPHRD_FCPP
: 'ARPHRD_FCPP',
2961 ARPHRD_FCAL
: 'ARPHRD_FCAL',
2962 ARPHRD_FCPL
: 'ARPHRD_FCPL',
2963 ARPHRD_FCFABRIC
: 'ARPHRD_FCFABRIC',
2964 ARPHRD_IEEE802_TR
: 'ARPHRD_IEEE802_TR',
2965 ARPHRD_IEEE80211
: 'ARPHRD_IEEE80211',
2966 ARPHRD_IEEE80211_PRISM
: 'ARPHRD_IEEE80211_PRISM',
2967 ARPHRD_IEEE80211_RADIOTAP
: 'ARPHRD_IEEE80211_RADIOTAP',
2968 ARPHRD_IEEE802154
: 'ARPHRD_IEEE802154',
2969 ARPHRD_PHONET
: 'ARPHRD_PHONET',
2970 ARPHRD_PHONET_PIPE
: 'ARPHRD_PHONET_PIPE',
2971 ARPHRD_CAIF
: 'ARPHRD_CAIF',
2972 ARPHRD_VOID
: 'ARPHRD_VOID',
2973 ARPHRD_NONE
: 'ARPHRD_NONE'
2976 # =========================================
2977 # IFLA_LINKINFO attributes
2978 # =========================================
2979 IFLA_INFO_UNSPEC
= 0
2982 IFLA_INFO_XSTATS
= 3
2983 IFLA_INFO_SLAVE_KIND
= 4
2984 IFLA_INFO_SLAVE_DATA
= 5
2987 ifla_info_to_string
= {
2988 IFLA_INFO_UNSPEC
: 'IFLA_INFO_UNSPEC',
2989 IFLA_INFO_KIND
: 'IFLA_INFO_KIND',
2990 IFLA_INFO_DATA
: 'IFLA_INFO_DATA',
2991 IFLA_INFO_XSTATS
: 'IFLA_INFO_XSTATS',
2992 IFLA_INFO_SLAVE_KIND
: 'IFLA_INFO_SLAVE_KIND',
2993 IFLA_INFO_SLAVE_DATA
: 'IFLA_INFO_SLAVE_DATA',
2994 IFLA_INFO_MAX
: 'IFLA_INFO_MAX'
2997 # =========================================
2998 # IFLA_INFO_DATA attributes for vlan
2999 # =========================================
3000 IFLA_VLAN_UNSPEC
= 0
3003 IFLA_VLAN_EGRESS_QOS
= 3
3004 IFLA_VLAN_INGRESS_QOS
= 4
3005 IFLA_VLAN_PROTOCOL
= 5
3007 ifla_vlan_to_string
= {
3008 IFLA_VLAN_UNSPEC
: 'IFLA_VLAN_UNSPEC',
3009 IFLA_VLAN_ID
: 'IFLA_VLAN_ID',
3010 IFLA_VLAN_FLAGS
: 'IFLA_VLAN_FLAGS',
3011 IFLA_VLAN_EGRESS_QOS
: 'IFLA_VLAN_EGRESS_QOS',
3012 IFLA_VLAN_INGRESS_QOS
: 'IFLA_VLAN_INGRESS_QOS',
3013 IFLA_VLAN_PROTOCOL
: 'IFLA_VLAN_PROTOCOL'
3016 ifla_vlan_protocol_dict
= {
3029 # =========================================
3030 # IFLA_INFO_DATA attributes for macvlan
3031 # =========================================
3032 IFLA_MACVLAN_UNSPEC
= 0
3033 IFLA_MACVLAN_MODE
= 1
3035 ifla_macvlan_to_string
= {
3036 IFLA_MACVLAN_UNSPEC
: 'IFLA_MACVLAN_UNSPEC',
3037 IFLA_MACVLAN_MODE
: 'IFLA_MACVLAN_MODE'
3041 MACVLAN_MODE_PRIVATE
= 1
3042 MACVLAN_MODE_VEPA
= 2
3043 MACVLAN_MODE_BRIDGE
= 3
3044 MACVLAN_MODE_PASSTHRU
= 4
3046 macvlan_mode_to_string
= {
3047 MACVLAN_MODE_PRIVATE
: 'MACVLAN_MODE_PRIVATE',
3048 MACVLAN_MODE_VEPA
: 'MACVLAN_MODE_VEPA',
3049 MACVLAN_MODE_BRIDGE
: 'MACVLAN_MODE_BRIDGE',
3050 MACVLAN_MODE_PASSTHRU
: 'MACVLAN_MODE_PASSTHRU'
3053 # =========================================
3054 # IFLA_INFO_DATA attributes for vxlan
3055 # =========================================
3056 IFLA_VXLAN_UNSPEC
= 0
3058 IFLA_VXLAN_GROUP
= 2
3060 IFLA_VXLAN_LOCAL
= 4
3063 IFLA_VXLAN_LEARNING
= 7
3064 IFLA_VXLAN_AGEING
= 8
3065 IFLA_VXLAN_LIMIT
= 9
3066 IFLA_VXLAN_PORT_RANGE
= 10
3067 IFLA_VXLAN_PROXY
= 11
3069 IFLA_VXLAN_L2MISS
= 13
3070 IFLA_VXLAN_L3MISS
= 14
3071 IFLA_VXLAN_PORT
= 15
3072 IFLA_VXLAN_GROUP6
= 16
3073 IFLA_VXLAN_LOCAL6
= 17
3074 IFLA_VXLAN_UDP_CSUM
= 18
3075 IFLA_VXLAN_UDP_ZERO_CSUM6_TX
= 19
3076 IFLA_VXLAN_UDP_ZERO_CSUM6_RX
= 20
3077 IFLA_VXLAN_REMCSUM_TX
= 21
3078 IFLA_VXLAN_REMCSUM_RX
= 22
3080 IFLA_VXLAN_REMCSUM_NOPARTIAL
= 24
3081 IFLA_VXLAN_COLLECT_METADATA
= 25
3082 IFLA_VXLAN_REPLICATION_NODE
= 253
3083 IFLA_VXLAN_REPLICATION_TYPE
= 254
3085 ifla_vxlan_to_string
= {
3086 IFLA_VXLAN_UNSPEC
: 'IFLA_VXLAN_UNSPEC',
3087 IFLA_VXLAN_ID
: 'IFLA_VXLAN_ID',
3088 IFLA_VXLAN_GROUP
: 'IFLA_VXLAN_GROUP',
3089 IFLA_VXLAN_LINK
: 'IFLA_VXLAN_LINK',
3090 IFLA_VXLAN_LOCAL
: 'IFLA_VXLAN_LOCAL',
3091 IFLA_VXLAN_TTL
: 'IFLA_VXLAN_TTL',
3092 IFLA_VXLAN_TOS
: 'IFLA_VXLAN_TOS',
3093 IFLA_VXLAN_LEARNING
: 'IFLA_VXLAN_LEARNING',
3094 IFLA_VXLAN_AGEING
: 'IFLA_VXLAN_AGEING',
3095 IFLA_VXLAN_LIMIT
: 'IFLA_VXLAN_LIMIT',
3096 IFLA_VXLAN_PORT_RANGE
: 'IFLA_VXLAN_PORT_RANGE',
3097 IFLA_VXLAN_PROXY
: 'IFLA_VXLAN_PROXY',
3098 IFLA_VXLAN_RSC
: 'IFLA_VXLAN_RSC',
3099 IFLA_VXLAN_L2MISS
: 'IFLA_VXLAN_L2MISS',
3100 IFLA_VXLAN_L3MISS
: 'IFLA_VXLAN_L3MISS',
3101 IFLA_VXLAN_PORT
: 'IFLA_VXLAN_PORT',
3102 IFLA_VXLAN_GROUP6
: 'IFLA_VXLAN_GROUP6',
3103 IFLA_VXLAN_LOCAL6
: 'IFLA_VXLAN_LOCAL6',
3104 IFLA_VXLAN_UDP_CSUM
: 'IFLA_VXLAN_UDP_CSUM',
3105 IFLA_VXLAN_UDP_ZERO_CSUM6_TX
: 'IFLA_VXLAN_UDP_ZERO_CSUM6_TX',
3106 IFLA_VXLAN_UDP_ZERO_CSUM6_RX
: 'IFLA_VXLAN_UDP_ZERO_CSUM6_RX',
3107 IFLA_VXLAN_REMCSUM_TX
: 'IFLA_VXLAN_REMCSUM_TX',
3108 IFLA_VXLAN_REMCSUM_RX
: 'IFLA_VXLAN_REMCSUM_RX',
3109 IFLA_VXLAN_GBP
: 'IFLA_VXLAN_GBP',
3110 IFLA_VXLAN_REMCSUM_NOPARTIAL
: 'IFLA_VXLAN_REMCSUM_NOPARTIAL',
3111 IFLA_VXLAN_COLLECT_METADATA
: 'IFLA_VXLAN_COLLECT_METADATA',
3112 IFLA_VXLAN_REPLICATION_NODE
: 'IFLA_VXLAN_REPLICATION_NODE',
3113 IFLA_VXLAN_REPLICATION_TYPE
: 'IFLA_VXLAN_REPLICATION_TYPE'
3116 # =========================================
3117 # IFLA_INFO_DATA attributes for bonds
3118 # =========================================
3119 IFLA_BOND_UNSPEC
= 0
3121 IFLA_BOND_ACTIVE_SLAVE
= 2
3122 IFLA_BOND_MIIMON
= 3
3123 IFLA_BOND_UPDELAY
= 4
3124 IFLA_BOND_DOWNDELAY
= 5
3125 IFLA_BOND_USE_CARRIER
= 6
3126 IFLA_BOND_ARP_INTERVAL
= 7
3127 IFLA_BOND_ARP_IP_TARGET
= 8
3128 IFLA_BOND_ARP_VALIDATE
= 9
3129 IFLA_BOND_ARP_ALL_TARGETS
= 10
3130 IFLA_BOND_PRIMARY
= 11
3131 IFLA_BOND_PRIMARY_RESELECT
= 12
3132 IFLA_BOND_FAIL_OVER_MAC
= 13
3133 IFLA_BOND_XMIT_HASH_POLICY
= 14
3134 IFLA_BOND_RESEND_IGMP
= 15
3135 IFLA_BOND_NUM_PEER_NOTIF
= 16
3136 IFLA_BOND_ALL_SLAVES_ACTIVE
= 17
3137 IFLA_BOND_MIN_LINKS
= 18
3138 IFLA_BOND_LP_INTERVAL
= 19
3139 IFLA_BOND_PACKETS_PER_SLAVE
= 20
3140 IFLA_BOND_AD_LACP_RATE
= 21
3141 IFLA_BOND_AD_SELECT
= 22
3142 IFLA_BOND_AD_INFO
= 23
3143 IFLA_BOND_AD_ACTOR_SYS_PRIO
= 24
3144 IFLA_BOND_AD_USER_PORT_KEY
= 25
3145 IFLA_BOND_AD_ACTOR_SYSTEM
= 26
3146 IFLA_BOND_AD_LACP_BYPASS
= 100
3148 ifla_bond_to_string
= {
3149 IFLA_BOND_UNSPEC
: 'IFLA_BOND_UNSPEC',
3150 IFLA_BOND_MODE
: 'IFLA_BOND_MODE',
3151 IFLA_BOND_ACTIVE_SLAVE
: 'IFLA_BOND_ACTIVE_SLAVE',
3152 IFLA_BOND_MIIMON
: 'IFLA_BOND_MIIMON',
3153 IFLA_BOND_UPDELAY
: 'IFLA_BOND_UPDELAY',
3154 IFLA_BOND_DOWNDELAY
: 'IFLA_BOND_DOWNDELAY',
3155 IFLA_BOND_USE_CARRIER
: 'IFLA_BOND_USE_CARRIER',
3156 IFLA_BOND_ARP_INTERVAL
: 'IFLA_BOND_ARP_INTERVAL',
3157 IFLA_BOND_ARP_IP_TARGET
: 'IFLA_BOND_ARP_IP_TARGET',
3158 IFLA_BOND_ARP_VALIDATE
: 'IFLA_BOND_ARP_VALIDATE',
3159 IFLA_BOND_ARP_ALL_TARGETS
: 'IFLA_BOND_ARP_ALL_TARGETS',
3160 IFLA_BOND_PRIMARY
: 'IFLA_BOND_PRIMARY',
3161 IFLA_BOND_PRIMARY_RESELECT
: 'IFLA_BOND_PRIMARY_RESELECT',
3162 IFLA_BOND_FAIL_OVER_MAC
: 'IFLA_BOND_FAIL_OVER_MAC',
3163 IFLA_BOND_XMIT_HASH_POLICY
: 'IFLA_BOND_XMIT_HASH_POLICY',
3164 IFLA_BOND_RESEND_IGMP
: 'IFLA_BOND_RESEND_IGMP',
3165 IFLA_BOND_NUM_PEER_NOTIF
: 'IFLA_BOND_NUM_PEER_NOTIF',
3166 IFLA_BOND_ALL_SLAVES_ACTIVE
: 'IFLA_BOND_ALL_SLAVES_ACTIVE',
3167 IFLA_BOND_MIN_LINKS
: 'IFLA_BOND_MIN_LINKS',
3168 IFLA_BOND_LP_INTERVAL
: 'IFLA_BOND_LP_INTERVAL',
3169 IFLA_BOND_PACKETS_PER_SLAVE
: 'IFLA_BOND_PACKETS_PER_SLAVE',
3170 IFLA_BOND_AD_LACP_RATE
: 'IFLA_BOND_AD_LACP_RATE',
3171 IFLA_BOND_AD_SELECT
: 'IFLA_BOND_AD_SELECT',
3172 IFLA_BOND_AD_INFO
: 'IFLA_BOND_AD_INFO',
3173 IFLA_BOND_AD_ACTOR_SYS_PRIO
: 'IFLA_BOND_AD_ACTOR_SYS_PRIO',
3174 IFLA_BOND_AD_USER_PORT_KEY
: 'IFLA_BOND_AD_USER_PORT_KEY',
3175 IFLA_BOND_AD_ACTOR_SYSTEM
: 'IFLA_BOND_AD_ACTOR_SYSTEM',
3176 IFLA_BOND_AD_LACP_BYPASS
: 'IFLA_BOND_AD_LACP_BYPASS'
3179 IFLA_BOND_AD_INFO_UNSPEC
= 0
3180 IFLA_BOND_AD_INFO_AGGREGATOR
= 1
3181 IFLA_BOND_AD_INFO_NUM_PORTS
= 2
3182 IFLA_BOND_AD_INFO_ACTOR_KEY
= 3
3183 IFLA_BOND_AD_INFO_PARTNER_KEY
= 4
3184 IFLA_BOND_AD_INFO_PARTNER_MAC
= 5
3186 ifla_bond_ad_to_string
= {
3187 IFLA_BOND_AD_INFO_UNSPEC
: 'IFLA_BOND_AD_INFO_UNSPEC',
3188 IFLA_BOND_AD_INFO_AGGREGATOR
: 'IFLA_BOND_AD_INFO_AGGREGATOR',
3189 IFLA_BOND_AD_INFO_NUM_PORTS
: 'IFLA_BOND_AD_INFO_NUM_PORTS',
3190 IFLA_BOND_AD_INFO_ACTOR_KEY
: 'IFLA_BOND_AD_INFO_ACTOR_KEY',
3191 IFLA_BOND_AD_INFO_PARTNER_KEY
: 'IFLA_BOND_AD_INFO_PARTNER_KEY',
3192 IFLA_BOND_AD_INFO_PARTNER_MAC
: 'IFLA_BOND_AD_INFO_PARTNER_MAC'
3195 ifla_bond_mode_tbl
= {
3219 ifla_bond_mode_pretty_tbl
= {
3229 ifla_bond_xmit_hash_policy_tbl
= {
3247 ifla_bond_xmit_hash_policy_pretty_tbl
= {
3255 # =========================================
3256 # IFLA_INFO_SLAVE_DATA attributes for bonds
3257 # =========================================
3258 IFLA_BOND_SLAVE_UNSPEC
= 0
3259 IFLA_BOND_SLAVE_STATE
= 1
3260 IFLA_BOND_SLAVE_MII_STATUS
= 2
3261 IFLA_BOND_SLAVE_LINK_FAILURE_COUNT
= 3
3262 IFLA_BOND_SLAVE_PERM_HWADDR
= 4
3263 IFLA_BOND_SLAVE_QUEUE_ID
= 5
3264 IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
= 6
3265 IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
= 7
3266 IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE
= 8
3267 IFLA_BOND_SLAVE_CL_START
= 50
3268 IFLA_BOND_SLAVE_AD_RX_BYPASS
= IFLA_BOND_SLAVE_CL_START
3270 ifla_bond_slave_to_string
= {
3271 IFLA_BOND_SLAVE_UNSPEC
: 'IFLA_BOND_SLAVE_UNSPEC',
3272 IFLA_BOND_SLAVE_STATE
: 'IFLA_BOND_SLAVE_STATE',
3273 IFLA_BOND_SLAVE_MII_STATUS
: 'IFLA_BOND_SLAVE_MII_STATUS',
3274 IFLA_BOND_SLAVE_LINK_FAILURE_COUNT
: 'IFLA_BOND_SLAVE_LINK_FAILURE_COUNT',
3275 IFLA_BOND_SLAVE_PERM_HWADDR
: 'IFLA_BOND_SLAVE_PERM_HWADDR',
3276 IFLA_BOND_SLAVE_QUEUE_ID
: 'IFLA_BOND_SLAVE_QUEUE_ID',
3277 IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
: 'IFLA_BOND_SLAVE_AD_AGGREGATOR_ID',
3278 IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
: 'IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE',
3279 IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE
: 'IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE',
3280 IFLA_BOND_SLAVE_CL_START
: 'IFLA_BOND_SLAVE_CL_START',
3281 IFLA_BOND_SLAVE_AD_RX_BYPASS
: 'IFLA_BOND_SLAVE_AD_RX_BYPASS'
3284 # =========================================
3285 # IFLA_PROTINFO attributes for bridge ports
3286 # =========================================
3287 IFLA_BRPORT_UNSPEC
= 0
3288 IFLA_BRPORT_STATE
= 1
3289 IFLA_BRPORT_PRIORITY
= 2
3290 IFLA_BRPORT_COST
= 3
3291 IFLA_BRPORT_MODE
= 4
3292 IFLA_BRPORT_GUARD
= 5
3293 IFLA_BRPORT_PROTECT
= 6
3294 IFLA_BRPORT_FAST_LEAVE
= 7
3295 IFLA_BRPORT_LEARNING
= 8
3296 IFLA_BRPORT_UNICAST_FLOOD
= 9
3297 IFLA_BRPORT_PROXYARP
= 10
3298 IFLA_BRPORT_LEARNING_SYNC
= 11
3299 IFLA_BRPORT_PROXYARP_WIFI
= 12
3300 IFLA_BRPORT_ROOT_ID
= 13
3301 IFLA_BRPORT_BRIDGE_ID
= 14
3302 IFLA_BRPORT_DESIGNATED_PORT
= 15
3303 IFLA_BRPORT_DESIGNATED_COST
= 16
3306 IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
= 19
3307 IFLA_BRPORT_CONFIG_PENDING
= 20
3308 IFLA_BRPORT_MESSAGE_AGE_TIMER
= 21
3309 IFLA_BRPORT_FORWARD_DELAY_TIMER
= 22
3310 IFLA_BRPORT_HOLD_TIMER
= 23
3311 IFLA_BRPORT_FLUSH
= 24
3312 IFLA_BRPORT_MULTICAST_ROUTER
= 25
3313 IFLA_BRPORT_PAD
= 26
3314 IFLA_BRPORT_MCAST_FLOOD
= 27
3315 IFLA_BRPORT_MCAST_TO_UCAST
= 28
3316 IFLA_BRPORT_VLAN_TUNNEL
= 29
3317 IFLA_BRPORT_BCAST_FLOOD
= 30
3318 IFLA_BRPORT_GROUP_FWD_MASK
= 31
3319 IFLA_BRPORT_ARP_SUPPRESS
= 32
3320 IFLA_BRPORT_PEER_LINK
= 150
3321 IFLA_BRPORT_DUAL_LINK
= 151
3322 IFLA_BRPORT_GROUP_FWD_MASKHI
= 153
3323 IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
= 154
3325 ifla_brport_to_string
= {
3326 IFLA_BRPORT_UNSPEC
: 'IFLA_BRPORT_UNSPEC',
3327 IFLA_BRPORT_STATE
: 'IFLA_BRPORT_STATE',
3328 IFLA_BRPORT_PRIORITY
: 'IFLA_BRPORT_PRIORITY',
3329 IFLA_BRPORT_COST
: 'IFLA_BRPORT_COST',
3330 IFLA_BRPORT_MODE
: 'IFLA_BRPORT_MODE',
3331 IFLA_BRPORT_GUARD
: 'IFLA_BRPORT_GUARD',
3332 IFLA_BRPORT_PROTECT
: 'IFLA_BRPORT_PROTECT',
3333 IFLA_BRPORT_FAST_LEAVE
: 'IFLA_BRPORT_FAST_LEAVE',
3334 IFLA_BRPORT_LEARNING
: 'IFLA_BRPORT_LEARNING',
3335 IFLA_BRPORT_UNICAST_FLOOD
: 'IFLA_BRPORT_UNICAST_FLOOD',
3336 IFLA_BRPORT_PROXYARP
: 'IFLA_BRPORT_PROXYARP',
3337 IFLA_BRPORT_LEARNING_SYNC
: 'IFLA_BRPORT_LEARNING_SYNC',
3338 IFLA_BRPORT_PROXYARP_WIFI
: 'IFLA_BRPORT_PROXYARP_WIFI',
3339 IFLA_BRPORT_ROOT_ID
: 'IFLA_BRPORT_ROOT_ID',
3340 IFLA_BRPORT_BRIDGE_ID
: 'IFLA_BRPORT_BRIDGE_ID',
3341 IFLA_BRPORT_DESIGNATED_PORT
: 'IFLA_BRPORT_DESIGNATED_PORT',
3342 IFLA_BRPORT_DESIGNATED_COST
: 'IFLA_BRPORT_DESIGNATED_COST',
3343 IFLA_BRPORT_ID
: 'IFLA_BRPORT_ID',
3344 IFLA_BRPORT_NO
: 'IFLA_BRPORT_NO',
3345 IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
: 'IFLA_BRPORT_TOPOLOGY_CHANGE_ACK',
3346 IFLA_BRPORT_CONFIG_PENDING
: 'IFLA_BRPORT_CONFIG_PENDING',
3347 IFLA_BRPORT_MESSAGE_AGE_TIMER
: 'IFLA_BRPORT_MESSAGE_AGE_TIMER',
3348 IFLA_BRPORT_FORWARD_DELAY_TIMER
: 'IFLA_BRPORT_FORWARD_DELAY_TIMER',
3349 IFLA_BRPORT_HOLD_TIMER
: 'IFLA_BRPORT_HOLD_TIMER',
3350 IFLA_BRPORT_FLUSH
: 'IFLA_BRPORT_FLUSH',
3351 IFLA_BRPORT_MULTICAST_ROUTER
: 'IFLA_BRPORT_MULTICAST_ROUTER',
3352 IFLA_BRPORT_PAD
: 'IFLA_BRPORT_PAD',
3353 IFLA_BRPORT_MCAST_FLOOD
: 'IFLA_BRPORT_MCAST_FLOOD',
3354 IFLA_BRPORT_MCAST_TO_UCAST
: 'IFLA_BRPORT_MCAST_TO_UCAST',
3355 IFLA_BRPORT_VLAN_TUNNEL
: 'IFLA_BRPORT_VLAN_TUNNEL',
3356 IFLA_BRPORT_BCAST_FLOOD
: 'IFLA_BRPORT_BCAST_FLOOD',
3357 IFLA_BRPORT_GROUP_FWD_MASK
: 'IFLA_BRPORT_GROUP_FWD_MASK',
3358 IFLA_BRPORT_PEER_LINK
: 'IFLA_BRPORT_PEER_LINK',
3359 IFLA_BRPORT_DUAL_LINK
: 'IFLA_BRPORT_DUAL_LINK',
3360 IFLA_BRPORT_ARP_SUPPRESS
: 'IFLA_BRPORT_ARP_SUPPRESS',
3361 IFLA_BRPORT_GROUP_FWD_MASKHI
: 'IFLA_BRPORT_GROUP_FWD_MASKHI',
3362 IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
: 'IFLA_BRPORT_DOWN_PEERLINK_REDIRECT'
3365 # BRIDGE IFLA_AF_SPEC attributes
3366 IFLA_BRIDGE_FLAGS
= 0
3367 IFLA_BRIDGE_MODE
= 1
3368 IFLA_BRIDGE_VLAN_INFO
= 2
3370 ifla_bridge_af_spec_to_string
= {
3371 IFLA_BRIDGE_FLAGS
: 'IFLA_BRIDGE_FLAGS',
3372 IFLA_BRIDGE_MODE
: 'IFLA_BRIDGE_MODE',
3373 IFLA_BRIDGE_VLAN_INFO
: 'IFLA_BRIDGE_VLAN_INFO'
3376 # BRIDGE_VLAN_INFO flags
3377 BRIDGE_VLAN_INFO_MASTER
= 1 << 0 # Operate on Bridge device as well
3378 BRIDGE_VLAN_INFO_PVID
= 1 << 1 # VLAN is PVID, ingress untagged
3379 BRIDGE_VLAN_INFO_UNTAGGED
= 1 << 2 # VLAN egresses untagged
3380 BRIDGE_VLAN_INFO_RANGE_BEGIN
= 1 << 3 # VLAN is start of vlan range
3381 BRIDGE_VLAN_INFO_RANGE_END
= 1 << 4 # VLAN is end of vlan range
3382 BRIDGE_VLAN_INFO_BRENTRY
= 1 << 5 # Global bridge VLAN entry
3384 bridge_vlan_to_string
= {
3385 BRIDGE_VLAN_INFO_MASTER
: 'BRIDGE_VLAN_INFO_MASTER',
3386 BRIDGE_VLAN_INFO_PVID
: 'BRIDGE_VLAN_INFO_PVID',
3387 BRIDGE_VLAN_INFO_UNTAGGED
: 'BRIDGE_VLAN_INFO_UNTAGGED',
3388 BRIDGE_VLAN_INFO_RANGE_BEGIN
: 'BRIDGE_VLAN_INFO_RANGE_BEGIN',
3389 BRIDGE_VLAN_INFO_RANGE_END
: 'BRIDGE_VLAN_INFO_RANGE_END',
3390 BRIDGE_VLAN_INFO_BRENTRY
: 'BRIDGE_VLAN_INFO_BRENTRY'
3394 BRIDGE_FLAGS_MASTER
= 1
3395 BRIDGE_FLAGS_SELF
= 2
3397 bridge_flags_to_string
= {
3398 BRIDGE_FLAGS_MASTER
: 'BRIDGE_FLAGS_MASTER',
3399 BRIDGE_FLAGS_SELF
: 'BRIDGE_FLAGS_SELF'
3402 # filters for IFLA_EXT_MASK
3403 RTEXT_FILTER_VF
= 1 << 0
3404 RTEXT_FILTER_BRVLAN
= 1 << 1
3405 RTEXT_FILTER_BRVLAN_COMPRESSED
= 1 << 2
3406 RTEXT_FILTER_SKIP_STATS
= 1 << 3
3409 RTEXT_FILTER_VF
: 'RTEXT_FILTER_VF',
3410 RTEXT_FILTER_BRVLAN
: 'RTEXT_FILTER_BRVLAN',
3411 RTEXT_FILTER_BRVLAN_COMPRESSED
: 'RTEXT_FILTER_BRVLAN_COMPRESSED',
3412 RTEXT_FILTER_SKIP_STATS
: 'RTEXT_FILTER_SKIP_STATS'
3416 IFLA_BR_FORWARD_DELAY
= 1
3417 IFLA_BR_HELLO_TIME
= 2
3419 IFLA_BR_AGEING_TIME
= 4
3420 IFLA_BR_STP_STATE
= 5
3421 IFLA_BR_PRIORITY
= 6
3422 IFLA_BR_VLAN_FILTERING
= 7
3423 IFLA_BR_VLAN_PROTOCOL
= 8
3424 IFLA_BR_GROUP_FWD_MASK
= 9
3425 IFLA_BR_ROOT_ID
= 10
3426 IFLA_BR_BRIDGE_ID
= 11
3427 IFLA_BR_ROOT_PORT
= 12
3428 IFLA_BR_ROOT_PATH_COST
= 13
3429 IFLA_BR_TOPOLOGY_CHANGE
= 14
3430 IFLA_BR_TOPOLOGY_CHANGE_DETECTED
= 15
3431 IFLA_BR_HELLO_TIMER
= 16
3432 IFLA_BR_TCN_TIMER
= 17
3433 IFLA_BR_TOPOLOGY_CHANGE_TIMER
= 18
3434 IFLA_BR_GC_TIMER
= 19
3435 IFLA_BR_GROUP_ADDR
= 20
3436 IFLA_BR_FDB_FLUSH
= 21
3437 IFLA_BR_MCAST_ROUTER
= 22
3438 IFLA_BR_MCAST_SNOOPING
= 23
3439 IFLA_BR_MCAST_QUERY_USE_IFADDR
= 24
3440 IFLA_BR_MCAST_QUERIER
= 25
3441 IFLA_BR_MCAST_HASH_ELASTICITY
= 26
3442 IFLA_BR_MCAST_HASH_MAX
= 27
3443 IFLA_BR_MCAST_LAST_MEMBER_CNT
= 28
3444 IFLA_BR_MCAST_STARTUP_QUERY_CNT
= 29
3445 IFLA_BR_MCAST_LAST_MEMBER_INTVL
= 30
3446 IFLA_BR_MCAST_MEMBERSHIP_INTVL
= 31
3447 IFLA_BR_MCAST_QUERIER_INTVL
= 32
3448 IFLA_BR_MCAST_QUERY_INTVL
= 33
3449 IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
= 34
3450 IFLA_BR_MCAST_STARTUP_QUERY_INTVL
= 35
3451 IFLA_BR_NF_CALL_IPTABLES
= 36
3452 IFLA_BR_NF_CALL_IP6TABLES
= 37
3453 IFLA_BR_NF_CALL_ARPTABLES
= 38
3454 IFLA_BR_VLAN_DEFAULT_PVID
= 39
3456 IFLA_BR_VLAN_STATS_ENABLED
= 41
3457 IFLA_BR_MCAST_STATS_ENABLED
= 42
3458 IFLA_BR_MCAST_IGMP_VERSION
= 43
3459 IFLA_BR_MCAST_MLD_VERSION
= 44
3461 ifla_br_to_string
= {
3462 IFLA_BR_UNSPEC
: 'IFLA_BR_UNSPEC',
3463 IFLA_BR_FORWARD_DELAY
: 'IFLA_BR_FORWARD_DELAY',
3464 IFLA_BR_HELLO_TIME
: 'IFLA_BR_HELLO_TIME',
3465 IFLA_BR_MAX_AGE
: 'IFLA_BR_MAX_AGE',
3466 IFLA_BR_AGEING_TIME
: 'IFLA_BR_AGEING_TIME',
3467 IFLA_BR_STP_STATE
: 'IFLA_BR_STP_STATE',
3468 IFLA_BR_PRIORITY
: 'IFLA_BR_PRIORITY',
3469 IFLA_BR_VLAN_FILTERING
: 'IFLA_BR_VLAN_FILTERING',
3470 IFLA_BR_VLAN_PROTOCOL
: 'IFLA_BR_VLAN_PROTOCOL',
3471 IFLA_BR_GROUP_FWD_MASK
: 'IFLA_BR_GROUP_FWD_MASK',
3472 IFLA_BR_ROOT_ID
: 'IFLA_BR_ROOT_ID',
3473 IFLA_BR_BRIDGE_ID
: 'IFLA_BR_BRIDGE_ID',
3474 IFLA_BR_ROOT_PORT
: 'IFLA_BR_ROOT_PORT',
3475 IFLA_BR_ROOT_PATH_COST
: 'IFLA_BR_ROOT_PATH_COST',
3476 IFLA_BR_TOPOLOGY_CHANGE
: 'IFLA_BR_TOPOLOGY_CHANGE',
3477 IFLA_BR_TOPOLOGY_CHANGE_DETECTED
: 'IFLA_BR_TOPOLOGY_CHANGE_DETECTED',
3478 IFLA_BR_HELLO_TIMER
: 'IFLA_BR_HELLO_TIMER',
3479 IFLA_BR_TCN_TIMER
: 'IFLA_BR_TCN_TIMER',
3480 IFLA_BR_TOPOLOGY_CHANGE_TIMER
: 'IFLA_BR_TOPOLOGY_CHANGE_TIMER',
3481 IFLA_BR_GC_TIMER
: 'IFLA_BR_GC_TIMER',
3482 IFLA_BR_GROUP_ADDR
: 'IFLA_BR_GROUP_ADDR',
3483 IFLA_BR_FDB_FLUSH
: 'IFLA_BR_FDB_FLUSH',
3484 IFLA_BR_MCAST_ROUTER
: 'IFLA_BR_MCAST_ROUTER',
3485 IFLA_BR_MCAST_SNOOPING
: 'IFLA_BR_MCAST_SNOOPING',
3486 IFLA_BR_MCAST_QUERY_USE_IFADDR
: 'IFLA_BR_MCAST_QUERY_USE_IFADDR',
3487 IFLA_BR_MCAST_QUERIER
: 'IFLA_BR_MCAST_QUERIER',
3488 IFLA_BR_MCAST_HASH_ELASTICITY
: 'IFLA_BR_MCAST_HASH_ELASTICITY',
3489 IFLA_BR_MCAST_HASH_MAX
: 'IFLA_BR_MCAST_HASH_MAX',
3490 IFLA_BR_MCAST_LAST_MEMBER_CNT
: 'IFLA_BR_MCAST_LAST_MEMBER_CNT',
3491 IFLA_BR_MCAST_STARTUP_QUERY_CNT
: 'IFLA_BR_MCAST_STARTUP_QUERY_CNT',
3492 IFLA_BR_MCAST_LAST_MEMBER_INTVL
: 'IFLA_BR_MCAST_LAST_MEMBER_INTVL',
3493 IFLA_BR_MCAST_MEMBERSHIP_INTVL
: 'IFLA_BR_MCAST_MEMBERSHIP_INTVL',
3494 IFLA_BR_MCAST_QUERIER_INTVL
: 'IFLA_BR_MCAST_QUERIER_INTVL',
3495 IFLA_BR_MCAST_QUERY_INTVL
: 'IFLA_BR_MCAST_QUERY_INTVL',
3496 IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
: 'IFLA_BR_MCAST_QUERY_RESPONSE_INTVL',
3497 IFLA_BR_MCAST_STARTUP_QUERY_INTVL
: 'IFLA_BR_MCAST_STARTUP_QUERY_INTVL',
3498 IFLA_BR_NF_CALL_IPTABLES
: 'IFLA_BR_NF_CALL_IPTABLES',
3499 IFLA_BR_NF_CALL_IP6TABLES
: 'IFLA_BR_NF_CALL_IP6TABLES',
3500 IFLA_BR_NF_CALL_ARPTABLES
: 'IFLA_BR_NF_CALL_ARPTABLES',
3501 IFLA_BR_VLAN_DEFAULT_PVID
: 'IFLA_BR_VLAN_DEFAULT_PVID',
3502 IFLA_BR_PAD
: 'IFLA_BR_PAD',
3503 IFLA_BR_VLAN_STATS_ENABLED
: 'IFLA_BR_VLAN_STATS_ENABLED',
3504 IFLA_BR_MCAST_STATS_ENABLED
: 'IFLA_BR_MCAST_STATS_ENABLED',
3505 IFLA_BR_MCAST_IGMP_VERSION
: 'IFLA_BR_MCAST_IGMP_VERSION',
3506 IFLA_BR_MCAST_MLD_VERSION
: 'IFLA_BR_MCAST_MLD_VERSION'
3509 # =========================================
3510 # IFLA_INFO_DATA attributes for vrfs
3511 # =========================================
3515 ifla_vrf_to_string
= {
3516 IFLA_VRF_UNSPEC
: 'IFLA_VRF_UNSPEC',
3517 IFLA_VRF_TABLE
: 'IFLA_VRF_TABLE'
3520 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
3521 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
3522 self
.PACK
= 'BxHiII'
3523 self
.LEN
= calcsize(self
.PACK
)
3525 def get_link_type_string(self
, index
):
3526 return self
.get_string(self
.link_type_to_string
, index
)
3528 def get_ifla_bridge_af_spec_to_string(self
, index
):
3529 return self
.get_string(self
.ifla_bridge_af_spec_to_string
, index
)
3531 def get_ifla_info_string(self
, index
):
3532 return self
.get_string(self
.ifla_info_to_string
, index
)
3534 def get_ifla_vlan_string(self
, index
):
3535 return self
.get_string(self
.ifla_vlan_to_string
, index
)
3537 def get_ifla_vxlan_string(self
, index
):
3538 return self
.get_string(self
.ifla_vxlan_to_string
, index
)
3540 def get_ifla_macvlan_string(self
, index
):
3541 return self
.get_string(self
.ifla_macvlan_to_string
, index
)
3543 def get_macvlan_mode_string(self
, index
):
3544 return self
.get_string(self
.macvlan_mode_to_string
, index
)
3546 def get_ifla_bond_string(self
, index
):
3547 return self
.get_string(self
.ifla_bond_to_string
, index
)
3549 def get_ifla_bond_ad_string(self
, index
):
3550 return self
.get_string(self
.ifla_bond_ad_to_string
, index
)
3552 def get_ifla_brport_string(self
, index
):
3553 return self
.get_string(self
.ifla_brport_to_string
, index
)
3555 def get_ifla_br_string(self
, index
):
3556 return self
.get_string(self
.ifla_br_to_string
, index
)
3558 def get_bridge_vlan_string(self
, index
):
3559 return self
.get_string(self
.bridge_vlan_to_string
, index
)
3561 def get_bridge_flags_string(self
, index
):
3562 return self
.get_string(self
.bridge_flags_to_string
, index
)
3564 def decode_service_header(self
):
3566 # Nothing to do if the message did not contain a service header
3567 if self
.length
== self
.header_LEN
:
3570 (self
.family
, self
.device_type
,
3573 self
.change_mask
) = \
3574 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
3577 color
= yellow
if self
.use_color
else None
3578 color_start
= "\033[%dm" % color
if color
else ""
3579 color_end
= "\033[0m" if color
else ""
3580 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
3582 for x
in range(0, self
.LEN
/4):
3583 if self
.line_number
== 5:
3584 extra
= "Family %s (%d), Device Type %s (%d - %s)" % \
3585 (zfilled_hex(self
.family
, 2), self
.family
,
3586 zfilled_hex(self
.device_type
, 4), self
.device_type
, self
.get_link_type_string(self
.device_type
))
3587 elif self
.line_number
== 6:
3588 extra
= "Interface Index %s (%d)" % (zfilled_hex(self
.ifindex
, 8), self
.ifindex
)
3589 elif self
.line_number
== 7:
3590 extra
= "Device Flags %s (%s)" % (zfilled_hex(self
.flags
, 8), self
.get_flags_string())
3591 elif self
.line_number
== 8:
3592 extra
= "Change Mask %s" % zfilled_hex(self
.change_mask
, 8)
3594 extra
= "Unexpected line number %d" % self
.line_number
3598 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
3599 self
.line_number
+= 1
3602 if self
.flags
& Link
.IFF_UP
:
3607 class Neighbor(NetlinkPacket
):
3612 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
3613 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3614 | Family | Reserved1 | Reserved2 |
3615 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3617 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3618 | State | Flags | Type |
3619 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3622 # Neighbor attributes
3623 # /usr/include/linux/neighbour.h
3624 NDA_UNSPEC
= 0x00 # Unknown type
3625 NDA_DST
= 0x01 # A neighbour cache network. layer destination address
3626 NDA_LLADDR
= 0x02 # A neighbor cache link layer address.
3627 NDA_CACHEINFO
= 0x03 # Cache statistics
3634 NDA_LINK_NETNSID
= 0x0A
3636 attribute_to_class
= {
3637 NDA_UNSPEC
: ('NDA_UNSPEC', AttributeGeneric
),
3638 NDA_DST
: ('NDA_DST', AttributeIPAddress
),
3639 NDA_LLADDR
: ('NDA_LLADDR', AttributeMACAddress
),
3640 NDA_CACHEINFO
: ('NDA_CACHEINFO', AttributeFourByteList
),
3641 NDA_PROBES
: ('NDA_PROBES', AttributeFourByteValue
),
3642 NDA_VLAN
: ('NDA_VLAN', AttributeTwoByteValue
),
3643 NDA_PORT
: ('NDA_PORT', AttributeGeneric
),
3644 NDA_VNI
: ('NDA_VNI', AttributeFourByteValue
),
3645 NDA_IFINDEX
: ('NDA_IFINDEX', AttributeFourByteValue
),
3646 NDA_MASTER
: ('NDA_MASTER', AttributeFourByteValue
),
3647 NDA_LINK_NETNSID
: ('NDA_LINK_NETNSID', AttributeGeneric
)
3651 # /usr/include/linux/neighbour.h
3655 NTF_PROXY
= 0x08 # A proxy ARP entry
3656 NTF_EXT_LEARNED
= 0x10 # neigh entry installed by an external APP
3657 NTF_ROUTER
= 0x80 # An IPv6 router
3660 NTF_USE
: 'NTF_USE',
3661 NTF_SELF
: 'NTF_SELF',
3662 NTF_MASTER
: 'NTF_MASTER',
3663 NTF_PROXY
: 'NTF_PROXY',
3664 NTF_EXT_LEARNED
: 'NTF_EXT_LEARNED',
3665 NTF_ROUTER
: 'NTF_ROUTER'
3669 # /usr/include/linux/neighbour.h
3671 NUD_INCOMPLETE
= 0x01 # Still attempting to resolve
3672 NUD_REACHABLE
= 0x02 # A confirmed working cache entry
3673 NUD_STALE
= 0x04 # an expired cache entry
3674 NUD_DELAY
= 0x08 # Neighbor no longer reachable. Traffic sent, waiting for confirmatio.
3675 NUD_PROBE
= 0x10 # A cache entry that is currently being re-solicited
3676 NUD_FAILED
= 0x20 # An invalid cache entry
3677 NUD_NOARP
= 0x40 # A device which does not do neighbor discovery(ARP)
3678 NUD_PERMANENT
= 0x80 # A static entry
3681 NUD_NONE
: 'NUD_NONE',
3682 NUD_INCOMPLETE
: 'NUD_INCOMPLETE',
3683 NUD_REACHABLE
: 'NUD_REACHABLE',
3684 NUD_STALE
: 'NUD_STALE',
3685 NUD_DELAY
: 'NUD_DELAY',
3686 NUD_PROBE
: 'NUD_PROBE',
3687 NUD_FAILED
: 'NUD_FAILED',
3688 NUD_NOARP
: 'NUD_NOARP',
3689 NUD_PERMANENT
: 'NUD_PERMANENT'
3692 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
3693 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
3694 self
.PACK
= 'BxxxiHBB'
3695 self
.LEN
= calcsize(self
.PACK
)
3697 def get_state_string(self
, index
):
3698 return self
.get_string(self
.state_to_string
, index
)
3700 def get_states_string(self
, states
):
3703 if states
& Neighbor
.NUD_INCOMPLETE
:
3704 for_string
.append('NUD_INCOMPLETE')
3706 if states
& Neighbor
.NUD_REACHABLE
:
3707 for_string
.append('NUD_REACHABLE')
3709 if states
& Neighbor
.NUD_STALE
:
3710 for_string
.append('NUD_STALE')
3712 if states
& Neighbor
.NUD_DELAY
:
3713 for_string
.append('NUD_DELAY')
3715 if states
& Neighbor
.NUD_PROBE
:
3716 for_string
.append('NUD_PROBE')
3718 if states
& Neighbor
.NUD_FAILED
:
3719 for_string
.append('NUD_FAILED')
3721 if states
& Neighbor
.NUD_NOARP
:
3722 for_string
.append('NUD_NOARP')
3724 if states
& Neighbor
.NUD_PERMANENT
:
3725 for_string
.append('NUD_PERMANENT')
3727 return ', '.join(for_string
)
3729 def get_flags_string(self
, flags
):
3732 if flags
& Neighbor
.NTF_USE
:
3733 for_string
.append('NTF_USE')
3735 if flags
& Neighbor
.NTF_SELF
:
3736 for_string
.append('NTF_SELF')
3738 if flags
& Neighbor
.NTF_MASTER
:
3739 for_string
.append('NTF_MASTER')
3741 if flags
& Neighbor
.NTF_PROXY
:
3742 for_string
.append('NTF_PROXY')
3744 if flags
& Neighbor
.NTF_ROUTER
:
3745 for_string
.append('NTF_ROUTER')
3747 return ', '.join(for_string
)
3749 def decode_service_header(self
):
3751 # Nothing to do if the message did not contain a service header
3752 if self
.length
== self
.header_LEN
:
3757 self
.state
, self
.flags
, self
.neighbor_type
) = \
3758 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
3761 color
= yellow
if self
.use_color
else None
3762 color_start
= "\033[%dm" % color
if color
else ""
3763 color_end
= "\033[0m" if color
else ""
3764 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
3766 for x
in range(0, self
.LEN
/4):
3767 if self
.line_number
== 5:
3768 extra
= "Family %s (%d)" % (zfilled_hex(self
.family
, 2), self
.family
)
3769 elif self
.line_number
== 6:
3770 extra
= "Interface Index %s (%d)" % (zfilled_hex(self
.ifindex
, 8), self
.ifindex
)
3771 elif self
.line_number
== 7:
3772 extra
= "State %s (%d) %s, Flags %s (%s) %s, Type %s (%d)" % \
3773 (zfilled_hex(self
.state
, 4), self
.state
, self
.get_states_string(self
.state
),
3774 zfilled_hex(self
.flags
, 2), self
.flags
, self
.get_flags_string(self
.flags
),
3775 zfilled_hex(self
.neighbor_type
, 4), self
.neighbor_type
)
3777 extra
= "Unexpected line number %d" % self
.line_number
3781 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
3782 self
.line_number
+= 1
3785 class Route(NetlinkPacket
):
3790 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
3791 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3792 | Family | Dest length | Src length | TOS |
3793 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3794 | Table ID | Protocol | Scope | Type |
3795 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3797 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3801 # /usr/include/linux/rtnetlink.h
3802 RTA_UNSPEC
= 0x00 # Ignored.
3803 RTA_DST
= 0x01 # Protocol address for route destination address.
3804 RTA_SRC
= 0x02 # Protocol address for route source address.
3805 RTA_IIF
= 0x03 # Input interface index.
3806 RTA_OIF
= 0x04 # Output interface index.
3807 RTA_GATEWAY
= 0x05 # Protocol address for the gateway of the route
3808 RTA_PRIORITY
= 0x06 # Priority of broker.
3809 RTA_PREFSRC
= 0x07 # Preferred source address in cases where more than one source address could be used.
3810 RTA_METRICS
= 0x08 # Route metrics attributed to route and associated protocols(e.g., RTT, initial TCP window, etc.).
3811 RTA_MULTIPATH
= 0x09 # Multipath route next hop's attributes.
3812 RTA_PROTOINFO
= 0x0A # Firewall based policy routing attribute.
3813 RTA_FLOW
= 0x0B # Route realm.
3814 RTA_CACHEINFO
= 0x0C # Cached route information.
3819 RTA_MFC_STATS
= 0x11
3823 RTA_ENCAP_TYPE
= 0x15
3826 attribute_to_class
= {
3827 RTA_UNSPEC
: ('RTA_UNSPEC', AttributeGeneric
),
3828 RTA_DST
: ('RTA_DST', AttributeIPAddress
),
3829 RTA_SRC
: ('RTA_SRC', AttributeIPAddress
),
3830 RTA_IIF
: ('RTA_IIF', AttributeFourByteValue
),
3831 RTA_OIF
: ('RTA_OIF', AttributeFourByteValue
),
3832 RTA_GATEWAY
: ('RTA_GATEWAY', AttributeIPAddress
),
3833 RTA_PRIORITY
: ('RTA_PRIORITY', AttributeFourByteValue
),
3834 RTA_PREFSRC
: ('RTA_PREFSRC', AttributeIPAddress
),
3835 RTA_METRICS
: ('RTA_METRICS', AttributeGeneric
),
3836 RTA_MULTIPATH
: ('RTA_MULTIPATH', AttributeRTA_MULTIPATH
),
3837 RTA_PROTOINFO
: ('RTA_PROTOINFO', AttributeGeneric
),
3838 RTA_FLOW
: ('RTA_FLOW', AttributeGeneric
),
3839 RTA_CACHEINFO
: ('RTA_CACHEINFO', AttributeGeneric
),
3840 RTA_SESSION
: ('RTA_SESSION', AttributeGeneric
),
3841 RTA_MP_ALGO
: ('RTA_MP_ALGO', AttributeGeneric
),
3842 RTA_TABLE
: ('RTA_TABLE', AttributeFourByteValue
),
3843 RTA_MARK
: ('RTA_MARK', AttributeGeneric
),
3844 RTA_MFC_STATS
: ('RTA_MFC_STATS', AttributeGeneric
),
3845 RTA_VIA
: ('RTA_VIA', AttributeGeneric
),
3846 RTA_NEWDST
: ('RTA_NEWDST', AttributeGeneric
),
3847 RTA_PREF
: ('RTA_PREF', AttributeGeneric
),
3848 RTA_ENCAP_TYPE
: ('RTA_ENCAP_TYPE', AttributeGeneric
),
3849 RTA_ENCAP
: ('RTA_ENCAP', AttributeGeneric
)
3853 # /usr/include/linux/rtnetlink.h
3854 RT_TABLE_UNSPEC
= 0x00 # An unspecified routing table
3855 RT_TABLE_COMPAT
= 0xFC
3856 RT_TABLE_DEFAULT
= 0xFD # The default table
3857 RT_TABLE_MAIN
= 0xFE # The main table
3858 RT_TABLE_LOCAL
= 0xFF # The local table
3861 RT_TABLE_UNSPEC
: 'RT_TABLE_UNSPEC',
3862 RT_TABLE_COMPAT
: 'RT_TABLE_COMPAT',
3863 RT_TABLE_DEFAULT
: 'RT_TABLE_DEFAULT',
3864 RT_TABLE_MAIN
: 'RT_TABLE_MAIN',
3865 RT_TABLE_LOCAL
: 'RT_TABLE_LOCAL'
3869 # /usr/include/linux/rtnetlink.h
3870 RT_SCOPE_UNIVERSE
= 0x00 # Global route
3871 RT_SCOPE_SITE
= 0xC8 # Interior route in the local autonomous system
3872 RT_SCOPE_LINK
= 0xFD # Route on this link
3873 RT_SCOPE_HOST
= 0xFE # Route on the local host
3874 RT_SCOPE_NOWHERE
= 0xFF # Destination does not exist
3877 RT_SCOPE_UNIVERSE
: 'RT_SCOPE_UNIVERSE',
3878 RT_SCOPE_SITE
: 'RT_SCOPE_SITE',
3879 RT_SCOPE_LINK
: 'RT_SCOPE_LINK',
3880 RT_SCOPE_HOST
: 'RT_SCOPE_HOST',
3881 RT_SCOPE_NOWHERE
: 'RT_SCOPE_NOWHERE'
3884 # Route scope to string
3885 # iproute2/lib/rt_names.c
3886 rtnl_rtscope_tab
= {
3887 RT_SCOPE_UNIVERSE
: 'global',
3888 RT_SCOPE_NOWHERE
: 'nowhere',
3889 RT_SCOPE_HOST
: 'host',
3890 RT_SCOPE_LINK
: 'link',
3891 RT_SCOPE_SITE
: 'site'
3895 # /usr/include/linux/rtnetlink.h
3896 RT_PROT_UNSPEC
= 0x00 # Identifies what/who added the route
3897 RT_PROT_REDIRECT
= 0x01 # By an ICMP redirect
3898 RT_PROT_KERNEL
= 0x02 # By the kernel
3899 RT_PROT_BOOT
= 0x03 # During bootup
3900 RT_PROT_STATIC
= 0x04 # By the administrator
3901 RT_PROT_GATED
= 0x08 # GateD
3902 RT_PROT_RA
= 0x09 # RDISC/ND router advertissements
3903 RT_PROT_MRT
= 0x0A # Merit MRT
3904 RT_PROT_ZEBRA
= 0x0B # ZEBRA
3905 RT_PROT_BIRD
= 0x0C # BIRD
3906 RT_PROT_DNROUTED
= 0x0D # DECnet routing daemon
3907 RT_PROT_XORP
= 0x0E # XORP
3908 RT_PROT_NTK
= 0x0F # Netsukuku
3909 RT_PROT_DHCP
= 0x10 # DHCP client
3910 RT_PROT_EXABGP
= 0x11 # Exa Networks ExaBGP
3913 RT_PROT_UNSPEC
: 'RT_PROT_UNSPEC',
3914 RT_PROT_REDIRECT
: 'RT_PROT_REDIRECT',
3915 RT_PROT_KERNEL
: 'RT_PROT_KERNEL',
3916 RT_PROT_BOOT
: 'RT_PROT_BOOT',
3917 RT_PROT_STATIC
: 'RT_PROT_STATIC',
3918 RT_PROT_GATED
: 'RT_PROT_GATED',
3919 RT_PROT_RA
: 'RT_PROT_RA',
3920 RT_PROT_MRT
: 'RT_PROT_MRT',
3921 RT_PROT_ZEBRA
: 'RT_PROT_ZEBRA',
3922 RT_PROT_BIRD
: 'RT_PROT_BIRD',
3923 RT_PROT_DNROUTED
: 'RT_PROT_DNROUTED',
3924 RT_PROT_XORP
: 'RT_PROT_XORP',
3925 RT_PROT_NTK
: 'RT_PROT_NTK',
3926 RT_PROT_DHCP
: 'RT_PROT_DHCP',
3927 RT_PROT_EXABGP
: 'RT_PROT_EXABGP'
3931 # /usr/include/linux/rtnetlink.h
3932 RTN_UNSPEC
= 0x00 # Unknown broker.
3933 RTN_UNICAST
= 0x01 # A gateway or direct broker.
3934 RTN_LOCAL
= 0x02 # A local interface broker.
3935 RTN_BROADCAST
= 0x03 # A local broadcast route(sent as a broadcast).
3936 RTN_ANYCAST
= 0x04 # An anycast broker.
3937 RTN_MULTICAST
= 0x05 # A multicast broker.
3938 RTN_BLACKHOLE
= 0x06 # A silent packet dropping broker.
3939 RTN_UNREACHABLE
= 0x07 # An unreachable destination. Packets dropped and
3940 # host unreachable ICMPs are sent to the originator.
3941 RTN_PROHIBIT
= 0x08 # A packet rejection broker. Packets are dropped and
3942 # communication prohibited ICMPs are sent to the originator.
3943 RTN_THROW
= 0x09 # When used with policy routing, continue routing lookup
3944 # in another table. Under normal routing, packets are
3945 # dropped and net unreachable ICMPs are sent to the originator.
3946 RTN_NAT
= 0x0A # A network address translation rule.
3947 RTN_XRESOLVE
= 0x0B # Refer to an external resolver(not implemented).
3949 rt_type_to_string
= {
3950 RTN_UNSPEC
: 'RTN_UNSPEC',
3951 RTN_UNICAST
: 'RTN_UNICAST',
3952 RTN_LOCAL
: 'RTN_LOCAL',
3953 RTN_BROADCAST
: 'RTN_BROADCAST',
3954 RTN_ANYCAST
: 'RTN_ANYCAST',
3955 RTN_MULTICAST
: 'RTN_MULTICAST',
3956 RTN_BLACKHOLE
: 'RTN_BLACKHOLE',
3957 RTN_UNREACHABLE
: 'RTN_UNREACHABLE',
3958 RTN_PROHIBIT
: 'RTN_PROHIBIT',
3959 RTN_THROW
: 'RTN_THROW',
3960 RTN_NAT
: 'RTN_NAT',
3961 RTN_XRESOLVE
: 'RTN_XRESOLVE'
3965 # /usr/include/linux/rtnetlink.h
3966 RTM_F_NOTIFY
= 0x100 # If the route changes, notify the user
3967 RTM_F_CLONED
= 0x200 # Route is cloned from another route
3968 RTM_F_EQUALIZE
= 0x400 # Allow randomization of next hop path in multi-path routing(currently not implemented)
3969 RTM_F_PREFIX
= 0x800 # Prefix Address
3972 RTM_F_NOTIFY
: 'RTM_F_NOTIFY',
3973 RTM_F_CLONED
: 'RTM_F_CLONED',
3974 RTM_F_EQUALIZE
: 'RTM_F_EQUALIZE',
3975 RTM_F_PREFIX
: 'RTM_F_PREFIX'
3978 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
3979 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
3980 self
.PACK
= '=8BI' # or is it 8Bi ?
3981 self
.LEN
= calcsize(self
.PACK
)
3983 def get_prefix_string(self
):
3984 dst
= self
.get_attribute_value(self
.RTA_DST
)
3987 return "%s/%d" % (dst
, self
.src_len
)
3989 if self
.family
== AF_INET
:
3991 elif self
.family
== AF_INET6
:
3994 def get_protocol_string(self
, index
=None):
3996 index
= self
.protocol
3997 return self
.get_string(self
.prot_to_string
, index
)
3999 def get_rt_type_string(self
, index
=None):
4001 index
= self
.route_type
4002 return self
.get_string(self
.rt_type_to_string
, index
)
4004 def get_scope_string(self
, index
=None):
4007 return self
.get_string(self
.scope_to_string
, index
)
4009 def get_table_id_string(self
, index
=None):
4011 index
= self
.table_id
4012 return self
.get_string(self
.table_to_string
, index
)
4014 def _get_ifname_from_index(self
, ifindex
, ifname_by_index
):
4016 ifname
= ifname_by_index
.get(ifindex
)
4019 ifname
= str(ifindex
)
4025 def get_nexthops(self
, ifname_by_index
={}):
4026 nexthop
= self
.get_attribute_value(self
.RTA_GATEWAY
)
4027 multipath
= self
.get_attribute_value(self
.RTA_MULTIPATH
)
4031 rta_oif
= self
.get_attribute_value(self
.RTA_OIF
)
4032 ifname
= self
._get
_ifname
_from
_index
(rta_oif
, ifname_by_index
)
4033 nexthops
.append((nexthop
, ifname
))
4036 for (nexthop
, rtnh_ifindex
, rtnh_flags
, rtnh_hops
) in multipath
:
4037 ifname
= self
._get
_ifname
_from
_index
(rtnh_ifindex
, ifname_by_index
)
4038 nexthops
.append((nexthop
, ifname
))
4042 def get_nexthops_string(self
, ifname_by_index
={}):
4045 for (nexthop
, ifname
) in self
.get_nexthops(ifname_by_index
):
4046 output
.append(" via %s on %s" % (nexthop
, ifname
))
4048 return ",".join(output
)
4050 def decode_service_header(self
):
4052 # Nothing to do if the message did not contain a service header
4053 if self
.length
== self
.header_LEN
:
4056 (self
.family
, self
.src_len
, self
.dst_len
, self
.tos
,
4057 self
.table_id
, self
.protocol
, self
.scope
, self
.route_type
,
4059 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
4062 color
= yellow
if self
.use_color
else None
4063 color_start
= "\033[%dm" % color
if color
else ""
4064 color_end
= "\033[0m" if color
else ""
4065 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
4067 for x
in range(0, self
.LEN
/4):
4068 if self
.line_number
== 5:
4069 extra
= "Family %s (%d), Source Length %s (%d), Destination Length %s (%d), TOS %s (%d)" % \
4070 (zfilled_hex(self
.family
, 2), self
.family
,
4071 zfilled_hex(self
.src_len
, 2), self
.src_len
,
4072 zfilled_hex(self
.dst_len
, 2), self
.dst_len
,
4073 zfilled_hex(self
.tos
, 2), self
.tos
)
4074 elif self
.line_number
== 6:
4075 extra
= "Table ID %s (%d - %s), Protocol %s (%d - %s), Scope %s (%d - %s), Type %s (%d - %s)" % \
4076 (zfilled_hex(self
.table_id
, 2), self
.table_id
, self
.get_table_id_string(),
4077 zfilled_hex(self
.protocol
, 2), self
.protocol
, self
.get_protocol_string(),
4078 zfilled_hex(self
.scope
, 2), self
.scope
, self
.get_scope_string(),
4079 zfilled_hex(self
.route_type
, 2), self
.route_type
, self
.get_rt_type_string())
4080 elif self
.line_number
== 7:
4081 extra
= "Flags %s" % zfilled_hex(self
.flags
, 8)
4083 extra
= "Unexpected line number %d" % self
.line_number
4087 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
4088 self
.line_number
+= 1
4090 class Done(NetlinkPacket
):
4096 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
4097 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4099 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4102 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
4103 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
4105 self
.LEN
= calcsize(self
.PACK
)
4107 def decode_service_header(self
):
4108 foo
= unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
4111 color
= yellow
if self
.use_color
else None
4112 color_start
= "\033[%dm" % color
if color
else ""
4113 color_end
= "\033[0m" if color
else ""
4114 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
4116 for x
in range(0, self
.LEN
/4):
4120 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
4121 self
.line_number
+= 1