]> The Tcpdump Group git mirrors - tcpdump/blob - print-medsa.c
Use nd_ types in 802.x and FDDI headers.
[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 "ethertype.h"
32 #include "addrtoname.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 const struct lladdr_info *src, const struct lladdr_info *dst)
142 {
143 const struct medsa_pkthdr *medsa;
144 u_short ether_type;
145
146 medsa = (const struct medsa_pkthdr *)bp;
147 ND_TCHECK(*medsa);
148
149 if (!ndo->ndo_eflag)
150 ND_PRINT((ndo, "MEDSA %d.%d:%d: ",
151 SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
152 else
153 medsa_print_full(ndo, medsa, caplen);
154
155 bp += 8;
156 length -= 8;
157 caplen -= 8;
158
159 ether_type = EXTRACT_BE_U_2(&medsa->ether_type);
160 if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
161 /* Try to print the LLC-layer header & higher layers */
162 if (llc_print(ndo, bp, length, caplen, src, dst) < 0) {
163 /* packet type not known, print raw packet */
164 if (!ndo->ndo_suppress_default_print)
165 ND_DEFAULTPRINT(bp, caplen);
166 }
167 } else {
168 if (ndo->ndo_eflag)
169 ND_PRINT((ndo, "ethertype %s (0x%04x) ",
170 tok2str(ethertype_values, "Unknown",
171 ether_type),
172 ether_type));
173 if (ethertype_print(ndo, ether_type, bp, length, caplen, src, dst) == 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