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