DPDK  16.04.0
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_1588 0x88F7
333 #define ETHER_TYPE_SLOW 0x8809
334 #define ETHER_TYPE_TEB 0x6558
336 #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr))
337 
350 static inline int rte_vlan_strip(struct rte_mbuf *m)
351 {
352  struct ether_hdr *eh
353  = rte_pktmbuf_mtod(m, struct ether_hdr *);
354 
356  return -1;
357 
358  struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1);
361 
362  /* Copy ether header over rather than moving whole packet */
363  memmove(rte_pktmbuf_adj(m, sizeof(struct vlan_hdr)),
364  eh, 2 * ETHER_ADDR_LEN);
365 
366  return 0;
367 }
368 
381 static inline int rte_vlan_insert(struct rte_mbuf **m)
382 {
383  struct ether_hdr *oh, *nh;
384  struct vlan_hdr *vh;
385 
386  /* Can't insert header if mbuf is shared */
387  if (rte_mbuf_refcnt_read(*m) > 1) {
388  struct rte_mbuf *copy;
389 
390  copy = rte_pktmbuf_clone(*m, (*m)->pool);
391  if (unlikely(copy == NULL))
392  return -ENOMEM;
393  rte_pktmbuf_free(*m);
394  *m = copy;
395  }
396 
397  oh = rte_pktmbuf_mtod(*m, struct ether_hdr *);
398  nh = (struct ether_hdr *)
399  rte_pktmbuf_prepend(*m, sizeof(struct vlan_hdr));
400  if (nh == NULL)
401  return -ENOSPC;
402 
403  memmove(nh, oh, 2 * ETHER_ADDR_LEN);
405 
406  vh = (struct vlan_hdr *) (nh + 1);
407  vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci);
408 
409  return 0;
410 }
411 
412 #ifdef __cplusplus
413 }
414 #endif
415 
416 #endif /* _RTE_ETHER_H_ */