]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Add support for decoding Broadcom Ethernet switches tags
authorFlorian Fainelli <[email protected]>
Fri, 18 Jan 2019 23:24:33 +0000 (15:24 -0800)
committerFlorian Fainelli <[email protected]>
Mon, 28 Jan 2019 18:56:18 +0000 (10:56 -0800)
This adds support for decoding the Broadcom Ethernet switches tags which
are are 4byte in length and are located between the Ethernet MAC SA and
the Type/Length field (DSA_TAG_BRCM) as well as the pre-pended Broadcom
tag (DSA_TAG_BRCM_PREPEND) which are located in front of the standard
Ethernet header.

This makes use of the recently introduced ether_print_hdr_len() to allow
specifying the non-standard Ethernet header length of 12 + 4 + 2 bytes.

CMakeLists.txt
Makefile.in
netdissect.h
print-brcmtag.c [new file with mode: 0644]
print.c

index c1178427ada1d2a170039fb767eb5bc92b3cf023..9ec842efdeca5d4b2f13ef835ffe340889dcf7fc 100644 (file)
@@ -944,6 +944,7 @@ set(NETDISSECT_SOURCE_LIST_C
     print-bfd.c
     print-bgp.c
     print-bootp.c
+    print-brcmtag.c
     print-bt.c
     print-calm-fast.c
     print-carp.c
index 419dfd67cc49d34ea59c30483ef9b735962ec38d..b1ba4d9fc99c569f09e3f99cccca19d1ff1678f7 100644 (file)
@@ -107,6 +107,7 @@ LIBNETDISSECT_SRC=\
        print-bfd.c \
        print-bgp.c \
        print-bootp.c \
+       print-brcmtag.c \
        print-bt.c \
        print-calm-fast.c \
        print-carp.c \
index 2160b20522b251a131c241c5c5e66aca68feb62a..fc415ed54192229902bf4d608a9000b2ca6243ad 100644 (file)
@@ -435,6 +435,8 @@ extern u_int arcnet_if_print IF_PRINTER_ARGS;
 extern u_int arcnet_linux_if_print IF_PRINTER_ARGS;
 extern u_int atm_if_print IF_PRINTER_ARGS;
 extern u_int bt_if_print IF_PRINTER_ARGS;
+extern u_int brcm_tag_if_print IF_PRINTER_ARGS;
+extern u_int brcm_tag_prepend_if_print IF_PRINTER_ARGS;
 extern u_int chdlc_if_print IF_PRINTER_ARGS;
 extern u_int cip_if_print IF_PRINTER_ARGS;
 extern u_int enc_if_print IF_PRINTER_ARGS;
diff --git a/print-brcmtag.c b/print-brcmtag.c
new file mode 100644 (file)
index 0000000..51966e3
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* \summary: Broadcom Ethernet switches tag (4 bytes) printer */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "netdissect-stdinc.h"
+
+#include "netdissect.h"
+#include "ethertype.h"
+#include "addrtoname.h"
+#include "extract.h"
+
+struct ether_header {
+       nd_mac_addr     ether_dhost;
+       nd_mac_addr     ether_shost;
+       nd_uint16_t     ether_length_type;
+};
+
+#define ETHER_SA_OFFSET                12
+#define ETHER_TYPE_LEN         2
+
+#define BRCM_TAG_LEN           4
+#define BRCM_OPCODE_SHIFT      5
+#define BRCM_OPCODE_MASK       0x7
+
+/* Ingress fields */
+#define BRCM_IG_TC_SHIFT       2
+#define BRCM_IG_TC_MASK                0x7
+#define BRCM_IG_TE_MASK                0x3
+#define BRCM_IG_TS_SHIFT       7
+#define BRCM_IG_DSTMAP_MASK    0x1ff
+
+/* Egress fields */
+#define BRCM_EG_CID_MASK       0xff
+#define BRCM_EG_RC_MASK                0xff
+#define  BRCM_EG_RC_RSVD       (3 << 6)
+#define  BRCM_EG_RC_EXCEPTION  (1 << 5)
+#define  BRCM_EG_RC_PROT_SNOOP (1 << 4)
+#define  BRCM_EG_RC_PROT_TERM  (1 << 3)
+#define  BRCM_EG_RC_SWITCH     (1 << 2)
+#define  BRCM_EG_RC_MAC_LEARN  (1 << 1)
+#define  BRCM_EG_RC_MIRROR     (1 << 0)
+#define BRCM_EG_TC_SHIFT       5
+#define BRCM_EG_TC_MASK                0x7
+#define BRCM_EG_PID_MASK       0x1f
+
+const struct tok brcm_tag_te_values[] = {
+       { 0, "None" },
+       { 1, "Untag" },
+       { 2, "Header"},
+       { 3, "Reserved" },
+};
+
+const struct tok brcm_tag_rc_values[] = {
+       { 1, "mirror" },
+       { 2, "MAC learning" },
+       { 4, "switching" },
+       { 8, "prot term" },
+       { 16, "prot snoop" },
+       { 32, "exception" },
+};
+
+static int brcm_tag_print_full(netdissect_options *ndo, const u_char *bp,
+                              u_int length)
+{
+       uint8_t tag[BRCM_TAG_LEN];
+       uint16_t dst_map;
+       unsigned int i;
+
+       if (length < BRCM_TAG_LEN)
+               return (1);
+
+       for (i = 0; i < BRCM_TAG_LEN; i++)
+               tag[i] = EXTRACT_U_1(bp + i);
+
+       ND_PRINT("BRCM tag OP: %s", tag[0] ? "IG" : "EG");
+       if (tag[0] & (1 << BRCM_OPCODE_SHIFT)) {
+               /* Ingress Broadcom tag */
+               ND_PRINT(", TC: %d", (tag[1] >> BRCM_IG_TC_SHIFT) &
+                                    BRCM_IG_TC_MASK);
+               ND_PRINT(", TE: %s",
+                        tok2str(brcm_tag_te_values, "unknown",
+                                (tag[1] & BRCM_IG_TE_MASK)));
+               ND_PRINT(", TS: %d", tag[1] >> BRCM_IG_TS_SHIFT);
+               dst_map = (uint16_t)tag[2] << 8 | tag[3];
+               ND_PRINT(", DST map: 0x%04x", dst_map & BRCM_IG_DSTMAP_MASK);
+       } else {
+               /* Egress Broadcom tag */
+               ND_PRINT(", CID: %d", tag[1]);
+               ND_PRINT(", RC: %s", tok2str(brcm_tag_rc_values,
+                                          "reserved", tag[2]));
+               ND_PRINT(", TC: %d", (tag[3] >> BRCM_EG_TC_SHIFT) &
+                                   BRCM_EG_TC_MASK);
+               ND_PRINT(", port: %d", tag[3] & BRCM_EG_PID_MASK);
+       }
+       ND_PRINT(", ");
+
+       return (0);
+}
+
+u_int
+brcm_tag_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
+                 const u_char *p)
+{
+       const struct ether_header *ehp;
+       int old_eflag = ndo->ndo_eflag;
+       u_int caplen = h->caplen;
+       u_int length = h->len;
+       int ret;
+
+       ndo->ndo_protocol = "brcm-tag";
+       if (caplen < ETHER_SA_OFFSET + BRCM_TAG_LEN) {
+               nd_print_trunc(ndo);
+               return (caplen);
+       }
+
+       if (length < ETHER_SA_OFFSET + BRCM_TAG_LEN) {
+               nd_print_trunc(ndo);
+               return (length);
+       }
+
+       ehp = (const struct ether_header *)p;
+       if (ndo->ndo_eflag)
+               ND_PRINT("%s > %s, ",
+                            etheraddr_string(ndo, ehp->ether_shost),
+                            etheraddr_string(ndo, ehp->ether_dhost));
+
+       if (brcm_tag_print_full(ndo, p + ETHER_SA_OFFSET,
+                               caplen - ETHER_SA_OFFSET))
+               return (1);
+
+       /* We printed the Ethernet header already */
+       ndo->ndo_eflag = 0;
+
+       /* Parse the Ethernet frame regularly telling how big the non
+        * standard Ethernet header is.
+        *
+        * +-----------++-----------++----------------++--------------+
+        * | MAC DA (6)|| MAC SA (6)||Broadcom tag (4)||Type/Length(2)|
+        * +-----------++-----------++----------------++--------------+
+        */
+       ret = ether_print_hdr_len(ndo, p, length, caplen, NULL, NULL,
+                                 ETHER_SA_OFFSET + BRCM_TAG_LEN + 2);
+       ndo->ndo_eflag = old_eflag;
+       return ret;
+}
+
+static void brcm_tag_print_encap(netdissect_options *ndo,
+                                const u_char *p)
+{
+       brcm_tag_print_full(ndo, p, BRCM_TAG_LEN);
+}
+
+u_int
+brcm_tag_prepend_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
+                         const u_char *p)
+{
+       u_int caplen = h->caplen;
+       u_int length = h->len;
+
+       ndo->ndo_protocol = "brcm-tag-prepend";
+       if (caplen < BRCM_TAG_LEN) {
+               nd_print_trunc(ndo);
+               return (caplen);
+       }
+
+       if (length < BRCM_TAG_LEN) {
+               nd_print_trunc(ndo);
+               return (length);
+       }
+
+       /* Parse the Ethernet frame regularly and utilize the encapsulation
+        * header printing facility to pring the pre-pended Broadcom tag.
+        *
+        * +-----------------++-----------++-----------++--------------+
+        * | Broadcom tag (4)|| MAC DA (6)|| MAC SA (6)||Type/Length(2)|
+        * +-----------------++-----------++-----------++--------------+
+        */
+       return ether_print(ndo, p + BRCM_TAG_LEN,
+                          length - BRCM_TAG_LEN,
+                          caplen - BRCM_TAG_LEN, brcm_tag_print_encap, p);
+}
diff --git a/print.c b/print.c
index 48374544f2034b1efb1671c65ddc03ea02db87bc..9ee88eb1758d1206b256043c8b0c47dd7e388f26 100644 (file)
--- a/print.c
+++ b/print.c
@@ -223,6 +223,12 @@ static const struct printer printers[] = {
 #endif
 #ifdef DLT_PPP_SERIAL
        { ppp_hdlc_if_print,    DLT_PPP_SERIAL },
+#endif
+#ifdef DLT_DSA_TAG_BRCM
+       { brcm_tag_if_print,    DLT_DSA_TAG_BRCM },
+#endif
+#ifdef DLT_DSA_TAG_BRCM_PREPEND
+       { brcm_tag_prepend_if_print, DLT_DSA_TAG_BRCM_PREPEND },
 #endif
        { NULL,                 0 },
 };