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 <vlib/vlib.h>
17 #include <vnet/vnet.h>
18 #include <vnet/pg/pg.h>
19 #include <vppinfra/error.h>
20 #include <vppinfra/pool.h>
22 #include <vnet/ip/ip.h>
23 #include <vnet/ethernet/ethernet.h>
26 #include "cnat_global.h"
28 #include "cnat_config.h"
29 #include "cnat_logging.h"
30 #include "cnat_config_api.h"
31 #include "cnat_show_api.h"
32 #include "cnat_show_response.h"
33 #include "cnat_ipv4_udp.h"
34 #include "cnat_common_api.h"
36 #include <arpa/inet.h>
39 u32 cached_next_index;
41 /* inside, outside interface handles */
42 u32 inside_sw_if_index;
43 u32 outside_sw_if_index;
45 /* convenience variables */
46 vlib_main_t * vlib_main;
47 vnet_main_t * vnet_main;
48 } vcgn_classify_main_t;
51 /* $$$$ fill in with per-pkt trace data */
56 } vcgn_classify_trace_t;
58 #define FIND_MY_VRF_USING_I_VRF_ID \
59 my_vrfmap_found = 0; \
60 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ \
61 if (my_vrfmap->i_vrf_id == i_vrf_id) { \
62 my_vrfmap_found = 1; \
63 my_vrfmap_temp = my_vrfmap; \
69 /* packet trace format function */
70 static u8 * format_swap_trace (u8 * s, va_list * args)
72 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
73 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
74 vcgn_classify_trace_t * t = va_arg (*args, vcgn_classify_trace_t *);
76 s = format (s, "VCGN_CLASSIFY: dst %U dst_port %d sw_if_index %d next %d",
77 format_ip4_address, (ip4_header_t *) &t->orig_dst_address,
78 clib_net_to_host_u16(t->orig_dst_port),
79 t->sw_if_index, t->next_index);
83 vcgn_classify_main_t vcgn_classify_main;
85 vlib_node_registration_t vcgn_classify_node;
87 #define foreach_vcgn_classify_error \
88 _(PACKETS_RECEIVED, "total packets received") \
89 _(V4_PACKETS_PROCESSED, "ipv4 packets processed for vCGN") \
90 _(V4_PACKETS_PUNTED, "ipv4 packets punted") \
91 _(V6_PACKETS_PUNTED, "ipv6 packets punted") \
92 _(MPLS_PACKETS_PUNTED, "mpls unicast packets punted") \
93 _(ETH_PACKETS_PUNTED, "ethernet packets punted")
97 #define _(sym,str) VCGN_CLASSIFY_ERROR_##sym,
98 foreach_vcgn_classify_error
100 VCGN_CLASSIFY_N_ERROR,
101 } vcgn_classify_error_t;
103 static char * vcgn_classify_error_strings[] = {
104 #define _(sym,string) string,
105 foreach_vcgn_classify_error
110 * To drop a pkt and increment one of the previous counters:
112 * set b0->error = error_node->errors[VCGN_CLASSIFY_ERROR_EXAMPLE];
113 * set next0 to a disposition index bound to "error-drop".
115 * To manually increment the specific counter VCGN_CLASSIFY_ERROR_EXAMPLE:
117 * vlib_node_t *n = vlib_get_node (vm, vcgn_classify.index);
118 * u32 node_counter_base_index = n->error_heap_index;
119 * vlib_error_main_t * em = &vm->error_main;
120 * em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_EXAMPLE] += 1;
125 VCGN_CLASSIFY_NEXT_IP4_INPUT,
126 VCGN_CLASSIFY_NEXT_IP6_INPUT,
127 VCGN_CLASSIFY_NEXT_MPLS_INPUT,
128 VCGN_CLASSIFY_NEXT_ETHERNET_INPUT,
129 VCGN_CLASSIFY_NEXT_UDP_INSIDE,
130 VCGN_CLASSIFY_NEXT_UDP_OUTSIDE,
131 VCGN_CLASSIFY_NEXT_TCP_INSIDE,
132 VCGN_CLASSIFY_NEXT_TCP_OUTSIDE,
133 VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE,
134 VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE,
135 VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE,
136 VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE,
137 VCGN_CLASSIFY_N_NEXT,
138 } vcgn_classify_next_t;
141 vcgn_classify_node_fn (vlib_main_t * vm,
142 vlib_node_runtime_t * node,
143 vlib_frame_t * frame)
145 u32 n_left_from, * from, * to_next;
146 vcgn_classify_next_t next_index;
147 vcgn_classify_main_t * vcm = &vcgn_classify_main;
148 vlib_node_t *n = vlib_get_node (vm, vcgn_classify_node.index);
149 u32 node_counter_base_index = n->error_heap_index;
150 vlib_error_main_t * em = &vm->error_main;
154 from = vlib_frame_vector_args (frame);
155 n_left_from = frame->n_vectors;
156 next_index = node->cached_next_index;
158 while (n_left_from > 0)
162 vlib_get_next_frame (vm, node, next_index,
163 to_next, n_left_to_next);
166 while (n_left_from >= 4 && n_left_to_next >= 2)
169 vlib_buffer_t * b0, * b1;
171 u32 sw_if_index0, sw_if_index1;
173 /* Prefetch next iteration. */
175 vlib_buffer_t * p2, * p3;
177 p2 = vlib_get_buffer (vm, from[2]);
178 p3 = vlib_get_buffer (vm, from[3]);
180 vlib_prefetch_buffer_header (p2, LOAD);
181 vlib_prefetch_buffer_header (p3, LOAD);
183 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
184 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
187 /* speculatively enqueue b0 and b1 to the current next frame */
188 to_next[0] = bi0 = from[0];
189 to_next[1] = bi1 = from[1];
195 b0 = vlib_get_buffer (vm, bi0);
196 b1 = vlib_get_buffer (vm, bi1);
198 sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
199 next0 = vcm->cached_next_index;
200 sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
201 next1 = vcm->cached_next_index;
203 /* $$$$ your message in this space. Process 2 x pkts */
204 em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 2;
206 if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)))
208 if (b0->flags & VLIB_BUFFER_IS_TRACED)
210 vcgn_classify_trace_t *t =
211 vlib_add_trace (vm, node, b0, sizeof (*t));
212 t->sw_if_index = sw_if_index0;
213 t->next_index = next0;
215 if (b1->flags & VLIB_BUFFER_IS_TRACED)
217 vcgn_classify_trace_t *t =
218 vlib_add_trace (vm, node, b1, sizeof (*t));
219 t->sw_if_index = sw_if_index1;
220 t->next_index = next1;
224 /* verify speculative enqueues, maybe switch current next frame */
225 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
226 to_next, n_left_to_next,
227 bi0, bi1, next0, next1);
231 while (n_left_from > 0 && n_left_to_next > 0)
239 ethernet_header_t *eth0;
244 /* speculatively enqueue b0 to the current next frame */
252 b0 = vlib_get_buffer (vm, bi0);
254 eth0 = (ethernet_header_t *) vlib_buffer_get_current(b0);
255 u16 *etype = ð0->type;
257 /* vlan tag 0x8100 */
258 if (*etype == clib_host_to_net_u16(ETHERNET_TYPE_VLAN)) {
259 l3_type = (etype + 1); /* Skip 2 bytes of vlan id */
260 vlib_buffer_advance(b0, 18);
263 vlib_buffer_advance(b0, 14);
265 /* Handling v4 pkts 0x800 */
266 if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP4)) {
268 h0 = vlib_buffer_get_current (b0);
270 u8 protocol_type = h0->protocol;
272 sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
273 next0 = VCGN_CLASSIFY_NEXT_IP4_INPUT;
274 counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PROCESSED;
276 if (protocol_type == 0x11) { /* UDP# 17 */
277 next0 = (sw_if_index0 == vcm->inside_sw_if_index) ?
278 VCGN_CLASSIFY_NEXT_UDP_INSIDE : next0;
280 next0 = (sw_if_index0 == vcm->outside_sw_if_index) ?
281 VCGN_CLASSIFY_NEXT_UDP_OUTSIDE : next0;
282 } else if (protocol_type == 0x06) { /* TCP# 6 */
283 next0 = (sw_if_index0 == vcm->inside_sw_if_index) ?
284 VCGN_CLASSIFY_NEXT_TCP_INSIDE : next0;
286 next0 = (sw_if_index0 == vcm->outside_sw_if_index) ?
287 VCGN_CLASSIFY_NEXT_TCP_OUTSIDE : next0;
288 } else if (protocol_type == 0x01) { /* ICMP # 1 */
290 ipv4_hdr_len = (h0->ip_version_and_header_length & 0xf) << 2;
291 icmp = (icmp_v4_t *)((u8*)h0 + ipv4_hdr_len);
292 icmp_type = icmp->type;
294 if ((icmp_type == ICMPV4_ECHO) ||
295 (icmp_type == ICMPV4_ECHOREPLY)) {
296 next0 = (sw_if_index0 == vcm->inside_sw_if_index) ?
297 VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE : next0;
299 next0 = (sw_if_index0 == vcm->outside_sw_if_index) ?
300 VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE : next0;
302 next0 = (sw_if_index0 == vcm->inside_sw_if_index) ?
303 VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE : next0;
305 next0 = (sw_if_index0 == vcm->outside_sw_if_index) ?
306 VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE : next0;
310 /* cannot do NATting with this L4 protocol */
311 counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PUNTED;
314 if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
315 && (b0->flags & VLIB_BUFFER_IS_TRACED))) {
316 udp_header_t * u0 = (udp_header_t *)(h0+1);
317 vcgn_classify_trace_t *t =
318 vlib_add_trace (vm, node, b0, sizeof (*t));
319 t->sw_if_index = sw_if_index0;
320 t->next_index = next0;
321 t->orig_dst_address = h0->dst_address.as_u32;
322 t->orig_dst_port = u0->dst_port;
325 } else if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP6)) {
328 next0 = VCGN_CLASSIFY_NEXT_IP6_INPUT;
329 counter = VCGN_CLASSIFY_ERROR_V6_PACKETS_PUNTED;
331 } else if (*l3_type ==
332 clib_host_to_net_u16(ETHERNET_TYPE_MPLS_UNICAST)) {
334 /* MPLS unicast 0x8847 */
335 next0 = VCGN_CLASSIFY_NEXT_MPLS_INPUT;
336 counter = VCGN_CLASSIFY_ERROR_MPLS_PACKETS_PUNTED;
337 } else { /* Remaining all should be pushed to "ethernet-input" */
339 next0 = VCGN_CLASSIFY_NEXT_ETHERNET_INPUT;
340 counter = VCGN_CLASSIFY_ERROR_ETH_PACKETS_PUNTED;
343 em->counters[node_counter_base_index + counter] += 1;
344 em->counters[node_counter_base_index +
345 VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 1;
347 /* verify speculative enqueue, maybe switch current next frame */
348 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
349 to_next, n_left_to_next,
353 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
356 return frame->n_vectors;
359 VLIB_REGISTER_NODE (vcgn_classify_node) = {
360 .function = vcgn_classify_node_fn,
361 .name = "vcgn-classify",
362 .vector_size = sizeof (u32),
363 .format_trace = format_swap_trace,
364 .type = VLIB_NODE_TYPE_INTERNAL,
366 .n_errors = ARRAY_LEN(vcgn_classify_error_strings),
367 .error_strings = vcgn_classify_error_strings,
369 .n_next_nodes = VCGN_CLASSIFY_N_NEXT,
371 /* edit / add dispositions here */
373 [VCGN_CLASSIFY_NEXT_IP4_INPUT] = "ip4-input",
374 [VCGN_CLASSIFY_NEXT_IP6_INPUT] = "ip6-input",
375 [VCGN_CLASSIFY_NEXT_MPLS_INPUT] = "mpls-gre-input",
376 [VCGN_CLASSIFY_NEXT_ETHERNET_INPUT] = "ethernet-input",
377 [VCGN_CLASSIFY_NEXT_UDP_INSIDE] = "vcgn-v4-udp-i2o",
378 [VCGN_CLASSIFY_NEXT_UDP_OUTSIDE] = "vcgn-v4-udp-o2i",
379 [VCGN_CLASSIFY_NEXT_TCP_INSIDE] = "vcgn-v4-tcp-i2o",
380 [VCGN_CLASSIFY_NEXT_TCP_OUTSIDE] = "vcgn-v4-tcp-o2i",
381 [VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE] = "vcgn-v4-icmp-q-i2o",
382 [VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE] = "vcgn-v4-icmp-q-o2i",
383 [VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE] = "vcgn-v4-icmp-e-i2o",
384 [VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE] = "vcgn-v4-icmp-e-o2i"
389 /* A test function to init the vrf map */
391 clib_error_t *vcgn_classify_init (vlib_main_t *vm)
393 vcgn_classify_main_t * mp = &vcgn_classify_main;
396 mp->vnet_main = vnet_get_main();
397 mp->inside_sw_if_index = 1;
398 mp->outside_sw_if_index = 0;
400 dpdk_set_next_node (DPDK_RX_NEXT_IP4_INPUT, "vcgn-classify");
404 pn = pg_get_node (vcgn_classify_node.index);
405 pn->unformat_edit = unformat_pg_ip4_header;
410 VLIB_INIT_FUNCTION (vcgn_classify_init);
412 /* Show command handlers */
413 static clib_error_t *
414 show_vcgn_stats_command_fn (vlib_main_t * vm,
415 unformat_input_t * input,
416 vlib_cli_command_t * cmd)
418 if (cnat_db_init_done) {
419 cnat_nat44_handle_show_stats(vm);
421 vlib_cli_output(vm, "vCGN is not configured !!\n");
427 static clib_error_t *
428 show_vcgn_config_command_fn (vlib_main_t * vm,
429 unformat_input_t * input,
430 vlib_cli_command_t * cmd)
432 cnat_nat44_handle_show_config(vm);
436 static clib_error_t *
437 show_vcgn_inside_translation_command_fn (vlib_main_t * vm,
438 unformat_input_t * input,
439 vlib_cli_command_t * cmd)
442 vnet_main_t * vnm = vnet_get_main();
444 vcgn_classify_main_t * vcm = &vcgn_classify_main;
445 spp_api_cnat_v4_show_inside_entry_req_t inside_req;
447 ip4_address_t inside_addr;
449 u32 end_port = 65535;
451 inside_req.start_port = start_port;
452 inside_req.end_port = end_port;
453 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
454 if (unformat(input, "protocol %s", &proto)) {
455 if (!strncmp((char *) proto, "udp", 3)) {
456 inside_req.protocol = 1;
457 } else if (!strncmp((char *) proto, "tcp", 3)) {
458 inside_req.protocol = 2;
460 inside_req.protocol = 3;
462 } else if (unformat (input, "inside-addr %U",
463 unformat_ip4_address, &inside_addr)) {
464 inside_req.ipv4_addr = clib_net_to_host_u32(inside_addr.as_u32);
465 } else if (unformat(input, "start-port %u", &start_port)) {
466 inside_req.start_port = start_port;
467 } else if (unformat(input, "end-port %u", &end_port)) {
468 inside_req.end_port = end_port;
471 inside_req.vrf_id = vcm->inside_sw_if_index;
472 inside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
473 inside_req.all_entries = 0; /* we can see it later */
475 vlib_cli_output(vm, "proto %d, inside-addr 0x%x, start_port %u, "
476 "end_port %u, vrf 0x%x\n",
478 inside_req.ipv4_addr,
479 inside_req.start_port,
481 vcm->inside_sw_if_index);
483 if (cnat_db_init_done) {
484 cnat_v4_show_inside_entry_req_t_handler(&inside_req, vm);
486 vlib_cli_output(vm, "vCGN is not configured !!\n");
492 static clib_error_t *
493 show_vcgn_outside_translation_command_fn (vlib_main_t * vm,
494 unformat_input_t * input,
495 vlib_cli_command_t * cmd)
497 void cnat_v4_show_outside_entry_req_t_handler
498 (spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm);
499 vcgn_classify_main_t * vcm = &vcgn_classify_main;
500 spp_api_cnat_v4_show_outside_entry_req_t outside_req;
502 ip4_address_t outside_addr;
504 u32 end_port = 65535;
506 outside_req.start_port = start_port;
507 outside_req.end_port = end_port;
508 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
509 if (unformat(input, "protocol %s", &proto)) {
510 if (!strncmp((char *) proto, "udp", 3)) {
511 outside_req.protocol = 1;
512 } else if (!strncmp((char *) proto, "tcp", 3)) {
513 outside_req.protocol = 2;
515 outside_req.protocol = 3;
517 } else if (unformat (input, "outside-addr %U",
518 unformat_ip4_address, &outside_addr)) {
519 outside_req.ipv4_addr = clib_net_to_host_u32(outside_addr.as_u32);
520 } else if (unformat(input, "start-port %u", &start_port)) {
521 outside_req.start_port = start_port;
522 } else if (unformat(input, "end-port %u", &end_port)) {
523 outside_req.end_port = end_port;
526 outside_req.vrf_id = vcm->outside_sw_if_index;
527 outside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
529 vlib_cli_output(vm, "proto %d, outside-addr 0x%x, start_port %u, "
530 "end_port %u, vrf 0x%x\n",
531 outside_req.protocol,
532 outside_req.ipv4_addr,
533 outside_req.start_port,
534 outside_req.end_port,
535 vcm->outside_sw_if_index);
537 if (cnat_db_init_done) {
538 cnat_v4_show_outside_entry_req_t_handler(&outside_req, vm);
540 vlib_cli_output(vm, "vCGN is not configured !!\n");
546 /* Config command handlers */
547 static clib_error_t *
548 set_vcgn_inside_command_fn (vlib_main_t * vm,
549 unformat_input_t * input,
550 vlib_cli_command_t * cmd)
552 vnet_main_t * vnm = vnet_get_main();
553 vcgn_classify_main_t * vcm = &vcgn_classify_main;
554 u32 inside_sw_if_index = 1;
555 u32 outside_sw_if_index = ~0;
556 void cnat_db_v2_init (void );
558 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
559 if (unformat(input, "%U",
560 unformat_vnet_sw_interface, vnm, &inside_sw_if_index))
562 else if (unformat(input, "outside %U",
563 unformat_vnet_sw_interface, vnm, &outside_sw_if_index))
567 if (inside_sw_if_index == ~0 ||
568 outside_sw_if_index == ~0)
569 return clib_error_return (0, "unknown input `%U'",
570 format_unformat_error, input);
572 if (inside_sw_if_index == outside_sw_if_index)
573 return clib_error_return (0, "inside and outside interfaces can't be the same...");
575 vcm->inside_sw_if_index = inside_sw_if_index;
576 vcm->outside_sw_if_index = outside_sw_if_index;
580 /* Turn on the db scanner process */
581 cnat_scanner_db_process_turn_on(vm);
585 static clib_error_t *
586 set_vcgn_map_command_fn (vlib_main_t * vm,
587 unformat_input_t * input,
588 vlib_cli_command_t * cmd)
590 vcgn_classify_main_t * vcm = &vcgn_classify_main;
591 ip4_address_t lo, hi;
592 spp_api_cnat_v4_add_vrf_map_t map;
595 vnet_hw_interface_t *inside_hw_if_index = NULL;
596 vnet_hw_interface_t *outside_hw_if_index = NULL;
598 if (!unformat (input, "%U", unformat_ip4_address, &lo))
599 return clib_error_return (0, "unknown input `%U'",
600 format_unformat_error, input);
602 if (unformat (input, "- %U", unformat_ip4_address, &hi))
605 /* $$$$ remember to set i_vrf, i_vrf_id as needed */
607 /* Fill the structure spp_api_cnat_v4_add_vrf_map_t & let this API handle it */
608 /* i_vrf_id & o_vrf_id are 32-bit & i_vrf, o_vrf are 16 bit */
609 map.i_vrf_id = vcm->inside_sw_if_index;
610 map.o_vrf_id = vcm->outside_sw_if_index;
611 map.i_vrf = vcm->inside_sw_if_index;
612 map.o_vrf = vcm->outside_sw_if_index;
614 map.start_addr[0] = clib_net_to_host_u32(lo.as_u32);
615 map.end_addr[0] = clib_net_to_host_u32(hi.as_u32);
617 for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) {
618 vrf_map_array[i] = VRF_MAP_ENTRY_EMPTY;
620 cnat_nat44_add_vrf_map_t_handler(&map, vm);
623 inside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, vcm->inside_sw_if_index);
624 if (inside_hw_if_index) {
625 vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
626 inside_hw_if_index->hw_if_index, vcgn_classify_node.index);
628 outside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, vcm->outside_sw_if_index);
629 if (outside_hw_if_index) {
630 vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
631 outside_hw_if_index->hw_if_index, vcgn_classify_node.index);
637 static clib_error_t *
638 set_vcgn_tcp_timeout_command_fn (vlib_main_t * vm,
639 unformat_input_t * input,
640 vlib_cli_command_t * cmd)
643 vnet_main_t * vnm = vnet_get_main();
644 vcgn_classify_main_t * vcm = &vcgn_classify_main;
647 u32 init_timeout = 0;
649 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
650 if (unformat(input, "active %u", &act_timeout))
651 tcp_active_timeout = act_timeout;
652 else if (unformat(input, "init %u", &init_timeout))
653 tcp_initial_setup_timeout = init_timeout;
659 static clib_error_t *
660 set_vcgn_udp_timeout_command_fn (vlib_main_t * vm,
661 unformat_input_t * input,
662 vlib_cli_command_t * cmd)
665 vnet_main_t * vnm = vnet_get_main();
666 vcgn_classify_main_t * vcm = &vcgn_classify_main;
669 u32 init_timeout = 0;
671 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
672 if (unformat(input, "active %u", &act_timeout))
673 udp_act_session_timeout = act_timeout;
674 else if (unformat(input, "init %u", &init_timeout))
675 udp_init_session_timeout = init_timeout;
682 static clib_error_t *
683 set_vcgn_icmp_timeout_command_fn (vlib_main_t * vm,
684 unformat_input_t * input,
685 vlib_cli_command_t * cmd)
688 * vnet_main_t * vnm = vnet_get_main();
689 * vcgn_classify_main_t * vcm = &vcgn_classify_main;
693 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
694 if (unformat(input, "%u", &timeout))
698 icmp_session_timeout = timeout;
703 static clib_error_t *
704 set_vcgn_protocol_default_timeout_command_fn (vlib_main_t * vm,
705 unformat_input_t * input,
706 vlib_cli_command_t * cmd)
709 vnet_main_t * vnm = vnet_get_main();
710 vcgn_classify_main_t * vcm = &vcgn_classify_main;
715 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
716 if (unformat(input, "%s", &protocol))
720 cnat_nat44_set_protocol_timeout_value(0, 0, protocol, reset, vm);
724 static clib_error_t *
725 set_vcgn_dynamic_port_start_range_command_fn (vlib_main_t * vm,
726 unformat_input_t * input,
727 vlib_cli_command_t * cmd)
730 vnet_main_t * vnm = vnet_get_main();
731 vcgn_classify_main_t * vcm = &vcgn_classify_main;
735 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
736 if (unformat(input, "%u", &port))
740 if (port != 0 && port > 65535) {
741 vlib_cli_output(vm, "Error !! Invalid port\n");
743 cnat_static_port_range = port;
744 vlib_cli_output(vm, "Dynamic Port Range Config Successful !!\n");
749 static clib_error_t *
750 set_vcgn_port_limit_command_fn (vlib_main_t * vm,
751 unformat_input_t * input,
752 vlib_cli_command_t * cmd)
755 vnet_main_t * vnm = vnet_get_main();
756 vcgn_classify_main_t * vcm = &vcgn_classify_main;
760 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
761 if (unformat(input, "%u", &port))
765 if (port != 0 && port > 65535) {
766 vlib_cli_output(vm, "Error !! Invalid port\n");
768 cnat_main_db_max_ports_per_user = port;
769 vlib_cli_output(vm, "Port Limit Config Successful !!\n");
774 static inline void nfv9_init_pkt_sent_data(cnat_nfv9_logging_info_t *nfv9_info)
776 nfv9_server_info_t *server = nfv9_server_info_pool +
777 nfv9_info->server_index;
780 * Reset the pkts_since_last_template and sent_time
781 * so that template will be sent next time
783 server->last_template_sent_time = 0;
784 server->pkts_since_last_template = 0xffffffff;
787 static inline u16 nfv9_get_max_length_minus_max_record_size(u16 path_mtu)
789 u16 max_length_minus_max_record_size;
790 if(!path_mtu) /* Use default */
791 path_mtu = NFV9_DEF_PATH_MTU;
793 max_length_minus_max_record_size = path_mtu -
794 CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH -
796 CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH; /* Note.. as of now this record
797 * requires max number of bytes. If you add more records,
798 * this needs to be re-checked */
799 if (max_length_minus_max_record_size < CNAT_NFV9_MIN_RECORD_SIZE) {
801 "Resetting max_length_minus_max_record_size from %d to %ld\n",
802 max_length_minus_max_record_size,
803 CNAT_NFV9_MIN_RECORD_SIZE);
805 max_length_minus_max_record_size = CNAT_NFV9_MIN_RECORD_SIZE;
807 return max_length_minus_max_record_size;
810 /* This function finds if the netflow server indicated by
811 * new_server_info is already configured for some other instance
812 * if yes, it returns the same pointer so that, info sent to the
813 * server is consistent. If the server is not found, a new instance
814 * is created and returned. If an existing server is used, its refernce
815 * count is incrimented (indicating the number of instances using the
818 /* #define DEBUG_NF_SERVER_CONFIG 1 */
819 static u16 nfv9_get_server_instance(
820 cnat_nfv9_logging_info_t *nfv9_info, nfv9_server_info_t *new_server_info)
823 /* Check if the instance has a server already and if yes, does it match */
824 nfv9_server_info_t *server;
825 if(nfv9_info->server_index != EMPTY) {
826 server = nfv9_server_info_pool + nfv9_info->server_index;
828 if((server->ipv4_address == new_server_info->ipv4_address) &&
829 (server->port == new_server_info->port)) {
830 /* Same server.. just check if refresh rate/timeouts are reduced */
831 #ifdef DEBUG_NF_SERVER_CONFIG
832 if(my_instance_number == 1) {
833 printf("\n Server match for %x and port %d\n",
834 new_server_info->ipv4_address, new_server_info->port);
836 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
837 goto adjust_refresh_rate;
838 } else { /* The server is being changed */
840 #ifdef DEBUG_NF_SERVER_CONFIG
841 if(my_instance_number == 1) {
842 printf("\n Server change from %x, %d to %x, %d"
844 server->ipv4_address,
846 new_server_info->ipv4_address, new_server_info->port,
849 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
850 if(!server->ref_count) {
851 /* Return this server to pool */
852 #ifdef DEBUG_NF_SERVER_CONFIG
853 if(my_instance_number == 1) {
854 PLATFORM_DEBUG_PRINT("Deleting Server %x, %d at %d\n",
855 server->ipv4_address,
857 nfv9_info->server_index);
859 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
860 pool_put(nfv9_server_info_pool, server);
865 /* Now check if the server is already present in the pool */
868 pool_foreach (server, nfv9_server_info_pool, ({
869 if ((server->ipv4_address == new_server_info->ipv4_address) &&
870 (server->port == new_server_info->port)) {
872 nfv9_info->server_index = server - nfv9_server_info_pool;
874 #ifdef DEBUG_NF_SERVER_CONFIG
875 if(my_instance_number == 1) {
876 printf("Re-using server %x, %d Ref count %d\n",
877 server->ipv4_address, server->port, server->ref_count);
879 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
885 /* Create a new one, initialize and return */
887 pool_get(nfv9_server_info_pool, server);
888 memcpy(server, new_server_info, sizeof(nfv9_server_info_t));
889 server->ref_count = 1;
890 nfv9_info->server_index = server - nfv9_server_info_pool;
891 #ifdef DEBUG_NF_SERVER_CONFIG
892 if(my_instance_number == 1) {
893 printf("Create new server for at %d %x and port %d\n",
894 nfv9_info->server_index,
895 new_server_info->ipv4_address, new_server_info->port);
897 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
902 if(server->refresh_rate >
903 new_server_info->refresh_rate) {
904 server->refresh_rate =
905 new_server_info->refresh_rate;
906 #ifdef DEBUG_NF_SERVER_CONFIG
907 if(my_instance_number == 1) {
908 printf("Reset refresh rate to %d\n",
909 server->refresh_rate);
911 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
914 if(server->timeout_rate >
915 new_server_info->timeout_rate) {
916 server->timeout_rate =
917 new_server_info->timeout_rate;
918 #ifdef DEBUG_NF_SERVER_CONFIG
919 if(my_instance_number == 1) {
920 printf("Reset timeout rate to %d\n",
921 server->timeout_rate);
923 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
928 static clib_error_t *
929 set_vcgn_nfv9_logging_cofig_command_fn (vlib_main_t * vm,
930 unformat_input_t * input,
931 vlib_cli_command_t * cmd)
933 vcgn_classify_main_t * vcm = &vcgn_classify_main;
934 spp_api_cnat_v4_config_nfv9_logging_t nfv9_conf;
935 ip4_address_t server_addr;
938 u32 refresh_rate = 0;
942 /* vcgn changes start*/
943 cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL;
944 cnat_nfv9_logging_info_t *my_nfv9_logging_info_tmp = NULL;
945 cnat_vrfmap_t *my_vrfmap = 0, *my_vrfmap_temp;
951 * Init NFv9 logging info as needed, this will be done only once
953 cnat_nfv9_logging_init();
955 i_vrf = vcm->inside_sw_if_index;
956 i_vrf_id = vcm->inside_sw_if_index;
960 /* vcgn changes end*/
961 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
962 if (unformat (input, "server %U", unformat_ip4_address, &server_addr))
963 ip_addr = clib_net_to_host_u32(server_addr.as_u32);
964 else if (unformat(input, "port %u", &port))
966 else if (unformat(input, "refresh-rate %u", &refresh_rate))
968 else if (unformat(input, "timeout %u", &timeout))
970 else if (unformat(input, "pmtu %u", &pmtu))
972 else if (unformat(input, "del"))
979 vlib_cli_output(vm, "ip 0x%x, port %u, refresh %u, "
980 "timeout %u, pmtu %u enable %u\n",
981 ip_addr, port, refresh_rate,
982 timeout, pmtu, enable);
984 nfv9_conf.enable = enable;
985 nfv9_conf.ipv4_address = ip_addr;
986 nfv9_conf.i_vrf_id = vcm->inside_sw_if_index;
987 nfv9_conf.i_vrf = vcm->inside_sw_if_index;
988 nfv9_conf.port = port;
989 nfv9_conf.refresh_rate = refresh_rate;
990 nfv9_conf.timeout_rate = timeout;
991 nfv9_conf.path_mtu = pmtu;
992 nfv9_conf.nfv9_global_collector = 0;
993 nfv9_conf.session_logging = 0;
996 * At this point the NFv9 global information should already be
997 * inited as we have called cnat_nfv9_logging_init()
1000 if (nfv9_conf.nfv9_global_collector) {
1001 if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) {
1003 my_nfv9_logging_info = cnat_nfv9_logging_info_pool +
1004 cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1007 /* Do we already have a map for this VRF? */
1008 pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1009 if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) {
1011 printf("found_vrf %d\n", found_vrf);
1012 nfv9_server_info_t *server = nfv9_server_info_pool +
1013 my_nfv9_logging_info->server_index;
1014 printf("server ip4 0x%x port %d\n", server->ipv4_address, server->port);
1015 printf("nfv9_conf v4 0x%x port %d\n", nfv9_conf.ipv4_address, nfv9_conf.port);
1016 if((server->ipv4_address == (nfv9_conf.ipv4_address)) && (server->port == (nfv9_conf.port))) {
1018 my_nfv9_logging_info_tmp = my_nfv9_logging_info;
1019 printf("found %d\n", found);
1026 if ((nfv9_conf.ipv4_address == 0) ||
1027 (nfv9_conf.port == 0)) {
1029 "Add NFv9 ivrf %d Logging Invalid values [IPv4 0x%x, PORT %d]\n",
1031 (nfv9_conf.ipv4_address),
1036 if (nfv9_conf.enable) {
1037 if ((nfv9_conf.ipv4_address == 0) ||
1038 (nfv9_conf.port == 0)) {
1039 nfv9_conf.rc = CNAT_ERR_PARSER;
1041 "NFV9_logging i_vrf %d, Invalid [v4_addr 0x%x port %d]\n",
1043 (nfv9_conf.ipv4_address),
1048 nfv9_server_info_t new_server_info;
1049 memset(&new_server_info, 0, sizeof(nfv9_server_info_t));
1050 new_server_info.ipv4_address =
1051 nfv9_conf.ipv4_address;
1052 new_server_info.port =
1054 new_server_info.refresh_rate =
1055 (nfv9_conf.refresh_rate);
1057 * Store the timeout in seconds. User configures it in minutes
1059 new_server_info.timeout_rate =
1060 60*(nfv9_conf.timeout_rate);
1061 if (found && my_nfv9_logging_info) {
1063 * Entry already present, change it
1065 my_nfv9_logging_info->max_length_minus_max_record_size =
1066 nfv9_get_max_length_minus_max_record_size(
1067 ((nfv9_conf.path_mtu)));
1069 pool_get(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1070 memset(my_nfv9_logging_info, 0, sizeof(*my_nfv9_logging_info));
1071 my_nfv9_logging_info->server_index = EMPTY;
1072 my_nfv9_logging_info->nfv9_logging_next_index = EMPTY;
1074 * Make the current and head logging context indeices as EMPTY.
1075 * When first logging happens, these get set correctly
1077 my_nfv9_logging_info->current_logging_context = NULL;
1078 my_nfv9_logging_info->queued_logging_context = NULL;
1080 my_nfv9_logging_info->f = NULL;
1081 my_nfv9_logging_info->to_next = NULL;
1082 output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-input");
1083 my_nfv9_logging_info->ip4_input_node_index = output_node->index;
1084 printf("ip4_input_node_index %d\n", my_nfv9_logging_info->ip4_input_node_index);
1086 my_nfv9_logging_info->i_vrf = i_vrf;
1087 my_nfv9_logging_info->i_vrf_id = i_vrf_id;
1088 my_nfv9_logging_info->max_length_minus_max_record_size =
1089 nfv9_get_max_length_minus_max_record_size(
1090 nfv9_conf.path_mtu);
1092 /* my_nfv9_logging_info will have a copy of logging_policy
1093 * because, it is quite possible that nfv9 config arrives before
1094 * the corresponding vrfmap is initialized. In such cases
1095 * this copy will be used to update the vrfmap entry
1097 my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1099 if (nfv9_conf.nfv9_global_collector) {
1100 cnat_nfv9_global_info.cnat_nfv9_global_collector_index =
1101 my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1103 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1104 if (my_vrfmap->nfv9_logging_index == EMPTY) {
1105 my_vrfmap->nfv9_logging_index =
1106 cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1110 u32 my_vrfmap_found = 0;
1112 FIND_MY_VRF_USING_I_VRF_ID
1113 my_vrfmap = my_vrfmap_temp;
1114 if (my_vrfmap_found) {
1115 if(my_vrfmap->nfv9_logging_index == EMPTY) {
1116 my_vrfmap->nfv9_logging_index =
1117 my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1118 // my_vrfmap->nf_logging_policy = mp->session_logging;
1120 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index;
1121 while(my_nfv9_logging_info_temp->nfv9_logging_next_index != EMPTY){
1122 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_nfv9_logging_info_temp->nfv9_logging_next_index;
1124 my_nfv9_logging_info_temp->nfv9_logging_next_index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1130 /* Update logging policy */
1131 my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1132 if (nfv9_conf.nfv9_global_collector) {
1133 if(PLATFORM_DBL_SUPPORT) {
1134 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1135 if (my_vrfmap->nfv9_logging_index ==
1136 cnat_nfv9_global_info.cnat_nfv9_global_collector_index) {
1137 my_vrfmap->nf_logging_policy = nfv9_conf.session_logging;
1141 nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1144 if(PLATFORM_DBL_SUPPORT) {
1145 u32 my_vrfmap_found = 0;
1146 my_vrfmap_temp = NULL;
1147 FIND_MY_VRF_USING_I_VRF_ID
1148 my_vrfmap = my_vrfmap_temp;
1149 if (my_vrfmap_found) {
1150 // my_vrfmap->nf_logging_policy = mp->session_logging;
1153 nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1156 u8 nfv9_logging_policy = 0;
1157 u32 my_vrfmap_found = 0;
1158 my_vrfmap_temp = NULL;
1159 FIND_MY_VRF_USING_I_VRF_ID
1160 my_vrfmap = my_vrfmap_temp;
1161 if (my_vrfmap_found) {
1162 u32 index_curr = my_vrfmap->nfv9_logging_index;
1163 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1164 while(index_curr != EMPTY) {
1165 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1166 nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1167 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1169 my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1171 //vlib_cli_output(vm,"Netflow logging policy = %d\n", my_vrfmap->nf_logging_policy);
1172 if(nfv9_get_server_instance(my_nfv9_logging_info, &new_server_info)
1174 vlib_cli_output(vm, "Error to get server instance");
1175 nfv9_conf.rc = CNAT_ERR_PARSER;
1178 nfv9_init_pkt_sent_data(my_nfv9_logging_info);
1180 vlib_cli_output(vm,"Adding NFv9 Logging Succeeded\n");
1181 nfv9_configured = 1;
1186 /* if found entry then we need to overwrite the my_nfv9_logging_info_tmp
1187 * to my_nfv9_logging_info
1189 my_nfv9_logging_info = my_nfv9_logging_info_tmp;
1190 if (i_vrf == INVALID_UIDX) {
1192 * We are deleting a global collector. Mark the collectors
1193 * in those VRFs using the global collector
1195 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1196 if (my_vrfmap->nfv9_logging_index ==
1197 cnat_nfv9_global_info.cnat_nfv9_global_collector_index) {
1198 my_vrfmap->nfv9_logging_index = EMPTY;
1202 cnat_nfv9_global_info.cnat_nfv9_global_collector_index = EMPTY;
1204 u32 my_vrfmap_found = 0;
1205 my_vrfmap_temp = NULL;
1206 FIND_MY_VRF_USING_I_VRF_ID
1207 my_vrfmap = my_vrfmap_temp;
1208 if (my_vrfmap_found) {
1209 // my_vrfmap->nfv9_logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1212 if (my_nfv9_logging_info->queued_logging_context ||
1213 my_nfv9_logging_info->current_logging_context) {
1215 * If there is a pending context:
1216 * Set the deleted flag to 1. This will ensure
1217 * that the logging info structure gets freed after any
1218 * pending packet get sent
1220 my_nfv9_logging_info->deleted = 1;
1223 * No pending context, just free the logging info structure
1225 u32 index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1226 if(index == my_vrfmap->nfv9_logging_index) {
1227 /* Deleting the first sever */
1228 my_vrfmap->nfv9_logging_index = my_nfv9_logging_info->nfv9_logging_next_index;
1229 /* if(my_nfv9_logging_info->nfv9_logging_next_index != EMPTY){
1230 my_vrfmap->nf_logging_policy = (cnat_nfv9_logging_info_pool + my_nfv9_logging_info->nfv9_logging_next_index)->logging_policy;
1232 my_vrfmap->nf_logging_policy = EMPTY;
1235 u32 index_curr = my_vrfmap->nfv9_logging_index;
1236 u32 index_prev = EMPTY;
1237 while(index_curr != EMPTY) {
1238 index_prev = index_curr;
1239 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1240 if(index == index_curr)
1242 (cnat_nfv9_logging_info_pool + index_prev)->nfv9_logging_next_index = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1247 nfv9_delete_server_info(my_nfv9_logging_info);
1248 pool_put(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1251 vlib_cli_output(vm, "Deleting NFv9 Logging Succeeded\n");
1253 * Search across all vrf and check if nfv9 logging is configured.
1255 nfv9_configured = 0;
1256 pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1257 nfv9_configured = 1;
1261 nfv9_conf.rc = CNAT_NO_CONFIG;
1262 vlib_cli_output(vm, "Add NFv9 Logging Failed (2) Non Existent vrf %d\n",
1266 u8 nfv9_logging_policy = 0;
1267 u32 my_vrfmap_found = 0;
1268 my_vrfmap_temp = NULL;
1269 FIND_MY_VRF_USING_I_VRF_ID
1270 my_vrfmap = my_vrfmap_temp;
1271 if (my_vrfmap_found) {
1272 u32 index_curr = my_vrfmap->nfv9_logging_index;
1273 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1274 while(index_curr != EMPTY) {
1275 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1276 nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1277 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1279 my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1281 printf("After deleting the netflow server,Netflow logging policy = %d\n", my_vrfmap->nf_logging_policy);
1289 VLIB_CLI_COMMAND (set_vcgn_map_command) = {
1290 .path = "set vcgn map",
1291 .short_help = "set vcgn map <lo-address> [- <hi-address>]",
1292 .function = set_vcgn_map_command_fn,
1295 VLIB_CLI_COMMAND (set_vcgn_inside_command) = {
1296 .path = "set vcgn inside",
1297 .short_help = "set vcgn inside <inside intfc> outside <outside intfc>",
1298 .function = set_vcgn_inside_command_fn,
1301 VLIB_CLI_COMMAND (set_vcgn_tcp_timeout_command) = {
1302 .path = "set vcgn tcp timeout",
1303 .short_help = "set vcgn tcp timeout active <1-65535> init <1-65535>",
1304 .function = set_vcgn_tcp_timeout_command_fn,
1307 VLIB_CLI_COMMAND (set_vcgn_udp_timeout_command) = {
1308 .path = "set vcgn udp timeout",
1309 .short_help = "set vcgn udp timeout active <1-65535> init <1-65535>",
1310 .function = set_vcgn_udp_timeout_command_fn,
1313 VLIB_CLI_COMMAND (set_vcgn_icmp_timeout_command) = {
1314 .path = "set vcgn icmp timeout",
1315 .short_help = "set vcgn icmp timeout <1-65535>",
1316 .function = set_vcgn_icmp_timeout_command_fn,
1319 VLIB_CLI_COMMAND (set_vcgn_protocol_default_timeout_command) = {
1320 .path = "set vcgn default timeout",
1321 .short_help = "set vcgn default timeout protocol <tcp/udp/icmp>",
1322 .function = set_vcgn_protocol_default_timeout_command_fn,
1325 VLIB_CLI_COMMAND (set_vcgn_dynamic_port_start_range_command) = {
1326 .path = "set vcgn dynamic port start",
1327 .short_help = "set vcgn dynamic port start <1-65535>",
1328 .function = set_vcgn_dynamic_port_start_range_command_fn,
1331 VLIB_CLI_COMMAND (set_vcgn_port_limit_command) = {
1332 .path = "set vcgn port limit",
1333 .short_help = "set vcgn port limit <1-65535>",
1334 .function = set_vcgn_port_limit_command_fn,
1337 VLIB_CLI_COMMAND (set_vcgn_nfv9_logging_cofig_command) = {
1338 .path = "set vcgn nfv9",
1339 .short_help = "set vcgn nfv9 [del] server <ip-addr> port <port> [refresh-rate <n>] [timeout <n>] [pmtu <n>]",
1340 .function = set_vcgn_nfv9_logging_cofig_command_fn,
1345 VLIB_CLI_COMMAND (show_vcgn_config_command) = {
1346 .path = "show vcgn config",
1347 .short_help = "show vcgn config",
1348 .function = show_vcgn_config_command_fn,
1351 VLIB_CLI_COMMAND (show_vcgn_stat_command) = {
1352 .path = "show vcgn statistics",
1353 .short_help = "show vcgn statistics",
1354 .function = show_vcgn_stats_command_fn,
1357 VLIB_CLI_COMMAND (show_vcgn_inside_translation_command) = {
1358 .path = "show vcgn inside-translation",
1359 .short_help = "show vcgn inside-translation protocol <tcp/udp/icmp> "
1360 "inside-addr <ip-addr> [start-port <n>] [end-port <n>]",
1361 .function = show_vcgn_inside_translation_command_fn,
1364 VLIB_CLI_COMMAND (show_vcgn_outside_translation_command) = {
1365 .path = "show vcgn outside-translation",
1366 .short_help = "show vcgn outside-translation protocol <tcp/udp/icmp> "
1367 "outside-addr <ip-addr> [start-port <n>] [end-port <n>]",
1368 .function = show_vcgn_outside_translation_command_fn,
1371 static clib_error_t *
1372 vcgn_init (vlib_main_t * vm)
1374 clib_error_t * error = 0;
1376 if ((error = vlib_call_init_function
1377 (vm, vcgn_classify_init)))
1379 if ((error = vlib_call_init_function
1380 (vm, cnat_ipv4_udp_inside_input_init)))
1382 if ((error = vlib_call_init_function
1383 (vm, cnat_ipv4_udp_outside_input_init)))
1385 if ((error = vlib_call_init_function
1386 (vm, cnat_ipv4_udp_inside_input_exc_init)))
1388 if ((error = vlib_call_init_function
1389 (vm, cnat_db_scanner_init)))
1391 if ((error = vlib_call_init_function
1392 (vm, cnat_ipv4_tcp_inside_input_init)))
1394 if ((error = vlib_call_init_function
1395 (vm, cnat_ipv4_tcp_inside_input_exc_init)))
1397 if ((error = vlib_call_init_function
1398 (vm, cnat_ipv4_tcp_outside_input_init)))
1400 if ((error = vlib_call_init_function
1401 (vm, cnat_ipv4_icmp_q_inside_input_init)))
1403 if ((error = vlib_call_init_function
1404 (vm, cnat_ipv4_icmp_q_inside_input_exc_init)))
1406 if ((error = vlib_call_init_function
1407 (vm, cnat_ipv4_icmp_q_outside_input_init)))
1409 if ((error = vlib_call_init_function
1410 (vm, cnat_ipv4_icmp_e_inside_input_init)))
1412 if ((error = vlib_call_init_function
1413 (vm, cnat_ipv4_icmp_e_outside_input_init)))
1419 VLIB_INIT_FUNCTION (vcgn_init);