Parse and print OpenFlow 1.3 PACKET_IN and OXM (Openflow eXtended Match) -
authorreyk <reyk@openbsd.org>
Wed, 20 Jul 2016 19:57:54 +0000 (19:57 +0000)
committerreyk <reyk@openbsd.org>
Wed, 20 Jul 2016 19:57:54 +0000 (19:57 +0000)
no action yet.

usr.sbin/switchd/genmap.sh
usr.sbin/switchd/ofp.h
usr.sbin/switchd/ofp13.c
usr.sbin/switchd/ofp_map.h

index 76ecee1..b10b335 100644 (file)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $OpenBSD: genmap.sh,v 1.1 2016/07/19 16:54:26 reyk Exp $
+# $OpenBSD: genmap.sh,v 1.2 2016/07/20 19:57:54 reyk Exp $
 
 # Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
 #
@@ -58,7 +58,7 @@ tok=$(echo ${TOKEN} | tr "[:upper:]" "[:lower:]")
 INC="#include ${HEADER}"
 
 MAP=$(grep "struct constmap ${tok}_" $MAPFILE |
-       sed -Ee "s/.*${tok}_([^_]+)_map.*/\1/g")
+       sed -Ee "s/.*${tok}_(.+)_map.*/\1/g")
 
 # Print license/copyright notice and headers
 cat <<EOF
