back to topotato report
topotato coverage report
Current view: top level - lib - ntop.c (source / functions) Hit Total Coverage
Test: test_bgp_minimum_holdtime.py::TestBGPMinimumHoldtime Lines: 75 80 93.8 %
Date: 2023-02-24 18:37:25 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * optimized ntop, about 10x faster than libc versions [as of 2019]
       3             :  *
       4             :  * Copyright (c) 2019  David Lamparter, for NetDEF, Inc.
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #ifdef HAVE_CONFIG_H
      20             : #include "config.h"
      21             : #endif
      22             : 
      23             : #include <stdio.h>
      24             : #include <stdint.h>
      25             : #include <stdbool.h>
      26             : #include <string.h>
      27             : #include <sys/socket.h>
      28             : #include <netinet/in.h>
      29             : #include <arpa/inet.h>
      30             : 
      31             : #include "compiler.h"
      32             : 
      33             : #define pos (*posx)
      34             : 
      35             : static inline void putbyte(uint8_t bytex, char **posx)
      36             :         __attribute__((always_inline)) OPTIMIZE;
      37             : 
      38         260 : static inline void putbyte(uint8_t bytex, char **posx)
      39             : {
      40         260 :         bool zero = false;
      41         260 :         int byte = bytex, tmp, a, b;
      42             : 
      43         260 :         tmp = byte - 200;
      44         260 :         if (tmp >= 0) {
      45          52 :                 *pos++ = '2';
      46          52 :                 zero = true;
      47          52 :                 byte = tmp;
      48             :         } else {
      49         208 :                 tmp = byte - 100;
      50         208 :                 if (tmp >= 0) {
      51          62 :                         *pos++ = '1';
      52          62 :                         zero = true;
      53          62 :                         byte = tmp;
      54             :                 }
      55             :         }
      56             : 
      57             :         /* make sure the compiler knows the value range of "byte" */
      58         260 :         assume(byte < 100 && byte >= 0);
      59             : 
      60         260 :         b = byte % 10;
      61         260 :         a = byte / 10;
      62         260 :         if (a || zero) {
      63         135 :                 *pos++ = '0' + a;
      64         135 :                 *pos++ = '0' + b;
      65             :         } else
      66         125 :                 *pos++ = '0' + b;
      67             : }
      68             : 
      69             : static inline void puthex(uint16_t word, char **posx)
      70             :         __attribute__((always_inline)) OPTIMIZE;
      71             : 
      72          85 : static inline void puthex(uint16_t word, char **posx)
      73             : {
      74          85 :         const char *digits = "0123456789abcdef";
      75          85 :         if (word >= 0x1000)
      76          47 :                 *pos++ = digits[(word >> 12) & 0xf];
      77          85 :         if (word >= 0x100)
      78          49 :                 *pos++ = digits[(word >> 8) & 0xf];
      79          85 :         if (word >= 0x10)
      80          51 :                 *pos++ = digits[(word >> 4) & 0xf];
      81          85 :         *pos++ = digits[word & 0xf];
      82             : }
      83             : 
      84             : #undef pos
      85             : 
      86             : const char *frr_inet_ntop(int af, const void * restrict src,
      87             :                           char * restrict dst, socklen_t size)
      88             :         __attribute__((flatten)) OPTIMIZE;
      89             : 
      90         112 : const char *frr_inet_ntop(int af, const void * restrict src,
      91             :                           char * restrict dst, socklen_t size)
      92             : {
      93         112 :         const uint8_t *b = src;
      94             :         /* 8 * "abcd:" for IPv6
      95             :          * note: the IPv4-embedded IPv6 syntax is only used for ::A.B.C.D,
      96             :          * which isn't longer than 40 chars either.  even with ::ffff:A.B.C.D
      97             :          * it's shorter.
      98             :          */
      99         112 :         char buf[8 * 5], *o = buf;
     100         112 :         size_t best = 0, bestlen = 0, curlen = 0, i;
     101             : 
     102         112 :         switch (af) {
     103             :         case AF_INET:
     104          65 : inet4:
     105          65 :                 putbyte(b[0], &o);
     106          65 :                 *o++ = '.';
     107          65 :                 putbyte(b[1], &o);
     108          65 :                 *o++ = '.';
     109          65 :                 putbyte(b[2], &o);
     110          65 :                 *o++ = '.';
     111          65 :                 putbyte(b[3], &o);
     112          65 :                 *o++ = '\0';
     113          65 :                 break;
     114             :         case AF_INET6:
     115         423 :                 for (i = 0; i < 8; i++) {
     116         376 :                         if (b[i * 2] || b[i * 2 + 1]) {
     117          85 :                                 if (curlen && curlen > bestlen) {
     118          14 :                                         best = i - curlen;
     119          14 :                                         bestlen = curlen;
     120             :                                 }
     121          85 :                                 curlen = 0;
     122          85 :                                 continue;
     123             :                         }
     124         291 :                         curlen++;
     125             :                 }
     126          47 :                 if (curlen && curlen > bestlen) {
     127          33 :                         best = i - curlen;
     128          33 :                         bestlen = curlen;
     129             :                 }
     130             :                 /* do we want ::ffff:A.B.C.D? */
     131          47 :                 if (best == 0 && bestlen == 6) {
     132           0 :                         *o++ = ':';
     133           0 :                         *o++ = ':';
     134           0 :                         b += 12;
     135           0 :                         goto inet4;
     136             :                 }
     137          47 :                 if (bestlen == 1)
     138           0 :                         bestlen = 0;
     139             : 
     140         423 :                 for (i = 0; i < 8; i++) {
     141         376 :                         if (bestlen && i == best) {
     142          47 :                                 if (i == 0)
     143           4 :                                         *o++ = ':';
     144          47 :                                 *o++ = ':';
     145          47 :                                 continue;
     146             :                         }
     147         329 :                         if (i > best && i < best + bestlen) {
     148         244 :                                 continue;
     149             :                         }
     150          85 :                         puthex((b[i * 2] << 8) | b[i * 2 + 1], &o);
     151             : 
     152          85 :                         if (i < 7)
     153          71 :                                 *o++ = ':';
     154             :                 }
     155          47 :                 *o++ = '\0';
     156          47 :                 break;
     157             :         default:
     158             :                 return NULL;
     159             :         }
     160             : 
     161         112 :         i = o - buf;
     162         112 :         if (i > size)
     163             :                 return NULL;
     164             :         /* compiler might inline memcpy if it knows the length is short,
     165             :          * although neither gcc nor clang actually do this currently [2019]
     166             :          */
     167         112 :         assume(i <= 8 * 5);
     168         112 :         memcpy(dst, buf, i);
     169         112 :         return dst;
     170             : }
     171             : 
     172             : #if !defined(INET_NTOP_NO_OVERRIDE) && !defined(__APPLE__)
     173             : /* we want to override libc inet_ntop, but make sure it shows up in backtraces
     174             :  * as frr_inet_ntop (to avoid confusion while debugging)
     175             :  */
     176             : const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
     177             :         __attribute__((alias ("frr_inet_ntop")));
     178             : #endif

Generated by: LCOV version v1.16-topotato