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
)
540 self
.value
= IPv4Address(unpack('>L', self
.data
[4:])[0])
541 self
.value_int
= int(self
.value
)
542 self
.value_int_str
= str(self
.value_int
)
543 # GRE interface uses a 4-byte IP address for this attribute
544 elif self
.length
== 10:
545 (data1
, data2
) = unpack(self
.PACK
, self
.data
[4:])
546 self
.value
= mac_int_to_str(data1
<< 16 | data2
)
547 # GREv6 interface uses a 16-byte IP address for this attribute
548 elif self
.length
== 20:
549 self
.value
= IPv6Address(unpack('>L', self
.data
[16:])[0])
550 self
.value_int
= int(self
.value
)
551 self
.value_int_str
= str(self
.value_int
)
553 raise Exception("Length of MACAddress attribute not supported: %d" % self
.length
)
556 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:])))
560 length
= self
.HEADER_LEN
+ self
.LEN
561 mac_raw
= int(self
.value
.replace('.', '').replace(':', ''), 16)
562 raw
= pack(self
.HEADER_PACK
, length
-2, self
.atype
) + pack(self
.PACK
, mac_raw
>> 16, mac_raw
& 0x0000FFFF)
563 raw
= self
.pad(length
, raw
)
566 def dump_lines(self
, dump_buffer
, line_number
, color
):
567 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
568 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8], self
.value
))
570 if len(self
.data
) >= 12:
571 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[8:12]))
576 class AttributeMplsLabel(Attribute
):
578 def __init__(self
, atype
, string
, family
, logger
):
579 Attribute
.__init
__(self
, atype
, string
, logger
)
580 self
.value_int
= None
581 self
.value_int_str
= None
585 def decode(self
, parent_msg
, data
):
586 self
.decode_length_type(data
)
589 (label_high
, label_low_tc_s
, self
.ttl
) = unpack(self
.PACK
, self
.data
[4:])
590 self
.s_bit
= label_low_tc_s
& 0x1
591 self
.traffic_class
= ((label_low_tc_s
& 0xf) >> 1)
592 self
.label
= (label_high
<< 4) |
(label_low_tc_s
>> 4)
593 self
.value
= self
.label
594 self
.value_int
= self
.value
595 self
.value_int_str
= str(self
.value_int
)
599 self
.value_int
= None
600 self
.value_int_str
= None
601 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:])))
604 def dump_lines(self
, dump_buffer
, line_number
, color
):
605 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
606 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8],
607 'label %s, TC %s, bottom-of-stack %s, TTL %d' %
608 (self
.label
, self
.traffic_class
, self
.s_bit
, self
.ttl
)))
614 class AttributeGeneric(Attribute
):
616 def __init__(self
, atype
, string
, family
, logger
):
617 Attribute
.__init
__(self
, atype
, string
, logger
)
621 def decode(self
, parent_msg
, data
):
622 self
.decode_length_type(data
)
623 wordcount
= (self
.attr_end
- 4)/4
624 self
.PACK
= '=%dL' % wordcount
625 self
.LEN
= calcsize(self
.PACK
)
628 self
.value
= ''.join(map(str, unpack(self
.PACK
, self
.data
[4:])))
630 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:])))
634 class AttributeOneByteValue(AttributeGeneric
):
636 def __init__(self
, atype
, string
, family
, logger
):
637 AttributeGeneric
.__init
__(self
, atype
, string
, family
, logger
)
639 self
.LEN
= calcsize(self
.PACK
)
641 def decode(self
, parent_msg
, data
):
642 self
.decode_length_type(data
)
643 assert self
.attr_end
== 8, "Attribute length for %s must be 8, it is %d" % (self
, self
.attr_end
)
646 self
.value
= int(unpack(self
.PACK
, self
.data
[4:8])[0])
648 self
.log
.error("%s unpack of %s failed, data 0x%s" % (self
, self
.PACK
, hexlify(self
.data
[4:5])))
652 length
= self
.HEADER_LEN
+ self
.LEN
653 raw
= pack(self
.HEADER_PACK
, length
-3, self
.atype
) + pack(self
.PACK
, self
.value
)
654 raw
= self
.pad(length
, raw
)
657 def dump_lines(self
, dump_buffer
, line_number
, color
):
658 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
659 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[4:8], self
.value
))
660 return line_number
+ 1
663 class AttributeIFLA_AF_SPEC(Attribute
):
665 value will be a dictionary such as:
667 Link.IFLA_BRIDGE_FLAGS: flags,
668 Link.IFLA_BRIDGE_VLAN_INFO: (vflags, vlanid)
671 def __init__(self
, atype
, string
, family
, logger
):
672 Attribute
.__init
__(self
, atype
, string
, logger
)
676 pack_layout
= [self
.HEADER_PACK
]
677 payload
= [0, self
.atype | NLA_F_NESTED
]
678 attr_length_index
= 0
680 # For now this assumes that all data will be packed in the native endian
681 # order (=). If a field is added that needs to be packed via network
682 # order (>) then some smarts will need to be added to split the pack_layout
683 # string at the >, split the payload and make the needed pack() calls.
685 # Until we cross that bridge though we will keep things nice and simple and
686 # pack everything via a single pack() call.
689 for (sub_attr_type
, sub_attr_value
) in self
.value
.iteritems():
691 if sub_attr_type
== Link
.IFLA_BRIDGE_FLAGS
:
692 sub_attr_to_add
.append((sub_attr_type
, sub_attr_value
))
694 elif sub_attr_type
== Link
.IFLA_BRIDGE_VLAN_INFO
:
695 for (vlan_flag
, vlan_id
) in sub_attr_value
:
696 sub_attr_to_add
.append((sub_attr_type
, (vlan_flag
, vlan_id
)))
699 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_AF_SPEC sub-attribute type %d' % sub_attr_type
)
702 for (sub_attr_type
, sub_attr_value
) in sub_attr_to_add
:
703 sub_attr_pack_layout
= ['=', 'HH']
704 sub_attr_payload
= [0, sub_attr_type
]
705 sub_attr_length_index
= 0
707 if sub_attr_type
== Link
.IFLA_BRIDGE_FLAGS
:
708 sub_attr_pack_layout
.append('H')
709 sub_attr_payload
.append(sub_attr_value
)
711 elif sub_attr_type
== Link
.IFLA_BRIDGE_VLAN_INFO
:
712 sub_attr_pack_layout
.append('HH')
713 sub_attr_payload
.append(sub_attr_value
[0])
714 sub_attr_payload
.append(sub_attr_value
[1])
716 sub_attr_length
= calcsize(''.join(sub_attr_pack_layout
))
717 sub_attr_payload
[sub_attr_length_index
] = sub_attr_length
720 for x
in xrange(self
.pad_bytes_needed(sub_attr_length
)):
721 sub_attr_pack_layout
.append('x')
723 # The [1:] is to remove the leading = so that when we do the ''.join() later
724 # we do not end up with an = in the middle of the pack layout string. There
725 # will be an = at the beginning via self.HEADER_PACK
726 sub_attr_pack_layout
= sub_attr_pack_layout
[1:]
728 # Now extend the ovarall attribute pack_layout/payload to include this sub-attribute
729 pack_layout
.extend(sub_attr_pack_layout
)
730 payload
.extend(sub_attr_payload
)
732 pack_layout
= ''.join(pack_layout
)
734 # Fill in the length field
735 length
= calcsize(pack_layout
)
736 payload
[attr_length_index
] = length
738 raw
= pack(pack_layout
, *payload
)
739 raw
= self
.pad(length
, raw
)
742 def decode(self
, parent_msg
, data
):
744 value is a dictionary such as:
746 Link.IFLA_BRIDGE_FLAGS: flags,
747 Link.IFLA_BRIDGE_VLAN_INFO: (vflags, vlanid)
751 The encoding of the IFLA_AF_SPEC attribute varies depending on the family
752 used for the request (RTM_GETLINK) message. For AF_UNSPEC the encoding
753 has another level of nesting for each address family with the type encoded
755 af_spec = nla_nest_start(skb, IFLA_AF_SPEC)
757 af = nla_nest_start(skb, af_ops->family)
758 af_ops->fill_link_af(skb, dev, ext_filter_mask)
762 This allows the parser to find the address family by looking at the first
765 Whereas AF_BRIDGE encoding is just:
766 af_spec = nla_nest_start(skb, IFLA_AF_SPEC)
767 br_fill_ifvlaninfo{_compressed}(skb, vg)
770 which means the parser can not use the attribute itself to know the family
771 to which the attribute belongs.
773 /include/uapi/linux/if_link.h
776 * Contains nested attributes for address family specific attributes.
777 * Each address family may create a attribute with the address family
778 * number as type and create its own attribute structure in it.
783 * [IFLA_INET_CONF] = ...,
786 * [IFLA_INET6_FLAGS] = ...,
787 * [IFLA_INET6_CONF] = ...,
793 self
.decode_length_type(data
)
796 # opti for now, since we only support AF_BRIDGE
797 if self
.family
!= AF_BRIDGE
:
803 (sub_attr_length
, sub_attr_type
) = unpack('=HH', data
[:4])
804 sub_attr_end
= padded_length(sub_attr_length
)
806 if not sub_attr_length
:
807 self
.log
.error('parsed a zero length sub-attr')
810 sub_attr_data
= data
[4:sub_attr_end
]
812 if self
.family
== AF_BRIDGE
:
813 if sub_attr_type
== Link
.IFLA_BRIDGE_FLAGS
:
814 self
.value
[Link
.IFLA_BRIDGE_FLAGS
] = unpack("=H", sub_attr_data
[0:2])[0]
816 elif sub_attr_type
== Link
.IFLA_BRIDGE_VLAN_INFO
:
817 if Link
.IFLA_BRIDGE_VLAN_INFO
not in self
.value
:
818 self
.value
[Link
.IFLA_BRIDGE_VLAN_INFO
] = []
819 self
.value
[Link
.IFLA_BRIDGE_VLAN_INFO
].append(tuple(unpack("=HH", sub_attr_data
[0:4])))
822 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_AF_SPEC sub-attribute '
823 'type %s (%d), length %d, padded to %d' %
824 (parent_msg
.get_ifla_bridge_af_spec_to_string(sub_attr_type
),
825 sub_attr_type
, sub_attr_length
, sub_attr_end
))
827 elif self
.family
== AF_UNSPEC
:
828 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_AF_SPEC sub-attribute '
829 'type AF_UNSPEC (0), length %d, padded to %d'
830 % (sub_attr_length
, sub_attr_end
))
833 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_AF_SPEC sub-attribute '
834 'family %d, length %d, padded to %d'
835 % (self
.family
, sub_attr_length
, sub_attr_end
))
837 data
= data
[sub_attr_end
:]
839 def dump_lines(self
, dump_buffer
, line_number
, color
):
840 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
843 next_sub_attr_line
= 0
846 for x
in xrange(1, self
.attr_end
/4):
850 if line_number
== next_sub_attr_line
:
854 sub_attr_line
= False
856 (sub_attr_length
, sub_attr_type
) = unpack('=HH', self
.data
[start
:start
+4])
857 sub_attr_end
= padded_length(sub_attr_length
)
859 next_sub_attr_line
= line_number
+ (sub_attr_end
/4)
861 if sub_attr_end
== sub_attr_length
:
864 padded_to
= ' padded to %d, ' % sub_attr_end
866 if self
.family
== AF_BRIDGE
:
867 extra
= 'Nested Attribute - Length %s (%d)%s Type %s (%d) %s' % \
868 (zfilled_hex(sub_attr_length
, 4), sub_attr_length
,
870 zfilled_hex(sub_attr_type
, 4), sub_attr_type
,
871 Link
.ifla_bridge_af_spec_to_string
.get(sub_attr_type
))
875 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[start
:end
], extra
))
880 def get_pretty_value(self
, obj
=None):
882 if obj
and callable(obj
):
883 return obj(self
.value
)
885 # We do this so we can print a more human readable dictionary
886 # with the names of the nested keys instead of their numbers
889 for (sub_key
, sub_value
) in self
.value
.iteritems():
890 sub_key_pretty
= "(%2d) %s" % (sub_key
, Link
.ifla_bridge_af_spec_to_string
.get(sub_key
))
891 value_pretty
[sub_key_pretty
] = sub_value
897 class AttributeRTA_MULTIPATH(Attribute
):
899 /* RTA_MULTIPATH --- array of struct rtnexthop.
901 * "struct rtnexthop" describes all necessary nexthop information,
902 * i.e. parameters of path to a destination via this nexthop.
904 * At the moment it is impossible to set different prefsrc, mtu, window
905 * and rtt for different paths from multipath.
909 unsigned short rtnh_len;
910 unsigned char rtnh_flags;
911 unsigned char rtnh_hops;
916 def __init__(self
, atype
, string
, family
, logger
):
917 Attribute
.__init
__(self
, atype
, string
, logger
)
921 self
.RTNH_PACK
= '=HBBL' # rtnh_len, flags, hops, ifindex
922 self
.RTNH_LEN
= calcsize(self
.RTNH_PACK
)
928 # Calculate the length
929 if self
.family
== AF_INET
:
930 ip_len
= self
.IPV4_LEN
931 elif self
.family
== AF_INET6
:
932 ip_len
= self
.IPV6_LEN
935 length
= self
.HEADER_LEN
+ ((self
.RTNH_LEN
+ self
.HEADER_LEN
+ ip_len
) * len(self
.value
))
936 raw
= pack(self
.HEADER_PACK
, length
, self
.atype
)
940 rtnh_len
= self
.RTNH_LEN
+ self
.HEADER_LEN
+ ip_len
942 for (nexthop
, rtnh_ifindex
) in self
.value
:
945 raw
+= pack(self
.RTNH_PACK
, rtnh_len
, rtnh_flags
, rtnh_hops
, rtnh_ifindex
)
948 raw
+= pack(self
.HEADER_PACK
, self
.HEADER_LEN
+ ip_len
, Route
.RTA_GATEWAY
)
950 if self
.family
== AF_INET
:
951 raw
+= pack('>L', nexthop
)
952 elif self
.family
== AF_INET6
:
953 raw
+= pack('>QQ', nexthop
>> 64, nexthop
& 0x0000000000000000FFFFFFFFFFFFFFFF)
955 raw
= self
.pad(length
, raw
)
958 def decode(self
, parent_msg
, data
):
959 self
.decode_length_type(data
)
965 (rtnh_len
, rtnh_flags
, rtnh_hops
, rtnh_ifindex
) = unpack(self
.RTNH_PACK
, data
[:self
.RTNH_LEN
])
966 data
= data
[self
.RTNH_LEN
:]
968 (attr_type
, attr_length
) = unpack(self
.HEADER_PACK
, self
.data
[:self
.HEADER_LEN
])
969 data
= data
[self
.HEADER_LEN
:]
971 if self
.family
== AF_INET
:
972 if len(data
) < self
.IPV4_LEN
:
974 nexthop
= IPv4Address(unpack('>L', data
[:self
.IPV4_LEN
])[0])
975 self
.value
.append((nexthop
, rtnh_ifindex
, rtnh_flags
, rtnh_hops
))
977 elif self
.family
== AF_INET6
:
978 if len(data
) < self
.IPV6_LEN
:
980 (data1
, data2
) = unpack('>QQ', data
[:self
.IPV6_LEN
])
981 nexthop
= IPv6Address(data1
<< 64 | data2
)
982 self
.value
.append((nexthop
, rtnh_ifindex
, rtnh_flags
, rtnh_hops
))
984 data
= data
[(rtnh_len
-self
.RTNH_LEN
-self
.HEADER_LEN
):]
986 self
.value
= tuple(self
.value
)
989 class AttributeIFLA_LINKINFO(Attribute
):
991 value is a dictionary such as:
994 Link.IFLA_INFO_KIND : 'vlan',
995 Link.IFLA_INFO_DATA : {
996 Link.IFLA_VLAN_ID : vlanid,
1000 def __init__(self
, atype
, string
, family
, logger
):
1001 Attribute
.__init
__(self
, atype
, string
, logger
)
1004 pack_layout
= [self
.HEADER_PACK
]
1005 payload
= [0, self
.atype | NLA_F_NESTED
]
1006 attr_length_index
= 0
1008 kind
= self
.value
.get(Link
.IFLA_INFO_KIND
)
1009 slave_kind
= self
.value
.get(Link
.IFLA_INFO_SLAVE_KIND
)
1011 if not slave_kind
and kind
not in ('vlan', 'macvlan', 'vxlan', 'bond', 'bridge'):
1012 raise Exception('Unsupported IFLA_INFO_KIND %s' % kind
)
1013 elif not kind
and slave_kind
!= 'bridge':
1014 # only support brport for now.
1015 raise Exception('Unsupported IFLA_INFO_SLAVE_KIND %s' % slave_kind
)
1017 # For now this assumes that all data will be packed in the native endian
1018 # order (=). If a field is added that needs to be packed via network
1019 # order (>) then some smarts will need to be added to split the pack_layout
1020 # string at the >, split the payload and make the needed pack() calls.
1022 # Until we cross that bridge though we will keep things nice and simple and
1023 # pack everything via a single pack() call.
1024 for (sub_attr_type
, sub_attr_value
) in self
.value
.iteritems():
1025 sub_attr_pack_layout
= ['=', 'HH']
1026 sub_attr_payload
= [0, sub_attr_type
]
1027 sub_attr_length_index
= 0
1029 if sub_attr_type
== Link
.IFLA_INFO_KIND
:
1030 sub_attr_pack_layout
.append('%ds' % len(sub_attr_value
))
1031 sub_attr_payload
.append(sub_attr_value
)
1033 elif sub_attr_type
== Link
.IFLA_INFO_DATA
:
1035 sub_attr_payload
= [0, sub_attr_type | NLA_F_NESTED
]
1037 for (info_data_type
, info_data_value
) in sub_attr_value
.iteritems():
1040 if info_data_type
== Link
.IFLA_VLAN_ID
:
1041 sub_attr_pack_layout
.append('HH')
1042 sub_attr_payload
.append(6) # length
1043 sub_attr_payload
.append(info_data_type
)
1046 sub_attr_pack_layout
.append('H')
1047 sub_attr_payload
.append(info_data_value
)
1050 sub_attr_pack_layout
.extend('xx')
1052 elif info_data_type
== Link
.IFLA_VLAN_PROTOCOL
:
1053 sub_attr_pack_layout
.append('HH')
1054 sub_attr_payload
.append(6) # length
1055 sub_attr_payload
.append(info_data_type
)
1058 vlan_protocol
= Link
.ifla_vlan_protocol_dict
.get(info_data_value
)
1059 if not vlan_protocol
:
1060 raise NotImplementedError('vlan protocol %s not implemented' % info_data_value
)
1062 sub_attr_pack_layout
.append('H')
1063 sub_attr_payload
.append(htons(vlan_protocol
))
1066 sub_attr_pack_layout
.extend('xx')
1068 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA vlan sub-attribute type %d' % info_data_type
)
1070 elif kind
== 'macvlan':
1071 if info_data_type
== Link
.IFLA_MACVLAN_MODE
:
1072 sub_attr_pack_layout
.append('HH')
1073 sub_attr_payload
.append(8) # length
1074 sub_attr_payload
.append(info_data_type
)
1077 sub_attr_pack_layout
.append('L')
1078 sub_attr_payload
.append(info_data_value
)
1081 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA macvlan sub-attribute type %d' % info_data_type
)
1083 elif kind
== 'vxlan':
1084 if info_data_type
in (Link
.IFLA_VXLAN_ID
,
1085 Link
.IFLA_VXLAN_LINK
,
1086 Link
.IFLA_VXLAN_AGEING
,
1087 Link
.IFLA_VXLAN_LIMIT
,
1088 Link
.IFLA_VXLAN_PORT_RANGE
):
1089 sub_attr_pack_layout
.append('HH')
1090 sub_attr_payload
.append(8) # length
1091 sub_attr_payload
.append(info_data_type
)
1093 sub_attr_pack_layout
.append('L')
1094 sub_attr_payload
.append(info_data_value
)
1096 elif info_data_type
in (Link
.IFLA_VXLAN_GROUP
,
1097 Link
.IFLA_VXLAN_LOCAL
):
1098 sub_attr_pack_layout
.append('HH')
1099 sub_attr_payload
.append(8) # length
1100 sub_attr_payload
.append(info_data_type
)
1102 sub_attr_pack_layout
.append('L')
1104 reorder
= unpack('<L', IPv4Address(info_data_value
).packed
)[0]
1105 sub_attr_payload
.append(IPv4Address(reorder
))
1107 elif info_data_type
in (Link
.IFLA_VXLAN_PORT
,):
1108 sub_attr_pack_layout
.append('HH')
1109 sub_attr_payload
.append(6)
1110 sub_attr_payload
.append(info_data_type
)
1112 sub_attr_pack_layout
.append('H')
1115 swaped
= pack(">H", info_data_value
)
1116 sub_attr_payload
.append(unpack("<H", swaped
)[0])
1118 sub_attr_pack_layout
.extend('xx')
1120 elif info_data_type
in (Link
.IFLA_VXLAN_TTL
,
1121 Link
.IFLA_VXLAN_TOS
,
1122 Link
.IFLA_VXLAN_LEARNING
,
1123 Link
.IFLA_VXLAN_PROXY
,
1124 Link
.IFLA_VXLAN_RSC
,
1125 Link
.IFLA_VXLAN_L2MISS
,
1126 Link
.IFLA_VXLAN_L3MISS
,
1127 Link
.IFLA_VXLAN_UDP_CSUM
,
1128 Link
.IFLA_VXLAN_UDP_ZERO_CSUM6_TX
,
1129 Link
.IFLA_VXLAN_UDP_ZERO_CSUM6_RX
,
1130 Link
.IFLA_VXLAN_REMCSUM_TX
,
1131 Link
.IFLA_VXLAN_REMCSUM_RX
,
1132 Link
.IFLA_VXLAN_REPLICATION_TYPE
):
1133 sub_attr_pack_layout
.append('HH')
1134 sub_attr_payload
.append(6)
1135 sub_attr_payload
.append(info_data_type
)
1137 sub_attr_pack_layout
.append('B')
1138 sub_attr_payload
.append(info_data_value
)
1139 sub_attr_pack_layout
.extend('xxx')
1142 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA vxlan sub-attribute type %d' % info_data_type
)
1144 elif kind
== 'bond':
1145 if info_data_type
in (Link
.IFLA_BOND_AD_ACTOR_SYSTEM
, ):
1146 sub_attr_pack_layout
.append('HH')
1147 sub_attr_payload
.append(10) # length
1148 sub_attr_payload
.append(info_data_type
)
1150 sub_attr_pack_layout
.append('6B')
1151 for mbyte
in info_data_value
.replace('.', ' ').replace(':', ' ').split():
1152 sub_attr_payload
.append(int(mbyte
, 16))
1153 sub_attr_pack_layout
.extend('xx')
1155 elif info_data_type
== Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
:
1156 sub_attr_pack_layout
.append('HH')
1157 sub_attr_payload
.append(6) # length
1158 sub_attr_payload
.append(info_data_type
)
1161 sub_attr_pack_layout
.append('H')
1162 sub_attr_payload
.append(int(info_data_value
))
1165 sub_attr_pack_layout
.extend('xx')
1167 elif info_data_type
== Link
.IFLA_BOND_NUM_PEER_NOTIF
:
1168 sub_attr_pack_layout
.append('HH')
1169 sub_attr_payload
.append(5) # length
1170 sub_attr_payload
.append(info_data_type
)
1173 sub_attr_pack_layout
.append('B')
1174 sub_attr_payload
.append(int(info_data_value
))
1177 sub_attr_pack_layout
.extend('xxx')
1180 elif info_data_type
in (Link
.IFLA_BOND_AD_LACP_RATE
,
1181 Link
.IFLA_BOND_AD_LACP_BYPASS
,
1182 Link
.IFLA_BOND_USE_CARRIER
):
1183 # converts yes/no/on/off/0/1 strings to boolean value
1184 bool_value
= self
.get_bool_value(info_data_value
)
1186 sub_attr_pack_layout
.append('HH')
1187 sub_attr_payload
.append(5) # length
1188 sub_attr_payload
.append(info_data_type
)
1191 sub_attr_pack_layout
.append('B')
1192 sub_attr_payload
.append(bool_value
)
1195 sub_attr_pack_layout
.extend('xxx')
1197 elif info_data_type
== Link
.IFLA_BOND_XMIT_HASH_POLICY
:
1198 index
= self
.get_index(Link
.ifla_bond_xmit_hash_policy_tbl
,
1199 'bond xmit hash policy',
1202 sub_attr_pack_layout
.append('HH')
1203 sub_attr_payload
.append(5) # length
1204 sub_attr_payload
.append(info_data_type
)
1207 sub_attr_pack_layout
.append('B')
1208 sub_attr_payload
.append(index
)
1211 sub_attr_pack_layout
.extend('xxx')
1213 elif info_data_type
== Link
.IFLA_BOND_MODE
:
1214 index
= self
.get_index(Link
.ifla_bond_mode_tbl
,
1218 sub_attr_pack_layout
.append('HH')
1219 sub_attr_payload
.append(5) # length
1220 sub_attr_payload
.append(info_data_type
)
1223 sub_attr_pack_layout
.append('B')
1224 sub_attr_payload
.append(index
)
1227 sub_attr_pack_layout
.extend('xxx')
1229 elif info_data_type
in (Link
.IFLA_BOND_MIIMON
,
1230 Link
.IFLA_BOND_UPDELAY
,
1231 Link
.IFLA_BOND_DOWNDELAY
,
1232 Link
.IFLA_BOND_MIN_LINKS
):
1233 sub_attr_pack_layout
.append('HH')
1234 sub_attr_payload
.append(8) # length
1235 sub_attr_payload
.append(info_data_type
)
1237 sub_attr_pack_layout
.append('L')
1238 sub_attr_payload
.append(int(info_data_value
))
1241 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA bond sub-attribute type %d' % info_data_type
)
1243 elif kind
== 'bridge':
1244 if info_data_type
== Link
.IFLA_BR_VLAN_PROTOCOL
:
1245 sub_attr_pack_layout
.append('HH')
1246 sub_attr_payload
.append(6) # length
1247 sub_attr_payload
.append(info_data_type
)
1250 vlan_protocol
= Link
.ifla_vlan_protocol_dict
.get(info_data_value
)
1251 if not vlan_protocol
:
1252 raise NotImplementedError('vlan protocol %s not implemented' % info_data_value
)
1254 sub_attr_pack_layout
.append('H')
1255 sub_attr_payload
.append(htons(vlan_protocol
))
1258 sub_attr_pack_layout
.extend('xx')
1261 elif info_data_type
in (Link
.IFLA_BR_VLAN_FILTERING
,
1262 Link
.IFLA_BR_TOPOLOGY_CHANGE
,
1263 Link
.IFLA_BR_TOPOLOGY_CHANGE_DETECTED
,
1264 Link
.IFLA_BR_MCAST_ROUTER
,
1265 Link
.IFLA_BR_MCAST_SNOOPING
,
1266 Link
.IFLA_BR_MCAST_QUERY_USE_IFADDR
,
1267 Link
.IFLA_BR_MCAST_QUERIER
,
1268 Link
.IFLA_BR_NF_CALL_IPTABLES
,
1269 Link
.IFLA_BR_NF_CALL_IP6TABLES
,
1270 Link
.IFLA_BR_NF_CALL_ARPTABLES
,
1271 Link
.IFLA_BR_VLAN_STATS_ENABLED
,
1272 Link
.IFLA_BR_MCAST_STATS_ENABLED
,
1273 Link
.IFLA_BR_MCAST_IGMP_VERSION
,
1274 Link
.IFLA_BR_MCAST_MLD_VERSION
):
1275 sub_attr_pack_layout
.append('HH')
1276 sub_attr_payload
.append(5) # length
1277 sub_attr_payload
.append(info_data_type
)
1280 sub_attr_pack_layout
.append('B')
1281 sub_attr_payload
.append(int(info_data_value
))
1284 sub_attr_pack_layout
.extend('xxx')
1287 elif info_data_type
in (Link
.IFLA_BR_PRIORITY
,
1288 Link
.IFLA_BR_GROUP_FWD_MASK
,
1289 Link
.IFLA_BR_ROOT_PORT
,
1290 Link
.IFLA_BR_VLAN_DEFAULT_PVID
):
1291 sub_attr_pack_layout
.append('HH')
1292 sub_attr_payload
.append(6) # length
1293 sub_attr_payload
.append(info_data_type
)
1296 sub_attr_pack_layout
.append('H')
1297 sub_attr_payload
.append(int(info_data_value
))
1300 sub_attr_pack_layout
.extend('xx')
1303 elif info_data_type
in (Link
.IFLA_BR_FORWARD_DELAY
,
1304 Link
.IFLA_BR_HELLO_TIME
,
1305 Link
.IFLA_BR_MAX_AGE
,
1306 Link
.IFLA_BR_AGEING_TIME
,
1307 Link
.IFLA_BR_STP_STATE
,
1308 Link
.IFLA_BR_ROOT_PATH_COST
,
1309 Link
.IFLA_BR_MCAST_QUERIER
,
1310 Link
.IFLA_BR_MCAST_HASH_ELASTICITY
,
1311 Link
.IFLA_BR_MCAST_HASH_MAX
,
1312 Link
.IFLA_BR_MCAST_LAST_MEMBER_CNT
,
1313 Link
.IFLA_BR_MCAST_STARTUP_QUERY_CNT
):
1314 sub_attr_pack_layout
.append('HH')
1315 sub_attr_payload
.append(8) # length
1316 sub_attr_payload
.append(info_data_type
)
1318 sub_attr_pack_layout
.append('L')
1319 sub_attr_payload
.append(int(info_data_value
))
1322 elif info_data_type
in (Link
.IFLA_BR_MCAST_LAST_MEMBER_INTVL
,
1323 Link
.IFLA_BR_MCAST_MEMBERSHIP_INTVL
,
1324 Link
.IFLA_BR_MCAST_QUERIER_INTVL
,
1325 Link
.IFLA_BR_MCAST_QUERY_INTVL
,
1326 Link
.IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
,
1327 Link
.IFLA_BR_MCAST_STARTUP_QUERY_INTVL
):
1328 sub_attr_pack_layout
.append('HH')
1329 sub_attr_payload
.append(12) # length
1330 sub_attr_payload
.append(info_data_type
)
1332 sub_attr_pack_layout
.append('Q')
1333 sub_attr_payload
.append(int(info_data_value
))
1336 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_DATA bridge sub-attribute type %d' % info_data_type
)
1338 elif sub_attr_type
== Link
.IFLA_INFO_SLAVE_DATA
:
1340 sub_attr_payload
= [0, sub_attr_type | NLA_F_NESTED
]
1342 for (info_slave_data_type
, info_slave_data_value
) in sub_attr_value
.iteritems():
1344 if slave_kind
== 'bridge':
1347 if info_slave_data_type
in (Link
.IFLA_BRPORT_STATE
,
1348 Link
.IFLA_BRPORT_MODE
,
1349 Link
.IFLA_BRPORT_GUARD
,
1350 Link
.IFLA_BRPORT_PROTECT
,
1351 Link
.IFLA_BRPORT_FAST_LEAVE
,
1352 Link
.IFLA_BRPORT_LEARNING
,
1353 Link
.IFLA_BRPORT_UNICAST_FLOOD
,
1354 Link
.IFLA_BRPORT_PROXYARP
,
1355 Link
.IFLA_BRPORT_LEARNING_SYNC
,
1356 Link
.IFLA_BRPORT_PROXYARP_WIFI
,
1357 Link
.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
,
1358 Link
.IFLA_BRPORT_CONFIG_PENDING
,
1359 Link
.IFLA_BRPORT_MULTICAST_ROUTER
,
1360 Link
.IFLA_BRPORT_MCAST_FLOOD
,
1361 Link
.IFLA_BRPORT_MCAST_TO_UCAST
,
1362 Link
.IFLA_BRPORT_VLAN_TUNNEL
,
1363 Link
.IFLA_BRPORT_BCAST_FLOOD
,
1364 Link
.IFLA_BRPORT_PEER_LINK
,
1365 Link
.IFLA_BRPORT_DUAL_LINK
,
1366 Link
.IFLA_BRPORT_ARP_SUPPRESS
,
1367 Link
.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
):
1368 sub_attr_pack_layout
.append('HH')
1369 sub_attr_payload
.append(5) # length
1370 sub_attr_payload
.append(info_slave_data_type
)
1373 sub_attr_pack_layout
.append('B')
1374 sub_attr_payload
.append(int(info_slave_data_value
))
1377 sub_attr_pack_layout
.extend('xxx')
1380 elif info_slave_data_type
in (Link
.IFLA_BRPORT_PRIORITY
,
1381 Link
.IFLA_BRPORT_DESIGNATED_PORT
,
1382 Link
.IFLA_BRPORT_DESIGNATED_COST
,
1383 Link
.IFLA_BRPORT_ID
,
1384 Link
.IFLA_BRPORT_NO
,
1385 Link
.IFLA_BRPORT_GROUP_FWD_MASK
,
1386 Link
.IFLA_BRPORT_GROUP_FWD_MASKHI
):
1387 sub_attr_pack_layout
.append('HH')
1388 sub_attr_payload
.append(6) # length
1389 sub_attr_payload
.append(info_slave_data_type
)
1392 sub_attr_pack_layout
.append('H')
1393 sub_attr_payload
.append(int(info_slave_data_value
))
1396 sub_attr_pack_layout
.extend('xx')
1399 elif info_slave_data_type
== Link
.IFLA_BRPORT_COST
:
1400 sub_attr_pack_layout
.append('HH')
1401 sub_attr_payload
.append(8) # length
1402 sub_attr_payload
.append(info_slave_data_type
)
1404 sub_attr_pack_layout
.append('L')
1405 sub_attr_payload
.append(int(info_slave_data_value
))
1408 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_INFO_SLAVE_DATA bond sub-attribute type %d' % info_slave_data_type
)
1411 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_LINKINFO kind %s' % slave_kind
)
1414 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_LINKINFO sub-attribute type %d' % sub_attr_type
)
1417 sub_attr_length
= calcsize(''.join(sub_attr_pack_layout
))
1418 sub_attr_payload
[sub_attr_length_index
] = sub_attr_length
1421 for x
in xrange(self
.pad_bytes_needed(sub_attr_length
)):
1422 sub_attr_pack_layout
.append('x')
1424 # The [1:] is to remove the leading = so that when we do the ''.join() later
1425 # we do not end up with an = in the middle of the pack layout string. There
1426 # will be an = at the beginning via self.HEADER_PACK
1427 sub_attr_pack_layout
= sub_attr_pack_layout
[1:]
1429 # Now extend the ovarall attribute pack_layout/payload to include this sub-attribute
1430 pack_layout
.extend(sub_attr_pack_layout
)
1431 payload
.extend(sub_attr_payload
)
1433 pack_layout
= ''.join(pack_layout
)
1435 # Fill in the length field
1436 length
= calcsize(pack_layout
)
1437 payload
[attr_length_index
] = length
1439 raw
= pack(pack_layout
, *payload
)
1440 raw
= self
.pad(length
, raw
)
1443 def get_bool_value(self
, value
, default
=None):
1445 return value_to_bool_dict
[value
]
1447 self
.log
.debug('%s: unsupported boolean value' % value
)
1450 def get_index(self
, tbl
, attr
, value
, default
=None):
1454 self
.log
.debug('unsupported %s value %s (%s)' % (attr
, value
, tbl
.keys()))
1457 def decode(self
, parent_msg
, data
):
1459 value is a dictionary such as:
1462 Link.IFLA_INFO_KIND : 'vlan',
1463 Link.IFLA_INFO_DATA : {
1464 Link.IFLA_VLAN_ID : vlanid,
1468 self
.decode_length_type(data
)
1471 data
= self
.data
[4:]
1473 # IFLA_MACVLAN_MODE and IFLA_VLAN_ID both have a value of 1 and both are
1474 # valid IFLA_INFO_DATA entries :( The sender must TX IFLA_INFO_KIND
1475 # first in order for us to know if "1" is IFLA_MACVLAN_MODE vs IFLA_VLAN_ID.
1478 (sub_attr_length
, sub_attr_type
) = unpack('=HH', data
[:4])
1479 sub_attr_end
= padded_length(sub_attr_length
)
1481 if not sub_attr_length
:
1482 self
.log
.error('parsed a zero length sub-attr')
1485 if sub_attr_type
in (Link
.IFLA_INFO_KIND
, Link
.IFLA_INFO_SLAVE_KIND
):
1486 self
.value
[sub_attr_type
] = remove_trailing_null(unpack('%ds' % (sub_attr_length
- 4), data
[4:sub_attr_length
])[0])
1488 elif sub_attr_type
== Link
.IFLA_INFO_SLAVE_DATA
:
1489 sub_attr_data
= data
[4:sub_attr_end
]
1491 ifla_info_slave_data
= dict()
1492 ifla_info_slave_kind
= self
.value
.get(Link
.IFLA_INFO_SLAVE_KIND
)
1494 if not ifla_info_slave_kind
:
1495 self
.log
.warning('IFLA_INFO_SLAVE_KIND is not known...we cannot parse IFLA_INFO_SLAVE_DATA')
1497 while sub_attr_data
:
1498 (info_data_length
, info_data_type
) = unpack('=HH', sub_attr_data
[:4])
1499 info_data_end
= padded_length(info_data_length
)
1501 if ifla_info_slave_kind
== 'bridge':
1503 if info_data_type
in (Link
.IFLA_BRPORT_STATE
,
1504 Link
.IFLA_BRPORT_MODE
,
1505 Link
.IFLA_BRPORT_GUARD
,
1506 Link
.IFLA_BRPORT_PROTECT
,
1507 Link
.IFLA_BRPORT_FAST_LEAVE
,
1508 Link
.IFLA_BRPORT_LEARNING
,
1509 Link
.IFLA_BRPORT_UNICAST_FLOOD
,
1510 Link
.IFLA_BRPORT_PROXYARP
,
1511 Link
.IFLA_BRPORT_LEARNING_SYNC
,
1512 Link
.IFLA_BRPORT_PROXYARP_WIFI
,
1513 Link
.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
,
1514 Link
.IFLA_BRPORT_CONFIG_PENDING
,
1515 Link
.IFLA_BRPORT_MULTICAST_ROUTER
,
1516 Link
.IFLA_BRPORT_MCAST_FLOOD
,
1517 Link
.IFLA_BRPORT_MCAST_TO_UCAST
,
1518 Link
.IFLA_BRPORT_VLAN_TUNNEL
,
1519 Link
.IFLA_BRPORT_PEER_LINK
,
1520 Link
.IFLA_BRPORT_DUAL_LINK
,
1521 Link
.IFLA_BRPORT_ARP_SUPPRESS
,
1522 Link
.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
):
1523 ifla_info_slave_data
[info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1526 elif info_data_type
in (Link
.IFLA_BRPORT_PRIORITY
,
1527 Link
.IFLA_BRPORT_DESIGNATED_PORT
,
1528 Link
.IFLA_BRPORT_DESIGNATED_COST
,
1529 Link
.IFLA_BRPORT_ID
,
1530 Link
.IFLA_BRPORT_NO
,
1531 Link
.IFLA_BRPORT_GROUP_FWD_MASK
,
1532 Link
.IFLA_BRPORT_GROUP_FWD_MASKHI
):
1533 ifla_info_slave_data
[info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1536 elif info_data_type
== Link
.IFLA_BRPORT_COST
:
1537 ifla_info_slave_data
[info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1539 elif ifla_info_slave_kind
== 'bond':
1542 if info_data_type
in (
1543 Link
.IFLA_BOND_SLAVE_STATE
,
1544 Link
.IFLA_BOND_SLAVE_MII_STATUS
,
1545 Link
.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
,
1546 Link
.IFLA_BOND_SLAVE_AD_RX_BYPASS
,
1548 ifla_info_slave_data
[info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1551 elif info_data_type
in (
1552 Link
.IFLA_BOND_SLAVE_QUEUE_ID
,
1553 Link
.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
1555 ifla_info_slave_data
[info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1558 elif info_data_type
== (
1559 Link
.IFLA_BOND_SLAVE_PERM_HWADDR
,
1560 Link
.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT
1562 ifla_info_slave_data
[info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1564 except Exception as e
:
1565 self
.log
.debug('%s: attribute %s: %s'
1566 % (self
.value
[Link
.IFLA_INFO_SLAVE_KIND
],
1569 sub_attr_data
= sub_attr_data
[info_data_end
:]
1571 self
.value
[Link
.IFLA_INFO_SLAVE_DATA
] = ifla_info_slave_data
1573 elif sub_attr_type
== Link
.IFLA_INFO_DATA
:
1574 sub_attr_data
= data
[4:sub_attr_end
]
1575 self
.value
[Link
.IFLA_INFO_DATA
] = {}
1577 ifla_info_kind
= self
.value
.get(Link
.IFLA_INFO_KIND
)
1578 if not ifla_info_kind
:
1579 self
.log
.warning('IFLA_INFO_KIND is not known...we cannot parse IFLA_INFO_DATA')
1581 while sub_attr_data
:
1582 (info_data_length
, info_data_type
) = unpack('=HH', sub_attr_data
[:4])
1583 info_data_end
= padded_length(info_data_length
)
1585 if ifla_info_kind
== 'vlan':
1586 if info_data_type
== Link
.IFLA_VLAN_ID
:
1587 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1589 elif info_data_type
== Link
.IFLA_VLAN_PROTOCOL
:
1590 hex_value
= '0x%s' % sub_attr_data
[4:6].encode('hex')
1591 vlan_protocol
= Link
.ifla_vlan_protocol_dict
.get(int(hex_value
, base
=16))
1594 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = vlan_protocol
1596 self
.log
.warning('IFLA_VLAN_PROTOCOL: cannot decode vlan protocol %s' % hex_value
)
1599 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND vlan type %s (%d), length %d, padded to %d' %
1600 (parent_msg
.get_ifla_vlan_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1602 elif ifla_info_kind
== 'macvlan':
1603 if info_data_type
== Link
.IFLA_MACVLAN_MODE
:
1604 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1606 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND macvlan type %s (%d), length %d, padded to %d' %
1607 (parent_msg
.get_ifla_macvlan_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1609 elif ifla_info_kind
== 'vxlan':
1612 if info_data_type
in (Link
.IFLA_VXLAN_GROUP
,
1613 Link
.IFLA_VXLAN_LOCAL
):
1614 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = IPv4Address(unpack('>L', sub_attr_data
[4:8])[0])
1617 elif info_data_type
in (Link
.IFLA_VXLAN_ID
,
1618 Link
.IFLA_VXLAN_LINK
,
1619 Link
.IFLA_VXLAN_AGEING
,
1620 Link
.IFLA_VXLAN_LIMIT
,
1621 Link
.IFLA_VXLAN_PORT_RANGE
):
1622 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1625 elif info_data_type
in (Link
.IFLA_VXLAN_PORT
, ):
1626 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('!H', sub_attr_data
[4:6])[0]
1627 # The form '!' is available for those poor souls who claim they can't
1628 # remember whether network byte order is big-endian or little-endian.
1631 elif info_data_type
in (Link
.IFLA_VXLAN_TTL
,
1632 Link
.IFLA_VXLAN_TOS
,
1633 Link
.IFLA_VXLAN_LEARNING
,
1634 Link
.IFLA_VXLAN_PROXY
,
1635 Link
.IFLA_VXLAN_RSC
,
1636 Link
.IFLA_VXLAN_L2MISS
,
1637 Link
.IFLA_VXLAN_L3MISS
,
1638 Link
.IFLA_VXLAN_UDP_CSUM
,
1639 Link
.IFLA_VXLAN_UDP_ZERO_CSUM6_TX
,
1640 Link
.IFLA_VXLAN_UDP_ZERO_CSUM6_RX
,
1641 Link
.IFLA_VXLAN_REMCSUM_TX
,
1642 Link
.IFLA_VXLAN_REMCSUM_RX
,
1643 Link
.IFLA_VXLAN_REPLICATION_TYPE
):
1644 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1647 # sub_attr_end = padded_length(sub_attr_length)
1648 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND vxlan type %s (%d), length %d, padded to %d' %
1649 (parent_msg
.get_ifla_vxlan_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1651 elif ifla_info_kind
== 'bond':
1653 if info_data_type
in (Link
.IFLA_BOND_AD_INFO
, ):
1654 ad_attr_data
= sub_attr_data
[4:info_data_end
]
1655 self
.value
[Link
.IFLA_INFO_DATA
][Link
.IFLA_BOND_AD_INFO
] = {}
1658 (ad_data_length
, ad_data_type
) = unpack('=HH', ad_attr_data
[:4])
1659 ad_data_end
= padded_length(ad_data_length
)
1661 if ad_data_type
in (Link
.IFLA_BOND_AD_INFO_PARTNER_MAC
,):
1662 (data1
, data2
) = unpack('>LHxx', ad_attr_data
[4:12])
1663 self
.value
[Link
.IFLA_INFO_DATA
][Link
.IFLA_BOND_AD_INFO
][ad_data_type
] = mac_int_to_str(data1
<< 16 | data2
)
1665 ad_attr_data
= ad_attr_data
[ad_data_end
:]
1668 elif info_data_type
in (Link
.IFLA_BOND_MODE
,
1669 Link
.IFLA_BOND_USE_CARRIER
,
1670 Link
.IFLA_BOND_AD_LACP_RATE
,
1671 Link
.IFLA_BOND_AD_LACP_BYPASS
,
1672 Link
.IFLA_BOND_XMIT_HASH_POLICY
,
1673 Link
.IFLA_BOND_NUM_PEER_NOTIF
):
1674 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1677 elif info_data_type
== Link
.IFLA_BOND_AD_ACTOR_SYS_PRIO
:
1678 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1681 elif info_data_type
in (Link
.IFLA_BOND_MIIMON
,
1682 Link
.IFLA_BOND_UPDELAY
,
1683 Link
.IFLA_BOND_DOWNDELAY
,
1684 Link
.IFLA_BOND_MIN_LINKS
):
1685 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1688 elif info_data_type
in (Link
.IFLA_BOND_AD_ACTOR_SYSTEM
, ):
1689 (data1
, data2
) = unpack('>LHxx', sub_attr_data
[4:12])
1690 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = mac_int_to_str(data1
<< 16 | data2
)
1693 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND bond type %s (%d), length %d, padded to %d' %
1694 (parent_msg
.get_ifla_bond_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1696 elif ifla_info_kind
== 'bridge':
1698 if info_data_type
in (Link
.IFLA_BR_AGEING_TIME
,
1699 Link
.IFLA_BR_FORWARD_DELAY
,
1700 Link
.IFLA_BR_HELLO_TIME
,
1701 Link
.IFLA_BR_MAX_AGE
,
1702 Link
.IFLA_BR_STP_STATE
,
1703 Link
.IFLA_BR_ROOT_PATH_COST
,
1704 Link
.IFLA_BR_MCAST_HASH_ELASTICITY
,
1705 Link
.IFLA_BR_MCAST_HASH_MAX
,
1706 Link
.IFLA_BR_MCAST_LAST_MEMBER_CNT
,
1707 Link
.IFLA_BR_MCAST_STARTUP_QUERY_CNT
):
1708 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1711 elif info_data_type
in (Link
.IFLA_BR_PRIORITY
,
1712 Link
.IFLA_BR_GROUP_FWD_MASK
,
1713 Link
.IFLA_BR_ROOT_PORT
,
1714 Link
.IFLA_BR_VLAN_DEFAULT_PVID
):
1715 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=H', sub_attr_data
[4:6])[0]
1717 elif info_data_type
== Link
.IFLA_BR_VLAN_PROTOCOL
:
1718 hex_value
= '0x%s' % sub_attr_data
[4:6].encode('hex')
1719 vlan_protocol
= Link
.ifla_vlan_protocol_dict
.get(int(hex_value
, base
=16))
1722 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = vlan_protocol
1724 self
.log
.warning('IFLA_VLAN_PROTOCOL: cannot decode vlan protocol %s' % hex_value
)
1727 elif info_data_type
in (Link
.IFLA_BR_MCAST_MEMBERSHIP_INTVL
,
1728 Link
.IFLA_BR_MCAST_QUERIER_INTVL
,
1729 Link
.IFLA_BR_MCAST_LAST_MEMBER_INTVL
,
1730 Link
.IFLA_BR_MCAST_MEMBERSHIP_INTVL
,
1731 Link
.IFLA_BR_MCAST_QUERIER_INTVL
,
1732 Link
.IFLA_BR_MCAST_QUERY_INTVL
,
1733 Link
.IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
,
1734 Link
.IFLA_BR_MCAST_STARTUP_QUERY_INTVL
):
1735 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=Q', sub_attr_data
[4:12])[0]
1738 elif info_data_type
in (Link
.IFLA_BR_VLAN_FILTERING
,
1739 Link
.IFLA_BR_TOPOLOGY_CHANGE
,
1740 Link
.IFLA_BR_TOPOLOGY_CHANGE_DETECTED
,
1741 Link
.IFLA_BR_MCAST_ROUTER
,
1742 Link
.IFLA_BR_MCAST_SNOOPING
,
1743 Link
.IFLA_BR_MCAST_QUERY_USE_IFADDR
,
1744 Link
.IFLA_BR_MCAST_QUERIER
,
1745 Link
.IFLA_BR_NF_CALL_IPTABLES
,
1746 Link
.IFLA_BR_NF_CALL_IP6TABLES
,
1747 Link
.IFLA_BR_NF_CALL_ARPTABLES
,
1748 Link
.IFLA_BR_VLAN_STATS_ENABLED
,
1749 Link
.IFLA_BR_MCAST_STATS_ENABLED
,
1750 Link
.IFLA_BR_MCAST_IGMP_VERSION
,
1751 Link
.IFLA_BR_MCAST_MLD_VERSION
):
1752 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=B', sub_attr_data
[4])[0]
1754 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_INFO_KIND bridge type %s (%d), length %d, padded to %d' %
1755 (parent_msg
.get_ifla_br_string(info_data_type
), info_data_type
, info_data_length
, info_data_end
))
1757 elif ifla_info_kind
== 'vrf':
1759 if info_data_type
in (Link
.IFLA_VRF_TABLE
,):
1760 self
.value
[Link
.IFLA_INFO_DATA
][info_data_type
] = unpack('=L', sub_attr_data
[4:8])[0]
1764 self
.log
.log(SYSLOG_EXTRA_DEBUG
, "Add support for decoding IFLA_INFO_KIND %s (%d), length %d, padded to %d" %
1765 (ifla_info_kind
, info_data_type
, info_data_length
, info_data_end
))
1767 except Exception as e
:
1768 self
.log
.debug('%s: attribute %s: %s'
1769 % (self
.value
[Link
.IFLA_INFO_KIND
],
1772 sub_attr_data
= sub_attr_data
[info_data_end
:]
1775 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_LINKINFO sub-attribute type %s (%d), length %d, padded to %d' %
1776 (parent_msg
.get_ifla_info_string(sub_attr_type
), sub_attr_type
, sub_attr_length
, sub_attr_end
))
1778 data
= data
[sub_attr_end
:]
1780 # self.log.info('IFLA_LINKINFO values %s' % pformat(self.value))
1782 def dump_lines(self
, dump_buffer
, line_number
, color
):
1783 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
1786 next_sub_attr_line
= 0
1787 sub_attr_line
= True
1789 for x
in xrange(1, self
.attr_end
/4):
1793 if line_number
== next_sub_attr_line
:
1794 sub_attr_line
= True
1797 sub_attr_line
= False
1799 (sub_attr_length
, sub_attr_type
) = unpack('=HH', self
.data
[start
:start
+4])
1800 sub_attr_end
= padded_length(sub_attr_length
)
1802 next_sub_attr_line
= line_number
+ (sub_attr_end
/4)
1804 if sub_attr_end
== sub_attr_length
:
1807 padded_to
= ' padded to %d, ' % sub_attr_end
1809 extra
= 'Nested Attribute - Length %s (%d)%s Type %s (%d) %s' % \
1810 (zfilled_hex(sub_attr_length
, 4), sub_attr_length
,
1812 zfilled_hex(sub_attr_type
, 4), sub_attr_type
,
1813 Link
.ifla_info_to_string
.get(sub_attr_type
))
1817 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[start
:end
], extra
))
1822 def get_pretty_value(self
, obj
=None):
1824 if obj
and callable(obj
):
1825 return obj(self
.value
)
1827 value_pretty
= self
.value
1828 ifla_info_kind
= self
.value
.get(Link
.IFLA_INFO_KIND
)
1829 ifla_info_slave_kind
= self
.value
.get(Link
.IFLA_INFO_SLAVE_KIND
)
1833 # We do this so we can print a more human readable dictionary
1834 # with the names of the nested keys instead of their numbers
1836 # Most of these are placeholders...we need to add support
1837 # for more human readable dictionaries for bond, bridge, etc
1838 kind_dict
[Link
.IFLA_INFO_DATA
] = {
1839 'bond': Link
.ifla_bond_to_string
,
1840 'vlan': Link
.ifla_vlan_to_string
,
1841 'vxlan': Link
.ifla_vxlan_to_string
,
1842 'bridge': Link
.ifla_br_to_string
,
1843 'macvlan': Link
.ifla_macvlan_to_string
1844 }.get(ifla_info_kind
, {})
1846 kind_dict
[Link
.IFLA_INFO_SLAVE_DATA
] = {
1847 'bridge': Link
.ifla_brport_to_string
,
1848 'bond': Link
.ifla_bond_slave_to_string
1849 }.get(ifla_info_slave_kind
, {})
1851 if ifla_info_kind
or ifla_info_slave_kind
:
1854 for (sub_key
, sub_value
) in self
.value
.iteritems():
1855 sub_key_pretty
= "(%2d) %s" % (sub_key
, Link
.ifla_info_to_string
.get(sub_key
, 'UNKNOWN'))
1856 sub_value_pretty
= sub_value
1858 if sub_key
in (Link
.IFLA_INFO_DATA
, Link
.IFLA_INFO_SLAVE_DATA
):
1859 kind_to_string_dict
= kind_dict
.get(sub_key
, {})
1860 sub_value_pretty
= {}
1862 for (sub_sub_key
, sub_sub_value
) in sub_value
.iteritems():
1863 sub_sub_key_pretty
= "(%2d) %s" % (sub_sub_key
, kind_to_string_dict
.get(sub_sub_key
, 'UNKNOWN'))
1864 sub_value_pretty
[sub_sub_key_pretty
] = sub_sub_value
1866 value_pretty
[sub_key_pretty
] = sub_value_pretty
1871 class AttributeIFLA_PROTINFO(Attribute
):
1873 IFLA_PROTINFO nested attributes.
1875 def __init__(self
, atype
, string
, family
, logger
):
1876 Attribute
.__init
__(self
, atype
, string
, logger
)
1877 self
.family
= family
1880 pack_layout
= [self
.HEADER_PACK
]
1881 payload
= [0, self
.atype | NLA_F_NESTED
]
1882 attr_length_index
= 0
1884 if self
.family
not in (AF_BRIDGE
,):
1885 raise Exception('Unsupported IFLA_PROTINFO family %d' % self
.family
)
1887 # For now this assumes that all data will be packed in the native endian
1888 # order (=). If a field is added that needs to be packed via network
1889 # order (>) then some smarts will need to be added to split the pack_layout
1890 # string at the >, split the payload and make the needed pack() calls.
1892 # Until we cross that bridge though we will keep things nice and simple and
1893 # pack everything via a single pack() call.
1894 for (sub_attr_type
, sub_attr_value
) in self
.value
.iteritems():
1895 sub_attr_pack_layout
= ['=', 'HH']
1896 sub_attr_payload
= [0, sub_attr_type
]
1897 sub_attr_length_index
= 0
1899 if self
.family
== AF_BRIDGE
:
1901 if sub_attr_type
in (Link
.IFLA_BRPORT_STATE
,
1902 Link
.IFLA_BRPORT_MODE
,
1903 Link
.IFLA_BRPORT_GUARD
,
1904 Link
.IFLA_BRPORT_PROTECT
,
1905 Link
.IFLA_BRPORT_FAST_LEAVE
,
1906 Link
.IFLA_BRPORT_LEARNING
,
1907 Link
.IFLA_BRPORT_UNICAST_FLOOD
,
1908 Link
.IFLA_BRPORT_PROXYARP
,
1909 Link
.IFLA_BRPORT_LEARNING_SYNC
,
1910 Link
.IFLA_BRPORT_PROXYARP_WIFI
,
1911 Link
.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
,
1912 Link
.IFLA_BRPORT_CONFIG_PENDING
,
1913 Link
.IFLA_BRPORT_FLUSH
,
1914 Link
.IFLA_BRPORT_MULTICAST_ROUTER
,
1915 Link
.IFLA_BRPORT_PEER_LINK
,
1916 Link
.IFLA_BRPORT_DUAL_LINK
,
1917 Link
.IFLA_BRPORT_ARP_SUPPRESS
,
1918 Link
.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
):
1919 sub_attr_pack_layout
.append('B')
1920 sub_attr_payload
.append(sub_attr_value
)
1921 sub_attr_pack_layout
.extend('xxx')
1924 elif sub_attr_type
in (Link
.IFLA_BRPORT_PRIORITY
,
1925 Link
.IFLA_BRPORT_DESIGNATED_PORT
,
1926 Link
.IFLA_BRPORT_DESIGNATED_COST
,
1927 Link
.IFLA_BRPORT_ID
,
1928 Link
.IFLA_BRPORT_NO
):
1929 sub_attr_pack_layout
.append('H')
1930 sub_attr_payload
.append(sub_attr_value
)
1931 sub_attr_pack_layout
.extend('xx')
1934 elif sub_attr_type
in (Link
.IFLA_BRPORT_COST
,):
1935 sub_attr_pack_layout
.append('L')
1936 sub_attr_payload
.append(sub_attr_value
)
1939 elif sub_attr_type
in (Link
.IFLA_BRPORT_MESSAGE_AGE_TIMER
,
1940 Link
.IFLA_BRPORT_FORWARD_DELAY_TIMER
,
1941 Link
.IFLA_BRPORT_HOLD_TIMER
):
1942 sub_attr_pack_layout
.append('Q')
1943 sub_attr_payload
.append(sub_attr_value
)
1946 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for encoding IFLA_PROTINFO sub-attribute type %d' % sub_attr_type
)
1948 sub_attr_length
= calcsize(''.join(sub_attr_pack_layout
))
1949 sub_attr_payload
[sub_attr_length_index
] = sub_attr_length
1952 for x
in xrange(self
.pad_bytes_needed(sub_attr_length
)):
1953 sub_attr_pack_layout
.append('x')
1955 # The [1:] is to remove the leading = so that when we do the ''.join() later
1956 # we do not end up with an = in the middle of the pack layout string. There
1957 # will be an = at the beginning via self.HEADER_PACK
1958 sub_attr_pack_layout
= sub_attr_pack_layout
[1:]
1960 # Now extend the ovarall attribute pack_layout/payload to include this sub-attribute
1961 pack_layout
.extend(sub_attr_pack_layout
)
1962 payload
.extend(sub_attr_payload
)
1964 pack_layout
= ''.join(pack_layout
)
1966 # Fill in the length field
1967 length
= calcsize(pack_layout
)
1968 payload
[attr_length_index
] = length
1970 raw
= pack(pack_layout
, *payload
)
1971 raw
= self
.pad(length
, raw
)
1974 def decode(self
, parent_msg
, data
):
1976 value is a dictionary such as:
1978 Link.IFLA_BRPORT_STATE : 3,
1979 Link.IFLA_BRPORT_PRIORITY : 8
1980 Link.IFLA_BRPORT_COST : 2
1984 self
.decode_length_type(data
)
1987 data
= self
.data
[4:]
1990 (sub_attr_length
, sub_attr_type
) = unpack('=HH', data
[:4])
1991 sub_attr_end
= padded_length(sub_attr_length
)
1993 if not sub_attr_length
:
1994 self
.log
.error('parsed a zero length sub-attr')
1997 if self
.family
== AF_BRIDGE
:
2000 if sub_attr_type
in (Link
.IFLA_BRPORT_STATE
,
2001 Link
.IFLA_BRPORT_MODE
,
2002 Link
.IFLA_BRPORT_GUARD
,
2003 Link
.IFLA_BRPORT_PROTECT
,
2004 Link
.IFLA_BRPORT_FAST_LEAVE
,
2005 Link
.IFLA_BRPORT_LEARNING
,
2006 Link
.IFLA_BRPORT_UNICAST_FLOOD
,
2007 Link
.IFLA_BRPORT_PROXYARP
,
2008 Link
.IFLA_BRPORT_LEARNING_SYNC
,
2009 Link
.IFLA_BRPORT_PROXYARP_WIFI
,
2010 Link
.IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
,
2011 Link
.IFLA_BRPORT_CONFIG_PENDING
,
2012 Link
.IFLA_BRPORT_FLUSH
,
2013 Link
.IFLA_BRPORT_MULTICAST_ROUTER
,
2014 Link
.IFLA_BRPORT_PEER_LINK
,
2015 Link
.IFLA_BRPORT_DUAL_LINK
,
2016 Link
.IFLA_BRPORT_ARP_SUPPRESS
,
2017 Link
.IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
):
2018 self
.value
[sub_attr_type
] = unpack('=B', data
[4])[0]
2021 elif sub_attr_type
in (Link
.IFLA_BRPORT_PRIORITY
,
2022 Link
.IFLA_BRPORT_DESIGNATED_PORT
,
2023 Link
.IFLA_BRPORT_DESIGNATED_COST
,
2024 Link
.IFLA_BRPORT_ID
,
2025 Link
.IFLA_BRPORT_NO
):
2026 self
.value
[sub_attr_type
] = unpack('=H', data
[4:6])[0]
2029 elif sub_attr_type
in (Link
.IFLA_BRPORT_COST
,):
2030 self
.value
[sub_attr_type
] = unpack('=L', data
[4:8])[0]
2033 elif sub_attr_type
in (Link
.IFLA_BRPORT_MESSAGE_AGE_TIMER
,
2034 Link
.IFLA_BRPORT_FORWARD_DELAY_TIMER
,
2035 Link
.IFLA_BRPORT_HOLD_TIMER
):
2036 self
.value
[sub_attr_type
] = unpack('=Q', data
[4:12])[0]
2039 self
.log
.log(SYSLOG_EXTRA_DEBUG
, 'Add support for decoding IFLA_PROTINFO sub-attribute type %s (%d), length %d, padded to %d' %
2040 (parent_msg
.get_ifla_brport_string(sub_attr_type
), sub_attr_type
, sub_attr_length
, sub_attr_end
))
2042 data
= data
[sub_attr_end
:]
2044 def dump_lines(self
, dump_buffer
, line_number
, color
):
2045 line_number
= self
.dump_first_line(dump_buffer
, line_number
, color
)
2048 next_sub_attr_line
= 0
2049 sub_attr_line
= True
2051 for x
in xrange(1, self
.attr_end
/4):
2055 if line_number
== next_sub_attr_line
:
2056 sub_attr_line
= True
2059 sub_attr_line
= False
2061 (sub_attr_length
, sub_attr_type
) = unpack('=HH', self
.data
[start
:start
+4])
2062 sub_attr_end
= padded_length(sub_attr_length
)
2064 next_sub_attr_line
= line_number
+ (sub_attr_end
/4)
2066 if sub_attr_end
== sub_attr_length
:
2069 padded_to
= ' padded to %d, ' % sub_attr_end
2071 extra
= 'Nested Attribute - Length %s (%d)%s Type %s (%d) %s' % \
2072 (zfilled_hex(sub_attr_length
, 4), sub_attr_length
,
2074 zfilled_hex(sub_attr_type
, 4), sub_attr_type
,
2075 Link
.ifla_brport_to_string
.get(sub_attr_type
))
2079 dump_buffer
.append(data_to_color_text(line_number
, color
, self
.data
[start
:end
], extra
))
2084 def get_pretty_value(self
, obj
=None):
2086 if obj
and callable(obj
):
2087 return obj(self
.value
)
2091 for (sub_key
, sub_value
) in self
.value
.iteritems():
2092 sub_key_pretty
= "(%2d) %s" % (sub_key
, Link
.ifla_brport_to_string
.get(sub_key
, 'UNKNOWN'))
2093 sub_value_pretty
= sub_value
2094 value_pretty
[sub_key_pretty
] = sub_value_pretty
2100 class NetlinkPacket(object):
2105 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
2106 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2108 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2110 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2112 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2113 | Process ID (PID) |
2114 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2117 header_PACK
= 'IHHII'
2118 header_LEN
= calcsize(header_PACK
)
2120 # Netlink packet types
2121 # /usr/include/linux/rtnetlink.h
2123 NLMSG_NOOP
: 'NLMSG_NOOP',
2124 NLMSG_ERROR
: 'NLMSG_ERROR',
2125 NLMSG_DONE
: 'NLMSG_DONE',
2126 NLMSG_OVERRUN
: 'NLMSG_OVERRUN',
2127 RTM_NEWLINK
: 'RTM_NEWLINK',
2128 RTM_DELLINK
: 'RTM_DELLINK',
2129 RTM_GETLINK
: 'RTM_GETLINK',
2130 RTM_SETLINK
: 'RTM_SETLINK',
2131 RTM_NEWADDR
: 'RTM_NEWADDR',
2132 RTM_DELADDR
: 'RTM_DELADDR',
2133 RTM_GETADDR
: 'RTM_GETADDR',
2134 RTM_NEWNEIGH
: 'RTM_NEWNEIGH',
2135 RTM_DELNEIGH
: 'RTM_DELNEIGH',
2136 RTM_GETNEIGH
: 'RTM_GETNEIGH',
2137 RTM_NEWROUTE
: 'RTM_NEWROUTE',
2138 RTM_DELROUTE
: 'RTM_DELROUTE',
2139 RTM_GETROUTE
: 'RTM_GETROUTE',
2140 RTM_NEWQDISC
: 'RTM_NEWQDISC',
2141 RTM_DELQDISC
: 'RTM_DELQDISC',
2142 RTM_GETQDISC
: 'RTM_GETQDISC'
2145 af_family_to_string
= {
2150 def __init__(self
, msgtype
, debug
, owner_logger
=None, use_color
=True):
2151 self
.msgtype
= msgtype
2152 self
.attributes
= {}
2153 self
.dump_buffer
= ['']
2154 self
.line_number
= 1
2157 self
.use_color
= use_color
2161 self
.log
= owner_logger
2166 return self
.get_type_string()
2168 def get_string(self
, to_string
, index
):
2170 Used to do lookups in all of the various FOO_to_string dictionaries
2171 but returns 'UNKNOWN' if the key is bogus
2173 if index
in to_string
:
2174 return to_string
[index
]
2177 def get_type_string(self
, msgtype
=None):
2179 msgtype
= self
.msgtype
2180 return self
.get_string(self
.type_to_string
, msgtype
)
2182 def get_flags_string(self
):
2185 for (flag
, flag_string
) in self
.flag_to_string
.iteritems():
2186 if self
.flags
& flag
:
2187 foo
.append(flag_string
)
2189 return ', '.join(foo
)
2191 def decode_packet(self
, length
, flags
, seq
, pid
, data
):
2192 self
.length
= length
2196 self
.header_data
= data
[0:self
.header_LEN
]
2197 self
.msg_data
= data
[self
.header_LEN
:length
]
2199 self
.decode_netlink_header()
2200 self
.decode_service_header()
2202 # NLMSG_ERROR is special case, it does not have attributes to decode
2203 if self
.msgtype
!= NLMSG_ERROR
:
2204 self
.decode_attributes()
2206 def get_netlink_header_flags_string(self
, msg_type
, flags
):
2209 if flags
& NLM_F_REQUEST
:
2210 foo
.append('NLM_F_REQUEST')
2212 if flags
& NLM_F_MULTI
:
2213 foo
.append('NLM_F_MULTI')
2215 if flags
& NLM_F_ACK
:
2216 foo
.append('NLM_F_ACK')
2218 if flags
& NLM_F_ECHO
:
2219 foo
.append('NLM_F_ECHO')
2221 # Modifiers to GET query
2222 if msg_type
in (RTM_GETLINK
, RTM_GETADDR
, RTM_GETNEIGH
, RTM_GETROUTE
, RTM_GETQDISC
):
2223 if flags
& NLM_F_DUMP
:
2224 foo
.append('NLM_F_DUMP')
2226 if flags
& NLM_F_MATCH
:
2227 foo
.append('NLM_F_MATCH')
2229 if flags
& NLM_F_ROOT
:
2230 foo
.append('NLM_F_ROOT')
2232 if flags
& NLM_F_ATOMIC
:
2233 foo
.append('NLM_F_ATOMIC')
2235 # Modifiers to NEW query
2236 elif msg_type
in (RTM_NEWLINK
, RTM_NEWADDR
, RTM_NEWNEIGH
, RTM_NEWROUTE
, RTM_NEWQDISC
):
2237 if flags
& NLM_F_REPLACE
:
2238 foo
.append('NLM_F_REPLACE')
2240 if flags
& NLM_F_EXCL
:
2241 foo
.append('NLM_F_EXCL')
2243 if flags
& NLM_F_CREATE
:
2244 foo
.append('NLM_F_CREATE')
2246 if flags
& NLM_F_APPEND
:
2247 foo
.append('NLM_F_APPEND')
2249 return ', '.join(foo
)
2251 # When we first RXed the netlink message we had to decode the header to
2252 # determine what type of netlink message we were dealing with. So the
2253 # header has actually already been decoded...what we do here is
2254 # populate the dump_buffer lines with the header content.
2255 def decode_netlink_header(self
):
2260 header_data
= self
.header_data
2262 # Print the netlink header in red
2263 netlink_header_length
= 16
2264 color
= red
if self
.use_color
else None
2265 color_start
= "\033[%dm" % color
if color
else ""
2266 color_end
= "\033[0m" if color
else ""
2267 self
.dump_buffer
.append(" %sNetlink Header%s" % (color_start
, color_end
))
2269 for x
in range(0, netlink_header_length
/4):
2273 if self
.line_number
== 1:
2274 data
= unpack('=L', header_data
[start
:end
])[0]
2275 extra
= "Length %s (%d)" % (zfilled_hex(data
, 8), data
)
2277 elif self
.line_number
== 2:
2278 (data1
, data2
) = unpack('HH', header_data
[start
:end
])
2279 extra
= "Type %s (%d - %s), Flags %s (%s)" % \
2280 (zfilled_hex(data1
, 4), data1
, self
.get_type_string(data1
),
2281 zfilled_hex(data2
, 4), self
.get_netlink_header_flags_string(data1
, data2
))
2283 elif self
.line_number
== 3:
2284 data
= unpack('=L', header_data
[start
:end
])[0]
2285 extra
= "Sequence Number %s (%d)" % (zfilled_hex(data
, 8), data
)
2287 elif self
.line_number
== 4:
2288 data
= unpack('=L', header_data
[start
:end
])[0]
2289 extra
= "Process ID %s (%d)" % (zfilled_hex(data
, 8), data
)
2291 extra
= "Unexpected line number %d" % self
.line_number
2293 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, header_data
[start
:end
], extra
))
2294 self
.line_number
+= 1
2296 def decode_attributes(self
):
2298 Decode the attributes and populate the dump_buffer
2302 self
.dump_buffer
.append(" Attributes")
2303 color
= green
if self
.use_color
else None
2305 data
= self
.msg_data
[self
.LEN
:]
2308 (length
, attr_type
) = unpack('=HH', data
[:4])
2310 # If this is zero we will stay in this loop for forever
2312 self
.log
.error('Length is zero')
2315 if len(data
) < length
:
2316 self
.log
.error("Buffer underrun %d < %d" % (len(data
), length
))
2319 attr
= self
.add_attribute(attr_type
, None)
2321 # Find the end of 'data' for this attribute and decode our section
2322 # of 'data'. attributes are padded for alignment thus the attr_end.
2324 # How the attribute is decoded/unpacked is specific per AttributeXXXX class.
2325 attr_end
= padded_length(length
)
2326 attr
.decode(self
, data
[0:attr_end
])
2329 self
.line_number
= attr
.dump_lines(self
.dump_buffer
, self
.line_number
, color
)
2331 # Alternate back and forth between green and blue
2338 data
= data
[attr_end
:]
2340 def add_attribute(self
, attr_type
, value
):
2341 nested
= True if attr_type
& NLA_F_NESTED
else False
2342 net_byteorder
= True if attr_type
& NLA_F_NET_BYTEORDER
else False
2343 attr_type
= attr_type
& NLA_TYPE_MASK
2345 # Given an attr_type (say RTA_DST) find the type of AttributeXXXX class
2346 # that we will use to store this attribute...AttributeIPAddress in the
2348 if attr_type
in self
.attribute_to_class
:
2349 (attr_string
, attr_class
) = self
.attribute_to_class
[attr_type
]
2352 attribute_to_class is a dictionary where the key is the attr_type, it doesn't
2353 take the family into account. For now we'll handle this as a special case for
2354 MPLS but long term we may need to make key a tuple of the attr_type and family.
2356 if attr_type
== Route
.RTA_DST
and self
.family
== AF_MPLS
:
2357 attr_string
= 'RTA_DST'
2358 attr_class
= AttributeMplsLabel
2361 attr_string
= "UNKNOWN_ATTRIBUTE_%d" % attr_type
2362 attr_class
= AttributeGeneric
2363 self
.log
.debug("Attribute %d is not defined in %s.attribute_to_class, assuming AttributeGeneric" %
2364 (attr_type
, self
.__class
__.__name
__))
2366 attr
= attr_class(attr_type
, attr_string
, self
.family
, self
.log
)
2368 attr
.set_value(value
)
2369 attr
.set_nested(nested
)
2370 attr
.set_net_byteorder(net_byteorder
)
2372 # self.attributes is a dictionary keyed by the attribute type where
2373 # the value is an instance of the corresponding AttributeXXXX class.
2374 self
.attributes
[attr_type
] = attr
2378 def get_attribute_value(self
, attr_type
, default
=None):
2379 if attr_type
not in self
.attributes
:
2382 return self
.attributes
[attr_type
].value
2384 def get_attr_string(self
, attr_type
):
2386 Example: If attr_type is Address.IFA_CACHEINFO return the string 'IFA_CACHEINFO'
2388 if attr_type
in self
.attribute_to_class
:
2389 (attr_string
, attr_class
) = self
.attribute_to_class
[attr_type
]
2391 return str(attr_type
)
2393 def build_message(self
, seq
, pid
):
2398 for attr
in self
.attributes
.itervalues():
2399 attrs
+= attr
.encode()
2401 self
.length
= self
.header_LEN
+ len(self
.body
) + len(attrs
)
2402 self
.header_data
= pack(self
.header_PACK
, self
.length
, self
.msgtype
, self
.flags
, self
.seq
, self
.pid
)
2403 self
.msg_data
= self
.body
+ attrs
2404 self
.message
= self
.header_data
+ self
.msg_data
2407 self
.decode_netlink_header()
2408 self
.decode_service_header()
2409 self
.decode_attributes()
2410 self
.dump("TXed %s, length %d, seq %d, pid %d, flags 0x%x (%s)" %
2411 (self
, self
.length
, self
.seq
, self
.pid
, self
.flags
,
2412 self
.get_netlink_header_flags_string(self
.msgtype
, self
.flags
)))
2414 def pretty_display_dict(self
, dic
, level
):
2415 for k
,v
in dic
.iteritems():
2416 if isinstance(v
, dict):
2417 self
.log
.debug(' '*level
+ str(k
) + ':')
2418 self
.pretty_display_dict(v
, level
+5)
2420 self
.log
.debug(' '*level
+ str(k
) + ': ' + str(v
))
2422 # Print the netlink message in hex. This is only used for debugging.
2423 def dump(self
, desc
=None):
2427 desc
= "RXed %s, length %d, seq %d, pid %d, flags 0x%x" % (self
, self
.length
, self
.seq
, self
.pid
, self
.flags
)
2429 for (attr_type
, attr_obj
) in self
.attributes
.iteritems():
2430 key_string
= "(%2d) %s" % (attr_type
, self
.get_attr_string(attr_type
))
2431 attr_string
[key_string
] = attr_obj
.get_pretty_value()
2434 self
.log
.debug("%s\n%s\n\nAttributes Summary\n%s\n" %
2435 (desc
, '\n'.join(self
.dump_buffer
), pformat(attr_string
)))
2437 # Assume if we are not allowing color output we also don't want embedded
2438 # newline characters in the output. Output each line individually.
2439 self
.log
.debug(desc
)
2440 for line
in self
.dump_buffer
:
2441 self
.log
.debug(line
)
2443 self
.log
.debug("Attributes Summary")
2444 self
.pretty_display_dict(attr_string
, 1)
2447 class Address(NetlinkPacket
):
2451 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
2452 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2453 | Family | Length | Flags | Scope |
2454 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2456 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2459 # Address attributes
2460 # /usr/include/linux/if_addr.h
2465 IFA_BROADCAST
= 0x04
2467 IFA_CACHEINFO
= 0x06
2468 IFA_MULTICAST
= 0x07
2471 attribute_to_class
= {
2472 IFA_UNSPEC
: ('IFA_UNSPEC', AttributeGeneric
),
2473 IFA_ADDRESS
: ('IFA_ADDRESS', AttributeIPAddress
),
2474 IFA_LOCAL
: ('IFA_LOCAL', AttributeIPAddress
),
2475 IFA_LABEL
: ('IFA_LABEL', AttributeString
),
2476 IFA_BROADCAST
: ('IFA_BROADCAST', AttributeIPAddress
),
2477 IFA_ANYCAST
: ('IFA_ANYCAST', AttributeIPAddress
),
2478 IFA_CACHEINFO
: ('IFA_CACHEINFO', AttributeGeneric
),
2479 IFA_MULTICAST
: ('IFA_MULTICAST', AttributeIPAddress
),
2480 IFA_FLAGS
: ('IFA_FLAGS', AttributeGeneric
)
2484 # /usr/include/linux/if_addr.h
2485 IFA_F_SECONDARY
= 0x01
2487 IFA_F_OPTIMISTIC
= 0x04
2488 IFA_F_DADFAILED
= 0x08
2489 IFA_F_HOMEADDRESS
= 0x10
2490 IFA_F_DEPRECATED
= 0x20
2491 IFA_F_TENTATIVE
= 0x40
2492 IFA_F_PERMANENT
= 0x80
2495 IFA_F_SECONDARY
: 'IFA_F_SECONDARY',
2496 IFA_F_NODAD
: 'IFA_F_NODAD',
2497 IFA_F_OPTIMISTIC
: 'IFA_F_OPTIMISTIC',
2498 IFA_F_DADFAILED
: 'IFA_F_DADFAILED',
2499 IFA_F_HOMEADDRESS
: 'IFA_F_HOMEADDRESS',
2500 IFA_F_DEPRECATED
: 'IFA_F_DEPRECATED',
2501 IFA_F_TENTATIVE
: 'IFA_F_TENTATIVE',
2502 IFA_F_PERMANENT
: 'IFA_F_PERMANENT'
2505 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
2506 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
2508 self
.LEN
= calcsize(self
.PACK
)
2510 def decode_service_header(self
):
2512 # Nothing to do if the message did not contain a service header
2513 if self
.length
== self
.header_LEN
:
2516 (self
.family
, self
.prefixlen
, self
.flags
, self
.scope
,
2518 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
2521 color
= yellow
if self
.use_color
else None
2522 color_start
= "\033[%dm" % color
if color
else ""
2523 color_end
= "\033[0m" if color
else ""
2524 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
2526 for x
in range(0, self
.LEN
/4):
2527 if self
.line_number
== 5:
2528 extra
= "Family %s (%d), Length %s (%d), Flags %s, Scope %s (%d)" % \
2529 (zfilled_hex(self
.family
, 2), self
.family
,
2530 zfilled_hex(self
.prefixlen
, 2), self
.prefixlen
,
2531 zfilled_hex(self
.flags
, 2),
2532 zfilled_hex(self
.scope
, 2), self
.scope
)
2533 elif self
.line_number
== 6:
2534 extra
= "Interface Index %s (%d)" % (zfilled_hex(self
.ifindex
, 8), self
.ifindex
)
2536 extra
= "Unexpected line number %d" % self
.line_number
2540 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
2541 self
.line_number
+= 1
2544 class Error(NetlinkPacket
):
2547 # /include/netlink/errno.h
2558 NLE_OPNOTSUPP
= 0x0A
2559 NLE_AF_NOSUPPORT
= 0x0B
2560 NLE_OBJ_NOTFOUND
= 0x0C
2562 NLE_MISSING_ATTR
= 0x0E
2563 NLE_AF_MISMATCH
= 0x0F
2564 NLE_SEQ_MISMATCH
= 0x10
2565 NLE_MSG_OVERFLOW
= 0x11
2566 NLE_MSG_TRUNC
= 0x12
2568 NLE_SRCRT_NOSUPPORT
= 0x14
2569 NLE_MSG_TOOSHORT
= 0x15
2570 NLE_MSGTYPE_NOSUPPORT
= 0x16
2571 NLE_OBJ_MISMATCH
= 0x17
2574 NLE_PROTO_MISMATCH
= 0x1A
2577 NLE_PKTLOC_FILE
= 0x1D
2578 NLE_PARSE_ERR
= 0x1E
2580 NLE_IMMUTABLE
= 0x20
2581 NLE_DUMP_INTR
= 0x21
2584 NLE_SUCCESS
: 'NLE_SUCCESS',
2585 NLE_FAILURE
: 'NLE_FAILURE',
2586 NLE_INTR
: 'NLE_INTR',
2587 NLE_BAD_SOCK
: 'NLE_BAD_SOCK',
2588 NLE_AGAIN
: 'NLE_AGAIN',
2589 NLE_NOMEM
: 'NLE_NOMEM',
2590 NLE_EXIST
: 'NLE_EXIST',
2591 NLE_INVAL
: 'NLE_INVAL',
2592 NLE_RANGE
: 'NLE_RANGE',
2593 NLE_MSGSIZE
: 'NLE_MSGSIZE',
2594 NLE_OPNOTSUPP
: 'NLE_OPNOTSUPP',
2595 NLE_AF_NOSUPPORT
: 'NLE_AF_NOSUPPORT',
2596 NLE_OBJ_NOTFOUND
: 'NLE_OBJ_NOTFOUND',
2597 NLE_NOATTR
: 'NLE_NOATTR',
2598 NLE_MISSING_ATTR
: 'NLE_MISSING_ATTR',
2599 NLE_AF_MISMATCH
: 'NLE_AF_MISMATCH',
2600 NLE_SEQ_MISMATCH
: 'NLE_SEQ_MISMATCH',
2601 NLE_MSG_OVERFLOW
: 'NLE_MSG_OVERFLOW',
2602 NLE_MSG_TRUNC
: 'NLE_MSG_TRUNC',
2603 NLE_NOADDR
: 'NLE_NOADDR',
2604 NLE_SRCRT_NOSUPPORT
: 'NLE_SRCRT_NOSUPPORT',
2605 NLE_MSG_TOOSHORT
: 'NLE_MSG_TOOSHORT',
2606 NLE_MSGTYPE_NOSUPPORT
: 'NLE_MSGTYPE_NOSUPPORT',
2607 NLE_OBJ_MISMATCH
: 'NLE_OBJ_MISMATCH',
2608 NLE_NOCACHE
: 'NLE_NOCACHE',
2609 NLE_BUSY
: 'NLE_BUSY',
2610 NLE_PROTO_MISMATCH
: 'NLE_PROTO_MISMATCH',
2611 NLE_NOACCESS
: 'NLE_NOACCESS',
2612 NLE_PERM
: 'NLE_PERM',
2613 NLE_PKTLOC_FILE
: 'NLE_PKTLOC_FILE',
2614 NLE_PARSE_ERR
: 'NLE_PARSE_ERR',
2615 NLE_NODEV
: 'NLE_NODEV',
2616 NLE_IMMUTABLE
: 'NLE_IMMUTABLE',
2617 NLE_DUMP_INTR
: 'NLE_DUMP_INTR'
2620 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
2621 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
2622 self
.PACK
= '=iLHHLL'
2623 self
.LEN
= calcsize(self
.PACK
)
2625 def decode_service_header(self
):
2627 # Nothing to do if the message did not contain a service header
2628 if self
.length
== self
.header_LEN
:
2631 (self
.negative_errno
, self
.bad_msg_len
, self
.bad_msg_type
,
2632 self
.bad_msg_flag
, self
.bad_msg_seq
, self
.bad_msg_pid
) =\
2633 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
2636 color
= yellow
if self
.use_color
else None
2637 color_start
= "\033[%dm" % color
if color
else ""
2638 color_end
= "\033[0m" if color
else ""
2639 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
2641 for x
in range(0, self
.LEN
/4):
2643 if self
.line_number
== 5:
2644 extra
= "Error Number %s is %s" % (self
.negative_errno
, self
.error_to_string
.get(abs(self
.negative_errno
)))
2645 # zfilled_hex(self.negative_errno, 2)
2647 elif self
.line_number
== 6:
2648 extra
= "Length %s (%d)" % (zfilled_hex(self
.bad_msg_len
, 8), self
.bad_msg_len
)
2650 elif self
.line_number
== 7:
2651 extra
= "Type %s (%d - %s), Flags %s (%s)" % \
2652 (zfilled_hex(self
.bad_msg_type
, 4), self
.bad_msg_type
, self
.get_type_string(self
.bad_msg_type
),
2653 zfilled_hex(self
.bad_msg_flag
, 4), self
.get_netlink_header_flags_string(self
.bad_msg_type
, self
.bad_msg_flag
))
2655 elif self
.line_number
== 8:
2656 extra
= "Sequence Number %s (%d)" % (zfilled_hex(self
.bad_msg_seq
, 8), self
.bad_msg_seq
)
2658 elif self
.line_number
== 9:
2659 extra
= "Process ID %s (%d)" % (zfilled_hex(self
.bad_msg_pid
, 8), self
.bad_msg_pid
)
2662 extra
= "Unexpected line number %d" % self
.line_number
2666 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
2667 self
.line_number
+= 1
2670 class Link(NetlinkPacket
):
2675 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
2676 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2677 | Family | Reserved | Device Type |
2678 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2680 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2682 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2684 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2688 # /usr/include/linux/if_link.h
2708 IFLA_NET_NS_PID
= 19
2711 IFLA_VFINFO_LIST
= 22
2719 IFLA_PROMISCUITY
= 30
2720 IFLA_NUM_TX_QUEUES
= 31
2721 IFLA_NUM_RX_QUEUES
= 32
2723 IFLA_PHYS_PORT_ID
= 34
2724 IFLA_CARRIER_CHANGES
= 35
2725 IFLA_PHYS_SWITCH_ID
= 36
2726 IFLA_LINK_NETNSID
= 37
2727 IFLA_PHYS_PORT_NAME
= 38
2728 IFLA_PROTO_DOWN
= 39
2729 IFLA_GSO_MAX_SEGS
= 40
2730 IFLA_GSO_MAX_SIZE
= 41
2732 attribute_to_class
= {
2733 IFLA_UNSPEC
: ('IFLA_UNSPEC', AttributeGeneric
),
2734 IFLA_ADDRESS
: ('IFLA_ADDRESS', AttributeMACAddress
),
2735 IFLA_BROADCAST
: ('IFLA_BROADCAST', AttributeMACAddress
),
2736 IFLA_IFNAME
: ('IFLA_IFNAME', AttributeStringInterfaceName
),
2737 IFLA_MTU
: ('IFLA_MTU', AttributeFourByteValue
),
2738 IFLA_LINK
: ('IFLA_LINK', AttributeFourByteValue
),
2739 IFLA_QDISC
: ('IFLA_QDISC', AttributeString
),
2740 IFLA_STATS
: ('IFLA_STATS', AttributeGeneric
),
2741 IFLA_COST
: ('IFLA_COST', AttributeGeneric
),
2742 IFLA_PRIORITY
: ('IFLA_PRIORITY', AttributeGeneric
),
2743 IFLA_MASTER
: ('IFLA_MASTER', AttributeFourByteValue
),
2744 IFLA_WIRELESS
: ('IFLA_WIRELESS', AttributeGeneric
),
2745 IFLA_PROTINFO
: ('IFLA_PROTINFO', AttributeIFLA_PROTINFO
),
2746 IFLA_TXQLEN
: ('IFLA_TXQLEN', AttributeFourByteValue
),
2747 IFLA_MAP
: ('IFLA_MAP', AttributeGeneric
),
2748 IFLA_WEIGHT
: ('IFLA_WEIGHT', AttributeGeneric
),
2749 IFLA_OPERSTATE
: ('IFLA_OPERSTATE', AttributeOneByteValue
),
2750 IFLA_LINKMODE
: ('IFLA_LINKMODE', AttributeOneByteValue
),
2751 IFLA_LINKINFO
: ('IFLA_LINKINFO', AttributeIFLA_LINKINFO
),
2752 IFLA_NET_NS_PID
: ('IFLA_NET_NS_PID', AttributeGeneric
),
2753 IFLA_IFALIAS
: ('IFLA_IFALIAS', AttributeGeneric
),
2754 IFLA_NUM_VF
: ('IFLA_NUM_VF', AttributeGeneric
),
2755 IFLA_VFINFO_LIST
: ('IFLA_VFINFO_LIST', AttributeGeneric
),
2756 IFLA_STATS64
: ('IFLA_STATS64', AttributeGeneric
),
2757 IFLA_VF_PORTS
: ('IFLA_VF_PORTS', AttributeGeneric
),
2758 IFLA_PORT_SELF
: ('IFLA_PORT_SELF', AttributeGeneric
),
2759 IFLA_AF_SPEC
: ('IFLA_AF_SPEC', AttributeIFLA_AF_SPEC
),
2760 IFLA_GROUP
: ('IFLA_GROUP', AttributeFourByteValue
),
2761 IFLA_NET_NS_FD
: ('IFLA_NET_NS_FD', AttributeGeneric
),
2762 IFLA_EXT_MASK
: ('IFLA_EXT_MASK', AttributeFourByteValue
),
2763 IFLA_PROMISCUITY
: ('IFLA_PROMISCUITY', AttributeGeneric
),
2764 IFLA_NUM_TX_QUEUES
: ('IFLA_NUM_TX_QUEUES', AttributeGeneric
),
2765 IFLA_NUM_RX_QUEUES
: ('IFLA_NUM_RX_QUEUES', AttributeGeneric
),
2766 IFLA_CARRIER
: ('IFLA_CARRIER', AttributeGeneric
),
2767 IFLA_PHYS_PORT_ID
: ('IFLA_PHYS_PORT_ID', AttributeGeneric
),
2768 IFLA_CARRIER_CHANGES
: ('IFLA_CARRIER_CHANGES', AttributeGeneric
),
2769 IFLA_PHYS_SWITCH_ID
: ('IFLA_PHYS_SWITCH_ID', AttributeGeneric
),
2770 IFLA_LINK_NETNSID
: ('IFLA_LINK_NETNSID', AttributeGeneric
),
2771 IFLA_PHYS_PORT_NAME
: ('IFLA_PHYS_PORT_NAME', AttributeGeneric
),
2772 IFLA_PROTO_DOWN
: ('IFLA_PROTO_DOWN', AttributeOneByteValue
),
2773 IFLA_GSO_MAX_SEGS
: ('IFLA_GSO_MAX_SEGS', AttributeFourByteValue
),
2774 IFLA_GSO_MAX_SIZE
: ('IFLA_GSO_MAX_SIZE', AttributeFourByteValue
)
2778 # /usr/include/linux/if.h
2779 IFF_UP
= 0x0001 # Interface is administratively up.
2780 IFF_BROADCAST
= 0x0002 # Valid broadcast address set.
2781 IFF_DEBUG
= 0x0004 # Internal debugging flag.
2782 IFF_LOOPBACK
= 0x0008 # Interface is a loopback interface.
2783 IFF_POINTOPOINT
= 0x0010 # Interface is a point-to-point link.
2784 IFF_NOTRAILERS
= 0x0020 # Avoid use of trailers.
2785 IFF_RUNNING
= 0x0040 # Interface is operationally up.
2786 IFF_NOARP
= 0x0080 # No ARP protocol needed for this interface.
2787 IFF_PROMISC
= 0x0100 # Interface is in promiscuous mode.
2788 IFF_ALLMULTI
= 0x0200 # Receive all multicast packets.
2789 IFF_MASTER
= 0x0400 # Master of a load balancing bundle.
2790 IFF_SLAVE
= 0x0800 # Slave of a load balancing bundle.
2791 IFF_MULTICAST
= 0x1000 # Supports multicast.
2792 IFF_PORTSEL
= 0x2000 # Is able to select media type via ifmap.
2793 IFF_AUTOMEDIA
= 0x4000 # Auto media selection active.
2794 IFF_DYNAMIC
= 0x8000 # Interface was dynamically created.
2795 IFF_LOWER_UP
= 0x10000 # driver signals L1 up
2796 IFF_DORMANT
= 0x20000 # driver signals dormant
2797 IFF_ECHO
= 0x40000 # echo sent packet
2798 IFF_PROTO_DOWN
= 0x1000000 # protocol is down on the interface
2802 IFF_BROADCAST
: 'IFF_BROADCAST',
2803 IFF_DEBUG
: 'IFF_DEBUG',
2804 IFF_LOOPBACK
: 'IFF_LOOPBACK',
2805 IFF_POINTOPOINT
: 'IFF_POINTOPOINT',
2806 IFF_NOTRAILERS
: 'IFF_NOTRAILERS',
2807 IFF_RUNNING
: 'IFF_RUNNING',
2808 IFF_NOARP
: 'IFF_NOARP',
2809 IFF_PROMISC
: 'IFF_PROMISC',
2810 IFF_ALLMULTI
: 'IFF_ALLMULTI',
2811 IFF_MASTER
: 'IFF_MASTER',
2812 IFF_SLAVE
: 'IFF_SLAVE',
2813 IFF_MULTICAST
: 'IFF_MULTICAST',
2814 IFF_PORTSEL
: 'IFF_PORTSEL',
2815 IFF_AUTOMEDIA
: 'IFF_AUTOMEDIA',
2816 IFF_DYNAMIC
: 'IFF_DYNAMIC',
2817 IFF_LOWER_UP
: 'IFF_LOWER_UP',
2818 IFF_DORMANT
: 'IFF_DORMANT',
2819 IFF_ECHO
: 'IFF_ECHO',
2820 IFF_PROTO_DOWN
: 'IFF_PROTO_DOWN'
2823 # RFC 2863 operational status
2825 IF_OPER_NOTPRESENT
= 1
2827 IF_OPER_LOWERLAYERDOWN
= 3
2833 IF_OPER_UNKNOWN
: 'IF_OPER_UNKNOWN',
2834 IF_OPER_NOTPRESENT
: 'IF_OPER_NOTPRESENT',
2835 IF_OPER_DOWN
: 'IF_OPER_DOWN',
2836 IF_OPER_LOWERLAYERDOWN
: 'IF_OPER_LOWERLAYERDOWN',
2837 IF_OPER_TESTING
: 'IF_OPER_TESTING',
2838 IF_OPER_DORMANT
: 'IF_OPER_DORMANT',
2839 IF_OPER_UP
: 'IF_OPER_UP'
2843 # /usr/include/linux/if_arp.h
2844 # ARP protocol HARDWARE identifiers
2845 ARPHRD_NETROM
= 0 # from KA9Q: NET/ROM pseudo
2846 ARPHRD_ETHER
= 1 # Ethernet 10Mbps
2847 ARPHRD_EETHER
= 2 # Experimental Ethernet
2848 ARPHRD_AX25
= 3 # AX.25 Level 2
2849 ARPHRD_PRONET
= 4 # PROnet token ring
2850 ARPHRD_CHAOS
= 5 # Chaosnet
2851 ARPHRD_IEEE802
= 6 # IEEE 802.2 Ethernet/TR/TB
2852 ARPHRD_ARCNET
= 7 # ARCnet
2853 ARPHRD_APPLETLK
= 8 # APPLEtalk
2854 ARPHRD_DLCI
= 15 # Frame Relay DLCI
2855 ARPHRD_ATM
= 19 # ATM
2856 ARPHRD_METRICOM
= 23 # Metricom STRIP (new IANA id)
2857 ARPHRD_IEEE1394
= 24 # IEEE 1394 IPv4 - RFC 2734
2858 ARPHRD_EUI64
= 27 # EUI-64
2859 ARPHRD_INFINIBAND
= 32 # InfiniBand
2860 # Dummy types for non ARP hardware
2865 ARPHRD_RSRVD
= 260 # Notional KISS type
2868 ARPHRD_X25
= 271 # CCITT X.25
2869 ARPHRD_HWX25
= 272 # Boards with X.25 in firmware
2870 ARPHRD_CAN
= 280 # Controller Area Network
2872 ARPHRD_CISCO
= 513 # Cisco HDLC
2873 ARPHRD_HDLC
= ARPHRD_CISCO
2874 ARPHRD_LAPB
= 516 # LAPB
2875 ARPHRD_DDCMP
= 517 # Digital's DDCMP protocol
2876 ARPHRD_RAWHDLC
= 518 # Raw HDLC
2877 ARPHRD_TUNNEL
= 768 # IPIP tunnel
2878 ARPHRD_TUNNEL6
= 769 # IP6IP6 tunnel
2879 ARPHRD_FRAD
= 770 # Frame Relay Access Device
2880 ARPHRD_SKIP
= 771 # SKIP vif
2881 ARPHRD_LOOPBACK
= 772 # Loopback device
2882 ARPHRD_LOCALTLK
= 773 # Localtalk device
2883 ARPHRD_FDDI
= 774 # Fiber Distributed Data Interface
2884 ARPHRD_BIF
= 775 # AP1000 BIF
2885 ARPHRD_SIT
= 776 # sit0 device - IPv6-in-IPv4
2886 ARPHRD_IPDDP
= 777 # IP over DDP tunneller
2887 ARPHRD_IPGRE
= 778 # GRE over IP
2888 ARPHRD_PIMREG
= 779 # PIMSM register interface
2889 ARPHRD_HIPPI
= 780 # High Performance Parallel Interface
2890 ARPHRD_ASH
= 781 # Nexus 64Mbps Ash
2891 ARPHRD_ECONET
= 782 # Acorn Econet
2892 ARPHRD_IRDA
= 783 # Linux-IrDA
2893 ARPHRD_FCPP
= 784 # Point to point fibrechannel
2894 ARPHRD_FCAL
= 785 # Fibrechannel arbitrated loop
2895 ARPHRD_FCPL
= 786 # Fibrechannel public loop
2896 ARPHRD_FCFABRIC
= 787 # Fibrechannel fabric
2897 # 787->799 reserved for fibrechannel media types
2898 ARPHRD_IEEE802_TR
= 800 # Magic type ident for TR
2899 ARPHRD_IEEE80211
= 801 # IEEE 802.11
2900 ARPHRD_IEEE80211_PRISM
= 802 # IEEE 802.11 + Prism2 header
2901 ARPHRD_IEEE80211_RADIOTAP
= 803 # IEEE 802.11 + radiotap header
2902 ARPHRD_IEEE802154
= 804
2903 ARPHRD_PHONET
= 820 # PhoNet media type
2904 ARPHRD_PHONET_PIPE
= 821 # PhoNet pipe header
2905 ARPHRD_CAIF
= 822 # CAIF media type
2906 ARPHRD_VOID
= 0xFFFF # Void type, nothing is known
2907 ARPHRD_NONE
= 0xFFFE # zero header length
2909 link_type_to_string
= {
2910 ARPHRD_NETROM
: 'ARPHRD_NETROM',
2911 ARPHRD_ETHER
: 'ARPHRD_ETHER',
2912 ARPHRD_EETHER
: 'ARPHRD_EETHER',
2913 ARPHRD_AX25
: 'ARPHRD_AX25',
2914 ARPHRD_PRONET
: 'ARPHRD_PRONET',
2915 ARPHRD_CHAOS
: 'ARPHRD_CHAOS',
2916 ARPHRD_IEEE802
: 'ARPHRD_IEEE802',
2917 ARPHRD_ARCNET
: 'ARPHRD_ARCNET',
2918 ARPHRD_APPLETLK
: 'ARPHRD_APPLETLK',
2919 ARPHRD_DLCI
: 'ARPHRD_DLCI',
2920 ARPHRD_ATM
: 'ARPHRD_ATM',
2921 ARPHRD_METRICOM
: 'ARPHRD_METRICOM',
2922 ARPHRD_IEEE1394
: 'ARPHRD_IEEE1394',
2923 ARPHRD_EUI64
: 'ARPHRD_EUI64',
2924 ARPHRD_INFINIBAND
: 'ARPHRD_INFINIBAND',
2925 ARPHRD_SLIP
: 'ARPHRD_SLIP',
2926 ARPHRD_CSLIP
: 'ARPHRD_CSLIP',
2927 ARPHRD_SLIP6
: 'ARPHRD_SLIP6',
2928 ARPHRD_CSLIP6
: 'ARPHRD_CSLIP6',
2929 ARPHRD_RSRVD
: 'ARPHRD_RSRVD',
2930 ARPHRD_ADAPT
: 'ARPHRD_ADAPT',
2931 ARPHRD_ROSE
: 'ARPHRD_ROSE',
2932 ARPHRD_X25
: 'ARPHRD_X25',
2933 ARPHRD_HWX25
: 'ARPHRD_HWX25',
2934 ARPHRD_CAN
: 'ARPHRD_CAN',
2935 ARPHRD_PPP
: 'ARPHRD_PPP',
2936 ARPHRD_CISCO
: 'ARPHRD_CISCO',
2937 ARPHRD_HDLC
: 'ARPHRD_HDLC',
2938 ARPHRD_LAPB
: 'ARPHRD_LAPB',
2939 ARPHRD_DDCMP
: 'ARPHRD_DDCMP',
2940 ARPHRD_RAWHDLC
: 'ARPHRD_RAWHDLC',
2941 ARPHRD_TUNNEL
: 'ARPHRD_TUNNEL',
2942 ARPHRD_TUNNEL6
: 'ARPHRD_TUNNEL6',
2943 ARPHRD_FRAD
: 'ARPHRD_FRAD',
2944 ARPHRD_SKIP
: 'ARPHRD_SKIP',
2945 ARPHRD_LOOPBACK
: 'ARPHRD_LOOPBACK',
2946 ARPHRD_LOCALTLK
: 'ARPHRD_LOCALTLK',
2947 ARPHRD_FDDI
: 'ARPHRD_FDDI',
2948 ARPHRD_BIF
: 'ARPHRD_BIF',
2949 ARPHRD_SIT
: 'ARPHRD_SIT',
2950 ARPHRD_IPDDP
: 'ARPHRD_IPDDP',
2951 ARPHRD_IPGRE
: 'ARPHRD_IPGRE',
2952 ARPHRD_PIMREG
: 'ARPHRD_PIMREG',
2953 ARPHRD_HIPPI
: 'ARPHRD_HIPPI',
2954 ARPHRD_ASH
: 'ARPHRD_ASH',
2955 ARPHRD_ECONET
: 'ARPHRD_ECONET',
2956 ARPHRD_IRDA
: 'ARPHRD_IRDA',
2957 ARPHRD_FCPP
: 'ARPHRD_FCPP',
2958 ARPHRD_FCAL
: 'ARPHRD_FCAL',
2959 ARPHRD_FCPL
: 'ARPHRD_FCPL',
2960 ARPHRD_FCFABRIC
: 'ARPHRD_FCFABRIC',
2961 ARPHRD_IEEE802_TR
: 'ARPHRD_IEEE802_TR',
2962 ARPHRD_IEEE80211
: 'ARPHRD_IEEE80211',
2963 ARPHRD_IEEE80211_PRISM
: 'ARPHRD_IEEE80211_PRISM',
2964 ARPHRD_IEEE80211_RADIOTAP
: 'ARPHRD_IEEE80211_RADIOTAP',
2965 ARPHRD_IEEE802154
: 'ARPHRD_IEEE802154',
2966 ARPHRD_PHONET
: 'ARPHRD_PHONET',
2967 ARPHRD_PHONET_PIPE
: 'ARPHRD_PHONET_PIPE',
2968 ARPHRD_CAIF
: 'ARPHRD_CAIF',
2969 ARPHRD_VOID
: 'ARPHRD_VOID',
2970 ARPHRD_NONE
: 'ARPHRD_NONE'
2973 # =========================================
2974 # IFLA_LINKINFO attributes
2975 # =========================================
2976 IFLA_INFO_UNSPEC
= 0
2979 IFLA_INFO_XSTATS
= 3
2980 IFLA_INFO_SLAVE_KIND
= 4
2981 IFLA_INFO_SLAVE_DATA
= 5
2984 ifla_info_to_string
= {
2985 IFLA_INFO_UNSPEC
: 'IFLA_INFO_UNSPEC',
2986 IFLA_INFO_KIND
: 'IFLA_INFO_KIND',
2987 IFLA_INFO_DATA
: 'IFLA_INFO_DATA',
2988 IFLA_INFO_XSTATS
: 'IFLA_INFO_XSTATS',
2989 IFLA_INFO_SLAVE_KIND
: 'IFLA_INFO_SLAVE_KIND',
2990 IFLA_INFO_SLAVE_DATA
: 'IFLA_INFO_SLAVE_DATA',
2991 IFLA_INFO_MAX
: 'IFLA_INFO_MAX'
2994 # =========================================
2995 # IFLA_INFO_DATA attributes for vlan
2996 # =========================================
2997 IFLA_VLAN_UNSPEC
= 0
3000 IFLA_VLAN_EGRESS_QOS
= 3
3001 IFLA_VLAN_INGRESS_QOS
= 4
3002 IFLA_VLAN_PROTOCOL
= 5
3004 ifla_vlan_to_string
= {
3005 IFLA_VLAN_UNSPEC
: 'IFLA_VLAN_UNSPEC',
3006 IFLA_VLAN_ID
: 'IFLA_VLAN_ID',
3007 IFLA_VLAN_FLAGS
: 'IFLA_VLAN_FLAGS',
3008 IFLA_VLAN_EGRESS_QOS
: 'IFLA_VLAN_EGRESS_QOS',
3009 IFLA_VLAN_INGRESS_QOS
: 'IFLA_VLAN_INGRESS_QOS',
3010 IFLA_VLAN_PROTOCOL
: 'IFLA_VLAN_PROTOCOL'
3013 ifla_vlan_protocol_dict
= {
3026 # =========================================
3027 # IFLA_INFO_DATA attributes for macvlan
3028 # =========================================
3029 IFLA_MACVLAN_UNSPEC
= 0
3030 IFLA_MACVLAN_MODE
= 1
3032 ifla_macvlan_to_string
= {
3033 IFLA_MACVLAN_UNSPEC
: 'IFLA_MACVLAN_UNSPEC',
3034 IFLA_MACVLAN_MODE
: 'IFLA_MACVLAN_MODE'
3038 MACVLAN_MODE_PRIVATE
= 1
3039 MACVLAN_MODE_VEPA
= 2
3040 MACVLAN_MODE_BRIDGE
= 3
3041 MACVLAN_MODE_PASSTHRU
= 4
3043 macvlan_mode_to_string
= {
3044 MACVLAN_MODE_PRIVATE
: 'MACVLAN_MODE_PRIVATE',
3045 MACVLAN_MODE_VEPA
: 'MACVLAN_MODE_VEPA',
3046 MACVLAN_MODE_BRIDGE
: 'MACVLAN_MODE_BRIDGE',
3047 MACVLAN_MODE_PASSTHRU
: 'MACVLAN_MODE_PASSTHRU'
3050 # =========================================
3051 # IFLA_INFO_DATA attributes for vxlan
3052 # =========================================
3053 IFLA_VXLAN_UNSPEC
= 0
3055 IFLA_VXLAN_GROUP
= 2
3057 IFLA_VXLAN_LOCAL
= 4
3060 IFLA_VXLAN_LEARNING
= 7
3061 IFLA_VXLAN_AGEING
= 8
3062 IFLA_VXLAN_LIMIT
= 9
3063 IFLA_VXLAN_PORT_RANGE
= 10
3064 IFLA_VXLAN_PROXY
= 11
3066 IFLA_VXLAN_L2MISS
= 13
3067 IFLA_VXLAN_L3MISS
= 14
3068 IFLA_VXLAN_PORT
= 15
3069 IFLA_VXLAN_GROUP6
= 16
3070 IFLA_VXLAN_LOCAL6
= 17
3071 IFLA_VXLAN_UDP_CSUM
= 18
3072 IFLA_VXLAN_UDP_ZERO_CSUM6_TX
= 19
3073 IFLA_VXLAN_UDP_ZERO_CSUM6_RX
= 20
3074 IFLA_VXLAN_REMCSUM_TX
= 21
3075 IFLA_VXLAN_REMCSUM_RX
= 22
3077 IFLA_VXLAN_REMCSUM_NOPARTIAL
= 24
3078 IFLA_VXLAN_COLLECT_METADATA
= 25
3079 IFLA_VXLAN_REPLICATION_NODE
= 253
3080 IFLA_VXLAN_REPLICATION_TYPE
= 254
3082 ifla_vxlan_to_string
= {
3083 IFLA_VXLAN_UNSPEC
: 'IFLA_VXLAN_UNSPEC',
3084 IFLA_VXLAN_ID
: 'IFLA_VXLAN_ID',
3085 IFLA_VXLAN_GROUP
: 'IFLA_VXLAN_GROUP',
3086 IFLA_VXLAN_LINK
: 'IFLA_VXLAN_LINK',
3087 IFLA_VXLAN_LOCAL
: 'IFLA_VXLAN_LOCAL',
3088 IFLA_VXLAN_TTL
: 'IFLA_VXLAN_TTL',
3089 IFLA_VXLAN_TOS
: 'IFLA_VXLAN_TOS',
3090 IFLA_VXLAN_LEARNING
: 'IFLA_VXLAN_LEARNING',
3091 IFLA_VXLAN_AGEING
: 'IFLA_VXLAN_AGEING',
3092 IFLA_VXLAN_LIMIT
: 'IFLA_VXLAN_LIMIT',
3093 IFLA_VXLAN_PORT_RANGE
: 'IFLA_VXLAN_PORT_RANGE',
3094 IFLA_VXLAN_PROXY
: 'IFLA_VXLAN_PROXY',
3095 IFLA_VXLAN_RSC
: 'IFLA_VXLAN_RSC',
3096 IFLA_VXLAN_L2MISS
: 'IFLA_VXLAN_L2MISS',
3097 IFLA_VXLAN_L3MISS
: 'IFLA_VXLAN_L3MISS',
3098 IFLA_VXLAN_PORT
: 'IFLA_VXLAN_PORT',
3099 IFLA_VXLAN_GROUP6
: 'IFLA_VXLAN_GROUP6',
3100 IFLA_VXLAN_LOCAL6
: 'IFLA_VXLAN_LOCAL6',
3101 IFLA_VXLAN_UDP_CSUM
: 'IFLA_VXLAN_UDP_CSUM',
3102 IFLA_VXLAN_UDP_ZERO_CSUM6_TX
: 'IFLA_VXLAN_UDP_ZERO_CSUM6_TX',
3103 IFLA_VXLAN_UDP_ZERO_CSUM6_RX
: 'IFLA_VXLAN_UDP_ZERO_CSUM6_RX',
3104 IFLA_VXLAN_REMCSUM_TX
: 'IFLA_VXLAN_REMCSUM_TX',
3105 IFLA_VXLAN_REMCSUM_RX
: 'IFLA_VXLAN_REMCSUM_RX',
3106 IFLA_VXLAN_GBP
: 'IFLA_VXLAN_GBP',
3107 IFLA_VXLAN_REMCSUM_NOPARTIAL
: 'IFLA_VXLAN_REMCSUM_NOPARTIAL',
3108 IFLA_VXLAN_COLLECT_METADATA
: 'IFLA_VXLAN_COLLECT_METADATA',
3109 IFLA_VXLAN_REPLICATION_NODE
: 'IFLA_VXLAN_REPLICATION_NODE',
3110 IFLA_VXLAN_REPLICATION_TYPE
: 'IFLA_VXLAN_REPLICATION_TYPE'
3113 # =========================================
3114 # IFLA_INFO_DATA attributes for bonds
3115 # =========================================
3116 IFLA_BOND_UNSPEC
= 0
3118 IFLA_BOND_ACTIVE_SLAVE
= 2
3119 IFLA_BOND_MIIMON
= 3
3120 IFLA_BOND_UPDELAY
= 4
3121 IFLA_BOND_DOWNDELAY
= 5
3122 IFLA_BOND_USE_CARRIER
= 6
3123 IFLA_BOND_ARP_INTERVAL
= 7
3124 IFLA_BOND_ARP_IP_TARGET
= 8
3125 IFLA_BOND_ARP_VALIDATE
= 9
3126 IFLA_BOND_ARP_ALL_TARGETS
= 10
3127 IFLA_BOND_PRIMARY
= 11
3128 IFLA_BOND_PRIMARY_RESELECT
= 12
3129 IFLA_BOND_FAIL_OVER_MAC
= 13
3130 IFLA_BOND_XMIT_HASH_POLICY
= 14
3131 IFLA_BOND_RESEND_IGMP
= 15
3132 IFLA_BOND_NUM_PEER_NOTIF
= 16
3133 IFLA_BOND_ALL_SLAVES_ACTIVE
= 17
3134 IFLA_BOND_MIN_LINKS
= 18
3135 IFLA_BOND_LP_INTERVAL
= 19
3136 IFLA_BOND_PACKETS_PER_SLAVE
= 20
3137 IFLA_BOND_AD_LACP_RATE
= 21
3138 IFLA_BOND_AD_SELECT
= 22
3139 IFLA_BOND_AD_INFO
= 23
3140 IFLA_BOND_AD_ACTOR_SYS_PRIO
= 24
3141 IFLA_BOND_AD_USER_PORT_KEY
= 25
3142 IFLA_BOND_AD_ACTOR_SYSTEM
= 26
3143 IFLA_BOND_AD_LACP_BYPASS
= 100
3145 ifla_bond_to_string
= {
3146 IFLA_BOND_UNSPEC
: 'IFLA_BOND_UNSPEC',
3147 IFLA_BOND_MODE
: 'IFLA_BOND_MODE',
3148 IFLA_BOND_ACTIVE_SLAVE
: 'IFLA_BOND_ACTIVE_SLAVE',
3149 IFLA_BOND_MIIMON
: 'IFLA_BOND_MIIMON',
3150 IFLA_BOND_UPDELAY
: 'IFLA_BOND_UPDELAY',
3151 IFLA_BOND_DOWNDELAY
: 'IFLA_BOND_DOWNDELAY',
3152 IFLA_BOND_USE_CARRIER
: 'IFLA_BOND_USE_CARRIER',
3153 IFLA_BOND_ARP_INTERVAL
: 'IFLA_BOND_ARP_INTERVAL',
3154 IFLA_BOND_ARP_IP_TARGET
: 'IFLA_BOND_ARP_IP_TARGET',
3155 IFLA_BOND_ARP_VALIDATE
: 'IFLA_BOND_ARP_VALIDATE',
3156 IFLA_BOND_ARP_ALL_TARGETS
: 'IFLA_BOND_ARP_ALL_TARGETS',
3157 IFLA_BOND_PRIMARY
: 'IFLA_BOND_PRIMARY',
3158 IFLA_BOND_PRIMARY_RESELECT
: 'IFLA_BOND_PRIMARY_RESELECT',
3159 IFLA_BOND_FAIL_OVER_MAC
: 'IFLA_BOND_FAIL_OVER_MAC',
3160 IFLA_BOND_XMIT_HASH_POLICY
: 'IFLA_BOND_XMIT_HASH_POLICY',
3161 IFLA_BOND_RESEND_IGMP
: 'IFLA_BOND_RESEND_IGMP',
3162 IFLA_BOND_NUM_PEER_NOTIF
: 'IFLA_BOND_NUM_PEER_NOTIF',
3163 IFLA_BOND_ALL_SLAVES_ACTIVE
: 'IFLA_BOND_ALL_SLAVES_ACTIVE',
3164 IFLA_BOND_MIN_LINKS
: 'IFLA_BOND_MIN_LINKS',
3165 IFLA_BOND_LP_INTERVAL
: 'IFLA_BOND_LP_INTERVAL',
3166 IFLA_BOND_PACKETS_PER_SLAVE
: 'IFLA_BOND_PACKETS_PER_SLAVE',
3167 IFLA_BOND_AD_LACP_RATE
: 'IFLA_BOND_AD_LACP_RATE',
3168 IFLA_BOND_AD_SELECT
: 'IFLA_BOND_AD_SELECT',
3169 IFLA_BOND_AD_INFO
: 'IFLA_BOND_AD_INFO',
3170 IFLA_BOND_AD_ACTOR_SYS_PRIO
: 'IFLA_BOND_AD_ACTOR_SYS_PRIO',
3171 IFLA_BOND_AD_USER_PORT_KEY
: 'IFLA_BOND_AD_USER_PORT_KEY',
3172 IFLA_BOND_AD_ACTOR_SYSTEM
: 'IFLA_BOND_AD_ACTOR_SYSTEM',
3173 IFLA_BOND_AD_LACP_BYPASS
: 'IFLA_BOND_AD_LACP_BYPASS'
3176 IFLA_BOND_AD_INFO_UNSPEC
= 0
3177 IFLA_BOND_AD_INFO_AGGREGATOR
= 1
3178 IFLA_BOND_AD_INFO_NUM_PORTS
= 2
3179 IFLA_BOND_AD_INFO_ACTOR_KEY
= 3
3180 IFLA_BOND_AD_INFO_PARTNER_KEY
= 4
3181 IFLA_BOND_AD_INFO_PARTNER_MAC
= 5
3183 ifla_bond_ad_to_string
= {
3184 IFLA_BOND_AD_INFO_UNSPEC
: 'IFLA_BOND_AD_INFO_UNSPEC',
3185 IFLA_BOND_AD_INFO_AGGREGATOR
: 'IFLA_BOND_AD_INFO_AGGREGATOR',
3186 IFLA_BOND_AD_INFO_NUM_PORTS
: 'IFLA_BOND_AD_INFO_NUM_PORTS',
3187 IFLA_BOND_AD_INFO_ACTOR_KEY
: 'IFLA_BOND_AD_INFO_ACTOR_KEY',
3188 IFLA_BOND_AD_INFO_PARTNER_KEY
: 'IFLA_BOND_AD_INFO_PARTNER_KEY',
3189 IFLA_BOND_AD_INFO_PARTNER_MAC
: 'IFLA_BOND_AD_INFO_PARTNER_MAC'
3192 ifla_bond_mode_tbl
= {
3216 ifla_bond_mode_pretty_tbl
= {
3226 ifla_bond_xmit_hash_policy_tbl
= {
3244 ifla_bond_xmit_hash_policy_pretty_tbl
= {
3252 # =========================================
3253 # IFLA_INFO_SLAVE_DATA attributes for bonds
3254 # =========================================
3255 IFLA_BOND_SLAVE_UNSPEC
= 0
3256 IFLA_BOND_SLAVE_STATE
= 1
3257 IFLA_BOND_SLAVE_MII_STATUS
= 2
3258 IFLA_BOND_SLAVE_LINK_FAILURE_COUNT
= 3
3259 IFLA_BOND_SLAVE_PERM_HWADDR
= 4
3260 IFLA_BOND_SLAVE_QUEUE_ID
= 5
3261 IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
= 6
3262 IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
= 7
3263 IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE
= 8
3264 IFLA_BOND_SLAVE_CL_START
= 50
3265 IFLA_BOND_SLAVE_AD_RX_BYPASS
= IFLA_BOND_SLAVE_CL_START
3267 ifla_bond_slave_to_string
= {
3268 IFLA_BOND_SLAVE_UNSPEC
: 'IFLA_BOND_SLAVE_UNSPEC',
3269 IFLA_BOND_SLAVE_STATE
: 'IFLA_BOND_SLAVE_STATE',
3270 IFLA_BOND_SLAVE_MII_STATUS
: 'IFLA_BOND_SLAVE_MII_STATUS',
3271 IFLA_BOND_SLAVE_LINK_FAILURE_COUNT
: 'IFLA_BOND_SLAVE_LINK_FAILURE_COUNT',
3272 IFLA_BOND_SLAVE_PERM_HWADDR
: 'IFLA_BOND_SLAVE_PERM_HWADDR',
3273 IFLA_BOND_SLAVE_QUEUE_ID
: 'IFLA_BOND_SLAVE_QUEUE_ID',
3274 IFLA_BOND_SLAVE_AD_AGGREGATOR_ID
: 'IFLA_BOND_SLAVE_AD_AGGREGATOR_ID',
3275 IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE
: 'IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE',
3276 IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE
: 'IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE',
3277 IFLA_BOND_SLAVE_CL_START
: 'IFLA_BOND_SLAVE_CL_START',
3278 IFLA_BOND_SLAVE_AD_RX_BYPASS
: 'IFLA_BOND_SLAVE_AD_RX_BYPASS'
3281 # =========================================
3282 # IFLA_PROTINFO attributes for bridge ports
3283 # =========================================
3284 IFLA_BRPORT_UNSPEC
= 0
3285 IFLA_BRPORT_STATE
= 1
3286 IFLA_BRPORT_PRIORITY
= 2
3287 IFLA_BRPORT_COST
= 3
3288 IFLA_BRPORT_MODE
= 4
3289 IFLA_BRPORT_GUARD
= 5
3290 IFLA_BRPORT_PROTECT
= 6
3291 IFLA_BRPORT_FAST_LEAVE
= 7
3292 IFLA_BRPORT_LEARNING
= 8
3293 IFLA_BRPORT_UNICAST_FLOOD
= 9
3294 IFLA_BRPORT_PROXYARP
= 10
3295 IFLA_BRPORT_LEARNING_SYNC
= 11
3296 IFLA_BRPORT_PROXYARP_WIFI
= 12
3297 IFLA_BRPORT_ROOT_ID
= 13
3298 IFLA_BRPORT_BRIDGE_ID
= 14
3299 IFLA_BRPORT_DESIGNATED_PORT
= 15
3300 IFLA_BRPORT_DESIGNATED_COST
= 16
3303 IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
= 19
3304 IFLA_BRPORT_CONFIG_PENDING
= 20
3305 IFLA_BRPORT_MESSAGE_AGE_TIMER
= 21
3306 IFLA_BRPORT_FORWARD_DELAY_TIMER
= 22
3307 IFLA_BRPORT_HOLD_TIMER
= 23
3308 IFLA_BRPORT_FLUSH
= 24
3309 IFLA_BRPORT_MULTICAST_ROUTER
= 25
3310 IFLA_BRPORT_PAD
= 26
3311 IFLA_BRPORT_MCAST_FLOOD
= 27
3312 IFLA_BRPORT_MCAST_TO_UCAST
= 28
3313 IFLA_BRPORT_VLAN_TUNNEL
= 29
3314 IFLA_BRPORT_BCAST_FLOOD
= 30
3315 IFLA_BRPORT_GROUP_FWD_MASK
= 31
3316 IFLA_BRPORT_ARP_SUPPRESS
= 32
3317 IFLA_BRPORT_PEER_LINK
= 150
3318 IFLA_BRPORT_DUAL_LINK
= 151
3319 IFLA_BRPORT_GROUP_FWD_MASKHI
= 153
3320 IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
= 154
3322 ifla_brport_to_string
= {
3323 IFLA_BRPORT_UNSPEC
: 'IFLA_BRPORT_UNSPEC',
3324 IFLA_BRPORT_STATE
: 'IFLA_BRPORT_STATE',
3325 IFLA_BRPORT_PRIORITY
: 'IFLA_BRPORT_PRIORITY',
3326 IFLA_BRPORT_COST
: 'IFLA_BRPORT_COST',
3327 IFLA_BRPORT_MODE
: 'IFLA_BRPORT_MODE',
3328 IFLA_BRPORT_GUARD
: 'IFLA_BRPORT_GUARD',
3329 IFLA_BRPORT_PROTECT
: 'IFLA_BRPORT_PROTECT',
3330 IFLA_BRPORT_FAST_LEAVE
: 'IFLA_BRPORT_FAST_LEAVE',
3331 IFLA_BRPORT_LEARNING
: 'IFLA_BRPORT_LEARNING',
3332 IFLA_BRPORT_UNICAST_FLOOD
: 'IFLA_BRPORT_UNICAST_FLOOD',
3333 IFLA_BRPORT_PROXYARP
: 'IFLA_BRPORT_PROXYARP',
3334 IFLA_BRPORT_LEARNING_SYNC
: 'IFLA_BRPORT_LEARNING_SYNC',
3335 IFLA_BRPORT_PROXYARP_WIFI
: 'IFLA_BRPORT_PROXYARP_WIFI',
3336 IFLA_BRPORT_ROOT_ID
: 'IFLA_BRPORT_ROOT_ID',
3337 IFLA_BRPORT_BRIDGE_ID
: 'IFLA_BRPORT_BRIDGE_ID',
3338 IFLA_BRPORT_DESIGNATED_PORT
: 'IFLA_BRPORT_DESIGNATED_PORT',
3339 IFLA_BRPORT_DESIGNATED_COST
: 'IFLA_BRPORT_DESIGNATED_COST',
3340 IFLA_BRPORT_ID
: 'IFLA_BRPORT_ID',
3341 IFLA_BRPORT_NO
: 'IFLA_BRPORT_NO',
3342 IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
: 'IFLA_BRPORT_TOPOLOGY_CHANGE_ACK',
3343 IFLA_BRPORT_CONFIG_PENDING
: 'IFLA_BRPORT_CONFIG_PENDING',
3344 IFLA_BRPORT_MESSAGE_AGE_TIMER
: 'IFLA_BRPORT_MESSAGE_AGE_TIMER',
3345 IFLA_BRPORT_FORWARD_DELAY_TIMER
: 'IFLA_BRPORT_FORWARD_DELAY_TIMER',
3346 IFLA_BRPORT_HOLD_TIMER
: 'IFLA_BRPORT_HOLD_TIMER',
3347 IFLA_BRPORT_FLUSH
: 'IFLA_BRPORT_FLUSH',
3348 IFLA_BRPORT_MULTICAST_ROUTER
: 'IFLA_BRPORT_MULTICAST_ROUTER',
3349 IFLA_BRPORT_PAD
: 'IFLA_BRPORT_PAD',
3350 IFLA_BRPORT_MCAST_FLOOD
: 'IFLA_BRPORT_MCAST_FLOOD',
3351 IFLA_BRPORT_MCAST_TO_UCAST
: 'IFLA_BRPORT_MCAST_TO_UCAST',
3352 IFLA_BRPORT_VLAN_TUNNEL
: 'IFLA_BRPORT_VLAN_TUNNEL',
3353 IFLA_BRPORT_BCAST_FLOOD
: 'IFLA_BRPORT_BCAST_FLOOD',
3354 IFLA_BRPORT_GROUP_FWD_MASK
: 'IFLA_BRPORT_GROUP_FWD_MASK',
3355 IFLA_BRPORT_PEER_LINK
: 'IFLA_BRPORT_PEER_LINK',
3356 IFLA_BRPORT_DUAL_LINK
: 'IFLA_BRPORT_DUAL_LINK',
3357 IFLA_BRPORT_ARP_SUPPRESS
: 'IFLA_BRPORT_ARP_SUPPRESS',
3358 IFLA_BRPORT_GROUP_FWD_MASKHI
: 'IFLA_BRPORT_GROUP_FWD_MASKHI',
3359 IFLA_BRPORT_DOWN_PEERLINK_REDIRECT
: 'IFLA_BRPORT_DOWN_PEERLINK_REDIRECT'
3362 # BRIDGE IFLA_AF_SPEC attributes
3363 IFLA_BRIDGE_FLAGS
= 0
3364 IFLA_BRIDGE_MODE
= 1
3365 IFLA_BRIDGE_VLAN_INFO
= 2
3367 ifla_bridge_af_spec_to_string
= {
3368 IFLA_BRIDGE_FLAGS
: 'IFLA_BRIDGE_FLAGS',
3369 IFLA_BRIDGE_MODE
: 'IFLA_BRIDGE_MODE',
3370 IFLA_BRIDGE_VLAN_INFO
: 'IFLA_BRIDGE_VLAN_INFO'
3373 # BRIDGE_VLAN_INFO flags
3374 BRIDGE_VLAN_INFO_MASTER
= 1 << 0 # Operate on Bridge device as well
3375 BRIDGE_VLAN_INFO_PVID
= 1 << 1 # VLAN is PVID, ingress untagged
3376 BRIDGE_VLAN_INFO_UNTAGGED
= 1 << 2 # VLAN egresses untagged
3377 BRIDGE_VLAN_INFO_RANGE_BEGIN
= 1 << 3 # VLAN is start of vlan range
3378 BRIDGE_VLAN_INFO_RANGE_END
= 1 << 4 # VLAN is end of vlan range
3379 BRIDGE_VLAN_INFO_BRENTRY
= 1 << 5 # Global bridge VLAN entry
3381 bridge_vlan_to_string
= {
3382 BRIDGE_VLAN_INFO_MASTER
: 'BRIDGE_VLAN_INFO_MASTER',
3383 BRIDGE_VLAN_INFO_PVID
: 'BRIDGE_VLAN_INFO_PVID',
3384 BRIDGE_VLAN_INFO_UNTAGGED
: 'BRIDGE_VLAN_INFO_UNTAGGED',
3385 BRIDGE_VLAN_INFO_RANGE_BEGIN
: 'BRIDGE_VLAN_INFO_RANGE_BEGIN',
3386 BRIDGE_VLAN_INFO_RANGE_END
: 'BRIDGE_VLAN_INFO_RANGE_END',
3387 BRIDGE_VLAN_INFO_BRENTRY
: 'BRIDGE_VLAN_INFO_BRENTRY'
3391 BRIDGE_FLAGS_MASTER
= 1
3392 BRIDGE_FLAGS_SELF
= 2
3394 bridge_flags_to_string
= {
3395 BRIDGE_FLAGS_MASTER
: 'BRIDGE_FLAGS_MASTER',
3396 BRIDGE_FLAGS_SELF
: 'BRIDGE_FLAGS_SELF'
3399 # filters for IFLA_EXT_MASK
3400 RTEXT_FILTER_VF
= 1 << 0
3401 RTEXT_FILTER_BRVLAN
= 1 << 1
3402 RTEXT_FILTER_BRVLAN_COMPRESSED
= 1 << 2
3403 RTEXT_FILTER_SKIP_STATS
= 1 << 3
3406 RTEXT_FILTER_VF
: 'RTEXT_FILTER_VF',
3407 RTEXT_FILTER_BRVLAN
: 'RTEXT_FILTER_BRVLAN',
3408 RTEXT_FILTER_BRVLAN_COMPRESSED
: 'RTEXT_FILTER_BRVLAN_COMPRESSED',
3409 RTEXT_FILTER_SKIP_STATS
: 'RTEXT_FILTER_SKIP_STATS'
3413 IFLA_BR_FORWARD_DELAY
= 1
3414 IFLA_BR_HELLO_TIME
= 2
3416 IFLA_BR_AGEING_TIME
= 4
3417 IFLA_BR_STP_STATE
= 5
3418 IFLA_BR_PRIORITY
= 6
3419 IFLA_BR_VLAN_FILTERING
= 7
3420 IFLA_BR_VLAN_PROTOCOL
= 8
3421 IFLA_BR_GROUP_FWD_MASK
= 9
3422 IFLA_BR_ROOT_ID
= 10
3423 IFLA_BR_BRIDGE_ID
= 11
3424 IFLA_BR_ROOT_PORT
= 12
3425 IFLA_BR_ROOT_PATH_COST
= 13
3426 IFLA_BR_TOPOLOGY_CHANGE
= 14
3427 IFLA_BR_TOPOLOGY_CHANGE_DETECTED
= 15
3428 IFLA_BR_HELLO_TIMER
= 16
3429 IFLA_BR_TCN_TIMER
= 17
3430 IFLA_BR_TOPOLOGY_CHANGE_TIMER
= 18
3431 IFLA_BR_GC_TIMER
= 19
3432 IFLA_BR_GROUP_ADDR
= 20
3433 IFLA_BR_FDB_FLUSH
= 21
3434 IFLA_BR_MCAST_ROUTER
= 22
3435 IFLA_BR_MCAST_SNOOPING
= 23
3436 IFLA_BR_MCAST_QUERY_USE_IFADDR
= 24
3437 IFLA_BR_MCAST_QUERIER
= 25
3438 IFLA_BR_MCAST_HASH_ELASTICITY
= 26
3439 IFLA_BR_MCAST_HASH_MAX
= 27
3440 IFLA_BR_MCAST_LAST_MEMBER_CNT
= 28
3441 IFLA_BR_MCAST_STARTUP_QUERY_CNT
= 29
3442 IFLA_BR_MCAST_LAST_MEMBER_INTVL
= 30
3443 IFLA_BR_MCAST_MEMBERSHIP_INTVL
= 31
3444 IFLA_BR_MCAST_QUERIER_INTVL
= 32
3445 IFLA_BR_MCAST_QUERY_INTVL
= 33
3446 IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
= 34
3447 IFLA_BR_MCAST_STARTUP_QUERY_INTVL
= 35
3448 IFLA_BR_NF_CALL_IPTABLES
= 36
3449 IFLA_BR_NF_CALL_IP6TABLES
= 37
3450 IFLA_BR_NF_CALL_ARPTABLES
= 38
3451 IFLA_BR_VLAN_DEFAULT_PVID
= 39
3453 IFLA_BR_VLAN_STATS_ENABLED
= 41
3454 IFLA_BR_MCAST_STATS_ENABLED
= 42
3455 IFLA_BR_MCAST_IGMP_VERSION
= 43
3456 IFLA_BR_MCAST_MLD_VERSION
= 44
3458 ifla_br_to_string
= {
3459 IFLA_BR_UNSPEC
: 'IFLA_BR_UNSPEC',
3460 IFLA_BR_FORWARD_DELAY
: 'IFLA_BR_FORWARD_DELAY',
3461 IFLA_BR_HELLO_TIME
: 'IFLA_BR_HELLO_TIME',
3462 IFLA_BR_MAX_AGE
: 'IFLA_BR_MAX_AGE',
3463 IFLA_BR_AGEING_TIME
: 'IFLA_BR_AGEING_TIME',
3464 IFLA_BR_STP_STATE
: 'IFLA_BR_STP_STATE',
3465 IFLA_BR_PRIORITY
: 'IFLA_BR_PRIORITY',
3466 IFLA_BR_VLAN_FILTERING
: 'IFLA_BR_VLAN_FILTERING',
3467 IFLA_BR_VLAN_PROTOCOL
: 'IFLA_BR_VLAN_PROTOCOL',
3468 IFLA_BR_GROUP_FWD_MASK
: 'IFLA_BR_GROUP_FWD_MASK',
3469 IFLA_BR_ROOT_ID
: 'IFLA_BR_ROOT_ID',
3470 IFLA_BR_BRIDGE_ID
: 'IFLA_BR_BRIDGE_ID',
3471 IFLA_BR_ROOT_PORT
: 'IFLA_BR_ROOT_PORT',
3472 IFLA_BR_ROOT_PATH_COST
: 'IFLA_BR_ROOT_PATH_COST',
3473 IFLA_BR_TOPOLOGY_CHANGE
: 'IFLA_BR_TOPOLOGY_CHANGE',
3474 IFLA_BR_TOPOLOGY_CHANGE_DETECTED
: 'IFLA_BR_TOPOLOGY_CHANGE_DETECTED',
3475 IFLA_BR_HELLO_TIMER
: 'IFLA_BR_HELLO_TIMER',
3476 IFLA_BR_TCN_TIMER
: 'IFLA_BR_TCN_TIMER',
3477 IFLA_BR_TOPOLOGY_CHANGE_TIMER
: 'IFLA_BR_TOPOLOGY_CHANGE_TIMER',
3478 IFLA_BR_GC_TIMER
: 'IFLA_BR_GC_TIMER',
3479 IFLA_BR_GROUP_ADDR
: 'IFLA_BR_GROUP_ADDR',
3480 IFLA_BR_FDB_FLUSH
: 'IFLA_BR_FDB_FLUSH',
3481 IFLA_BR_MCAST_ROUTER
: 'IFLA_BR_MCAST_ROUTER',
3482 IFLA_BR_MCAST_SNOOPING
: 'IFLA_BR_MCAST_SNOOPING',
3483 IFLA_BR_MCAST_QUERY_USE_IFADDR
: 'IFLA_BR_MCAST_QUERY_USE_IFADDR',
3484 IFLA_BR_MCAST_QUERIER
: 'IFLA_BR_MCAST_QUERIER',
3485 IFLA_BR_MCAST_HASH_ELASTICITY
: 'IFLA_BR_MCAST_HASH_ELASTICITY',
3486 IFLA_BR_MCAST_HASH_MAX
: 'IFLA_BR_MCAST_HASH_MAX',
3487 IFLA_BR_MCAST_LAST_MEMBER_CNT
: 'IFLA_BR_MCAST_LAST_MEMBER_CNT',
3488 IFLA_BR_MCAST_STARTUP_QUERY_CNT
: 'IFLA_BR_MCAST_STARTUP_QUERY_CNT',
3489 IFLA_BR_MCAST_LAST_MEMBER_INTVL
: 'IFLA_BR_MCAST_LAST_MEMBER_INTVL',
3490 IFLA_BR_MCAST_MEMBERSHIP_INTVL
: 'IFLA_BR_MCAST_MEMBERSHIP_INTVL',
3491 IFLA_BR_MCAST_QUERIER_INTVL
: 'IFLA_BR_MCAST_QUERIER_INTVL',
3492 IFLA_BR_MCAST_QUERY_INTVL
: 'IFLA_BR_MCAST_QUERY_INTVL',
3493 IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
: 'IFLA_BR_MCAST_QUERY_RESPONSE_INTVL',
3494 IFLA_BR_MCAST_STARTUP_QUERY_INTVL
: 'IFLA_BR_MCAST_STARTUP_QUERY_INTVL',
3495 IFLA_BR_NF_CALL_IPTABLES
: 'IFLA_BR_NF_CALL_IPTABLES',
3496 IFLA_BR_NF_CALL_IP6TABLES
: 'IFLA_BR_NF_CALL_IP6TABLES',
3497 IFLA_BR_NF_CALL_ARPTABLES
: 'IFLA_BR_NF_CALL_ARPTABLES',
3498 IFLA_BR_VLAN_DEFAULT_PVID
: 'IFLA_BR_VLAN_DEFAULT_PVID',
3499 IFLA_BR_PAD
: 'IFLA_BR_PAD',
3500 IFLA_BR_VLAN_STATS_ENABLED
: 'IFLA_BR_VLAN_STATS_ENABLED',
3501 IFLA_BR_MCAST_STATS_ENABLED
: 'IFLA_BR_MCAST_STATS_ENABLED',
3502 IFLA_BR_MCAST_IGMP_VERSION
: 'IFLA_BR_MCAST_IGMP_VERSION',
3503 IFLA_BR_MCAST_MLD_VERSION
: 'IFLA_BR_MCAST_MLD_VERSION'
3506 # =========================================
3507 # IFLA_INFO_DATA attributes for vrfs
3508 # =========================================
3512 ifla_vrf_to_string
= {
3513 IFLA_VRF_UNSPEC
: 'IFLA_VRF_UNSPEC',
3514 IFLA_VRF_TABLE
: 'IFLA_VRF_TABLE'
3517 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
3518 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
3519 self
.PACK
= 'BxHiII'
3520 self
.LEN
= calcsize(self
.PACK
)
3522 def get_link_type_string(self
, index
):
3523 return self
.get_string(self
.link_type_to_string
, index
)
3525 def get_ifla_bridge_af_spec_to_string(self
, index
):
3526 return self
.get_string(self
.ifla_bridge_af_spec_to_string
, index
)
3528 def get_ifla_info_string(self
, index
):
3529 return self
.get_string(self
.ifla_info_to_string
, index
)
3531 def get_ifla_vlan_string(self
, index
):
3532 return self
.get_string(self
.ifla_vlan_to_string
, index
)
3534 def get_ifla_vxlan_string(self
, index
):
3535 return self
.get_string(self
.ifla_vxlan_to_string
, index
)
3537 def get_ifla_macvlan_string(self
, index
):
3538 return self
.get_string(self
.ifla_macvlan_to_string
, index
)
3540 def get_macvlan_mode_string(self
, index
):
3541 return self
.get_string(self
.macvlan_mode_to_string
, index
)
3543 def get_ifla_bond_string(self
, index
):
3544 return self
.get_string(self
.ifla_bond_to_string
, index
)
3546 def get_ifla_bond_ad_string(self
, index
):
3547 return self
.get_string(self
.ifla_bond_ad_to_string
, index
)
3549 def get_ifla_brport_string(self
, index
):
3550 return self
.get_string(self
.ifla_brport_to_string
, index
)
3552 def get_ifla_br_string(self
, index
):
3553 return self
.get_string(self
.ifla_br_to_string
, index
)
3555 def get_bridge_vlan_string(self
, index
):
3556 return self
.get_string(self
.bridge_vlan_to_string
, index
)
3558 def get_bridge_flags_string(self
, index
):
3559 return self
.get_string(self
.bridge_flags_to_string
, index
)
3561 def decode_service_header(self
):
3563 # Nothing to do if the message did not contain a service header
3564 if self
.length
== self
.header_LEN
:
3567 (self
.family
, self
.device_type
,
3570 self
.change_mask
) = \
3571 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
3574 color
= yellow
if self
.use_color
else None
3575 color_start
= "\033[%dm" % color
if color
else ""
3576 color_end
= "\033[0m" if color
else ""
3577 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
3579 for x
in range(0, self
.LEN
/4):
3580 if self
.line_number
== 5:
3581 extra
= "Family %s (%d), Device Type %s (%d - %s)" % \
3582 (zfilled_hex(self
.family
, 2), self
.family
,
3583 zfilled_hex(self
.device_type
, 4), self
.device_type
, self
.get_link_type_string(self
.device_type
))
3584 elif self
.line_number
== 6:
3585 extra
= "Interface Index %s (%d)" % (zfilled_hex(self
.ifindex
, 8), self
.ifindex
)
3586 elif self
.line_number
== 7:
3587 extra
= "Device Flags %s (%s)" % (zfilled_hex(self
.flags
, 8), self
.get_flags_string())
3588 elif self
.line_number
== 8:
3589 extra
= "Change Mask %s" % zfilled_hex(self
.change_mask
, 8)
3591 extra
= "Unexpected line number %d" % self
.line_number
3595 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
3596 self
.line_number
+= 1
3599 if self
.flags
& Link
.IFF_UP
:
3604 class Neighbor(NetlinkPacket
):
3609 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
3610 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3611 | Family | Reserved1 | Reserved2 |
3612 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3614 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3615 | State | Flags | Type |
3616 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3619 # Neighbor attributes
3620 # /usr/include/linux/neighbour.h
3621 NDA_UNSPEC
= 0x00 # Unknown type
3622 NDA_DST
= 0x01 # A neighbour cache network. layer destination address
3623 NDA_LLADDR
= 0x02 # A neighbor cache link layer address.
3624 NDA_CACHEINFO
= 0x03 # Cache statistics
3631 NDA_LINK_NETNSID
= 0x0A
3633 attribute_to_class
= {
3634 NDA_UNSPEC
: ('NDA_UNSPEC', AttributeGeneric
),
3635 NDA_DST
: ('NDA_DST', AttributeIPAddress
),
3636 NDA_LLADDR
: ('NDA_LLADDR', AttributeMACAddress
),
3637 NDA_CACHEINFO
: ('NDA_CACHEINFO', AttributeFourByteList
),
3638 NDA_PROBES
: ('NDA_PROBES', AttributeFourByteValue
),
3639 NDA_VLAN
: ('NDA_VLAN', AttributeTwoByteValue
),
3640 NDA_PORT
: ('NDA_PORT', AttributeGeneric
),
3641 NDA_VNI
: ('NDA_VNI', AttributeFourByteValue
),
3642 NDA_IFINDEX
: ('NDA_IFINDEX', AttributeFourByteValue
),
3643 NDA_MASTER
: ('NDA_MASTER', AttributeFourByteValue
),
3644 NDA_LINK_NETNSID
: ('NDA_LINK_NETNSID', AttributeGeneric
)
3648 # /usr/include/linux/neighbour.h
3652 NTF_PROXY
= 0x08 # A proxy ARP entry
3653 NTF_EXT_LEARNED
= 0x10 # neigh entry installed by an external APP
3654 NTF_ROUTER
= 0x80 # An IPv6 router
3657 NTF_USE
: 'NTF_USE',
3658 NTF_SELF
: 'NTF_SELF',
3659 NTF_MASTER
: 'NTF_MASTER',
3660 NTF_PROXY
: 'NTF_PROXY',
3661 NTF_EXT_LEARNED
: 'NTF_EXT_LEARNED',
3662 NTF_ROUTER
: 'NTF_ROUTER'
3666 # /usr/include/linux/neighbour.h
3668 NUD_INCOMPLETE
= 0x01 # Still attempting to resolve
3669 NUD_REACHABLE
= 0x02 # A confirmed working cache entry
3670 NUD_STALE
= 0x04 # an expired cache entry
3671 NUD_DELAY
= 0x08 # Neighbor no longer reachable. Traffic sent, waiting for confirmatio.
3672 NUD_PROBE
= 0x10 # A cache entry that is currently being re-solicited
3673 NUD_FAILED
= 0x20 # An invalid cache entry
3674 NUD_NOARP
= 0x40 # A device which does not do neighbor discovery(ARP)
3675 NUD_PERMANENT
= 0x80 # A static entry
3678 NUD_NONE
: 'NUD_NONE',
3679 NUD_INCOMPLETE
: 'NUD_INCOMPLETE',
3680 NUD_REACHABLE
: 'NUD_REACHABLE',
3681 NUD_STALE
: 'NUD_STALE',
3682 NUD_DELAY
: 'NUD_DELAY',
3683 NUD_PROBE
: 'NUD_PROBE',
3684 NUD_FAILED
: 'NUD_FAILED',
3685 NUD_NOARP
: 'NUD_NOARP',
3686 NUD_PERMANENT
: 'NUD_PERMANENT'
3689 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
3690 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
3691 self
.PACK
= 'BxxxiHBB'
3692 self
.LEN
= calcsize(self
.PACK
)
3694 def get_state_string(self
, index
):
3695 return self
.get_string(self
.state_to_string
, index
)
3697 def get_states_string(self
, states
):
3700 if states
& Neighbor
.NUD_INCOMPLETE
:
3701 for_string
.append('NUD_INCOMPLETE')
3703 if states
& Neighbor
.NUD_REACHABLE
:
3704 for_string
.append('NUD_REACHABLE')
3706 if states
& Neighbor
.NUD_STALE
:
3707 for_string
.append('NUD_STALE')
3709 if states
& Neighbor
.NUD_DELAY
:
3710 for_string
.append('NUD_DELAY')
3712 if states
& Neighbor
.NUD_PROBE
:
3713 for_string
.append('NUD_PROBE')
3715 if states
& Neighbor
.NUD_FAILED
:
3716 for_string
.append('NUD_FAILED')
3718 if states
& Neighbor
.NUD_NOARP
:
3719 for_string
.append('NUD_NOARP')
3721 if states
& Neighbor
.NUD_PERMANENT
:
3722 for_string
.append('NUD_PERMANENT')
3724 return ', '.join(for_string
)
3726 def get_flags_string(self
, flags
):
3729 if flags
& Neighbor
.NTF_USE
:
3730 for_string
.append('NTF_USE')
3732 if flags
& Neighbor
.NTF_SELF
:
3733 for_string
.append('NTF_SELF')
3735 if flags
& Neighbor
.NTF_MASTER
:
3736 for_string
.append('NTF_MASTER')
3738 if flags
& Neighbor
.NTF_PROXY
:
3739 for_string
.append('NTF_PROXY')
3741 if flags
& Neighbor
.NTF_ROUTER
:
3742 for_string
.append('NTF_ROUTER')
3744 return ', '.join(for_string
)
3746 def decode_service_header(self
):
3748 # Nothing to do if the message did not contain a service header
3749 if self
.length
== self
.header_LEN
:
3754 self
.state
, self
.flags
, self
.neighbor_type
) = \
3755 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
3758 color
= yellow
if self
.use_color
else None
3759 color_start
= "\033[%dm" % color
if color
else ""
3760 color_end
= "\033[0m" if color
else ""
3761 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
3763 for x
in range(0, self
.LEN
/4):
3764 if self
.line_number
== 5:
3765 extra
= "Family %s (%d)" % (zfilled_hex(self
.family
, 2), self
.family
)
3766 elif self
.line_number
== 6:
3767 extra
= "Interface Index %s (%d)" % (zfilled_hex(self
.ifindex
, 8), self
.ifindex
)
3768 elif self
.line_number
== 7:
3769 extra
= "State %s (%d) %s, Flags %s (%s) %s, Type %s (%d)" % \
3770 (zfilled_hex(self
.state
, 4), self
.state
, self
.get_states_string(self
.state
),
3771 zfilled_hex(self
.flags
, 2), self
.flags
, self
.get_flags_string(self
.flags
),
3772 zfilled_hex(self
.neighbor_type
, 4), self
.neighbor_type
)
3774 extra
= "Unexpected line number %d" % self
.line_number
3778 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
3779 self
.line_number
+= 1
3782 class Route(NetlinkPacket
):
3787 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
3788 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3789 | Family | Dest length | Src length | TOS |
3790 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3791 | Table ID | Protocol | Scope | Type |
3792 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3794 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3798 # /usr/include/linux/rtnetlink.h
3799 RTA_UNSPEC
= 0x00 # Ignored.
3800 RTA_DST
= 0x01 # Protocol address for route destination address.
3801 RTA_SRC
= 0x02 # Protocol address for route source address.
3802 RTA_IIF
= 0x03 # Input interface index.
3803 RTA_OIF
= 0x04 # Output interface index.
3804 RTA_GATEWAY
= 0x05 # Protocol address for the gateway of the route
3805 RTA_PRIORITY
= 0x06 # Priority of broker.
3806 RTA_PREFSRC
= 0x07 # Preferred source address in cases where more than one source address could be used.
3807 RTA_METRICS
= 0x08 # Route metrics attributed to route and associated protocols(e.g., RTT, initial TCP window, etc.).
3808 RTA_MULTIPATH
= 0x09 # Multipath route next hop's attributes.
3809 RTA_PROTOINFO
= 0x0A # Firewall based policy routing attribute.
3810 RTA_FLOW
= 0x0B # Route realm.
3811 RTA_CACHEINFO
= 0x0C # Cached route information.
3816 RTA_MFC_STATS
= 0x11
3820 RTA_ENCAP_TYPE
= 0x15
3823 attribute_to_class
= {
3824 RTA_UNSPEC
: ('RTA_UNSPEC', AttributeGeneric
),
3825 RTA_DST
: ('RTA_DST', AttributeIPAddress
),
3826 RTA_SRC
: ('RTA_SRC', AttributeIPAddress
),
3827 RTA_IIF
: ('RTA_IIF', AttributeFourByteValue
),
3828 RTA_OIF
: ('RTA_OIF', AttributeFourByteValue
),
3829 RTA_GATEWAY
: ('RTA_GATEWAY', AttributeIPAddress
),
3830 RTA_PRIORITY
: ('RTA_PRIORITY', AttributeFourByteValue
),
3831 RTA_PREFSRC
: ('RTA_PREFSRC', AttributeIPAddress
),
3832 RTA_METRICS
: ('RTA_METRICS', AttributeGeneric
),
3833 RTA_MULTIPATH
: ('RTA_MULTIPATH', AttributeRTA_MULTIPATH
),
3834 RTA_PROTOINFO
: ('RTA_PROTOINFO', AttributeGeneric
),
3835 RTA_FLOW
: ('RTA_FLOW', AttributeGeneric
),
3836 RTA_CACHEINFO
: ('RTA_CACHEINFO', AttributeGeneric
),
3837 RTA_SESSION
: ('RTA_SESSION', AttributeGeneric
),
3838 RTA_MP_ALGO
: ('RTA_MP_ALGO', AttributeGeneric
),
3839 RTA_TABLE
: ('RTA_TABLE', AttributeFourByteValue
),
3840 RTA_MARK
: ('RTA_MARK', AttributeGeneric
),
3841 RTA_MFC_STATS
: ('RTA_MFC_STATS', AttributeGeneric
),
3842 RTA_VIA
: ('RTA_VIA', AttributeGeneric
),
3843 RTA_NEWDST
: ('RTA_NEWDST', AttributeGeneric
),
3844 RTA_PREF
: ('RTA_PREF', AttributeGeneric
),
3845 RTA_ENCAP_TYPE
: ('RTA_ENCAP_TYPE', AttributeGeneric
),
3846 RTA_ENCAP
: ('RTA_ENCAP', AttributeGeneric
)
3850 # /usr/include/linux/rtnetlink.h
3851 RT_TABLE_UNSPEC
= 0x00 # An unspecified routing table
3852 RT_TABLE_COMPAT
= 0xFC
3853 RT_TABLE_DEFAULT
= 0xFD # The default table
3854 RT_TABLE_MAIN
= 0xFE # The main table
3855 RT_TABLE_LOCAL
= 0xFF # The local table
3858 RT_TABLE_UNSPEC
: 'RT_TABLE_UNSPEC',
3859 RT_TABLE_COMPAT
: 'RT_TABLE_COMPAT',
3860 RT_TABLE_DEFAULT
: 'RT_TABLE_DEFAULT',
3861 RT_TABLE_MAIN
: 'RT_TABLE_MAIN',
3862 RT_TABLE_LOCAL
: 'RT_TABLE_LOCAL'
3866 # /usr/include/linux/rtnetlink.h
3867 RT_SCOPE_UNIVERSE
= 0x00 # Global route
3868 RT_SCOPE_SITE
= 0xC8 # Interior route in the local autonomous system
3869 RT_SCOPE_LINK
= 0xFD # Route on this link
3870 RT_SCOPE_HOST
= 0xFE # Route on the local host
3871 RT_SCOPE_NOWHERE
= 0xFF # Destination does not exist
3874 RT_SCOPE_UNIVERSE
: 'RT_SCOPE_UNIVERSE',
3875 RT_SCOPE_SITE
: 'RT_SCOPE_SITE',
3876 RT_SCOPE_LINK
: 'RT_SCOPE_LINK',
3877 RT_SCOPE_HOST
: 'RT_SCOPE_HOST',
3878 RT_SCOPE_NOWHERE
: 'RT_SCOPE_NOWHERE'
3881 # Route scope to string
3882 # iproute2/lib/rt_names.c
3883 rtnl_rtscope_tab
= {
3884 RT_SCOPE_UNIVERSE
: 'global',
3885 RT_SCOPE_NOWHERE
: 'nowhere',
3886 RT_SCOPE_HOST
: 'host',
3887 RT_SCOPE_LINK
: 'link',
3888 RT_SCOPE_SITE
: 'site'
3892 # /usr/include/linux/rtnetlink.h
3893 RT_PROT_UNSPEC
= 0x00 # Identifies what/who added the route
3894 RT_PROT_REDIRECT
= 0x01 # By an ICMP redirect
3895 RT_PROT_KERNEL
= 0x02 # By the kernel
3896 RT_PROT_BOOT
= 0x03 # During bootup
3897 RT_PROT_STATIC
= 0x04 # By the administrator
3898 RT_PROT_GATED
= 0x08 # GateD
3899 RT_PROT_RA
= 0x09 # RDISC/ND router advertissements
3900 RT_PROT_MRT
= 0x0A # Merit MRT
3901 RT_PROT_ZEBRA
= 0x0B # ZEBRA
3902 RT_PROT_BIRD
= 0x0C # BIRD
3903 RT_PROT_DNROUTED
= 0x0D # DECnet routing daemon
3904 RT_PROT_XORP
= 0x0E # XORP
3905 RT_PROT_NTK
= 0x0F # Netsukuku
3906 RT_PROT_DHCP
= 0x10 # DHCP client
3907 RT_PROT_EXABGP
= 0x11 # Exa Networks ExaBGP
3910 RT_PROT_UNSPEC
: 'RT_PROT_UNSPEC',
3911 RT_PROT_REDIRECT
: 'RT_PROT_REDIRECT',
3912 RT_PROT_KERNEL
: 'RT_PROT_KERNEL',
3913 RT_PROT_BOOT
: 'RT_PROT_BOOT',
3914 RT_PROT_STATIC
: 'RT_PROT_STATIC',
3915 RT_PROT_GATED
: 'RT_PROT_GATED',
3916 RT_PROT_RA
: 'RT_PROT_RA',
3917 RT_PROT_MRT
: 'RT_PROT_MRT',
3918 RT_PROT_ZEBRA
: 'RT_PROT_ZEBRA',
3919 RT_PROT_BIRD
: 'RT_PROT_BIRD',
3920 RT_PROT_DNROUTED
: 'RT_PROT_DNROUTED',
3921 RT_PROT_XORP
: 'RT_PROT_XORP',
3922 RT_PROT_NTK
: 'RT_PROT_NTK',
3923 RT_PROT_DHCP
: 'RT_PROT_DHCP',
3924 RT_PROT_EXABGP
: 'RT_PROT_EXABGP'
3928 # /usr/include/linux/rtnetlink.h
3929 RTN_UNSPEC
= 0x00 # Unknown broker.
3930 RTN_UNICAST
= 0x01 # A gateway or direct broker.
3931 RTN_LOCAL
= 0x02 # A local interface broker.
3932 RTN_BROADCAST
= 0x03 # A local broadcast route(sent as a broadcast).
3933 RTN_ANYCAST
= 0x04 # An anycast broker.
3934 RTN_MULTICAST
= 0x05 # A multicast broker.
3935 RTN_BLACKHOLE
= 0x06 # A silent packet dropping broker.
3936 RTN_UNREACHABLE
= 0x07 # An unreachable destination. Packets dropped and
3937 # host unreachable ICMPs are sent to the originator.
3938 RTN_PROHIBIT
= 0x08 # A packet rejection broker. Packets are dropped and
3939 # communication prohibited ICMPs are sent to the originator.
3940 RTN_THROW
= 0x09 # When used with policy routing, continue routing lookup
3941 # in another table. Under normal routing, packets are
3942 # dropped and net unreachable ICMPs are sent to the originator.
3943 RTN_NAT
= 0x0A # A network address translation rule.
3944 RTN_XRESOLVE
= 0x0B # Refer to an external resolver(not implemented).
3946 rt_type_to_string
= {
3947 RTN_UNSPEC
: 'RTN_UNSPEC',
3948 RTN_UNICAST
: 'RTN_UNICAST',
3949 RTN_LOCAL
: 'RTN_LOCAL',
3950 RTN_BROADCAST
: 'RTN_BROADCAST',
3951 RTN_ANYCAST
: 'RTN_ANYCAST',
3952 RTN_MULTICAST
: 'RTN_MULTICAST',
3953 RTN_BLACKHOLE
: 'RTN_BLACKHOLE',
3954 RTN_UNREACHABLE
: 'RTN_UNREACHABLE',
3955 RTN_PROHIBIT
: 'RTN_PROHIBIT',
3956 RTN_THROW
: 'RTN_THROW',
3957 RTN_NAT
: 'RTN_NAT',
3958 RTN_XRESOLVE
: 'RTN_XRESOLVE'
3962 # /usr/include/linux/rtnetlink.h
3963 RTM_F_NOTIFY
= 0x100 # If the route changes, notify the user
3964 RTM_F_CLONED
= 0x200 # Route is cloned from another route
3965 RTM_F_EQUALIZE
= 0x400 # Allow randomization of next hop path in multi-path routing(currently not implemented)
3966 RTM_F_PREFIX
= 0x800 # Prefix Address
3969 RTM_F_NOTIFY
: 'RTM_F_NOTIFY',
3970 RTM_F_CLONED
: 'RTM_F_CLONED',
3971 RTM_F_EQUALIZE
: 'RTM_F_EQUALIZE',
3972 RTM_F_PREFIX
: 'RTM_F_PREFIX'
3975 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
3976 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
3977 self
.PACK
= '=8BI' # or is it 8Bi ?
3978 self
.LEN
= calcsize(self
.PACK
)
3980 def get_prefix_string(self
):
3981 dst
= self
.get_attribute_value(self
.RTA_DST
)
3984 return "%s/%d" % (dst
, self
.src_len
)
3986 if self
.family
== AF_INET
:
3988 elif self
.family
== AF_INET6
:
3991 def get_protocol_string(self
, index
=None):
3993 index
= self
.protocol
3994 return self
.get_string(self
.prot_to_string
, index
)
3996 def get_rt_type_string(self
, index
=None):
3998 index
= self
.route_type
3999 return self
.get_string(self
.rt_type_to_string
, index
)
4001 def get_scope_string(self
, index
=None):
4004 return self
.get_string(self
.scope_to_string
, index
)
4006 def get_table_id_string(self
, index
=None):
4008 index
= self
.table_id
4009 return self
.get_string(self
.table_to_string
, index
)
4011 def _get_ifname_from_index(self
, ifindex
, ifname_by_index
):
4013 ifname
= ifname_by_index
.get(ifindex
)
4016 ifname
= str(ifindex
)
4022 def get_nexthops(self
, ifname_by_index
={}):
4023 nexthop
= self
.get_attribute_value(self
.RTA_GATEWAY
)
4024 multipath
= self
.get_attribute_value(self
.RTA_MULTIPATH
)
4028 rta_oif
= self
.get_attribute_value(self
.RTA_OIF
)
4029 ifname
= self
._get
_ifname
_from
_index
(rta_oif
, ifname_by_index
)
4030 nexthops
.append((nexthop
, ifname
))
4033 for (nexthop
, rtnh_ifindex
, rtnh_flags
, rtnh_hops
) in multipath
:
4034 ifname
= self
._get
_ifname
_from
_index
(rtnh_ifindex
, ifname_by_index
)
4035 nexthops
.append((nexthop
, ifname
))
4039 def get_nexthops_string(self
, ifname_by_index
={}):
4042 for (nexthop
, ifname
) in self
.get_nexthops(ifname_by_index
):
4043 output
.append(" via %s on %s" % (nexthop
, ifname
))
4045 return ",".join(output
)
4047 def decode_service_header(self
):
4049 # Nothing to do if the message did not contain a service header
4050 if self
.length
== self
.header_LEN
:
4053 (self
.family
, self
.src_len
, self
.dst_len
, self
.tos
,
4054 self
.table_id
, self
.protocol
, self
.scope
, self
.route_type
,
4056 unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
4059 color
= yellow
if self
.use_color
else None
4060 color_start
= "\033[%dm" % color
if color
else ""
4061 color_end
= "\033[0m" if color
else ""
4062 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
4064 for x
in range(0, self
.LEN
/4):
4065 if self
.line_number
== 5:
4066 extra
= "Family %s (%d), Source Length %s (%d), Destination Length %s (%d), TOS %s (%d)" % \
4067 (zfilled_hex(self
.family
, 2), self
.family
,
4068 zfilled_hex(self
.src_len
, 2), self
.src_len
,
4069 zfilled_hex(self
.dst_len
, 2), self
.dst_len
,
4070 zfilled_hex(self
.tos
, 2), self
.tos
)
4071 elif self
.line_number
== 6:
4072 extra
= "Table ID %s (%d - %s), Protocol %s (%d - %s), Scope %s (%d - %s), Type %s (%d - %s)" % \
4073 (zfilled_hex(self
.table_id
, 2), self
.table_id
, self
.get_table_id_string(),
4074 zfilled_hex(self
.protocol
, 2), self
.protocol
, self
.get_protocol_string(),
4075 zfilled_hex(self
.scope
, 2), self
.scope
, self
.get_scope_string(),
4076 zfilled_hex(self
.route_type
, 2), self
.route_type
, self
.get_rt_type_string())
4077 elif self
.line_number
== 7:
4078 extra
= "Flags %s" % zfilled_hex(self
.flags
, 8)
4080 extra
= "Unexpected line number %d" % self
.line_number
4084 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
4085 self
.line_number
+= 1
4087 class Done(NetlinkPacket
):
4093 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
4094 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4096 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4099 def __init__(self
, msgtype
, debug
=False, logger
=None, use_color
=True):
4100 NetlinkPacket
.__init
__(self
, msgtype
, debug
, logger
, use_color
)
4102 self
.LEN
= calcsize(self
.PACK
)
4104 def decode_service_header(self
):
4105 foo
= unpack(self
.PACK
, self
.msg_data
[:self
.LEN
])
4108 color
= yellow
if self
.use_color
else None
4109 color_start
= "\033[%dm" % color
if color
else ""
4110 color_end
= "\033[0m" if color
else ""
4111 self
.dump_buffer
.append(" %sService Header%s" % (color_start
, color_end
))
4113 for x
in range(0, self
.LEN
/4):
4117 self
.dump_buffer
.append(data_to_color_text(self
.line_number
, color
, self
.msg_data
[start
:end
], extra
))
4118 self
.line_number
+= 1