/* \summary: Marvell (Ethertype) Distributed Switch Architecture printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
/*
* Format of (Ethertyped or not) DSA tagged frames:
*
- * 7 6 5 4 3 2 1 0
+ * 7 6 5 4 3 2 1 0
* . . . . . . . . .
* 0 +---+---+---+---+---+---+---+---+
* | Ether Destination Address |
* b12: To_CPU's Code[0]
*/
-#define TOK(tag, byte, mask, shift) ((((const u_char *) tag)[byte] & (mask)) >> (shift))
+#define TOK(tag, byte, mask, shift) ((GET_U_1(&(((const u_char *) tag)[byte])) & (mask)) >> (shift))
#define DSA_LEN 4
#define DSA_MODE(tag) TOK(tag, 0, 0xc0, 6)
#define DSA_RX_SNIFF(tag) TOK(tag, 1, 0x04, 2)
#define DSA_CFI(tag) TOK(tag, 1, 0x01, 0)
#define DSA_PRI(tag) TOK(tag, 2, 0xe0, 5)
-#define DSA_VID(tag) ((u_short)((TOK(tag, 2, 0xe0, 5) << 8) | (TOK(tag, 3, 0xff, 0))))
+#define DSA_VID(tag) ((u_short)((TOK(tag, 2, 0x0f, 0) << 8) | (TOK(tag, 3, 0xff, 0))))
#define DSA_CODE(tag) ((TOK(tag, 1, 0x06, 1) << 1) | TOK(tag, 2, 0x10, 4))
#define EDSA_LEN 8
-#define EDSA_ETYPE(tag) ((u_short)((TOK(tag, 0, 0xff, 0) << 8) | (TOK(tag, 1, 0xff, 0))))
static const struct tok dsa_mode_values[] = {
{ DSA_MODE_TO_CPU, "To CPU" },
{ 0, NULL }
};
-static u_int
-dsa_if_print_full(netdissect_options *ndo, const struct pcap_pkthdr *h,
- const u_char *p, u_int taglen)
+static void
+tag_common_print(netdissect_options *ndo, const u_char *p)
{
- const u_char *edsa, *dsa;
- int eflag, ret;
-
- if (h->caplen < 12 + taglen) {
- nd_print_trunc(ndo);
- return (h->caplen);
- }
-
- if (h->len < 12 + taglen) {
- nd_print_trunc(ndo);
- return (h->len);
- }
-
- if (taglen == EDSA_LEN) {
- edsa = p + 12;
- dsa = edsa + 4;
- } else {
- edsa = NULL;
- dsa = p + 12;
- }
-
if (ndo->ndo_eflag) {
- ND_PRINT("%s > %s, ",
- etheraddr_string(ndo, p + 6),
- etheraddr_string(ndo, p));
-
- if (edsa) {
- ND_PRINT("Marvell EDSA ethertype 0x%04x (%s), ", EDSA_ETYPE(edsa),
- tok2str(ethertype_values, "unregistered", EDSA_ETYPE(edsa)));
- ND_PRINT("rsvd %u %u, ", edsa[2], edsa[3]);
- } else {
- ND_PRINT("Marvell DSA ");
- }
+ ND_PRINT("mode %s, ", tok2str(dsa_mode_values, "unknown", DSA_MODE(p)));
- ND_PRINT("mode %s, ", tok2str(dsa_mode_values, "unknown", DSA_MODE(dsa)));
-
- switch (DSA_MODE(dsa)) {
+ switch (DSA_MODE(p)) {
case DSA_MODE_FORWARD:
- ND_PRINT("dev %u, %s %u, ", DSA_DEV(dsa),
- DSA_TRUNK(dsa) ? "trunk" : "port", DSA_PORT(dsa));
+ ND_PRINT("dev %u, %s %u, ", DSA_DEV(p),
+ DSA_TRUNK(p) ? "trunk" : "port", DSA_PORT(p));
break;
case DSA_MODE_FROM_CPU:
ND_PRINT("target dev %u, port %u, ",
- DSA_DEV(dsa), DSA_PORT(dsa));
+ DSA_DEV(p), DSA_PORT(p));
break;
case DSA_MODE_TO_CPU:
ND_PRINT("source dev %u, port %u, ",
- DSA_DEV(dsa), DSA_PORT(dsa));
+ DSA_DEV(p), DSA_PORT(p));
ND_PRINT("code %s, ",
- tok2str(dsa_code_values, "reserved", DSA_CODE(dsa)));
+ tok2str(dsa_code_values, "reserved", DSA_CODE(p)));
break;
case DSA_MODE_TO_SNIFFER:
ND_PRINT("source dev %u, port %u, ",
- DSA_DEV(dsa), DSA_PORT(dsa));
+ DSA_DEV(p), DSA_PORT(p));
ND_PRINT("%s sniff, ",
- DSA_RX_SNIFF(dsa) ? "ingress" : "egress");
+ DSA_RX_SNIFF(p) ? "ingress" : "egress");
break;
default:
break;
}
- ND_PRINT("%s, ", DSA_TAGGED(dsa) ? "tagged" : "untagged");
- ND_PRINT("%s", DSA_CFI(dsa) ? "CFI, " : "");
- ND_PRINT("VID %u, ", DSA_VID(dsa));
- ND_PRINT("FPri %u, ", DSA_PRI(dsa));
+ ND_PRINT("%s, ", DSA_TAGGED(p) ? "tagged" : "untagged");
+ ND_PRINT("%s", DSA_CFI(p) ? "CFI, " : "");
+ ND_PRINT("VID %u, ", DSA_VID(p));
+ ND_PRINT("FPri %u, ", DSA_PRI(p));
} else {
- if (edsa) {
- ND_PRINT("EDSA 0x%04x, ", EDSA_ETYPE(edsa));
- } else {
- ND_PRINT("DSA ");
- }
-
- switch (DSA_MODE(dsa)) {
+ switch (DSA_MODE(p)) {
case DSA_MODE_FORWARD:
ND_PRINT("Forward %s %u.%u, ",
- DSA_TRUNK(dsa) ? "trunk" : "port",
- DSA_DEV(dsa), DSA_PORT(dsa));
+ DSA_TRUNK(p) ? "trunk" : "port",
+ DSA_DEV(p), DSA_PORT(p));
break;
case DSA_MODE_FROM_CPU:
ND_PRINT("CPU > port %u.%u, ",
- DSA_DEV(dsa), DSA_PORT(dsa));
+ DSA_DEV(p), DSA_PORT(p));
break;
case DSA_MODE_TO_CPU:
ND_PRINT("port %u.%u > CPU, ",
- DSA_DEV(dsa), DSA_PORT(dsa));
+ DSA_DEV(p), DSA_PORT(p));
break;
case DSA_MODE_TO_SNIFFER:
ND_PRINT("port %u.%u > %s Sniffer, ",
- DSA_DEV(dsa), DSA_PORT(dsa),
- DSA_RX_SNIFF(dsa) ? "Rx" : "Tx");
+ DSA_DEV(p), DSA_PORT(p),
+ DSA_RX_SNIFF(p) ? "Rx" : "Tx");
break;
default:
break;
}
- ND_PRINT("VLAN %u%c, ", DSA_VID(dsa), DSA_TAGGED(dsa) ? 't' : 'u');
+ ND_PRINT("VLAN %u%c, ", DSA_VID(p), DSA_TAGGED(p) ? 't' : 'u');
}
+}
+
+static void
+dsa_tag_print(netdissect_options *ndo, const u_char *bp)
+{
+ if (ndo->ndo_eflag)
+ ND_PRINT("Marvell DSA ");
+ else
+ ND_PRINT("DSA ");
+ tag_common_print(ndo, bp);
+}
- eflag = ndo->ndo_eflag;
- ndo->ndo_eflag = 0;
- ret = ether_hdr_len_print(ndo, p, h->len, h->caplen, NULL, NULL,
- 12 + taglen + 2);
- ndo->ndo_eflag = eflag;
+static void
+edsa_tag_print(netdissect_options *ndo, const u_char *bp)
+{
+ const u_char *p = bp;
+ uint16_t edsa_etype;
- return ret;
+ edsa_etype = GET_BE_U_2(p);
+ if (ndo->ndo_eflag) {
+ ND_PRINT("Marvell EDSA ethertype 0x%04x (%s), ", edsa_etype,
+ tok2str(ethertype_values, "Unknown", edsa_etype));
+ ND_PRINT("rsvd %u %u, ", GET_U_1(p + 2), GET_U_1(p + 3));
+ } else
+ ND_PRINT("EDSA 0x%04x, ", edsa_etype);
+ p += 4;
+ tag_common_print(ndo, p);
}
-u_int
+void
dsa_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
- ndo->ndo_protocol = "dsa";
+ u_int caplen = h->caplen;
+ u_int length = h->len;
- return dsa_if_print_full(ndo, h, p, DSA_LEN);
+ ndo->ndo_protocol = "dsa";
+ ndo->ndo_ll_hdr_len +=
+ ether_switch_tag_print(ndo, p, length, caplen, dsa_tag_print, DSA_LEN);
}
-u_int
+void
edsa_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
- ndo->ndo_protocol = "edsa";
+ u_int caplen = h->caplen;
+ u_int length = h->len;
- return dsa_if_print_full(ndo, h, p, EDSA_LEN);
+ ndo->ndo_protocol = "edsa";
+ ndo->ndo_ll_hdr_len +=
+ ether_switch_tag_print(ndo, p, length, caplen, edsa_tag_print, EDSA_LEN);
}