LCOV - code coverage report
Current view: top level - vnet/ip - ip_types.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 195 288 67.7 %
Date: 2023-10-26 01:39:38 Functions: 30 38 78.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vnet/ip/ip_types.h>
      17             : #include <vnet/ip/format.h>
      18             : #include <vnet/ip/ip.h>
      19             : 
      20             : u8 *
      21       32931 : format_ip_address (u8 * s, va_list * args)
      22             : {
      23       32931 :   ip_address_t *a = va_arg (*args, ip_address_t *);
      24       32931 :   u8 ver = ip_addr_version (a);
      25       32931 :   if (ver == AF_IP4)
      26             :     {
      27       18622 :       return format (s, "%U", format_ip4_address, &ip_addr_v4 (a));
      28             :     }
      29       14309 :   else if (ver == AF_IP6)
      30             :     {
      31       14309 :       return format (s, "%U", format_ip6_address, &ip_addr_v6 (a));
      32             :     }
      33             :   else
      34             :     {
      35           0 :       clib_warning ("Can't format IP version %d!", ver);
      36           0 :       return 0;
      37             :     }
      38             : }
      39             : 
      40             : uword
      41           5 : unformat_ip_address (unformat_input_t * input, va_list * args)
      42             : {
      43           5 :   ip_address_t *a = va_arg (*args, ip_address_t *);
      44           5 :   ip_address_t tmp, *p_tmp = &tmp;
      45             : 
      46           5 :   clib_memset (p_tmp, 0, sizeof (*p_tmp));
      47           5 :   if (unformat (input, "%U", unformat_ip4_address, &ip_addr_v4 (p_tmp)))
      48           5 :     ip_addr_version (p_tmp) = AF_IP4;
      49           0 :   else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6 (p_tmp)))
      50           0 :     ip_addr_version (p_tmp) = AF_IP6;
      51             :   else
      52           0 :     return 0;
      53           5 :   *a = *p_tmp;
      54           5 :   return 1;
      55             : }
      56             : 
      57             : u8 *
      58           0 : format_ip_prefix (u8 * s, va_list * args)
      59             : {
      60           0 :   ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
      61           0 :   return format (s, "%U/%d", format_ip_address, &ip_prefix_addr (a),
      62           0 :                  ip_prefix_len (a));
      63             : }
      64             : 
      65             : uword
      66           0 : unformat_ip_prefix (unformat_input_t * input, va_list * args)
      67             : {
      68           0 :   ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
      69             :   /* %d writes more than a u8 */
      70             :   int plen;
      71           0 :   if (unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr (a),
      72             :                 &plen))
      73             :     {
      74           0 :       ip_prefix_len (a) = plen;
      75           0 :       if ((ip_prefix_version (a) == AF_IP4 && 32 < ip_prefix_len (a)) ||
      76           0 :           (ip_prefix_version (a) == AF_IP6 && 128 < ip_prefix_len (a)))
      77             :         {
      78           0 :           clib_warning ("Prefix length to big: %d!", ip_prefix_len (a));
      79           0 :           return 0;
      80             :         }
      81           0 :       ip_prefix_normalize (a);
      82             :     }
      83             :   else
      84           0 :     return 0;
      85           0 :   return 1;
      86             : }
      87             : 
      88             : u16
      89         666 : ip_address_size (const ip_address_t * a)
      90             : {
      91         666 :   switch (ip_addr_version (a))
      92             :     {
      93         644 :     case AF_IP4:
      94         644 :       return sizeof (ip4_address_t);
      95             :       break;
      96          22 :     case AF_IP6:
      97          22 :       return sizeof (ip6_address_t);
      98             :       break;
      99             :     }
     100           0 :   return 0;
     101             : }
     102             : 
     103             : bool
     104      255871 : ip_address_is_zero (const ip_address_t * ip)
     105             : {
     106      255871 :   switch (ip_addr_version (ip))
     107             :     {
     108      255534 :     case AF_IP4:
     109      255534 :       return (ip_addr_v4 (ip).as_u32 == 0);
     110         337 :     case AF_IP6:
     111         385 :       return (ip_addr_v6 (ip).as_u64[0] == 0 &&
     112          48 :               ip_addr_v6 (ip).as_u64[1] == 0);
     113             :       break;
     114             :     }
     115           0 :   return false;
     116             : }
     117             : 
     118             : int
     119      121370 : ip_address_cmp (const ip_address_t * ip1, const ip_address_t * ip2)
     120             : {
     121      121370 :   int res = 0;
     122      121370 :   if (ip_addr_version (ip1) != ip_addr_version (ip2))
     123       20780 :     return -1;
     124      100590 :   res = ip46_address_cmp (&ip_addr_46 (ip1), &ip_addr_46 (ip2));
     125             : 
     126      100590 :   if (res < 0)
     127       97324 :     res = 2;
     128        3266 :   else if (res > 0)
     129        3176 :     res = 1;
     130             : 
     131      100590 :   return res;
     132             : }
     133             : 
     134             : void
     135       14600 : ip_address_copy (ip_address_t * dst, const ip_address_t * src)
     136             : {
     137       14600 :   if (AF_IP4 == ip_addr_version (src))
     138             :     {
     139             :       /* don't copy any garbage from the union */
     140       11177 :       clib_memset (dst, 0, sizeof (*dst));
     141       11177 :       ip_addr_v4 (dst) = ip_addr_v4 (src);
     142       11177 :       dst->version = AF_IP4;
     143             :     }
     144             :   else
     145             :     {
     146        3423 :       clib_memcpy (dst, src, sizeof (ip_address_t));
     147             :     }
     148       14600 : }
     149             : 
     150             : u8 *
     151          78 : ip_addr_bytes (ip_address_t * ip)
     152             : {
     153          78 :   switch (ip->version)
     154             :     {
     155          76 :     case AF_IP4:
     156          76 :       return (u8 *) & ip_addr_v4 (ip);
     157           2 :     case AF_IP6:
     158           2 :       return (u8 *) & ip_addr_v6 (ip);
     159             :       break;
     160             :     }
     161           0 :   ASSERT (0);
     162           0 :   return (NULL);
     163             : }
     164             : 
     165             : void
     166         222 : ip_address_copy_addr (void *dst, const ip_address_t * src)
     167             : {
     168         222 :   switch (src->version)
     169             :     {
     170         214 :     case AF_IP4:
     171         214 :       clib_memcpy (dst, &ip_addr_v4 (src), ip_address_size (src));
     172         214 :       break;
     173           8 :     case AF_IP6:
     174           8 :       clib_memcpy (dst, &ip_addr_v6 (src), ip_address_size (src));
     175           8 :       break;
     176             :     }
     177         222 : }
     178             : 
     179             : u16
     180           0 : ip_version_to_size (ip_address_family_t af)
     181             : {
     182           0 :   switch (af)
     183             :     {
     184           0 :     case AF_IP4:
     185           0 :       return sizeof (ip4_address_t);
     186             :       break;
     187           0 :     case AF_IP6:
     188           0 :       return sizeof (ip6_address_t);
     189             :       break;
     190             :     }
     191           0 :   return 0;
     192             : }
     193             : 
     194             : vnet_link_t
     195           0 : ip_address_family_to_link_type (ip_address_family_t af)
     196             : {
     197           0 :   switch (af)
     198             :     {
     199           0 :     case AF_IP4:
     200           0 :       return (VNET_LINK_IP4);
     201           0 :     case AF_IP6:
     202           0 :       return (VNET_LINK_IP6);
     203             :     }
     204           0 :   ASSERT (0);
     205           0 :   return (VNET_LINK_IP4);
     206             : }
     207             : 
     208             : void
     209        9657 : ip_address_set (ip_address_t *dst, const void *src, ip_address_family_t af)
     210             : {
     211        9657 :   ip_addr_version (dst) = af;
     212             : 
     213        9657 :   switch (af)
     214             :     {
     215        5524 :     case AF_IP4:
     216        5524 :       ip_addr_v4 (dst) = *(ip4_address_t *) src;
     217        5524 :       break;
     218        4133 :     case AF_IP6:
     219        4133 :       ip_addr_v6 (dst) = *(ip6_address_t *) src;
     220        4133 :       break;
     221             :     }
     222        9657 : }
     223             : 
     224             : fib_protocol_t
     225       52768 : ip_address_family_to_fib_proto (ip_address_family_t af)
     226             : {
     227       52768 :   switch (af)
     228             :     {
     229       28875 :     case AF_IP4:
     230       28875 :       return (FIB_PROTOCOL_IP4);
     231       23893 :     case AF_IP6:
     232       23893 :       return (FIB_PROTOCOL_IP6);
     233             :     }
     234           0 :   ASSERT (0);
     235           0 :   return (FIB_PROTOCOL_IP4);
     236             : }
     237             : 
     238             : ip_address_family_t
     239       11093 : ip_address_family_from_fib_proto (fib_protocol_t fp)
     240             : {
     241       11093 :   switch (fp)
     242             :     {
     243        6549 :     case FIB_PROTOCOL_IP4:
     244        6549 :       return (AF_IP4);
     245        4544 :     case FIB_PROTOCOL_IP6:
     246        4544 :       return (AF_IP6);
     247           0 :     case FIB_PROTOCOL_MPLS:
     248           0 :       ASSERT (0);
     249             :     }
     250           0 :   return (AF_IP4);
     251             : }
     252             : 
     253             : fib_protocol_t
     254         461 : ip_address_to_46 (const ip_address_t * addr, ip46_address_t * a)
     255             : {
     256         461 :   *a = ip_addr_46 (addr);
     257         461 :   return (ip_address_family_to_fib_proto (ip_addr_version (addr)));
     258             : }
     259             : 
     260             : void
     261       10854 : ip_address_from_46 (const ip46_address_t * nh,
     262             :                     fib_protocol_t fproto, ip_address_t * ip)
     263             : {
     264       10854 :   ip_addr_46 (ip) = *nh;
     265       10854 :   ip_addr_version (ip) = ip_address_family_from_fib_proto (fproto);
     266       10854 : }
     267             : 
     268             : /**
     269             :  * convert from a IP address to a FIB prefix
     270             :  */
     271             : void
     272        3835 : ip_address_to_fib_prefix (const ip_address_t * addr, fib_prefix_t * prefix)
     273             : {
     274        3835 :   if (addr->version == AF_IP4)
     275             :     {
     276        2037 :       prefix->fp_len = 32;
     277        2037 :       prefix->fp_proto = FIB_PROTOCOL_IP4;
     278        2037 :       clib_memset (&prefix->fp_addr.pad, 0, sizeof (prefix->fp_addr.pad));
     279        2037 :       memcpy (&prefix->fp_addr.ip4, &addr->ip.ip4,
     280             :               sizeof (prefix->fp_addr.ip4));
     281             :     }
     282             :   else
     283             :     {
     284        1798 :       prefix->fp_len = 128;
     285        1798 :       prefix->fp_proto = FIB_PROTOCOL_IP6;
     286        1798 :       memcpy (&prefix->fp_addr.ip6, &addr->ip.ip6,
     287             :               sizeof (prefix->fp_addr.ip6));
     288             :     }
     289        3835 :   prefix->___fp___pad = 0;
     290        3835 : }
     291             : 
     292             : void
     293           0 : ip_address_to_prefix (const ip_address_t *addr, ip_prefix_t *prefix)
     294             : {
     295           0 :   prefix->len = (addr->version == AF_IP4 ? 32 : 128);
     296           0 :   clib_memcpy (&prefix->addr, addr, sizeof (prefix->addr));
     297           0 : }
     298             : 
     299             : void
     300           5 : ip_address_increment (ip_address_t * ip)
     301             : {
     302           5 :   ip46_address_increment ((ip_addr_version (ip) == AF_IP4 ?
     303             :                            IP46_TYPE_IP4 : IP46_TYPE_IP6), &ip_addr_46 (ip));
     304           5 : }
     305             : 
     306             : void
     307       15098 : ip_address_reset (ip_address_t * ip)
     308             : {
     309       15098 :   clib_memset (ip, 0, sizeof (*ip));
     310       15098 : }
     311             : 
     312             : static void
     313          12 : ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
     314             : {
     315          12 :   u32 mask = ~0;
     316             : 
     317          12 :   ASSERT (ip4);
     318             : 
     319          12 :   if (32 <= preflen)
     320             :     {
     321           5 :       return;
     322             :     }
     323             : 
     324           7 :   mask = pow2_mask (preflen) << (32 - preflen);
     325           7 :   mask = clib_host_to_net_u32 (mask);
     326           7 :   ip4->data_u32 &= mask;
     327             : }
     328             : 
     329             : static void
     330           0 : ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
     331             : {
     332             :   u8 mask_6[16];
     333             :   u32 *m;
     334             :   u8 j, i0, i1;
     335             : 
     336           0 :   ASSERT (ip6);
     337             : 
     338           0 :   clib_memset (mask_6, 0, sizeof (mask_6));
     339             : 
     340           0 :   if (128 <= preflen)
     341             :     {
     342           0 :       return;
     343             :     }
     344             : 
     345           0 :   i1 = preflen % 32;
     346           0 :   i0 = preflen / 32;
     347           0 :   m = (u32 *) & mask_6[0];
     348             : 
     349           0 :   for (j = 0; j < i0; j++)
     350             :     {
     351           0 :       m[j] = ~0;
     352             :     }
     353             : 
     354           0 :   if (i1)
     355             :     {
     356           0 :       m[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
     357             :     }
     358             : 
     359           0 :   for (j = 0; j < sizeof (mask_6); j++)
     360             :     {
     361           0 :       ip6->as_u8[j] &= mask_6[j];
     362             :     }
     363             : }
     364             : 
     365             : void
     366          12 : ip_prefix_normalize (ip_prefix_t * a)
     367             : {
     368          12 :   u8 preflen = ip_prefix_len (a);
     369             : 
     370          12 :   switch (ip_prefix_version (a))
     371             :     {
     372          12 :     case AF_IP4:
     373          12 :       ip_prefix_normalize_ip4 (&ip_prefix_v4 (a), preflen);
     374          12 :       break;
     375             : 
     376           0 :     case AF_IP6:
     377           0 :       ip_prefix_normalize_ip6 (&ip_prefix_v6 (a), preflen);
     378           0 :       break;
     379             : 
     380           0 :     default:
     381           0 :       ASSERT (0);
     382             :     }
     383          12 : }
     384             : 
     385             : void
     386          21 : ip_prefix_copy (void *dst, void *src)
     387             : {
     388          21 :   clib_memcpy (dst, src, sizeof (ip_prefix_t));
     389          21 : }
     390             : 
     391             : int
     392           1 : ip_prefix_cmp (const ip_prefix_t *ipp1, const ip_prefix_t *ipp2)
     393             : {
     394           1 :   ip_prefix_t p1 = *ipp1, p2 = *ipp2;
     395           1 :   int cmp = 0;
     396             : 
     397           1 :   ip_prefix_normalize (&p1);
     398           1 :   ip_prefix_normalize (&p2);
     399             : 
     400           1 :   cmp = ip_address_cmp (&ip_prefix_addr (&p1), &ip_prefix_addr (&p2));
     401           1 :   if (cmp == 0)
     402             :     {
     403           1 :       if (ip_prefix_len (&p1) < ip_prefix_len (&p2))
     404             :         {
     405           0 :           cmp = 1;
     406             :         }
     407             :       else
     408             :         {
     409           1 :           if (ip_prefix_len (&p1) > ip_prefix_len (&p2))
     410           0 :             cmp = 2;
     411             :         }
     412             :     }
     413           1 :   return cmp;
     414             : }
     415             : 
     416             : /**
     417             :  * convert from a LISP to a FIB prefix
     418             :  */
     419             : void
     420           2 : ip_prefix_to_fib_prefix (const ip_prefix_t * ip_prefix,
     421             :                          fib_prefix_t * fib_prefix)
     422             : {
     423           2 :   ip_address_to_fib_prefix (&ip_prefix->addr, fib_prefix);
     424           2 :   fib_prefix->fp_len = ip_prefix->len;
     425           2 : }
     426             : 
     427             : static bool
     428       16558 : ip4_prefix_validate (const ip_prefix_t * ip)
     429             : {
     430             :   ip4_address_t ip4_addr, ip4_mask;
     431             : 
     432       16558 :   if (ip_prefix_len (ip) > 32)
     433           0 :     return (false);
     434             : 
     435       16558 :   ip4_addr = ip_prefix_v4 (ip);
     436       16558 :   ip4_preflen_to_mask (ip_prefix_len (ip), &ip4_mask);
     437             : 
     438       16558 :   return ((ip4_addr.as_u32 & ip4_mask.as_u32) == ip4_addr.as_u32);
     439             : }
     440             : 
     441             : static bool
     442       16500 : ip6_prefix_validate (const ip_prefix_t * ip)
     443             : {
     444             :   ip6_address_t ip6_addr, ip6_mask;
     445             : 
     446       16500 :   if (ip_prefix_len (ip) > 128)
     447           0 :     return (false);
     448             : 
     449       16500 :   ip6_addr = ip_prefix_v6 (ip);
     450       16500 :   ip6_preflen_to_mask (ip_prefix_len (ip), &ip6_mask);
     451             : 
     452       33000 :   return (((ip6_addr.as_u64[0] & ip6_mask.as_u64[0]) == ip6_addr.as_u64[0]) &&
     453       16500 :           ((ip6_addr.as_u64[1] & ip6_mask.as_u64[1]) == ip6_addr.as_u64[1]));
     454             : }
     455             : 
     456             : bool
     457       33058 : ip_prefix_validate (const ip_prefix_t * ip)
     458             : {
     459       33058 :   switch (ip_prefix_version (ip))
     460             :     {
     461       16558 :     case AF_IP4:
     462       16558 :       return (ip4_prefix_validate (ip));
     463       16500 :     case AF_IP6:
     464       16500 :       return (ip6_prefix_validate (ip));
     465             :     }
     466           0 :   ASSERT (0);
     467           0 :   return (false);
     468             : }
     469             : 
     470             : void
     471       22352 : ip4_address_normalize (ip4_address_t * ip4, u8 preflen)
     472             : {
     473       22352 :   ASSERT (preflen <= 32);
     474       22352 :   if (preflen == 0)
     475       15400 :     ip4->data_u32 = 0;
     476             :   else
     477        6952 :     ip4->data_u32 &= clib_net_to_host_u32 (0xffffffff << (32 - preflen));
     478       22352 : }
     479             : 
     480             : void
     481        5923 : ip6_address_normalize (ip6_address_t * ip6, u8 preflen)
     482             : {
     483        5923 :   ASSERT (preflen <= 128);
     484        5923 :   if (preflen == 0)
     485             :     {
     486           0 :       ip6->as_u64[0] = 0;
     487           0 :       ip6->as_u64[1] = 0;
     488             :     }
     489        5923 :   else if (preflen <= 64)
     490             :     {
     491        5923 :       ip6->as_u64[0] &=
     492        5923 :         clib_host_to_net_u64 (0xffffffffffffffffL << (64 - preflen));
     493        5923 :       ip6->as_u64[1] = 0;
     494             :     }
     495             :   else
     496           0 :     ip6->as_u64[1] &=
     497           0 :       clib_host_to_net_u64 (0xffffffffffffffffL << (128 - preflen));
     498        5923 : }
     499             : 
     500             : void
     501       20292 : ip4_preflen_to_mask (u8 pref_len, ip4_address_t * ip)
     502             : {
     503       20292 :   if (pref_len == 0)
     504        3825 :     ip->as_u32 = 0;
     505             :   else
     506       16467 :     ip->as_u32 = clib_host_to_net_u32 (~((1 << (32 - pref_len)) - 1));
     507       20292 : }
     508             : 
     509             : u32
     510           0 : ip4_mask_to_preflen (ip4_address_t * mask)
     511             : {
     512           0 :   if (mask->as_u32 == 0)
     513           0 :     return 0;
     514           0 :   return (32 - log2_first_set (clib_net_to_host_u32 (mask->as_u32)));
     515             : }
     516             : 
     517             : void
     518        3734 : ip4_prefix_max_address_host_order (ip4_address_t * ip, u8 plen,
     519             :                                    ip4_address_t * res)
     520             : {
     521             :   u32 not_mask;
     522        3734 :   not_mask = (1 << (32 - plen)) - 1;
     523        3734 :   res->as_u32 = clib_net_to_host_u32 (ip->as_u32) + not_mask;
     524        3734 : }
     525             : 
     526             : void
     527       20150 : ip6_preflen_to_mask (u8 pref_len, ip6_address_t * mask)
     528             : {
     529       20150 :   if (pref_len == 0)
     530             :     {
     531        3752 :       mask->as_u64[0] = 0;
     532        3752 :       mask->as_u64[1] = 0;
     533             :     }
     534       16398 :   else if (pref_len <= 64)
     535             :     {
     536           4 :       mask->as_u64[0] =
     537           4 :         clib_host_to_net_u64 (0xffffffffffffffffL << (64 - pref_len));
     538           4 :       mask->as_u64[1] = 0;
     539             :     }
     540             :   else
     541             :     {
     542       16394 :       mask->as_u64[0] = 0xffffffffffffffffL;
     543       16394 :       mask->as_u64[1] =
     544       16394 :         clib_host_to_net_u64 (0xffffffffffffffffL << (128 - pref_len));
     545             :     }
     546       20150 : }
     547             : 
     548             : void
     549        3650 : ip6_prefix_max_address_host_order (ip6_address_t * ip, u8 plen,
     550             :                                    ip6_address_t * res)
     551             : {
     552             :   u64 not_mask;
     553        3650 :   if (plen == 0)
     554             :     {
     555        3650 :       res->as_u64[0] = 0xffffffffffffffffL;
     556        3650 :       res->as_u64[1] = 0xffffffffffffffffL;
     557             :     }
     558           0 :   else if (plen <= 64)
     559             :     {
     560           0 :       not_mask = ((u64) 1 << (64 - plen)) - 1;
     561           0 :       res->as_u64[0] = clib_net_to_host_u64 (ip->as_u64[0]) + not_mask;
     562           0 :       res->as_u64[1] = 0xffffffffffffffffL;
     563             :     }
     564             :   else
     565             :     {
     566           0 :       not_mask = ((u64) 1 << (128 - plen)) - 1;
     567           0 :       res->as_u64[1] = clib_net_to_host_u64 (ip->as_u64[1]) + not_mask;
     568             :     }
     569        3650 : }
     570             : 
     571             : u32
     572           0 : ip6_mask_to_preflen (ip6_address_t * mask)
     573             : {
     574           0 :   if (mask->as_u64[1] != 0)
     575           0 :     return 128 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[1]));
     576           0 :   if (mask->as_u64[0] != 0)
     577           0 :     return 64 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[0]));
     578           0 :   return 0;
     579             : }
     580             : 
     581             : /*
     582             :  * fd.io coding-style-patch-verification: ON
     583             :  *
     584             :  * Local Variables:
     585             :  * eval: (c-set-style "gnu")
     586             :  * End:
     587             :  */

Generated by: LCOV version 1.14