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