nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Copyright (c) 1998-2006 The TCPDUMP project |
||
3 | * |
||
4 | * Redistribution and use in source and binary forms, with or without |
||
5 | * modification, are permitted provided that: (1) source code |
||
6 | * distributions retain the above copyright notice and this paragraph |
||
7 | * in its entirety, and (2) distributions including binary code include |
||
8 | * the above copyright notice and this paragraph in its entirety in |
||
9 | * the documentation or other materials provided with the distribution. |
||
10 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND |
||
11 | * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT |
||
12 | * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
||
13 | * FOR A PARTICULAR PURPOSE. |
||
14 | * |
||
15 | * support for the IEEE MPCP protocol as per 802.3ah |
||
16 | * |
||
17 | * Original code by Hannes Gredler (hannes@juniper.net) |
||
18 | */ |
||
19 | |||
20 | #define NETDISSECT_REWORKED |
||
21 | #ifdef HAVE_CONFIG_H |
||
22 | #include "config.h" |
||
23 | #endif |
||
24 | |||
25 | #include <tcpdump-stdinc.h> |
||
26 | |||
27 | #include "interface.h" |
||
28 | #include "extract.h" |
||
29 | |||
30 | #define MPCP_TIMESTAMP_LEN 4 |
||
31 | #define MPCP_TIMESTAMP_DURATION_LEN 2 |
||
32 | |||
33 | struct mpcp_common_header_t { |
||
34 | uint8_t opcode[2]; |
||
35 | uint8_t timestamp[MPCP_TIMESTAMP_LEN]; |
||
36 | }; |
||
37 | |||
38 | #define MPCP_OPCODE_PAUSE 0x0001 |
||
39 | #define MPCP_OPCODE_GATE 0x0002 |
||
40 | #define MPCP_OPCODE_REPORT 0x0003 |
||
41 | #define MPCP_OPCODE_REG_REQ 0x0004 |
||
42 | #define MPCP_OPCODE_REG 0x0005 |
||
43 | #define MPCP_OPCODE_REG_ACK 0x0006 |
||
44 | |||
45 | static const struct tok mpcp_opcode_values[] = { |
||
46 | { MPCP_OPCODE_PAUSE, "Pause" }, |
||
47 | { MPCP_OPCODE_GATE, "Gate" }, |
||
48 | { MPCP_OPCODE_REPORT, "Report" }, |
||
49 | { MPCP_OPCODE_REG_REQ, "Register Request" }, |
||
50 | { MPCP_OPCODE_REG, "Register" }, |
||
51 | { MPCP_OPCODE_REG_ACK, "Register ACK" }, |
||
52 | { 0, NULL} |
||
53 | }; |
||
54 | |||
55 | #define MPCP_GRANT_NUMBER_LEN 1 |
||
56 | #define MPCP_GRANT_NUMBER_MASK 0x7 |
||
57 | static const struct tok mpcp_grant_flag_values[] = { |
||
58 | { 0x08, "Discovery" }, |
||
59 | { 0x10, "Force Grant #1" }, |
||
60 | { 0x20, "Force Grant #2" }, |
||
61 | { 0x40, "Force Grant #3" }, |
||
62 | { 0x80, "Force Grant #4" }, |
||
63 | { 0, NULL} |
||
64 | }; |
||
65 | |||
66 | struct mpcp_grant_t { |
||
67 | uint8_t starttime[MPCP_TIMESTAMP_LEN]; |
||
68 | uint8_t duration[MPCP_TIMESTAMP_DURATION_LEN]; |
||
69 | }; |
||
70 | |||
71 | struct mpcp_reg_req_t { |
||
72 | uint8_t flags; |
||
73 | uint8_t pending_grants; |
||
74 | }; |
||
75 | |||
76 | |||
77 | static const struct tok mpcp_reg_req_flag_values[] = { |
||
78 | { 1, "Register" }, |
||
79 | { 3, "De-Register" }, |
||
80 | { 0, NULL} |
||
81 | }; |
||
82 | |||
83 | struct mpcp_reg_t { |
||
84 | uint8_t assigned_port[2]; |
||
85 | uint8_t flags; |
||
86 | uint8_t sync_time[MPCP_TIMESTAMP_DURATION_LEN]; |
||
87 | uint8_t echoed_pending_grants; |
||
88 | }; |
||
89 | |||
90 | static const struct tok mpcp_reg_flag_values[] = { |
||
91 | { 1, "Re-Register" }, |
||
92 | { 2, "De-Register" }, |
||
93 | { 3, "ACK" }, |
||
94 | { 4, "NACK" }, |
||
95 | { 0, NULL} |
||
96 | }; |
||
97 | |||
98 | #define MPCP_REPORT_QUEUESETS_LEN 1 |
||
99 | #define MPCP_REPORT_REPORTBITMAP_LEN 1 |
||
100 | static const struct tok mpcp_report_bitmap_values[] = { |
||
101 | { 0x01, "Q0" }, |
||
102 | { 0x02, "Q1" }, |
||
103 | { 0x04, "Q2" }, |
||
104 | { 0x08, "Q3" }, |
||
105 | { 0x10, "Q4" }, |
||
106 | { 0x20, "Q5" }, |
||
107 | { 0x40, "Q6" }, |
||
108 | { 0x80, "Q7" }, |
||
109 | { 0, NULL} |
||
110 | }; |
||
111 | |||
112 | struct mpcp_reg_ack_t { |
||
113 | uint8_t flags; |
||
114 | uint8_t echoed_assigned_port[2]; |
||
115 | uint8_t echoed_sync_time[MPCP_TIMESTAMP_DURATION_LEN]; |
||
116 | }; |
||
117 | |||
118 | static const struct tok mpcp_reg_ack_flag_values[] = { |
||
119 | { 0, "NACK" }, |
||
120 | { 1, "ACK" }, |
||
121 | { 0, NULL} |
||
122 | }; |
||
123 | |||
124 | void |
||
125 | mpcp_print(netdissect_options *ndo, register const u_char *pptr, register u_int length) |
||
126 | { |
||
127 | union { |
||
128 | const struct mpcp_common_header_t *common_header; |
||
129 | const struct mpcp_grant_t *grant; |
||
130 | const struct mpcp_reg_req_t *reg_req; |
||
131 | const struct mpcp_reg_t *reg; |
||
132 | const struct mpcp_reg_ack_t *reg_ack; |
||
133 | } mpcp; |
||
134 | |||
135 | |||
136 | const u_char *tptr; |
||
137 | uint16_t opcode; |
||
138 | uint8_t grant_numbers, grant; |
||
139 | uint8_t queue_sets, queue_set, report_bitmap, report; |
||
140 | |||
141 | tptr=pptr; |
||
142 | mpcp.common_header = (const struct mpcp_common_header_t *)pptr; |
||
143 | |||
144 | ND_TCHECK2(*tptr, sizeof(const struct mpcp_common_header_t)); |
||
145 | opcode = EXTRACT_16BITS(mpcp.common_header->opcode); |
||
146 | ND_PRINT((ndo, "MPCP, Opcode %s", tok2str(mpcp_opcode_values, "Unknown (%u)", opcode))); |
||
147 | if (opcode != MPCP_OPCODE_PAUSE) { |
||
148 | ND_PRINT((ndo, ", Timestamp %u ticks", EXTRACT_32BITS(mpcp.common_header->timestamp))); |
||
149 | } |
||
150 | ND_PRINT((ndo, ", length %u", length)); |
||
151 | |||
152 | if (!ndo->ndo_vflag) |
||
153 | return; |
||
154 | |||
155 | tptr += sizeof(const struct mpcp_common_header_t); |
||
156 | |||
157 | switch (opcode) { |
||
158 | case MPCP_OPCODE_PAUSE: |
||
159 | break; |
||
160 | |||
161 | case MPCP_OPCODE_GATE: |
||
162 | ND_TCHECK2(*tptr, MPCP_GRANT_NUMBER_LEN); |
||
163 | grant_numbers = *tptr & MPCP_GRANT_NUMBER_MASK; |
||
164 | ND_PRINT((ndo, "\n\tGrant Numbers %u, Flags [ %s ]", |
||
165 | grant_numbers, |
||
166 | bittok2str(mpcp_grant_flag_values, |
||
167 | "?", |
||
168 | *tptr &~ MPCP_GRANT_NUMBER_MASK))); |
||
169 | tptr++; |
||
170 | |||
171 | for (grant = 1; grant <= grant_numbers; grant++) { |
||
172 | ND_TCHECK2(*tptr, sizeof(const struct mpcp_grant_t)); |
||
173 | mpcp.grant = (const struct mpcp_grant_t *)tptr; |
||
174 | ND_PRINT((ndo, "\n\tGrant #%u, Start-Time %u ticks, duration %u ticks", |
||
175 | grant, |
||
176 | EXTRACT_32BITS(mpcp.grant->starttime), |
||
177 | EXTRACT_16BITS(mpcp.grant->duration))); |
||
178 | tptr += sizeof(const struct mpcp_grant_t); |
||
179 | } |
||
180 | |||
181 | ND_TCHECK2(*tptr, MPCP_TIMESTAMP_DURATION_LEN); |
||
182 | ND_PRINT((ndo, "\n\tSync-Time %u ticks", EXTRACT_16BITS(tptr))); |
||
183 | break; |
||
184 | |||
185 | |||
186 | case MPCP_OPCODE_REPORT: |
||
187 | ND_TCHECK2(*tptr, MPCP_REPORT_QUEUESETS_LEN); |
||
188 | queue_sets = *tptr; |
||
189 | tptr+=MPCP_REPORT_QUEUESETS_LEN; |
||
190 | ND_PRINT((ndo, "\n\tTotal Queue-Sets %u", queue_sets)); |
||
191 | |||
192 | for (queue_set = 1; queue_set < queue_sets; queue_set++) { |
||
193 | ND_TCHECK2(*tptr, MPCP_REPORT_REPORTBITMAP_LEN); |
||
194 | report_bitmap = *(tptr); |
||
195 | ND_PRINT((ndo, "\n\t Queue-Set #%u, Report-Bitmap [ %s ]", |
||
196 | queue_sets, |
||
197 | bittok2str(mpcp_report_bitmap_values, "Unknown", report_bitmap))); |
||
198 | tptr++; |
||
199 | |||
200 | report=1; |
||
201 | while (report_bitmap != 0) { |
||
202 | if (report_bitmap & 1) { |
||
203 | ND_TCHECK2(*tptr, MPCP_TIMESTAMP_DURATION_LEN); |
||
204 | ND_PRINT((ndo, "\n\t Q%u Report, Duration %u ticks", |
||
205 | report, |
||
206 | EXTRACT_16BITS(tptr))); |
||
207 | tptr+=MPCP_TIMESTAMP_DURATION_LEN; |
||
208 | } |
||
209 | report++; |
||
210 | report_bitmap = report_bitmap >> 1; |
||
211 | } |
||
212 | } |
||
213 | break; |
||
214 | |||
215 | case MPCP_OPCODE_REG_REQ: |
||
216 | ND_TCHECK2(*tptr, sizeof(const struct mpcp_reg_req_t)); |
||
217 | mpcp.reg_req = (const struct mpcp_reg_req_t *)tptr; |
||
218 | ND_PRINT((ndo, "\n\tFlags [ %s ], Pending-Grants %u", |
||
219 | bittok2str(mpcp_reg_req_flag_values, "Reserved", mpcp.reg_req->flags), |
||
220 | mpcp.reg_req->pending_grants)); |
||
221 | break; |
||
222 | |||
223 | case MPCP_OPCODE_REG: |
||
224 | ND_TCHECK2(*tptr, sizeof(const struct mpcp_reg_t)); |
||
225 | mpcp.reg = (const struct mpcp_reg_t *)tptr; |
||
226 | ND_PRINT((ndo, "\n\tAssigned-Port %u, Flags [ %s ]" \ |
||
227 | "\n\tSync-Time %u ticks, Echoed-Pending-Grants %u", |
||
228 | EXTRACT_16BITS(mpcp.reg->assigned_port), |
||
229 | bittok2str(mpcp_reg_flag_values, "Reserved", mpcp.reg->flags), |
||
230 | EXTRACT_16BITS(mpcp.reg->sync_time), |
||
231 | mpcp.reg->echoed_pending_grants)); |
||
232 | break; |
||
233 | |||
234 | case MPCP_OPCODE_REG_ACK: |
||
235 | ND_TCHECK2(*tptr, sizeof(const struct mpcp_reg_ack_t)); |
||
236 | mpcp.reg_ack = (const struct mpcp_reg_ack_t *)tptr; |
||
237 | ND_PRINT((ndo, "\n\tEchoed-Assigned-Port %u, Flags [ %s ]" \ |
||
238 | "\n\tEchoed-Sync-Time %u ticks", |
||
239 | EXTRACT_16BITS(mpcp.reg_ack->echoed_assigned_port), |
||
240 | bittok2str(mpcp_reg_ack_flag_values, "Reserved", mpcp.reg_ack->flags), |
||
241 | EXTRACT_16BITS(mpcp.reg_ack->echoed_sync_time))); |
||
242 | break; |
||
243 | |||
244 | default: |
||
245 | /* unknown opcode - hexdump for now */ |
||
246 | print_unknown_data(ndo,pptr, "\n\t", length); |
||
247 | break; |
||
248 | } |
||
249 | |||
250 | return; |
||
251 | |||
252 | trunc: |
||
253 | ND_PRINT((ndo, "\n\t[|MPCP]")); |
||
254 | } |
||
255 | /* |
||
256 | * Local Variables: |
||
257 | * c-style: whitesmith |
||
258 | * c-basic-offset: 8 |
||
259 | * End: |
||
260 | */ |