diff --git a/CMakeLists.txt b/CMakeLists.txt index 9535e0a35..44467095f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1307,6 +1307,7 @@ set(NETDISSECT_SOURCE_LIST_C print-dhcp6.c print-domain.c print-dsa.c + print-dsa-gsw1xx.c print-dtp.c print-dvmrp.c print-eap.c diff --git a/Makefile.in b/Makefile.in index fc102099c..4f5116d0e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -120,6 +120,7 @@ LIBNETDISSECT_SRC=\ print-dhcp6.c \ print-domain.c \ print-dsa.c \ + print-dsa-gsw1xx.c \ print-dtp.c \ print-dvmrp.c \ print-eap.c \ diff --git a/ethertype.h b/ethertype.h index 8b71b3025..5f21d22fa 100644 --- a/ethertype.h +++ b/ethertype.h @@ -182,6 +182,9 @@ #ifndef ETHERTYPE_AOE #define ETHERTYPE_AOE 0x88a2 #endif +#ifndef ETHERTYPE_GSW1XX +#define ETHERTYPE_GSW1XX 0x88c3 +#endif #ifndef ETHERTYPE_PTP #define ETHERTYPE_PTP 0x88f7 #endif diff --git a/netdissect.h b/netdissect.h index 6663e9d6d..e33f7aea0 100644 --- a/netdissect.h +++ b/netdissect.h @@ -556,6 +556,7 @@ extern void chdlc_if_print IF_PRINTER_ARGS; extern void cip_if_print IF_PRINTER_ARGS; extern void dsa_if_print IF_PRINTER_ARGS; extern void edsa_if_print IF_PRINTER_ARGS; +extern void edsa_gsw1xx_if_print IF_PRINTER_ARGS; extern void enc_if_print IF_PRINTER_ARGS; extern void ether_if_print IF_PRINTER_ARGS; extern void fddi_if_print IF_PRINTER_ARGS; diff --git a/print-dsa-gsw1xx.c b/print-dsa-gsw1xx.c new file mode 100644 index 000000000..480b0eb3c --- /dev/null +++ b/print-dsa-gsw1xx.c @@ -0,0 +1,199 @@ +/* + * 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. + */ + +/* based on print-dsa.c */ + +/* \summary: MaxLinear (Ethertype) Distributed Switch Architecture */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "netdissect-stdinc.h" + +#include "netdissect.h" +#include "ethertype.h" +#include "addrtoname.h" +#include "extract.h" + +/* + * Ingress and Egress have different formats. + * + * Format of (Ethertyped) Ingress tagged frames: + * + * 0 +----+----+----+----+----+----+----+----+ + * | Ether Destination Address | + * +6 +----+----+----+----+----+----+----+----+ + * | Ether Source Address | + * +6 +----+----+----+----+----+----+----+----+ +- + * | Prog. DSA Ether Type [15:8] | | (8-byte) EDSA Tag + * +1 +----+----+----+----+----+----+----+----+ | Contains a programmable Ether type. + * | Prog. DSA Ether Type [7:0] | | + + * +1 +----+----+----+----+----+----+----+----+ | | (6-byte) Special Tag Content + * |PME[7] TCE[6] TSE[5] FNL[4] TTC[3:0] | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | TEPML [7:0] | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | TEPMH [7:0] | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | Res[7:5] IE[4] SP[3:0] | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | Res [7:0] all zero | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | Res [7:0] all zero | | | + * +1 +----+----+----+----+----+----+----+----+ +- +- + * + * Format of (Ethertyped) Egress tagged frames: + * + * 0 +----+----+----+----+----+----+----+----+ + * | Ether Destination Address | + * +6 +----+----+----+----+----+----+----+----+ + * | Ether Source Address | + * +6 +----+----+----+----+----+----+----+----+ +- + * | Prog. DSA Ether Type [15:8] | | (8-byte) EDSA Tag + * +1 +----+----+----+----+----+----+----+----+ | Contains a programmable Ether type. + * | Prog. DSA Ether Type [7:0] | | + + * +1 +----+----+----+----+----+----+----+----+ | | (6-byte) Special Tag Content + * | TC[7:4] IPN [3:0] | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | PPPOE[7] IPV[6] IPO[5:0] | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | DLPML [7:0] | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | DLPMR [7:0] | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | MI[7] KL2UM[6] PLHB[5:0] | | | + * +1 +----+----+----+----+----+----+----+----+ | | + * | PLLB [7:0] | | | + * +2 +----+----+----+----+----+----+----+----+ +- +- + * . . . . . . . . . + * + * PME: Port map enable + * IPN: Ingress port number + * TCE: Traffic class enable + * TSE: Time stamp enable + * FNL: Force no learning + * TC: Traffic class + * IPV: IPv4 packet + * IPO: IP offset + * SP: Source port + * IE: Interrupt enable + * PPPOE: ppp-over-ethernet + * DLPML: Destination logical port map low bits. + * DLPMR: Destination logical port map high (reserved) + * MI: Mirror indication + * KL2UM Known l2 unicast/multicast mac. + * PLHB: Packet Length High Bits + * PLLB: Packet Length Low Bits. + * TEPML: Target egress port maps low bits + * TEPMH: Target egress port maps high bits (reserved) + * Res: Reserved + */ + +#define TOK(tag, byte, mask, shift) ((GET_U_1(&(((const u_char *) tag)[byte])) & (mask)) >> (shift)) + +#define GSW1XX_ET1(tag) TOK(tag, 0, 0xFF, 0) +#define GSW1XX_ET2(tag) TOK(tag, 1, 0xFF, 0) +#define GSW1XX_TTC(tag) TOK(tag, 2, 0x08, 0) +#define GSW1XX_IG_PME(tag) TOK(tag, 2, 0x80, 7) +#define GSW1XX_IG_TCE(tag) TOK(tag, 2, 0x40, 6) +#define GSW1XX_IG_TSE(tag) TOK(tag, 2, 0x20, 5) +#define GSW1XX_IG_FNL(tag) TOK(tag, 2, 0x10, 4) +#define GSW1XX_IG_SP(tag) TOK(tag, 2, 0x0F, 0) +#define GSW1XX_IG_IE(tag) TOK(tag, 5, 0x10, 3) +#define GSW1XX_EG_IPN(tag) TOK(tag, 2, 0x0F, 0) +#define GSW1XX_EG_TC(tag) TOK(tag, 2, 0xF0, 4) +#define GSW1XX_EG_POE(tag) TOK(tag, 2, 0x80, 7) +#define GSW1XX_EG_IV4(tag) TOK(tag, 2, 0x40, 6) +#define GSW1XX_EG_IPO(tag) TOK(tag, 3, 0x3F, 0) + +#define GSW1XX_MAP_LOW(tag) TOK(tag, 3, 0xFF, 0) +#define GSW1XX_MAP_HIGH(tag) TOK(tag, 4, 0xFF, 0) +#define GSW1XX_MAP(tag) ((GSW1XX_MAP_HIGH(tag) << 8) + GSW1XX_MAP_LOW(tag)) +#define GSW1XX_LEN_LOW(tag) TOK(tag, 7, 0xFF, 0) +#define GSW1XX_LEN_HIGH(tag) TOK(tag, 6, 0x3F, 0) +#define GSW1XX_LEN(tag) ((GSW1XX_LEN_HIGH(tag) << 8) + GSW1XX_LEN_LOW(tag)) + +#define EDSA_LEN 8 + +static void +tag_common_print(netdissect_options *ndo, const u_char *p) +{ + if (ndo->ndo_eflag ) { + int egress = !!GSW1XX_LEN(p); + + if (egress) { + ND_PRINT("Egress Port %d,", GSW1XX_EG_IPN(p)); + if (ndo->ndo_eflag > 1) { + ND_PRINT("TTC %d,", GSW1XX_TTC(p)); + ND_PRINT("TC %d,", GSW1XX_EG_TC(p)); + ND_PRINT("IPN %d,", GSW1XX_EG_IPN(p)); + ND_PRINT("POE %d,", GSW1XX_EG_POE(p)); + if (GSW1XX_EG_IPO(p)) { + ND_PRINT("IV4 %d,", GSW1XX_EG_IV4(p)); + ND_PRINT("IPO %d,", GSW1XX_EG_IPO(p)); + } + ND_PRINT("Len %d,", GSW1XX_LEN(p)); + } + } else { + ND_PRINT("Ingress Port %d,", GSW1XX_IG_SP(p)); + ND_PRINT("MAP %d,", GSW1XX_MAP(p)); + if (ndo->ndo_eflag > 1) { + ND_PRINT("PME %d,", GSW1XX_IG_PME(p)); + ND_PRINT("TCE %d,", GSW1XX_IG_TCE(p)); + ND_PRINT("TTC %d,", GSW1XX_TTC(p)); + ND_PRINT("FNL %d,", GSW1XX_IG_FNL(p)); + ND_PRINT("IE %d,", GSW1XX_IG_IE(p)); + ND_PRINT("TSE %d,", GSW1XX_IG_TSE(p)); + } + } + } +} + +static void +edsa_tag_print(netdissect_options *ndo, const u_char *bp) +{ + const u_char *p = bp; + uint16_t edsa_etype; + + edsa_etype = GET_BE_U_2(p); + if (ndo->ndo_eflag > 2) { + ND_PRINT("MaxLinear ethertype 0x%04x (%s), ", edsa_etype, + tok2str(ethertype_values, "Unknown", edsa_etype)); + } else { + if (edsa_etype == ETHERTYPE_GSW1XX) + ND_PRINT("GSW1XX "); + else + ND_PRINT("GSW1XX Unknown 0x%04x, ", edsa_etype); + } + tag_common_print(ndo, p); +} + +void +edsa_gsw1xx_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 = "gsw1xx"; + ndo->ndo_ll_hdr_len += + ether_switch_tag_print(ndo, p, length, caplen, edsa_tag_print, EDSA_LEN); +} diff --git a/print-ether.c b/print-ether.c index 324d089fc..51cca36fa 100644 --- a/print-ether.c +++ b/print-ether.c @@ -102,6 +102,7 @@ const struct tok ethertype_values[] = { { ETHERTYPE_AOE, "AoE" }, { ETHERTYPE_PTP, "PTP" }, { ETHERTYPE_ARISTA, "Arista Vendor Specific Protocol" }, + { ETHERTYPE_GSW1XX, "GSW1XX" }, { 0, NULL} }; diff --git a/print.c b/print.c index 4f36aec92..5fddc7d20 100644 --- a/print.c +++ b/print.c @@ -79,6 +79,9 @@ static const struct printer printers[] = { #ifdef DLT_DSA_TAG_EDSA { edsa_if_print, DLT_DSA_TAG_EDSA }, #endif +#ifdef DLT_DSA_TAG_GSW1XX + { edsa_gsw1xx_if_print, DLT_DSA_TAG_GSW1XX }, +#endif #ifdef DLT_ENC { enc_if_print, DLT_ENC }, #endif diff --git a/tests/TESTLIST b/tests/TESTLIST index 96f7b7f04..10ca578e3 100644 --- a/tests/TESTLIST +++ b/tests/TESTLIST @@ -108,6 +108,9 @@ edsa-e edsa.pcap edsa-e.out -e edsa-high-vid edsa-high-vid.pcap edsa-high-vid.out edsa-high-vid-e edsa-high-vid.pcap edsa-high-vid-e.out -e +# MaxLinear DSA tag tests +gsw1xx gsw1xx.pcap gsw1xx.out -n -e + # ESP tests esp0 02-sunrise-sunset-esp.pcap esp0.out esp_truncated esp_truncated.pcap esp_truncated.out diff --git a/tests/gsw1xx.out b/tests/gsw1xx.out new file mode 100644 index 000000000..06c215ac8 --- /dev/null +++ b/tests/gsw1xx.out @@ -0,0 +1,3 @@ + 1 2025-10-29 11:53:16.673113 1c:fd:08:7c:0a:e1 > b8:a4:4f:fc:53:8a, GSW1XX Egress Port 1,ethertype IPv4 (0x0800), length 106: 192.168.0.1 > 192.168.0.240: ICMP echo request, id 5, seq 2918, length 64 + 2 2025-10-29 11:53:16.673257 b8:a4:4f:fc:53:8a > 1c:fd:08:7c:0a:e1, GSW1XX Ingress Port 0,MAP 2,ethertype IPv4 (0x0800), length 106: 192.168.0.240 > 192.168.0.1: ICMP echo reply, id 5, seq 2918, length 64 + 3 2025-10-29 11:53:16.674057 b8:a4:4f:fc:53:8a > 01:00:5e:00:00:fb, GSW1XX Ingress Port 0,MAP 2,ethertype IPv4 (0x0800), length 362: 192.168.0.240.5353 > 224.0.0.251.5353: 0*- [0q] 3/0/4 (Cache flush) PTR axis-b8a44ffc538a.local., (Cache flush) PTR axis-b8a44ffc538a.local., (Cache flush) PTR axis-b8a44ffc538a.local. (312) diff --git a/tests/gsw1xx.pcap b/tests/gsw1xx.pcap new file mode 100644 index 000000000..7aea17838 Binary files /dev/null and b/tests/gsw1xx.pcap differ