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