LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dp-core - vrouter.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 38 292 13.0 %
Date: 2026-11-09 02:10:49 Functions: 6 16 37.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * se ts=4;se expandtab
       3             :  *
       4             :  * vrouter.c -- virtual router
       5             :  *
       6             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       7             :  * Copyright Contributors to the OpenSDN project
       8             :  */
       9             : #include <vr_os.h>
      10             : #if defined(__linux__)
      11             : #include <linux/version.h>
      12             : #endif
      13             : #include "vr_types.h"
      14             : #include "vr_sandesh.h"
      15             : #include "vr_message.h"
      16             : #include "vr_cpuid.h"
      17             : #include <vr_packet.h>
      18             : #include <vr_interface.h>
      19             : #include <vr_nexthop.h>
      20             : #include <vr_route.h>
      21             : #include <vr_mpls.h>
      22             : #include <vr_flow.h>
      23             : #include <vr_bridge.h>
      24             : #include <vr_packet.h>
      25             : #include <vr_mirror.h>
      26             : #include <vr_vrf_table.h>
      27             : #include <vr_vxlan.h>
      28             : #include <vr_qos.h>
      29             : #include <vr_offloads_dp.h>
      30             : 
      31             : static struct vrouter router;
      32             : struct host_os *vrouter_host;
      33             : struct vr_offload_ops *offload_ops;
      34             : void (*vr_init_cpuid)(struct vr_cpu_type_t *vr_cpu_type) = NULL;
      35             : struct vr_cpu_type_t vr_cpu_type = {0};
      36             : static bool vr_ipv6_underlay_enabled = false;
      37             : bool vr_force_ipv6_underlay_enabled = false;
      38             : 
      39             : extern struct host_os *vrouter_get_host(void);
      40             : extern int vr_stats_init(struct vrouter *);
      41             : extern void vr_stats_exit(struct vrouter *, bool);
      42             : #if defined (__linux__) && defined(__KERNEL__)
      43             : extern int vr_shmem_init(void);
      44             : #endif
      45             : 
      46             : extern unsigned int vr_flow_entries;
      47             : extern unsigned int vr_oflow_entries;
      48             : extern unsigned int vr_bridge_entries;
      49             : extern unsigned int vr_bridge_oentries;
      50             : extern unsigned int vif_bridge_entries;
      51             : extern unsigned int vif_bridge_oentries;
      52             : extern unsigned int vr_pkt_droplog_bufsz;
      53             : extern unsigned int vr_pkt_droplog_buf_en;
      54             : extern unsigned int vr_pkt_droplog_sysctl_en;
      55             : extern const char *ContrailBuildInfo;
      56             : extern unsigned int vr_uncond_close_flow_on_tcp_rst;
      57             : extern void *vr_flow_table;
      58             : extern void *vr_oflow_table;
      59             : extern void *vr_bridge_table;
      60             : extern void *vr_obridge_table;
      61             : void vrouter_exit(bool);
      62             : 
      63             : volatile bool vr_not_ready = true;
      64             : 
      65             : /* Below hugepage req recv and resp variables are added for debug purpose */
      66             : int vr_hpage_req_recv = 0;
      67             : int vr_hpage_req_resp = 0;
      68             : int vr_hpage_mem_fail = 0;
      69             : int vr_genetlink_group_id = 0;
      70             : 
      71             : unsigned int vr_memory_alloc_checks = 0;
      72             : unsigned int vr_priority_tagging = 0;
      73             : 
      74             : struct vr_module {
      75             :     char *mod_name;
      76             :     int error;
      77             :     const char *error_func;
      78             :     int error_line;
      79             :     int error_data;
      80             :     int (*init)(struct vrouter *);
      81             :     void (*exit)(struct vrouter *, bool);
      82             :     void (*shut)(struct vrouter *);
      83             :     int (*mem)(struct vrouter *);
      84             : };
      85             : 
      86             : struct vr_module *module_under_init;
      87             : 
      88             : static struct vr_module modules[] = {
      89             :     {
      90             :         .mod_name       =       "Stats",
      91             :         .init           =       vr_stats_init,
      92             :         .exit           =       vr_stats_exit,
      93             :     },
      94             :     {
      95             :         .mod_name       =       "Nexthop",
      96             :         .init           =       vr_nexthop_init,
      97             :         .exit           =       vr_nexthop_exit,
      98             :     },
      99             :     {
     100             :         .mod_name       =       "Fib",
     101             :         .init           =       vr_fib_init,
     102             :         .mem            =       vr_fib_mem,
     103             :         .exit           =       vr_fib_exit,
     104             :     },
     105             :     {
     106             :         .mod_name       =       "Mpls",
     107             :         .init           =       vr_mpls_init,
     108             :         .exit           =       vr_mpls_exit,
     109             :     },
     110             :     {
     111             :         .mod_name       =       "Flow",
     112             :         .init           =       vr_flow_init,
     113             :         .mem            =       vr_flow_mem,
     114             :         .exit           =       vr_flow_exit,
     115             :     },
     116             :     {
     117             :         .mod_name       =       "Mirror",
     118             :         .init           =       vr_mirror_init,
     119             :         .exit           =       vr_mirror_exit,
     120             :     },
     121             :     {
     122             :         .mod_name       =       "Vxlan",
     123             :         .init           =       vr_vxlan_init,
     124             :         .exit           =       vr_vxlan_exit,
     125             :     },
     126             :     {
     127             :         .mod_name       =       "QOS",
     128             :         .init           =       vr_qos_init,
     129             :         .exit           =       vr_qos_exit,
     130             :     },
     131             :     {
     132             :         .mod_name       =       "Offloads",
     133             :         .init           =       vr_offloads_init,
     134             :         .exit           =       vr_offloads_exit,
     135             :     },
     136             :     {
     137             :         .mod_name       =       "Vrf",
     138             :         .init           =       vr_vrf_table_init,
     139             :         .exit           =       vr_vrf_table_exit,
     140             :     },
     141             :     {
     142             :         .mod_name       =       "Interface",
     143             :         .init           =       vr_interface_init,
     144             :         .exit           =       vr_interface_exit,
     145             :         .shut           =       vr_interface_shut,
     146             :     },
     147             : };
     148             : 
     149             : 
     150             : #define VR_NUM_MODULES  (sizeof(modules) / sizeof(modules[0]))
     151             : /*
     152             :  * TODO For BSD we turn off all performance tweaks for now, it will
     153             :  * be implemented later.
     154             :  */
     155             : /*
     156             :  * Enable changes for better performance
     157             :  */
     158             : #if defined(__linux__)
     159             : int vr_perfr = 1;    /* GRO */
     160             : int vr_perfs = 1;    /* segmentation in software */
     161             : #endif
     162             : 
     163             : /*
     164             :  * Enable MPLS over UDP globally
     165             :  */
     166             : int vr_mudp = 0;
     167             : 
     168             : /*
     169             :  * TCP MSS adjust settings
     170             :  */
     171             : #if defined(__linux__)
     172             : int vr_from_vm_mss_adj = 1; /* adjust TCP MSS on packets from VM */
     173             : int vr_to_vm_mss_adj = 1;   /* adjust TCP MSS on packet sent to VM */
     174             : #endif
     175             : /*
     176             :  * Following sysctls are to enable RPS. Based on empirical results,
     177             :  * performing RPS immediately after packets arrive on a physical interface
     178             :  * gives the best bidirectional throughput (as opposed to performing
     179             :  * RPS after pulling inner headers on the CPU core which received the
     180             :  * interrupt from the physical interface). This is probably because
     181             :  * more work can happen in parallel on multiple cores in the former case.
     182             :  * So, vr_perfr1 is set to 0 and vr_perfr3 is set to 1. vr_perfr2 is always
     183             :  * set as the vhost thread is usually scheduled on the CPU which received
     184             :  * the packet after GRO. Setting vr_perfr2 allows us to influence the
     185             :  * scheduling of the vhost thread to some extent (otherwise the scheduler
     186             :  * can sometimes make sub-optimal choices such as scheduling it on the CPU
     187             :  * which receives interrupts from the physical interface). vrouter ensures
     188             :  * that the receive processing happens on multiple cores which are in the
     189             :  * same NUMA node as the physical interface i.e. the CPU core which receives
     190             :  * packets from the physical interface is different from the CPU core which
     191             :  * does vrouter RX processing. A third CPU core does GRO processing (assuming
     192             :  * that enough cores are available). Also, hyper-thread siblings of the
     193             :  * above 3 cores are not used by vrouter for RX processing.
     194             :  */
     195             : #if defined(__linux__)
     196             : 
     197             : int vr_perfr1 = 0;   /* RPS after pulling inner headers */
     198             : int vr_perfr2 = 1;   /* RPS after GRO on pkt1 interface */
     199             : int vr_perfr3 = 1;   /* RPS from physical interface rx handler */
     200             : int vr_perfp = 1;    /* pull inner headers, faster version */
     201             : 
     202             : int vr_use_linux_br = 0; /* nop if netdev_rx_handler_register() is used */
     203             : 
     204             : #endif
     205             : /*
     206             :  * Following sysctls can be set if vrouter shouldn't pick a CPU for RPS
     207             :  * core based on a hash of the received packet. Turned off by default.
     208             :  */
     209             : int vr_perfq1 = 0;   /* CPU to send packets to if vr_perfr1 is 1 */
     210             : int vr_perfq2 = 0;   /* CPU to send packets to if vr_perfr2 is 1 */
     211             : int vr_perfq3 = 0;   /* CPU to send packets to if vr_perfr3 is 1 */
     212             : 
     213             : /* Should NIC perform checksum offload for outer UDP header? */
     214             : int vr_udp_coff = 0;
     215             : 
     216             : int
     217           0 : vr_module_error(int error, const char *func,
     218             :         int line, int mod_specific)
     219             : {
     220           0 :     struct vr_module *module = module_under_init;
     221             : 
     222             :     /*
     223             :      * set the error only if it was not set earlier. sometimes, the module
     224             :      * init can call functions which fail and set the error. In those cases,
     225             :      * for the sake of consistency, the module init should also be able to
     226             :      * call this function without overwriting the set error data
     227             :      */
     228           0 :     if (module && !module->error) {
     229           0 :         module->error = error;
     230           0 :         module->error_func = func;
     231           0 :         module->error_line = line;
     232           0 :         module->error_data = mod_specific;
     233             :     }
     234             : 
     235           0 :     return error;
     236             : }
     237             : 
     238             : static void
     239           0 : vr_module_debug_dump(void)
     240             : {
     241           0 :     struct vr_module *module = module_under_init;
     242             : 
     243           0 :     if (!module)
     244           0 :         return;
     245             : 
     246           0 :     vr_printf("vrouter (%s): Init failed at %s:%d with return %d (data %d)\n",
     247             :             module->mod_name, module->error_func, module->error_line,
     248             :             module->error, module->error_data);
     249             : 
     250             :     /* reset error data */
     251           0 :     module->error = 0;
     252           0 :     module->error_func = NULL;
     253           0 :     module->error_line = -1;
     254           0 :     module->error_data = 0;
     255             : 
     256           0 :     return;
     257             : }
     258             : 
     259             : struct vrouter *
     260  1969749792 : vrouter_get(unsigned int vr_id)
     261             : {
     262  1969749792 :     return &router;
     263             : }
     264             : 
     265             : unsigned int
     266         332 : vrouter_generation_num_get(struct vrouter *router)
     267             : {
     268         332 :     return ++router->vr_generation_num;
     269             : }
     270             : 
     271             : static void
     272           0 : vrouter_ops_destroy(vrouter_ops *req)
     273             : {
     274           0 :     if (!req)
     275           0 :         return;
     276             : 
     277           0 :     if (req->vo_build_info) {
     278           0 :         vr_free(req->vo_build_info, VR_BUILD_INFO_OBJECT);
     279           0 :         req->vo_build_info = NULL;
     280             :     }
     281             : 
     282           0 :     if (req->vo_log_type_enable) {
     283           0 :         vr_free(req->vo_log_type_enable, VR_LOG_TYPES_OBJECT);
     284           0 :         req->vo_log_type_enable = NULL;
     285             :     }
     286             : 
     287           0 :     vr_free(req, VR_VROUTER_REQ_OBJECT);
     288             : 
     289           0 :     return;
     290             : }
     291             : 
     292             : static vrouter_ops *
     293           0 : vrouter_ops_get(void)
     294             : {
     295             :     vrouter_ops *req;
     296             : 
     297           0 :     req = vr_zalloc(sizeof(*req), VR_VROUTER_REQ_OBJECT);
     298           0 :     if (!req)
     299           0 :         return NULL;
     300             : 
     301           0 :     req->vo_build_info = vr_zalloc(strlen(ContrailBuildInfo) + 1,
     302             :             VR_BUILD_INFO_OBJECT);
     303           0 :     if (!req->vo_build_info) {
     304           0 :         vr_free(req, VR_VROUTER_REQ_OBJECT);
     305           0 :         return NULL;
     306             :     }
     307             : 
     308           0 :     return req;
     309             : }
     310             : 
     311             : static void
     312           0 : vrouter_ops_get_process(void *s_req)
     313             : {
     314           0 :     int ret = 0;
     315             :     struct vrouter *router;
     316           0 :     vrouter_ops *req = (vrouter_ops *)s_req;
     317           0 :     vrouter_ops *resp = NULL;
     318             : 
     319           0 :     if (req->h_op != SANDESH_OP_GET) {
     320           0 :         ret = -EOPNOTSUPP;
     321           0 :         goto generate_response;
     322             :     }
     323             : 
     324           0 :     router = vrouter_get(req->vo_rid);
     325           0 :     if (!router) {
     326           0 :         ret = -EINVAL;
     327           0 :         goto generate_response;
     328             :     }
     329             : 
     330           0 :     resp = vrouter_ops_get();
     331           0 :     if (!resp) {
     332           0 :         ret = -ENOMEM;
     333           0 :         goto generate_response;
     334             :     }
     335             : 
     336             :     /* Startup command line parameters */
     337           0 :     resp->vo_interfaces = router->vr_max_interfaces;
     338           0 :     resp->vo_vrfs = router->vr_max_vrfs;
     339           0 :     resp->vo_mpls_labels = router->vr_max_labels;
     340           0 :     resp->vo_nexthops = router->vr_max_nexthops;
     341           0 :     resp->vo_bridge_entries = vr_bridge_entries;
     342           0 :     resp->vo_oflow_bridge_entries = vr_bridge_oentries;
     343           0 :     resp->vo_flow_entries = vr_flow_entries;
     344           0 :     resp->vo_oflow_entries = vr_oflow_entries;
     345           0 :     resp->vo_mirror_entries = router->vr_max_mirror_indices;
     346           0 :     resp->vo_vif_bridge_entries = vif_bridge_entries;
     347           0 :     resp->vo_vif_oflow_bridge_entries = vif_bridge_oentries;
     348           0 :     resp->vo_pkt_droplog_bufsz = vr_pkt_droplog_bufsz;
     349           0 :     resp->vo_pkt_droplog_buf_en = vr_pkt_droplog_buf_en;
     350             : 
     351             :     /* Runtime parameters adjustable via sysctl or the vrouter utility */
     352           0 :     resp->vo_perfr = vr_perfr;
     353           0 :     resp->vo_perfs = vr_perfs;
     354           0 :     resp->vo_from_vm_mss_adj = vr_from_vm_mss_adj;
     355           0 :     resp->vo_to_vm_mss_adj = vr_to_vm_mss_adj;
     356           0 :     resp->vo_perfr1 = vr_perfr1;
     357           0 :     resp->vo_perfr2 = vr_perfr2;
     358           0 :     resp->vo_perfr3 = vr_perfr3;
     359           0 :     resp->vo_perfp = vr_perfp;
     360           0 :     resp->vo_perfq1 = vr_perfq1;
     361           0 :     resp->vo_perfq2 = vr_perfq2;
     362           0 :     resp->vo_perfq3 = vr_perfq3;
     363           0 :     resp->vo_udp_coff = vr_udp_coff;
     364           0 :     resp->vo_flow_hold_limit = vr_flow_hold_limit;
     365           0 :     resp->vo_mudp = vr_mudp;
     366           0 :     resp->vo_packet_dump = 0;
     367           0 :     resp->vo_pkt_droplog_en = vr_pkt_droplog_sysctl_en;
     368           0 :     resp->vo_pkt_droplog_min_en = vr_pkt_droplog_min_sysctl_en;
     369           0 :     resp->vo_uncond_close_flow_on_tcp_rst = vr_uncond_close_flow_on_tcp_rst;
     370           0 :     resp->vo_genetlink_group_id = vr_genetlink_group_id;
     371             : 
     372           0 :     if(vr_get_dump_packets != NULL) {
     373           0 :         resp->vo_packet_dump = vr_get_dump_packets();
     374             :     }
     375             : 
     376             :     /* Build info */
     377           0 :     memcpy(resp->vo_build_info, ContrailBuildInfo,
     378           0 :            strlen(ContrailBuildInfo)+1);
     379             : 
     380             :     /* Logging entries */
     381           0 :     resp->vo_log_level = vr_get_log_level();
     382           0 :     resp->vo_log_type_enable =
     383           0 :         vr_get_enabled_log_types(&resp->vo_log_type_enable_size);
     384             : 
     385             : 
     386             :     /* Used entries */
     387           0 :     resp->vo_flow_used_entries =
     388           0 :         vr_flow_table_used_total_entries(router);
     389           0 :     resp->vo_flow_used_oentries =
     390           0 :        vr_flow_table_used_oflow_entries(router);
     391             : 
     392           0 :     resp->vo_bridge_used_entries =
     393           0 :         vr_bridge_table_used_total_entries(router);
     394           0 :     resp->vo_bridge_used_oentries =
     395           0 :         vr_bridge_table_used_oflow_entries(router);
     396             : 
     397           0 :     vr_flow_get_burst_params(router, &resp->vo_burst_tokens,
     398           0 :             &resp->vo_burst_interval, &resp->vo_burst_step);
     399             : 
     400           0 :     resp->vo_memory_alloc_checks = vr_memory_alloc_checks;
     401           0 :     resp->vo_priority_tagging = vr_priority_tagging;
     402             : 
     403           0 :     req = resp;
     404           0 : generate_response:
     405           0 :     if (ret)
     406           0 :         req = NULL;
     407             : 
     408           0 :     vr_message_response(VR_VROUTER_OPS_OBJECT_ID, req, ret, false);
     409           0 :     if (resp)
     410           0 :         vrouter_ops_destroy(resp);
     411             : 
     412           0 :     return;
     413             : }
     414             : 
     415             : /**
     416             :  * A handler for control messages.
     417             :  *
     418             :  * Currently logging control and runtime parameters are supported.
     419             :  * Setting runtime parameters is also possible via sysctl.
     420             :  *
     421             :  * @param s_req Received request to be processed.
     422             :  */
     423             : static void
     424           0 : vrouter_ops_add_process(void *s_req)
     425             : {
     426             :     int i;
     427             : 
     428           0 :     vrouter_ops *req = (vrouter_ops *)s_req;
     429             : 
     430             :     /* Log levels */
     431           0 :     if (req->vo_log_level)
     432           0 :         vr_set_log_level(req->vo_log_level);
     433             : 
     434           0 :     if (req->vo_log_type_enable_size)
     435           0 :         for (i = 0; i < req->vo_log_type_enable_size; ++i)
     436           0 :             vr_set_log_type(req->vo_log_type_enable[i], 1);
     437             : 
     438           0 :     if (req->vo_log_type_disable_size)
     439           0 :         for (i = 0; i < req->vo_log_type_disable_size; ++i)
     440           0 :             vr_set_log_type(req->vo_log_type_disable[i], 0);
     441             : 
     442             :     /* Runtime parameters */
     443           0 :     if (req->vo_packet_dump != -1 && vr_set_dump_packets != NULL)
     444           0 :         vr_set_dump_packets(req->vo_packet_dump);
     445           0 :     if (req->vo_perfr != -1)
     446           0 :         vr_perfr = req->vo_perfr;
     447           0 :     if (req->vo_perfs != -1)
     448           0 :         vr_perfs = req->vo_perfs;
     449           0 :     if (req->vo_from_vm_mss_adj != -1)
     450           0 :         vr_from_vm_mss_adj = req->vo_from_vm_mss_adj;
     451           0 :     if (req->vo_to_vm_mss_adj != -1)
     452           0 :         vr_to_vm_mss_adj = req->vo_to_vm_mss_adj;
     453           0 :     if (req->vo_perfr1 != -1)
     454           0 :         vr_perfr1 = req->vo_perfr1;
     455           0 :     if (req->vo_perfr2 != -1)
     456           0 :         vr_perfr2 = req->vo_perfr2;
     457           0 :     if (req->vo_perfr3 != -1)
     458           0 :         vr_perfr3 = req->vo_perfr3;
     459           0 :     if (req->vo_perfp != -1)
     460           0 :         vr_perfp = req->vo_perfp;
     461           0 :     if (req->vo_perfq1 != -1)
     462           0 :         vr_perfq1 = req->vo_perfq1;
     463           0 :     if (req->vo_perfq2 != -1)
     464           0 :         vr_perfq2 = req->vo_perfq2;
     465           0 :     if (req->vo_perfq3 != -1)
     466           0 :         vr_perfq3 = req->vo_perfq3;
     467           0 :     if (req->vo_udp_coff != -1)
     468           0 :         vr_udp_coff = req->vo_udp_coff;
     469           0 :     if (req->vo_flow_hold_limit != -1)
     470           0 :         vr_flow_hold_limit = (unsigned int)req->vo_flow_hold_limit;
     471           0 :     if (req->vo_mudp != -1)
     472           0 :         vr_mudp = req->vo_mudp;
     473           0 :     vr_flow_set_burst_params(vrouter_get(req->vo_rid), req->vo_burst_tokens,
     474             :             req->vo_burst_interval, req->vo_burst_step);
     475             : 
     476           0 :     vr_priority_tagging = req->vo_priority_tagging;
     477             : 
     478             :     /* Neither of currently called functions signals an error. Just send OK
     479             :      * response here for now. */
     480           0 :     vr_send_response(0);
     481           0 : }
     482             : 
     483             : void
     484          53 : vrouter_exit(bool soft_reset)
     485             : {
     486             :     int i;
     487             : 
     488         636 :     for (i = 0; i < (int)VR_NUM_MODULES; i++)
     489         583 :         if (modules[i].shut)
     490          53 :             modules[i].shut(&router);
     491             : 
     492             :     /* Mark that vrouter is no more ready as shut is already done */
     493          53 :     vr_not_ready = true;
     494             : 
     495             :     /* Flush the previous ashynchronous events, before init */
     496          53 :     if (vr_soft_reset)
     497          53 :         vr_soft_reset(&router);
     498             : 
     499         636 :     for (i = VR_NUM_MODULES - 1; i >= 0; --i) {
     500         583 :         modules[i].exit(&router, soft_reset);
     501             :     }
     502             : 
     503             :     /*
     504             :      * This is necessary on operating systems that don't
     505             :      * unload the binary on exit.
     506             :      * When soft reset is happening we must not reinitialize
     507             :      * vrouter struct.
     508             :      */
     509          53 :     if (!soft_reset) {
     510          53 :         memset(&router, 0, sizeof(router));
     511             :     }
     512             : 
     513          53 :     return;
     514             : }
     515             : 
     516             : int
     517          53 : vrouter_init(void)
     518             : {
     519             :     unsigned int i;
     520             :     int ret;
     521             : 
     522             :     /* init CPU id struct*/
     523          53 :     if (vr_init_cpuid != NULL)
     524          53 :         vr_init_cpuid(&vr_cpu_type);
     525             : 
     526          53 :     vrouter_host = vrouter_get_host();
     527          53 :     if (!vrouter_host && (ret = -ENOMEM))
     528           0 :         goto init_fail;
     529             : 
     530         636 :     for (i = 0; i < VR_NUM_MODULES; i++) {
     531         583 :         module_under_init = &modules[i];
     532         583 :         ret = modules[i].init(&router);
     533         583 :         if (ret) {
     534           0 :             vr_printf("vrouter module %u init error (%d)\n", i, ret);
     535           0 :             goto init_fail;
     536             :         }
     537             :         // actually, this is not executed in the linux kernel mode
     538             :         // in most cases
     539         583 :         if (vr_hpage_mem_fail || !vr_huge_page_config) {
     540         583 :             if (modules[i].mem) {
     541         106 :                 ret = modules[i].mem(&router);
     542         106 :                 if (ret) {
     543           0 :                     vr_printf("vrouter module %u mem error (%d)\n", i, ret);
     544           0 :                     goto init_fail;
     545             :                 }
     546             :             }
     547             :         }
     548             :     }
     549          53 :     vr_hpage_mem_fail = 0;
     550          53 :     module_under_init = NULL;
     551          53 :     vr_not_ready = false;
     552          53 :     return 0;
     553             : 
     554           0 : init_fail:
     555           0 :     vrouter_exit(false);
     556           0 :     vr_module_debug_dump();
     557           0 :     module_under_init = NULL;
     558             : 
     559           0 :     return ret;
     560             : }
     561             : 
     562             : static int
     563           0 : vrouter_soft_reset(void)
     564             : {
     565           0 :     int ret = 0;
     566           0 :     vrouter_exit(true);
     567           0 :     ret = vrouter_init();
     568           0 :     if (!ret)
     569           0 :         ret = vr_offload_soft_reset();
     570           0 :     return ret;
     571             : }
     572             : 
     573             : void
     574           0 : vrouter_ops_process(void *s_req)
     575             : {
     576             :     int ret;
     577             : 
     578           0 :     vrouter_ops *ops = (vrouter_ops *)s_req;
     579             : 
     580           0 :     switch (ops->h_op) {
     581           0 :     case SANDESH_OP_RESET:
     582           0 :         vr_printf("vrouter soft reset start\n");
     583           0 :         ret = vrouter_soft_reset();
     584           0 :         vr_printf("vrouter soft reset done (%d)\n", ret);
     585           0 :         break;
     586             : 
     587           0 :     case SANDESH_OP_GET:
     588           0 :         vrouter_ops_get_process(s_req);
     589           0 :         return;
     590             : 
     591           0 :     case SANDESH_OP_ADD:
     592           0 :         vrouter_ops_add_process(s_req);
     593           0 :         return;
     594             : 
     595           0 :     default:
     596           0 :         ret = -EOPNOTSUPP;
     597             :     }
     598             : 
     599           0 :     vr_send_response(ret);
     600             : 
     601           0 :     return;
     602             : }
     603             : 
     604           0 : static int vr_shmem_open(const struct vrouter *router) {
     605             : #if defined (__linux__) && defined(__KERNEL__)
     606             :     if (router->vr_flow_table != NULL &&
     607             :         router->vr_bridge_table != NULL) {
     608             :         printk ("tables are in memory\n");
     609             :         return vr_shmem_init();
     610             :     }
     611             :     return -1;
     612             : #endif
     613           0 :     return 0;
     614             : }
     615             : 
     616             : void
     617           0 : vr_hugepage_config_process(void *s_req)
     618             : {
     619           0 :     int i, ret = -EEXIST, mret = 0;
     620             :     vr_hugepage_config hcfg_resp;
     621           0 :     vr_hugepage_config *req= (vr_hugepage_config *)s_req;
     622           0 :     struct vrouter *router = vrouter_get(0);
     623             : 
     624             :     /* Debug purpose: Increment below variable when we get hugepage req from agent */
     625           0 :     vr_hpage_req_recv++;
     626             : 
     627             :     /* Only addition of huge pages is supported */
     628           0 :     if (req->vhp_op != SANDESH_OP_ADD) {
     629           0 :         vr_send_response(-EOPNOTSUPP);
     630           0 :         return;
     631             :     }
     632             : 
     633             :     /* Invoke huge page configuration only if a segment exists */
     634           0 :     if (vr_huge_page_config) {
     635           0 :         ret = vr_huge_page_config(req->vhp_mem, req->vhp_mem_size,
     636           0 :                                   req->vhp_psize, req->vhp_psize_size,
     637           0 :                                   req->vhp_mem_sz, req->vhp_mem_sz_size,
     638             :                                   req->vhp_file_paths, req->vhp_file_path_sz);
     639             :     }
     640             : 
     641           0 :     if (ret != -EEXIST) {
     642           0 :         for (i = 0; i < (int)VR_NUM_MODULES; i++) {
     643           0 :             if (modules[i].mem)  {
     644           0 :                 mret = modules[i].mem(router);
     645           0 :                 if (mret)
     646           0 :                     break;
     647             :             }
     648             :         }
     649             :     }
     650             : 
     651           0 :     memset(&hcfg_resp, 0, sizeof(hcfg_resp));
     652           0 :     hcfg_resp.vhp_op = req->vhp_op;
     653             : 
     654             :     /*
     655             :      * If we fail to allocate memory both in huge pages and as well
     656             :      * regular respond with VR_HPAGE_CFG_RESP_MEM_FAILURE. Return status
     657             :      * in vrouter_response would be an error value. If memory allocation
     658             :      * succeds in either the huge pages or regular, return status is
     659             :      * going to be "0" and response code gives the details of the
     660             :      * allocation
     661             :      */
     662             : 
     663           0 :     switch (ret)  {
     664           0 :     case 0:
     665           0 :         if (!mret)
     666           0 :             hcfg_resp.vhp_resp = VR_HPAGE_CFG_RESP_HPAGE_SUCCESS;
     667           0 :         break;
     668             : 
     669           0 :     case -EINVAL:
     670           0 :         if (!mret) {
     671           0 :             hcfg_resp.vhp_resp = VR_HPAGE_CFG_RESP_INVALID_ARG_MEM_INITED;
     672           0 :             ret = 0;
     673             :         }
     674           0 :         break;
     675             : 
     676           0 :     case -EEXIST:
     677           0 :         hcfg_resp.vhp_resp = VR_HPAGE_CFG_RESP_MEM_ALREADY_INITED;
     678           0 :         break;
     679             : 
     680           0 :     case -ENOMEM:
     681           0 :         if (!mret) {
     682           0 :             hcfg_resp.vhp_resp = VR_HPAGE_CFG_RESP_HPAGE_FAILURE_MEM_INITED;
     683           0 :             ret = 0;
     684             :         }
     685           0 :         break;
     686             : 
     687           0 :     case -E2BIG:
     688           0 :         if (!mret) {
     689           0 :             hcfg_resp.vhp_resp = VR_HPAGE_CFG_RESP_HPAGE_PARTIAL_SUCCESS;
     690           0 :             ret = 0;
     691             :         }
     692           0 :         break;
     693             : 
     694           0 :     default:
     695           0 :         ret = -EINVAL;
     696           0 :         break;
     697             :     }
     698             : 
     699           0 :     if (mret) {
     700           0 :         hcfg_resp.vhp_resp = VR_HPAGE_CFG_RESP_MEM_FAILURE;
     701           0 :         ret = mret;
     702             :         /* cleaning up partially allocated memory. */
     703           0 :         for (i = 0; i < (int)VR_NUM_MODULES; i++) {
     704           0 :             if (modules[i].mem)  {
     705           0 :                 modules[i].exit(router, false);
     706             :             }
     707             :         }
     708           0 :         vr_hpage_mem_fail = mret;
     709             :     }
     710             : 
     711           0 :     if (ret == 0) {
     712           0 :         ret = vr_shmem_open(router);
     713           0 :         if (ret != 0) {
     714           0 :             hcfg_resp.vhp_resp = VR_HPAGE_CFG_RESP_SHMEM_FAILURE;
     715             :         }
     716             :     }
     717             : 
     718             :     /* Debug purpose: Increment below variable before sending response */
     719           0 :     vr_hpage_req_resp++;
     720           0 :     vr_printf("Huge page req_recv_cntr:%d resp_cntr:%d resp: %d ret: %d\n", vr_hpage_req_recv,
     721             :             vr_hpage_req_resp, hcfg_resp.vhp_resp, ret);
     722             : 
     723           0 :     vr_message_response(VR_HPAGE_CFG_OBJECT_ID, &hcfg_resp, ret,
     724             :                 false);
     725             : 
     726           0 :     return;
     727             : }
     728             : 
     729             : bool
     730          13 : vr_is_ipv6_underlay_enabled(void)
     731             : {
     732          13 :     return vr_ipv6_underlay_enabled ||
     733             :         vr_force_ipv6_underlay_enabled;
     734             : }
     735             : 
     736             : void
     737           9 : vr_set_ipv6_underlay_enabled(void)
     738             : {
     739           9 :     vr_ipv6_underlay_enabled = true;
     740           9 : }

Generated by: LCOV version 1.14