14b9d779ecb34310b6bb8eb1f8a62f5a5002e9a0
[dpdk.git] / lib / net / rte_ether.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <stdbool.h>
6
7 #include <rte_ether.h>
8 #include <rte_errno.h>
9
10 void
11 rte_eth_random_addr(uint8_t *addr)
12 {
13 #ifdef RTE_EXEC_ENV_WINDOWS /* FIXME: random is not supported */
14         RTE_SET_USED(addr);
15 #else
16         uint64_t rand = rte_rand();
17         uint8_t *p = (uint8_t *)&rand;
18
19         rte_memcpy(addr, p, RTE_ETHER_ADDR_LEN);
20         addr[0] &= (uint8_t)~RTE_ETHER_GROUP_ADDR;      /* clear multicast bit */
21         addr[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR;  /* set local assignment bit */
22 #endif
23 }
24
25 void
26 rte_ether_format_addr(char *buf, uint16_t size,
27                       const struct rte_ether_addr *eth_addr)
28 {
29         snprintf(buf, size, RTE_ETHER_ADDR_PRT_FMT,
30                 RTE_ETHER_ADDR_BYTES(eth_addr));
31 }
32
33 static int8_t get_xdigit(char ch)
34 {
35         if (ch >= '0' && ch <= '9')
36                 return ch - '0';
37         if (ch >= 'a' && ch <= 'f')
38                 return ch - 'a' + 10;
39         if (ch >= 'A' && ch <= 'F')
40                 return ch - 'A' + 10;
41         return -1;
42 }
43
44 /* Convert 00:11:22:33:44:55 to ethernet address */
45 static bool get_ether_addr6(const char *s0, struct rte_ether_addr *ea)
46 {
47         const char *s = s0;
48         int i;
49
50         for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
51                 int8_t x;
52
53                 x = get_xdigit(*s++);
54                 if (x < 0)
55                         return false;
56
57                 ea->addr_bytes[i] = x << 4;
58                 x = get_xdigit(*s++);
59                 if (x < 0)
60                         return false;
61                 ea->addr_bytes[i] |= x;
62
63                 if (i < RTE_ETHER_ADDR_LEN - 1 &&
64                     *s++ != ':')
65                         return false;
66         }
67
68         /* return true if at end of string */
69         return *s == '\0';
70 }
71
72 /* Convert 0011:2233:4455 to ethernet address */
73 static bool get_ether_addr3(const char *s, struct rte_ether_addr *ea)
74 {
75         int i, j;
76
77         for (i = 0; i < RTE_ETHER_ADDR_LEN; i += 2) {
78                 uint16_t w = 0;
79
80                 for (j = 0; j < 4; j++) {
81                         int8_t x;
82
83                         x = get_xdigit(*s++);
84                         if (x < 0)
85                                 return false;
86                         w = (w << 4) | x;
87                 }
88                 ea->addr_bytes[i] = w >> 8;
89                 ea->addr_bytes[i + 1] = w & 0xff;
90
91                 if (i < RTE_ETHER_ADDR_LEN - 2 &&
92                     *s++ != ':')
93                         return false;
94         }
95
96         return *s == '\0';
97 }
98
99 /*
100  * Like ether_aton_r but can handle either
101  * XX:XX:XX:XX:XX:XX or XXXX:XXXX:XXXX
102  * and is more restrictive.
103  */
104 int
105 rte_ether_unformat_addr(const char *s, struct rte_ether_addr *ea)
106 {
107         if (get_ether_addr6(s, ea))
108                 return 0;
109         if (get_ether_addr3(s, ea))
110                 return 0;
111
112         rte_errno = EINVAL;
113         return -1;
114 }