index ba9ec71..4b75752 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ofp.h,v 1.1 2016/07/19 16:54:26 reyk Exp $    */
+/*     $OpenBSD: ofp.h,v 1.2 2016/07/20 19:57:54 reyk Exp $    */
 
 /*
  * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -26,7 +26,9 @@
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 
-#define OFP_IFNAMSIZ                   16      /* on-wire (not IF_NAMSIZE) */
+#define OFP_IFNAMSIZ   16      /* on-wire (not IF_NAMSIZE) */
+#define OFP_ALIGNMENT  8       /* OFP alignment */
+#define OFP_ALIGN(_x)  (((_x) + (OFP_ALIGNMENT - 1)) & ~(OFP_ALIGNMENT - 1))
 
 struct ofp_header {
        uint8_t          oh_version;            /* OpenFlow version */
@@ -265,21 +267,21 @@ struct ofp_instruction_experimenter {
 
 /* Actions */
 #define OFP_ACTION_OUTPUT              0       /* Output to switch port */
-#define OFP_ACTION_COPY_TTL_OUT                11      /* */
-#define OFP_ACTION_COPY_TTL_IN         12      /* */
-#define OFP_ACTION_SET_MPLS_TTL                15      /* */
-#define OFP_ACTION_DEC_MPLS_TTL                16      /* */
-#define OFP_ACTION_PUSH_VLAN           17      /* */
-#define OFP_ACTION_POP_VLAN            18      /* */
-#define OFP_ACTION_PUSH_MPLS           19      /* */
-#define OFP_ACTION_POP_MPLS            20      /* */
-#define OFP_ACTION_SET_QUEUE           21      /* */
-#define OFP_ACTION_GROUP               22      /* */
-#define OFP_ACTION_SET_NW_TTL          23      /* */
-#define OFP_ACTION_DEC_NW_TTL          24      /* */
-#define OFP_ACTION_SET_FIELD           25      /* */
-#define OFP_ACTION_PUSH_PBB            26      /* */
-#define OFP_ACTION_POP_PBB             27      /* */
+#define OFP_ACTION_COPY_TTL_OUT                11      /* */
+#define OFP_ACTION_COPY_TTL_IN         12      /* */
+#define OFP_ACTION_SET_MPLS_TTL                15      /* */
+#define OFP_ACTION_DEC_MPLS_TTL                16      /* */
+#define OFP_ACTION_PUSH_VLAN           17      /* */
+#define OFP_ACTION_POP_VLAN            18      /* */
+#define OFP_ACTION_PUSH_MPLS           19      /* */
+#define OFP_ACTION_POP_MPLS            20      /* */
+#define OFP_ACTION_SET_QUEUE           21      /* */
+#define OFP_ACTION_GROUP               22      /* */
+#define OFP_ACTION_SET_NW_TTL          23      /* */
+#define OFP_ACTION_DEC_NW_TTL          24      /* */
+#define OFP_ACTION_SET_FIELD           25      /* */
+#define OFP_ACTION_PUSH_PBB            26      /* */
+#define OFP_ACTION_POP_PBB             27      /* */
 #define OFP_ACTION_EXPERIMENTER                0xffff  /* Vendor-specific action */
 
 /* Action Header */
@@ -353,64 +355,64 @@ struct ofp_packet_out {
 } __packed;
 
 /* Flow match fields for basic class */
-#define OFP_XM_T_IN_PORT               0
-#define OFP_XM_T_IN_PHY_PORT           1
-#define OFP_XM_T_META                  2
-#define OFP_XM_T_ETH_DST               3
-#define OFP_XM_T_ETH_SRC               4
-#define OFP_XM_T_ETH_TYPE              5
-#define OFP_XM_T_VLAN_VID              6
-#define OFP_XM_T_VLAN_PCP              7
-#define OFP_XM_T_IP_DSCP               8
-#define OFP_XM_T_IP_ECN                        9
-#define OFP_XM_T_IP_PROTO              10
-#define OFP_XM_T_IPV4_SRC              11
-#define OFP_XM_T_IPV4_DST              12
-#define OFP_XM_T_TCP_SRC               13
-#define OFP_XM_T_TCP_DST               14
-#define OFP_XM_T_UDP_SRC               15
-#define OFP_XM_T_UDP_DST               16
-#define OFP_XM_T_SCTP_SRC              17
-#define OFP_XM_T_SCTP_DST              18
-#define OFP_XM_T_ICMPV4_TYPE           19
-#define OFP_XM_T_ICMPV4_CODE           20
-#define OFP_XM_T_ARP_OP                        21
-#define OFP_XM_T_ARP_SPA               22
-#define OFP_XM_T_ARP_TPA               23
-#define OFP_XM_T_ARP_SHA               24
-#define OFP_XM_T_ARP_THA               25
-#define OFP_XM_T_IPV6_SRC              26
-#define OFP_XM_T_IPV6_DST              27
-#define OFP_XM_T_IPV6_FLABEL           28
-#define OFP_XM_T_ICMPV6_TYPE           29
-#define OFP_XM_T_ICMPV6_CODE           30
-#define OFP_XM_T_IPV6_ND_TARGET                31
-#define OFP_XM_T_IPV6_ND_SLL           32
-#define OFP_XM_T_IPV6_ND_TLL           33
-#define OFP_XM_T_MPLS_LABEL            34
-#define OFP_XM_T_MPLS_TC               35
-#define OFP_XM_T_MPLS_BOS              36
-#define OFP_XM_T_PBB_ISID              37
-#define OFP_XM_T_TUNNEL_ID             38
-#define OFP_XM_T_IPV6_EXTHDR           39
-#define OFP_XM_T_MAX                   40
+#define OFP_XM_T_IN_PORT               0       /* ? */
+#define OFP_XM_T_IN_PHY_PORT           1       /* ? */
+#define OFP_XM_T_META                  2       /* ? */
+#define OFP_XM_T_ETH_DST               3       /* ? */
+#define OFP_XM_T_ETH_SRC               4       /* ? */
+#define OFP_XM_T_ETH_TYPE              5       /* ? */
+#define OFP_XM_T_VLAN_VID              6       /* ? */
+#define OFP_XM_T_VLAN_PCP              7       /* ? */
+#define OFP_XM_T_IP_DSCP               8       /* ? */
+#define OFP_XM_T_IP_ECN                        9       /* ? */
+#define OFP_XM_T_IP_PROTO              10      /* ? */
+#define OFP_XM_T_IPV4_SRC              11      /* ? */
+#define OFP_XM_T_IPV4_DST              12      /* ? */
+#define OFP_XM_T_TCP_SRC               13      /* ? */
+#define OFP_XM_T_TCP_DST               14      /* ? */
+#define OFP_XM_T_UDP_SRC               15      /* ? */
+#define OFP_XM_T_UDP_DST               16      /* ? */
+#define OFP_XM_T_SCTP_SRC              17      /* ? */
+#define OFP_XM_T_SCTP_DST              18      /* ? */
+#define OFP_XM_T_ICMPV4_TYPE           19      /* ? */
+#define OFP_XM_T_ICMPV4_CODE           20      /* ? */
+#define OFP_XM_T_ARP_OP                        21      /* ? */
+#define OFP_XM_T_ARP_SPA               22      /* ? */
+#define OFP_XM_T_ARP_TPA               23      /* ? */
+#define OFP_XM_T_ARP_SHA               24      /* ? */
+#define OFP_XM_T_ARP_THA               25      /* ? */
+#define OFP_XM_T_IPV6_SRC              26      /* ? */
+#define OFP_XM_T_IPV6_DST              27      /* ? */
+#define OFP_XM_T_IPV6_FLABEL           28      /* ? */
+#define OFP_XM_T_ICMPV6_TYPE           29      /* ? */
+#define OFP_XM_T_ICMPV6_CODE           30      /* ? */
+#define OFP_XM_T_IPV6_ND_TARGET                31      /* ? */
+#define OFP_XM_T_IPV6_ND_SLL           32      /* ? */
+#define OFP_XM_T_IPV6_ND_TLL           33      /* ? */
+#define OFP_XM_T_MPLS_LABEL            34      /* ? */
+#define OFP_XM_T_MPLS_TC               35      /* ? */
+#define OFP_XM_T_MPLS_BOS              36      /* ? */
+#define OFP_XM_T_PBB_ISID              37      /* ? */
+#define OFP_XM_T_TUNNEL_ID             38      /* ? */
+#define OFP_XM_T_IPV6_EXTHDR           39      /* ? */
+#define OFP_XM_T_MAX                   40      /* ? */
 
 /* Flow match fields for nxm1 class */
-#define OFP_XM_NXMT_TUNNEL_ID          38
-#define OFP_XM_NXMT_TUNNEL_IPV4_SRC    31
-#define OFP_XM_NXMT_TUNNEL_IPV4_DST    32
-#define OFP_XM_NXMT_TUNNEL_IPV6_SRC    109
-#define OFP_XM_NXMT_TUNNEL_IPV6_DST    110
+#define OFP_XM_NXMT_TUNNEL_ID          38      /* ? */
+#define OFP_XM_NXMT_TUNNEL_IPV4_SRC    31      /* ? */
+#define OFP_XM_NXMT_TUNNEL_IPV4_DST    32      /* ? */
+#define OFP_XM_NXMT_TUNNEL_IPV6_SRC    109     /* ? */
+#define OFP_XM_NXMT_TUNNEL_IPV6_DST    110     /* ? */
 
 /* OXM class */
-#define OFP_OXM_C_NXM_0                        0x0000
-#define OFP_OXM_C_NXM_1                        0x0001
-#define OFP_OXM_C_OPENFLOW_BASIC       0x8000
-#define OFP_OXM_C_OPENFLOW_EXPERIMENTER        0xffff
+#define OFP_OXM_C_NXM_0                        0x0000  /* NXM 0 */
+#define OFP_OXM_C_NXM_1                        0x0001  /* NXM 1 */
+#define OFP_OXM_C_OPENFLOW_BASIC       0x8000  /* OpenFlow Basic */
+#define OFP_OXM_C_OPENFLOW_EXPERIMENTER        0xffff  /* OpenFlow Experimenter */
 
 /* VLAN matching flag */
-#define OFP_XM_VID_PRESENT             0x1000
-#define OFP_XM_VID_NONE                        0x0000
+#define OFP_XM_VID_PRESENT             0x1000  /* VLAN ID present */
+#define OFP_XM_VID_NONE                        0x0000  /* No VLAN ID */
 
 struct ofp_ox_match {
        uint16_t        oxm_class;
index 8c850a5..9403f63 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ofp13.c,v 1.2 2016/07/20 14:15:08 reyk Exp $  */
+/*     $OpenBSD: ofp13.c,v 1.3 2016/07/20 19:57:54 reyk Exp $  */
 
 /*
  * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -28,6 +28,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stddef.h>
 #include <unistd.h>
 #include <string.h>
 #include <fcntl.h>
@@ -55,6 +56,8 @@ void   ofp13_debug(struct switchd *,
 void    ofp13_debug_header(struct switchd *,
            struct sockaddr_storage *, struct sockaddr_storage *,
            struct ofp_header *);
+int     ofp13_debug_oxm(struct switchd *, struct ofp_ox_match *,
+           struct ofp_header *, struct ibuf *, off_t);
 int     ofp13_debug_packet_in(struct switchd *,
            struct sockaddr_storage *, struct sockaddr_storage *,
            struct ofp_header *, struct ibuf *);
@@ -131,15 +134,55 @@ ofp13_debug(struct switchd *sc,
        log_debug("\tinvalid packet");
 }
 
+int
+ofp13_debug_oxm(struct switchd *sc, struct ofp_ox_match *oxm,
+   struct ofp_header *oh, struct ibuf *ibuf, off_t off)
+{
+       uint16_t         class;
+       uint8_t          type;
+       uint32_t         port;
+       void            *ptr;
+
+       /* match element is always followed by data */
+       if (oxm->oxm_length == 0)
+               return (0);
+
+       type = OFP_OXM_GET_FIELD(oxm);
+       class = ntohs(oxm->oxm_class);
+
+       log_debug("\tox match class %s type %s length %u",
+           print_map(class, ofp_oxm_map),
+           print_map(type, ofp_xm_t_map),
+           oxm->oxm_length);
+
+       switch (class) {
+       case OFP_OXM_C_OPENFLOW_BASIC:
+               switch (type) {
+               case OFP_XM_T_IN_PORT:
+                       off += sizeof(*oxm);
+                       if ((ptr = ibuf_seek(ibuf, off, sizeof(port))) == NULL)
+                               return (-1);
+                       port = *(uint32_t *)ptr;
+                       log_debug("\t\tport %u", ntohl(port));
+                       break;
+               }
+               break;
+       }
+
+       return (0);
+}
+
 int
 ofp13_debug_packet_in(struct switchd *sc,
     struct sockaddr_storage *src, struct sockaddr_storage *dst,
     struct ofp_header *oh, struct ibuf *ibuf)
 {
        struct ofp_packet_in    *pin;
+       struct ofp_match        *om;
+       struct ofp_ox_match     *oxm;
        uint8_t                 *p;
-       size_t                   len;
-       off_t                    off;
+       ssize_t                  len, mlen;
+       off_t                    moff, off;
 
        off = 0;
        if ((pin = ibuf_seek(ibuf, off, sizeof(*pin))) == NULL)
@@ -150,8 +193,36 @@ ofp13_debug_packet_in(struct switchd *sc,
            print_map(ntohs(pin->pin_reason), ofp_pktin_map),
            pin->pin_table_id,
            be64toh(pin->pin_cookie));
+       off += offsetof(struct ofp_packet_in, pin_match);
+
+       om = &pin->pin_match;
+       mlen = ntohs(om->om_length);
+       log_debug("\tmatch type %s length %zu (padded to %zu)",
+           print_map(ntohs(om->om_type), ofp_match_map),
+           mlen, OFP_ALIGN(mlen) + ETHER_ALIGN);
+
+       /* current match offset, aligned offset after all matches */
+       moff = off + sizeof(*om);
+       off += OFP_ALIGN(mlen) + ETHER_ALIGN;
+
+       switch (htons(om->om_type)) {
+       case OFP_MATCH_OXM:
+               do {
+                       if ((oxm = ibuf_seek(ibuf, moff, sizeof(*oxm))) == NULL)
+                               return (-1);
+                       if (ofp13_debug_oxm(sc, oxm, oh, ibuf, moff) == -1)
+                               return (-1);
+                       moff += sizeof(*oxm) + oxm->oxm_length;
+                       mlen -= sizeof(*oxm) + oxm->oxm_length;
+               } while (mlen > 0 && oxm->oxm_length);
+               break;
+       case OFP_MATCH_STANDARD:
+               /* deprecated */
+               break;
+       }
+
+       /* Calculate offset from the beginning */
        len = ntohs(pin->pin_total_len);
-       off += sizeof(*pin);
        if ((p = ibuf_seek(ibuf, off, len)) == NULL)
                return (-1);
        if (sc->sc_tap != -1)
index a9613ab..63d3b30 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ofp_map.h,v 1.2 2016/07/20 14:15:08 reyk Exp $        */
+/*     $OpenBSD: ofp_map.h,v 1.3 2016/07/20 19:57:54 reyk Exp $        */
 
 /*
  * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -37,9 +37,10 @@ extern struct constmap ofp10_errflowmod_map[];
 /* OpenFlow 1.3+ maps */
 extern struct constmap ofp_v_map[];
 extern struct constmap ofp_t_map[];
-extern struct constmap ofp_hi_map[];
 extern struct constmap ofp_pktin_map[];
 extern struct constmap ofp_port_map[];
+extern struct constmap ofp_oxm_map[];
+extern struct constmap ofp_xm_t_map[];
 extern struct constmap ofp_config_map[];
 extern struct constmap ofp_portstate_map[];
 extern struct constmap ofp_portconfig_map[];