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-02-01 18:54:23 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 <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                 :            : }

Generated by: LCOV version 1.14