LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dp-core - vr_route.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 179 328 54.6 %
Date: 2026-08-03 02:19:58 Functions: 16 22 72.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_route.c -- route management
       3             :  *
       4             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       5             :  */
       6             : #include <vr_os.h>
       7             : #include <vr_types.h>
       8             : #include <vr_packet.h>
       9             : #include <vr_route.h>
      10             : #include "vr_message.h"
      11             : #include "vr_sandesh.h"
      12             : #include "vr_offloads_dp.h"
      13             : 
      14             : unsigned int vr_vrfs = VR_DEF_VRFS;
      15             : 
      16             : extern int mtrie_algo_init(struct vr_rtable *, struct rtable_fspec *);
      17             : extern void mtrie_algo_deinit(struct vr_rtable *, struct rtable_fspec *, bool);
      18             : extern int bridge_table_init(struct vr_rtable *, struct rtable_fspec *);
      19             : extern void bridge_table_deinit(struct vr_rtable *, struct rtable_fspec *, bool);
      20             : 
      21             : static int inet_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router);
      22             : static void inet_rtb_family_deinit(struct rtable_fspec *fs, struct vrouter *router, bool soft_reset);
      23             : static int bridge_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router);
      24             : static void bridge_rtb_family_deinit(struct rtable_fspec *fs, struct vrouter *router, bool soft_reset);
      25             : 
      26             : int vr_route_delete(vr_route_req *);
      27             : int vr_route_get(vr_route_req *);
      28             : int vr_route_dump(vr_route_req *);
      29             : 
      30             : int inet_route_add(struct rtable_fspec *, struct vr_route_req *);
      31             : int inet_route_del(struct rtable_fspec *, struct vr_route_req *);
      32             : 
      33             : int bridge_entry_add(struct rtable_fspec *, struct vr_route_req *);
      34             : int bridge_entry_del(struct rtable_fspec *, struct vr_route_req *);
      35             : 
      36             : /* hopefully we can afford a bit of bloat while loading ? */
      37             : static struct rtable_fspec rtable_families[] = {
      38             :     {
      39             :         .rtb_family = AF_INET,
      40             :         .rtb_family_init = inet_rtb_family_init,
      41             :         .rtb_family_deinit = inet_rtb_family_deinit,
      42             :         .route_add = inet_route_add,
      43             :         .route_del = inet_route_del,
      44             :         .algo_init = mtrie_algo_init,
      45             :         .algo_deinit = mtrie_algo_deinit,
      46             :     },
      47             :     {
      48             :         .rtb_family = AF_BRIDGE,
      49             :         .rtb_family_init = bridge_rtb_family_init,
      50             :         .rtb_family_deinit = bridge_rtb_family_deinit,
      51             :         .route_add = bridge_entry_add,
      52             :         .route_del = bridge_entry_del,
      53             :         .algo_init = bridge_table_init,
      54             :         .algo_deinit = bridge_table_deinit,
      55             :     },
      56             :     {
      57             :         .rtb_family = AF_INET6,
      58             :         .rtb_family_init = inet_rtb_family_init,
      59             :         .rtb_family_deinit = inet_rtb_family_deinit,
      60             :         .route_add = inet_route_add,
      61             :         .route_del = inet_route_del,
      62             :         .algo_init = mtrie_algo_init,
      63             :         .algo_deinit = mtrie_algo_deinit,
      64             :     }
      65             : };
      66             : 
      67             : static struct rtable_fspec *
      68         709 : vr_get_family(unsigned int family)
      69             : {
      70         709 :     switch (family) {
      71         473 :     case AF_INET:
      72         473 :         return &rtable_families[0];
      73         179 :     case AF_BRIDGE:
      74         179 :         return &rtable_families[1];
      75          57 :     case AF_INET6:
      76          57 :         return &rtable_families[2];
      77             : 
      78           0 :     default:
      79           0 :         return NULL;
      80             :     }
      81             : 
      82             :     return NULL;
      83             : }
      84             : 
      85             : int
      86         490 : vr_route_delete(vr_route_req *req)
      87             : {
      88             :     struct rtable_fspec *fs;
      89             :     struct vr_route_req vr_req;
      90             :     int ret;
      91             :     uint32_t rt_prefix[4];
      92             : 
      93         490 :     fs = vr_get_family(req->rtr_family);
      94         490 :     if (!fs)
      95           0 :         ret = -ENOENT;
      96             :     else {
      97         490 :         vr_req.rtr_req = *req;
      98             : 
      99         490 :         if (req->rtr_family != AF_BRIDGE && !req->rtr_prefix_size) {
     100           0 :             ret = -EINVAL;
     101           0 :             goto error;
     102             :         }
     103             : 
     104         490 :         if (req ->rtr_family == AF_BRIDGE &&
     105          87 :                 (!req->rtr_mac_size  || !req->rtr_mac)) {
     106           0 :             ret = -EINVAL;
     107           0 :             goto error;
     108             :         }
     109             : 
     110         490 :         if (req ->rtr_family != AF_BRIDGE) {
     111         403 :             vr_req.rtr_req.rtr_prefix = (uint8_t*)&rt_prefix;
     112         403 :             memcpy(vr_req.rtr_req.rtr_prefix, req->rtr_prefix, RT_IP_ADDR_SIZE(req->rtr_family));
     113             :         }
     114         490 :         vr_req.rtr_req.rtr_marker_size = 0;
     115         490 :         ret = fs->route_del(fs, &vr_req);
     116             :     }
     117             : 
     118             :     /* notify hw offload of change, if enabled */
     119         490 :     if (!ret)
     120         109 :         vr_offload_route_del(req);
     121             : 
     122         381 : error:
     123         490 :     vr_send_response(ret);
     124         490 :     vr_send_broadcast(VR_ROUTE_OBJECT_ID, &vr_req, SANDESH_OP_DEL, ret);
     125             : 
     126         490 :     return ret;
     127             : }
     128             : 
     129             : int
     130         219 : vr_route_add(vr_route_req *req)
     131             : {
     132             :     struct rtable_fspec *fs;
     133             :     struct vr_route_req vr_req;
     134             :     int ret;
     135             :     uint32_t rt_prefix[4];
     136             : 
     137         219 :     fs = vr_get_family(req->rtr_family);
     138         219 :     if (!fs) {
     139           0 :         ret = -ENOENT;
     140             :     } else {
     141         219 :         vr_req.rtr_req = *req;
     142         219 :         if (req->rtr_prefix_size) {
     143         127 :             vr_req.rtr_req.rtr_prefix = (uint8_t*)&rt_prefix;
     144         127 :             memcpy(vr_req.rtr_req.rtr_prefix, req->rtr_prefix, RT_IP_ADDR_SIZE(req->rtr_family));
     145         127 :             vr_req.rtr_req.rtr_marker_size = 0;
     146         127 :             vr_req.rtr_req.rtr_prefix_size = req->rtr_prefix_size;
     147             :         } else {
     148          92 :            vr_req.rtr_req.rtr_prefix = NULL;
     149             :         }
     150             : 
     151         219 :         ret = fs->route_add(fs, &vr_req);
     152             :     }
     153             : 
     154             :     /* notify hw offload of change, if enabled */
     155         219 :     if (!ret) {
     156         218 :         ret = vr_offload_route_add(req);
     157         218 :         if (ret)
     158           0 :             fs->route_del(fs, &vr_req);
     159             :     }
     160             : 
     161         219 :     vr_send_response(ret);
     162         219 :     vr_send_broadcast(VR_ROUTE_OBJECT_ID, &vr_req, SANDESH_OP_ADD, ret);
     163             : 
     164         219 :     return ret;
     165             : }
     166             : 
     167             : int
     168         331 : vr_route_get(vr_route_req *req)
     169             : {
     170         331 :     int ret = 0;
     171             :     uint32_t rt_prefix[4];
     172         331 :     bool mac_mem_free = false;
     173             : 
     174             :     struct vr_route_req vr_req;
     175             :     struct vrouter *router;
     176         331 :     struct vr_rtable *rtable = NULL;
     177             : 
     178         331 :     if (!req->rtr_mac)
     179           0 :         mac_mem_free = true;
     180             : 
     181         331 :     if ((req->rtr_family != AF_INET) && (req->rtr_family != AF_INET6) &&
     182           0 :             (req->rtr_family != AF_BRIDGE)) {
     183           0 :         ret = -EINVAL;
     184           0 :         goto generate_response;
     185             :     }
     186             : 
     187         331 :     vr_req.rtr_req = *req;
     188             : 
     189         331 :     vr_req.rtr_req.rtr_marker_size = 0;
     190         331 :     vr_req.rtr_req.rtr_prefix_size = req->rtr_prefix_size;
     191         331 :     if (req->rtr_prefix_size) {
     192         331 :         vr_req.rtr_req.rtr_prefix = (uint8_t*)&rt_prefix;
     193         331 :         memcpy(vr_req.rtr_req.rtr_prefix, req->rtr_prefix, RT_IP_ADDR_SIZE(req->rtr_family));
     194             :     } else
     195           0 :         vr_req.rtr_req.rtr_prefix = NULL;
     196             : 
     197         331 :     router = vrouter_get(req->rtr_rid);
     198         331 :     if (!router) {
     199           0 :         ret = -ENOENT;
     200           0 :         goto generate_response;
     201             :     } else {
     202         331 :         if ((req->rtr_family == AF_INET) || (req->rtr_family == AF_INET6)) {
     203         331 :             rtable = router->vr_inet_rtable;
     204           0 :         } else if (req->rtr_family == AF_BRIDGE) {
     205           0 :             rtable = router->vr_bridge_table;
     206             :         }
     207             : 
     208         331 :         if (!rtable) {
     209           0 :             ret = -ENOENT;
     210           0 :             goto generate_response;
     211             :         }
     212             : 
     213         331 :         ret = rtable->algo_get(vr_req.rtr_req.rtr_vrf_id, &vr_req);
     214             :     }
     215             :     /* Allow for debug comparison to check if matching entry is programmed on NIC */
     216         331 :     if (!ret)
     217         331 :         vr_offload_route_get(req);
     218           0 : generate_response:
     219         331 :     vr_message_response(VR_ROUTE_OBJECT_ID, ret ? NULL : &vr_req, ret, false);
     220         331 :     if (mac_mem_free && vr_req.rtr_req.rtr_mac) {
     221           0 :         vr_free(vr_req.rtr_req.rtr_mac, VR_ROUTE_REQ_MAC_OBJECT);
     222           0 :         vr_req.rtr_req.rtr_mac = NULL;
     223             :     }
     224             : 
     225         331 :     return ret;
     226             : }
     227             : 
     228             : int
     229           0 : vr_route_dump(vr_route_req *req)
     230             : {
     231             :     struct vr_route_req vr_req;
     232             :     struct vrouter *router;
     233           0 :     struct vr_rtable *rtable = NULL;
     234             :     int ret;
     235             :     uint32_t rt_prefix[4], rt_marker[4];
     236             : 
     237           0 :     vr_req.rtr_req = *req;
     238           0 :     vr_req.rtr_req.rtr_prefix_size = req->rtr_prefix_size;
     239           0 :     if (req->rtr_prefix_size) {
     240           0 :         vr_req.rtr_req.rtr_prefix = (uint8_t*)&rt_prefix;
     241           0 :         memcpy(vr_req.rtr_req.rtr_prefix, req->rtr_prefix, RT_IP_ADDR_SIZE(req->rtr_family));
     242             :     } else {
     243           0 :         vr_req.rtr_req.rtr_prefix = NULL;
     244             :     }
     245             : 
     246           0 :     vr_req.rtr_req.rtr_marker_size = req->rtr_marker_size;
     247           0 :     if (req->rtr_marker_size) {
     248           0 :         vr_req.rtr_req.rtr_marker = (uint8_t*)&rt_marker;
     249           0 :         memcpy(vr_req.rtr_req.rtr_marker, req->rtr_marker, RT_IP_ADDR_SIZE(req->rtr_family));
     250             :     } else {
     251           0 :         vr_req.rtr_req.rtr_marker = NULL;
     252             :     }
     253             : 
     254           0 :     router = vrouter_get(req->rtr_rid);
     255           0 :     if (!router) {
     256           0 :         ret = -ENOENT;
     257           0 :         goto generate_error;
     258             :     } else {
     259             : 
     260           0 :         if (req->rtr_family == AF_BRIDGE) {
     261           0 :             rtable = router->vr_bridge_table;
     262             :         } else  {
     263           0 :             rtable = router->vr_inet_rtable;
     264             :         }
     265             : 
     266           0 :         if (!rtable) {
     267           0 :             ret = -ENOENT;
     268           0 :             goto generate_error;
     269             :         }
     270             : 
     271           0 :         ret = rtable->algo_dump(NULL, &vr_req);
     272             :     }
     273             :     /* Allow for debug comparison to check if matching entry is programmed on NIC */
     274           0 :     if (!ret)
     275           0 :         vr_offload_route_dump(&vr_req);
     276             : 
     277           0 :     return ret;
     278             : 
     279           0 : generate_error:
     280           0 :     vr_send_response(ret);
     281             : 
     282           0 :     return ret;
     283             : }
     284             : 
     285             : void
     286        1040 : vr_route_req_process(void *s_req)
     287             : {
     288        1040 :     vr_route_req *req = (vr_route_req *)s_req;
     289             : 
     290        1040 :     switch (req->h_op) {
     291         219 :     case SANDESH_OP_ADD:
     292         219 :         vr_route_add(req);
     293         219 :         break;
     294             : 
     295         490 :     case SANDESH_OP_DEL:
     296         490 :         vr_route_delete(req);
     297         490 :         break;
     298             : 
     299         331 :     case SANDESH_OP_GET:
     300         331 :         vr_route_get(req);
     301         331 :         break;
     302             : 
     303           0 :     case SANDESH_OP_DUMP:
     304           0 :         vr_route_dump(req);
     305           0 :         break;
     306             : 
     307           0 :     default:
     308           0 :         break;
     309             :     }
     310             : 
     311        1040 :     return;
     312             : }
     313             : 
     314             : static void
     315           0 : vr_inet_vrf_stats_dump(struct vrouter *router, vr_vrf_stats_req *req)
     316             : {
     317           0 :     int ret = 0;
     318             :     struct vr_rtable *rtable;
     319             : 
     320           0 :     rtable = router->vr_inet_rtable;
     321           0 :     if (!rtable) {
     322           0 :         ret = -ENOENT;
     323           0 :         goto generate_error;
     324             :     }
     325             : 
     326           0 :     ret = rtable->algo_stats_dump(rtable, req);
     327           0 :     return;
     328             : 
     329           0 : generate_error:
     330           0 :     vr_send_response(ret);
     331           0 :     return;
     332             : }
     333             : 
     334             : static void
     335           0 : vr_inet_vrf_stats_get(struct vrouter *router, vr_vrf_stats_req *req)
     336             : {
     337           0 :     int ret = 0;
     338             :     struct vr_rtable *rtable;
     339             :     vr_vrf_stats_req response;
     340             : 
     341           0 :     rtable = router->vr_inet_rtable;
     342           0 :     if (!rtable) {
     343           0 :         ret = -ENOENT;
     344           0 :         goto generate_error;
     345             :     }
     346             : 
     347           0 :     if (req->vsr_vrf >= 0 &&
     348           0 :             (unsigned int)req->vsr_vrf >= rtable->algo_max_vrfs) {
     349           0 :         ret = -EINVAL;
     350           0 :         goto generate_error;
     351             :     }
     352             : 
     353           0 :     ret = rtable->algo_stats_get(req, &response);
     354           0 : generate_error:
     355           0 :     vr_message_response(VR_VRF_STATS_OBJECT_ID, ret ? NULL : &response, ret, false);
     356           0 :     return;
     357             : }
     358             : 
     359             : static void
     360           0 : vr_inet_vrf_stats_op(struct vrouter *router, vr_vrf_stats_req *req)
     361             : {
     362           0 :     if (req->h_op == SANDESH_OP_GET)
     363           0 :         vr_inet_vrf_stats_get(router, req);
     364           0 :     else if (req->h_op == SANDESH_OP_DUMP)
     365           0 :         vr_inet_vrf_stats_dump(router, req);
     366             : 
     367           0 :     return;
     368             : }
     369             : 
     370             : static void
     371           0 : vr_vrf_stats_op(vr_vrf_stats_req *req)
     372             : {
     373           0 :     int ret = 0;
     374             :     struct vrouter *router;
     375             : 
     376           0 :     router = vrouter_get(req->vsr_rid);
     377           0 :     if (!router) {
     378           0 :         ret = -EINVAL;
     379           0 :         goto generate_error;
     380             :     }
     381             : 
     382           0 :     switch (req->vsr_family) {
     383           0 :     case AF_INET:
     384           0 :         vr_inet_vrf_stats_op(router, req);
     385           0 :         break;
     386             : 
     387           0 :     default:
     388           0 :         ret = -EINVAL;
     389           0 :         goto generate_error;
     390             :     }
     391             : 
     392           0 :     return;
     393             : 
     394           0 : generate_error:
     395           0 :     vr_send_response(ret);
     396           0 :     return;
     397             : }
     398             : 
     399             : void
     400           0 : vr_vrf_stats_req_process(void *s_req)
     401             : {
     402           0 :     vr_vrf_stats_req *req = (vr_vrf_stats_req *)s_req;
     403             : 
     404           0 :     switch (req->h_op) {
     405           0 :     case SANDESH_OP_GET:
     406             :     case SANDESH_OP_DUMP:
     407           0 :         vr_vrf_stats_op(req);
     408           0 :         break;
     409             : 
     410           0 :     default:
     411           0 :         break;
     412             :     }
     413             : 
     414           0 :     return;
     415             : }
     416             : 
     417             : int
     418         127 : inet_route_add(struct rtable_fspec *fs, struct vr_route_req *req)
     419             : {
     420             :     unsigned char pmask, pmask_byte;
     421             :     struct vr_rtable *rtable;
     422             :     struct vrouter *router;
     423             : 
     424         127 :     router = vrouter_get(req->rtr_req.rtr_rid);
     425         127 :     if (!router)
     426           0 :         return -EINVAL;
     427             : 
     428             :     /* V4 and V6 only */
     429         127 :     if (req->rtr_req.rtr_family != AF_INET &&
     430          24 :         req->rtr_req.rtr_family != AF_INET6)
     431           0 :         return -EINVAL;
     432             : 
     433             :     /* There has to be some prefix to add */
     434         127 :     if (!req->rtr_req.rtr_prefix_size)
     435           0 :         return -EINVAL;
     436             : 
     437             : 
     438         127 :     rtable = router->vr_inet_rtable;
     439         127 :     if (!rtable ||
     440         254 :             ((unsigned int)req->rtr_req.rtr_vrf_id >= fs->rtb_max_vrfs) ||
     441         127 :             ((unsigned int)(req->rtr_req.rtr_prefix_len) >
     442         127 :                             (RT_IP_ADDR_SIZE(req->rtr_req.rtr_family)*8)))
     443           0 :         return -EINVAL;
     444             : 
     445             :     /* Zero the bits in prefix, which are set beyond the mask len */
     446         127 :     if (req->rtr_req.rtr_prefix) {
     447             : 
     448         127 :         pmask = req->rtr_req.rtr_prefix_len % 8;
     449         127 :         pmask_byte = req->rtr_req.rtr_prefix_len / 8;
     450             :         /*
     451             :          * pmask_byte identifies the byte bumber from which we need to
     452             :          * reset prefix till the end of prefix. If mask len is not 8 bit
     453             :          * boundary, we calculate that in pmask
     454             :          */
     455         127 :         if (pmask) {
     456           8 :             pmask = ~((1 << (8 - pmask)) - 1);
     457           8 :             req->rtr_req.rtr_prefix[pmask_byte] =
     458           8 :                          req->rtr_req.rtr_prefix[pmask_byte] & pmask;
     459           8 :             pmask_byte++;
     460             :         }
     461         362 :         for (; pmask_byte < RT_IP_ADDR_SIZE(req->rtr_req.rtr_family);
     462         235 :                                                             pmask_byte++) {
     463         235 :             req->rtr_req.rtr_prefix[pmask_byte] = 0;
     464             :         }
     465             :     }
     466             : 
     467         127 :     if (rtable) {
     468         127 :         if (rtable->algo_add)
     469         127 :             return rtable->algo_add(rtable, req);
     470             :         else
     471           0 :             return -1;
     472             :         } else {
     473           0 :         return -1;
     474             :     }
     475             : }
     476             : 
     477             : int
     478         403 : inet_route_del(struct rtable_fspec *fs, struct vr_route_req *req)
     479             : {
     480             :     struct vr_rtable *rtable;
     481             :     struct vrouter *router;
     482             : 
     483         403 :     if (((unsigned int)(req->rtr_req.rtr_prefix_len) >
     484         403 :                             (RT_IP_ADDR_SIZE(req->rtr_req.rtr_family)*8)) ||
     485         403 :             (unsigned int)(req->rtr_req.rtr_vrf_id) >= fs->rtb_max_vrfs)
     486           0 :         return -EINVAL;
     487             : 
     488         403 :     router = vrouter_get(req->rtr_req.rtr_rid);
     489         403 :     if (!router)
     490           0 :         return -EINVAL;
     491             : 
     492         403 :     rtable = router->vr_inet_rtable;
     493         403 :     if (!rtable ||
     494         403 :             (unsigned int)req->rtr_req.rtr_vrf_id >= fs->rtb_max_vrfs)
     495           0 :         return -EINVAL;
     496             : 
     497         403 :     return rtable->algo_del(rtable, req);
     498             : }
     499             : 
     500             : static void
     501         106 : inet_rtb_family_deinit(struct rtable_fspec *fs, struct vrouter *router,
     502             :                                                         bool soft_reset)
     503             : {
     504         106 :     if (router->vr_inet_rtable) {
     505          53 :         fs->algo_deinit(router->vr_inet_rtable, fs, soft_reset);
     506          53 :         if (!soft_reset) {
     507          53 :             vr_free(router->vr_inet_rtable, VR_ROUTE_TABLE_OBJECT);
     508          53 :             router->vr_inet_rtable = NULL;
     509             :         }
     510             :     }
     511             : 
     512         106 :     return;
     513             : }
     514             : 
     515             : static int
     516         106 : inet_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router)
     517             : {
     518             :     int ret;
     519             : 
     520         106 :     if (!fs->algo_init)
     521           0 :         return 1;
     522             : 
     523         106 :     if (!router->vr_inet_rtable) {
     524          53 :         router->vr_inet_rtable = vr_zalloc(sizeof(struct vr_rtable),
     525             :                 VR_ROUTE_TABLE_OBJECT);
     526          53 :         if (!router->vr_inet_rtable)
     527           0 :             return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, 0);
     528             :     }
     529             : 
     530         106 :     ret = fs->algo_init(router->vr_inet_rtable, fs);
     531         106 :     if (ret)
     532           0 :         return vr_module_error(ret, __FUNCTION__, __LINE__, 0);
     533             : 
     534         106 :     return 0;
     535             : }
     536             : 
     537             : int
     538          92 : bridge_entry_add(struct rtable_fspec *fs, struct vr_route_req *req)
     539             : {
     540             :     struct vrouter *router;
     541             : 
     542          92 :     if (!fs) {
     543           0 :         fs = vr_get_family(AF_BRIDGE);
     544           0 :         if (!fs)
     545           0 :             return -EINVAL;
     546             :     }
     547             : 
     548          92 :     router = vrouter_get(req->rtr_req.rtr_rid);
     549          92 :     if (!router)
     550           0 :         return -EINVAL;
     551             : 
     552          92 :     if (!router->vr_bridge_table ||
     553          92 :             ((unsigned int)req->rtr_req.rtr_vrf_id >= fs->rtb_max_vrfs) ||
     554          92 :             ((unsigned int)(req->rtr_req.rtr_mac_size) != VR_ETHER_ALEN))
     555           0 :         return -EINVAL;
     556             : 
     557          92 :     return router->vr_bridge_table->algo_add(router->vr_bridge_table, req);
     558             : }
     559             : 
     560             : int
     561          87 : bridge_entry_del(struct rtable_fspec *fs, struct vr_route_req *req)
     562             : {
     563             :     struct vrouter *router;
     564             : 
     565          87 :     if ((unsigned int)(req->rtr_req.rtr_mac_size) > 6 ||
     566          87 :             (unsigned int)(req->rtr_req.rtr_vrf_id) >= fs->rtb_max_vrfs)
     567           0 :         return -EINVAL;
     568             : 
     569          87 :     router = vrouter_get(req->rtr_req.rtr_rid);
     570          87 :     if (!router)
     571           0 :         return -EINVAL;
     572             : 
     573          87 :     if (!router->vr_bridge_table ||
     574          87 :             (unsigned int)req->rtr_req.rtr_vrf_id >= fs->rtb_max_vrfs)
     575           0 :         return -EINVAL;
     576             : 
     577          87 :     return router->vr_bridge_table->algo_del(router->vr_bridge_table, req);
     578             : }
     579             : 
     580             : static int
     581          53 : bridge_rtb_family_init(struct rtable_fspec *fs, struct vrouter *router)
     582             : {
     583             :     int ret;
     584          53 :     struct vr_rtable *table = NULL;
     585             : 
     586          53 :     if (router->vr_bridge_table)
     587           0 :         return 0;
     588             : 
     589          53 :     if (fs->algo_init) {
     590          53 :         table = vr_zalloc(sizeof(struct vr_rtable), VR_ROUTE_TABLE_OBJECT);
     591          53 :         if (!table)
     592           0 :             return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, 0);
     593             : 
     594          53 :         ret = fs->algo_init(table, fs);
     595          53 :         if (ret) {
     596           0 :             vr_free(table, VR_ROUTE_TABLE_OBJECT);
     597           0 :             return vr_module_error(ret, __FUNCTION__, __LINE__, 0);
     598             :         }
     599             :     }
     600             : 
     601          53 :     router->vr_bridge_table = table;
     602          53 :     return 0;
     603             : }
     604             : 
     605             : static void
     606          53 : bridge_rtb_family_deinit(struct rtable_fspec *fs, struct vrouter *router,
     607             :         bool soft_reset)
     608             : {
     609          53 :     if (!router->vr_bridge_table) {
     610           0 :         return;
     611             :     }
     612             : 
     613          53 :     fs->algo_deinit(router->vr_bridge_table, fs, soft_reset);
     614             : 
     615          53 :     if (!soft_reset) {
     616          53 :         vr_free(router->vr_bridge_table, VR_ROUTE_TABLE_OBJECT);
     617          53 :         router->vr_bridge_table = NULL;
     618             :     }
     619             : }
     620             : 
     621             : void
     622          53 : vr_fib_exit(struct vrouter *router, bool soft_reset)
     623             : {
     624             :     unsigned int i;
     625             :     struct rtable_fspec *fs;
     626             : 
     627         212 :     for (i = 0; i < ARRAYSIZE(rtable_families); i++) {
     628         159 :         fs = &rtable_families[i];
     629         159 :         fs->rtb_family_deinit(fs, router, soft_reset);
     630             :     }
     631             : 
     632          53 :     return;
     633             : }
     634             : 
     635             : int
     636          53 : vr_fib_mem(struct vrouter *router)
     637             : {
     638          53 :     int i = 0, ret, size;
     639             :     struct rtable_fspec *fs;
     640             : 
     641          53 :     if (vr_vrfs > VR_MAX_VRFS) {
     642           0 :         return vr_module_error(-EINVAL, __FUNCTION__, __LINE__, vr_vrfs);
     643             :     }
     644             : 
     645          53 :     router->vr_max_vrfs = vr_vrfs;
     646             : 
     647          53 :     size = (int)ARRAYSIZE(rtable_families);
     648         212 :     for (i = 0; i < size; i++) {
     649         159 :         fs = &rtable_families[i];
     650         159 :         fs->rtb_max_vrfs = router->vr_max_vrfs;
     651         159 :         ret = fs->rtb_family_init(fs, router);
     652         159 :         if (ret) {
     653           0 :             vr_module_error(ret, __FUNCTION__, __LINE__, 0);
     654           0 :             goto exit_init;
     655             :         }
     656             :     }
     657             : 
     658          53 :     return 0;
     659             : 
     660           0 : exit_init:
     661           0 :     if (!i)
     662           0 :         return ret;
     663             : 
     664           0 :     for (--i, --fs; i >= 0; i--) {
     665           0 :         fs->rtb_family_deinit(fs, router, false);
     666             :     }
     667             : 
     668           0 :     return ret;
     669             : }
     670             : 
     671             : int
     672          53 : vr_fib_init(struct vrouter *router)
     673             : {
     674          53 :     return 0;
     675             : }

Generated by: LCOV version 1.14