]> git.proxmox.com Git - mirror_ifupdown2.git/commitdiff
nlpacket:: add netconf support (RTM_GETNETCONF/RTM_NEWNETCONF)
authorJulien Fortin <julien@cumulusnetworks.com>
Wed, 29 Aug 2018 15:21:54 +0000 (17:21 +0200)
committerJulien Fortin <julien@cumulusnetworks.com>
Thu, 13 Dec 2018 22:43:57 +0000 (14:43 -0800)
$ cd python-nlmanager/examples
$ ./netconf_show.py
    2018-06-01 16:59:02,398   DEBUG: TXed RTM_GETNETCONF, length 32, seq 1, pid 14202, flags 0x0 ()

      Netlink Header
       1: 0x20000000   ...  Length 0x00000020 (32)
       2: 0x52000503  R...  Type 0x0052 (82 - RTM_GETNETCONF), Flags 0x0305 (NLM_F_REQUEST, NLM_F_ACK, NLM_F_DUMP)
       3: 0x01000000  ....  Sequence Number 0x00000001 (1)
       4: 0x7a370000  z7..  Process ID 0x0000377a (14202)
      Service Header
       5: 0x00000000  ....  Family 0x00 (0), Device Type 0x0000 (0 - ARPHRD_NETROM)
       6: 0x00000000  ....  Interface Index 0x00000000 (0)
       7: 0x00000000  ....  Device Flags 0x00000000 ()
       8: 0x00000000  ....  Change Mask 0x00000000
      Attributes

    Attributes Summary
    {}

    2018-06-01 16:59:02,401   DEBUG: RXed RTM_NEWNETCONF, length 68, seq 1, pid 14202, flags 0x2

      Netlink Header
       1: 0x44000000  D...  Length 0x00000044 (68)
       2: 0x50000200  P...  Type 0x0050 (80 - RTM_NEWNETCONF), Flags 0x0002 (NLM_F_MULTI)
       3: 0x01000000  ....  Sequence Number 0x00000001 (1)
       4: 0x7a370000  z7..  Process ID 0x0000377a (14202)
      Service Header
       1: 0x00000002  ....  Family 0x02 (2)
      Attributes
       5: 0x08000100  ....  Length 0x0008 (8), Type 0x0001 (1) NETCONFA_IFINDEX
       6: 0x01000000  ....  1
       7: 0x08000200  ....  Length 0x0008 (8), Type 0x0002 (2) NETCONFA_FORWARDING
       8: 0x01000000  ....  1
       9: 0x08000300  ....  Length 0x0008 (8), Type 0x0003 (3) NETCONFA_RP_FILTER
      10: 0x00000000  ....  0
      11: 0x08000400  ....  Length 0x0008 (8), Type 0x0004 (4) NETCONFA_MC_FORWARDING
      12: 0x00000000  ....  0
      13: 0x08000500  ....  Length 0x0008 (8), Type 0x0005 (5) NETCONFA_PROXY_NEIGH
      14: 0x00000000  ....  0
      15: 0x08000600  ....  Length 0x0008 (8), Type 0x0006 (6) NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN
      16: 0x01000000  ....  1

    Attributes Summary
    {'( 1) NETCONFA_IFINDEX': 1,
     '( 2) NETCONFA_FORWARDING': 1,
     '( 3) NETCONFA_RP_FILTER': 0,
     '( 4) NETCONFA_MC_FORWARDING': 0,
     '( 5) NETCONFA_PROXY_NEIGH': 0,
     '( 6) NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN': 1}

Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
ifupdown2/nlmanager/nlmanager.py
ifupdown2/nlmanager/nlpacket.py

index 9110a0b5d1d804c598441cc14c731e7686b5a686..baa0023267386747fcc2d82dbc94dd3c91d17645 100644 (file)
@@ -129,6 +129,9 @@ class NetlinkManager(object):
     def debug_route(self, enabled):
         self._debug_set_clear((RTM_NEWROUTE, RTM_DELROUTE, RTM_GETROUTE), enabled)
 
+    def debug_netconf(self, enabled):
+        self._debug_set_clear((RTM_GETNETCONF, RTM_NEWNETCONF), enabled)
+
     def debug_this_packet(self, mtype):
         if mtype in self.debug:
             return True
