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