]> The Tcpdump Group git mirrors - tcpdump/blob - print-medsa.c
Add a summary comment in all other printers
[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 /* \summary: Marvell Extended Distributed Switch Architecture (MEDSA) printer */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <netdissect-stdinc.h>
29
30 #include "netdissect.h"
31 #include "ether.h"
32 #include "ethertype.h"
33 #include "extract.h"
34
35 static const char tstr[] = "[|MEDSA]";
36
37 /*
38 * Marvell Extended Distributed Switch Archiecture.
39 *
40 * A Marvell propriatary header used for passing packets to/from
41 * specific ports of a switch. There is no open specification of this
42 * header, but is documented in the Marvell Switch data sheets. For
43 * background, see:
44 *
45 * https://lwn.net/Articles/302333/
46 */
47 struct medsa_pkthdr {
48 u_char bytes[6];
49 u_short ether_type;
50 };
51
52 /* Bytes 0 and 1 are reserved and should contain 0 */
53 #define TAG(medsa) (medsa->bytes[2] >> 6)
54 #define TAG_TO_CPU 0
55 #define TAG_FROM_CPU 1
56 #define TAG_FORWARD 3
57 #define SRC_TAG(medsa) ((medsa->bytes[2] >> 5) & 0x01)
58 #define SRC_DEV(medsa) (medsa->bytes[2] & 0x1f)
59 #define SRC_PORT(medsa) ((medsa->bytes[3] >> 3) & 0x01f)
60 #define TRUNK(medsa) ((medsa->bytes[3] >> 2) & 0x01)
61 #define CODE(medsa) ((medsa->bytes[3] & 0x06) | \
62 ((medsa->bytes[4] >> 4) & 0x01))
63 #define CODE_BDPU 0
64 #define CODE_IGMP_MLD 2
65 #define CODE_ARP_MIRROR 4
66 #define CFI(medsa) (medsa->bytes[3] & 0x01)
67 #define PRI(medsa) (medsa->bytes[4] >> 5)
68 #define VID(medsa) (((u_short)(medsa->bytes[4] & 0xf) << 8 | \
69 medsa->bytes[5]))
70
71 static const struct tok tag_values[] = {
72 { TAG_TO_CPU, "To_CPU" },
73 { TAG_FROM_CPU, "From_CPU" },
74 { TAG_FORWARD, "Forward" },
75 { 0, NULL },
76 };
77
78 static const struct tok code_values[] = {
79 { CODE_BDPU, "BDPU" },
80 { CODE_IGMP_MLD, "IGMP/MLD" },
81 { CODE_ARP_MIRROR, "APR_Mirror" },
82 { 0, NULL },
83 };
84
85 static void
86 medsa_print_full(netdissect_options *ndo,
87 const struct medsa_pkthdr *medsa,
88 u_int caplen)
89 {
90 u_char tag = TAG(medsa);
91
92 ND_PRINT((ndo, "%s",
93 tok2str(tag_values, "Unknown (%u)", tag)));
94
95 switch (tag) {
96 case TAG_TO_CPU:
97 ND_PRINT((ndo, ", %stagged", SRC_TAG(medsa) ? "" : "un"));
98 ND_PRINT((ndo, ", dev.port:vlan %d.%d:%d",
99 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
100
101 ND_PRINT((ndo, ", %s",
102 tok2str(code_values, "Unknown (%u)", CODE(medsa))));
103 if (CFI(medsa))
104 ND_PRINT((ndo, ", CFI"));
105
106 ND_PRINT((ndo, ", pri %d: ", PRI(medsa)));
107 break;
108 case TAG_FROM_CPU:
109 ND_PRINT((ndo, ", %stagged", SRC_TAG(medsa) ? "" : "un"));
110 ND_PRINT((ndo, ", dev.port:vlan %d.%d:%d",
111 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
112
113 if (CFI(medsa))
114 ND_PRINT((ndo, ", CFI"));
115
116 ND_PRINT((ndo, ", pri %d: ", PRI(medsa)));
117 break;
118 case TAG_FORWARD:
119 ND_PRINT((ndo, ", %stagged", SRC_TAG(medsa) ? "" : "un"));
120 if (TRUNK(medsa))
121 ND_PRINT((ndo, ", dev.trunk:vlan %d.%d:%d",
122 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
123 else
124 ND_PRINT((ndo, ", dev.port:vlan %d.%d:%d",
125 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
126
127 if (CFI(medsa))
128 ND_PRINT((ndo, ", CFI"));
129
130 ND_PRINT((ndo, ", pri %d: ", PRI(medsa)));
131 break;
132 default:
133 ND_DEFAULTPRINT((const u_char *)medsa, caplen);
134 return;
135 }
136 }
137
138 void
139 medsa_print(netdissect_options *ndo,
140 const u_char *bp, u_int length, u_int caplen)
141 {
142 register const struct ether_header *ep;
143 const struct medsa_pkthdr *medsa;
144 u_short ether_type;
145
146 medsa = (const struct medsa_pkthdr *)bp;
147 ep = (const struct ether_header *)(bp - sizeof(*ep));
148 ND_TCHECK(*medsa);
149
150 if (!ndo->ndo_eflag)
151 ND_PRINT((ndo, "MEDSA %d.%d:%d: ",
152 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
153 else
154 medsa_print_full(ndo, medsa, caplen);
155
156 bp += 8;
157 length -= 8;
158 caplen -= 8;
159
160 ether_type = EXTRACT_16BITS(&medsa->ether_type);
161 if (ether_type <= ETHERMTU) {
162 /* Try to print the LLC-layer header & higher layers */
163 if (llc_print(ndo, bp, length, caplen, ESRC(ep), EDST(ep)) < 0) {
164 /* packet type not known, print raw packet */
165 if (!ndo->ndo_suppress_default_print)
166 ND_DEFAULTPRINT(bp, caplen);
167 }
168 } else {
169 if (ndo->ndo_eflag)
170 ND_PRINT((ndo, "ethertype %s (0x%04x) ",
171 tok2str(ethertype_values, "Unknown",
172 ether_type),
173 ether_type));
174
175 if (ethertype_print(ndo, ether_type, bp, length, caplen) == 0) {
176 /* ether_type not known, print raw packet */
177 if (!ndo->ndo_eflag)
178 ND_PRINT((ndo, "ethertype %s (0x%04x) ",
179 tok2str(ethertype_values, "Unknown",
180 ether_type),
181 ether_type));
182
183 if (!ndo->ndo_suppress_default_print)
184 ND_DEFAULTPRINT(bp, caplen);
185 }
186 }
187 return;
188 trunc:
189 ND_PRINT((ndo, "%s", tstr));
190 }
191
192 /*
193 * Local Variables:
194 * c-style: bsd
195 * End:
196 */
197