DPDK  17.02.1
rte_ether.h
Go to the documentation of this file.
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 
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
56 #define ETHER_TYPE_LEN 2
57 #define ETHER_CRC_LEN 4
58 #define ETHER_HDR_LEN \
59  (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
60 #define ETHER_MIN_LEN 64
61 #define ETHER_MAX_LEN 1518
62 #define ETHER_MTU \
63  (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
65 #define ETHER_MAX_VLAN_FRAME_LEN \
66  (ETHER_MAX_LEN + 4)
68 #define ETHER_MAX_JUMBO_FRAME_LEN \
69  0x3F00
71 #define ETHER_MAX_VLAN_ID 4095
73 #define ETHER_MIN_MTU 68
86 struct ether_addr {
87  uint8_t addr_bytes[ETHER_ADDR_LEN];
88 } __attribute__((__packed__));
89 
90 #define ETHER_LOCAL_ADMIN_ADDR 0x02
91 #define ETHER_GROUP_ADDR 0x01
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
300 struct ether_hdr {
303  uint16_t ether_type;
304 } __attribute__((__packed__));
305 
311 struct vlan_hdr {
312  uint16_t vlan_tci;
313  uint16_t eth_proto;
314 } __attribute__((__packed__));
315 
321 struct vxlan_hdr {
322  uint32_t vx_flags;
323  uint32_t vx_vni;
324 } __attribute__((__packed__));
325 
326 /* Ethernet frame types */
327 #define ETHER_TYPE_IPv4 0x0800
328 #define ETHER_TYPE_IPv6 0x86DD
329 #define ETHER_TYPE_ARP 0x0806
330 #define ETHER_TYPE_RARP 0x8035
331 #define ETHER_TYPE_VLAN 0x8100
332 #define ETHER_TYPE_QINQ 0x88A8
333 #define ETHER_TYPE_1588 0x88F7
334 #define ETHER_TYPE_SLOW 0x8809
335 #define ETHER_TYPE_TEB 0x6558
337 #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr))
338 
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 
357  return -1;
358 
359  struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1);
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 
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);
406 
407  vh = (struct vlan_hdr *) (nh + 1);
408  vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci);
409 
410  (*m)->ol_flags &= ~PKT_RX_VLAN_STRIPPED;
411 
412  return 0;
413 }
414 
415 #ifdef __cplusplus
416 }
417 #endif
418 
419 #endif /* _RTE_ETHER_H_ */