]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Lib: Optimized printing of IP addresses
authorOndrej Zajicek <santiago@crfreenet.org>
Fri, 8 Nov 2024 17:51:54 +0000 (18:51 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Fri, 8 Nov 2024 17:51:54 +0000 (18:51 +0100)
Makes printing network prefixes ~15x faster.

lib/ip.c
lib/ip.h
lib/net.c

index 4b28451ce85ee791ec9ac465b1ff696a488d0d3f..e62f9f533a21cfef30b04a367d32ed3b61c9479d 100644 (file)
--- a/lib/ip.c
+++ b/lib/ip.c
@@ -205,20 +205,88 @@ ip6_shift_right(ip6_addr a, uint bits)
 }
 
 
-/*
- *  Conversion of IPv6 address to presentation format and vice versa.
- *  Heavily inspired by routines written by Paul Vixie for the BIND project
- *  and of course by RFC 2373.
- */
-
+static const char numbers[] = {
+  '0',   0,   0, 0,  '1',   0,   0, 0,  '2',   0,   0, 0,  '3',   0,   0, 0,  '4',   0,   0, 0,  '5',   0,   0, 0,  '6',   0,   0, 0,  '7',   0,   0, 0,
+  '8',   0,   0, 0,  '9',   0,   0, 0,  '1', '0',   0, 0,  '1', '1',   0, 0,  '1', '2',   0, 0,  '1', '3',   0, 0,  '1', '4',   0, 0,  '1', '5',   0, 0,
+  '1', '6',   0, 0,  '1', '7',   0, 0,  '1', '8',   0, 0,  '1', '9',   0, 0,  '2', '0',   0, 0,  '2', '1',   0, 0,  '2', '2',   0, 0,  '2', '3',   0, 0,
+  '2', '4',   0, 0,  '2', '5',   0, 0,  '2', '6',   0, 0,  '2', '7',   0, 0,  '2', '8',   0, 0,  '2', '9',   0, 0,  '3', '0',   0, 0,  '3', '1',   0, 0,
+  '3', '2',   0, 0,  '3', '3',   0, 0,  '3', '4',   0, 0,  '3', '5',   0, 0,  '3', '6',   0, 0,  '3', '7',   0, 0,  '3', '8',   0, 0,  '3', '9',   0, 0,
+  '4', '0',   0, 0,  '4', '1',   0, 0,  '4', '2',   0, 0,  '4', '3',   0, 0,  '4', '4',   0, 0,  '4', '5',   0, 0,  '4', '6',   0, 0,  '4', '7',   0, 0,
+  '4', '8',   0, 0,  '4', '9',   0, 0,  '5', '0',   0, 0,  '5', '1',   0, 0,  '5', '2',   0, 0,  '5', '3',   0, 0,  '5', '4',   0, 0,  '5', '5',   0, 0,
+  '5', '6',   0, 0,  '5', '7',   0, 0,  '5', '8',   0, 0,  '5', '9',   0, 0,  '6', '0',   0, 0,  '6', '1',   0, 0,  '6', '2',   0, 0,  '6', '3',   0, 0,
+  '6', '4',   0, 0,  '6', '5',   0, 0,  '6', '6',   0, 0,  '6', '7',   0, 0,  '6', '8',   0, 0,  '6', '9',   0, 0,  '7', '0',   0, 0,  '7', '1',   0, 0,
+  '7', '2',   0, 0,  '7', '3',   0, 0,  '7', '4',   0, 0,  '7', '5',   0, 0,  '7', '6',   0, 0,  '7', '7',   0, 0,  '7', '8',   0, 0,  '7', '9',   0, 0,
+  '8', '0',   0, 0,  '8', '1',   0, 0,  '8', '2',   0, 0,  '8', '3',   0, 0,  '8', '4',   0, 0,  '8', '5',   0, 0,  '8', '6',   0, 0,  '8', '7',   0, 0,
+  '8', '8',   0, 0,  '8', '9',   0, 0,  '9', '0',   0, 0,  '9', '1',   0, 0,  '9', '2',   0, 0,  '9', '3',   0, 0,  '9', '4',   0, 0,  '9', '5',   0, 0,
+  '9', '6',   0, 0,  '9', '7',   0, 0,  '9', '8',   0, 0,  '9', '9',   0, 0,  '1', '0', '0', 0,  '1', '0', '1', 0,  '1', '0', '2', 0,  '1', '0', '3', 0,
+  '1', '0', '4', 0,  '1', '0', '5', 0,  '1', '0', '6', 0,  '1', '0', '7', 0,  '1', '0', '8', 0,  '1', '0', '9', 0,  '1', '1', '0', 0,  '1', '1', '1', 0,
+  '1', '1', '2', 0,  '1', '1', '3', 0,  '1', '1', '4', 0,  '1', '1', '5', 0,  '1', '1', '6', 0,  '1', '1', '7', 0,  '1', '1', '8', 0,  '1', '1', '9', 0,
+  '1', '2', '0', 0,  '1', '2', '1', 0,  '1', '2', '2', 0,  '1', '2', '3', 0,  '1', '2', '4', 0,  '1', '2', '5', 0,  '1', '2', '6', 0,  '1', '2', '7', 0,
+  '1', '2', '8', 0,  '1', '2', '9', 0,  '1', '3', '0', 0,  '1', '3', '1', 0,  '1', '3', '2', 0,  '1', '3', '3', 0,  '1', '3', '4', 0,  '1', '3', '5', 0,
+  '1', '3', '6', 0,  '1', '3', '7', 0,  '1', '3', '8', 0,  '1', '3', '9', 0,  '1', '4', '0', 0,  '1', '4', '1', 0,  '1', '4', '2', 0,  '1', '4', '3', 0,
+  '1', '4', '4', 0,  '1', '4', '5', 0,  '1', '4', '6', 0,  '1', '4', '7', 0,  '1', '4', '8', 0,  '1', '4', '9', 0,  '1', '5', '0', 0,  '1', '5', '1', 0,
+  '1', '5', '2', 0,  '1', '5', '3', 0,  '1', '5', '4', 0,  '1', '5', '5', 0,  '1', '5', '6', 0,  '1', '5', '7', 0,  '1', '5', '8', 0,  '1', '5', '9', 0,
+  '1', '6', '0', 0,  '1', '6', '1', 0,  '1', '6', '2', 0,  '1', '6', '3', 0,  '1', '6', '4', 0,  '1', '6', '5', 0,  '1', '6', '6', 0,  '1', '6', '7', 0,
+  '1', '6', '8', 0,  '1', '6', '9', 0,  '1', '7', '0', 0,  '1', '7', '1', 0,  '1', '7', '2', 0,  '1', '7', '3', 0,  '1', '7', '4', 0,  '1', '7', '5', 0,
+  '1', '7', '6', 0,  '1', '7', '7', 0,  '1', '7', '8', 0,  '1', '7', '9', 0,  '1', '8', '0', 0,  '1', '8', '1', 0,  '1', '8', '2', 0,  '1', '8', '3', 0,
+  '1', '8', '4', 0,  '1', '8', '5', 0,  '1', '8', '6', 0,  '1', '8', '7', 0,  '1', '8', '8', 0,  '1', '8', '9', 0,  '1', '9', '0', 0,  '1', '9', '1', 0,
+  '1', '9', '2', 0,  '1', '9', '3', 0,  '1', '9', '4', 0,  '1', '9', '5', 0,  '1', '9', '6', 0,  '1', '9', '7', 0,  '1', '9', '8', 0,  '1', '9', '9', 0,
+  '2', '0', '0', 0,  '2', '0', '1', 0,  '2', '0', '2', 0,  '2', '0', '3', 0,  '2', '0', '4', 0,  '2', '0', '5', 0,  '2', '0', '6', 0,  '2', '0', '7', 0,
+  '2', '0', '8', 0,  '2', '0', '9', 0,  '2', '1', '0', 0,  '2', '1', '1', 0,  '2', '1', '2', 0,  '2', '1', '3', 0,  '2', '1', '4', 0,  '2', '1', '5', 0,
+  '2', '1', '6', 0,  '2', '1', '7', 0,  '2', '1', '8', 0,  '2', '1', '9', 0,  '2', '2', '0', 0,  '2', '2', '1', 0,  '2', '2', '2', 0,  '2', '2', '3', 0,
+  '2', '2', '4', 0,  '2', '2', '5', 0,  '2', '2', '6', 0,  '2', '2', '7', 0,  '2', '2', '8', 0,  '2', '2', '9', 0,  '2', '3', '0', 0,  '2', '3', '1', 0,
+  '2', '3', '2', 0,  '2', '3', '3', 0,  '2', '3', '4', 0,  '2', '3', '5', 0,  '2', '3', '6', 0,  '2', '3', '7', 0,  '2', '3', '8', 0,  '2', '3', '9', 0,
+  '2', '4', '0', 0,  '2', '4', '1', 0,  '2', '4', '2', 0,  '2', '4', '3', 0,  '2', '4', '4', 0,  '2', '4', '5', 0,  '2', '4', '6', 0,  '2', '4', '7', 0,
+  '2', '4', '8', 0,  '2', '4', '9', 0,  '2', '5', '0', 0,  '2', '5', '1', 0,  '2', '5', '2', 0,  '2', '5', '3', 0,  '2', '5', '4', 0,  '2', '5', '5', 0,
+};
+
+static inline char *
+print_u8(char *s, u8 n)
+{
+  memcpy(s, numbers + n * 4, 4);
+  return s + 1 + (n >= 10) + (n >= 100);
+}
 
 char *
 ip4_ntop(ip4_addr a, char *b)
 {
   u32 x = _I(a);
-  return b + bsprintf(b, "%d.%d.%d.%d", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff);
+
+  b = print_u8(b, (x >> 24) & 0xff);
+  *b++ = '.';
+  b = print_u8(b, (x >> 16) & 0xff);
+  *b++ = '.';
+  b = print_u8(b, (x >> 8) & 0xff);
+  *b++ = '.';
+  b = print_u8(b, x & 0xff);
+
+  return b;
 }
 
