]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-openflow-1.0.c
OpenFlow: Use bittok2str(), fix OF1.0 port status.
[tcpdump] / print-openflow-1.0.c
index 473a8dc31a9342bdac744f9a18a79ec523401b14..dd42866a89ff3cf15b1fca5748427928aa8261fd 100644 (file)
@@ -144,14 +144,18 @@ static const struct tok ofppc_bm[] = {
                    OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \
                    OFPPC_NO_PACKET_IN))
 
-#define OFPPS_LINK_DOWN   (1U << 0)
-#define OFPPS_STP_LISTEN  (0U << 8)
-#define OFPPS_STP_LEARN   (1U << 8)
-#define OFPPS_STP_FORWARD (2U << 8)
-#define OFPPS_STP_BLOCK   (3U << 8)
-#define OFPPS_STP_MASK    (3U << 8)
-static const struct tok ofpps_bm[] = {
-       { OFPPS_LINK_DOWN,   "LINK_DOWN"   },
+/*
+ * [OF10] lists all FPPS_ constants in one enum, but they mean a 1-bit bitmap
+ * in the least significant octet and a 2-bit code point in the next octet.
+ * Remember to mix or to separate these two parts as the context requires.
+ */
+#define OFPPS_LINK_DOWN   (1U << 0) /* bitmap             */
+#define OFPPS_STP_LISTEN  (0U << 8) /* code point         */
+#define OFPPS_STP_LEARN   (1U << 8) /* code point         */
+#define OFPPS_STP_FORWARD (2U << 8) /* code point         */
+#define OFPPS_STP_BLOCK   (3U << 8) /* code point         */
+#define OFPPS_STP_MASK    (3U << 8) /* code point bitmask */
+static const struct tok ofpps_stp_str[] = {
        { OFPPS_STP_LISTEN,  "STP_LISTEN"  },
        { OFPPS_STP_LEARN,   "STP_LEARN"   },
        { OFPPS_STP_FORWARD, "STP_FORWARD" },
@@ -456,7 +460,6 @@ static const struct tok ofpet_str[] = {
        { OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" },
        { 0, NULL }
 };
-#define OFPET_MAX OFPET_QUEUE_OP_FAILED /* for of10_error_print() */
 
 #define OFPHFC_INCOMPATIBLE 0x0000U
 #define OFPHFC_EPERM        0x0001U
@@ -544,6 +547,16 @@ static const struct tok ofpqofc_str[] = {
        { 0, NULL }
 };
 
+static const struct uint_tokary of10_ofpet2tokary[] = {
+       { OFPET_HELLO_FAILED,    ofphfc_str  },
+       { OFPET_BAD_REQUEST,     ofpbrc_str  },
+       { OFPET_BAD_ACTION,      ofpbac_str  },
+       { OFPET_FLOW_MOD_FAILED, ofpfmfc_str },
+       { OFPET_PORT_MOD_FAILED, ofppmfc_str },
+       { OFPET_QUEUE_OP_FAILED, ofpqofc_str },
+       /* uint2tokary() does not use array termination. */
+};
+
 /* lengths (fixed or minimal) of particular protocol structures */
 #define OF_SWITCH_CONFIG_FIXLEN               12
 #define OF_PHY_PORT_FIXLEN                    48
@@ -682,6 +695,12 @@ static const struct tok bsn_onoff_str[] = {
        { 0, NULL },
 };
 
+/* [OF10] Section 5.1 */
+const char * of10_msgtype_str(const uint8_t type)
+{
+       return tok2str(ofpt_str, "invalid (0x%02x)", type);
+}
+
 static const char *
 vlan_str(const uint16_t vid)
 {
@@ -703,24 +722,6 @@ pcp_str(const uint8_t pcp)
        return buf;
 }
 
-static void
-of10_bitmap_print(netdissect_options *ndo,
-                  const struct tok *t, const uint32_t v, const uint32_t u)
-{
-       const char *sep = " (";
-
-       if (v == 0)
-               return;
-       /* assigned bits */
-       for (; t->s != NULL; t++)
-               if (v & t->v) {
-                       ND_PRINT("%s%s", sep, t->s);
-                       sep = ", ";
-               }
-       /* unassigned bits? */
-       ND_PRINT((v & u) ? ") (bogus)" : ")");
-}
-
 static void
 of10_bsn_message_print(netdissect_options *ndo,
                        const u_char *cp, u_int len)
@@ -1061,6 +1062,8 @@ of10_phy_ports_print(netdissect_options *ndo,
                      const u_char *cp, u_int len)
 {
        while (len) {
+               uint32_t state;
+
                if (len < OF_PHY_PORT_FIXLEN)
                        goto invalid;
                /* port_no */
@@ -1082,27 +1085,35 @@ of10_phy_ports_print(netdissect_options *ndo,
                }
                /* config */
                ND_PRINT("\n\t   config 0x%08x", GET_BE_U_4(cp));
-               of10_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
+               of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
                OF_FWD(4);
                /* state */
-               ND_PRINT("\n\t   state 0x%08x", GET_BE_U_4(cp));
-               of10_bitmap_print(ndo, ofpps_bm, GET_BE_U_4(cp), OFPPS_U);
+               state = GET_BE_U_4(cp);
+               /*
+                * Decode the code point and the single bit separately, but
+                * format the result as a single sequence of comma-separated
+                * strings (see the comments at the OFPPS_ props).
+                */
+               ND_PRINT("\n\t   state 0x%08x (%s%s)%s", state,
+                        tok2str(ofpps_stp_str, "", state & OFPPS_STP_MASK),
+                        state & OFPPS_LINK_DOWN ? ", LINK_DOWN" : "",
+                        state & OFPPS_U ? " (bogus)" : "");
                OF_FWD(4);
                /* curr */
                ND_PRINT("\n\t   curr 0x%08x", GET_BE_U_4(cp));
-               of10_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
+               of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
                OF_FWD(4);
                /* advertised */
                ND_PRINT("\n\t   advertised 0x%08x", GET_BE_U_4(cp));
-               of10_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
+               of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
                OF_FWD(4);
                /* supported */
                ND_PRINT("\n\t   supported 0x%08x", GET_BE_U_4(cp));
-               of10_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
+               of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
                OF_FWD(4);
                /* peer */
                ND_PRINT("\n\t   peer 0x%08x", GET_BE_U_4(cp));
-               of10_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
+               of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
                OF_FWD(4);
        } /* while */
        return;
@@ -1482,11 +1493,11 @@ of10_features_reply_print(netdissect_options *ndo,
        OF_FWD(3);
        /* capabilities */
        ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp));
-       of10_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U);
+       of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U);
        OF_FWD(4);
        /* actions */
        ND_PRINT("\n\t actions 0x%08x", GET_BE_U_4(cp));
-       of10_bitmap_print(ndo, ofpat_bm, GET_BE_U_4(cp), OFPAT_U);
+       of_bitmap_print(ndo, ofpat_bm, GET_BE_U_4(cp), OFPAT_U);
        OF_FWD(4);
        /* ports */
        of10_phy_ports_print(ndo, cp, len);
@@ -1534,7 +1545,7 @@ of10_flow_mod_print(netdissect_options *ndo,
        OF_FWD(2);
        /* flags */
        ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
-       of10_bitmap_print(ndo, ofpff_bm, GET_BE_U_2(cp), OFPFF_U);
+       of_bitmap_print(ndo, ofpff_bm, GET_BE_U_2(cp), OFPFF_U);
        OF_FWD(2);
        /* actions */
        of10_actions_print(ndo, "\n\t ", cp, len);
@@ -1553,15 +1564,15 @@ of10_port_mod_print(netdissect_options *ndo,
        cp += MAC_ADDR_LEN;
        /* config */
        ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
-       of10_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
+       of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
        cp += 4;
        /* mask */
        ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp));
-       of10_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
+       of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
        cp += 4;
        /* advertise */
        ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp));
