xref: /dpdk/lib/net/rte_ether.c (revision 9c30a6f3c9a456e8111a2b1e5f6c2c02a62025b6)
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, "%02X:%02X:%02X:%02X:%02X:%02X",
30 		 eth_addr->addr_bytes[0],
31 		 eth_addr->addr_bytes[1],
32 		 eth_addr->addr_bytes[2],
33 		 eth_addr->addr_bytes[3],
34 		 eth_addr->addr_bytes[4],
35 		 eth_addr->addr_bytes[5]);
36 }
37 
38 static int8_t get_xdigit(char ch)
39 {
40 	if (ch >= '0' && ch <= '9')
41 		return ch - '0';
42 	if (ch >= 'a' && ch <= 'f')
43 		return ch - 'a' + 10;
44 	if (ch >= 'A' && ch <= 'F')
45 		return ch - 'A' + 10;
46 	return -1;
47 }
48 
49 /* Convert 00:11:22:33:44:55 to ethernet address */
50 static bool get_ether_addr6(const char *s0, struct rte_ether_addr *ea)
51 {
52 	const char *s = s0;
53 	int i;
54 
55 	for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
56 		int8_t x;
57 
58 		x = get_xdigit(*s++);
59 		if (x < 0)
60 			return false;
61 
62 		ea->addr_bytes[i] = x << 4;
63 		x = get_xdigit(*s++);
64 		if (x < 0)
65 			return false;
66 		ea->addr_bytes[i] |= x;
67 
68 		if (i < RTE_ETHER_ADDR_LEN - 1 &&
69 		    *s++ != ':')
70 			return false;
71 	}
72 
73 	/* return true if at end of string */
74 	return *s == '\0';
75 }
76 
77 /* Convert 0011:2233:4455 to ethernet address */
78 static bool get_ether_addr3(const char *s, struct rte_ether_addr *ea)
79 {
80 	int i, j;
81 
82 	for (i = 0; i < RTE_ETHER_ADDR_LEN; i += 2) {
83 		uint16_t w = 0;
84 
85 		for (j = 0; j < 4; j++) {
86 			int8_t x;
87 
88 			x = get_xdigit(*s++);
89 			if (x < 0)
90 				return false;
91 			w = (w << 4) | x;
92 		}
93 		ea->addr_bytes[i] = w >> 8;
94 		ea->addr_bytes[i + 1] = w & 0xff;
95 
96 		if (i < RTE_ETHER_ADDR_LEN - 2 &&
97 		    *s++ != ':')
98 			return false;
99 	}
100 
101 	return *s == '\0';
102 }
103 
104 /*
105  * Like ether_aton_r but can handle either
106  * XX:XX:XX:XX:XX:XX or XXXX:XXXX:XXXX
107  * and is more restrictive.
108  */
109 int
110 rte_ether_unformat_addr(const char *s, struct rte_ether_addr *ea)
111 {
112 	if (get_ether_addr6(s, ea))
113 		return 0;
114 	if (get_ether_addr3(s, ea))
115 		return 0;
116 
117 	rte_errno = EINVAL;
118 	return -1;
119 }
120