+char *
+ip4_px_ntop(ip4_addr a, int len, char *b)
+{
+  u32 x = _I(a);
+
+  b = print_u8(b, (x >> 24) & 0xff);
+  *b++ = '.';
+  b = print_u8(b, (x >> 16) & 0xff);
+  *b++ = '.';
+  b = print_u8(b, (x >> 8) & 0xff);
+  *b++ = '.';
+  b = print_u8(b, x & 0xff);
+  *b++ = '/';
+  b = print_u8(b, len & 0xff);
+
+  return b;
+}
+
+
+/*
+ *  Conversion of IPv6 address to presentation format and vice versa.
+ *  Heavily inspired by routines written by Paul Vixie for the BIND project
+ *  and of course by RFC 2373.
+ */
 
 char *
 ip6_ntop(ip6_addr a, char *b)
index 49f28079cb3955dd7984d1d1dfbda69c02840f0b..661331ec2b99ac042857f004600e1638150d465a 100644 (file)
--- a/lib/ip.h
+++ b/lib/ip.h
@@ -457,9 +457,14 @@ static inline void * put_ip6(void *buf, ip6_addr a)
  *     Binary/text form conversions
  */
 
+#define IP4_BUFFER_SIZE                16      /* Required buffer for ip4_ntop() */
+#define IP4_PX_BUFFER_SIZE     20      /* Required buffer for ip4_ntop_px() */
+
 char *ip4_ntop(ip4_addr a, char *b);
 char *ip6_ntop(ip6_addr a, char *b);
 
+char *ip4_px_ntop(ip4_addr a, int len, char *b);
+
 static inline char * ip4_ntox(ip4_addr a, char *b)
 { return b + bsprintf(b, "%08x", _I(a)); }
 
index 76bb3e806c101c22512e6191999831ee6e581af5..3bd7bc6712cf07dabdc1189794f551461844b31a 100644 (file)
--- a/lib/net.c
+++ b/lib/net.c
@@ -100,7 +100,7 @@ net_format(const net_addr *N, char *buf, int buflen)
   switch (n->n.type)
   {
   case NET_IP4:
-    return bsnprintf(buf, buflen, "%I4/%d", n->ip4.prefix, n->ip4.pxlen);
+    return (buflen < IP4_PX_BUFFER_SIZE) ? -1 : ip4_px_ntop(n->ip4.prefix, n->ip4.pxlen, buf) - buf;
   case NET_IP6:
     return bsnprintf(buf, buflen, "%I6/%d", n->ip6.prefix, n->ip6.pxlen);
   case NET_VPN4: