]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-openflow-1.0.c
OpenFlow 1.3: Implement OFPT_FEATURES_REPLY.
[tcpdump] / print-openflow-1.0.c
index 4548f4eee8e4671b944846afb04914b038cce3bd..6e659b30c9a6cece38a8b171136edf4dc5188278 100644 (file)
@@ -456,6 +456,7 @@ 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
@@ -543,10 +544,6 @@ static const struct tok ofpqofc_str[] = {
        { 0, NULL }
 };
 
-static const struct tok empty_str[] = {
-       { 0, NULL }
-};
-
 /* lengths (fixed or minimal) of particular protocol structures */
 #define OF_SWITCH_CONFIG_FIXLEN               12
 #define OF_PHY_PORT_FIXLEN                    48
@@ -685,6 +682,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)
 {
@@ -706,38 +709,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_data_print(netdissect_options *ndo,
-                const u_char *cp, const u_int len)
-{
-       if (len == 0)
-               return;
-       /* data */
-       ND_PRINT("\n\t data (%u octets)", len);
-       if (ndo->ndo_vflag >= 2)
-               hex_and_ascii_print(ndo, "\n\t  ", cp, len);
-       else
-               ND_TCHECK_LEN(cp, len);
-}
-
 static void
 of10_bsn_message_print(netdissect_options *ndo,
                        const u_char *cp, u_int len)
@@ -998,7 +969,7 @@ of10_vendor_action_print(netdissect_options *ndo,
        /* data */
        decoder =
                vendor == OUI_BSN         ? of10_bsn_actions_print         :
-               of10_data_print;
+               of_data_print;
        decoder(ndo, cp, len);
        return;
 
@@ -1023,7 +994,7 @@ of10_vendor_message_print(netdissect_options *ndo,
        /* data */
        decoder =
                vendor == OUI_BSN         ? of10_bsn_message_print         :
-               of10_data_print;
+               of_data_print;
        decoder(ndo, cp, len);
        return;
 
@@ -1046,7 +1017,7 @@ of10_vendor_data_print(netdissect_options *ndo,
        OF_FWD(4);
        ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
        /* data */
-       of10_data_print(ndo, cp, len);
+       of_data_print(ndo, cp, len);
        return;
 
 invalid: /* skip the undersized data */
@@ -1099,27 +1070,27 @@ 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);
+               of_bitmap_print(ndo, ofpps_bm, GET_BE_U_4(cp), OFPPS_U);
                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;
@@ -1499,11 +1470,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);
@@ -1551,7 +1522,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);
@@ -1570,15 +1541,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. */
@@ -1807,7 +1778,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));
@@ -1938,7 +1909,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) {
@@ -2060,41 +2031,42 @@ static void
 of10_error_print(netdissect_options *ndo,
                  const u_char *cp, u_int len)
 {
-       uint16_t type;
-       const struct tok *code_str;
+       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,
+       };
 
        /* type */
        type = GET_BE_U_2(cp);
        OF_FWD(2);
        ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type));
        /* code */
-       code_str =
-               type == OFPET_HELLO_FAILED    ? ofphfc_str  :
-               type == OFPET_BAD_REQUEST     ? ofpbrc_str  :
-               type == OFPET_BAD_ACTION      ? ofpbac_str  :
-               type == OFPET_FLOW_MOD_FAILED ? ofpfmfc_str :
-               type == OFPET_PORT_MOD_FAILED ? ofppmfc_str :
-               type == OFPET_QUEUE_OP_FAILED ? ofpqofc_str :
-               empty_str;
-       ND_PRINT(", code %s",
-                tok2str(code_str, "invalid (0x%04x)", GET_BE_U_2(cp)));
+       code = GET_BE_U_2(cp);
        OF_FWD(2);
+       if (type <= OFPET_MAX && code_str[type] != NULL)
+               ND_PRINT(", code %s",
+                        tok2str(code_str[type], "invalid (0x%04x)", code));
+       else
+               ND_PRINT(", code invalid (0x%04x)", code);
        /* data */
-       of10_data_print(ndo, cp, len);
+       of_data_print(ndo, cp, len);
 }
 
 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
@@ -2102,11 +2074,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 */
@@ -2190,7 +2157,7 @@ of10_header_body_print(netdissect_options *ndo,
        case OFPT_ECHO_REPLY: /* [OF10] Section 5.5.3 */
                if (ndo->ndo_vflag < 1)
                        break;
-               of10_data_print(ndo, cp, len);
+               of_data_print(ndo, cp, len);
                return;
 
        /* OpenFlow header, fixed-size message body and variable-size data. */