]> The Tcpdump Group git mirrors - tcpdump/blob - print-arista.c
CI: Add warning exemptions for Sun C (suncc-5.14) on Solaris 10
[tcpdump] / print-arista.c
1 // Copyright (c) 2018 Arista Networks, Inc. All rights reserved.
2
3 /* \summary: EtherType protocol for Arista Networks printer */
4
5 #include <config.h>
6
7 #include "netdissect-stdinc.h"
8
9 #include "netdissect.h"
10 #include "extract.h"
11 #include "timeval-operations.h"
12
13 /*
14
15 From Bill Fenner:
16
17 The Arista timestamp header consists of the following fields:
18 1. The Arista ethertype (0xd28b)
19 2. A 2-byte subtype field; 0x01 indicates the timestamp header
20 3. A 2-byte version field, described below.
21 4. A 48-bit or 64-bit timestamp field, depending on the contents of the version field
22
23 This header is then followed by the original ethertype and the remainder of the original packet.
24
25 0 1 2 3
26 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
27 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28 | dst mac |
29 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 | | |
31 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
32 | src mac |
33 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 | ethertype 0xd28b | subtype 0x1 |
35 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 | version | |
37 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
38 | timestamp... |
39 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40
41 The two-byte version value is split into 3 fields:
42 1. The timescale in use. Currently assigned values include:
43 0 = TAI
44 1 = UTC
45 2. The timestamp format and length. Currently assigned values include:
46 1 = 64-bit timestamp
47 2 = 48-bit timestamp
48 3. The hardware info
49 0 = R/R2 series
50 1 = R3 series
51
52 0 1
53 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
54 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 | timescale | format|hw info|
56 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57
58
59 See also: https://www.arista.com/assets/data/pdf/Whitepapers/Overview_Arista_Timestamps.pdf
60
61 */
62
63 #define ARISTA_SUBTYPE_TIMESTAMP 0x0001
64 static const struct tok subtype_str[] = {
65 { ARISTA_SUBTYPE_TIMESTAMP, "Timestamp" },
66 { 0, NULL }
67 };
68
69 static const struct tok ts_timescale_str[] = {
70 { 0, "TAI" },
71 { 1, "UTC" },
72 { 0, NULL }
73 };
74
75 #define FORMAT_64BIT 0x1
76 #define FORMAT_48BIT 0x2
77 static const struct tok ts_format_str[] = {
78 { FORMAT_64BIT, "64-bit" },
79 { FORMAT_48BIT, "48-bit" },
80 { 0, NULL }
81 };
82
83 static const struct tok hw_info_str[] = {
84 { 0, "R/R2" },
85 { 1, "R3" },
86 { 0, NULL }
87 };
88
89 static inline void
90 arista_print_date_hms_time(netdissect_options *ndo, const uint32_t seconds,
91 const uint32_t nanoseconds)
92 {
93 const time_t ts = seconds;
94 char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss")];
95
96 ND_PRINT("%s.%09u",
97 nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S",
98 gmtime(&ts)), nanoseconds);
99 if (nanoseconds > ND_NANO_PER_SEC - 1)
100 ND_PRINT(" " ND_INVALID_NANO_SEC_STR);
101 }
102
103 int
104 arista_ethertype_print(netdissect_options *ndo, const u_char *bp, u_int len _U_)
105 {
106 uint16_t subTypeId;
107 u_short bytesConsumed = 0;
108
109 ndo->ndo_protocol = "arista";
110
111 subTypeId = GET_BE_U_2(bp);
112 bp += 2;
113 bytesConsumed += 2;
114
115 ND_PRINT("SubType %s (0x%04x), ",
116 tok2str(subtype_str, "Unknown", subTypeId),
117 subTypeId);
118
119 // TapAgg Header Timestamping
120 if (subTypeId == ARISTA_SUBTYPE_TIMESTAMP) {
121 uint32_t seconds;
122 uint32_t nanoseconds;
123 uint8_t ts_timescale = GET_U_1(bp);
124 bp += 1;
125 bytesConsumed += 1;
126 ND_PRINT("Timescale %s (%u), ",
127 tok2str(ts_timescale_str, "Unknown", ts_timescale),
128 ts_timescale);
129
130 uint8_t ts_format = GET_U_1(bp) >> 4;
131 uint8_t hw_info = GET_U_1(bp) & 0x0f;
132 bp += 1;
133 bytesConsumed += 1;
134
135 // Timestamp has 32-bit lsb in nanosec and remaining msb in sec
136 ND_PRINT("Format %s (%u), HwInfo %s (%u), Timestamp ",
137 tok2str(ts_format_str, "Unknown", ts_format),
138 ts_format,
139 tok2str(hw_info_str, "Unknown", hw_info),
140 hw_info);
141 switch (ts_format) {
142 case FORMAT_64BIT:
143 seconds = GET_BE_U_4(bp);
144 nanoseconds = GET_BE_U_4(bp + 4);
145 arista_print_date_hms_time(ndo, seconds, nanoseconds);
146 bytesConsumed += 8;
147 break;
148 case FORMAT_48BIT:
149 seconds = GET_BE_U_2(bp);
150 nanoseconds = GET_BE_U_4(bp + 2);
151 ND_PRINT("%u.%09u", seconds, nanoseconds);
152 if (nanoseconds > ND_NANO_PER_SEC - 1)
153 ND_PRINT(" " ND_INVALID_NANO_SEC_STR);
154 bytesConsumed += 6;
155 break;
156 default:
157 return -1;
158 }
159 } else {
160 return -1;
161 }
162 ND_PRINT(": ");
163 return bytesConsumed;
164 }