2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include <vnet/plugin/plugin.h>
17 #include <vlib/vlib.h>
18 #include <vnet/vnet.h>
19 #include <vnet/pg/pg.h>
20 #include <vppinfra/error.h>
21 #include <vppinfra/pool.h>
23 #include <vnet/ip/ip.h>
24 #include <vnet/ethernet/ethernet.h>
27 #include "cnat_global.h"
29 #include "cnat_config.h"
30 #include "cnat_logging.h"
31 #include "cnat_config_api.h"
32 #include "cnat_show_api.h"
33 #include "cnat_show_response.h"
34 #include "cnat_ipv4_udp.h"
35 #include "cnat_common_api.h"
37 #include <arpa/inet.h>
40 u32 cached_next_index;
42 /* inside, outside interface handles */
43 u32 * inside_sw_if_index_table;
44 u32 * outside_sw_if_index_table;
46 /* convenience variables */
47 vlib_main_t * vlib_main;
48 vnet_main_t * vnet_main;
49 u8 cnat_db_initalized;
50 } vcgn_classify_main_t;
53 /* $$$$ fill in with per-pkt trace data */
58 } vcgn_classify_trace_t;
60 #define FIND_MY_VRF_USING_I_VRF_ID \
61 my_vrfmap_found = 0; \
62 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ \
63 if (my_vrfmap->i_vrf_id == i_vrf_id) { \
64 my_vrfmap_found = 1; \
65 my_vrfmap_temp = my_vrfmap; \
71 /* packet trace format function */
72 static u8 * format_swap_trace (u8 * s, va_list * args)
74 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
75 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
76 vcgn_classify_trace_t * t = va_arg (*args, vcgn_classify_trace_t *);
78 s = format (s, "VCGN_CLASSIFY: dst %U dst_port %d sw_if_index %d next %d",
79 format_ip4_address, (ip4_header_t *) &t->orig_dst_address,
80 clib_net_to_host_u16(t->orig_dst_port),
81 t->sw_if_index, t->next_index);
85 vcgn_classify_main_t vcgn_classify_main;
87 vlib_node_registration_t vcgn_classify_node;
89 #define foreach_vcgn_classify_error \
90 _(PACKETS_RECEIVED, "total packets received") \
91 _(V4_PACKETS_PROCESSED, "ipv4 packets processed for vCGN") \
92 _(V4_PACKETS_PUNTED, "ipv4 packets punted") \
93 _(V6_PACKETS_PUNTED, "ipv6 packets punted") \
94 _(MPLS_PACKETS_PUNTED, "mpls unicast packets punted") \
95 _(ETH_PACKETS_PUNTED, "ethernet packets punted")
99 #define _(sym,str) VCGN_CLASSIFY_ERROR_##sym,
100 foreach_vcgn_classify_error
102 VCGN_CLASSIFY_N_ERROR,
103 } vcgn_classify_error_t;
105 static char * vcgn_classify_error_strings[] = {
106 #define _(sym,string) string,
107 foreach_vcgn_classify_error
112 * To drop a pkt and increment one of the previous counters:
114 * set b0->error = error_node->errors[VCGN_CLASSIFY_ERROR_EXAMPLE];
115 * set next0 to a disposition index bound to "error-drop".
117 * To manually increment the specific counter VCGN_CLASSIFY_ERROR_EXAMPLE:
119 * vlib_node_t *n = vlib_get_node (vm, vcgn_classify.index);
120 * u32 node_counter_base_index = n->error_heap_index;
121 * vlib_error_main_t * em = &vm->error_main;
122 * em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_EXAMPLE] += 1;
127 VCGN_CLASSIFY_NEXT_IP4_INPUT,
128 VCGN_CLASSIFY_NEXT_IP6_INPUT,
129 VCGN_CLASSIFY_NEXT_MPLS_INPUT,
130 VCGN_CLASSIFY_NEXT_ETHERNET_INPUT,
131 VCGN_CLASSIFY_NEXT_UDP_INSIDE,
132 VCGN_CLASSIFY_NEXT_UDP_OUTSIDE,
133 VCGN_CLASSIFY_NEXT_TCP_INSIDE,
134 VCGN_CLASSIFY_NEXT_TCP_OUTSIDE,
135 VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE,
136 VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE,
137 VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE,
138 VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE,
139 VCGN_CLASSIFY_N_NEXT,
140 } vcgn_classify_next_t;
143 vcgn_classify_node_fn (vlib_main_t * vm,
144 vlib_node_runtime_t * node,
145 vlib_frame_t * frame)
147 u32 n_left_from, * from, * to_next;
148 vcgn_classify_next_t next_index;
149 vcgn_classify_main_t * vcm = &vcgn_classify_main;
150 vlib_node_t *n = vlib_get_node (vm, vcgn_classify_node.index);
151 u32 node_counter_base_index = n->error_heap_index;
152 vlib_error_main_t * em = &vm->error_main;
156 from = vlib_frame_vector_args (frame);
157 n_left_from = frame->n_vectors;
158 next_index = node->cached_next_index;
160 while (n_left_from > 0)
164 vlib_get_next_frame (vm, node, next_index,
165 to_next, n_left_to_next);
168 while (n_left_from >= 4 && n_left_to_next >= 2)
171 vlib_buffer_t * b0, * b1;
173 u32 sw_if_index0, sw_if_index1;
175 /* Prefetch next iteration. */
177 vlib_buffer_t * p2, * p3;
179 p2 = vlib_get_buffer (vm, from[2]);
180 p3 = vlib_get_buffer (vm, from[3]);
182 vlib_prefetch_buffer_header (p2, LOAD);
183 vlib_prefetch_buffer_header (p3, LOAD);
185 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
186 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
189 /* speculatively enqueue b0 and b1 to the current next frame */
190 to_next[0] = bi0 = from[0];
191 to_next[1] = bi1 = from[1];
197 b0 = vlib_get_buffer (vm, bi0);
198 b1 = vlib_get_buffer (vm, bi1);
200 sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
201 next0 = vcm->cached_next_index;
202 sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
203 next1 = vcm->cached_next_index;
205 /* $$$$ your message in this space. Process 2 x pkts */
206 em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 2;
208 if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)))
210 if (b0->flags & VLIB_BUFFER_IS_TRACED)
212 vcgn_classify_trace_t *t =
213 vlib_add_trace (vm, node, b0, sizeof (*t));
214 t->sw_if_index = sw_if_index0;
215 t->next_index = next0;
217 if (b1->flags & VLIB_BUFFER_IS_TRACED)
219 vcgn_classify_trace_t *t =
220 vlib_add_trace (vm, node, b1, sizeof (*t));
221 t->sw_if_index = sw_if_index1;
222 t->next_index = next1;
226 /* verify speculative enqueues, maybe switch current next frame */
227 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
228 to_next, n_left_to_next,
229 bi0, bi1, next0, next1);
233 while (n_left_from > 0 && n_left_to_next > 0)
241 ethernet_header_t *eth0;
246 /* speculatively enqueue b0 to the current next frame */
254 b0 = vlib_get_buffer (vm, bi0);
256 eth0 = (ethernet_header_t *) vlib_buffer_get_current(b0);
257 u16 *etype = ð0->type;
259 /* vlan tag 0x8100 */
260 if (*etype == clib_host_to_net_u16(ETHERNET_TYPE_VLAN)) {
261 l3_type = (etype + 1); /* Skip 2 bytes of vlan id */
262 vlib_buffer_advance(b0, 18);
265 vlib_buffer_advance(b0, 14);
267 /* Handling v4 pkts 0x800 */
268 if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP4)) {
270 h0 = vlib_buffer_get_current (b0);
272 u8 protocol_type = h0->protocol;
274 sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
275 next0 = VCGN_CLASSIFY_NEXT_IP4_INPUT;
276 counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PROCESSED;
278 if (protocol_type == 0x11) { /* UDP# 17 */
279 next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
280 vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
281 VCGN_CLASSIFY_NEXT_UDP_INSIDE : next0;
283 next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
284 vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
285 VCGN_CLASSIFY_NEXT_UDP_OUTSIDE : next0;
287 } else if (protocol_type == 0x06) { /* TCP# 6 */
288 next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
289 vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
290 VCGN_CLASSIFY_NEXT_TCP_INSIDE : next0;
292 next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
293 vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
294 VCGN_CLASSIFY_NEXT_TCP_OUTSIDE : next0;
296 } else if (protocol_type == 0x01) { /* ICMP # 1 */
298 ipv4_hdr_len = (h0->ip_version_and_header_length & 0xf) << 2;
299 icmp = (icmp_v4_t *)((u8*)h0 + ipv4_hdr_len);
300 icmp_type = icmp->type;
302 if ((icmp_type == ICMPV4_ECHO) ||
303 (icmp_type == ICMPV4_ECHOREPLY)) {
304 next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
305 vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
306 VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE : next0;
308 next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
309 vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
310 VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE : next0;
313 next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
314 vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
315 VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE : next0;
317 next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
318 vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
319 VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE : next0;
322 /* cannot do NATting with this L4 protocol */
323 counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PUNTED;
326 if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
327 && (b0->flags & VLIB_BUFFER_IS_TRACED))) {
328 udp_header_t * u0 = (udp_header_t *)(h0+1);
329 vcgn_classify_trace_t *t =
330 vlib_add_trace (vm, node, b0, sizeof (*t));
331 t->sw_if_index = sw_if_index0;
332 t->next_index = next0;
333 t->orig_dst_address = h0->dst_address.as_u32;
334 t->orig_dst_port = u0->dst_port;
337 } else if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP6)) {
340 next0 = VCGN_CLASSIFY_NEXT_IP6_INPUT;
341 counter = VCGN_CLASSIFY_ERROR_V6_PACKETS_PUNTED;
343 } else if (*l3_type ==
344 clib_host_to_net_u16(ETHERNET_TYPE_MPLS_UNICAST)) {
346 /* MPLS unicast 0x8847 */
347 next0 = VCGN_CLASSIFY_NEXT_MPLS_INPUT;
348 counter = VCGN_CLASSIFY_ERROR_MPLS_PACKETS_PUNTED;
349 } else { /* Remaining all should be pushed to "ethernet-input" */
351 next0 = VCGN_CLASSIFY_NEXT_ETHERNET_INPUT;
352 counter = VCGN_CLASSIFY_ERROR_ETH_PACKETS_PUNTED;
355 em->counters[node_counter_base_index + counter] += 1;
356 em->counters[node_counter_base_index +
357 VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 1;
359 /* verify speculative enqueue, maybe switch current next frame */
360 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
361 to_next, n_left_to_next,
365 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
368 return frame->n_vectors;
371 VLIB_REGISTER_NODE (vcgn_classify_node) = {
372 .function = vcgn_classify_node_fn,
373 .name = "vcgn-classify",
374 .vector_size = sizeof (u32),
375 .format_trace = format_swap_trace,
376 .type = VLIB_NODE_TYPE_INTERNAL,
378 .n_errors = ARRAY_LEN(vcgn_classify_error_strings),
379 .error_strings = vcgn_classify_error_strings,
381 .n_next_nodes = VCGN_CLASSIFY_N_NEXT,
383 /* edit / add dispositions here */
385 [VCGN_CLASSIFY_NEXT_IP4_INPUT] = "ip4-input",
386 [VCGN_CLASSIFY_NEXT_IP6_INPUT] = "ip6-input",
387 [VCGN_CLASSIFY_NEXT_MPLS_INPUT] = "mpls-gre-input",
388 [VCGN_CLASSIFY_NEXT_ETHERNET_INPUT] = "ethernet-input",
389 [VCGN_CLASSIFY_NEXT_UDP_INSIDE] = "vcgn-v4-udp-i2o",
390 [VCGN_CLASSIFY_NEXT_UDP_OUTSIDE] = "vcgn-v4-udp-o2i",
391 [VCGN_CLASSIFY_NEXT_TCP_INSIDE] = "vcgn-v4-tcp-i2o",
392 [VCGN_CLASSIFY_NEXT_TCP_OUTSIDE] = "vcgn-v4-tcp-o2i",
393 [VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE] = "vcgn-v4-icmp-q-i2o",
394 [VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE] = "vcgn-v4-icmp-q-o2i",
395 [VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE] = "vcgn-v4-icmp-e-i2o",
396 [VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE] = "vcgn-v4-icmp-e-o2i"
401 /* A test function to init the vrf map */
403 clib_error_t *vcgn_classify_init (vlib_main_t *vm)
405 vcgn_classify_main_t * mp = &vcgn_classify_main;
408 mp->vnet_main = vnet_get_main();
409 u32 inside_sw_if_index = 1;
410 u32 outside_sw_if_index = 0;
412 vec_validate_init_empty (mp->inside_sw_if_index_table,
413 inside_sw_if_index + 1, EMPTY);
414 vec_validate_init_empty (mp->outside_sw_if_index_table,
415 outside_sw_if_index + 1, EMPTY);
418 * inside_sw_if_index cell of the table stores outside_sw_if_index
419 * and vice versa. This is ensurs pair of indices being remembered
420 * using one mem-location.
422 mp->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index;
423 mp->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index;
426 dpdk_set_next_node (DPDK_RX_NEXT_IP4_INPUT, "vcgn-classify");
431 pn = pg_get_node (vcgn_classify_node.index);
432 pn->unformat_edit = unformat_pg_ip4_header;
437 VLIB_INIT_FUNCTION (vcgn_classify_init);
439 /* Show command handlers */
440 static clib_error_t *
441 show_vcgn_stats_command_fn (vlib_main_t * vm,
442 unformat_input_t * input,
443 vlib_cli_command_t * cmd)
445 if (cnat_db_init_done) {
446 cnat_nat44_handle_show_stats(vm);
448 vlib_cli_output(vm, "vCGN is not configured !!\n");
454 static clib_error_t *
455 show_vcgn_config_command_fn (vlib_main_t * vm,
456 unformat_input_t * input,
457 vlib_cli_command_t * cmd)
459 cnat_nat44_handle_show_config(vm);
463 static clib_error_t *
464 show_vcgn_inside_translation_command_fn (vlib_main_t * vm,
465 unformat_input_t * input,
466 vlib_cli_command_t * cmd)
468 vnet_main_t * vnm = vnet_get_main();
469 vcgn_classify_main_t * vcm = &vcgn_classify_main;
470 spp_api_cnat_v4_show_inside_entry_req_t inside_req;
472 ip4_address_t inside_addr;
474 u32 end_port = 65535;
475 u32 inside_sw_if_index = EMPTY;
477 inside_req.start_port = start_port;
478 inside_req.end_port = end_port;
479 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
480 if (unformat(input, "protocol %s", &proto)) {
481 if (!strncmp((char *) proto, "udp", 3)) {
482 inside_req.protocol = 1;
483 } else if (!strncmp((char *) proto, "tcp", 3)) {
484 inside_req.protocol = 2;
486 inside_req.protocol = 3;
488 } else if (unformat (input, "interface %U",
489 unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) {
490 if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
491 vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
492 return clib_error_return (0, "Could not find the inside interface");
494 } else if (unformat (input, "inside-addr %U",
495 unformat_ip4_address, &inside_addr)) {
496 inside_req.ipv4_addr = clib_net_to_host_u32(inside_addr.as_u32);
497 } else if (unformat(input, "start-port %u", &start_port)) {
498 inside_req.start_port = start_port;
499 } else if (unformat(input, "end-port %u", &end_port)) {
500 inside_req.end_port = end_port;
503 inside_req.vrf_id = inside_sw_if_index;
504 inside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
505 inside_req.all_entries = 0; /* we can see it later */
507 vlib_cli_output(vm, "proto %d, inside-addr 0x%x, start_port %u, "
508 "end_port %u, vrf 0x%x\n",
510 inside_req.ipv4_addr,
511 inside_req.start_port,
515 if (cnat_db_init_done) {
516 cnat_v4_show_inside_entry_req_t_handler(&inside_req, vm);
518 vlib_cli_output(vm, "vCGN is not configured !!\n");
524 static clib_error_t *
525 show_vcgn_outside_translation_command_fn (vlib_main_t * vm,
526 unformat_input_t * input,
527 vlib_cli_command_t * cmd)
529 void cnat_v4_show_outside_entry_req_t_handler
530 (spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm);
531 vnet_main_t * vnm = vnet_get_main();
532 vcgn_classify_main_t * vcm = &vcgn_classify_main;
533 spp_api_cnat_v4_show_outside_entry_req_t outside_req;
535 ip4_address_t outside_addr;
537 u32 end_port = 65535;
538 u32 outside_sw_if_index = EMPTY;
541 outside_req.start_port = start_port;
542 outside_req.end_port = end_port;
543 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
544 if (unformat(input, "protocol %s", &proto)) {
545 if (!strncmp((char *) proto, "udp", 3)) {
546 outside_req.protocol = 1;
547 } else if (!strncmp((char *) proto, "tcp", 3)) {
548 outside_req.protocol = 2;
550 outside_req.protocol = 3;
552 } else if (unformat (input, "interface %U",
553 unformat_vnet_sw_interface, vnm, &outside_sw_if_index)) {
554 if (outside_sw_if_index > vec_len(vcm->outside_sw_if_index_table) ||
555 vcm->outside_sw_if_index_table[outside_sw_if_index] == EMPTY) {
556 return clib_error_return (0, "Could not find the outside interface");
558 } else if (unformat (input, "outside-addr %U",
559 unformat_ip4_address, &outside_addr)) {
560 outside_req.ipv4_addr = clib_net_to_host_u32(outside_addr.as_u32);
561 } else if (unformat(input, "start-port %u", &start_port)) {
562 outside_req.start_port = start_port;
563 } else if (unformat(input, "end-port %u", &end_port)) {
564 outside_req.end_port = end_port;
567 outside_req.vrf_id = outside_sw_if_index;
568 outside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
570 vlib_cli_output(vm, "proto %d, outside-addr 0x%x, start_port %u, "
571 "end_port %u, vrf 0x%x\n",
572 outside_req.protocol,
573 outside_req.ipv4_addr,
574 outside_req.start_port,
575 outside_req.end_port,
576 outside_sw_if_index);
578 if (cnat_db_init_done) {
579 cnat_v4_show_outside_entry_req_t_handler(&outside_req, vm);
581 vlib_cli_output(vm, "vCGN is not configured !!\n");
587 /* Config command handlers */
588 static clib_error_t *
589 set_vcgn_inside_command_fn (vlib_main_t * vm,
590 unformat_input_t * input,
591 vlib_cli_command_t * cmd)
593 vnet_main_t * vnm = vnet_get_main();
594 vcgn_classify_main_t * vcm = &vcgn_classify_main;
595 u32 inside_sw_if_index = 1;
596 u32 outside_sw_if_index = ~0;
597 void cnat_db_v2_init (void );
599 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
600 if (unformat(input, "%U",
601 unformat_vnet_sw_interface, vnm, &inside_sw_if_index))
603 else if (unformat(input, "outside %U",
604 unformat_vnet_sw_interface, vnm, &outside_sw_if_index))
608 if (inside_sw_if_index == ~0 ||
609 outside_sw_if_index == ~0)
610 return clib_error_return (0, "unknown input `%U'",
611 format_unformat_error, input);
613 if (inside_sw_if_index == outside_sw_if_index)
614 return clib_error_return (0, "inside and outside interfaces can't be the same...");
617 * Initialize in/out sw_if_index table. Could use
618 * non-indexed table to reduce memory. However, this
619 * is consulted in vcgn_classify for every packet.
620 * Therefore, table is indexed by sw_if_index.
622 vec_validate_init_empty (vcm->inside_sw_if_index_table,
623 inside_sw_if_index + 1, EMPTY);
624 vec_validate_init_empty (vcm->outside_sw_if_index_table,
625 outside_sw_if_index + 1, EMPTY);
628 * inside_sw_if_index cell of the table stores outside_sw_if_index
629 * and vice versa. This is ensurs pair of indices being remembered
630 * using one mem-location.
632 vcm->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index;
633 vcm->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index;
635 if (! vcm->cnat_db_initalized) {
639 for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) {
640 vrf_map_array[i] = VRF_MAP_ENTRY_EMPTY;
642 /* Turn on the db scanner process */
643 cnat_scanner_db_process_turn_on(vm);
644 vcm->cnat_db_initalized = 1;
649 static clib_error_t *
650 set_vcgn_map_command_fn (vlib_main_t * vm,
651 unformat_input_t * input,
652 vlib_cli_command_t * cmd)
654 vnet_main_t * vnm = vnet_get_main();
655 vcgn_classify_main_t * vcm = &vcgn_classify_main;
656 ip4_address_t lo, hi;
657 spp_api_cnat_v4_add_vrf_map_t map;
658 u32 inside_sw_if_index = EMPTY;
659 u32 outside_sw_if_index;
661 vnet_hw_interface_t *inside_hw_if_index = NULL;
662 vnet_hw_interface_t *outside_hw_if_index = NULL;
664 if (! unformat(input, "inside %U",
665 unformat_vnet_sw_interface, vnm, &inside_sw_if_index))
666 return clib_error_return (0, "unknown input `%U'",
667 format_unformat_error, input);
669 if (!unformat (input, "%U", unformat_ip4_address, &lo))
670 return clib_error_return (0, "unknown input `%U'",
671 format_unformat_error, input);
673 if (unformat (input, "- %U", unformat_ip4_address, &hi))
676 /* $$$$ remember to set i_vrf, i_vrf_id as needed */
678 /* Fill the structure spp_api_cnat_v4_add_vrf_map_t & let this API handle it */
679 /* i_vrf_id & o_vrf_id are 32-bit & i_vrf, o_vrf are 16 bit */
681 if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
682 vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
683 return clib_error_return (0, "Could not find the inside interface");
685 outside_sw_if_index = vcm->inside_sw_if_index_table[inside_sw_if_index];
687 map.i_vrf_id = inside_sw_if_index;
688 map.o_vrf_id = outside_sw_if_index;
689 map.i_vrf = inside_sw_if_index;
690 map.o_vrf = outside_sw_if_index;
692 map.start_addr[0] = clib_net_to_host_u32(lo.as_u32);
693 map.end_addr[0] = clib_net_to_host_u32(hi.as_u32);
695 cnat_nat44_add_vrf_map_t_handler(&map, vm);
698 inside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, inside_sw_if_index);
699 if (inside_hw_if_index) {
700 vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
701 inside_hw_if_index->hw_if_index, vcgn_classify_node.index);
703 outside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, outside_sw_if_index);
704 if (outside_hw_if_index) {
705 vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
706 outside_hw_if_index->hw_if_index, vcgn_classify_node.index);
712 static clib_error_t *
713 set_vcgn_tcp_timeout_command_fn (vlib_main_t * vm,
714 unformat_input_t * input,
715 vlib_cli_command_t * cmd)
718 vnet_main_t * vnm = vnet_get_main();
719 vcgn_classify_main_t * vcm = &vcgn_classify_main;
722 u32 init_timeout = 0;
724 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
725 if (unformat(input, "active %u", &act_timeout))
726 tcp_active_timeout = act_timeout;
727 else if (unformat(input, "init %u", &init_timeout))
728 tcp_initial_setup_timeout = init_timeout;
734 static clib_error_t *
735 set_vcgn_udp_timeout_command_fn (vlib_main_t * vm,
736 unformat_input_t * input,
737 vlib_cli_command_t * cmd)
740 vnet_main_t * vnm = vnet_get_main();
741 vcgn_classify_main_t * vcm = &vcgn_classify_main;
744 u32 init_timeout = 0;
746 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
747 if (unformat(input, "active %u", &act_timeout))
748 udp_act_session_timeout = act_timeout;
749 else if (unformat(input, "init %u", &init_timeout))
750 udp_init_session_timeout = init_timeout;
757 static clib_error_t *
758 set_vcgn_icmp_timeout_command_fn (vlib_main_t * vm,
759 unformat_input_t * input,
760 vlib_cli_command_t * cmd)
763 * vnet_main_t * vnm = vnet_get_main();
764 * vcgn_classify_main_t * vcm = &vcgn_classify_main;
768 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
769 if (unformat(input, "%u", &timeout))
773 icmp_session_timeout = timeout;
778 static clib_error_t *
779 set_vcgn_protocol_default_timeout_command_fn (vlib_main_t * vm,
780 unformat_input_t * input,
781 vlib_cli_command_t * cmd)
784 vnet_main_t * vnm = vnet_get_main();
785 vcgn_classify_main_t * vcm = &vcgn_classify_main;
790 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
791 if (unformat(input, "%s", &protocol))
795 cnat_nat44_set_protocol_timeout_value(0, 0, protocol, reset, vm);
799 static clib_error_t *
800 set_vcgn_dynamic_port_start_range_command_fn (vlib_main_t * vm,
801 unformat_input_t * input,
802 vlib_cli_command_t * cmd)
805 vnet_main_t * vnm = vnet_get_main();
806 vcgn_classify_main_t * vcm = &vcgn_classify_main;
810 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
811 if (unformat(input, "%u", &port))
815 if (port != 0 && port > 65535) {
816 vlib_cli_output(vm, "Error !! Invalid port\n");
818 cnat_static_port_range = port;
819 vlib_cli_output(vm, "Dynamic Port Range Config Successful !!\n");
824 static clib_error_t *
825 set_vcgn_port_limit_command_fn (vlib_main_t * vm,
826 unformat_input_t * input,
827 vlib_cli_command_t * cmd)
830 vnet_main_t * vnm = vnet_get_main();
831 vcgn_classify_main_t * vcm = &vcgn_classify_main;
835 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
836 if (unformat(input, "%u", &port))
840 if (port != 0 && port > 65535) {
841 vlib_cli_output(vm, "Error !! Invalid port\n");
843 cnat_main_db_max_ports_per_user = port;
844 vlib_cli_output(vm, "Port Limit Config Successful !!\n");
849 static inline void nfv9_init_pkt_sent_data(cnat_nfv9_logging_info_t *nfv9_info)
851 nfv9_server_info_t *server = nfv9_server_info_pool +
852 nfv9_info->server_index;
855 * Reset the pkts_since_last_template and sent_time
856 * so that template will be sent next time
858 server->last_template_sent_time = 0;
859 server->pkts_since_last_template = 0xffffffff;
862 static inline u16 nfv9_get_max_length_minus_max_record_size(u16 path_mtu)
864 u16 max_length_minus_max_record_size;
865 if(!path_mtu) /* Use default */
866 path_mtu = NFV9_DEF_PATH_MTU;
868 max_length_minus_max_record_size = path_mtu -
869 CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH -
871 CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH; /* Note.. as of now this record
872 * requires max number of bytes. If you add more records,
873 * this needs to be re-checked */
874 if (max_length_minus_max_record_size < CNAT_NFV9_MIN_RECORD_SIZE) {
875 max_length_minus_max_record_size = CNAT_NFV9_MIN_RECORD_SIZE;
877 return max_length_minus_max_record_size;
880 /* This function finds if the netflow server indicated by
881 * new_server_info is already configured for some other instance
882 * if yes, it returns the same pointer so that, info sent to the
883 * server is consistent. If the server is not found, a new instance
884 * is created and returned. If an existing server is used, its refernce
885 * count is incrimented (indicating the number of instances using the
888 /* #define DEBUG_NF_SERVER_CONFIG 1 */
889 static u16 nfv9_get_server_instance(
890 cnat_nfv9_logging_info_t *nfv9_info, nfv9_server_info_t *new_server_info)
893 /* Check if the instance has a server already and if yes, does it match */
894 nfv9_server_info_t *server;
895 if(nfv9_info->server_index != EMPTY) {
896 server = nfv9_server_info_pool + nfv9_info->server_index;
898 if((server->ipv4_address == new_server_info->ipv4_address) &&
899 (server->port == new_server_info->port)) {
900 /* Same server.. just check if refresh rate/timeouts are reduced */
901 #ifdef DEBUG_NF_SERVER_CONFIG
902 if(my_instance_number == 1) {
903 printf("\n Server match for %x and port %d\n",
904 new_server_info->ipv4_address, new_server_info->port);
906 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
907 goto adjust_refresh_rate;
908 } else { /* The server is being changed */
910 #ifdef DEBUG_NF_SERVER_CONFIG
911 if(my_instance_number == 1) {
912 printf("\n Server change from %x, %d to %x, %d"
914 server->ipv4_address,
916 new_server_info->ipv4_address, new_server_info->port,
919 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
920 if(!server->ref_count) {
921 /* Return this server to pool */
922 #ifdef DEBUG_NF_SERVER_CONFIG
923 if(my_instance_number == 1) {
924 PLATFORM_DEBUG_PRINT("Deleting Server %x, %d at %d\n",
925 server->ipv4_address,
927 nfv9_info->server_index);
929 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
930 pool_put(nfv9_server_info_pool, server);
935 /* Now check if the server is already present in the pool */
938 pool_foreach (server, nfv9_server_info_pool, ({
939 if ((server->ipv4_address == new_server_info->ipv4_address) &&
940 (server->port == new_server_info->port)) {
942 nfv9_info->server_index = server - nfv9_server_info_pool;
944 #ifdef DEBUG_NF_SERVER_CONFIG
945 if(my_instance_number == 1) {
946 printf("Re-using server %x, %d Ref count %d\n",
947 server->ipv4_address, server->port, server->ref_count);
949 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
955 /* Create a new one, initialize and return */
957 pool_get(nfv9_server_info_pool, server);
958 clib_memcpy(server, new_server_info, sizeof(nfv9_server_info_t));
959 server->ref_count = 1;
960 nfv9_info->server_index = server - nfv9_server_info_pool;
961 #ifdef DEBUG_NF_SERVER_CONFIG
962 if(my_instance_number == 1) {
963 printf("Create new server for at %d %x and port %d\n",
964 nfv9_info->server_index,
965 new_server_info->ipv4_address, new_server_info->port);
967 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
972 if(server->refresh_rate >
973 new_server_info->refresh_rate) {
974 server->refresh_rate =
975 new_server_info->refresh_rate;
976 #ifdef DEBUG_NF_SERVER_CONFIG
977 if(my_instance_number == 1) {
978 printf("Reset refresh rate to %d\n",
979 server->refresh_rate);
981 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
984 if(server->timeout_rate >
985 new_server_info->timeout_rate) {
986 server->timeout_rate =
987 new_server_info->timeout_rate;
988 #ifdef DEBUG_NF_SERVER_CONFIG
989 if(my_instance_number == 1) {
990 printf("Reset timeout rate to %d\n",
991 server->timeout_rate);
993 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
998 static clib_error_t *
999 set_vcgn_nfv9_logging_cofig_command_fn (vlib_main_t * vm,
1000 unformat_input_t * input,
1001 vlib_cli_command_t * cmd)
1003 vcgn_classify_main_t * vcm = &vcgn_classify_main;
1004 spp_api_cnat_v4_config_nfv9_logging_t nfv9_conf;
1005 ip4_address_t server_addr;
1008 u32 refresh_rate = 0;
1012 /* vcgn changes start*/
1013 cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL;
1014 cnat_nfv9_logging_info_t *my_nfv9_logging_info_tmp = NULL;
1015 cnat_vrfmap_t *my_vrfmap = 0, *my_vrfmap_temp = 0;
1019 u32 inside_sw_if_index = EMPTY;
1021 * Init NFv9 logging info as needed, this will be done only once
1023 cnat_nfv9_logging_init();
1027 /* vcgn changes end*/
1028 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
1029 if (unformat (input, "inside %U",
1030 unformat_vnet_sw_interface, &inside_sw_if_index)) {
1032 } else if (unformat (input, "server %U", unformat_ip4_address, &server_addr))
1033 ip_addr = clib_net_to_host_u32(server_addr.as_u32);
1034 else if (unformat(input, "port %u", &port))
1036 else if (unformat(input, "refresh-rate %u", &refresh_rate))
1038 else if (unformat(input, "timeout %u", &timeout))
1040 else if (unformat(input, "pmtu %u", &pmtu))
1042 else if (unformat(input, "del"))
1047 if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
1048 vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
1049 return clib_error_return (0, "Could not find the inside interface");
1051 i_vrf = inside_sw_if_index;
1052 i_vrf_id = inside_sw_if_index;
1055 vlib_cli_output(vm, "ip 0x%x, port %u, refresh %u, "
1056 "timeout %u, pmtu %u enable %u\n",
1057 ip_addr, port, refresh_rate,
1058 timeout, pmtu, enable);
1060 if (refresh_rate == 0) refresh_rate = 500; /* num of pkts */
1061 if (timeout == 0) timeout = 30; /* in mins */
1063 nfv9_conf.enable = enable;
1064 nfv9_conf.ipv4_address = ip_addr;
1065 nfv9_conf.i_vrf_id = inside_sw_if_index;
1066 nfv9_conf.i_vrf = inside_sw_if_index;
1067 nfv9_conf.port = port;
1068 nfv9_conf.refresh_rate = refresh_rate;
1069 nfv9_conf.timeout_rate = timeout;
1070 nfv9_conf.path_mtu = pmtu;
1071 nfv9_conf.nfv9_global_collector = 0;
1072 nfv9_conf.session_logging = 0;
1075 * At this point the NFv9 global information should already be
1076 * inited as we have called cnat_nfv9_logging_init()
1079 if (nfv9_conf.nfv9_global_collector) {
1080 if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) {
1082 my_nfv9_logging_info = cnat_nfv9_logging_info_pool +
1083 cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1086 /* Do we already have a map for this VRF? */
1087 pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1088 if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) {
1089 nfv9_server_info_t *server = nfv9_server_info_pool +
1090 my_nfv9_logging_info->server_index;
1091 if((server->ipv4_address == (nfv9_conf.ipv4_address)) && (server->port == (nfv9_conf.port))) {
1093 my_nfv9_logging_info_tmp = my_nfv9_logging_info;
1100 if ((nfv9_conf.ipv4_address == 0) ||
1101 (nfv9_conf.port == 0)) {
1103 "Add NFv9 ivrf %d Logging Invalid values [IPv4 0x%x, PORT %d]\n",
1105 (nfv9_conf.ipv4_address),
1110 if (nfv9_conf.enable) {
1111 if ((nfv9_conf.ipv4_address == 0) ||
1112 (nfv9_conf.port == 0)) {
1113 nfv9_conf.rc = CNAT_ERR_PARSER;
1115 "NFV9_logging i_vrf %d, Invalid [v4_addr 0x%x port %d]\n",
1117 (nfv9_conf.ipv4_address),
1122 nfv9_server_info_t new_server_info;
1123 memset(&new_server_info, 0, sizeof(nfv9_server_info_t));
1124 new_server_info.ipv4_address =
1125 nfv9_conf.ipv4_address;
1126 new_server_info.port =
1128 new_server_info.refresh_rate =
1129 (nfv9_conf.refresh_rate);
1131 * Store the timeout in seconds. User configures it in minutes
1133 new_server_info.timeout_rate =
1134 60*(nfv9_conf.timeout_rate);
1135 if (found && my_nfv9_logging_info) {
1137 * Entry already present, change it
1139 my_nfv9_logging_info->max_length_minus_max_record_size =
1140 nfv9_get_max_length_minus_max_record_size(
1141 ((nfv9_conf.path_mtu)));
1143 pool_get(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1144 memset(my_nfv9_logging_info, 0, sizeof(*my_nfv9_logging_info));
1145 my_nfv9_logging_info->server_index = EMPTY;
1146 my_nfv9_logging_info->nfv9_logging_next_index = EMPTY;
1148 * Make the current and head logging context indeices as EMPTY.
1149 * When first logging happens, these get set correctly
1151 my_nfv9_logging_info->current_logging_context = NULL;
1152 my_nfv9_logging_info->queued_logging_context = NULL;
1154 my_nfv9_logging_info->f = NULL;
1155 my_nfv9_logging_info->to_next = NULL;
1156 output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-input");
1157 my_nfv9_logging_info->ip4_input_node_index = output_node->index;
1158 printf("ip4_input_node_index %d\n", my_nfv9_logging_info->ip4_input_node_index);
1160 my_nfv9_logging_info->i_vrf = i_vrf;
1161 my_nfv9_logging_info->i_vrf_id = i_vrf_id;
1162 my_nfv9_logging_info->max_length_minus_max_record_size =
1163 nfv9_get_max_length_minus_max_record_size(
1164 nfv9_conf.path_mtu);
1166 /* my_nfv9_logging_info will have a copy of logging_policy
1167 * because, it is quite possible that nfv9 config arrives before
1168 * the corresponding vrfmap is initialized. In such cases
1169 * this copy will be used to update the vrfmap entry
1171 my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1173 if (nfv9_conf.nfv9_global_collector) {
1174 cnat_nfv9_global_info.cnat_nfv9_global_collector_index =
1175 my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1177 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1178 if (my_vrfmap->nfv9_logging_index == EMPTY) {
1179 my_vrfmap->nfv9_logging_index =
1180 cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1184 u32 my_vrfmap_found = 0;
1186 FIND_MY_VRF_USING_I_VRF_ID
1187 my_vrfmap = my_vrfmap_temp;
1188 if (my_vrfmap_found) {
1189 if(my_vrfmap->nfv9_logging_index == EMPTY) {
1190 my_vrfmap->nfv9_logging_index =
1191 my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1192 // my_vrfmap->nf_logging_policy = mp->session_logging;
1194 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index;
1195 while(my_nfv9_logging_info_temp->nfv9_logging_next_index != EMPTY){
1196 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_nfv9_logging_info_temp->nfv9_logging_next_index;
1198 my_nfv9_logging_info_temp->nfv9_logging_next_index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1204 /* Update logging policy */
1205 my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1206 if (nfv9_conf.nfv9_global_collector) {
1207 if(PLATFORM_DBL_SUPPORT) {
1208 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1209 if (my_vrfmap->nfv9_logging_index ==
1210 cnat_nfv9_global_info.cnat_nfv9_global_collector_index) {
1211 my_vrfmap->nf_logging_policy = nfv9_conf.session_logging;
1215 nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1218 if(PLATFORM_DBL_SUPPORT) {
1219 u32 my_vrfmap_found = 0;
1220 my_vrfmap_temp = NULL;
1221 FIND_MY_VRF_USING_I_VRF_ID
1222 my_vrfmap = my_vrfmap_temp;
1223 if (my_vrfmap_found) {
1224 // my_vrfmap->nf_logging_policy = mp->session_logging;
1227 nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1230 u8 nfv9_logging_policy = 0;
1231 u32 my_vrfmap_found = 0;
1232 my_vrfmap_temp = NULL;
1233 FIND_MY_VRF_USING_I_VRF_ID
1234 my_vrfmap = my_vrfmap_temp;
1235 if (my_vrfmap_found) {
1236 u32 index_curr = my_vrfmap->nfv9_logging_index;
1237 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1238 while(index_curr != EMPTY) {
1239 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1240 nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1241 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1243 my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1245 //vlib_cli_output(vm,"Netflow logging policy = %d\n", my_vrfmap->nf_logging_policy);
1246 if(nfv9_get_server_instance(my_nfv9_logging_info, &new_server_info)
1248 vlib_cli_output(vm, "Error to get server instance");
1249 nfv9_conf.rc = CNAT_ERR_PARSER;
1252 nfv9_init_pkt_sent_data(my_nfv9_logging_info);
1254 vlib_cli_output(vm,"Adding NFv9 Logging Succeeded\n");
1255 nfv9_configured = 1;
1260 /* if found entry then we need to overwrite the my_nfv9_logging_info_tmp
1261 * to my_nfv9_logging_info
1263 my_nfv9_logging_info = my_nfv9_logging_info_tmp;
1264 if (i_vrf == INVALID_UIDX) {
1266 * We are deleting a global collector. Mark the collectors
1267 * in those VRFs using the global collector
1269 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1270 if (my_vrfmap->nfv9_logging_index ==
1271 cnat_nfv9_global_info.cnat_nfv9_global_collector_index) {
1272 my_vrfmap->nfv9_logging_index = EMPTY;
1276 cnat_nfv9_global_info.cnat_nfv9_global_collector_index = EMPTY;
1278 u32 my_vrfmap_found = 0;
1279 my_vrfmap_temp = NULL;
1280 FIND_MY_VRF_USING_I_VRF_ID
1281 my_vrfmap = my_vrfmap_temp;
1282 if (my_vrfmap_found) {
1283 // my_vrfmap->nfv9_logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1286 if (my_nfv9_logging_info->queued_logging_context ||
1287 my_nfv9_logging_info->current_logging_context) {
1289 * If there is a pending context:
1290 * Set the deleted flag to 1. This will ensure
1291 * that the logging info structure gets freed after any
1292 * pending packet get sent
1294 my_nfv9_logging_info->deleted = 1;
1297 * No pending context, just free the logging info structure
1299 u32 index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1300 if(index == my_vrfmap->nfv9_logging_index) {
1301 /* Deleting the first sever */
1302 my_vrfmap->nfv9_logging_index = my_nfv9_logging_info->nfv9_logging_next_index;
1303 /* if(my_nfv9_logging_info->nfv9_logging_next_index != EMPTY){
1304 my_vrfmap->nf_logging_policy = (cnat_nfv9_logging_info_pool + my_nfv9_logging_info->nfv9_logging_next_index)->logging_policy;
1306 my_vrfmap->nf_logging_policy = EMPTY;
1309 u32 index_curr = my_vrfmap->nfv9_logging_index;
1310 u32 index_prev = EMPTY;
1311 while(index_curr != EMPTY) {
1312 index_prev = index_curr;
1313 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1314 if(index == index_curr)
1316 (cnat_nfv9_logging_info_pool + index_prev)->nfv9_logging_next_index = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1321 nfv9_delete_server_info(my_nfv9_logging_info);
1322 pool_put(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1325 vlib_cli_output(vm, "Deleting NFv9 Logging Succeeded\n");
1327 * Search across all vrf and check if nfv9 logging is configured.
1329 nfv9_configured = 0;
1330 pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1331 nfv9_configured = 1;
1335 nfv9_conf.rc = CNAT_NO_CONFIG;
1336 vlib_cli_output(vm, "Add NFv9 Logging Failed (2) Non Existent vrf %d\n",
1340 u8 nfv9_logging_policy = 0;
1341 u32 my_vrfmap_found = 0;
1342 my_vrfmap_temp = NULL;
1343 FIND_MY_VRF_USING_I_VRF_ID
1344 my_vrfmap = my_vrfmap_temp;
1345 if (my_vrfmap_found) {
1346 u32 index_curr = my_vrfmap->nfv9_logging_index;
1347 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1348 while(index_curr != EMPTY) {
1349 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1350 nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1351 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1353 my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1362 VLIB_CLI_COMMAND (set_vcgn_map_command) = {
1363 .path = "set vcgn map",
1364 .short_help = "set vcgn map <lo-address> [- <hi-address>]",
1365 .function = set_vcgn_map_command_fn,
1368 VLIB_CLI_COMMAND (set_vcgn_inside_command) = {
1369 .path = "set vcgn inside",
1370 .short_help = "set vcgn inside <inside intfc> outside <outside intfc>",
1371 .function = set_vcgn_inside_command_fn,
1374 VLIB_CLI_COMMAND (set_vcgn_tcp_timeout_command) = {
1375 .path = "set vcgn tcp timeout",
1376 .short_help = "set vcgn tcp timeout active <1-65535> init <1-65535>",
1377 .function = set_vcgn_tcp_timeout_command_fn,
1380 VLIB_CLI_COMMAND (set_vcgn_udp_timeout_command) = {
1381 .path = "set vcgn udp timeout",
1382 .short_help = "set vcgn udp timeout active <1-65535> init <1-65535>",
1383 .function = set_vcgn_udp_timeout_command_fn,
1386 VLIB_CLI_COMMAND (set_vcgn_icmp_timeout_command) = {
1387 .path = "set vcgn icmp timeout",
1388 .short_help = "set vcgn icmp timeout <1-65535>",
1389 .function = set_vcgn_icmp_timeout_command_fn,
1392 VLIB_CLI_COMMAND (set_vcgn_protocol_default_timeout_command) = {
1393 .path = "set vcgn default timeout",
1394 .short_help = "set vcgn default timeout protocol <tcp/udp/icmp>",
1395 .function = set_vcgn_protocol_default_timeout_command_fn,
1398 VLIB_CLI_COMMAND (set_vcgn_dynamic_port_start_range_command) = {
1399 .path = "set vcgn dynamic port start",
1400 .short_help = "set vcgn dynamic port start <1-65535>",
1401 .function = set_vcgn_dynamic_port_start_range_command_fn,
1404 VLIB_CLI_COMMAND (set_vcgn_port_limit_command) = {
1405 .path = "set vcgn port limit",
1406 .short_help = "set vcgn port limit <1-65535>",
1407 .function = set_vcgn_port_limit_command_fn,
1410 VLIB_CLI_COMMAND (set_vcgn_nfv9_logging_cofig_command) = {
1411 .path = "set vcgn nfv9",
1412 .short_help = "set vcgn nfv9 [del] inside <interface> "
1413 "server <ip-addr> port <port> [refresh-rate <n>] "
1414 "[timeout <n>] [pmtu <n>]",
1415 .function = set_vcgn_nfv9_logging_cofig_command_fn,
1420 VLIB_CLI_COMMAND (show_vcgn_config_command) = {
1421 .path = "show vcgn config",
1422 .short_help = "show vcgn config",
1423 .function = show_vcgn_config_command_fn,
1426 VLIB_CLI_COMMAND (show_vcgn_stat_command) = {
1427 .path = "show vcgn statistics",
1428 .short_help = "show vcgn statistics",
1429 .function = show_vcgn_stats_command_fn,
1432 VLIB_CLI_COMMAND (show_vcgn_inside_translation_command) = {
1433 .path = "show vcgn inside-translation",
1434 .short_help = "show vcgn inside-translation protocol <tcp/udp/icmp> "
1435 "interface <inside-if> inside-addr <ip-addr> "
1436 "[start-port <n>] [end-port <n>]",
1437 .function = show_vcgn_inside_translation_command_fn,
1440 VLIB_CLI_COMMAND (show_vcgn_outside_translation_command) = {
1441 .path = "show vcgn outside-translation",
1442 .short_help = "show vcgn outside-translation protocol <tcp/udp/icmp> "
1443 "interface <outside-if> outside-addr <ip-addr> "
1444 "[start-port <n>] [end-port <n>]",
1445 .function = show_vcgn_outside_translation_command_fn,
1448 static clib_error_t *
1449 vcgn_init (vlib_main_t * vm)
1451 clib_error_t * error = 0;
1453 if ((error = vlib_call_init_function
1454 (vm, vcgn_classify_init)))
1456 if ((error = vlib_call_init_function
1457 (vm, cnat_ipv4_udp_inside_input_init)))
1459 if ((error = vlib_call_init_function
1460 (vm, cnat_ipv4_udp_outside_input_init)))
1462 if ((error = vlib_call_init_function
1463 (vm, cnat_ipv4_udp_inside_input_exc_init)))
1465 if ((error = vlib_call_init_function
1466 (vm, cnat_db_scanner_init)))
1468 if ((error = vlib_call_init_function
1469 (vm, cnat_ipv4_tcp_inside_input_init)))
1471 if ((error = vlib_call_init_function
1472 (vm, cnat_ipv4_tcp_inside_input_exc_init)))
1474 if ((error = vlib_call_init_function
1475 (vm, cnat_ipv4_tcp_outside_input_init)))
1477 if ((error = vlib_call_init_function
1478 (vm, cnat_ipv4_icmp_q_inside_input_init)))
1480 if ((error = vlib_call_init_function
1481 (vm, cnat_ipv4_icmp_q_inside_input_exc_init)))
1483 if ((error = vlib_call_init_function
1484 (vm, cnat_ipv4_icmp_q_outside_input_init)))
1486 if ((error = vlib_call_init_function
1487 (vm, cnat_ipv4_icmp_e_inside_input_init)))
1489 if ((error = vlib_call_init_function
1490 (vm, cnat_ipv4_icmp_e_outside_input_init)))
1497 * This routine exists to convince the vlib plugin framework that
1498 * we haven't accidentally copied a random .dll into the plugin
1499 * directory. This is used in lieu of VLIB_INIT_FUNCTION(vcgn_init).
1501 * Also collects global variable pointers passed from the vpp engine
1504 vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
1505 int from_early_init)
1507 return vcgn_init(vm);