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

Generated by: LCOV version 1.14