@@ -328,6 +331,9 @@ class NetlinkManager(object):
                         elif msgtype == RTM_NEWROUTE or msgtype == RTM_DELROUTE:
                             msg = Route(msgtype, nlpacket.debug, use_color=self.use_color)
 
+                        elif msgtype in (RTM_GETNETCONF, RTM_NEWNETCONF):
+                            msg = Netconf(msgtype, nlpacket.debug, use_color=self.use_color)
+
                         else:
                             raise Exception("RXed unknown netlink message type %s" % msgtype)
 
@@ -1019,3 +1025,20 @@ class NetlinkManager(object):
 
         msg.build_message(self.sequence.next(), self.pid)
         return self.tx_nlpacket_get_response(msg)
+
+    # =======
+    # Netconf
+    # =======
+    def netconf_dump(self):
+        """
+            The attribute Netconf.NETCONFA_IFINDEX is available but don't let it fool you
+            it seems like the kernel doesn't really care about this attribute and will dump
+            everything according of the requested family (AF_UNSPEC for everything).
+            Device filtering needs to be done afterwards by the user.
+        """
+        debug = RTM_GETNETCONF in self.debug
+        msg = Netconf(RTM_GETNETCONF, debug, use_color=self.use_color)
+        msg.body = pack('Bxxxiii', socket.AF_UNSPEC, 0, 0, 0)
+        msg.flags = NLM_F_REQUEST | NLM_F_DUMP | NLM_F_ACK
+        msg.build_message(self.sequence.next(), self.pid)
+        return self.tx_nlpacket_get_response(msg)
index 470ec88eff62506ebef52307855e184792cfeb44..6515b78e040b2e9830da5487d8183565e6f0e4be 100644 (file)
@@ -71,6 +71,9 @@ RTM_NEWQDISC  = 0x24
 RTM_DELQDISC  = 0x25
 RTM_GETQDISC  = 0x26
 
+RTM_NEWNETCONF = 80
+RTM_GETNETCONF = 82
+
 # Netlink message flags
 NLM_F_REQUEST = 0x01  # It is query message.
 NLM_F_MULTI   = 0x02  # Multipart message, terminated by NLMSG_DONE
@@ -2219,7 +2222,9 @@ class NetlinkPacket(object):
         RTM_GETROUTE  : 'RTM_GETROUTE',
         RTM_NEWQDISC  : 'RTM_NEWQDISC',
         RTM_DELQDISC  : 'RTM_DELQDISC',
