LCOV - code coverage report
Current view: top level - lib/net - rte_ether.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 53 53 100.0 %
Date: 2025-05-01 17:49:45 Functions: 6 6 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 45 49 91.8 %

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

Generated by: LCOV version 1.14