-       of10_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
+       of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
        cp += 4;
        /* pad */
        /* Always the last field, check bounds. */
@@ -1790,7 +1801,7 @@ of10_table_stats_reply_print(netdissect_options *ndo,
                OF_FWD(OFP_MAX_TABLE_NAME_LEN);
                /* wildcards */
                ND_PRINT("\n\t  wildcards 0x%08x", GET_BE_U_4(cp));
-               of10_bitmap_print(ndo, ofpfw_bm, GET_BE_U_4(cp), OFPFW_U);
+               of_bitmap_print(ndo, ofpfw_bm, GET_BE_U_4(cp), OFPFW_U);
                OF_FWD(4);
                /* max_entries */
                ND_PRINT("\n\t  max_entries %u", GET_BE_U_4(cp));
@@ -1921,7 +1932,7 @@ of10_stats_reply_print(netdissect_options *ndo,
        OF_FWD(2);
        /* flags */
        ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
-       of10_bitmap_print(ndo, ofpsf_reply_bm, GET_BE_U_2(cp), OFPSF_REPLY_U);
+       of_bitmap_print(ndo, ofpsf_reply_bm, GET_BE_U_2(cp), OFPSF_REPLY_U);
        OF_FWD(2);
 
        if (ndo->ndo_vflag > 0) {
@@ -2044,14 +2055,7 @@ of10_error_print(netdissect_options *ndo,
                  const u_char *cp, u_int len)
 {
        uint16_t type, code;
-       const struct tok *code_str[OFPET_MAX + 1] = {
-               /* [OFPET_HELLO_FAILED   ] = */ ofphfc_str,
-               /* [OFPET_BAD_REQUEST    ] = */ ofpbrc_str,
-               /* [OFPET_BAD_ACTION     ] = */ ofpbac_str,
-               /* [OFPET_FLOW_MOD_FAILED] = */ ofpfmfc_str,
-               /* [OFPET_PORT_MOD_FAILED] = */ ofppmfc_str,
-               /* [OFPET_QUEUE_OP_FAILED] = */ ofpqofc_str,
-       };
+       const struct tok *code_str;
 
        /* type */
        type = GET_BE_U_2(cp);
@@ -2060,9 +2064,10 @@ of10_error_print(netdissect_options *ndo,
        /* code */
        code = GET_BE_U_2(cp);
        OF_FWD(2);
-       if (type <= OFPET_MAX && code_str[type] != NULL)
+       code_str = uint2tokary(of10_ofpet2tokary, type);
+       if (code_str != NULL)
                ND_PRINT(", code %s",
-                        tok2str(code_str[type], "invalid (0x%04x)", code));
+                        tok2str(code_str, "invalid (0x%04x)", code));
        else
                ND_PRINT(", code invalid (0x%04x)", code);
        /* data */
@@ -2070,17 +2075,15 @@ of10_error_print(netdissect_options *ndo,
 }
 
 void
-of10_header_body_print(netdissect_options *ndo,
-                       const u_char *cp, const uint8_t type,
-                       uint16_t len, const uint32_t xid)
+of10_message_print(netdissect_options *ndo,
+                   const u_char *cp, uint16_t len, const uint8_t type)
 {
        /*
         * Here "cp" and "len" stand for the message part beyond the common
-        * OpenFlow 1.0 header, if any. Add OF_HEADER_FIXLEN when printing the
-        * message header. Subtract OF_HEADER_FIXLEN from the type-specific
-        * lengths, which include the header length, when (and only when)
-        * validating the length in this function, which is the only one in
-        * this file that needs to know about OF_HEADER_FIXLEN.
+        * OpenFlow 1.0 header, if any. Subtract OF_HEADER_FIXLEN from the
+        * type-specific lengths, which include the header length, when (and
+        * only when) validating the length in this function. No other code
+        * in this file needs to take OF_HEADER_FIXLEN into account.
         *
         * Most message types are longer than just the header, and the length
         * constraints may be complex. When possible, validate the constraint
@@ -2088,11 +2091,6 @@ of10_header_body_print(netdissect_options *ndo,
         * begin the decoding and let the lower-layer function do any remaining
         * validation.
         */
-
-       /* [OF10] Section 5.1 */
-       ND_PRINT("\n\tversion 1.0, type %s, length %u, xid 0x%08x",
-                tok2str(ofpt_str, "invalid (0x%02x)", type),
-                OF_HEADER_FIXLEN + len, xid);
        switch (type) {
        /* OpenFlow header only. */
        case OFPT_FEATURES_REQUEST: /* [OF10] Section 5.3.1 */