]> The Tcpdump Group git mirrors - tcpdump/blob - print-medsa.c
Functions in libnetdissect must use ndo_error() function
[tcpdump] / print-medsa.c
1 /*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <tcpdump-stdinc.h>
27
28 #include "interface.h"
29 #include "ether.h"
30 #include "ethertype.h"
31 #include "extract.h" /* must come after interface.h */
32
33 static const char tstr[] = "[|MEDSA]";
34
35 /*
36 * Marvell Extended Distributed Switch Archiecture.
37 *
38 * A Marvell propriatary header used for passing packets to/from
39 * specific ports of a switch. There is no open specification of this
40 * header, but is documented in the Marvell Switch data sheets. For
41 * background, see:
42 *
43 * https://lwn.net/Articles/302333/
44 */
45 struct medsa_pkthdr {
46 u_char bytes[6];
47 u_short ether_type;
48 };
49
50 /* Bytes 0 and 1 are reserved and should contain 0 */
51 #define TAG(medsa) (medsa->bytes[2] >> 6)
52 #define TAG_TO_CPU 0
53 #define TAG_FROM_CPU 1
54 #define TAG_FORWARD 3
55 #define SRC_TAG(medsa) ((medsa->bytes[2] >> 5) & 0x01)
56 #define SRC_DEV(medsa) (medsa->bytes[2] & 0x1f)
57 #define SRC_PORT(medsa) ((medsa->bytes[3] >> 3) & 0x01f)
58 #define TRUNK(medsa) ((medsa->bytes[3] >> 2) & 0x01)
59 #define CODE(medsa) ((medsa->bytes[3] & 0x06) | \
60 ((medsa->bytes[4] >> 4) & 0x01))
61 #define CODE_BDPU 0
62 #define CODE_IGMP_MLD 2
63 #define CODE_ARP_MIRROR 4
64 #define CFI(medsa) (medsa->bytes[3] & 0x01)
65 #define PRI(medsa) (medsa->bytes[4] >> 5)
66 #define VID(medsa) (((u_short)(medsa->bytes[4] & 0xf) << 8 | \
67 medsa->bytes[5]))
68
69 static const struct tok tag_values[] = {
70 { TAG_TO_CPU, "To_CPU" },
71 { TAG_FROM_CPU, "From_CPU" },
72 { TAG_FORWARD, "Forward" },
73 { 0, NULL },
74 };
75
76 static const struct tok code_values[] = {
77 { CODE_BDPU, "BDPU" },
78 { CODE_IGMP_MLD, "IGMP/MLD" },
79 { CODE_ARP_MIRROR, "APR_Mirror" },
80 { 0, NULL },
81 };
82
83 static void
84 medsa_print_full(netdissect_options *ndo,
85 const struct medsa_pkthdr *medsa,
86 u_int caplen)
87 {
88 u_char tag = TAG(medsa);
89
90 ND_PRINT((ndo, "%s",
91 tok2str(tag_values, "Unknown (%u)", tag)));
92
93 switch (tag) {
94 case TAG_TO_CPU:
95 ND_PRINT((ndo, ", %stagged", SRC_TAG(medsa) ? "" : "un"));
96 ND_PRINT((ndo, ", dev.port:vlan %d.%d:%d",
97 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
98
99 ND_PRINT((ndo, ", %s",
100 tok2str(code_values, "Unknown (%u)", CODE(medsa))));
101 if (CFI(medsa))
102 ND_PRINT((ndo, ", CFI"));
103
104 ND_PRINT((ndo, ", pri %d: ", PRI(medsa)));
105 break;
106 case TAG_FROM_CPU:
107 ND_PRINT((ndo, ", %stagged", SRC_TAG(medsa) ? "" : "un"));
108 ND_PRINT((ndo, ", dev.port:vlan %d.%d:%d",
109 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
110
111 if (CFI(medsa))
112 ND_PRINT((ndo, ", CFI"));
113
114 ND_PRINT((ndo, ", pri %d: ", PRI(medsa)));
115 break;
116 case TAG_FORWARD:
117 ND_PRINT((ndo, ", %stagged", SRC_TAG(medsa) ? "" : "un"));
118 if (TRUNK(medsa))
119 ND_PRINT((ndo, ", dev.trunk:vlan %d.%d:%d",
120 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
121 else
122 ND_PRINT((ndo, ", dev.port:vlan %d.%d:%d",
123 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
124
125 if (CFI(medsa))
126 ND_PRINT((ndo, ", CFI"));
127
128 ND_PRINT((ndo, ", pri %d: ", PRI(medsa)));
129 break;
130 default:
131 ND_DEFAULTPRINT((const u_char *)medsa, caplen);
132 return;
133 }
134 }
135
136 void
137 medsa_print(netdissect_options *ndo,
138 const u_char *bp, u_int length, u_int caplen)
139 {
140 register const struct ether_header *ep;
141 const struct medsa_pkthdr *medsa;
142 u_short ether_type;
143
144 medsa = (const struct medsa_pkthdr *)bp;
145 ep = (const struct ether_header *)(bp - sizeof(*ep));
146 ND_TCHECK(*medsa);
147
148 if (!ndo->ndo_eflag)
149 ND_PRINT((ndo, "MEDSA %d.%d:%d: ",
150 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
151 else
152 medsa_print_full(ndo, medsa, caplen);
153
154 bp += 8;
155 length -= 8;
156 caplen -= 8;
157
158 ether_type = EXTRACT_16BITS(&medsa->ether_type);
159 if (ether_type <= ETHERMTU) {
160 /* Try to print the LLC-layer header & higher layers */
161 if (llc_print(ndo, bp, length, caplen, ESRC(ep), EDST(ep)) < 0) {
162 /* packet type not known, print raw packet */
163 if (!ndo->ndo_suppress_default_print)
164 ND_DEFAULTPRINT(bp, caplen);
165 }
166 } else {
167 if (ndo->ndo_eflag)
168 ND_PRINT((ndo, "ethertype %s (0x%04x) ",
169 tok2str(ethertype_values, "Unknown",
170 ether_type),
171 ether_type));
172
173 if (ethertype_print(ndo, ether_type, bp, length, caplen) == 0) {
174 /* ether_type not known, print raw packet */
175 if (!ndo->ndo_eflag)
176 ND_PRINT((ndo, "ethertype %s (0x%04x) ",
177 tok2str(ethertype_values, "Unknown",
178 ether_type),
179 ether_type));
180
181 if (!ndo->ndo_suppress_default_print)
182 ND_DEFAULTPRINT(bp, caplen);
183 }
184 }
185 return;
186 trunc:
187 ND_PRINT((ndo, "%s", tstr));
188 }
189
190 /*
191 * Local Variables:
192 * c-style: bsd
193 * End:
194 */
195