Handle switch tags more cleanly.

Have the switch tag dissectors handle *only* the switch tag, not
anything else in the Ethernet header.

Have a routine ether_print_switch_tag() that takes a pointer to a
routine to dissect the switch tag, and a switch tag length, as an
argument, and have a common Ethernet dissection routine called by
ether_print_switch_tag() and by ether_print(), passing a null pointer
for the switch tag dissector and 0 for the switch tag length.

Dissect the switch tag after the MAC addresses, if there's a non-null
switch tag routine dissector pointer.

Clean up the processing logic in the common Ethernet dissection code -
have a loop to process VLAN tags, if any, and, when it's done, handle
frames with a length field, frames with a regular type field, and Alteon
jumbo frames.
diff --git a/netdissect.h b/netdissect.h
index 085aeac..f2839e0 100644
--- a/netdissect.h
+++ b/netdissect.h
@@ -593,7 +593,7 @@
 extern void eigrp_print(netdissect_options *, const u_char *, u_int);
 extern void esp_print(netdissect_options *, const u_char *, u_int, const u_char *, u_int, int, u_int);
 extern u_int ether_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), const u_char *);
-extern u_int ether_hdr_len_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), const u_char *, u_int);
+extern u_int ether_print_switch_tag(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), u_int);
 extern int ethertype_print(netdissect_options *, u_short, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *);
 extern u_int fddi_print(netdissect_options *, const u_char *, u_int, u_int);
 extern void forces_print(netdissect_options *, const u_char *, u_int);
diff --git a/print-brcmtag.c b/print-brcmtag.c
index 47b114b..1544978 100644
--- a/print-brcmtag.c
+++ b/print-brcmtag.c
@@ -77,16 +77,13 @@
 	{ 0, NULL }
 };
 
-static int brcm_tag_print_full(netdissect_options *ndo, const u_char *bp,
-			       u_int length)
+static void
+brcm_tag_print(netdissect_options *ndo, const u_char *bp)
 {
 	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] = GET_U_1(bp + i);
 
@@ -111,8 +108,6 @@
 		ND_PRINT(", port: %d", tag[3] & BRCM_EG_PID_MASK);
 	}
 	ND_PRINT(", ");
-
-	return (0);
 }
 
 u_int
@@ -121,51 +116,10 @@
 {
 	u_int caplen = h->caplen;
 	u_int length = h->len;
-	int save_eflag;
-	int ret;
 
 	ndo->ndo_protocol = "brcm-tag";
-	if (caplen < 2*MAC_ADDR_LEN + BRCM_TAG_LEN) {
-		nd_print_trunc(ndo);
-		return (caplen);
-	}
-
-	if (length < 2*MAC_ADDR_LEN + BRCM_TAG_LEN) {
-		nd_print_trunc(ndo);
-		return (length);
-	}
-
-	if (ndo->ndo_eflag)
-		ND_PRINT("%s > %s, ",
-			 etheraddr_string(ndo, p + MAC_ADDR_LEN),
-			 etheraddr_string(ndo, p));
-
-	if (brcm_tag_print_full(ndo, p + 2*MAC_ADDR_LEN,
-				caplen - 2*MAC_ADDR_LEN))
-		return (1);
-
-	/* We printed the Ethernet destination and source addresses already */
-	save_eflag = ndo->ndo_eflag;
-	ndo->ndo_eflag = 0;
-
-	/* Parse the rest of the Ethernet header, and the frame payload,
-	 * telling ether_hdr_len_print() how big the non-standard Ethernet
-	 * header is.
-	 *
-	 * +-----------+-----------+----------------+--------------+
-	 * | MAC DA (6)| MAC SA (6)|Broadcom tag (4)|Type/Length(2)|
-	 * +-----------+-----------+----------------+--------------+
-	 */
-	ret = ether_hdr_len_print(ndo, p, length, caplen, NULL, NULL,
-				  2*MAC_ADDR_LEN + BRCM_TAG_LEN + ETHER_TYPE_LEN);
-	ndo->ndo_eflag = save_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);
+	return (ether_print_switch_tag(ndo, p, length, caplen,
+	    brcm_tag_print, BRCM_TAG_LEN));
 }
 
 u_int
@@ -186,14 +140,16 @@
 		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)|
-	 * +-----------------++-----------++-----------++--------------+
+	if (ndo->ndo_eflag) {
+		/* Print the prepended Broadcom tag. */
+		brcm_tag_print(ndo, p);
+	}
+	p += BRCM_TAG_LEN;
+	length -= BRCM_TAG_LEN;
+	caplen -= BRCM_TAG_LEN;
+
+	/*
+	 * Now print the Ethernet frame following it.
 	 */
-	return ether_print(ndo, p + BRCM_TAG_LEN,
-			   length - BRCM_TAG_LEN,
-			   caplen - BRCM_TAG_LEN, brcm_tag_print_encap, p);
+	return ether_print(ndo, p, length, caplen, NULL, NULL);
 }
