xref: /dpdk/lib/net/rte_ether.c (revision c9902a15bd005b6d4fe072cf7b60fe4ee679155f)
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 }
115