-        RTM_GETQDISC  : 'RTM_GETQDISC'
+        RTM_GETQDISC  : 'RTM_GETQDISC',
+        RTM_NEWNETCONF: 'RTM_NEWNETCONF',
+        RTM_GETNETCONF: 'RTM_GETNETCONF'
     }
 
     af_family_to_string = {
@@ -2299,7 +2304,7 @@ class NetlinkPacket(object):
             foo.append('NLM_F_ECHO')
 
         # Modifiers to GET query
-        if msg_type in (RTM_GETLINK, RTM_GETADDR, RTM_GETNEIGH, RTM_GETROUTE, RTM_GETQDISC):
+        if msg_type in (RTM_GETLINK, RTM_GETADDR, RTM_GETNEIGH, RTM_GETROUTE, RTM_GETQDISC, RTM_GETNETCONF):
             if flags & NLM_F_DUMP:
                 foo.append('NLM_F_DUMP')
             else:
@@ -2433,7 +2438,7 @@ class NetlinkPacket(object):
             take the family into account. For now we'll handle this as a special case for
             MPLS but long term we may need to make key a tuple of the attr_type and family.
             '''
-            if attr_type == Route.RTA_DST and self.family == AF_MPLS:
+            if self.msgtype not in (RTM_NEWNETCONF, RTM_GETNETCONF) and attr_type == Route.RTA_DST and self.family == AF_MPLS:
                 attr_string = 'RTA_DST'
                 attr_class = AttributeMplsLabel
 
@@ -3721,6 +3726,95 @@ class Link(NetlinkPacket):
         return False
 
 
+class Netconf(Link):
+    """
+    RTM_NEWNETCONF - Service Header
+
+    0               1
+    0 1 2 3 4 5 6 7 8
+    +-+-+-+-+-+-+-+-+
+    |   Family      |
+    +-+-+-+-+-+-+-+-+
+
+    RTM_GETNETCONF - Service Header
+
+     0                   1                   2                   3
+     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
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |   Family    |   Reserved  |          Device Type              |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                     Interface Index                           |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                      Device Flags                             |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                      Change Mask                              |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    """
+    # Netconf attributes
+    # /usr/include/linux/netconf.h
+    NETCONFA_UNSPEC                         = 0
+    NETCONFA_IFINDEX                        = 1
+    NETCONFA_FORWARDING                     = 2
+    NETCONFA_RP_FILTER                      = 3
+    NETCONFA_MC_FORWARDING                  = 4
+    NETCONFA_PROXY_NEIGH                    = 5
+    NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN    = 6
+    NETCONFA_INPUT                          = 7
+    __NETCONFA_MAX                          = 8
+
+    NETCONFA_MAX                            = (__NETCONFA_MAX - 1)
+
+    NETCONFA_ALL                            = -1
+    NETCONFA_IFINDEX_ALL                    = -1
+    NETCONFA_IFINDEX_DEFAULT                = -2
+
+    NETCONF_ATTR_FAMILY = 0x0001
+    NETCONF_ATTR_IFINDEX = 0x0002
+    NETCONF_ATTR_RP_FILTER = 0x0004
+    NETCONF_ATTR_FWDING        = 0x0008
+    NETCONF_ATTR_MC_FWDING = 0x0010
+    NETCONF_ATTR_PROXY_NEIGH = 0x0020
+    NETCONF_ATTR_IGNORE_RT_LINKDWN = 0x0040
+
+    attribute_to_class = {
+        NETCONFA_UNSPEC                         : ('NETCONFA_UNSPEC', AttributeGeneric),
+        NETCONFA_IFINDEX                        : ('NETCONFA_IFINDEX', AttributeFourByteValue),
+        NETCONFA_FORWARDING                     : ('NETCONFA_FORWARDING', AttributeFourByteValue),
+        NETCONFA_RP_FILTER                      : ('NETCONFA_RP_FILTER', AttributeFourByteValue),
+        NETCONFA_MC_FORWARDING                  : ('NETCONFA_MC_FORWARDING', AttributeFourByteValue),
+        NETCONFA_PROXY_NEIGH                    : ('NETCONFA_PROXY_NEIGH', AttributeFourByteValue),
+        NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN    : ('NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN', AttributeFourByteValue),
+        NETCONFA_INPUT                          : ('NETCONFA_INPUT', AttributeFourByteValue),
+    }
+
+    def __init__(self, msgtype, debug=False, logger=None, use_color=True):
+        NetlinkPacket.__init__(self, msgtype, debug, logger, use_color)
+        if msgtype == RTM_GETNETCONF:  # same as RTM_GETLINK
+            self.PACK = 'BxHiII'
+            self.LEN  = calcsize(self.PACK)
+        elif msgtype == RTM_NEWNETCONF:
+            self.PACK = 'Bxxx'
+            self.LEN  = calcsize(self.PACK)
+
+    def decode_service_header(self):
+        # Nothing to do if the message did not contain a service header
+        if self.length == self.header_LEN:
+            return
+
+        if self.msgtype == RTM_GETNETCONF:
+            super(Netconf, self).decode_service_header()
+
+        elif self.msgtype == RTM_NEWNETCONF:
+            (self.family,) = unpack(self.PACK, self.msg_data[:self.LEN])
+
+            if self.debug:
+                color = yellow if self.use_color else None
+                color_start = "\033[%dm" % color if color else ""
+                color_end = "\033[0m" if color else ""
+                self.dump_buffer.append("  %sService Header%s" % (color_start, color_end))
+                self.dump_buffer.append(data_to_color_text(1, color, bytearray(struct.pack('!I', self.family)), "Family %s (%d)" % (zfilled_hex(self.family, 2), self.family)))
+
+
 class Neighbor(NetlinkPacket):
     """
     Service Header