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" },
{ 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
{ 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
{ 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)
{
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)
const u_char *cp, u_int len)
{
while (len) {
+ uint32_t state;
+
if (len < OF_PHY_PORT_FIXLEN)
goto invalid;
/* port_no */
}
/* 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;
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);
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);
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. */
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));
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) {
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);
/* 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 */
}
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
* 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 */