diff --git a/print-dsa.c b/print-dsa.c
index ad24795..975285c 100644
--- a/print-dsa.c
+++ b/print-dsa.c
@@ -87,7 +87,6 @@
 #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" },
@@ -107,141 +106,114 @@
 	{ 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 save_eflag;
-	int ret;
-
-	if (h->caplen < 2*MAC_ADDR_LEN + taglen) {
-		nd_print_trunc(ndo);
-		return (h->caplen);
-	}
-
-	if (h->len < 2*MAC_ADDR_LEN + taglen) {
-		nd_print_trunc(ndo);
-		return (h->len);
-	}
-
-	if (taglen == EDSA_LEN) {
-		edsa = p + 2*MAC_ADDR_LEN;
-		dsa = edsa + 4;
-	} else {
-		edsa = NULL;
-		dsa = p + 2*MAC_ADDR_LEN;
-	}
-
 	if (ndo->ndo_eflag) {
-		ND_PRINT("%s > %s, ",
-			 etheraddr_string(ndo, p + MAC_ADDR_LEN),
-			 etheraddr_string(ndo, p));
+		ND_PRINT("mode %s, ", tok2str(dsa_mode_values, "unknown", DSA_MODE(p)));
 
-		if (edsa) {
-			ND_PRINT("Marvell EDSA ethertype 0x%04x (%s), ", EDSA_ETYPE(edsa),
-				 tok2str(ethertype_values, "Unknown", 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(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');
 	}
+}
 
-	/* We printed the Ethernet destination and source addresses already */
-	save_eflag = ndo->ndo_eflag;
-	ndo->ndo_eflag = 0;
+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);
+}
 
-	/* Parse the rest of the Ethernet header, and the frame payload,
-	 * telling ether_hdr_len_print() how big the non-standard Ethernet
-	 * header is.
-	 *
-	 * +-----------+-----------+---------------------+--------------+
-	 * | MAC DA (6)| MAC SA (6)|DSA/EDSA tag (taglen)|Type/Length(2)|
-	 * +-----------+-----------+---------------------+--------------+
-	 */
-	ret = ether_hdr_len_print(ndo, p, h->len, h->caplen, NULL, NULL,
-				  2*MAC_ADDR_LEN + taglen + 2);
+static void
+edsa_tag_print(netdissect_options *ndo, const u_char *bp)
+{
+	const u_char *p = bp;
+	uint16_t edsa_etype;
 
-	ndo->ndo_eflag = save_eflag;
-
-	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
 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";
+	return (ether_print_switch_tag(ndo, p, length, caplen,
+	    dsa_tag_print, DSA_LEN));
 }
 
 u_int
 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";
+	return (ether_print_switch_tag(ndo, p, length, caplen,
+	    edsa_tag_print, EDSA_LEN));
 }
diff --git a/print-ether.c b/print-ether.c
index 4e0d6f0..6202a69 100644
--- a/print-ether.c
+++ b/print-ether.c
@@ -104,136 +104,112 @@
 };
 
 static void
-ether_hdr_print(netdissect_options *ndo,
-		const u_char *bp, u_int length,
-		u_int hdrlen)
+ether_addresses_print(netdissect_options *ndo, const u_char *src,
+		      const u_char *dst)
 {
-	const struct ether_header *ehp;
-	uint16_t length_type;
+	ND_PRINT("%s > %s, ",
+		 etheraddr_string(ndo, src), etheraddr_string(ndo, dst));
+}
 
-	ehp = (const struct ether_header *)bp;
-
-	ND_PRINT("%s > %s",
-		 etheraddr_string(ndo, ehp->ether_shost),
-		 etheraddr_string(ndo, ehp->ether_dhost));
-
-	length_type = GET_BE_U_2(bp + (hdrlen - sizeof(ehp->ether_length_type)));
-	if (length_type <= MAX_ETHERNET_LENGTH_VAL) {
-		/*
-		 * It's a length field.
-		 */
-		ND_PRINT(", 802.3, length %u", length_type);
-		if (length_type > length - hdrlen)
-			ND_PRINT(" (too large, > %u)", length - hdrlen);
-		ND_PRINT(": ");
-	} else {
-		/*
-		 * It's a type field.
-		 */
-		if (!ndo->ndo_qflag)
-			ND_PRINT(", ethertype %s (0x%04x), length %u: ",
-				 tok2str(ethertype_values,"Unknown", length_type),
-				 length_type, length);
-		else
-			ND_PRINT(", %s, length %u: ",
-			         tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", length_type),
-			         length);
-	}
+static void
+ether_type_print(netdissect_options *ndo, uint16_t type)
+{
+	if (!ndo->ndo_qflag)
+		ND_PRINT("ethertype %s (0x%04x)",
+			 tok2str(ethertype_values, "Unknown", type), type);
+	else
+		ND_PRINT("%s",
+			 tok2str(ethertype_values, "Unknown Ethertype (0x%04x)", type));
 }
 
 /*
- * Print an Ethernet frame while specyfing a non-standard Ethernet header
- * length.
- * This might be encapsulated within another frame; we might be passed
- * a pointer to a function that can print header information for that
- * frame's protocol, and an argument to pass to that function.
+ * Common code for printing Ethernet frames.
  *
- * FIXME: caplen can and should be derived from ndo->ndo_snapend and p.
+ * It can handle Ethernet headers with extra tag information inserted
+ * after the destination and source addresses, as is inserted by some
+ * switch chips, and extra encapsulation header information before
+ * printing Ethernet header information (such as a LANE ID for ATM LANE).
  */
