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_table;
43 u32 * outside_sw_if_index_table;
45 /* convenience variables */
46 vlib_main_t * vlib_main;
47 vnet_main_t * vnet_main;
48 u8 cnat_db_initalized;
49 } vcgn_classify_main_t;
52 /* $$$$ fill in with per-pkt trace data */
57 } vcgn_classify_trace_t;
59 #define FIND_MY_VRF_USING_I_VRF_ID \
60 my_vrfmap_found = 0; \
61 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ \
62 if (my_vrfmap->i_vrf_id == i_vrf_id) { \
63 my_vrfmap_found = 1; \
64 my_vrfmap_temp = my_vrfmap; \
70 /* packet trace format function */
71 static u8 * format_swap_trace (u8 * s, va_list * args)
73 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
74 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
75 vcgn_classify_trace_t * t = va_arg (*args, vcgn_classify_trace_t *);
77 s = format (s, "VCGN_CLASSIFY: dst %U dst_port %d sw_if_index %d next %d",
78 format_ip4_address, (ip4_header_t *) &t->orig_dst_address,
79 clib_net_to_host_u16(t->orig_dst_port),
80 t->sw_if_index, t->next_index);
84 vcgn_classify_main_t vcgn_classify_main;
86 vlib_node_registration_t vcgn_classify_node;
88 #define foreach_vcgn_classify_error \
89 _(PACKETS_RECEIVED, "total packets received") \
90 _(V4_PACKETS_PROCESSED, "ipv4 packets processed for vCGN") \
91 _(V4_PACKETS_PUNTED, "ipv4 packets punted") \
92 _(V6_PACKETS_PUNTED, "ipv6 packets punted") \
93 _(MPLS_PACKETS_PUNTED, "mpls unicast packets punted") \
94 _(ETH_PACKETS_PUNTED, "ethernet packets punted")
98 #define _(sym,str) VCGN_CLASSIFY_ERROR_##sym,
99 foreach_vcgn_classify_error
101 VCGN_CLASSIFY_N_ERROR,
102 } vcgn_classify_error_t;
104 static char * vcgn_classify_error_strings[] = {
105 #define _(sym,string) string,
106 foreach_vcgn_classify_error
111 * To drop a pkt and increment one of the previous counters:
113 * set b0->error = error_node->errors[VCGN_CLASSIFY_ERROR_EXAMPLE];
114 * set next0 to a disposition index bound to "error-drop".
116 * To manually increment the specific counter VCGN_CLASSIFY_ERROR_EXAMPLE:
118 * vlib_node_t *n = vlib_get_node (vm, vcgn_classify.index);
119 * u32 node_counter_base_index = n->error_heap_index;
120 * vlib_error_main_t * em = &vm->error_main;
121 * em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_EXAMPLE] += 1;
126 VCGN_CLASSIFY_NEXT_IP4_INPUT,
127 VCGN_CLASSIFY_NEXT_IP6_INPUT,
128 VCGN_CLASSIFY_NEXT_MPLS_INPUT,
129 VCGN_CLASSIFY_NEXT_ETHERNET_INPUT,
130 VCGN_CLASSIFY_NEXT_UDP_INSIDE,
131 VCGN_CLASSIFY_NEXT_UDP_OUTSIDE,
132 VCGN_CLASSIFY_NEXT_TCP_INSIDE,
133 VCGN_CLASSIFY_NEXT_TCP_OUTSIDE,
134 VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE,
135 VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE,
136 VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE,
137 VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE,
138 VCGN_CLASSIFY_N_NEXT,
139 } vcgn_classify_next_t;
142 vcgn_classify_node_fn (vlib_main_t * vm,
143 vlib_node_runtime_t * node,
144 vlib_frame_t * frame)
146 u32 n_left_from, * from, * to_next;
147 vcgn_classify_next_t next_index;
148 vcgn_classify_main_t * vcm = &vcgn_classify_main;
149 vlib_node_t *n = vlib_get_node (vm, vcgn_classify_node.index);
150 u32 node_counter_base_index = n->error_heap_index;
151 vlib_error_main_t * em = &vm->error_main;
155 from = vlib_frame_vector_args (frame);
156 n_left_from = frame->n_vectors;
157 next_index = node->cached_next_index;
159 while (n_left_from > 0)
163 vlib_get_next_frame (vm, node, next_index,
164 to_next, n_left_to_next);
167 while (n_left_from >= 4 && n_left_to_next >= 2)
170 vlib_buffer_t * b0, * b1;
172 u32 sw_if_index0, sw_if_index1;
174 /* Prefetch next iteration. */
176 vlib_buffer_t * p2, * p3;
178 p2 = vlib_get_buffer (vm, from[2]);
179 p3 = vlib_get_buffer (vm, from[3]);
181 vlib_prefetch_buffer_header (p2, LOAD);
182 vlib_prefetch_buffer_header (p3, LOAD);
184 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
185 CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
188 /* speculatively enqueue b0 and b1 to the current next frame */
189 to_next[0] = bi0 = from[0];
190 to_next[1] = bi1 = from[1];
196 b0 = vlib_get_buffer (vm, bi0);
197 b1 = vlib_get_buffer (vm, bi1);
199 sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
200 next0 = vcm->cached_next_index;
201 sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
202 next1 = vcm->cached_next_index;
204 /* $$$$ your message in this space. Process 2 x pkts */
205 em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 2;
207 if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)))
209 if (b0->flags & VLIB_BUFFER_IS_TRACED)
211 vcgn_classify_trace_t *t =
212 vlib_add_trace (vm, node, b0, sizeof (*t));
213 t->sw_if_index = sw_if_index0;
214 t->next_index = next0;
216 if (b1->flags & VLIB_BUFFER_IS_TRACED)
218 vcgn_classify_trace_t *t =
219 vlib_add_trace (vm, node, b1, sizeof (*t));
220 t->sw_if_index = sw_if_index1;
221 t->next_index = next1;
225 /* verify speculative enqueues, maybe switch current next frame */
226 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
227 to_next, n_left_to_next,
228 bi0, bi1, next0, next1);
232 while (n_left_from > 0 && n_left_to_next > 0)
240 ethernet_header_t *eth0;
245 /* speculatively enqueue b0 to the current next frame */
253 b0 = vlib_get_buffer (vm, bi0);
255 eth0 = (ethernet_header_t *) vlib_buffer_get_current(b0);
256 u16 *etype = ð0->type;
258 /* vlan tag 0x8100 */
259 if (*etype == clib_host_to_net_u16(ETHERNET_TYPE_VLAN)) {
260 l3_type = (etype + 1); /* Skip 2 bytes of vlan id */
261 vlib_buffer_advance(b0, 18);
264 vlib_buffer_advance(b0, 14);
266 /* Handling v4 pkts 0x800 */
267 if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP4)) {
269 h0 = vlib_buffer_get_current (b0);
271 u8 protocol_type = h0->protocol;
273 sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
274 next0 = VCGN_CLASSIFY_NEXT_IP4_INPUT;
275 counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PROCESSED;
277 if (protocol_type == 0x11) { /* UDP# 17 */
278 next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
279 vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
280 VCGN_CLASSIFY_NEXT_UDP_INSIDE : next0;
282 next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
283 vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
284 VCGN_CLASSIFY_NEXT_UDP_OUTSIDE : next0;
286 } else if (protocol_type == 0x06) { /* TCP# 6 */
287 next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
288 vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
289 VCGN_CLASSIFY_NEXT_TCP_INSIDE : next0;
291 next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
292 vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
293 VCGN_CLASSIFY_NEXT_TCP_OUTSIDE : next0;
295 } else if (protocol_type == 0x01) { /* ICMP # 1 */
297 ipv4_hdr_len = (h0->ip_version_and_header_length & 0xf) << 2;
298 icmp = (icmp_v4_t *)((u8*)h0 + ipv4_hdr_len);
299 icmp_type = icmp->type;
301 if ((icmp_type == ICMPV4_ECHO) ||
302 (icmp_type == ICMPV4_ECHOREPLY)) {
303 next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
304 vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
305 VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE : next0;
307 next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
308 vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
309 VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE : next0;
312 next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
313 vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
314 VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE : next0;
316 next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
317 vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
318 VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE : next0;
321 /* cannot do NATting with this L4 protocol */
322 counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PUNTED;
325 if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
326 && (b0->flags & VLIB_BUFFER_IS_TRACED))) {
327 udp_header_t * u0 = (udp_header_t *)(h0+1);
328 vcgn_classify_trace_t *t =
329 vlib_add_trace (vm, node, b0, sizeof (*t));
330 t->sw_if_index = sw_if_index0;
331 t->next_index = next0;
332 t->orig_dst_address = h0->dst_address.as_u32;
333 t->orig_dst_port = u0->dst_port;
336 } else if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP6)) {
339 next0 = VCGN_CLASSIFY_NEXT_IP6_INPUT;
340 counter = VCGN_CLASSIFY_ERROR_V6_PACKETS_PUNTED;
342 } else if (*l3_type ==
343 clib_host_to_net_u16(ETHERNET_TYPE_MPLS_UNICAST)) {
345 /* MPLS unicast 0x8847 */
346 next0 = VCGN_CLASSIFY_NEXT_MPLS_INPUT;
347 counter = VCGN_CLASSIFY_ERROR_MPLS_PACKETS_PUNTED;
348 } else { /* Remaining all should be pushed to "ethernet-input" */
350 next0 = VCGN_CLASSIFY_NEXT_ETHERNET_INPUT;
351 counter = VCGN_CLASSIFY_ERROR_ETH_PACKETS_PUNTED;
354 em->counters[node_counter_base_index + counter] += 1;
355 em->counters[node_counter_base_index +
356 VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 1;
358 /* verify speculative enqueue, maybe switch current next frame */
359 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
360 to_next, n_left_to_next,
364 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
367 return frame->n_vectors;
370 VLIB_REGISTER_NODE (vcgn_classify_node) = {
371 .function = vcgn_classify_node_fn,
372 .name = "vcgn-classify",
373 .vector_size = sizeof (u32),
374 .format_trace = format_swap_trace,
375 .type = VLIB_NODE_TYPE_INTERNAL,
377 .n_errors = ARRAY_LEN(vcgn_classify_error_strings),
378 .error_strings = vcgn_classify_error_strings,
380 .n_next_nodes = VCGN_CLASSIFY_N_NEXT,
382 /* edit / add dispositions here */
384 [VCGN_CLASSIFY_NEXT_IP4_INPUT] = "ip4-input",
385 [VCGN_CLASSIFY_NEXT_IP6_INPUT] = "ip6-input",
386 [VCGN_CLASSIFY_NEXT_MPLS_INPUT] = "mpls-gre-input",
387 [VCGN_CLASSIFY_NEXT_ETHERNET_INPUT] = "ethernet-input",
388 [VCGN_CLASSIFY_NEXT_UDP_INSIDE] = "vcgn-v4-udp-i2o",
389 [VCGN_CLASSIFY_NEXT_UDP_OUTSIDE] = "vcgn-v4-udp-o2i",
390 [VCGN_CLASSIFY_NEXT_TCP_INSIDE] = "vcgn-v4-tcp-i2o",
391 [VCGN_CLASSIFY_NEXT_TCP_OUTSIDE] = "vcgn-v4-tcp-o2i",
392 [VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE] = "vcgn-v4-icmp-q-i2o",
393 [VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE] = "vcgn-v4-icmp-q-o2i",
394 [VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE] = "vcgn-v4-icmp-e-i2o",
395 [VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE] = "vcgn-v4-icmp-e-o2i"
400 /* A test function to init the vrf map */
402 clib_error_t *vcgn_classify_init (vlib_main_t *vm)
404 vcgn_classify_main_t * mp = &vcgn_classify_main;
407 mp->vnet_main = vnet_get_main();
408 u32 inside_sw_if_index = 1;
409 u32 outside_sw_if_index = 0;
411 vec_validate_init_empty (mp->inside_sw_if_index_table,
412 inside_sw_if_index + 1, EMPTY);
413 vec_validate_init_empty (mp->outside_sw_if_index_table,
414 outside_sw_if_index + 1, EMPTY);
417 * inside_sw_if_index cell of the table stores outside_sw_if_index
418 * and vice versa. This is ensurs pair of indices being remembered
419 * using one mem-location.
421 mp->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index;
422 mp->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index;
425 dpdk_set_next_node (DPDK_RX_NEXT_IP4_INPUT, "vcgn-classify");
430 pn = pg_get_node (vcgn_classify_node.index);
431 pn->unformat_edit = unformat_pg_ip4_header;
436 VLIB_INIT_FUNCTION (vcgn_classify_init);
438 /* Show command handlers */
439 static clib_error_t *
440 show_vcgn_stats_command_fn (vlib_main_t * vm,
441 unformat_input_t * input,
442 vlib_cli_command_t * cmd)
444 if (cnat_db_init_done) {
445 cnat_nat44_handle_show_stats(vm);
447 vlib_cli_output(vm, "vCGN is not configured !!\n");
453 static clib_error_t *
454 show_vcgn_config_command_fn (vlib_main_t * vm,
455 unformat_input_t * input,
456 vlib_cli_command_t * cmd)
458 cnat_nat44_handle_show_config(vm);
462 static clib_error_t *
463 show_vcgn_inside_translation_command_fn (vlib_main_t * vm,
464 unformat_input_t * input,
465 vlib_cli_command_t * cmd)
467 vnet_main_t * vnm = vnet_get_main();
468 vcgn_classify_main_t * vcm = &vcgn_classify_main;
469 spp_api_cnat_v4_show_inside_entry_req_t inside_req;
471 ip4_address_t inside_addr;
473 u32 end_port = 65535;
474 u32 inside_sw_if_index = EMPTY;
476 inside_req.start_port = start_port;
477 inside_req.end_port = end_port;
478 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
479 if (unformat(input, "protocol %s", &proto)) {
480 if (!strncmp((char *) proto, "udp", 3)) {
481 inside_req.protocol = 1;
482 } else if (!strncmp((char *) proto, "tcp", 3)) {
483 inside_req.protocol = 2;
485 inside_req.protocol = 3;
487 } else if (unformat (input, "interface %U",
488 unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) {
489 if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
490 vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
491 return clib_error_return (0, "Could not find the inside interface");
493 } else if (unformat (input, "inside-addr %U",
494 unformat_ip4_address, &inside_addr)) {
495 inside_req.ipv4_addr = clib_net_to_host_u32(inside_addr.as_u32);
496 } else if (unformat(input, "start-port %u", &start_port)) {
497 inside_req.start_port = start_port;
498 } else if (unformat(input, "end-port %u", &end_port)) {
499 inside_req.end_port = end_port;
502 inside_req.vrf_id = inside_sw_if_index;
503 inside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
504 inside_req.all_entries = 0; /* we can see it later */
506 vlib_cli_output(vm, "proto %d, inside-addr 0x%x, start_port %u, "
507 "end_port %u, vrf 0x%x\n",
509 inside_req.ipv4_addr,
510 inside_req.start_port,
514 if (cnat_db_init_done) {
515 cnat_v4_show_inside_entry_req_t_handler(&inside_req, vm);
517 vlib_cli_output(vm, "vCGN is not configured !!\n");
523 static clib_error_t *
524 show_vcgn_outside_translation_command_fn (vlib_main_t * vm,
525 unformat_input_t * input,
526 vlib_cli_command_t * cmd)
528 void cnat_v4_show_outside_entry_req_t_handler
529 (spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm);
530 vnet_main_t * vnm = vnet_get_main();
531 vcgn_classify_main_t * vcm = &vcgn_classify_main;
532 spp_api_cnat_v4_show_outside_entry_req_t outside_req;
534 ip4_address_t outside_addr;
536 u32 end_port = 65535;
537 u32 outside_sw_if_index = EMPTY;
540 outside_req.start_port = start_port;
541 outside_req.end_port = end_port;
542 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
543 if (unformat(input, "protocol %s", &proto)) {
544 if (!strncmp((char *) proto, "udp", 3)) {
545 outside_req.protocol = 1;
546 } else if (!strncmp((char *) proto, "tcp", 3)) {
547 outside_req.protocol = 2;
549 outside_req.protocol = 3;
551 } else if (unformat (input, "interface %U",
552 unformat_vnet_sw_interface, vnm, &outside_sw_if_index)) {
553 if (outside_sw_if_index > vec_len(vcm->outside_sw_if_index_table) ||
554 vcm->outside_sw_if_index_table[outside_sw_if_index] == EMPTY) {
555 return clib_error_return (0, "Could not find the outside interface");
557 } else if (unformat (input, "outside-addr %U",
558 unformat_ip4_address, &outside_addr)) {
559 outside_req.ipv4_addr = clib_net_to_host_u32(outside_addr.as_u32);
560 } else if (unformat(input, "start-port %u", &start_port)) {
561 outside_req.start_port = start_port;
562 } else if (unformat(input, "end-port %u", &end_port)) {
563 outside_req.end_port = end_port;
566 outside_req.vrf_id = outside_sw_if_index;
567 outside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
569 vlib_cli_output(vm, "proto %d, outside-addr 0x%x, start_port %u, "
570 "end_port %u, vrf 0x%x\n",
571 outside_req.protocol,
572 outside_req.ipv4_addr,
573 outside_req.start_port,
574 outside_req.end_port,
575 outside_sw_if_index);
577 if (cnat_db_init_done) {
578 cnat_v4_show_outside_entry_req_t_handler(&outside_req, vm);
580 vlib_cli_output(vm, "vCGN is not configured !!\n");
586 /* Config command handlers */
587 static clib_error_t *
588 set_vcgn_inside_command_fn (vlib_main_t * vm,
589 unformat_input_t * input,
590 vlib_cli_command_t * cmd)
592 vnet_main_t * vnm = vnet_get_main();
593 vcgn_classify_main_t * vcm = &vcgn_classify_main;
594 u32 inside_sw_if_index = 1;
595 u32 outside_sw_if_index = ~0;
596 void cnat_db_v2_init (void );
598 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
599 if (unformat(input, "%U",
600 unformat_vnet_sw_interface, vnm, &inside_sw_if_index))
602 else if (unformat(input, "outside %U",
603 unformat_vnet_sw_interface, vnm, &outside_sw_if_index))
607 if (inside_sw_if_index == ~0 ||
608 outside_sw_if_index == ~0)
609 return clib_error_return (0, "unknown input `%U'",
610 format_unformat_error, input);
612 if (inside_sw_if_index == outside_sw_if_index)
613 return clib_error_return (0, "inside and outside interfaces can't be the same...");
616 * Initialize in/out sw_if_index table. Could use
617 * non-indexed table to reduce memory. However, this
618 * is consulted in vcgn_classify for every packet.
619 * Therefore, table is indexed by sw_if_index.
621 vec_validate_init_empty (vcm->inside_sw_if_index_table,
622 inside_sw_if_index + 1, EMPTY);
623 vec_validate_init_empty (vcm->outside_sw_if_index_table,
624 outside_sw_if_index + 1, EMPTY);
627 * inside_sw_if_index cell of the table stores outside_sw_if_index
628 * and vice versa. This is ensurs pair of indices being remembered
629 * using one mem-location.
631 vcm->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index;
632 vcm->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index;
634 if (! vcm->cnat_db_initalized) {
638 for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) {
639 vrf_map_array[i] = VRF_MAP_ENTRY_EMPTY;
641 /* Turn on the db scanner process */
642 cnat_scanner_db_process_turn_on(vm);
643 vcm->cnat_db_initalized = 1;
648 static clib_error_t *
649 set_vcgn_map_command_fn (vlib_main_t * vm,
650 unformat_input_t * input,
651 vlib_cli_command_t * cmd)
653 vnet_main_t * vnm = vnet_get_main();
654 vcgn_classify_main_t * vcm = &vcgn_classify_main;
655 ip4_address_t lo, hi;
656 spp_api_cnat_v4_add_vrf_map_t map;
657 u32 inside_sw_if_index = EMPTY;
658 u32 outside_sw_if_index;
660 vnet_hw_interface_t *inside_hw_if_index = NULL;
661 vnet_hw_interface_t *outside_hw_if_index = NULL;
663 if (! unformat(input, "inside %U",
664 unformat_vnet_sw_interface, vnm, &inside_sw_if_index))
665 return clib_error_return (0, "unknown input `%U'",
666 format_unformat_error, input);
668 if (!unformat (input, "%U", unformat_ip4_address, &lo))
669 return clib_error_return (0, "unknown input `%U'",
670 format_unformat_error, input);
672 if (unformat (input, "- %U", unformat_ip4_address, &hi))
675 /* $$$$ remember to set i_vrf, i_vrf_id as needed */
677 /* Fill the structure spp_api_cnat_v4_add_vrf_map_t & let this API handle it */
678 /* i_vrf_id & o_vrf_id are 32-bit & i_vrf, o_vrf are 16 bit */
680 if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
681 vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
682 return clib_error_return (0, "Could not find the inside interface");
684 outside_sw_if_index = vcm->inside_sw_if_index_table[inside_sw_if_index];
686 map.i_vrf_id = inside_sw_if_index;
687 map.o_vrf_id = outside_sw_if_index;
688 map.i_vrf = inside_sw_if_index;
689 map.o_vrf = outside_sw_if_index;
691 map.start_addr[0] = clib_net_to_host_u32(lo.as_u32);
692 map.end_addr[0] = clib_net_to_host_u32(hi.as_u32);
694 cnat_nat44_add_vrf_map_t_handler(&map, vm);
697 inside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, inside_sw_if_index);
698 if (inside_hw_if_index) {
699 vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
700 inside_hw_if_index->hw_if_index, vcgn_classify_node.index);
702 outside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, outside_sw_if_index);
703 if (outside_hw_if_index) {
704 vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main,
705 outside_hw_if_index->hw_if_index, vcgn_classify_node.index);
711 static clib_error_t *
712 set_vcgn_tcp_timeout_command_fn (vlib_main_t * vm,
713 unformat_input_t * input,
714 vlib_cli_command_t * cmd)
717 vnet_main_t * vnm = vnet_get_main();
718 vcgn_classify_main_t * vcm = &vcgn_classify_main;
721 u32 init_timeout = 0;
723 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
724 if (unformat(input, "active %u", &act_timeout))
725 tcp_active_timeout = act_timeout;
726 else if (unformat(input, "init %u", &init_timeout))
727 tcp_initial_setup_timeout = init_timeout;
733 static clib_error_t *
734 set_vcgn_udp_timeout_command_fn (vlib_main_t * vm,
735 unformat_input_t * input,
736 vlib_cli_command_t * cmd)
739 vnet_main_t * vnm = vnet_get_main();
740 vcgn_classify_main_t * vcm = &vcgn_classify_main;
743 u32 init_timeout = 0;
745 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
746 if (unformat(input, "active %u", &act_timeout))
747 udp_act_session_timeout = act_timeout;
748 else if (unformat(input, "init %u", &init_timeout))
749 udp_init_session_timeout = init_timeout;
756 static clib_error_t *
757 set_vcgn_icmp_timeout_command_fn (vlib_main_t * vm,
758 unformat_input_t * input,
759 vlib_cli_command_t * cmd)
762 * vnet_main_t * vnm = vnet_get_main();
763 * vcgn_classify_main_t * vcm = &vcgn_classify_main;
767 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
768 if (unformat(input, "%u", &timeout))
772 icmp_session_timeout = timeout;
777 static clib_error_t *
778 set_vcgn_protocol_default_timeout_command_fn (vlib_main_t * vm,
779 unformat_input_t * input,
780 vlib_cli_command_t * cmd)
783 vnet_main_t * vnm = vnet_get_main();
784 vcgn_classify_main_t * vcm = &vcgn_classify_main;
789 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
790 if (unformat(input, "%s", &protocol))
794 cnat_nat44_set_protocol_timeout_value(0, 0, protocol, reset, vm);
798 static clib_error_t *
799 set_vcgn_dynamic_port_start_range_command_fn (vlib_main_t * vm,
800 unformat_input_t * input,
801 vlib_cli_command_t * cmd)
804 vnet_main_t * vnm = vnet_get_main();
805 vcgn_classify_main_t * vcm = &vcgn_classify_main;
809 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
810 if (unformat(input, "%u", &port))
814 if (port != 0 && port > 65535) {
815 vlib_cli_output(vm, "Error !! Invalid port\n");
817 cnat_static_port_range = port;
818 vlib_cli_output(vm, "Dynamic Port Range Config Successful !!\n");
823 static clib_error_t *
824 set_vcgn_port_limit_command_fn (vlib_main_t * vm,
825 unformat_input_t * input,
826 vlib_cli_command_t * cmd)
829 vnet_main_t * vnm = vnet_get_main();
830 vcgn_classify_main_t * vcm = &vcgn_classify_main;
834 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
835 if (unformat(input, "%u", &port))
839 if (port != 0 && port > 65535) {
840 vlib_cli_output(vm, "Error !! Invalid port\n");
842 cnat_main_db_max_ports_per_user = port;
843 vlib_cli_output(vm, "Port Limit Config Successful !!\n");
848 static inline void nfv9_init_pkt_sent_data(cnat_nfv9_logging_info_t *nfv9_info)
850 nfv9_server_info_t *server = nfv9_server_info_pool +
851 nfv9_info->server_index;
854 * Reset the pkts_since_last_template and sent_time
855 * so that template will be sent next time
857 server->last_template_sent_time = 0;
858 server->pkts_since_last_template = 0xffffffff;
861 static inline u16 nfv9_get_max_length_minus_max_record_size(u16 path_mtu)
863 u16 max_length_minus_max_record_size;
864 if(!path_mtu) /* Use default */
865 path_mtu = NFV9_DEF_PATH_MTU;
867 max_length_minus_max_record_size = path_mtu -
868 CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH -
870 CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH; /* Note.. as of now this record
871 * requires max number of bytes. If you add more records,
872 * this needs to be re-checked */
873 if (max_length_minus_max_record_size < CNAT_NFV9_MIN_RECORD_SIZE) {
874 max_length_minus_max_record_size = CNAT_NFV9_MIN_RECORD_SIZE;
876 return max_length_minus_max_record_size;
879 /* This function finds if the netflow server indicated by
880 * new_server_info is already configured for some other instance
881 * if yes, it returns the same pointer so that, info sent to the
882 * server is consistent. If the server is not found, a new instance
883 * is created and returned. If an existing server is used, its refernce
884 * count is incrimented (indicating the number of instances using the
887 /* #define DEBUG_NF_SERVER_CONFIG 1 */
888 static u16 nfv9_get_server_instance(
889 cnat_nfv9_logging_info_t *nfv9_info, nfv9_server_info_t *new_server_info)
892 /* Check if the instance has a server already and if yes, does it match */
893 nfv9_server_info_t *server;
894 if(nfv9_info->server_index != EMPTY) {
895 server = nfv9_server_info_pool + nfv9_info->server_index;
897 if((server->ipv4_address == new_server_info->ipv4_address) &&
898 (server->port == new_server_info->port)) {
899 /* Same server.. just check if refresh rate/timeouts are reduced */
900 #ifdef DEBUG_NF_SERVER_CONFIG
901 if(my_instance_number == 1) {
902 printf("\n Server match for %x and port %d\n",
903 new_server_info->ipv4_address, new_server_info->port);
905 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
906 goto adjust_refresh_rate;
907 } else { /* The server is being changed */
909 #ifdef DEBUG_NF_SERVER_CONFIG
910 if(my_instance_number == 1) {
911 printf("\n Server change from %x, %d to %x, %d"
913 server->ipv4_address,
915 new_server_info->ipv4_address, new_server_info->port,
918 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
919 if(!server->ref_count) {
920 /* Return this server to pool */
921 #ifdef DEBUG_NF_SERVER_CONFIG
922 if(my_instance_number == 1) {
923 PLATFORM_DEBUG_PRINT("Deleting Server %x, %d at %d\n",
924 server->ipv4_address,
926 nfv9_info->server_index);
928 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
929 pool_put(nfv9_server_info_pool, server);
934 /* Now check if the server is already present in the pool */
937 pool_foreach (server, nfv9_server_info_pool, ({
938 if ((server->ipv4_address == new_server_info->ipv4_address) &&
939 (server->port == new_server_info->port)) {
941 nfv9_info->server_index = server - nfv9_server_info_pool;
943 #ifdef DEBUG_NF_SERVER_CONFIG
944 if(my_instance_number == 1) {
945 printf("Re-using server %x, %d Ref count %d\n",
946 server->ipv4_address, server->port, server->ref_count);
948 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
954 /* Create a new one, initialize and return */
956 pool_get(nfv9_server_info_pool, server);
957 clib_memcpy(server, new_server_info, sizeof(nfv9_server_info_t));
958 server->ref_count = 1;
959 nfv9_info->server_index = server - nfv9_server_info_pool;
960 #ifdef DEBUG_NF_SERVER_CONFIG
961 if(my_instance_number == 1) {
962 printf("Create new server for at %d %x and port %d\n",
963 nfv9_info->server_index,
964 new_server_info->ipv4_address, new_server_info->port);
966 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
971 if(server->refresh_rate >
972 new_server_info->refresh_rate) {
973 server->refresh_rate =
974 new_server_info->refresh_rate;
975 #ifdef DEBUG_NF_SERVER_CONFIG
976 if(my_instance_number == 1) {
977 printf("Reset refresh rate to %d\n",
978 server->refresh_rate);
980 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
983 if(server->timeout_rate >
984 new_server_info->timeout_rate) {
985 server->timeout_rate =
986 new_server_info->timeout_rate;
987 #ifdef DEBUG_NF_SERVER_CONFIG
988 if(my_instance_number == 1) {
989 printf("Reset timeout rate to %d\n",
990 server->timeout_rate);
992 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
997 static clib_error_t *
998 set_vcgn_nfv9_logging_cofig_command_fn (vlib_main_t * vm,
999 unformat_input_t * input,
1000 vlib_cli_command_t * cmd)
1002 vcgn_classify_main_t * vcm = &vcgn_classify_main;
1003 spp_api_cnat_v4_config_nfv9_logging_t nfv9_conf;
1004 ip4_address_t server_addr;
1007 u32 refresh_rate = 0;
1011 /* vcgn changes start*/
1012 cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL;
1013 cnat_nfv9_logging_info_t *my_nfv9_logging_info_tmp = NULL;
1014 cnat_vrfmap_t *my_vrfmap = 0, *my_vrfmap_temp = 0;
1018 u32 inside_sw_if_index = EMPTY;
1020 * Init NFv9 logging info as needed, this will be done only once
1022 cnat_nfv9_logging_init();
1026 /* vcgn changes end*/
1027 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
1028 if (unformat (input, "inside %U",
1029 unformat_vnet_sw_interface, &inside_sw_if_index)) {
1031 } else if (unformat (input, "server %U", unformat_ip4_address, &server_addr))
1032 ip_addr = clib_net_to_host_u32(server_addr.as_u32);
1033 else if (unformat(input, "port %u", &port))
1035 else if (unformat(input, "refresh-rate %u", &refresh_rate))
1037 else if (unformat(input, "timeout %u", &timeout))
1039 else if (unformat(input, "pmtu %u", &pmtu))
1041 else if (unformat(input, "del"))
1046 if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
1047 vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
1048 return clib_error_return (0, "Could not find the inside interface");
1050 i_vrf = inside_sw_if_index;
1051 i_vrf_id = inside_sw_if_index;
1054 vlib_cli_output(vm, "ip 0x%x, port %u, refresh %u, "
1055 "timeout %u, pmtu %u enable %u\n",
1056 ip_addr, port, refresh_rate,
1057 timeout, pmtu, enable);
1059 if (refresh_rate == 0) refresh_rate = 500; /* num of pkts */
1060 if (timeout == 0) timeout = 30; /* in mins */
1062 nfv9_conf.enable = enable;
1063 nfv9_conf.ipv4_address = ip_addr;
1064 nfv9_conf.i_vrf_id = inside_sw_if_index;
1065 nfv9_conf.i_vrf = inside_sw_if_index;
1066 nfv9_conf.port = port;
1067 nfv9_conf.refresh_rate = refresh_rate;
1068 nfv9_conf.timeout_rate = timeout;
1069 nfv9_conf.path_mtu = pmtu;
1070 nfv9_conf.nfv9_global_collector = 0;
1071 nfv9_conf.session_logging = 0;
1074 * At this point the NFv9 global information should already be
1075 * inited as we have called cnat_nfv9_logging_init()
1078 if (nfv9_conf.nfv9_global_collector) {
1079 if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) {
1081 my_nfv9_logging_info = cnat_nfv9_logging_info_pool +
1082 cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1085 /* Do we already have a map for this VRF? */
1086 pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1087 if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) {
1088 nfv9_server_info_t *server = nfv9_server_info_pool +
1089 my_nfv9_logging_info->server_index;
1090 if((server->ipv4_address == (nfv9_conf.ipv4_address)) && (server->port == (nfv9_conf.port))) {
1092 my_nfv9_logging_info_tmp = my_nfv9_logging_info;
1099 if ((nfv9_conf.ipv4_address == 0) ||
1100 (nfv9_conf.port == 0)) {
1102 "Add NFv9 ivrf %d Logging Invalid values [IPv4 0x%x, PORT %d]\n",
1104 (nfv9_conf.ipv4_address),
1109 if (nfv9_conf.enable) {
1110 if ((nfv9_conf.ipv4_address == 0) ||
1111 (nfv9_conf.port == 0)) {
1112 nfv9_conf.rc = CNAT_ERR_PARSER;
1114 "NFV9_logging i_vrf %d, Invalid [v4_addr 0x%x port %d]\n",
1116 (nfv9_conf.ipv4_address),
1121 nfv9_server_info_t new_server_info;
1122 memset(&new_server_info, 0, sizeof(nfv9_server_info_t));
1123 new_server_info.ipv4_address =
1124 nfv9_conf.ipv4_address;
1125 new_server_info.port =
1127 new_server_info.refresh_rate =
1128 (nfv9_conf.refresh_rate);
1130 * Store the timeout in seconds. User configures it in minutes
1132 new_server_info.timeout_rate =
1133 60*(nfv9_conf.timeout_rate);
1134 if (found && my_nfv9_logging_info) {
1136 * Entry already present, change it
1138 my_nfv9_logging_info->max_length_minus_max_record_size =
1139 nfv9_get_max_length_minus_max_record_size(
1140 ((nfv9_conf.path_mtu)));
1142 pool_get(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1143 memset(my_nfv9_logging_info, 0, sizeof(*my_nfv9_logging_info));
1144 my_nfv9_logging_info->server_index = EMPTY;
1145 my_nfv9_logging_info->nfv9_logging_next_index = EMPTY;
1147 * Make the current and head logging context indeices as EMPTY.
1148 * When first logging happens, these get set correctly
1150 my_nfv9_logging_info->current_logging_context = NULL;
1151 my_nfv9_logging_info->queued_logging_context = NULL;
1153 my_nfv9_logging_info->f = NULL;
1154 my_nfv9_logging_info->to_next = NULL;
1155 output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-input");
1156 my_nfv9_logging_info->ip4_input_node_index = output_node->index;
1157 printf("ip4_input_node_index %d\n", my_nfv9_logging_info->ip4_input_node_index);
1159 my_nfv9_logging_info->i_vrf = i_vrf;
1160 my_nfv9_logging_info->i_vrf_id = i_vrf_id;
1161 my_nfv9_logging_info->max_length_minus_max_record_size =
1162 nfv9_get_max_length_minus_max_record_size(
1163 nfv9_conf.path_mtu);
1165 /* my_nfv9_logging_info will have a copy of logging_policy
1166 * because, it is quite possible that nfv9 config arrives before
1167 * the corresponding vrfmap is initialized. In such cases
1168 * this copy will be used to update the vrfmap entry
1170 my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1172 if (nfv9_conf.nfv9_global_collector) {
1173 cnat_nfv9_global_info.cnat_nfv9_global_collector_index =
1174 my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1176 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1177 if (my_vrfmap->nfv9_logging_index == EMPTY) {
1178 my_vrfmap->nfv9_logging_index =
1179 cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1183 u32 my_vrfmap_found = 0;
1185 FIND_MY_VRF_USING_I_VRF_ID
1186 my_vrfmap = my_vrfmap_temp;
1187 if (my_vrfmap_found) {
1188 if(my_vrfmap->nfv9_logging_index == EMPTY) {
1189 my_vrfmap->nfv9_logging_index =
1190 my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1191 // my_vrfmap->nf_logging_policy = mp->session_logging;
1193 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index;
1194 while(my_nfv9_logging_info_temp->nfv9_logging_next_index != EMPTY){
1195 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_nfv9_logging_info_temp->nfv9_logging_next_index;
1197 my_nfv9_logging_info_temp->nfv9_logging_next_index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1203 /* Update logging policy */
1204 my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1205 if (nfv9_conf.nfv9_global_collector) {
1206 if(PLATFORM_DBL_SUPPORT) {
1207 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1208 if (my_vrfmap->nfv9_logging_index ==
1209 cnat_nfv9_global_info.cnat_nfv9_global_collector_index) {
1210 my_vrfmap->nf_logging_policy = nfv9_conf.session_logging;
1214 nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1217 if(PLATFORM_DBL_SUPPORT) {
1218 u32 my_vrfmap_found = 0;
1219 my_vrfmap_temp = NULL;
1220 FIND_MY_VRF_USING_I_VRF_ID
1221 my_vrfmap = my_vrfmap_temp;
1222 if (my_vrfmap_found) {
1223 // my_vrfmap->nf_logging_policy = mp->session_logging;
1226 nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1229 u8 nfv9_logging_policy = 0;
1230 u32 my_vrfmap_found = 0;
1231 my_vrfmap_temp = NULL;
1232 FIND_MY_VRF_USING_I_VRF_ID
1233 my_vrfmap = my_vrfmap_temp;
1234 if (my_vrfmap_found) {
1235 u32 index_curr = my_vrfmap->nfv9_logging_index;
1236 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1237 while(index_curr != EMPTY) {
1238 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1239 nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1240 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1242 my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1244 //vlib_cli_output(vm,"Netflow logging policy = %d\n", my_vrfmap->nf_logging_policy);
1245 if(nfv9_get_server_instance(my_nfv9_logging_info, &new_server_info)
1247 vlib_cli_output(vm, "Error to get server instance");
1248 nfv9_conf.rc = CNAT_ERR_PARSER;
1251 nfv9_init_pkt_sent_data(my_nfv9_logging_info);
1253 vlib_cli_output(vm,"Adding NFv9 Logging Succeeded\n");
1254 nfv9_configured = 1;
1259 /* if found entry then we need to overwrite the my_nfv9_logging_info_tmp
1260 * to my_nfv9_logging_info
1262 my_nfv9_logging_info = my_nfv9_logging_info_tmp;
1263 if (i_vrf == INVALID_UIDX) {
1265 * We are deleting a global collector. Mark the collectors
1266 * in those VRFs using the global collector
1268 pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1269 if (my_vrfmap->nfv9_logging_index ==
1270 cnat_nfv9_global_info.cnat_nfv9_global_collector_index) {
1271 my_vrfmap->nfv9_logging_index = EMPTY;
1275 cnat_nfv9_global_info.cnat_nfv9_global_collector_index = EMPTY;
1277 u32 my_vrfmap_found = 0;
1278 my_vrfmap_temp = NULL;
1279 FIND_MY_VRF_USING_I_VRF_ID
1280 my_vrfmap = my_vrfmap_temp;
1281 if (my_vrfmap_found) {
1282 // my_vrfmap->nfv9_logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1285 if (my_nfv9_logging_info->queued_logging_context ||
1286 my_nfv9_logging_info->current_logging_context) {
1288 * If there is a pending context:
1289 * Set the deleted flag to 1. This will ensure
1290 * that the logging info structure gets freed after any
1291 * pending packet get sent
1293 my_nfv9_logging_info->deleted = 1;
1296 * No pending context, just free the logging info structure
1298 u32 index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1299 if(index == my_vrfmap->nfv9_logging_index) {
1300 /* Deleting the first sever */
1301 my_vrfmap->nfv9_logging_index = my_nfv9_logging_info->nfv9_logging_next_index;
1302 /* if(my_nfv9_logging_info->nfv9_logging_next_index != EMPTY){
1303 my_vrfmap->nf_logging_policy = (cnat_nfv9_logging_info_pool + my_nfv9_logging_info->nfv9_logging_next_index)->logging_policy;
1305 my_vrfmap->nf_logging_policy = EMPTY;
1308 u32 index_curr = my_vrfmap->nfv9_logging_index;
1309 u32 index_prev = EMPTY;
1310 while(index_curr != EMPTY) {
1311 index_prev = index_curr;
1312 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1313 if(index == index_curr)
1315 (cnat_nfv9_logging_info_pool + index_prev)->nfv9_logging_next_index = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1320 nfv9_delete_server_info(my_nfv9_logging_info);
1321 pool_put(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1324 vlib_cli_output(vm, "Deleting NFv9 Logging Succeeded\n");
1326 * Search across all vrf and check if nfv9 logging is configured.
1328 nfv9_configured = 0;
1329 pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1330 nfv9_configured = 1;
1334 nfv9_conf.rc = CNAT_NO_CONFIG;
1335 vlib_cli_output(vm, "Add NFv9 Logging Failed (2) Non Existent vrf %d\n",
1339 u8 nfv9_logging_policy = 0;
1340 u32 my_vrfmap_found = 0;
1341 my_vrfmap_temp = NULL;
1342 FIND_MY_VRF_USING_I_VRF_ID
1343 my_vrfmap = my_vrfmap_temp;
1344 if (my_vrfmap_found) {
1345 u32 index_curr = my_vrfmap->nfv9_logging_index;
1346 cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1347 while(index_curr != EMPTY) {
1348 my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1349 nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1350 index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1352 my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1361 VLIB_CLI_COMMAND (set_vcgn_map_command) = {
1362 .path = "set vcgn map",
1363 .short_help = "set vcgn map <lo-address> [- <hi-address>]",
1364 .function = set_vcgn_map_command_fn,
1367 VLIB_CLI_COMMAND (set_vcgn_inside_command) = {
1368 .path = "set vcgn inside",
1369 .short_help = "set vcgn inside <inside intfc> outside <outside intfc>",
1370 .function = set_vcgn_inside_command_fn,
1373 VLIB_CLI_COMMAND (set_vcgn_tcp_timeout_command) = {
1374 .path = "set vcgn tcp timeout",
1375 .short_help = "set vcgn tcp timeout active <1-65535> init <1-65535>",
1376 .function = set_vcgn_tcp_timeout_command_fn,
1379 VLIB_CLI_COMMAND (set_vcgn_udp_timeout_command) = {
1380 .path = "set vcgn udp timeout",
1381 .short_help = "set vcgn udp timeout active <1-65535> init <1-65535>",
1382 .function = set_vcgn_udp_timeout_command_fn,
1385 VLIB_CLI_COMMAND (set_vcgn_icmp_timeout_command) = {
1386 .path = "set vcgn icmp timeout",
1387 .short_help = "set vcgn icmp timeout <1-65535>",
1388 .function = set_vcgn_icmp_timeout_command_fn,
1391 VLIB_CLI_COMMAND (set_vcgn_protocol_default_timeout_command) = {
1392 .path = "set vcgn default timeout",
1393 .short_help = "set vcgn default timeout protocol <tcp/udp/icmp>",
1394 .function = set_vcgn_protocol_default_timeout_command_fn,
1397 VLIB_CLI_COMMAND (set_vcgn_dynamic_port_start_range_command) = {
1398 .path = "set vcgn dynamic port start",
1399 .short_help = "set vcgn dynamic port start <1-65535>",
1400 .function = set_vcgn_dynamic_port_start_range_command_fn,
1403 VLIB_CLI_COMMAND (set_vcgn_port_limit_command) = {
1404 .path = "set vcgn port limit",
1405 .short_help = "set vcgn port limit <1-65535>",
1406 .function = set_vcgn_port_limit_command_fn,
1409 VLIB_CLI_COMMAND (set_vcgn_nfv9_logging_cofig_command) = {
1410 .path = "set vcgn nfv9",
1411 .short_help = "set vcgn nfv9 [del] inside <interface> "
1412 "server <ip-addr> port <port> [refresh-rate <n>] "
1413 "[timeout <n>] [pmtu <n>]",
1414 .function = set_vcgn_nfv9_logging_cofig_command_fn,
1419 VLIB_CLI_COMMAND (show_vcgn_config_command) = {
1420 .path = "show vcgn config",
1421 .short_help = "show vcgn config",
1422 .function = show_vcgn_config_command_fn,
1425 VLIB_CLI_COMMAND (show_vcgn_stat_command) = {
1426 .path = "show vcgn statistics",
1427 .short_help = "show vcgn statistics",
1428 .function = show_vcgn_stats_command_fn,
1431 VLIB_CLI_COMMAND (show_vcgn_inside_translation_command) = {
1432 .path = "show vcgn inside-translation",
1433 .short_help = "show vcgn inside-translation protocol <tcp/udp/icmp> "
1434 "interface <inside-if> inside-addr <ip-addr> "
1435 "[start-port <n>] [end-port <n>]",
1436 .function = show_vcgn_inside_translation_command_fn,
1439 VLIB_CLI_COMMAND (show_vcgn_outside_translation_command) = {
1440 .path = "show vcgn outside-translation",
1441 .short_help = "show vcgn outside-translation protocol <tcp/udp/icmp> "
1442 "interface <outside-if> outside-addr <ip-addr> "
1443 "[start-port <n>] [end-port <n>]",
1444 .function = show_vcgn_outside_translation_command_fn,
1447 static clib_error_t *
1448 vcgn_init (vlib_main_t * vm)
1450 clib_error_t * error = 0;
1452 if ((error = vlib_call_init_function
1453 (vm, vcgn_classify_init)))
1455 if ((error = vlib_call_init_function
1456 (vm, cnat_ipv4_udp_inside_input_init)))
1458 if ((error = vlib_call_init_function
1459 (vm, cnat_ipv4_udp_outside_input_init)))
1461 if ((error = vlib_call_init_function
1462 (vm, cnat_ipv4_udp_inside_input_exc_init)))
1464 if ((error = vlib_call_init_function
1465 (vm, cnat_db_scanner_init)))
1467 if ((error = vlib_call_init_function
1468 (vm, cnat_ipv4_tcp_inside_input_init)))
1470 if ((error = vlib_call_init_function
1471 (vm, cnat_ipv4_tcp_inside_input_exc_init)))
1473 if ((error = vlib_call_init_function
1474 (vm, cnat_ipv4_tcp_outside_input_init)))
1476 if ((error = vlib_call_init_function
1477 (vm, cnat_ipv4_icmp_q_inside_input_init)))
1479 if ((error = vlib_call_init_function
1480 (vm, cnat_ipv4_icmp_q_inside_input_exc_init)))
1482 if ((error = vlib_call_init_function
1483 (vm, cnat_ipv4_icmp_q_outside_input_init)))
1485 if ((error = vlib_call_init_function
1486 (vm, cnat_ipv4_icmp_e_inside_input_init)))
1488 if ((error = vlib_call_init_function
1489 (vm, cnat_ipv4_icmp_e_outside_input_init)))
1495 VLIB_INIT_FUNCTION (vcgn_init);