Branch data Line data Source code
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 : 2000007 : rte_eth_random_addr(uint8_t *addr) 12 : : { 13 [ - + ]: 2000007 : uint64_t rand = rte_rand(); 14 : : uint8_t *p = (uint8_t *)&rand; 15 : : 16 : : rte_memcpy(addr, p, RTE_ETHER_ADDR_LEN); 17 : 2000007 : addr[0] &= (uint8_t)~RTE_ETHER_GROUP_ADDR; /* clear multicast bit */ 18 : 2000007 : addr[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR; /* set local assignment bit */ 19 : 2000007 : } 20 : : 21 : : void 22 : 1000000 : rte_ether_format_addr(char *buf, uint16_t size, 23 : : const struct rte_ether_addr *eth_addr) 24 : : { 25 : 1000000 : snprintf(buf, size, RTE_ETHER_ADDR_PRT_FMT, 26 : 1000000 : RTE_ETHER_ADDR_BYTES(eth_addr)); 27 : 1000000 : } 28 : : 29 : : static int8_t get_xdigit(char ch) 30 : : { 31 : 12000242 : if (ch >= '0' && ch <= '9') 32 : 7375867 : return ch - '0'; 33 [ - + + + : 4624375 : if (ch >= 'a' && ch <= 'f') + + ] 34 : 4 : return ch - 'a' + 10; 35 [ + + + + : 4624371 : if (ch >= 'A' && ch <= 'F') + - ] 36 : 4624364 : return ch - 'A' + 10; 37 : : return -1; 38 : : } 39 : : 40 : : /* Convert 00:11:22:33:44:55 to ethernet address */ 41 : 1000020 : static bool get_ether_addr6(const char *s0, struct rte_ether_addr *ea, 42 : : const char sep) 43 : : { 44 : : const char *s = s0; 45 : : int i; 46 : : 47 [ + + ]: 7000127 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { 48 : : int8_t x; 49 : : 50 [ + + ]: 6000110 : x = get_xdigit(*s++); 51 : : if (x < 0) 52 : : return false; /* not a hex digit */ 53 : : 54 : 6000108 : ea->addr_bytes[i] = x; 55 [ + + + + ]: 6000108 : if (*s != sep && *s != '\0') { 56 [ + + ]: 6000096 : x = get_xdigit(*s++); 57 : : if (x < 0) 58 : : return false; /* not a hex digit */ 59 : 6000096 : ea->addr_bytes[i] <<= 4; 60 : 6000096 : ea->addr_bytes[i] |= x; 61 : : } 62 : : 63 [ + + ]: 6000108 : if (i < RTE_ETHER_ADDR_LEN - 1 && 64 [ + + ]: 5000091 : *s++ != sep) 65 : : return false; /* premature end of string */ 66 : : } 67 : : 68 : : /* return true if no trailing characters */ 69 : 1000017 : return *s == '\0'; 70 : : } 71 : : 72 : : /* Convert 0011:2233:4455 to ethernet address */ 73 : 7 : static bool get_ether_addr3(const char *s, struct rte_ether_addr *ea, 74 : : const char sep) 75 : : { 76 : : int i, j; 77 : : 78 [ + + ]: 13 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i += 2) { 79 : : uint16_t w = 0; 80 : : 81 [ + + ]: 42 : for (j = 0; j < 4; j++) { 82 : : int8_t x; 83 : : 84 [ + + ]: 36 : x = get_xdigit(*s++); 85 : : if (x < 0) 86 : : return false; /* not a hex digit */ 87 : 31 : w = (w << 4) | x; 88 : : } 89 : : 90 : 6 : ea->addr_bytes[i] = w >> 8; 91 : 6 : ea->addr_bytes[i + 1] = w & 0xff; 92 : : 93 [ + + ]: 6 : if (i < RTE_ETHER_ADDR_LEN - 2 && 94 [ + - ]: 4 : *s++ != sep) 95 : : return false; 96 : : } 97 : : 98 : 2 : return *s == '\0'; 99 : : } 100 : : 101 : : /* 102 : : * Scan input to see if separated by dash, colon or period 103 : : * Returns separator and number of matches 104 : : * If separators are mixed will return 105 : : */ 106 : 1000045 : static unsigned int get_ether_sep(const char *s, char *sep) 107 : : { 108 : : static const char separators[] = "-:."; 109 : : unsigned int count = 0; 110 : : const char *cp; 111 : : 112 : 1000045 : cp = strpbrk(s, separators); 113 [ + + ]: 1000045 : if (cp == NULL) 114 : : return 0; /* no separator found */ 115 : : 116 : 1000038 : *sep = *cp; /* return the separator */ 117 : : do { 118 : 5000153 : ++count; 119 : : /* find next instance of separator */ 120 : 5000153 : cp = strchr(cp + 1, *sep); 121 [ + + ]: 5000153 : } while (cp != NULL); 122 : : 123 : : return count; 124 : : } 125 : : 126 : : /* 127 : : * Be liberal in accepting a wide variety of notational formats 128 : : * for MAC address including: 129 : : * - Linux format six groups of hexadecimal digits separated by colon 130 : : * - Windows format six groups separated by hyphen 131 : : * - two groups hexadecimal digits 132 : : */ 133 : : int 134 : 1000045 : rte_ether_unformat_addr(const char *s, struct rte_ether_addr *ea) 135 : : { 136 : : unsigned int count; 137 : 1000045 : char sep = '\0'; 138 : : 139 : 1000045 : count = get_ether_sep(s, &sep); 140 [ + + + ]: 1000045 : switch (count) { 141 : 1000020 : case 5: /* i.e 01:23:45:67:89:AB */ 142 [ + + ]: 1000020 : if (get_ether_addr6(s, ea, sep)) 143 : : return 0; 144 : : break; 145 : 7 : case 2: /* i.e 0123.4567.89AB */ 146 [ + + ]: 7 : if (get_ether_addr3(s, ea, sep)) 147 : : return 0; 148 : : break; 149 : : default: 150 : : break; 151 : : } 152 : : 153 : 26 : rte_errno = EINVAL; 154 : 26 : return -1; 155 : : }