-u_int
-ether_hdr_len_print(netdissect_options *ndo,
-		    const u_char *p, u_int length, u_int caplen,
-		    void (*print_encap_header)(netdissect_options *ndo, const u_char *),
-		    const u_char *encap_header_arg, u_int hdrlen)
+static u_int
+ether_print_common(netdissect_options *ndo, const u_char *p, u_int length,
+    u_int caplen,
+    void (*print_switch_tag)(netdissect_options *ndo, const u_char *),
+    u_int switch_tag_len,
+    void (*print_encap_header)(netdissect_options *ndo, const u_char *),
+    const u_char *encap_header_arg)
 {
 	const struct ether_header *ehp;
 	u_int orig_length;
+	u_int hdrlen;
 	u_short length_type;
+	int printed_length;
 	int llc_hdrlen;
 	struct lladdr_info src, dst;
 
-	/* Unless specified otherwise, assume a standard Ethernet header */
-	if (hdrlen == ETHER_HDRLEN)
-		ndo->ndo_protocol = "ether";
-
-	if (caplen < hdrlen) {
+	if (caplen < ETHER_HDRLEN + switch_tag_len) {
 		nd_print_trunc(ndo);
 		return (caplen);
 	}
-	if (length < hdrlen) {
+	if (length < ETHER_HDRLEN + switch_tag_len) {
 		nd_print_trunc(ndo);
 		return (length);
 	}
 
-	/* If the offset is set, then the upper printer is responsible for
-	 * printing the relevant part of the Ethernet header.
-	 */
-	if (ndo->ndo_eflag) {
-		if (print_encap_header != NULL)
-			(*print_encap_header)(ndo, encap_header_arg);
-		ether_hdr_print(ndo, p, length, hdrlen);
-	}
+	if (print_encap_header != NULL)
+		(*print_encap_header)(ndo, encap_header_arg);
 
 	orig_length = length;
 
-	length -= hdrlen;
-	caplen -= hdrlen;
+	/*
+	 * Get the source and destination addresses, skip past them,
+	 * and print them if we're printing the link-layer header.
+	 */
 	ehp = (const struct ether_header *)p;
-	p += hdrlen;
-
 	src.addr = ehp->ether_shost;
 	src.addr_string = etheraddr_string;
 	dst.addr = ehp->ether_dhost;
 	dst.addr_string = etheraddr_string;
-	length_type = GET_BE_U_2((const u_char *)ehp + (hdrlen - sizeof(ehp->ether_length_type)));
 
-recurse:
+	length -= 2*MAC_ADDR_LEN;
+	caplen -= 2*MAC_ADDR_LEN;
+	p += 2*MAC_ADDR_LEN;
+	hdrlen = 2*MAC_ADDR_LEN;
+
+	if (ndo->ndo_eflag)
+		ether_addresses_print(ndo, src.addr, dst.addr);
+
 	/*
-	 * Is it (gag) an 802.3 encapsulation?
+	 * Print the switch tag, if we have one, and skip past it.
 	 */
-	if (length_type <= MAX_ETHERNET_LENGTH_VAL) {
-		/*
-		 * The length/type field contains the length of the
-		 * remaining payload; use it as such, as long as
-		 * it's not too large (bigger than the actual payload).
-		 */
-		if (length_type < length) {
-			length = length_type;
-			if (caplen > length)
-				caplen = length;
-		}
+	if (print_switch_tag != NULL)
+		(*print_switch_tag)(ndo, p);
 
-		/*
-		 * Cut off the snapshot length to the end of the payload.
-		 */
-		nd_push_snapend(ndo, p + length);
+	length -= switch_tag_len;
+	caplen -= switch_tag_len;
+	p += switch_tag_len;
+	hdrlen += switch_tag_len;
 
-		/* Try to print the LLC-layer header & higher layers */
-		llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
-		if (llc_hdrlen < 0) {
-			/* packet type not known, print raw packet */
-			if (!ndo->ndo_suppress_default_print)
-				ND_DEFAULTPRINT(p, caplen);
-			llc_hdrlen = -llc_hdrlen;
-		}
-		hdrlen += llc_hdrlen;
-		nd_pop_packet_info(ndo);
-		return (hdrlen);
-	} else if (length_type == ETHERTYPE_8021Q  ||
+	/*
+	 * Get the length/type field, skip past it, and print it
+	 * if we're printing the link-layer header.
+	 */
+	length_type = GET_BE_U_2(p);
+
+	length -= 2;
+	caplen += 2;
+	p += 2;
+	hdrlen += 2;
+
+	/*
+	 * Process VLAN tag types.
+	 */
+	printed_length = 0;
+	while (length_type == ETHERTYPE_8021Q  ||
 		length_type == ETHERTYPE_8021Q9100 ||
 		length_type == ETHERTYPE_8021Q9200 ||
 		length_type == ETHERTYPE_8021QinQ) {
 		/*
+		 * It has a VLAN tag.
 		 * Print VLAN information, and then go back and process
 		 * the enclosed type field.
 		 */
@@ -250,27 +226,65 @@
 		if (ndo->ndo_eflag) {
 			uint16_t tag = GET_BE_U_2(p);
 
+			ether_type_print(ndo, length_type);
+			if (!printed_length) {
+				ND_PRINT(", length %u: ", orig_length);
+				printed_length = 1;
+			} else
+				ND_PRINT(", ");
 			ND_PRINT("%s, ", ieee8021q_tci_string(tag));
 		}
 
 		length_type = GET_BE_U_2(p + 2);
-		if (ndo->ndo_eflag && length_type > MAX_ETHERNET_LENGTH_VAL) {
-			if (!ndo->ndo_qflag)
-				ND_PRINT("ethertype %s (0x%04x), ",
-					 tok2str(ethertype_values,"Unknown", length_type),
-					 length_type);
-			else
-				ND_PRINT("%s, ",
-				         tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", length_type));
-		}
 		p += 4;
 		length -= 4;
 		caplen -= 4;
 		hdrlen += 4;
-		goto recurse;
+	}
+
+	/*
+	 * We now have the final length/type field.
+	 */
+	if (length_type <= MAX_ETHERNET_LENGTH_VAL) {
+		/*
+		 * It's a length field, containing the length of the
+		 * remaining payload; use it as such, as long as
+		 * it's not too large (bigger than the actual payload).
+		 */
+		if (length_type < length) {
+			length = length_type;
+			if (caplen > length)
+				caplen = length;
+		}
+
+		/*
+		 * Cut off the snapshot length to the end of the
+		 * payload.
+		 */
+		nd_push_snapend(ndo, p + length);
+
+		if (ndo->ndo_eflag) {
+			ND_PRINT("802.3");
+			if (!printed_length)
+				ND_PRINT(", length %u: ", length);
+		}
+
+		/*
+		 * An LLC header follows the length.  Print that and
+		 * higher layers.
+		 */
+		llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
+		if (llc_hdrlen < 0) {
+			/* packet type not known, print raw packet */
+			if (!ndo->ndo_suppress_default_print)
+				ND_DEFAULTPRINT(p, caplen);
+			llc_hdrlen = -llc_hdrlen;
+		}
+		hdrlen += llc_hdrlen;
+		nd_pop_packet_info(ndo);
 	} else if (length_type == ETHERTYPE_JUMBO) {
 		/*
-		 * Alteon jumbo frames.
+		 * It's a type field, with the type for Alteon jumbo frames.
 		 * See
 		 *
 		 *	http://tools.ietf.org/html/draft-ietf-isis-ext-eth-01
@@ -288,13 +302,29 @@
 		}
 		hdrlen += llc_hdrlen;
 	} else {
+		/*
+		 * It's a type field with some other value.
+		 */
+		if (ndo->ndo_eflag) {
+			ether_type_print(ndo, length_type);
+			if (!printed_length)
+				ND_PRINT(", length %u: ", orig_length);
+			else
+				ND_PRINT(", ");
+		}
 		if (ethertype_print(ndo, length_type, p, length, caplen, &src, &dst) == 0) {
 			/* type not known, print raw packet */
 			if (!ndo->ndo_eflag) {
-				if (print_encap_header != NULL)
-					(*print_encap_header)(ndo, encap_header_arg);
-				ether_hdr_print(ndo, (const u_char *)ehp, orig_length,
-						hdrlen);
+				/*
+				 * We didn't print the full link-layer
+				 * header, as -e wasn't specified, so
+				 * print only the source and destination
+				 * MAC addresses and the final Ethernet
+				 * type.
+				 */
+				ether_addresses_print(ndo, src.addr, dst.addr);
+				ether_type_print(ndo, length_type);
+				ND_PRINT(", length %u: ", orig_length);
 			}
 
 			if (!ndo->ndo_suppress_default_print)
@@ -305,6 +335,25 @@
 }
 
 /*
+ * Print an Ethernet frame while specyfing a non-standard Ethernet header
+ * length.
+ * This might be encapsulated within another frame; we might be passed
+ * a pointer to a function that can print header information for that
+ * frame's protocol, and an argument to pass to that function.
+ *
+ * FIXME: caplen can and should be derived from ndo->ndo_snapend and p.
+ */
+u_int
+ether_print_switch_tag(netdissect_options *ndo, const u_char *p, u_int length,
+    u_int caplen,
+    void (*print_switch_tag)(netdissect_options *, const u_char *),
+    u_int switch_tag_len)
+{
+	return (ether_print_common(ndo, p, length, caplen, print_switch_tag,
+				   switch_tag_len, NULL, NULL));
+}
+
+/*
  * Print an Ethernet frame.
  * This might be encapsulated within another frame; we might be passed
  * a pointer to a function that can print header information for that
@@ -318,9 +367,9 @@
 	    void (*print_encap_header)(netdissect_options *ndo, const u_char *),
 	    const u_char *encap_header_arg)
 {
-	return (ether_hdr_len_print(ndo, p, length, caplen,
-				    print_encap_header, encap_header_arg,
-				    ETHER_HDRLEN));
+	ndo->ndo_protocol = "ether";
+	return (ether_print_common(ndo, p, length, caplen, NULL, 0,
+				    print_encap_header, encap_header_arg));
 }
 
 /*
diff --git a/tests/brcm-tag-e.out b/tests/brcm-tag-e.out
index 34e5d58..7177014 100644
--- a/tests/brcm-tag-e.out
+++ b/tests/brcm-tag-e.out
@@ -1,23 +1,23 @@
-    1  02:10:20.634030 00:10:18:de:38:1e > ff:ff:ff:ff:ff:ff, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0080, IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
-    2  02:10:20.696008 00:10:18:de:38:1e > ff:ff:ff:ff:ff:ff, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0020, IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
-    3  02:10:23.151503 68:05:ca:18:47:70 > ff:ff:ff:ff:ff:ff, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, IP 192.168.1.1 > 192.168.1.255: ICMP echo request, id 22737, seq 1, length 64
-    4  02:10:23.650963 00:10:18:de:38:1e > ff:ff:ff:ff:ff:ff, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0080, IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
-    5  02:10:23.712960 00:10:18:de:38:1e > ff:ff:ff:ff:ff:ff, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0020, IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
-    6  02:10:24.177588 68:05:ca:18:47:70 > ff:ff:ff:ff:ff:ff, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, IP 192.168.1.1 > 192.168.1.255: ICMP echo request, id 22737, seq 2, length 64
-    7  02:10:25.201640 68:05:ca:18:47:70 > ff:ff:ff:ff:ff:ff, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, IP 192.168.1.1 > 192.168.1.255: ICMP echo request, id 22737, seq 3, length 64
-    8  02:10:30.015266 68:05:ca:18:47:70 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, IP 192.168.1.1 > 192.168.1.115: ICMP echo request, id 22744, seq 1, length 64
-    9  02:10:30.015480 00:10:18:de:38:1e > 68:05:ca:18:47:70, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0001, IP 192.168.1.115 > 192.168.1.1: ICMP echo reply, id 22744, seq 1, length 64
-   10  02:10:30.158348 00:10:18:de:38:1e > 68:05:ca:18:47:70, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0001, IP 192.168.1.115.68 > 192.168.1.1.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
-   11  02:10:30.170023 68:05:ca:18:47:70 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, IP 192.168.1.1.67 > 192.168.1.115.68: BOOTP/DHCP, Reply, length 300
-   12  02:10:33.178632 00:10:18:de:38:1e > 68:05:ca:18:47:74, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0002, IP 192.168.3.23.68 > 192.168.3.1.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
-   13  02:10:33.191027 68:05:ca:18:47:74 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 1, IP 192.168.3.1.67 > 192.168.3.23.68: BOOTP/DHCP, Reply, length 300
-   14  02:10:35.080973 00:10:18:de:38:1e > 68:05:ca:18:47:70, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0001, ARP, Request who-has 192.168.1.1 tell 192.168.1.115, length 50
-   15  02:10:35.081198 68:05:ca:18:47:70 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, ARP, Reply 192.168.1.1 is-at 68:05:ca:18:47:70, length 46
-   16  02:10:35.249563 68:05:ca:18:47:70 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, ARP, Request who-has 192.168.1.115 tell 192.168.1.1, length 46
-   17  02:10:35.249634 00:10:18:de:38:1e > 68:05:ca:18:47:70, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0001, ARP, Reply 192.168.1.115 is-at 00:10:18:de:38:1e, length 50
-   18  02:10:36.495763 68:05:ca:18:47:74 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 1, IP 192.168.3.1 > 192.168.3.23: ICMP echo request, id 22748, seq 1, length 64
-   19  02:10:36.495906 00:10:18:de:38:1e > 68:05:ca:18:47:74, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0002, IP 192.168.3.23 > 192.168.3.1: ICMP echo reply, id 22748, seq 1, length 64
-   20  02:10:37.521654 68:05:ca:18:47:74 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 1, IP 192.168.3.1 > 192.168.3.23: ICMP echo request, id 22748, seq 2, length 64
-   21  02:10:37.521717 00:10:18:de:38:1e > 68:05:ca:18:47:74, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0002, IP 192.168.3.23 > 192.168.3.1: ICMP echo reply, id 22748, seq 2, length 64
-   22  02:10:38.321557 68:05:ca:18:47:74 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 1, ARP, Request who-has 192.168.3.23 tell 192.168.3.1, length 46
-   23  02:10:38.321602 00:10:18:de:38:1e > 68:05:ca:18:47:74, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0002, ARP, Reply 192.168.3.23 is-at 00:10:18:de:38:1e, length 50
+    1  02:10:20.634030 00:10:18:de:38:1e > ff:ff:ff:ff:ff:ff, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0080, ethertype IPv4 (0x0800), length 346: 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
+    2  02:10:20.696008 00:10:18:de:38:1e > ff:ff:ff:ff:ff:ff, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0020, ethertype IPv4 (0x0800), length 346: 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
+    3  02:10:23.151503 68:05:ca:18:47:70 > ff:ff:ff:ff:ff:ff, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, ethertype IPv4 (0x0800), length 102: 192.168.1.1 > 192.168.1.255: ICMP echo request, id 22737, seq 1, length 64
+    4  02:10:23.650963 00:10:18:de:38:1e > ff:ff:ff:ff:ff:ff, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0080, ethertype IPv4 (0x0800), length 346: 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
+    5  02:10:23.712960 00:10:18:de:38:1e > ff:ff:ff:ff:ff:ff, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0020, ethertype IPv4 (0x0800), length 346: 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
+    6  02:10:24.177588 68:05:ca:18:47:70 > ff:ff:ff:ff:ff:ff, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, ethertype IPv4 (0x0800), length 102: 192.168.1.1 > 192.168.1.255: ICMP echo request, id 22737, seq 2, length 64
+    7  02:10:25.201640 68:05:ca:18:47:70 > ff:ff:ff:ff:ff:ff, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, ethertype IPv4 (0x0800), length 102: 192.168.1.1 > 192.168.1.255: ICMP echo request, id 22737, seq 3, length 64
+    8  02:10:30.015266 68:05:ca:18:47:70 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, ethertype IPv4 (0x0800), length 102: 192.168.1.1 > 192.168.1.115: ICMP echo request, id 22744, seq 1, length 64
+    9  02:10:30.015480 00:10:18:de:38:1e > 68:05:ca:18:47:70, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0001, ethertype IPv4 (0x0800), length 102: 192.168.1.115 > 192.168.1.1: ICMP echo reply, id 22744, seq 1, length 64
+   10  02:10:30.158348 00:10:18:de:38:1e > 68:05:ca:18:47:70, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0001, ethertype IPv4 (0x0800), length 346: 192.168.1.115.68 > 192.168.1.1.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
+   11  02:10:30.170023 68:05:ca:18:47:70 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, ethertype IPv4 (0x0800), length 346: 192.168.1.1.67 > 192.168.1.115.68: BOOTP/DHCP, Reply, length 300
+   12  02:10:33.178632 00:10:18:de:38:1e > 68:05:ca:18:47:74, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0002, ethertype IPv4 (0x0800), length 346: 192.168.3.23.68 > 192.168.3.1.67: BOOTP/DHCP, Request from 00:10:18:de:38:1e, length 300
+   13  02:10:33.191027 68:05:ca:18:47:74 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 1, ethertype IPv4 (0x0800), length 346: 192.168.3.1.67 > 192.168.3.23.68: BOOTP/DHCP, Reply, length 300
+   14  02:10:35.080973 00:10:18:de:38:1e > 68:05:ca:18:47:70, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0001, ethertype ARP (0x0806), length 68: Request who-has 192.168.1.1 tell 192.168.1.115, length 50
+   15  02:10:35.081198 68:05:ca:18:47:70 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, ethertype ARP (0x0806), length 64: Reply 192.168.1.1 is-at 68:05:ca:18:47:70, length 46
+   16  02:10:35.249563 68:05:ca:18:47:70 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 0, ethertype ARP (0x0806), length 64: Request who-has 192.168.1.115 tell 192.168.1.1, length 46
+   17  02:10:35.249634 00:10:18:de:38:1e > 68:05:ca:18:47:70, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0001, ethertype ARP (0x0806), length 68: Reply 192.168.1.115 is-at 00:10:18:de:38:1e, length 50
+   18  02:10:36.495763 68:05:ca:18:47:74 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 1, ethertype IPv4 (0x0800), length 102: 192.168.3.1 > 192.168.3.23: ICMP echo request, id 22748, seq 1, length 64
+   19  02:10:36.495906 00:10:18:de:38:1e > 68:05:ca:18:47:74, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0002, ethertype IPv4 (0x0800), length 102: 192.168.3.23 > 192.168.3.1: ICMP echo reply, id 22748, seq 1, length 64
+   20  02:10:37.521654 68:05:ca:18:47:74 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 1, ethertype IPv4 (0x0800), length 102: 192.168.3.1 > 192.168.3.23: ICMP echo request, id 22748, seq 2, length 64
+   21  02:10:37.521717 00:10:18:de:38:1e > 68:05:ca:18:47:74, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0002, ethertype IPv4 (0x0800), length 102: 192.168.3.23 > 192.168.3.1: ICMP echo reply, id 22748, seq 2, length 64
+   22  02:10:38.321557 68:05:ca:18:47:74 > 00:10:18:de:38:1e, BRCM tag OP: EG, CID: 0, RC: exception, TC: 0, port: 1, ethertype ARP (0x0806), length 64: Request who-has 192.168.3.23 tell 192.168.3.1, length 46
+   23  02:10:38.321602 00:10:18:de:38:1e > 68:05:ca:18:47:74, BRCM tag OP: IG, TC: 0, TE: None, TS: 0, DST map: 0x0002, ethertype ARP (0x0806), length 68: Reply 192.168.3.23 is-at 00:10:18:de:38:1e, length 50
diff --git a/tests/dsa-e.out b/tests/dsa-e.out
index 6dcadf2..b22dbec 100644
--- a/tests/dsa-e.out
+++ b/tests/dsa-e.out
@@ -1,8 +1,8 @@
-    1  22:21:39.544060 00:50:b6:29:10:70 > d6:c5:28:21:3e:af, Marvell DSA mode Forward, dev 0, port 1, untagged, VID 0, FPri 0, IP 192.168.30.1 > 192.168.30.2: ICMP echo request, id 13586, seq 1, length 64
-    2  22:21:39.544382 d6:c5:28:21:3e:af > 00:50:b6:29:10:70, Marvell DSA mode From CPU, target dev 0, port 1, untagged, VID 0, FPri 0, IP 192.168.30.2 > 192.168.30.1: ICMP echo reply, id 13586, seq 1, length 64
-    3  22:21:40.563126 00:50:b6:29:10:70 > d6:c5:28:21:3e:af, Marvell DSA mode Forward, dev 0, port 1, untagged, VID 0, FPri 0, IP 192.168.30.1 > 192.168.30.2: ICMP echo request, id 13586, seq 2, length 64
-    4  22:21:40.563252 d6:c5:28:21:3e:af > 00:50:b6:29:10:70, Marvell DSA mode From CPU, target dev 0, port 1, untagged, VID 0, FPri 0, IP 192.168.30.2 > 192.168.30.1: ICMP echo reply, id 13586, seq 2, length 64
-    5  22:21:41.576445 00:50:b6:29:10:70 > d6:c5:28:21:3e:af, Marvell DSA mode Forward, dev 0, port 1, untagged, VID 0, FPri 0, IP 192.168.30.1 > 192.168.30.2: ICMP echo request, id 13586, seq 3, length 64
-    6  22:21:41.576541 d6:c5:28:21:3e:af > 00:50:b6:29:10:70, Marvell DSA mode From CPU, target dev 0, port 1, untagged, VID 0, FPri 0, IP 192.168.30.2 > 192.168.30.1: ICMP echo reply, id 13586, seq 3, length 64
-    7  22:21:44.560086 d6:c5:28:21:3e:af > 00:50:b6:29:10:70, Marvell DSA mode From CPU, target dev 0, port 1, untagged, VID 0, FPri 0, ARP, Request who-has 192.168.30.1 tell 192.168.30.2, length 28
-    8  22:21:44.560415 00:50:b6:29:10:70 > d6:c5:28:21:3e:af, Marvell DSA mode Forward, dev 0, port 1, untagged, VID 0, FPri 0, ARP, Reply 192.168.30.1 is-at 00:50:b6:29:10:70, length 46
+    1  22:21:39.544060 00:50:b6:29:10:70 > d6:c5:28:21:3e:af, Marvell DSA mode Forward, dev 0, port 1, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 102: 192.168.30.1 > 192.168.30.2: ICMP echo request, id 13586, seq 1, length 64
+    2  22:21:39.544382 d6:c5:28:21:3e:af > 00:50:b6:29:10:70, Marvell DSA mode From CPU, target dev 0, port 1, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 102: 192.168.30.2 > 192.168.30.1: ICMP echo reply, id 13586, seq 1, length 64
+    3  22:21:40.563126 00:50:b6:29:10:70 > d6:c5:28:21:3e:af, Marvell DSA mode Forward, dev 0, port 1, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 102: 192.168.30.1 > 192.168.30.2: ICMP echo request, id 13586, seq 2, length 64
+    4  22:21:40.563252 d6:c5:28:21:3e:af > 00:50:b6:29:10:70, Marvell DSA mode From CPU, target dev 0, port 1, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 102: 192.168.30.2 > 192.168.30.1: ICMP echo reply, id 13586, seq 2, length 64
+    5  22:21:41.576445 00:50:b6:29:10:70 > d6:c5:28:21:3e:af, Marvell DSA mode Forward, dev 0, port 1, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 102: 192.168.30.1 > 192.168.30.2: ICMP echo request, id 13586, seq 3, length 64
+    6  22:21:41.576541 d6:c5:28:21:3e:af > 00:50:b6:29:10:70, Marvell DSA mode From CPU, target dev 0, port 1, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 102: 192.168.30.2 > 192.168.30.1: ICMP echo reply, id 13586, seq 3, length 64
+    7  22:21:44.560086 d6:c5:28:21:3e:af > 00:50:b6:29:10:70, Marvell DSA mode From CPU, target dev 0, port 1, untagged, VID 0, FPri 0, ethertype ARP (0x0806), length 46: Request who-has 192.168.30.1 tell 192.168.30.2, length 28
+    8  22:21:44.560415 00:50:b6:29:10:70 > d6:c5:28:21:3e:af, Marvell DSA mode Forward, dev 0, port 1, untagged, VID 0, FPri 0, ethertype ARP (0x0806), length 64: Reply 192.168.30.1 is-at 00:50:b6:29:10:70, length 46
diff --git a/tests/edsa-e.out b/tests/edsa-e.out
index 314eccf..2c04dee 100644
--- a/tests/edsa-e.out
+++ b/tests/edsa-e.out
@@ -1,10 +1,10 @@
-    1  22:21:44.604675 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, IP 192.168.20.1 > 192.168.20.2: ICMP echo request, id 13583, seq 1, length 64
-    2  22:21:44.604995 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, IP 192.168.20.2 > 192.168.20.1: ICMP echo reply, id 13583, seq 1, length 64
-    3  22:21:45.622749 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, IP 192.168.20.1 > 192.168.20.2: ICMP echo request, id 13583, seq 2, length 64
-    4  22:21:45.622883 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, IP 192.168.20.2 > 192.168.20.1: ICMP echo reply, id 13583, seq 2, length 64
-    5  22:21:46.636035 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, IP 192.168.20.1 > 192.168.20.2: ICMP echo request, id 13583, seq 3, length 64
-    6  22:21:46.636142 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, IP 192.168.20.2 > 192.168.20.1: ICMP echo reply, id 13583, seq 3, length 64
-    7  22:21:49.680084 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, ARP, Request who-has 192.168.20.1 tell 192.168.20.2, length 28
-    8  22:21:49.680474 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, ARP, Reply 192.168.20.1 is-at 00:50:b6:29:10:7e, length 46
-    9  22:21:49.809266 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, ARP, Request who-has 192.168.20.2 tell 192.168.20.1, length 46
-   10  22:21:49.809342 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, ARP, Reply 192.168.20.2 is-at c6:e8:9f:7d:69:da, length 28
+    1  22:21:44.604675 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 106: 192.168.20.1 > 192.168.20.2: ICMP echo request, id 13583, seq 1, length 64
+    2  22:21:44.604995 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 106: 192.168.20.2 > 192.168.20.1: ICMP echo reply, id 13583, seq 1, length 64
+    3  22:21:45.622749 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 106: 192.168.20.1 > 192.168.20.2: ICMP echo request, id 13583, seq 2, length 64
+    4  22:21:45.622883 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 106: 192.168.20.2 > 192.168.20.1: ICMP echo reply, id 13583, seq 2, length 64
+    5  22:21:46.636035 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 106: 192.168.20.1 > 192.168.20.2: ICMP echo request, id 13583, seq 3, length 64
+    6  22:21:46.636142 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, ethertype IPv4 (0x0800), length 106: 192.168.20.2 > 192.168.20.1: ICMP echo reply, id 13583, seq 3, length 64
+    7  22:21:49.680084 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, ethertype ARP (0x0806), length 50: Request who-has 192.168.20.1 tell 192.168.20.2, length 28
+    8  22:21:49.680474 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, ethertype ARP (0x0806), length 68: Reply 192.168.20.1 is-at 00:50:b6:29:10:7e, length 46
+    9  22:21:49.809266 00:50:b6:29:10:7e > c6:e8:9f:7d:69:da, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode Forward, dev 0, port 0, untagged, VID 0, FPri 0, ethertype ARP (0x0806), length 68: Request who-has 192.168.20.2 tell 192.168.20.1, length 46
+   10  22:21:49.809342 c6:e8:9f:7d:69:da > 00:50:b6:29:10:7e, Marvell EDSA ethertype 0xdada (Unknown), rsvd 0 0, mode From CPU, target dev 0, port 0, untagged, VID 0, FPri 0, ethertype ARP (0x0806), length 50: Reply 192.168.20.2 is-at c6:e8:9f:7d:69:da, length 28