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;
401 dpdk_set_next_node (DPDK_RX_NEXT_IP4_INPUT, "vcgn-classify");
406 pn = pg_get_node (vcgn_classify_node.index);
407 pn->unformat_edit = unformat_pg_ip4_header;
412 VLIB_INIT_FUNCTION (vcgn_classify_init);
414 /* Show command handlers */
415 static clib_error_t *
416 show_vcgn_stats_command_fn (vlib_main_t * vm,
417 unformat_input_t * input,
418 vlib_cli_command_t * cmd)
420 if (cnat_db_init_done) {
421 cnat_nat44_handle_show_stats(vm);
423 vlib_cli_output(vm, "vCGN is not configured !!\n");
429 static clib_error_t *
430 show_vcgn_config_command_fn (vlib_main_t * vm,
431 unformat_input_t * input,
432 vlib_cli_command_t * cmd)
434 cnat_nat44_handle_show_config(vm);
438 static clib_error_t *
439 show_vcgn_inside_translation_command_fn (vlib_main_t * vm,
440 unformat_input_t * input,
441 vlib_cli_command_t * cmd)
444 vnet_main_t * vnm = vnet_get_main();
446 vcgn_classify_main_t * vcm = &vcgn_classify_main;
447 spp_api_cnat_v4_show_inside_entry_req_t inside_req;
449 ip4_address_t inside_addr;
451 u32 end_port = 65535;
453 inside_req.start_port = start_port;
454 inside_req.end_port = end_port;
455 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
456 if (unformat(input, "protocol %s", &proto)) {
457 if (!strncmp((char *) proto, "udp", 3)) {
458 inside_req.protocol = 1;
459 } else if (!strncmp((char *) proto, "tcp", 3)) {
460 inside_req.protocol = 2;
462 inside_req.protocol = 3;
464 } else if (unformat (input, "inside-addr %U",
465 unformat_ip4_address, &inside_addr)) {
466 inside_req.ipv4_addr = clib_net_to_host_u32(inside_addr.as_u32);
467 } else if (unformat(input, "start-port %u", &start_port)) {
468 inside_req.start_port = start_port;
469 } else if (unformat(input, "end-port %u", &end_port)) {
470 inside_req.end_port = end_port;
473 inside_req.vrf_id = vcm->inside_sw_if_index;
474 inside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
475 inside_req.all_entries = 0; /* we can see it later */
477 vlib_cli_output(vm, "proto %d, inside-addr 0x%x, start_port %u, "
478 "end_port %u, vrf 0x%x\n",
480 inside_req.ipv4_addr,
481 inside_req.start_port,
483 vcm->inside_sw_if_index);
485 if (cnat_db_init_done) {
486 cnat_v4_show_inside_entry_req_t_handler(&inside_req, vm);
488 vlib_cli_output(vm, "vCGN is not configured !!\n");
494 static clib_error_t *
495 show_vcgn_outside_translation_command_fn (vlib_main_t * vm,
496 unformat_input_t * input,
497 vlib_cli_command_t * cmd)
499 void cnat_v4_show_outside_entry_req_t_handler
500 (spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm);
501 vcgn_classify_main_t * vcm = &vcgn_classify_main;
502 spp_api_cnat_v4_show_outside_entry_req_t outside_req;
504 ip4_address_t outside_addr;
506 u32 end_port = 65535;
508 outside_req.start_port = start_port;
509 outside_req.end_port = end_port;
510 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
511 if (unformat(input, "protocol %s", &proto)) {
512 if (!strncmp((char *) proto, "udp", 3)) {
513 outside_req.protocol = 1;
514 } else if (!strncmp((char *) proto, "tcp", 3)) {
515 outside_req.protocol = 2;
517 outside_req.protocol = 3;
519 } else if (unformat (input, "outside-addr %U",
520 unformat_ip4_address, &outside_addr)) {
521 outside_req.ipv4_addr = clib_net_to_host_u32(outside_addr.as_u32);
522 } else if (unformat(input, "start-port %u", &start_port)) {
523 outside_req.start_port = start_port;
524 } else if (unformat(input, "end-port %u", &end_port)) {
525 outside_req.end_port = end_port;
528 outside_req.vrf_id = vcm->outside_sw_if_index;
529 outside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
531 vlib_cli_output(vm, "proto %d, outside-addr 0x%x, start_port %u, "
532 "end_port %u, vrf 0x%x\n",
533 outside_req.protocol,
534 outside_req.ipv4_addr,
535 outside_req.start_port,
536 outside_req.end_port,
537 vcm->outside_sw_if_index);
539 if (cnat_db_init_done) {
540 cnat_v4_show_outside_entry_req_t_handler(&outside_req, vm);
542 vlib_cli_output(vm, "vCGN is not configured !!\n");
548 /* Config command handlers */
549 static clib_error_t *
550 set_vcgn_inside_command_fn (vlib_main_t * vm,
551 unformat_input_t * input,
552 vlib_cli_command_t * cmd)
554 vnet_main_t * vnm = vnet_get_main();
555 vcgn_classify_main_t * vcm = &vcgn_classify_main;
556 u32 inside_sw_if_index = 1;
557 u32 outside_sw_if_index = ~0;
558 void cnat_db_v2_init (void );
560 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
561 if (unformat(input, "%U",
562 unformat_vnet_sw_interface, vnm, &inside_sw_if_index))
564 else if (unformat(input, "outside %U",
565 unformat_vnet_sw_interface, vnm, &outside_sw_if_index))
569 if (inside_sw_if_index == ~0 ||
570 outside_sw_if_index == ~0)
571 return clib_error_return (0, "unknown input `%U'",
572 format_unformat_error, input);
574 if (inside_sw_if_index == outside_sw_if_index)
575 return clib_error_return (0, "inside and outside interfaces can't be the same...");
577 vcm->inside_sw_if_index = inside_sw_if_index;
578 vcm->outside_sw_if_index = outside_sw_if_index;
582 /* Turn on the db scanner process */
583 cnat_scanner_db_process_turn_on(vm);
587 static clib_error_t *
588 set_vcgn_map_command_fn (vlib_main_t * vm,
589 unformat_input_t * input,
590 vlib_cli_command_t * cmd)
592 vcgn_classify_main_t * vcm = &vcgn_classify_main;
593 ip4_address_t lo, hi;
594 spp_api_cnat_v4_add_vrf_map_t map;
597 vnet_hw_interface_t *inside_hw_if_index = NULL;
598 vnet_hw_interface_t *outside_hw_if_index = NULL;
600 if (!unformat (input, "%U", unformat_ip4_address, &lo))
601 return clib_error_return (0, "unknown input `%U'",
602 format_unformat_error, input);
604 if (unformat (input, "- %U", unformat_ip4_address, &hi))
607 /* $$$$ remember to set i_vrf, i_vrf_id as needed */
609 /* Fill the structure spp_api_cnat_v4_add_vrf_map_t & let this API handle it */
610 /* i_vrf_id & o_vrf_id are 32-bit & i_vrf, o_vrf are 16 bit */
611 map.i_vrf_id = vcm->inside_sw_if_index;
612 map.o_vrf_id = vcm->outside_sw_if_index;
613 map.i_vrf = vcm->inside_sw_if_index;
614 map.o_vrf = vcm->outside_sw_if_index;
616 map.start_addr[0] = clib_net_to_host_u32(lo.as_u32);
617 map.end_addr[0] = clib_net_to_host_u32(hi.as_u32);
619 for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) {
620 vrf_map_array[i] = VRF_MAP_ENTRY_EMPTY;
622 cnat_nat44_add_vrf_map_t_handler(&map, vm);
625 inside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, vcm->inside_sw_if_index);
626 if (inside_hw_if_index) {
627 vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
628 inside_hw_if_index->hw_if_index, vcgn_classify_node.index);
630 outside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, vcm->outside_sw_if_index);
631 if (outside_hw_if_index) {
632 vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
633 outside_hw_if_index->hw_if_index, vcgn_classify_node.index);
639 static clib_error_t *
640 set_vcgn_tcp_timeout_command_fn (vlib_main_t * vm,
641 unformat_input_t * input,
642 vlib_cli_command_t * cmd)
645 vnet_main_t * vnm = vnet_get_main();
646 vcgn_classify_main_t * vcm = &vcgn_classify_main;
649 u32 init_timeout = 0;
651 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
652 if (unformat(input, "active %u", &act_timeout))
653 tcp_active_timeout = act_timeout;
654 else if (unformat(input, "init %u", &init_timeout))
655 tcp_initial_setup_timeout = init_timeout;
661 static clib_error_t *
662 set_vcgn_udp_timeout_command_fn (vlib_main_t * vm,
663 unformat_input_t * input,
664 vlib_cli_command_t * cmd)
667 vnet_main_t * vnm = vnet_get_main();
668 vcgn_classify_main_t * vcm = &vcgn_classify_main;
671 u32 init_timeout = 0;
673 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
674 if (unformat(input, "active %u", &act_timeout))
675 udp_act_session_timeout = act_timeout;
676 else if (unformat(input, "init %u", &init_timeout))
677 udp_init_session_timeout = init_timeout;
684 static clib_error_t *
685 set_vcgn_icmp_timeout_command_fn (vlib_main_t * vm,
686 unformat_input_t * input,
687 vlib_cli_command_t * cmd)
690 * vnet_main_t * vnm = vnet_get_main();
691 * vcgn_classify_main_t * vcm = &vcgn_classify_main;
695 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
696 if (unformat(input, "%u", &timeout))
700 icmp_session_timeout = timeout;
705 static clib_error_t *
706 set_vcgn_protocol_default_timeout_command_fn (vlib_main_t * vm,
707 unformat_input_t * input,
708 vlib_cli_command_t * cmd)
711 vnet_main_t * vnm = vnet_get_main();
712 vcgn_classify_main_t * vcm = &vcgn_classify_main;
717 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
718 if (unformat(input, "%s", &protocol))
722 cnat_nat44_set_protocol_timeout_value(0, 0, protocol, reset, vm);
726 static clib_error_t *
727 set_vcgn_dynamic_port_start_range_command_fn (vlib_main_t * vm,
728 unformat_input_t * input,
729 vlib_cli_command_t * cmd)
732 vnet_main_t * vnm = vnet_get_main();
733 vcgn_classify_main_t * vcm = &vcgn_classify_main;
737 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
738 if (unformat(input, "%u", &port))
742 if (port != 0 && port > 65535) {
743 vlib_cli_output(vm, "Error !! Invalid port\n");
745 cnat_static_port_range = port;
746 vlib_cli_output(vm, "Dynamic Port Range Config Successful !!\n");
751 static clib_error_t *
752 set_vcgn_port_limit_command_fn (vlib_main_t * vm,
753 unformat_input_t * input,
754 vlib_cli_command_t * cmd)
757 vnet_main_t * vnm = vnet_get_main();
758 vcgn_classify_main_t * vcm = &vcgn_classify_main;
762 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
763 if (unformat(input, "%u", &port))
767 if (port != 0 && port > 65535) {
768 vlib_cli_output(vm, "Error !! Invalid port\n");
770 cnat_main_db_max_ports_per_user = port;
771 vlib_cli_output(vm, "Port Limit Config Successful !!\n");
776 static inline void nfv9_init_pkt_sent_data(cnat_nfv9_logging_info_t *nfv9_info)
778 nfv9_server_info_t *server = nfv9_server_info_pool +
779 nfv9_info->server_index;
782 * Reset the pkts_since_last_template and sent_time
783 * so that template will be sent next time
785 server->last_template_sent_time = 0;
786 server->pkts_since_last_template = 0xffffffff;
789 static inline u16 nfv9_get_max_length_minus_max_record_size(u16 path_mtu)
791 u16 max_length_minus_max_record_size;
792 if(!path_mtu) /* Use default */
793 path_mtu = NFV9_DEF_PATH_MTU;
795 max_length_minus_max_record_size = path_mtu -
796 CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH -
798 CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH; /* Note.. as of now this record
799 * requires max number of bytes. If you add more records,
800 * this needs to be re-checked */
801 if (max_length_minus_max_record_size < CNAT_NFV9_MIN_RECORD_SIZE) {
802 max_length_minus_max_record_size = CNAT_NFV9_MIN_RECORD_SIZE;
804 return max_length_minus_max_record_size;
807 /* This function finds if the netflow server indicated by
808 * new_server_info is already configured for some other instance
809 * if yes, it returns the same pointer so that, info sent to the
810 * server is consistent. If the server is not found, a new instance
811 * is created and returned. If an existing server is used, its refernce
812 * count is incrimented (indicating the number of instances using the
815 /* #define DEBUG_NF_SERVER_CONFIG 1 */
816 static u16 nfv9_get_server_instance(
817 cnat_nfv9_logging_info_t *nfv9_info, nfv9_server_info_t *new_server_info)
820 /* Check if the instance has a server already and if yes, does it match */
821 nfv9_server_info_t *server;
822 if(nfv9_info->server_index != EMPTY) {
823 server = nfv9_server_info_pool + nfv9_info->server_index;
825 if((server->ipv4_address == new_server_info->ipv4_address) &&
826 (server->port == new_server_info->port)) {
827 /* Same server.. just check if refresh rate/timeouts are reduced */
828 #ifdef DEBUG_NF_SERVER_CONFIG
829 if(my_instance_number == 1) {
830 printf("\n Server match for %x and port %d\n",
831 new_server_info->ipv4_address, new_server_info->port);
833 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
834 goto adjust_refresh_rate;
835 } else { /* The server is being changed */
837 #ifdef DEBUG_NF_SERVER_CONFIG
838 if(my_instance_number == 1) {
839 printf("\n Server change from %x, %d to %x, %d"
841 server->ipv4_address,
843 new_server_info->ipv4_address, new_server_info->port,
846 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
847 if(!server->ref_count) {
848 /* Return this server to pool */
849 #ifdef DEBUG_NF_SERVER_CONFIG
850 if(my_instance_number == 1) {
851 PLATFORM_DEBUG_PRINT("Deleting Server %x, %d at %d\n",
852 server->ipv4_address,
854 nfv9_info->server_index);
856 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
857 pool_put(nfv9_server_info_pool, server);
862 /* Now check if the server is already present in the pool */
865 pool_foreach (server, nfv9_server_info_pool, ({
866 if ((server->ipv4_address == new_server_info->ipv4_address) &&
867 (server->port == new_server_info->port)) {
869 nfv9_info->server_index = server - nfv9_server_info_pool;
871 #ifdef DEBUG_NF_SERVER_CONFIG
872 if(my_instance_number == 1) {
873 printf("Re-using server %x, %d Ref count %d\n",
874 server->ipv4_address, server->port, server->ref_count);
876 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
882 /* Create a new one, initialize and return */
884 pool_get(nfv9_server_info_pool, server);
885 memcpy(server, new_server_info, sizeof(nfv9_server_info_t));
886 server->ref_count = 1;
887 nfv9_info->server_index = server - nfv9_server_info_pool;
888 #ifdef DEBUG_NF_SERVER_CONFIG
889 if(my_instance_number == 1) {
890 printf("Create new server for at %d %x and port %d\n",
891 nfv9_info->server_index,
892 new_server_info->ipv4_address, new_server_info->port);
894 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
899 if(server->refresh_rate >
900 new_server_info->refresh_rate) {
901 server->refresh_rate =
902 new_server_info->refresh_rate;
903 #ifdef DEBUG_NF_SERVER_CONFIG
904 if(my_instance_number == 1) {
905 printf("Reset refresh rate to %d\n",
906 server->refresh_rate);
908 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
911 if(server->timeout_rate >
912 new_server_info->timeout_rate) {
913 server->timeout_rate =
914 new_server_info->timeout_rate;
915 #ifdef DEBUG_NF_SERVER_CONFIG
916 if(my_instance_number == 1) {
917 printf("Reset timeout rate to %d\n",
918 server->timeout_rate);
920 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
925 static clib_error_t *
926 set_vcgn_nfv9_logging_cofig_command_fn (vlib_main_t * vm,
927 unformat_input_t * input,
928 vlib_cli_command_t * cmd)
930 vcgn_classify_main_t * vcm = &vcgn_classify_main;
931 spp_api_cnat_v4_config_nfv9_logging_t nfv9_conf;
932 ip4_address_t server_addr;
935 u32 refresh_rate = 0;
939 /* vcgn changes start*/
940 cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL;
941 cnat_nfv9_logging_info_t *my_nfv9_logging_info_tmp = NULL;
942 cnat_vrfmap_t *my_vrfmap = 0, *my_vrfmap_temp;
947 * Init NFv9 logging info as needed, this will be done only once
949 cnat_nfv9_logging_init();
951 i_vrf = vcm->inside_sw_if_index;
952 i_vrf_id = vcm->inside_sw_if_index;
956 /* vcgn changes end*/
957 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
958 if (unformat (input, "server %U", unformat_ip4_address, &server_addr))
959 ip_addr = clib_net_to_host_u32(server_addr.as_u32);
960 else if (unformat(input, "port %u", &port))
962 else if (unformat(input, "refresh-rate %u", &refresh_rate))
964 else if (unformat(input, "timeout %u", &timeout))
966 else if (unformat(input, "pmtu %u", &pmtu))
968 else if (unformat(input, "del"))
975 vlib_cli_output(vm, "ip 0x%x, port %u, refresh %u, "
976 "timeout %u, pmtu %u enable %u\n",
977 ip_addr, port, refresh_rate,
978 timeout, pmtu, enable);
980 if (refresh_rate == 0) refresh_rate = 500; /* num of pkts */
981 if (timeout == 0) timeout = 30; /* in mins */
983 nfv9_conf.enable = enable;
984 nfv9_conf.ipv4_address = ip_addr;
985 nfv9_conf.i_vrf_id = vcm->inside_sw_if_index;
986 nfv9_conf.i_vrf = vcm->inside_sw_if_index;
987 nfv9_conf.port = port;
988 nfv9_conf.refresh_rate = refresh_rate;
989 nfv9_conf.timeout_rate = timeout;
990 nfv9_conf.path_mtu = pmtu;
991 nfv9_conf.nfv9_global_collector = 0;
992 nfv9_conf.session_logging = 0;
995 * At this point the NFv9 global information should already be
996 * inited as we have called cnat_nfv9_logging_init()
999 if (nfv9_conf.nfv9_global_collector) {
1000 if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) {
1002 my_nfv9_logging_info = cnat_nfv9_logging_info_pool +
1003 cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1006 /* Do we already have a map for this VRF? */
1007 pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1008 if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) {
1009 nfv9_server_info_t *server = nfv9_server_info_pool +
1010 my_nfv9_logging_info->server_index;
1011 if((server->ipv4_address == (nfv9_conf.ipv4_address)) && (server->port == (nfv9_conf.port))) {
1013 my_nfv9_logging_info_tmp = my_nfv9_logging_info;
1020 if ((nfv9_conf.ipv4_address == 0) ||
1021 (nfv9_conf.port == 0)) {
1023 "Add NFv9 ivrf %d Logging Invalid values [IPv4 0x%x, PORT %d]\n",
1025 (nfv9_conf.ipv4_address),
1030 if (nfv9_conf.enable) {
1031 if ((nfv9_conf.ipv4_address == 0) ||
1032 (nfv9_conf.port == 0)) {
1033 nfv9_conf.rc = CNAT_ERR_PARSER;
1035 "NFV9_logging i_vrf %d, Invalid [v4_addr 0x%x port %d]\n",
1037 (nfv9_conf.ipv4_address),
1042 nfv9_server_info_t new_server_info;
1043 memset(&new_server_info, 0, sizeof(nfv9_server_info_t));
1044 new_server_info.ipv4_address =
1045 nfv9_conf.ipv4_address;
1046 new_server_info.port =
1048 new_server_info.refresh_rate =
1049 (nfv9_conf.refresh_rate);
1051 * Store the timeout in seconds. User configures it in minutes
1053 new_server_info.timeout_rate =
1054 60*(nfv9_conf.timeout_rate);
1055 if (found && my_nfv9_logging_info) {
1057 * Entry already present, change it
1059 my_nfv9_logging_info->max_length_minus_max_record_size =
1060 nfv9_get_max_length_minus_max_record_size(
1061 ((nfv9_conf.path_mtu)));
1063 pool_get(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1064 memset(my_nfv9_logging_info, 0, sizeof(*my_nfv9_logging_info));
1065 my_nfv9_logging_info->server_index = EMPTY;
1066 my_nfv9_logging_info->nfv9_logging_next_index = EMPTY;
1068 * Make the current and head logging context indeices as EMPTY.
1069 * When first logging happens, these get set correctly
1071 my_nfv9_logging_info->current_logging_context = NULL;
1072 my_nfv9_logging_info->queued_logging_context = NULL;
1074 my_nfv9_logging_info->f = NULL;
1075 my_nfv9_logging_info->to_next = NULL;
1076 output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-input");
1077 my_nfv9_logging_info->ip4_input_node_index = output_node->index;
1078 printf("ip4_input_node_index %d\n", my_nfv9_logging_info->ip4_input_node_index);
1080 my_nfv9_logging_info->i_vrf = i_vrf;
1081 my_nfv9_logging_info->i_vrf_id = i_vrf_id;
1082 my_nfv9_logging_info->max_length_minus_max_record_size =
1083 nfv9_get_max_length_minus_max_record_size(
1084 nfv9_conf.path_mtu);
1086 /* my_nfv9_logging_info will have a copy of logging_policy
1087 * because, it is quite possible that nfv9 config arrives before
1088 * the corresponding vrfmap is initialized. In such cases
1089 * this copy will be used to update the vrfmap entry
1091 my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1093 if (nfv9_conf.nfv9_global_collector) {
1094 cnat_nfv9_global_info.cnat_nfv9_global_collector_index =
1095 my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1097 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1098 if (my_vrfmap->nfv9_logging_index == EMPTY) {
1099 my_vrfmap->nfv9_logging_index =
1100 cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1104 u32 my_vrfmap_found = 0;
1106 FIND_MY_VRF_USING_I_VRF_ID
1107 my_vrfmap = my_vrfmap_temp;
1108 if (my_vrfmap_found) {
1109 if(my_vrfmap->nfv9_logging_index == EMPTY) {
1110 my_vrfmap->nfv9_logging_index =
1111 my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1112 // my_vrfmap->nf_logging_policy = mp->session_logging;
1114 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index;
1115 while(my_nfv9_logging_info_temp->nfv9_logging_next_index != EMPTY){
1116 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_nfv9_logging_info_temp->nfv9_logging_next_index;
1118 my_nfv9_logging_info_temp->nfv9_logging_next_index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1124 /* Update logging policy */
1125 my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1126 if (nfv9_conf.nfv9_global_collector) {
1127 if(PLATFORM_DBL_SUPPORT) {
1128 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1129 if (my_vrfmap->nfv9_logging_index ==
1130 cnat_nfv9_global_info.cnat_nfv9_global_collector_index) {
1131 my_vrfmap->nf_logging_policy = nfv9_conf.session_logging;
1135 nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1138 if(PLATFORM_DBL_SUPPORT) {
1139 u32 my_vrfmap_found = 0;
1140 my_vrfmap_temp = NULL;
1141 FIND_MY_VRF_USING_I_VRF_ID
1142 my_vrfmap = my_vrfmap_temp;
1143 if (my_vrfmap_found) {
1144 // my_vrfmap->nf_logging_policy = mp->session_logging;
1147 nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1150 u8 nfv9_logging_policy = 0;
1151 u32 my_vrfmap_found = 0;
1152 my_vrfmap_temp = NULL;
1153 FIND_MY_VRF_USING_I_VRF_ID
1154 my_vrfmap = my_vrfmap_temp;
1155 if (my_vrfmap_found) {
1156 u32 index_curr = my_vrfmap->nfv9_logging_index;
1157 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1158 while(index_curr != EMPTY) {
1159 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1160 nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1161 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1163 my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1165 //vlib_cli_output(vm,"Netflow logging policy = %d\n", my_vrfmap->nf_logging_policy);
1166 if(nfv9_get_server_instance(my_nfv9_logging_info, &new_server_info)
1168 vlib_cli_output(vm, "Error to get server instance");
1169 nfv9_conf.rc = CNAT_ERR_PARSER;
1172 nfv9_init_pkt_sent_data(my_nfv9_logging_info);
1174 vlib_cli_output(vm,"Adding NFv9 Logging Succeeded\n");
1175 nfv9_configured = 1;
1180 /* if found entry then we need to overwrite the my_nfv9_logging_info_tmp
1181 * to my_nfv9_logging_info
1183 my_nfv9_logging_info = my_nfv9_logging_info_tmp;
1184 if (i_vrf == INVALID_UIDX) {
1186 * We are deleting a global collector. Mark the collectors
1187 * in those VRFs using the global collector
1189 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1190 if (my_vrfmap->nfv9_logging_index ==
1191 cnat_nfv9_global_info.cnat_nfv9_global_collector_index) {
1192 my_vrfmap->nfv9_logging_index = EMPTY;
1196 cnat_nfv9_global_info.cnat_nfv9_global_collector_index = EMPTY;
1198 u32 my_vrfmap_found = 0;
1199 my_vrfmap_temp = NULL;
1200 FIND_MY_VRF_USING_I_VRF_ID
1201 my_vrfmap = my_vrfmap_temp;
1202 if (my_vrfmap_found) {
1203 // my_vrfmap->nfv9_logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1206 if (my_nfv9_logging_info->queued_logging_context ||
1207 my_nfv9_logging_info->current_logging_context) {
1209 * If there is a pending context:
1210 * Set the deleted flag to 1. This will ensure
1211 * that the logging info structure gets freed after any
1212 * pending packet get sent
1214 my_nfv9_logging_info->deleted = 1;
1217 * No pending context, just free the logging info structure
1219 u32 index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1220 if(index == my_vrfmap->nfv9_logging_index) {
1221 /* Deleting the first sever */
1222 my_vrfmap->nfv9_logging_index = my_nfv9_logging_info->nfv9_logging_next_index;
1223 /* if(my_nfv9_logging_info->nfv9_logging_next_index != EMPTY){
1224 my_vrfmap->nf_logging_policy = (cnat_nfv9_logging_info_pool + my_nfv9_logging_info->nfv9_logging_next_index)->logging_policy;
1226 my_vrfmap->nf_logging_policy = EMPTY;
1229 u32 index_curr = my_vrfmap->nfv9_logging_index;
1230 u32 index_prev = EMPTY;
1231 while(index_curr != EMPTY) {
1232 index_prev = index_curr;
1233 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1234 if(index == index_curr)
1236 (cnat_nfv9_logging_info_pool + index_prev)->nfv9_logging_next_index = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1241 nfv9_delete_server_info(my_nfv9_logging_info);
1242 pool_put(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1245 vlib_cli_output(vm, "Deleting NFv9 Logging Succeeded\n");
1247 * Search across all vrf and check if nfv9 logging is configured.
1249 nfv9_configured = 0;
1250 pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1251 nfv9_configured = 1;
1255 nfv9_conf.rc = CNAT_NO_CONFIG;
1256 vlib_cli_output(vm, "Add NFv9 Logging Failed (2) Non Existent vrf %d\n",
1260 u8 nfv9_logging_policy = 0;
1261 u32 my_vrfmap_found = 0;
1262 my_vrfmap_temp = NULL;
1263 FIND_MY_VRF_USING_I_VRF_ID
1264 my_vrfmap = my_vrfmap_temp;
1265 if (my_vrfmap_found) {
1266 u32 index_curr = my_vrfmap->nfv9_logging_index;
1267 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1268 while(index_curr != EMPTY) {
1269 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1270 nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1271 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1273 my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1282 VLIB_CLI_COMMAND (set_vcgn_map_command) = {
1283 .path = "set vcgn map",
1284 .short_help = "set vcgn map <lo-address> [- <hi-address>]",
1285 .function = set_vcgn_map_command_fn,
1288 VLIB_CLI_COMMAND (set_vcgn_inside_command) = {
1289 .path = "set vcgn inside",
1290 .short_help = "set vcgn inside <inside intfc> outside <outside intfc>",
1291 .function = set_vcgn_inside_command_fn,
1294 VLIB_CLI_COMMAND (set_vcgn_tcp_timeout_command) = {
1295 .path = "set vcgn tcp timeout",
1296 .short_help = "set vcgn tcp timeout active <1-65535> init <1-65535>",
1297 .function = set_vcgn_tcp_timeout_command_fn,
1300 VLIB_CLI_COMMAND (set_vcgn_udp_timeout_command) = {
1301 .path = "set vcgn udp timeout",
1302 .short_help = "set vcgn udp timeout active <1-65535> init <1-65535>",
1303 .function = set_vcgn_udp_timeout_command_fn,
1306 VLIB_CLI_COMMAND (set_vcgn_icmp_timeout_command) = {
1307 .path = "set vcgn icmp timeout",
1308 .short_help = "set vcgn icmp timeout <1-65535>",
1309 .function = set_vcgn_icmp_timeout_command_fn,
1312 VLIB_CLI_COMMAND (set_vcgn_protocol_default_timeout_command) = {
1313 .path = "set vcgn default timeout",
1314 .short_help = "set vcgn default timeout protocol <tcp/udp/icmp>",
1315 .function = set_vcgn_protocol_default_timeout_command_fn,
1318 VLIB_CLI_COMMAND (set_vcgn_dynamic_port_start_range_command) = {
1319 .path = "set vcgn dynamic port start",
1320 .short_help = "set vcgn dynamic port start <1-65535>",
1321 .function = set_vcgn_dynamic_port_start_range_command_fn,
1324 VLIB_CLI_COMMAND (set_vcgn_port_limit_command) = {
1325 .path = "set vcgn port limit",
1326 .short_help = "set vcgn port limit <1-65535>",
1327 .function = set_vcgn_port_limit_command_fn,
1330 VLIB_CLI_COMMAND (set_vcgn_nfv9_logging_cofig_command) = {
1331 .path = "set vcgn nfv9",
1332 .short_help = "set vcgn nfv9 [del] server <ip-addr> port <port> [refresh-rate <n>] [timeout <n>] [pmtu <n>]",
1333 .function = set_vcgn_nfv9_logging_cofig_command_fn,
1338 VLIB_CLI_COMMAND (show_vcgn_config_command) = {
1339 .path = "show vcgn config",
1340 .short_help = "show vcgn config",
1341 .function = show_vcgn_config_command_fn,
1344 VLIB_CLI_COMMAND (show_vcgn_stat_command) = {
1345 .path = "show vcgn statistics",
1346 .short_help = "show vcgn statistics",
1347 .function = show_vcgn_stats_command_fn,
1350 VLIB_CLI_COMMAND (show_vcgn_inside_translation_command) = {
1351 .path = "show vcgn inside-translation",
1352 .short_help = "show vcgn inside-translation protocol <tcp/udp/icmp> "
1353 "inside-addr <ip-addr> [start-port <n>] [end-port <n>]",
1354 .function = show_vcgn_inside_translation_command_fn,
1357 VLIB_CLI_COMMAND (show_vcgn_outside_translation_command) = {
1358 .path = "show vcgn outside-translation",
1359 .short_help = "show vcgn outside-translation protocol <tcp/udp/icmp> "
1360 "outside-addr <ip-addr> [start-port <n>] [end-port <n>]",
1361 .function = show_vcgn_outside_translation_command_fn,
1364 static clib_error_t *
1365 vcgn_init (vlib_main_t * vm)
1367 clib_error_t * error = 0;
1369 if ((error = vlib_call_init_function
1370 (vm, vcgn_classify_init)))
1372 if ((error = vlib_call_init_function
1373 (vm, cnat_ipv4_udp_inside_input_init)))
1375 if ((error = vlib_call_init_function
1376 (vm, cnat_ipv4_udp_outside_input_init)))
1378 if ((error = vlib_call_init_function
1379 (vm, cnat_ipv4_udp_inside_input_exc_init)))
1381 if ((error = vlib_call_init_function
1382 (vm, cnat_db_scanner_init)))
1384 if ((error = vlib_call_init_function
1385 (vm, cnat_ipv4_tcp_inside_input_init)))
1387 if ((error = vlib_call_init_function
1388 (vm, cnat_ipv4_tcp_inside_input_exc_init)))
1390 if ((error = vlib_call_init_function
1391 (vm, cnat_ipv4_tcp_outside_input_init)))
1393 if ((error = vlib_call_init_function
1394 (vm, cnat_ipv4_icmp_q_inside_input_init)))
1396 if ((error = vlib_call_init_function
1397 (vm, cnat_ipv4_icmp_q_inside_input_exc_init)))
1399 if ((error = vlib_call_init_function
1400 (vm, cnat_ipv4_icmp_q_outside_input_init)))
1402 if ((error = vlib_call_init_function
1403 (vm, cnat_ipv4_icmp_e_inside_input_init)))
1405 if ((error = vlib_call_init_function
1406 (vm, cnat_ipv4_icmp_e_outside_input_init)))
1412 VLIB_INIT_FUNCTION (vcgn_init);