LCOV - code coverage report
Current view: top level - vnet/fib - fib_types.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 264 445 59.3 %
Date: 2023-10-26 01:39:38 Functions: 30 32 93.8 %

          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.h>
      17             : 
      18             : #include <vnet/fib/fib_types.h>
      19             : #include <vnet/fib/fib_internal.h>
      20             : #include <vnet/fib/fib_table.h>
      21             : #include <vnet/mfib/mfib_types.h>
      22             : #include <vnet/mpls/mpls.h>
      23             : 
      24             : /*
      25             :  * arrays of protocol and link names
      26             :  */
      27             : static const char* fib_protocol_names[] = FIB_PROTOCOLS;
      28             : static const char* vnet_link_names[] = VNET_LINKS;
      29             : static const char* fib_forw_chain_names[] = FIB_FORW_CHAINS;
      30             : static const char* fib_mpls_lsp_mode_names[] = FIB_MPLS_LSP_MODES;
      31             : 
      32             : u8 *
      33        4337 : format_fib_protocol (u8 * s, va_list * ap)
      34             : {
      35        4337 :     fib_protocol_t proto = va_arg(*ap, int); // fib_protocol_t promotion
      36             : 
      37        4337 :     return (format (s, "%s", fib_protocol_names[proto]));
      38             : }
      39             : 
      40             : u8 *
      41      392201 : format_vnet_link (u8 * s, va_list * ap)
      42             : {
      43      392201 :     vnet_link_t link = va_arg(*ap, int); // vnet_link_t promotion
      44             : 
      45      392201 :     return (format (s, "%s", vnet_link_names[link]));
      46             : }
      47             : 
      48             : u8 *
      49        5228 : format_fib_forw_chain_type (u8 * s, va_list * args)
      50             : {
      51        5228 :     fib_forward_chain_type_t fct = va_arg(*args, int);
      52             : 
      53        5228 :     return (format (s, "%s", fib_forw_chain_names[fct]));
      54             : }
      55             : 
      56             : u8 *
      57        3672 : format_fib_mpls_lsp_mode(u8 *s, va_list *ap)
      58             : {
      59        3672 :     fib_mpls_lsp_mode_t mode = va_arg(*ap, int);
      60             : 
      61        3672 :     return (format (s, "%s", fib_mpls_lsp_mode_names[mode])); 
      62             : }
      63             : 
      64             : u8 *
      65           4 : format_fib_mpls_label (u8 *s, va_list *ap)
      66             : {
      67           4 :     fib_mpls_label_t *label = va_arg(*ap, fib_mpls_label_t *);
      68             : 
      69           4 :     s = format(s, "%U %U ttl:%d exp:%d",
      70             :                format_mpls_unicast_label,
      71             :                label->fml_value,
      72             :                format_fib_mpls_lsp_mode,
      73           4 :                label->fml_mode,
      74           4 :                label->fml_ttl,
      75           4 :                label->fml_exp);
      76             : 
      77           4 :     return (s);
      78             : }
      79             : 
      80             : void
      81        5150 : fib_prefix_from_ip46_addr (fib_protocol_t fproto,
      82             :                            const ip46_address_t *addr,
      83             :                            fib_prefix_t *pfx)
      84             : {
      85        5150 :     ASSERT(FIB_PROTOCOL_MPLS != fproto);
      86             : 
      87        5150 :     pfx->fp_proto = fproto;
      88        5150 :     pfx->fp_len = ((FIB_PROTOCOL_IP4 == fproto) ?
      89             :                     32 : 128);
      90        5150 :     pfx->fp_addr = *addr;
      91        5150 :     pfx->___fp___pad = 0;
      92        5150 : }
      93             : 
      94             : u8 *
      95           0 : format_fib_route_path_flags (u8 *s, va_list *ap)
      96             : {
      97           0 :     fib_route_path_flags_t flags = va_arg (*ap, fib_route_path_flags_t);
      98             : 
      99           0 :     if (flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST)
     100           0 :         s = format (s, "via-host");
     101           0 :     if (flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED)
     102           0 :         s = format (s, "via-attached,");
     103           0 :     if (flags & FIB_ROUTE_PATH_LOCAL)
     104           0 :         s = format (s, "local,");
     105           0 :     if (flags & FIB_ROUTE_PATH_ATTACHED)
     106           0 :         s = format (s, "attached,");
     107           0 :     if (flags & FIB_ROUTE_PATH_DROP)
     108           0 :          s = format (s, "drop,");
     109           0 :    if (flags & FIB_ROUTE_PATH_EXCLUSIVE)
     110           0 :         s = format (s, "exclusive,");
     111           0 :     if (flags & FIB_ROUTE_PATH_INTF_RX)
     112           0 :         s = format (s, "intf-rx,");
     113           0 :     if (flags & FIB_ROUTE_PATH_RPF_ID)
     114           0 :         s = format (s, "rpf-id,");
     115           0 :     if (flags & FIB_ROUTE_PATH_SOURCE_LOOKUP)
     116           0 :         s = format (s, "src-lkup,");
     117           0 :     if (flags & FIB_ROUTE_PATH_UDP_ENCAP)
     118           0 :         s = format (s, "udp-encap,");
     119           0 :     if (flags & FIB_ROUTE_PATH_BIER_FMASK)
     120           0 :         s = format (s, "bier-fmask,");
     121           0 :     if (flags & FIB_ROUTE_PATH_BIER_TABLE)
     122           0 :         s = format (s, "bier-table,");
     123           0 :     if (flags & FIB_ROUTE_PATH_BIER_IMP)
     124           0 :         s = format (s, "bier-imp,");
     125           0 :     if (flags & FIB_ROUTE_PATH_DEAG)
     126           0 :         s = format (s, "deag,");
     127           0 :     if (flags & FIB_ROUTE_PATH_DVR)
     128           0 :         s = format (s, "dvr,");
     129           0 :     if (flags & FIB_ROUTE_PATH_ICMP_UNREACH)
     130           0 :         s = format (s, "imcp-unreach,");
     131           0 :     if (flags & FIB_ROUTE_PATH_ICMP_PROHIBIT)
     132           0 :         s = format (s, "icmp-prohibit,");
     133           0 :     if (flags & FIB_ROUTE_PATH_CLASSIFY)
     134           0 :         s = format (s, "classify,");
     135           0 :     if (flags & FIB_ROUTE_PATH_POP_PW_CW)
     136           0 :         s = format (s, "pop-pw-cw,");
     137             : 
     138           0 :     return (s);
     139             : }
     140             : 
     141             : u8 *
     142           0 : format_fib_route_path (u8 *s, va_list *ap)
     143             : {
     144           0 :     fib_route_path_t *rpath = va_arg (*ap, fib_route_path_t*);
     145             : 
     146           0 :     s = format (s, "%U %U, %U, [%U]",
     147           0 :                 format_dpo_proto, rpath->frp_proto,
     148             :                 format_ip46_address, &rpath->frp_addr, IP46_TYPE_ANY,
     149             :                 format_vnet_sw_if_index_name, vnet_get_main (),
     150             :                 rpath->frp_sw_if_index,
     151           0 :                 format_fib_route_path_flags, rpath->frp_flags);
     152             : 
     153           0 :     return (s);
     154             : }
     155             : 
     156             : void
     157          10 : fib_prefix_from_mpls_label (mpls_label_t label,
     158             :                             mpls_eos_bit_t eos,
     159             :                             fib_prefix_t *pfx)
     160             : {
     161          10 :     pfx->fp_proto = FIB_PROTOCOL_MPLS;
     162          10 :     pfx->fp_len = 21;
     163          10 :     pfx->fp_label = label;
     164          10 :     pfx->fp_eos = eos;
     165          10 :     pfx->___fp___pad = 0;
     166          10 : }
     167             : 
     168             : void
     169       20922 : fib_prefix_copy (fib_prefix_t *dst,
     170             :                  const fib_prefix_t *src)
     171             : {
     172       20922 :     clib_memcpy(dst, src, sizeof(*dst));
     173       20922 : }
     174             : 
     175             : int
     176          31 : fib_prefix_cmp (const fib_prefix_t *p1,
     177             :                 const fib_prefix_t *p2)
     178             : {
     179             :     int res;
     180             : 
     181          31 :     res = (p1->fp_proto - p2->fp_proto);
     182             : 
     183          31 :     if (0 == res)
     184             :     {
     185          31 :         switch (p1->fp_proto)
     186             :         {
     187          31 :         case FIB_PROTOCOL_IP4:
     188             :         case FIB_PROTOCOL_IP6:
     189          31 :             res = (p1->fp_len - p2->fp_len);
     190             : 
     191          31 :             if (0 == res)
     192             :             {
     193           1 :                 res = ip46_address_cmp(&p1->fp_addr, &p2->fp_addr);
     194             :             }
     195          31 :             break;
     196           0 :         case FIB_PROTOCOL_MPLS:
     197           0 :             res = (p1->fp_label - p2->fp_label);
     198             : 
     199           0 :             if (0 == res)
     200             :             {
     201           0 :                 res = (p1->fp_eos - p2->fp_eos);
     202             :             }
     203           0 :             break;
     204             :         }
     205           0 :     }
     206             : 
     207          31 :     return (res);
     208             : }
     209             : 
     210             : int
     211        6587 : fib_prefix_is_cover (const fib_prefix_t *p1,
     212             :                      const fib_prefix_t *p2)
     213             : {
     214        6587 :     switch (p1->fp_proto)
     215             :     {
     216        4370 :     case FIB_PROTOCOL_IP4:
     217        4370 :         return (ip4_destination_matches_route(&ip4_main,
     218             :                                               &p1->fp_addr.ip4,
     219             :                                               &p2->fp_addr.ip4,
     220        4370 :                                               p1->fp_len));
     221        2217 :     case FIB_PROTOCOL_IP6:
     222        2217 :         return (ip6_destination_matches_route(&ip6_main,
     223             :                                               &p1->fp_addr.ip6,
     224             :                                               &p2->fp_addr.ip6,
     225        2217 :                                               p1->fp_len));
     226           0 :     case FIB_PROTOCOL_MPLS:
     227           0 :         break;
     228             :     }
     229           0 :     return (0);
     230             : }
     231             : 
     232             : u8
     233        1169 : fib_prefix_get_host_length (fib_protocol_t proto)
     234             : {
     235        1169 :     switch (proto)
     236             :     {
     237        1118 :     case FIB_PROTOCOL_IP4:
     238        1118 :         return (32);
     239          51 :     case FIB_PROTOCOL_IP6:
     240          51 :         return (128);
     241           0 :     case FIB_PROTOCOL_MPLS:
     242           0 :         return (21);
     243             :     }
     244           0 :     return (0);
     245             : }
     246             : 
     247             : int
     248       82997 : fib_prefix_is_host (const fib_prefix_t *prefix)
     249             : {
     250       82997 :     switch (prefix->fp_proto)
     251             :     {
     252       52385 :     case FIB_PROTOCOL_IP4:
     253       52385 :         return (prefix->fp_len == 32);
     254       30558 :     case FIB_PROTOCOL_IP6:
     255       30558 :         return (prefix->fp_len == 128);
     256          54 :     case FIB_PROTOCOL_MPLS:
     257          54 :         return (!0);
     258             :     }
     259           0 :     return (0);
     260             : }
     261             : 
     262             : void
     263       20891 : fib_prefix_normalize (const fib_prefix_t *p,
     264             :                       fib_prefix_t *out)
     265             : {
     266       20891 :     fib_prefix_copy (out, p);
     267             : 
     268       20891 :     switch (p->fp_proto)
     269             :     {
     270       14968 :     case FIB_PROTOCOL_IP4:
     271       14968 :         ip4_address_normalize(&out->fp_addr.ip4, out->fp_len);
     272       14968 :         break;
     273        5923 :     case FIB_PROTOCOL_IP6:
     274        5923 :         ip6_address_normalize(&out->fp_addr.ip6, out->fp_len);
     275        5923 :         break;
     276           0 :     case FIB_PROTOCOL_MPLS:
     277           0 :         break;
     278             :     }
     279       20891 : }
     280             : 
     281             : u8 *
     282        6189 : format_fib_prefix (u8 * s, va_list * args)
     283             : {
     284        6189 :     fib_prefix_t *fp = va_arg (*args, fib_prefix_t *);
     285             : 
     286             :     /*
     287             :      * protocol specific so it prints ::/0 correctly.
     288             :      */
     289        6189 :     switch (fp->fp_proto)
     290             :     {
     291        2186 :     case FIB_PROTOCOL_IP6:
     292             :     {
     293        2186 :         ip6_address_t p6 = fp->fp_addr.ip6;
     294             : 
     295        2186 :         ip6_address_mask(&p6, &(ip6_main.fib_masks[fp->fp_len]));
     296        2186 :         s = format (s, "%U", format_ip6_address, &p6);
     297        2186 :         break;
     298             :     }
     299        4001 :     case FIB_PROTOCOL_IP4:
     300             :     {
     301        4001 :         ip4_address_t p4 = fp->fp_addr.ip4;
     302        4001 :         p4.as_u32 &= ip4_main.fib_masks[fp->fp_len];
     303             : 
     304        4001 :         s = format (s, "%U", format_ip4_address, &p4);
     305        4001 :         break;
     306             :     }
     307           2 :     case FIB_PROTOCOL_MPLS:
     308           2 :         s = format (s, "%U:%U",
     309             :                     format_mpls_unicast_label, fp->fp_label,
     310           2 :                     format_mpls_eos_bit, fp->fp_eos);
     311           2 :         break;
     312             :     }
     313        6189 :     s = format (s, "/%d", fp->fp_len);
     314             : 
     315        6189 :     return (s);
     316             : }
     317             : 
     318             : int
     319       85727 : fib_route_path_cmp (const fib_route_path_t *rpath1,
     320             :                     const fib_route_path_t *rpath2)
     321             : {
     322             :     int res;
     323             : 
     324       85727 :     res = ip46_address_cmp(&rpath1->frp_addr,
     325             :                            &rpath2->frp_addr);
     326             : 
     327       85727 :     if (0 != res) return (res);
     328             : 
     329       83601 :     res = (rpath1->frp_sw_if_index - rpath2->frp_sw_if_index);
     330             : 
     331       83601 :     if (0 != res) return (res);
     332             : 
     333       83596 :     if (ip46_address_is_zero(&rpath1->frp_addr))
     334             :     {
     335       77934 :         res = rpath1->frp_fib_index - rpath2->frp_fib_index;
     336             :     }
     337             : 
     338       83596 :     return (res);
     339             : }
     340             : 
     341             : dpo_proto_t
     342      273952 : fib_proto_to_dpo (fib_protocol_t fib_proto)
     343             : {
     344      273952 :     switch (fib_proto)
     345             :     {
     346      141890 :     case FIB_PROTOCOL_IP6:
     347      141890 :         return (DPO_PROTO_IP6);
     348      131376 :     case FIB_PROTOCOL_IP4:
     349      131376 :         return (DPO_PROTO_IP4);
     350         686 :     case FIB_PROTOCOL_MPLS:
     351         686 :         return (DPO_PROTO_MPLS);
     352             :     }
     353           0 :     ASSERT(0);
     354           0 :     return (0);
     355             : }
     356             : 
     357             : fib_protocol_t
     358      124492 : dpo_proto_to_fib (dpo_proto_t dpo_proto)
     359             : {
     360      124492 :     switch (dpo_proto)
     361             :     {
     362       52706 :     case DPO_PROTO_IP6:
     363       52706 :         return (FIB_PROTOCOL_IP6);
     364       71066 :     case DPO_PROTO_IP4:
     365       71066 :         return (FIB_PROTOCOL_IP4);
     366         720 :     case DPO_PROTO_MPLS:
     367         720 :         return (FIB_PROTOCOL_MPLS);
     368           0 :     default:
     369           0 :         break;
     370             :     }
     371           0 :     ASSERT(0);
     372           0 :     return (0);
     373             : }
     374             : 
     375             : vnet_link_t
     376        8194 : fib_proto_to_link (fib_protocol_t proto)
     377             : {
     378        8194 :     switch (proto)
     379             :     {
     380        5547 :     case FIB_PROTOCOL_IP4:
     381        5547 :         return (VNET_LINK_IP4);
     382        2647 :     case FIB_PROTOCOL_IP6:
     383        2647 :         return (VNET_LINK_IP6);
     384           0 :     case FIB_PROTOCOL_MPLS:
     385           0 :         return (VNET_LINK_MPLS);
     386             :     }
     387           0 :     ASSERT(0);
     388           0 :     return (0);
     389             : }
     390             : 
     391             : ip46_type_t
     392          35 : fib_proto_to_ip46 (fib_protocol_t fproto)
     393             : {
     394          35 :     switch (fproto)
     395             :     {
     396          13 :     case FIB_PROTOCOL_IP4:
     397          13 :         return (IP46_TYPE_IP4);
     398          22 :     case FIB_PROTOCOL_IP6:
     399          22 :         return (IP46_TYPE_IP6);
     400           0 :     case FIB_PROTOCOL_MPLS:
     401           0 :         return (IP46_TYPE_ANY);
     402             :     }
     403           0 :     ASSERT(0);
     404           0 :     return (IP46_TYPE_ANY);
     405             : }
     406             : 
     407             : fib_protocol_t
     408         116 : fib_proto_from_ip46 (ip46_type_t iproto)
     409             : {
     410         116 :     switch (iproto)
     411             :     {
     412          66 :     case IP46_TYPE_IP4:
     413          66 :         return FIB_PROTOCOL_IP4;
     414          50 :     case IP46_TYPE_IP6:
     415          50 :         return FIB_PROTOCOL_IP6;
     416           0 :     case IP46_TYPE_ANY:
     417           0 :         ASSERT(0);
     418           0 :         return FIB_PROTOCOL_IP4;
     419             :     }
     420             : 
     421           0 :     ASSERT(0);
     422           0 :     return FIB_PROTOCOL_IP4;
     423             : }
     424             : 
     425             : fib_forward_chain_type_t
     426      158417 : fib_forw_chain_type_from_dpo_proto (dpo_proto_t proto)
     427             : {
     428      158417 :     switch (proto)
     429             :     {
     430       82154 :     case DPO_PROTO_IP4:
     431       82154 :         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
     432       76153 :     case DPO_PROTO_IP6:
     433       76153 :         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
     434           1 :     case DPO_PROTO_MPLS:
     435           1 :         return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
     436           3 :     case DPO_PROTO_ETHERNET:
     437           3 :         return (FIB_FORW_CHAIN_TYPE_ETHERNET);
     438           0 :     case DPO_PROTO_NSH:
     439           0 :         return (FIB_FORW_CHAIN_TYPE_NSH);
     440         106 :     case DPO_PROTO_BIER:
     441         106 :         return (FIB_FORW_CHAIN_TYPE_BIER);
     442             :     }
     443           0 :     ASSERT(0);
     444           0 :     return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
     445             : }
     446             : 
     447             : fib_forward_chain_type_t
     448        4262 : fib_forw_chain_type_from_fib_proto (fib_protocol_t proto)
     449             : {
     450        4262 :     switch (proto)
     451             :     {
     452        2287 :     case FIB_PROTOCOL_IP4:
     453        2287 :         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
     454        1975 :     case FIB_PROTOCOL_IP6:
     455        1975 :         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
     456           0 :     case FIB_PROTOCOL_MPLS:
     457           0 :         return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
     458             :     }
     459           0 :     ASSERT(0);
     460           0 :     return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
     461             : }
     462             : 
     463             : vnet_link_t
     464        4127 : fib_forw_chain_type_to_link_type (fib_forward_chain_type_t fct)
     465             : {
     466        4127 :     switch (fct)
     467             :     {
     468        1620 :     case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
     469             :     case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
     470        1620 :         return (VNET_LINK_IP4);
     471        1514 :     case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
     472             :     case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
     473        1514 :         return (VNET_LINK_IP6);
     474           0 :     case FIB_FORW_CHAIN_TYPE_ETHERNET:
     475           0 :         return (VNET_LINK_ETHERNET);
     476           0 :     case FIB_FORW_CHAIN_TYPE_NSH:
     477           0 :         return (VNET_LINK_NSH);
     478           0 :     case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
     479             :     case FIB_FORW_CHAIN_TYPE_BIER:
     480             :         /*
     481             :          * insufficient information to to convert
     482             :          */
     483           0 :         ASSERT(0);
     484           0 :         break;
     485         993 :     case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
     486         993 :         return (VNET_LINK_MPLS);
     487             :     }
     488           0 :     return (VNET_LINK_IP4);
     489             : }
     490             : 
     491             : fib_forward_chain_type_t
     492          41 : fib_forw_chain_type_from_link_type (vnet_link_t link_type)
     493             : {
     494          41 :     switch (link_type)
     495             :     {
     496          26 :     case VNET_LINK_IP4:
     497          26 :         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
     498           0 :     case VNET_LINK_IP6:
     499           0 :         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
     500          15 :     case VNET_LINK_MPLS:
     501          15 :         return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
     502           0 :     case VNET_LINK_ETHERNET:
     503           0 :         return (FIB_FORW_CHAIN_TYPE_ETHERNET);
     504           0 :     case VNET_LINK_NSH:
     505           0 :         return (FIB_FORW_CHAIN_TYPE_NSH);
     506           0 :     case VNET_LINK_ARP:
     507           0 :         break;
     508             :     }
     509             : 
     510           0 :     ASSERT(0);
     511           0 :     return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
     512             : }
     513             : 
     514             : dpo_proto_t
     515       91962 : fib_forw_chain_type_to_dpo_proto (fib_forward_chain_type_t fct)
     516             : {
     517       91962 :     switch (fct)
     518             :     {
     519       46355 :     case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
     520             :     case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
     521       46355 :         return (DPO_PROTO_IP4);
     522       35325 :     case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
     523             :     case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
     524       35325 :         return (DPO_PROTO_IP6);
     525         950 :     case FIB_FORW_CHAIN_TYPE_ETHERNET:
     526         950 :         return (DPO_PROTO_ETHERNET);
     527           0 :     case FIB_FORW_CHAIN_TYPE_NSH:
     528           0 :         return (DPO_PROTO_NSH);
     529        5572 :     case FIB_FORW_CHAIN_TYPE_BIER:
     530        5572 :         return (DPO_PROTO_BIER);
     531        3760 :     case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
     532             :     case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
     533        3760 :         return (DPO_PROTO_MPLS);
     534             :     }
     535           0 :     return (DPO_PROTO_IP4);
     536             : }
     537             : 
     538             : uword
     539          19 : unformat_fib_route_path (unformat_input_t * input, va_list * args)
     540             : {
     541          19 :     fib_route_path_t *rpath = va_arg (*args, fib_route_path_t *);
     542          19 :     dpo_proto_t *payload_proto = va_arg (*args, void*);
     543          19 :     dpo_proto_t explicit_proto = DPO_PROTO_NONE;
     544             :     u32 weight, preference, udp_encap_id, fi;
     545             :     mpls_label_t out_label;
     546             :     vnet_main_t *vnm;
     547             : 
     548          19 :     vnm = vnet_get_main ();
     549          19 :     clib_memset(rpath, 0, sizeof(*rpath));
     550          19 :     rpath->frp_weight = 1;
     551          19 :     rpath->frp_sw_if_index = ~0;
     552             : 
     553          36 :     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     554             :     {
     555          19 :         if (unformat (input, "%U %U",
     556             :                       unformat_ip4_address,
     557             :                       &rpath->frp_addr.ip4,
     558             :                       unformat_vnet_sw_interface, vnm,
     559             :                       &rpath->frp_sw_if_index))
     560             :         {
     561           0 :             rpath->frp_proto = DPO_PROTO_IP4;
     562             :         }
     563          19 :         else if (unformat (input, "%U %U",
     564             :                            unformat_ip6_address,
     565             :                            &rpath->frp_addr.ip6,
     566             :                            unformat_vnet_sw_interface, vnm,
     567             :                            &rpath->frp_sw_if_index))
     568             :         {
     569           0 :             rpath->frp_proto = DPO_PROTO_IP6;
     570             :         }
     571          19 :         else if (unformat (input, "weight %u", &weight))
     572             :         {
     573           0 :             rpath->frp_weight = weight;
     574             :         }
     575          19 :         else if (unformat (input, "preference %u", &preference))
     576             :         {
     577           0 :             rpath->frp_preference = preference;
     578             :         }
     579          19 :         else if (unformat (input, "%U next-hop-table %d",
     580             :                            unformat_ip4_address,
     581             :                            &rpath->frp_addr.ip4,
     582             :                            &rpath->frp_fib_index))
     583             :         {
     584           0 :             rpath->frp_sw_if_index = ~0;
     585           0 :             rpath->frp_proto = DPO_PROTO_IP4;
     586             : 
     587             :             /*
     588             :              * the user enter table-ids, convert to index
     589             :              */
     590           0 :             fi = fib_table_find (FIB_PROTOCOL_IP4, rpath->frp_fib_index);
     591           0 :             if (~0 == fi)
     592           0 :                 return 0;
     593           0 :             rpath->frp_fib_index = fi;
     594             :         }
     595          19 :         else if (unformat (input, "%U next-hop-table %d",
     596             :                            unformat_ip6_address,
     597             :                            &rpath->frp_addr.ip6,
     598             :                            &rpath->frp_fib_index))
     599             :         {
     600           0 :             rpath->frp_sw_if_index = ~0;
     601           0 :             rpath->frp_proto = DPO_PROTO_IP6;
     602           0 :             fi = fib_table_find (FIB_PROTOCOL_IP6, rpath->frp_fib_index);
     603           0 :             if (~0 == fi)
     604           0 :                 return 0;
     605           0 :             rpath->frp_fib_index = fi;
     606             :         }
     607          19 :         else if (unformat (input, "%U",
     608             :                            unformat_ip4_address,
     609             :                            &rpath->frp_addr.ip4))
     610             :         {
     611             :             /*
     612             :              * the recursive next-hops are by default in the default table
     613             :              */
     614           0 :             rpath->frp_fib_index = 0;
     615           0 :             rpath->frp_sw_if_index = ~0;
     616           0 :             rpath->frp_proto = DPO_PROTO_IP4;
     617             :         }
     618          19 :         else if (unformat (input, "%U",
     619             :                            unformat_ip6_address,
     620             :                            &rpath->frp_addr.ip6))
     621             :         {
     622          15 :             rpath->frp_fib_index = 0;
     623          15 :             rpath->frp_sw_if_index = ~0;
     624          15 :             rpath->frp_proto = DPO_PROTO_IP6;
     625             :         }
     626           4 :         else if (unformat (input, "udp-encap %d", &udp_encap_id))
     627             :         {
     628           0 :             rpath->frp_udp_encap_id = udp_encap_id;
     629           0 :             rpath->frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
     630           0 :             rpath->frp_proto = *payload_proto;
     631             :         }
     632           4 :         else if (unformat (input, "lookup in table %d", &rpath->frp_fib_index))
     633             :         {
     634           0 :             rpath->frp_proto = *payload_proto;
     635           0 :             rpath->frp_sw_if_index = ~0;
     636           0 :             rpath->frp_flags |= FIB_ROUTE_PATH_DEAG;
     637             :         }
     638           4 :         else if (unformat (input, "resolve-via-host"))
     639             :         {
     640           0 :             rpath->frp_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
     641             :         }
     642           4 :         else if (unformat (input, "resolve-via-attached"))
     643             :         {
     644           0 :             rpath->frp_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
     645             :         }
     646           4 :         else if (unformat (input, "pop-pw-cw"))
     647             :         {
     648           0 :             rpath->frp_flags |= FIB_ROUTE_PATH_POP_PW_CW;
     649             :         }
     650           4 :         else if (unformat (input,
     651             :                            "ip4-lookup-in-table %d",
     652             :                            &rpath->frp_fib_index))
     653             :         {
     654           0 :             rpath->frp_proto = DPO_PROTO_IP4;
     655           0 :             *payload_proto = DPO_PROTO_IP4;
     656           0 :             fi = fib_table_find (FIB_PROTOCOL_IP4, rpath->frp_fib_index);
     657           0 :             if (~0 == fi)
     658           0 :                 return 0;
     659           0 :             rpath->frp_fib_index = fi;
     660             :         }
     661           4 :         else if (unformat (input,
     662             :                            "ip6-lookup-in-table %d",
     663             :                            &rpath->frp_fib_index))
     664             :         {
     665           0 :             rpath->frp_proto = DPO_PROTO_IP6;
     666           0 :             *payload_proto = DPO_PROTO_IP6;
     667           0 :             fi = fib_table_find (FIB_PROTOCOL_IP6, rpath->frp_fib_index);
     668           0 :             if (~0 == fi)
     669           0 :                 return 0;
     670           0 :             rpath->frp_fib_index = fi;
     671             :         }
     672           4 :         else if (unformat (input,
     673             :                            "mpls-lookup-in-table %d",
     674             :                            &rpath->frp_fib_index))
     675             :         {
     676           0 :             rpath->frp_proto = DPO_PROTO_MPLS;
     677           0 :             *payload_proto = DPO_PROTO_MPLS;
     678           0 :             fi = fib_table_find (FIB_PROTOCOL_MPLS, rpath->frp_fib_index);
     679           0 :             if (~0 == fi)
     680           0 :                 return 0;
     681           0 :             rpath->frp_fib_index = fi;
     682             :         }
     683           4 :         else if (unformat (input, "src-lookup"))
     684             :         {
     685           0 :             rpath->frp_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP;
     686             :         }
     687           4 :         else if (unformat (input,
     688             :                            "l2-input-on %U",
     689             :                            unformat_vnet_sw_interface, vnm,
     690             :                            &rpath->frp_sw_if_index))
     691             :         {
     692           0 :             rpath->frp_proto = DPO_PROTO_ETHERNET;
     693           0 :             *payload_proto = DPO_PROTO_ETHERNET;
     694           0 :             rpath->frp_flags |= FIB_ROUTE_PATH_INTF_RX;
     695             :         }
     696           4 :         else if (unformat (input, "via-label %U",
     697             :                            unformat_mpls_unicast_label,
     698             :                            &rpath->frp_local_label))
     699             :         {
     700           0 :             rpath->frp_eos = MPLS_NON_EOS;
     701           0 :             rpath->frp_proto = DPO_PROTO_MPLS;
     702           0 :             rpath->frp_sw_if_index = ~0;
     703             :         }
     704           4 :         else if (unformat (input, "rx-ip4 %U",
     705             :                            unformat_vnet_sw_interface, vnm,
     706             :                            &rpath->frp_sw_if_index))
     707             :         {
     708           0 :             rpath->frp_proto = DPO_PROTO_IP4;
     709           0 :             rpath->frp_flags = FIB_ROUTE_PATH_INTF_RX;
     710             :         }
     711           4 :       else if (unformat (input, "local"))
     712             :         {
     713           2 :           clib_memset (&rpath->frp_addr, 0, sizeof (rpath->frp_addr));
     714           2 :           rpath->frp_sw_if_index = ~0;
     715           2 :           rpath->frp_weight = 1;
     716           2 :           rpath->frp_flags |= FIB_ROUTE_PATH_LOCAL;
     717             :         }
     718           2 :       else if (unformat (input, "out-labels"))
     719             :         {
     720           0 :             while (unformat (input, "%U",
     721             :                              unformat_mpls_unicast_label, &out_label))
     722             :             {
     723           0 :                 fib_mpls_label_t fml = {
     724             :                     .fml_value = out_label,
     725             :                 };
     726           0 :                 vec_add1(rpath->frp_label_stack, fml);
     727             :             }
     728             :         }
     729           2 :       else if (unformat (input, "ip4"))
     730             :         {
     731           0 :           explicit_proto = DPO_PROTO_IP4;
     732             :         }
     733           2 :       else if (unformat (input, "ip6"))
     734             :         {
     735           0 :           explicit_proto = DPO_PROTO_IP6;
     736             :         }
     737           2 :         else if (unformat (input, "%U",
     738             :                            unformat_vnet_sw_interface, vnm,
     739             :                            &rpath->frp_sw_if_index))
     740             :         {
     741           0 :             rpath->frp_proto = *payload_proto;
     742             :         }
     743           2 :         else if (unformat (input, "%U",
     744             :                          unformat_mfib_itf_flags, &rpath->frp_mitf_flags))
     745             :         ;
     746           2 :         else if (unformat (input, "via"))
     747             :         {
     748             :             /* new path, back up and return */
     749           0 :             unformat_put_input (input);
     750           0 :             unformat_put_input (input);
     751           0 :             unformat_put_input (input);
     752           0 :             unformat_put_input (input);
     753           0 :             break;
     754             :         }
     755             :         else
     756             :         {
     757           2 :             return (0);
     758             :         }
     759             :     }
     760             : 
     761          17 :     if (DPO_PROTO_NONE != explicit_proto)
     762           0 :       *payload_proto = rpath->frp_proto = explicit_proto;
     763             : 
     764          17 :     return (1);
     765             : }
     766             : 
     767             : /*
     768             :  * Return true if the path is attached
     769             :  */
     770             : int
     771      107028 : fib_route_path_is_attached (const fib_route_path_t *rpath)
     772             : {
     773             :     /*
     774             :      * DVR paths are not attached, since we are not playing the
     775             :      * L3 game with these
     776             :      */
     777      107028 :     if (rpath->frp_flags & (FIB_ROUTE_PATH_DVR |
     778             :                             FIB_ROUTE_PATH_UDP_ENCAP))
     779             :     {
     780          38 :         return (0);
     781             :     }
     782             : 
     783             :     /*
     784             :      * - All zeros next-hop
     785             :      * - a valid interface
     786             :      */
     787      106990 :     if (ip46_address_is_zero(&rpath->frp_addr) &&
     788       27162 :         (~0 != rpath->frp_sw_if_index))
     789             :     {
     790       26960 :         return (!0);
     791             :     }
     792       80030 :     else if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED ||
     793       67153 :              rpath->frp_flags & FIB_ROUTE_PATH_GLEAN)
     794             :     {
     795       17528 :         return (!0);
     796             :     }
     797       62502 :     return (0);
     798             : }
     799             : 
     800             : static void
     801           1 : fib_prefix_ip4_addr_increment (fib_prefix_t *pfx)
     802             : {
     803             :     /* Calculate the addend based on the host length of address */
     804           1 :     u32 incr = 1ULL << (32 - pfx->fp_len);
     805           1 :     ip4_address_t dst = (pfx->fp_addr).ip4;
     806           1 :     dst.as_u32 = clib_host_to_net_u32 (incr + clib_net_to_host_u32 (dst.as_u32));
     807           1 :     pfx->fp_addr.ip4.as_u32 = dst.as_u32;
     808           1 : }
     809             : 
     810             : static void
     811          16 : fib_prefix_ip6_addr_increment (fib_prefix_t *pfx)
     812             : {
     813             :     /*
     814             :      * Calculate the addend based on the host length of address
     815             :      * and which part(lower 64 bits or higher 64 bits) it lies
     816             :      * in
     817             :      */
     818          16 :     u32 host_len = 128 - pfx->fp_len;
     819          16 :     u64 incr = 1ULL << ((host_len > 64) ? (host_len - 64) : host_len);
     820          16 :     i32 bucket = (host_len < 64 ? 1 : 0);
     821          16 :     ip6_address_t dst = (pfx->fp_addr).ip6;
     822          16 :     u64 tmp = incr + clib_net_to_host_u64 (dst.as_u64[bucket]);
     823             :     /* Handle overflow */
     824          16 :     if (bucket && (tmp < incr))
     825             :     {
     826           0 :         dst.as_u64[1] = clib_host_to_net_u64 (tmp);
     827           0 :         dst.as_u64[0] = clib_host_to_net_u64 (1ULL + clib_net_to_host_u64 (dst.as_u64[0]));
     828             :     }
     829             :     else
     830          16 :         dst.as_u64[bucket] = clib_host_to_net_u64 (tmp);
     831             : 
     832          16 :     pfx->fp_addr.ip6.as_u128 = dst.as_u128;
     833          16 : }
     834             : 
     835             : /*
     836             :  * Increase IPv4/IPv6 address according to the prefix length
     837             :  */
     838          17 : void fib_prefix_increment (fib_prefix_t *pfx)
     839             : {
     840          17 :     switch (pfx->fp_proto)
     841             :     {
     842           1 :     case FIB_PROTOCOL_IP4:
     843           1 :         fib_prefix_ip4_addr_increment (pfx);
     844           1 :         break;
     845          16 :     case FIB_PROTOCOL_IP6:
     846          16 :         fib_prefix_ip6_addr_increment (pfx);
     847          16 :         break;
     848           0 :     case FIB_PROTOCOL_MPLS:
     849           0 :         break;
     850             :     }
     851          17 : }

Generated by: LCOV version 1.14