]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2010-2014 Intel Corporation | |
7c673cae FG |
3 | */ |
4 | ||
5 | #ifndef _RTE_ETHER_H_ | |
6 | #define _RTE_ETHER_H_ | |
7 | ||
8 | /** | |
9 | * @file | |
10 | * | |
11 | * Ethernet Helpers in RTE | |
12 | */ | |
13 | ||
14 | #ifdef __cplusplus | |
15 | extern "C" { | |
16 | #endif | |
17 | ||
18 | #include <stdint.h> | |
19 | #include <stdio.h> | |
20 | ||
21 | #include <rte_memcpy.h> | |
22 | #include <rte_random.h> | |
23 | #include <rte_mbuf.h> | |
24 | #include <rte_byteorder.h> | |
25 | ||
26 | #define ETHER_ADDR_LEN 6 /**< Length of Ethernet address. */ | |
27 | #define ETHER_TYPE_LEN 2 /**< Length of Ethernet type field. */ | |
28 | #define ETHER_CRC_LEN 4 /**< Length of Ethernet CRC. */ | |
29 | #define ETHER_HDR_LEN \ | |
30 | (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) /**< Length of Ethernet header. */ | |
31 | #define ETHER_MIN_LEN 64 /**< Minimum frame len, including CRC. */ | |
32 | #define ETHER_MAX_LEN 1518 /**< Maximum frame len, including CRC. */ | |
33 | #define ETHER_MTU \ | |
34 | (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) /**< Ethernet MTU. */ | |
35 | ||
36 | #define ETHER_MAX_VLAN_FRAME_LEN \ | |
37 | (ETHER_MAX_LEN + 4) /**< Maximum VLAN frame length, including CRC. */ | |
38 | ||
39 | #define ETHER_MAX_JUMBO_FRAME_LEN \ | |
40 | 0x3F00 /**< Maximum Jumbo frame length, including CRC. */ | |
41 | ||
42 | #define ETHER_MAX_VLAN_ID 4095 /**< Maximum VLAN ID. */ | |
43 | ||
44 | #define ETHER_MIN_MTU 68 /**< Minimum MTU for IPv4 packets, see RFC 791. */ | |
45 | ||
46 | /** | |
47 | * Ethernet address: | |
48 | * A universally administered address is uniquely assigned to a device by its | |
49 | * manufacturer. The first three octets (in transmission order) contain the | |
50 | * Organizationally Unique Identifier (OUI). The following three (MAC-48 and | |
51 | * EUI-48) octets are assigned by that organization with the only constraint | |
52 | * of uniqueness. | |
53 | * A locally administered address is assigned to a device by a network | |
54 | * administrator and does not contain OUIs. | |
55 | * See http://standards.ieee.org/regauth/groupmac/tutorial.html | |
56 | */ | |
57 | struct ether_addr { | |
58 | uint8_t addr_bytes[ETHER_ADDR_LEN]; /**< Addr bytes in tx order */ | |
59 | } __attribute__((__packed__)); | |
60 | ||
61 | #define ETHER_LOCAL_ADMIN_ADDR 0x02 /**< Locally assigned Eth. address. */ | |
62 | #define ETHER_GROUP_ADDR 0x01 /**< Multicast or broadcast Eth. address. */ | |
63 | ||
64 | /** | |
65 | * Check if two Ethernet addresses are the same. | |
66 | * | |
67 | * @param ea1 | |
68 | * A pointer to the first ether_addr structure containing | |
69 | * the ethernet address. | |
70 | * @param ea2 | |
71 | * A pointer to the second ether_addr structure containing | |
72 | * the ethernet address. | |
73 | * | |
74 | * @return | |
75 | * True (1) if the given two ethernet address are the same; | |
76 | * False (0) otherwise. | |
77 | */ | |
78 | static inline int is_same_ether_addr(const struct ether_addr *ea1, | |
79 | const struct ether_addr *ea2) | |
80 | { | |
81 | int i; | |
82 | for (i = 0; i < ETHER_ADDR_LEN; i++) | |
83 | if (ea1->addr_bytes[i] != ea2->addr_bytes[i]) | |
84 | return 0; | |
85 | return 1; | |
86 | } | |
87 | ||
88 | /** | |
89 | * Check if an Ethernet address is filled with zeros. | |
90 | * | |
91 | * @param ea | |
92 | * A pointer to a ether_addr structure containing the ethernet address | |
93 | * to check. | |
94 | * @return | |
95 | * True (1) if the given ethernet address is filled with zeros; | |
96 | * false (0) otherwise. | |
97 | */ | |
98 | static inline int is_zero_ether_addr(const struct ether_addr *ea) | |
99 | { | |
100 | int i; | |
101 | for (i = 0; i < ETHER_ADDR_LEN; i++) | |
102 | if (ea->addr_bytes[i] != 0x00) | |
103 | return 0; | |
104 | return 1; | |
105 | } | |
106 | ||
107 | /** | |
108 | * Check if an Ethernet address is a unicast address. | |
109 | * | |
110 | * @param ea | |
111 | * A pointer to a ether_addr structure containing the ethernet address | |
112 | * to check. | |
113 | * @return | |
114 | * True (1) if the given ethernet address is a unicast address; | |
115 | * false (0) otherwise. | |
116 | */ | |
117 | static inline int is_unicast_ether_addr(const struct ether_addr *ea) | |
118 | { | |
119 | return (ea->addr_bytes[0] & ETHER_GROUP_ADDR) == 0; | |
120 | } | |
121 | ||
122 | /** | |
123 | * Check if an Ethernet address is a multicast address. | |
124 | * | |
125 | * @param ea | |
126 | * A pointer to a ether_addr structure containing the ethernet address | |
127 | * to check. | |
128 | * @return | |
129 | * True (1) if the given ethernet address is a multicast address; | |
130 | * false (0) otherwise. | |
131 | */ | |
132 | static inline int is_multicast_ether_addr(const struct ether_addr *ea) | |
133 | { | |
134 | return ea->addr_bytes[0] & ETHER_GROUP_ADDR; | |
135 | } | |
136 | ||
137 | /** | |
138 | * Check if an Ethernet address is a broadcast address. | |
139 | * | |
140 | * @param ea | |
141 | * A pointer to a ether_addr structure containing the ethernet address | |
142 | * to check. | |
143 | * @return | |
144 | * True (1) if the given ethernet address is a broadcast address; | |
145 | * false (0) otherwise. | |
146 | */ | |
147 | static inline int is_broadcast_ether_addr(const struct ether_addr *ea) | |
148 | { | |
149 | const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea; | |
150 | ||
151 | return (ea_words[0] == 0xFFFF && ea_words[1] == 0xFFFF && | |
152 | ea_words[2] == 0xFFFF); | |
153 | } | |
154 | ||
155 | /** | |
156 | * Check if an Ethernet address is a universally assigned address. | |
157 | * | |
158 | * @param ea | |
159 | * A pointer to a ether_addr structure containing the ethernet address | |
160 | * to check. | |
161 | * @return | |
162 | * True (1) if the given ethernet address is a universally assigned address; | |
163 | * false (0) otherwise. | |
164 | */ | |
165 | static inline int is_universal_ether_addr(const struct ether_addr *ea) | |
166 | { | |
167 | return (ea->addr_bytes[0] & ETHER_LOCAL_ADMIN_ADDR) == 0; | |
168 | } | |
169 | ||
170 | /** | |
171 | * Check if an Ethernet address is a locally assigned address. | |
172 | * | |
173 | * @param ea | |
174 | * A pointer to a ether_addr structure containing the ethernet address | |
175 | * to check. | |
176 | * @return | |
177 | * True (1) if the given ethernet address is a locally assigned address; | |
178 | * false (0) otherwise. | |
179 | */ | |
180 | static inline int is_local_admin_ether_addr(const struct ether_addr *ea) | |
181 | { | |
182 | return (ea->addr_bytes[0] & ETHER_LOCAL_ADMIN_ADDR) != 0; | |
183 | } | |
184 | ||
185 | /** | |
186 | * Check if an Ethernet address is a valid address. Checks that the address is a | |
187 | * unicast address and is not filled with zeros. | |
188 | * | |
189 | * @param ea | |
190 | * A pointer to a ether_addr structure containing the ethernet address | |
191 | * to check. | |
192 | * @return | |
193 | * True (1) if the given ethernet address is valid; | |
194 | * false (0) otherwise. | |
195 | */ | |
196 | static inline int is_valid_assigned_ether_addr(const struct ether_addr *ea) | |
197 | { | |
198 | return is_unicast_ether_addr(ea) && (!is_zero_ether_addr(ea)); | |
199 | } | |
200 | ||
201 | /** | |
202 | * Generate a random Ethernet address that is locally administered | |
203 | * and not multicast. | |
204 | * @param addr | |
205 | * A pointer to Ethernet address. | |
206 | */ | |
207 | static inline void eth_random_addr(uint8_t *addr) | |
208 | { | |
209 | uint64_t rand = rte_rand(); | |
210 | uint8_t *p = (uint8_t *)&rand; | |
211 | ||
212 | rte_memcpy(addr, p, ETHER_ADDR_LEN); | |
9f95a23c | 213 | addr[0] &= (uint8_t)~ETHER_GROUP_ADDR; /* clear multicast bit */ |
7c673cae FG |
214 | addr[0] |= ETHER_LOCAL_ADMIN_ADDR; /* set local assignment bit */ |
215 | } | |
216 | ||
217 | /** | |
218 | * Fast copy an Ethernet address. | |
219 | * | |
220 | * @param ea_from | |
221 | * A pointer to a ether_addr structure holding the Ethernet address to copy. | |
222 | * @param ea_to | |
223 | * A pointer to a ether_addr structure where to copy the Ethernet address. | |
224 | */ | |
225 | static inline void ether_addr_copy(const struct ether_addr *ea_from, | |
226 | struct ether_addr *ea_to) | |
227 | { | |
228 | #ifdef __INTEL_COMPILER | |
229 | uint16_t *from_words = (uint16_t *)(ea_from->addr_bytes); | |
230 | uint16_t *to_words = (uint16_t *)(ea_to->addr_bytes); | |
231 | ||
232 | to_words[0] = from_words[0]; | |
233 | to_words[1] = from_words[1]; | |
234 | to_words[2] = from_words[2]; | |
235 | #else | |
236 | /* | |
237 | * Use the common way, because of a strange gcc warning. | |
238 | */ | |
239 | *ea_to = *ea_from; | |
240 | #endif | |
241 | } | |
242 | ||
243 | #define ETHER_ADDR_FMT_SIZE 18 | |
244 | /** | |
245 | * Format 48bits Ethernet address in pattern xx:xx:xx:xx:xx:xx. | |
246 | * | |
247 | * @param buf | |
248 | * A pointer to buffer contains the formatted MAC address. | |
249 | * @param size | |
250 | * The format buffer size. | |
251 | * @param eth_addr | |
252 | * A pointer to a ether_addr structure. | |
253 | */ | |
254 | static inline void | |
255 | ether_format_addr(char *buf, uint16_t size, | |
256 | const struct ether_addr *eth_addr) | |
257 | { | |
258 | snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X", | |
259 | eth_addr->addr_bytes[0], | |
260 | eth_addr->addr_bytes[1], | |
261 | eth_addr->addr_bytes[2], | |
262 | eth_addr->addr_bytes[3], | |
263 | eth_addr->addr_bytes[4], | |
264 | eth_addr->addr_bytes[5]); | |
265 | } | |
266 | ||
267 | /** | |
268 | * Ethernet header: Contains the destination address, source address | |
269 | * and frame type. | |
270 | */ | |
271 | struct ether_hdr { | |
272 | struct ether_addr d_addr; /**< Destination address. */ | |
273 | struct ether_addr s_addr; /**< Source address. */ | |
274 | uint16_t ether_type; /**< Frame type. */ | |
275 | } __attribute__((__packed__)); | |
276 | ||
277 | /** | |
278 | * Ethernet VLAN Header. | |
279 | * Contains the 16-bit VLAN Tag Control Identifier and the Ethernet type | |
280 | * of the encapsulated frame. | |
281 | */ | |
282 | struct vlan_hdr { | |
283 | uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */ | |
284 | uint16_t eth_proto;/**< Ethernet type of encapsulated frame. */ | |
285 | } __attribute__((__packed__)); | |
286 | ||
287 | /** | |
288 | * VXLAN protocol header. | |
289 | * Contains the 8-bit flag, 24-bit VXLAN Network Identifier and | |
290 | * Reserved fields (24 bits and 8 bits) | |
291 | */ | |
292 | struct vxlan_hdr { | |
293 | uint32_t vx_flags; /**< flag (8) + Reserved (24). */ | |
294 | uint32_t vx_vni; /**< VNI (24) + Reserved (8). */ | |
295 | } __attribute__((__packed__)); | |
296 | ||
297 | /* Ethernet frame types */ | |
298 | #define ETHER_TYPE_IPv4 0x0800 /**< IPv4 Protocol. */ | |
299 | #define ETHER_TYPE_IPv6 0x86DD /**< IPv6 Protocol. */ | |
300 | #define ETHER_TYPE_ARP 0x0806 /**< Arp Protocol. */ | |
301 | #define ETHER_TYPE_RARP 0x8035 /**< Reverse Arp Protocol. */ | |
302 | #define ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */ | |
303 | #define ETHER_TYPE_QINQ 0x88A8 /**< IEEE 802.1ad QinQ tagging. */ | |
9f95a23c TL |
304 | #define ETHER_TYPE_PPPOE_DISCOVERY 0x8863 /**< PPPoE Discovery Stage. */ |
305 | #define ETHER_TYPE_PPPOE_SESSION 0x8864 /**< PPPoE Session Stage. */ | |
306 | #define ETHER_TYPE_ETAG 0x893F /**< IEEE 802.1BR E-Tag. */ | |
7c673cae FG |
307 | #define ETHER_TYPE_1588 0x88F7 /**< IEEE 802.1AS 1588 Precise Time Protocol. */ |
308 | #define ETHER_TYPE_SLOW 0x8809 /**< Slow protocols (LACP and Marker). */ | |
309 | #define ETHER_TYPE_TEB 0x6558 /**< Transparent Ethernet Bridging. */ | |
11fdf7f2 | 310 | #define ETHER_TYPE_LLDP 0x88CC /**< LLDP Protocol. */ |
9f95a23c TL |
311 | #define ETHER_TYPE_MPLS 0x8847 /**< MPLS ethertype. */ |
312 | #define ETHER_TYPE_MPLSM 0x8848 /**< MPLS multicast ethertype. */ | |
7c673cae FG |
313 | |
314 | #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)) | |
315 | /**< VXLAN tunnel header length. */ | |
316 | ||
9f95a23c TL |
317 | /** |
318 | * VXLAN-GPE protocol header (draft-ietf-nvo3-vxlan-gpe-05). | |
319 | * Contains the 8-bit flag, 8-bit next-protocol, 24-bit VXLAN Network | |
320 | * Identifier and Reserved fields (16 bits and 8 bits). | |
321 | */ | |
322 | struct vxlan_gpe_hdr { | |
323 | uint8_t vx_flags; /**< flag (8). */ | |
324 | uint8_t reserved[2]; /**< Reserved (16). */ | |
325 | uint8_t proto; /**< next-protocol (8). */ | |
326 | uint32_t vx_vni; /**< VNI (24) + Reserved (8). */ | |
327 | } __attribute__((__packed__)); | |
328 | ||
329 | /* VXLAN-GPE next protocol types */ | |
330 | #define VXLAN_GPE_TYPE_IPV4 1 /**< IPv4 Protocol. */ | |
331 | #define VXLAN_GPE_TYPE_IPV6 2 /**< IPv6 Protocol. */ | |
332 | #define VXLAN_GPE_TYPE_ETH 3 /**< Ethernet Protocol. */ | |
333 | #define VXLAN_GPE_TYPE_NSH 4 /**< NSH Protocol. */ | |
334 | #define VXLAN_GPE_TYPE_MPLS 5 /**< MPLS Protocol. */ | |
335 | #define VXLAN_GPE_TYPE_GBP 6 /**< GBP Protocol. */ | |
336 | #define VXLAN_GPE_TYPE_VBNG 7 /**< vBNG Protocol. */ | |
337 | ||
338 | #define ETHER_VXLAN_GPE_HLEN (sizeof(struct udp_hdr) + \ | |
339 | sizeof(struct vxlan_gpe_hdr)) | |
340 | /**< VXLAN-GPE tunnel header length. */ | |
341 | ||
7c673cae FG |
342 | /** |
343 | * Extract VLAN tag information into mbuf | |
344 | * | |
345 | * Software version of VLAN stripping | |
346 | * | |
347 | * @param m | |
348 | * The packet mbuf. | |
349 | * @return | |
350 | * - 0: Success | |
351 | * - 1: not a vlan packet | |
352 | */ | |
353 | static inline int rte_vlan_strip(struct rte_mbuf *m) | |
354 | { | |
355 | struct ether_hdr *eh | |
356 | = rte_pktmbuf_mtod(m, struct ether_hdr *); | |
9f95a23c | 357 | struct vlan_hdr *vh; |
7c673cae FG |
358 | |
359 | if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) | |
360 | return -1; | |
361 | ||
9f95a23c TL |
362 | vh = (struct vlan_hdr *)(eh + 1); |
363 | m->ol_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED; | |
7c673cae FG |
364 | m->vlan_tci = rte_be_to_cpu_16(vh->vlan_tci); |
365 | ||
366 | /* Copy ether header over rather than moving whole packet */ | |
367 | memmove(rte_pktmbuf_adj(m, sizeof(struct vlan_hdr)), | |
368 | eh, 2 * ETHER_ADDR_LEN); | |
369 | ||
370 | return 0; | |
371 | } | |
372 | ||
373 | /** | |
374 | * Insert VLAN tag into mbuf. | |
375 | * | |
376 | * Software version of VLAN unstripping | |
377 | * | |
378 | * @param m | |
379 | * The packet mbuf. | |
380 | * @return | |
381 | * - 0: On success | |
382 | * -EPERM: mbuf is is shared overwriting would be unsafe | |
383 | * -ENOSPC: not enough headroom in mbuf | |
384 | */ | |
385 | static inline int rte_vlan_insert(struct rte_mbuf **m) | |
386 | { | |
387 | struct ether_hdr *oh, *nh; | |
388 | struct vlan_hdr *vh; | |
389 | ||
390 | /* Can't insert header if mbuf is shared */ | |
391 | if (rte_mbuf_refcnt_read(*m) > 1) { | |
392 | struct rte_mbuf *copy; | |
393 | ||
394 | copy = rte_pktmbuf_clone(*m, (*m)->pool); | |
395 | if (unlikely(copy == NULL)) | |
396 | return -ENOMEM; | |
397 | rte_pktmbuf_free(*m); | |
398 | *m = copy; | |
399 | } | |
400 | ||
401 | oh = rte_pktmbuf_mtod(*m, struct ether_hdr *); | |
402 | nh = (struct ether_hdr *) | |
403 | rte_pktmbuf_prepend(*m, sizeof(struct vlan_hdr)); | |
404 | if (nh == NULL) | |
405 | return -ENOSPC; | |
406 | ||
407 | memmove(nh, oh, 2 * ETHER_ADDR_LEN); | |
408 | nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); | |
409 | ||
410 | vh = (struct vlan_hdr *) (nh + 1); | |
411 | vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci); | |
412 | ||
9f95a23c | 413 | (*m)->ol_flags &= ~(PKT_RX_VLAN_STRIPPED | PKT_TX_VLAN); |
11fdf7f2 | 414 | |
7c673cae FG |
415 | return 0; |
416 | } | |
417 | ||
418 | #ifdef __cplusplus | |
419 | } | |
420 | #endif | |
421 | ||
422 | #endif /* _RTE_ETHER_H_ */ |