|
41 | 41 | #include "extract.h"
|
42 | 42 | #include "gre.h"
|
43 | 43 |
|
| 44 | +/* |
| 45 | + * ERSPAN Type II. |
| 46 | + */ |
44 | 47 | #define ERSPAN2_VER_SHIFT 28
|
45 | 48 | #define ERSPAN2_VER_MASK (0xfU << ERSPAN2_VER_SHIFT)
|
46 | 49 | #define ERSPAN2_VER (0x1U << ERSPAN2_VER_SHIFT)
|
|
63 | 66 | #define ERSPAN2_INDEX_MASK (0xfffffU << ERSPAN2_INDEX_SHIFT)
|
64 | 67 |
|
65 | 68 | void
|
66 |
| -erspan_print(netdissect_options *ndo, uint16_t flags, const u_char *bp, u_int len) |
| 69 | +erspan_print_i_ii(netdissect_options *ndo, uint16_t flags, const u_char *bp, u_int len) |
67 | 70 | {
|
68 | 71 | uint32_t hdr, ver, vlan, cos, en, sid, index;
|
69 | 72 |
|
70 | 73 | ndo->ndo_protocol = "erspan";
|
71 | 74 | nd_print_protocol(ndo);
|
72 | 75 |
|
73 | 76 | if (!(flags & GRE_SP)) {
|
| 77 | + /* |
| 78 | + * ERSPAN Type I; no header, just a raw Ethernet frame. |
| 79 | + */ |
74 | 80 | ND_PRINT(" type1: ");
|
75 | 81 | ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
|
76 | 82 | return;
|
77 | 83 | }
|
78 | 84 |
|
| 85 | + /* |
| 86 | + * ERSPAN Type II. |
| 87 | + */ |
79 | 88 | ND_ICHECK_U(len, <, 4);
|
80 | 89 | hdr = GET_BE_U_4(bp);
|
81 | 90 | bp += 4;
|
82 | 91 | len -= 4;
|
83 | 92 |
|
84 | 93 | ver = hdr & ERSPAN2_VER_MASK;
|
85 | 94 | if (ver != ERSPAN2_VER) {
|
| 95 | + /* |
| 96 | + * Not Type II. |
| 97 | + */ |
86 | 98 | ver >>= ERSPAN2_VER_SHIFT;
|
87 | 99 | ND_PRINT(" erspan-unknown-version-%x", ver);
|
88 | 100 | return;
|
@@ -135,3 +147,121 @@ erspan_print(netdissect_options *ndo, uint16_t flags, const u_char *bp, u_int le
|
135 | 147 | invalid:
|
136 | 148 | nd_print_invalid(ndo);
|
137 | 149 | }
|
| 150 | + |
| 151 | +/* |
| 152 | + * ERSPAN Type III. |
| 153 | + */ |
| 154 | +#define ERSPAN3_VER_SHIFT 28 |
| 155 | +#define ERSPAN3_VER_MASK (0xfU << ERSPAN3_VER_SHIFT) |
| 156 | +#define ERSPAN3_VER (0x2U << ERSPAN3_VER_SHIFT) |
| 157 | +#define ERSPAN3_VLAN_SHIFT 16 |
| 158 | +#define ERSPAN3_VLAN_MASK (0xfffU << ERSPAN3_VLAN_SHIFT) |
| 159 | +#define ERSPAN3_COS_SHIFT 13 |
| 160 | +#define ERSPAN3_COS_MASK (0x7U << ERSPAN3_COS_SHIFT) |
| 161 | +#define ERSPAN3_BSO_SHIFT 11 |
| 162 | +#define ERSPAN3_BSO_MASK (0x3U << ERSPAN3_BSO_SHIFT) |
| 163 | +#define ERSPAN3_BSO_GOOD_UNKNOWN 0x0U |
| 164 | +#define ERSPAN3_BSO_BAD 0x3U |
| 165 | +#define ERSPAN3_BSO_SHORT 0x1U |
| 166 | +#define ERSPAN3_BSO_OVERSIZED 0x2U |
| 167 | +#define ERSPAN3_T_SHIFT 10 |
| 168 | +#define ERSPAN3_T_MASK (0x1U << ERSPAN3_T_SHIFT) |
| 169 | +#define ERSPAN3_SID_SHIFT 0 |
| 170 | +#define ERSPAN3_SID_MASK (0x3ffU << ERSPAN3_SID_SHIFT) |
| 171 | +#define ERSPAN3_P_SHIFT 15 |
| 172 | +#define ERSPAN3_P_MASK (0x1U << ERSPAN3_P_MASK) |
| 173 | +#define ERSPAN3_FT_SHIFT 10 |
| 174 | +#define ERSPAN3_FT_MASK (0x1fU << ERSPAN3_FT_MASK) |
| 175 | +#define ERSPAN3_HW_ID_SHIFT 4 |
| 176 | +#define ERSPAN3_HW_ID_MASK (0x3fU << ERSPAN3_HW_ID_MASK) |
| 177 | +#define ERSPAN3_D_SHIFT 3 |
| 178 | +#define ERSPAN3_D_MASK (0x1U << ERSPAN3_D_SHIFT) |
| 179 | +#define ERSPAN3_GRA_SHIFT 1 |
| 180 | +#define ERSPAN3_GRA_MASK (0x3U << ERSPAN3_GRA_MASK) |
| 181 | +#define ERSPAN3_O_SHIFT 0 |
| 182 | +#define ERSPAN3_O_MASK (0x1U << ERSPAN3_O_SHIFT) |
| 183 | + |
| 184 | +static const struct tok erspan3_bso_values[] = { |
| 185 | + { ERSPAN3_BSO_GOOD_UNKNOWN, "Good/unknown" }, |
| 186 | + { ERSPAN3_BSO_BAD, "Bad" }, |
| 187 | + { ERSPAN3_BSO_SHORT, "Short" }, |
| 188 | + { ERSPAN3_BSO_OVERSIZED, "Oversized" }, |
| 189 | + { 0, NULL } |
| 190 | +}; |
| 191 | + |
| 192 | +void |
| 193 | +erspan_print_iii(netdissect_options *ndo, const u_char *bp, u_int len) |
| 194 | +{ |
| 195 | + uint32_t hdr, hdr2, ver, cos, sid; |
| 196 | + |
| 197 | + ndo->ndo_protocol = "erspan"; |
| 198 | + nd_print_protocol(ndo); |
| 199 | + |
| 200 | + /* |
| 201 | + * We do not check the GRE flags; ERSPAN Type III always |
| 202 | + * has an ERSPAN header. |
| 203 | + */ |
| 204 | + ND_ICHECK_U(len, <, 4); |
| 205 | + hdr = GET_BE_U_4(bp); |
| 206 | + bp += 4; |
| 207 | + len -= 4; |
| 208 | + |
| 209 | + ver = hdr & ERSPAN3_VER_MASK; |
| 210 | + if (ver != ERSPAN3_VER) { |
| 211 | + /* |
| 212 | + * Not Type III. |
| 213 | + */ |
| 214 | + ver >>= ERSPAN3_VER_SHIFT; |
| 215 | + ND_PRINT(" erspan-unknown-version-%x", ver); |
| 216 | + return; |
| 217 | + } |
| 218 | + |
| 219 | + if (ndo->ndo_vflag) |
| 220 | + ND_PRINT(" type3"); |
| 221 | + |
| 222 | + sid = (hdr & ERSPAN3_SID_MASK) >> ERSPAN3_SID_SHIFT; |
| 223 | + ND_PRINT(" session %u", sid); |
| 224 | + |
| 225 | + ND_PRINT(" bso %s", |
| 226 | + tok2str(erspan3_bso_values, "unknown %x", |
| 227 | + (hdr & ERSPAN3_BSO_MASK) >> ERSPAN3_BSO_SHIFT)); |
| 228 | + |
| 229 | + if (ndo->ndo_vflag) { |
| 230 | + cos = (hdr & ERSPAN3_COS_MASK) >> ERSPAN3_COS_SHIFT; |
| 231 | + ND_PRINT(" cos %u", cos); |
| 232 | + |
| 233 | + if (hdr & ERSPAN3_T_MASK) |
| 234 | + ND_PRINT(" truncated"); |
| 235 | + } |
| 236 | + |
| 237 | + /* Skip timestamp */ |
| 238 | + ND_ICHECK_U(len, <, 4); |
| 239 | + bp += 4; |
| 240 | + len -= 4; |
| 241 | + |
| 242 | + /* Skip SGT */ |
| 243 | + ND_ICHECK_U(len, <, 2); |
| 244 | + bp += 2; |
| 245 | + len -= 2; |
| 246 | + |
| 247 | + /* Additional fields */ |
| 248 | + ND_ICHECK_U(len, <, 2); |
| 249 | + hdr2 = GET_BE_U_2(bp); |
| 250 | + bp += 2; |
| 251 | + len -= 2; |
| 252 | + |
| 253 | + /* Do we have the platform-specific header? */ |
| 254 | + if (hdr2 & ERSPAN3_O_MASK) { |
| 255 | + /* Yes. Skip it. */ |
| 256 | + ND_ICHECK_U(len, <, 8); |
| 257 | + bp += 8; |
| 258 | + len -= 8; |
| 259 | + } |
| 260 | + |
| 261 | + ND_PRINT(": "); |
| 262 | + ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL); |
| 263 | + return; |
| 264 | + |
| 265 | +invalid: |
| 266 | + nd_print_invalid(ndo); |
| 267 | +} |
0 commit comments