FD.io VPP  v17.01.1-3-gc6833f8
Vector Packet Processing
vcgn_classify.c
Go to the documentation of this file.
1 /*
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:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 
16 #include <vnet/plugin/plugin.h>
17 #include <vlib/vlib.h>
18 #include <vnet/vnet.h>
19 #include <vnet/pg/pg.h>
20 #include <vppinfra/error.h>
21 #include <vppinfra/pool.h>
22 
23 #include <vnet/ip/ip.h>
24 #include <vnet/ethernet/ethernet.h>
25 
26 #include "cnat_db.h"
27 #include "cnat_global.h"
28 #include "cnat_cli.h"
29 #include "cnat_config.h"
30 #include "cnat_logging.h"
31 #include "cnat_config_api.h"
32 #include "cnat_show_api.h"
33 #include "cnat_show_response.h"
34 #include "cnat_ipv4_udp.h"
35 #include "cnat_common_api.h"
36 
37 #include <arpa/inet.h>
38 
39 typedef struct {
41 
42  /* inside, outside interface handles */
45 
46  /* convenience variables */
51 
52 typedef struct {
53  /* $$$$ fill in with per-pkt trace data */
59 
60 #define FIND_MY_VRF_USING_I_VRF_ID \
61  my_vrfmap_found = 0; \
62  pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ \
63  if (my_vrfmap->i_vrf_id == i_vrf_id) { \
64  my_vrfmap_found = 1; \
65  my_vrfmap_temp = my_vrfmap; \
66  break; \
67  } \
68  }));
69 
70 
71 /* packet trace format function */
72 static u8 * format_swap_trace (u8 * s, va_list * args)
73 {
74  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
75  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
76  vcgn_classify_trace_t * t = va_arg (*args, vcgn_classify_trace_t *);
77 
78  s = format (s, "VCGN_CLASSIFY: dst %U dst_port %d sw_if_index %d next %d",
80  clib_net_to_host_u16(t->orig_dst_port),
81  t->sw_if_index, t->next_index);
82  return s;
83 }
84 
86 
88 
89 #define foreach_vcgn_classify_error \
90 _(PACKETS_RECEIVED, "total packets received") \
91 _(V4_PACKETS_PROCESSED, "ipv4 packets processed for vCGN") \
92 _(V4_PACKETS_PUNTED, "ipv4 packets punted") \
93 _(V6_PACKETS_PUNTED, "ipv6 packets punted") \
94 _(MPLS_PACKETS_PUNTED, "mpls unicast packets punted") \
95 _(ETH_PACKETS_PUNTED, "ethernet packets punted")
96 
97 
98 typedef enum {
99 #define _(sym,str) VCGN_CLASSIFY_ERROR_##sym,
101 #undef _
104 
105 static char * vcgn_classify_error_strings[] = {
106 #define _(sym,string) string,
108 #undef _
109 };
110 
111 /*
112  * To drop a pkt and increment one of the previous counters:
113  *
114  * set b0->error = error_node->errors[VCGN_CLASSIFY_ERROR_EXAMPLE];
115  * set next0 to a disposition index bound to "error-drop".
116  *
117  * To manually increment the specific counter VCGN_CLASSIFY_ERROR_EXAMPLE:
118  *
119  * vlib_node_t *n = vlib_get_node (vm, vcgn_classify.index);
120  * u32 node_counter_base_index = n->error_heap_index;
121  * vlib_error_main_t * em = &vm->error_main;
122  * em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_EXAMPLE] += 1;
123  *
124  */
125 
126 typedef enum {
141 
142 static uword
144  vlib_node_runtime_t * node,
145  vlib_frame_t * frame)
146 {
147  u32 n_left_from, * from, * to_next;
148  vcgn_classify_next_t next_index;
151  u32 node_counter_base_index = n->error_heap_index;
152  vlib_error_main_t * em = &vm->error_main;
153  u16 *l3_type;
154  int counter;
155 
156  from = vlib_frame_vector_args (frame);
157  n_left_from = frame->n_vectors;
158  next_index = node->cached_next_index;
159 
160  while (n_left_from > 0)
161  {
162  u32 n_left_to_next;
163 
164  vlib_get_next_frame (vm, node, next_index,
165  to_next, n_left_to_next);
166 
167  #if 0
168  while (n_left_from >= 4 && n_left_to_next >= 2)
169  {
170  u32 bi0, bi1;
171  vlib_buffer_t * b0, * b1;
172  u32 next0, next1;
173  u32 sw_if_index0, sw_if_index1;
174 
175  /* Prefetch next iteration. */
176  {
177  vlib_buffer_t * p2, * p3;
178 
179  p2 = vlib_get_buffer (vm, from[2]);
180  p3 = vlib_get_buffer (vm, from[3]);
181 
182  vlib_prefetch_buffer_header (p2, LOAD);
183  vlib_prefetch_buffer_header (p3, LOAD);
184 
187  }
188 
189  /* speculatively enqueue b0 and b1 to the current next frame */
190  to_next[0] = bi0 = from[0];
191  to_next[1] = bi1 = from[1];
192  from += 2;
193  to_next += 2;
194  n_left_from -= 2;
195  n_left_to_next -= 2;
196 
197  b0 = vlib_get_buffer (vm, bi0);
198  b1 = vlib_get_buffer (vm, bi1);
199 
200  sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
201  next0 = vcm->cached_next_index;
202  sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
203  next1 = vcm->cached_next_index;
204 
205  /* $$$$ your message in this space. Process 2 x pkts */
206  em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 2;
207 
209  {
210  if (b0->flags & VLIB_BUFFER_IS_TRACED)
211  {
213  vlib_add_trace (vm, node, b0, sizeof (*t));
214  t->sw_if_index = sw_if_index0;
215  t->next_index = next0;
216  }
217  if (b1->flags & VLIB_BUFFER_IS_TRACED)
218  {
220  vlib_add_trace (vm, node, b1, sizeof (*t));
221  t->sw_if_index = sw_if_index1;
222  t->next_index = next1;
223  }
224  }
225 
226  /* verify speculative enqueues, maybe switch current next frame */
227  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
228  to_next, n_left_to_next,
229  bi0, bi1, next0, next1);
230  }
231  #endif /* if 0 */
232 
233  while (n_left_from > 0 && n_left_to_next > 0)
234  {
235  u32 bi0;
236  vlib_buffer_t * b0;
237  u32 next0;
238  u32 sw_if_index0;
239  ip4_header_t * h0;
240  //ipv4_header *h0;
241  ethernet_header_t *eth0;
242  icmp_v4_t *icmp;
243  u8 icmp_type;
244  u8 ipv4_hdr_len;
245 
246  /* speculatively enqueue b0 to the current next frame */
247  bi0 = from[0];
248  to_next[0] = bi0;
249  from += 1;
250  to_next += 1;
251  n_left_from -= 1;
252  n_left_to_next -= 1;
253 
254  b0 = vlib_get_buffer (vm, bi0);
255 
257  u16 *etype = &eth0->type;
258 
259  /* vlan tag 0x8100 */
260  if (*etype == clib_host_to_net_u16(ETHERNET_TYPE_VLAN)) {
261  l3_type = (etype + 1); /* Skip 2 bytes of vlan id */
262  vlib_buffer_advance(b0, 18);
263  } else {
264  l3_type = etype;
265  vlib_buffer_advance(b0, 14);
266  }
267  /* Handling v4 pkts 0x800 */
268  if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP4)) {
269 
270  h0 = vlib_buffer_get_current (b0);
271 
272  u8 protocol_type = h0->protocol;
273 
274  sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
276  counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PROCESSED;
277 
278  if (protocol_type == 0x11) { /* UDP# 17 */
279  next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
280  vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
282 
283  next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
284  vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
286 
287  } else if (protocol_type == 0x06) { /* TCP# 6 */
288  next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
289  vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
291 
292  next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
293  vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
295 
296  } else if (protocol_type == 0x01) { /* ICMP # 1 */
297 
298  ipv4_hdr_len = (h0->ip_version_and_header_length & 0xf) << 2;
299  icmp = (icmp_v4_t *)((u8*)h0 + ipv4_hdr_len);
300  icmp_type = icmp->type;
301 
302  if ((icmp_type == ICMPV4_ECHO) ||
303  (icmp_type == ICMPV4_ECHOREPLY)) {
304  next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
305  vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
307 
308  next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
309  vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
311 
312  } else {
313  next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) &&
314  vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ?
316 
317  next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) &&
318  vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ?
320  }
321  } else {
322  /* cannot do NATting with this L4 protocol */
323  counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PUNTED;
324  }
325 
327  && (b0->flags & VLIB_BUFFER_IS_TRACED))) {
328  udp_header_t * u0 = (udp_header_t *)(h0+1);
330  vlib_add_trace (vm, node, b0, sizeof (*t));
331  t->sw_if_index = sw_if_index0;
332  t->next_index = next0;
334  t->orig_dst_port = u0->dst_port;
335  }
336 
337  } else if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP6)) {
338 
339  /* IPv6 0x86DD */
341  counter = VCGN_CLASSIFY_ERROR_V6_PACKETS_PUNTED;
342 
343  } else if (*l3_type ==
344  clib_host_to_net_u16(ETHERNET_TYPE_MPLS_UNICAST)) {
345 
346  /* MPLS unicast 0x8847 */
348  counter = VCGN_CLASSIFY_ERROR_MPLS_PACKETS_PUNTED;
349  } else { /* Remaining all should be pushed to "ethernet-input" */
350 
352  counter = VCGN_CLASSIFY_ERROR_ETH_PACKETS_PUNTED;
353  }
354 
355  em->counters[node_counter_base_index + counter] += 1;
356  em->counters[node_counter_base_index +
357  VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 1;
358 
359  /* verify speculative enqueue, maybe switch current next frame */
360  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
361  to_next, n_left_to_next,
362  bi0, next0);
363  }
364 
365  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
366  }
367 
368  return frame->n_vectors;
369 }
370 
372  .function = vcgn_classify_node_fn,
373  .name = "vcgn-classify",
374  .vector_size = sizeof (u32),
375  .format_trace = format_swap_trace,
377 
379  .error_strings = vcgn_classify_error_strings,
380 
381  .n_next_nodes = VCGN_CLASSIFY_N_NEXT,
382 
383  /* edit / add dispositions here */
384  .next_nodes = {
385  [VCGN_CLASSIFY_NEXT_IP4_INPUT] = "ip4-input",
386  [VCGN_CLASSIFY_NEXT_IP6_INPUT] = "ip6-input",
387  [VCGN_CLASSIFY_NEXT_MPLS_INPUT] = "mpls-input",
388  [VCGN_CLASSIFY_NEXT_ETHERNET_INPUT] = "ethernet-input",
389  [VCGN_CLASSIFY_NEXT_UDP_INSIDE] = "vcgn-v4-udp-i2o",
390  [VCGN_CLASSIFY_NEXT_UDP_OUTSIDE] = "vcgn-v4-udp-o2i",
391  [VCGN_CLASSIFY_NEXT_TCP_INSIDE] = "vcgn-v4-tcp-i2o",
392  [VCGN_CLASSIFY_NEXT_TCP_OUTSIDE] = "vcgn-v4-tcp-o2i",
393  [VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE] = "vcgn-v4-icmp-q-i2o",
394  [VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE] = "vcgn-v4-icmp-q-o2i",
395  [VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE] = "vcgn-v4-icmp-e-i2o",
396  [VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE] = "vcgn-v4-icmp-e-o2i"
397  },
398 };
399 
400 
401 /* A test function to init the vrf map */
402 
404 {
406 
407  mp->vlib_main = vm;
408  mp->vnet_main = vnet_get_main();
409  u32 inside_sw_if_index = 1;
410  u32 outside_sw_if_index = 0;
411 
413  inside_sw_if_index + 1, EMPTY);
415  outside_sw_if_index + 1, EMPTY);
416 
417  /*
418  * inside_sw_if_index cell of the table stores outside_sw_if_index
419  * and vice versa. This is ensurs pair of indices being remembered
420  * using one mem-location.
421  */
422  mp->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index;
423  mp->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index;
424 
425 #if DPDK==1
426  dpdk_set_next_node (DPDK_RX_NEXT_IP4_INPUT, "vcgn-classify");
427 #endif
428 
429  {
430  pg_node_t * pn;
431  pn = pg_get_node (vcgn_classify_node.index);
433  }
434  return 0;
435 }
436 
438 
439 /* Show command handlers */
440 static clib_error_t *
442  unformat_input_t * input,
443  vlib_cli_command_t * cmd)
444 {
445  if (cnat_db_init_done) {
447  } else {
448  vlib_cli_output(vm, "vCGN is not configured !!\n");
449  }
450  return 0;
451 }
452 
453 
454 static clib_error_t *
456  unformat_input_t * input,
457  vlib_cli_command_t * cmd)
458 {
460  return 0;
461 }
462 
463 static clib_error_t *
465  unformat_input_t * input,
466  vlib_cli_command_t * cmd)
467 {
468  vnet_main_t * vnm = vnet_get_main();
471  u8 *proto;
472  ip4_address_t inside_addr;
473  u32 start_port = 1;
474  u32 end_port = 65535;
475  u32 inside_sw_if_index = EMPTY;
476 
477  inside_req.start_port = start_port;
478  inside_req.end_port = end_port;
479  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
480  if (unformat(input, "protocol %s", &proto)) {
481  if (!strncmp((char *) proto, "udp", 3)) {
482  inside_req.protocol = 1;
483  } else if (!strncmp((char *) proto, "tcp", 3)) {
484  inside_req.protocol = 2;
485  } else {
486  inside_req.protocol = 3;
487  }
488  } else if (unformat (input, "interface %U",
489  unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) {
490  if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
491  vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
492  return clib_error_return (0, "Could not find the inside interface");
493  }
494  } else if (unformat (input, "inside-addr %U",
495  unformat_ip4_address, &inside_addr)) {
496  inside_req.ipv4_addr = clib_net_to_host_u32(inside_addr.as_u32);
497  } else if (unformat(input, "start-port %u", &start_port)) {
498  inside_req.start_port = start_port;
499  } else if (unformat(input, "end-port %u", &end_port)) {
500  inside_req.end_port = end_port;
501  } else { break;}
502  }
503  inside_req.vrf_id = inside_sw_if_index;
504  inside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
505  inside_req.all_entries = 0; /* we can see it later */
506 #if DEBUG
507  vlib_cli_output(vm, "proto %d, inside-addr 0x%x, start_port %u, "
508  "end_port %u, vrf 0x%x\n",
509  inside_req.protocol,
510  inside_req.ipv4_addr,
511  inside_req.start_port,
512  inside_req.end_port,
513  inside_sw_if_index);
514 #endif
515  if (cnat_db_init_done) {
517  } else {
518  vlib_cli_output(vm, "vCGN is not configured !!\n");
519  }
520  return 0;
521 }
522 
523 
524 static clib_error_t *
526  unformat_input_t * input,
527  vlib_cli_command_t * cmd)
528 {
531  vnet_main_t * vnm = vnet_get_main();
534  u8 *proto;
535  ip4_address_t outside_addr;
536  u32 start_port = 1;
537  u32 end_port = 65535;
538  u32 outside_sw_if_index = EMPTY;
539 
540 
541  outside_req.start_port = start_port;
542  outside_req.end_port = end_port;
543  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
544  if (unformat(input, "protocol %s", &proto)) {
545  if (!strncmp((char *) proto, "udp", 3)) {
546  outside_req.protocol = 1;
547  } else if (!strncmp((char *) proto, "tcp", 3)) {
548  outside_req.protocol = 2;
549  } else {
550  outside_req.protocol = 3;
551  }
552  } else if (unformat (input, "interface %U",
553  unformat_vnet_sw_interface, vnm, &outside_sw_if_index)) {
554  if (outside_sw_if_index > vec_len(vcm->outside_sw_if_index_table) ||
555  vcm->outside_sw_if_index_table[outside_sw_if_index] == EMPTY) {
556  return clib_error_return (0, "Could not find the outside interface");
557  }
558  } else if (unformat (input, "outside-addr %U",
559  unformat_ip4_address, &outside_addr)) {
560  outside_req.ipv4_addr = clib_net_to_host_u32(outside_addr.as_u32);
561  } else if (unformat(input, "start-port %u", &start_port)) {
562  outside_req.start_port = start_port;
563  } else if (unformat(input, "end-port %u", &end_port)) {
564  outside_req.end_port = end_port;
565  } else { break;}
566  }
567  outside_req.vrf_id = outside_sw_if_index;
568  outside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */
569 #if DEBUG
570  vlib_cli_output(vm, "proto %d, outside-addr 0x%x, start_port %u, "
571  "end_port %u, vrf 0x%x\n",
572  outside_req.protocol,
573  outside_req.ipv4_addr,
574  outside_req.start_port,
575  outside_req.end_port,
576  outside_sw_if_index);
577 #endif
578  if (cnat_db_init_done) {
580  } else {
581  vlib_cli_output(vm, "vCGN is not configured !!\n");
582  }
583  return 0;
584 }
585 
586 
587 /* Config command handlers */
588 static clib_error_t *
590  unformat_input_t * input,
591  vlib_cli_command_t * cmd)
592 {
593  vnet_main_t * vnm = vnet_get_main();
595  u32 inside_sw_if_index = 1;
596  u32 outside_sw_if_index = ~0;
597  void cnat_db_v2_init (void );
598 
599  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
600  if (unformat(input, "%U",
601  unformat_vnet_sw_interface, vnm, &inside_sw_if_index))
602  ;
603  else if (unformat(input, "outside %U",
604  unformat_vnet_sw_interface, vnm, &outside_sw_if_index))
605  ;
606  else break;
607  }
608  if (inside_sw_if_index == ~0 ||
609  outside_sw_if_index == ~0)
610  return clib_error_return (0, "unknown input `%U'",
611  format_unformat_error, input);
612 
613  if (inside_sw_if_index == outside_sw_if_index)
614  return clib_error_return (0, "inside and outside interfaces can't be the same...");
615 
616  /*
617  * Initialize in/out sw_if_index table. Could use
618  * non-indexed table to reduce memory. However, this
619  * is consulted in vcgn_classify for every packet.
620  * Therefore, table is indexed by sw_if_index.
621  */
623  inside_sw_if_index + 1, EMPTY);
625  outside_sw_if_index + 1, EMPTY);
626 
627  /*
628  * inside_sw_if_index cell of the table stores outside_sw_if_index
629  * and vice versa. This is ensurs pair of indices being remembered
630  * using one mem-location.
631  */
632  vcm->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index;
633  vcm->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index;
634 
635  if (! vcm->cnat_db_initalized) {
636  int i;
637  cnat_db_v2_init();
638 
639  for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) {
641  }
642  /* Turn on the db scanner process */
644  vcm->cnat_db_initalized = 1;
645  }
646  return 0;
647 }
648 
649 static clib_error_t *
651  unformat_input_t * input,
652  vlib_cli_command_t * cmd)
653 {
654  vnet_main_t * vnm = vnet_get_main();
658  u32 inside_sw_if_index = EMPTY;
659  u32 outside_sw_if_index;
660 
661  vnet_hw_interface_t *inside_hw_if_index = NULL;
662  vnet_hw_interface_t *outside_hw_if_index = NULL;
663 
664  if (! unformat(input, "inside %U",
665  unformat_vnet_sw_interface, vnm, &inside_sw_if_index))
666  return clib_error_return (0, "unknown input `%U'",
667  format_unformat_error, input);
668 
669  if (!unformat (input, "%U", unformat_ip4_address, &lo))
670  return clib_error_return (0, "unknown input `%U'",
671  format_unformat_error, input);
672 
673  if (unformat (input, "- %U", unformat_ip4_address, &hi))
674  ;
675 
676  /* $$$$ remember to set i_vrf, i_vrf_id as needed */
677 
678  /* Fill the structure spp_api_cnat_v4_add_vrf_map_t & let this API handle it */
679  /* i_vrf_id & o_vrf_id are 32-bit & i_vrf, o_vrf are 16 bit */
680 
681  if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
682  vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
683  return clib_error_return (0, "Could not find the inside interface");
684  }
685  outside_sw_if_index = vcm->inside_sw_if_index_table[inside_sw_if_index];
686 
687  map.i_vrf_id = inside_sw_if_index;
688  map.o_vrf_id = outside_sw_if_index;
689  map.i_vrf = inside_sw_if_index;
690  map.o_vrf = outside_sw_if_index;
691 
692  map.start_addr[0] = clib_net_to_host_u32(lo.as_u32);
693  map.end_addr[0] = clib_net_to_host_u32(hi.as_u32);
694 
696 
697 #if 1
698  inside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, inside_sw_if_index);
699  if (inside_hw_if_index) {
701  inside_hw_if_index->hw_if_index, vcgn_classify_node.index);
702  }
703  outside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, outside_sw_if_index);
704  if (outside_hw_if_index) {
706  outside_hw_if_index->hw_if_index, vcgn_classify_node.index);
707  }
708 #endif
709  return 0;
710 }
711 
712 static clib_error_t *
714  unformat_input_t * input,
715  vlib_cli_command_t * cmd)
716 {
717  /*
718  vnet_main_t * vnm = vnet_get_main();
719  vcgn_classify_main_t * vcm = &vcgn_classify_main;
720  */
721  u32 act_timeout = 0;
722  u32 init_timeout = 0;
723 
724  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
725  if (unformat(input, "active %u", &act_timeout))
726  tcp_active_timeout = act_timeout;
727  else if (unformat(input, "init %u", &init_timeout))
728  tcp_initial_setup_timeout = init_timeout;
729  else break;
730  }
731  return 0;
732 }
733 
734 static clib_error_t *
736  unformat_input_t * input,
737  vlib_cli_command_t * cmd)
738 {
739  /*
740  vnet_main_t * vnm = vnet_get_main();
741  vcgn_classify_main_t * vcm = &vcgn_classify_main;
742  */
743  u32 act_timeout = 0;
744  u32 init_timeout = 0;
745 
746  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
747  if (unformat(input, "active %u", &act_timeout))
748  udp_act_session_timeout = act_timeout;
749  else if (unformat(input, "init %u", &init_timeout))
750  udp_init_session_timeout = init_timeout;
751  else break;
752  }
753  return 0;
754 }
755 
756 
757 static clib_error_t *
759  unformat_input_t * input,
760  vlib_cli_command_t * cmd)
761 {
762  /*
763  * vnet_main_t * vnm = vnet_get_main();
764  * vcgn_classify_main_t * vcm = &vcgn_classify_main;
765  */
766  u32 timeout = 0;
767 
768  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
769  if (unformat(input, "%u", &timeout))
770  ;
771  else break;
772  }
773  icmp_session_timeout = timeout;
774  return 0;
775 }
776 
777 
778 static clib_error_t *
780  unformat_input_t * input,
781  vlib_cli_command_t * cmd)
782 {
783  /*
784  vnet_main_t * vnm = vnet_get_main();
785  vcgn_classify_main_t * vcm = &vcgn_classify_main;
786  */
787  u8 *protocol;
788  u8 reset = 1;
789 
790  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
791  if (unformat(input, "%s", &protocol))
792  ;
793  else break;
794  }
795  cnat_nat44_set_protocol_timeout_value(0, 0, protocol, reset, vm);
796  return 0;
797 }
798 
799 static clib_error_t *
801  unformat_input_t * input,
802  vlib_cli_command_t * cmd)
803 {
804  /*
805  vnet_main_t * vnm = vnet_get_main();
806  vcgn_classify_main_t * vcm = &vcgn_classify_main;
807  */
808  u32 port = 0;
809 
810  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
811  if (unformat(input, "%u", &port))
812  ;
813  else break;
814  }
815  if (port != 0 && port > 65535) {
816  vlib_cli_output(vm, "Error !! Invalid port\n");
817  } else {
818  cnat_static_port_range = port;
819  vlib_cli_output(vm, "Dynamic Port Range Config Successful !!\n");
820  }
821  return 0;
822 }
823 
824 static clib_error_t *
826  unformat_input_t * input,
827  vlib_cli_command_t * cmd)
828 {
829  /*
830  vnet_main_t * vnm = vnet_get_main();
831  vcgn_classify_main_t * vcm = &vcgn_classify_main;
832  */
833  u32 port = 0;
834 
835  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
836  if (unformat(input, "%u", &port))
837  ;
838  else break;
839  }
840  if (port != 0 && port > 65535) {
841  vlib_cli_output(vm, "Error !! Invalid port\n");
842  } else {
844  vlib_cli_output(vm, "Port Limit Config Successful !!\n");
845  }
846  return 0;
847 }
848 
849 static inline void nfv9_init_pkt_sent_data(cnat_nfv9_logging_info_t *nfv9_info)
850 {
852  nfv9_info->server_index;
853 
854  /*
855  * Reset the pkts_since_last_template and sent_time
856  * so that template will be sent next time
857  */
858  server->last_template_sent_time = 0;
859  server->pkts_since_last_template = 0xffffffff;
860 }
861 
863 {
864  u16 max_length_minus_max_record_size;
865  if(!path_mtu) /* Use default */
866  path_mtu = NFV9_DEF_PATH_MTU;
867 
868  max_length_minus_max_record_size = path_mtu -
871  CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH; /* Note.. as of now this record
872  * requires max number of bytes. If you add more records,
873  * this needs to be re-checked */
874  if (max_length_minus_max_record_size < CNAT_NFV9_MIN_RECORD_SIZE) {
875  max_length_minus_max_record_size = CNAT_NFV9_MIN_RECORD_SIZE;
876  }
877  return max_length_minus_max_record_size;
878 }
879 
880 /* This function finds if the netflow server indicated by
881  * new_server_info is already configured for some other instance
882  * if yes, it returns the same pointer so that, info sent to the
883  * server is consistent. If the server is not found, a new instance
884  * is created and returned. If an existing server is used, its refernce
885  * count is incrimented (indicating the number of instances using the
886  * same server
887  */
888  /* #define DEBUG_NF_SERVER_CONFIG 1 */
890  cnat_nfv9_logging_info_t *nfv9_info, nfv9_server_info_t *new_server_info)
891 {
892 
893  /* Check if the instance has a server already and if yes, does it match */
894  nfv9_server_info_t *server;
895  if(nfv9_info->server_index != EMPTY) {
896  server = nfv9_server_info_pool + nfv9_info->server_index;
897 
898  if((server->ipv4_address == new_server_info->ipv4_address) &&
899  (server->port == new_server_info->port)) {
900  /* Same server.. just check if refresh rate/timeouts are reduced */
901 #ifdef DEBUG_NF_SERVER_CONFIG
902  if(my_instance_number == 1) {
903  printf("\n Server match for %x and port %d\n",
904  new_server_info->ipv4_address, new_server_info->port);
905  }
906 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
907  goto adjust_refresh_rate;
908  } else { /* The server is being changed */
909  server->ref_count--;
910 #ifdef DEBUG_NF_SERVER_CONFIG
911  if(my_instance_number == 1) {
912  printf("\n Server change from %x, %d to %x, %d"
913  "Ref count %d\n",
914  server->ipv4_address,
915  server->port,
916  new_server_info->ipv4_address, new_server_info->port,
917  server->ref_count);
918  }
919 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
920  if(!server->ref_count) {
921  /* Return this server to pool */
922 #ifdef DEBUG_NF_SERVER_CONFIG
923  if(my_instance_number == 1) {
924  PLATFORM_DEBUG_PRINT("Deleting Server %x, %d at %d\n",
925  server->ipv4_address,
926  server->port,
927  nfv9_info->server_index);
928  }
929 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
931  }
932  }
933  }
934 
935  /* Now check if the server is already present in the pool */
936  u8 found = 0;
937  server = 0;
939  if ((server->ipv4_address == new_server_info->ipv4_address) &&
940  (server->port == new_server_info->port)) {
941  server->ref_count++;
942  nfv9_info->server_index = server - nfv9_server_info_pool;
943  found = 1;
944 #ifdef DEBUG_NF_SERVER_CONFIG
945  if(my_instance_number == 1) {
946  printf("Re-using server %x, %d Ref count %d\n",
947  server->ipv4_address, server->port, server->ref_count);
948  }
949 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
950  break;
951  }
952  }));
953 
954  if(!found) {
955  /* Create a new one, initialize and return */
956  server = 0;
958  clib_memcpy(server, new_server_info, sizeof(nfv9_server_info_t));
959  server->ref_count = 1;
960  nfv9_info->server_index = server - nfv9_server_info_pool;
961 #ifdef DEBUG_NF_SERVER_CONFIG
962  if(my_instance_number == 1) {
963  printf("Create new server for at %d %x and port %d\n",
964  nfv9_info->server_index,
965  new_server_info->ipv4_address, new_server_info->port);
966  }
967 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
968  return CNAT_SUCCESS;
969  }
970 
971 adjust_refresh_rate:
972  if(server->refresh_rate >
973  new_server_info->refresh_rate) {
974  server->refresh_rate =
975  new_server_info->refresh_rate;
976 #ifdef DEBUG_NF_SERVER_CONFIG
977  if(my_instance_number == 1) {
978  printf("Reset refresh rate to %d\n",
979  server->refresh_rate);
980  }
981 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
982  }
983 
984  if(server->timeout_rate >
985  new_server_info->timeout_rate) {
986  server->timeout_rate =
987  new_server_info->timeout_rate;
988 #ifdef DEBUG_NF_SERVER_CONFIG
989  if(my_instance_number == 1) {
990  printf("Reset timeout rate to %d\n",
991  server->timeout_rate);
992  }
993 #endif /* #ifdef DEBUG_NF_SERVER_CONFIG */
994  }
995 
996  return CNAT_SUCCESS;
997 }
998 static clib_error_t *
1000  unformat_input_t * input,
1001  vlib_cli_command_t * cmd)
1002 {
1005  ip4_address_t server_addr;
1006  u32 ip_addr = 0;
1007  u32 port;
1008  u32 refresh_rate = 0;
1009  u32 timeout = 0;
1010  u32 pmtu = 0;
1011  u8 enable = 1;
1012 /* vcgn changes start*/
1013  cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL;
1014  cnat_nfv9_logging_info_t *my_nfv9_logging_info_tmp = NULL;
1015  cnat_vrfmap_t *my_vrfmap = 0, *my_vrfmap_temp = 0;
1016  u16 i_vrf = ~0;
1017  u32 i_vrf_id = ~0;
1018  u8 found;
1019  u32 inside_sw_if_index = EMPTY;
1020  /*
1021  * Init NFv9 logging info as needed, this will be done only once
1022  */
1024 
1025  found = 0;
1026 
1027 /* vcgn changes end*/
1028  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
1029  if (unformat (input, "inside %U",
1030  unformat_vnet_sw_interface, &inside_sw_if_index)) {
1031  /* Do nothing */
1032  } else if (unformat (input, "server %U", unformat_ip4_address, &server_addr))
1033  ip_addr = clib_net_to_host_u32(server_addr.as_u32);
1034  else if (unformat(input, "port %u", &port))
1035  ;
1036  else if (unformat(input, "refresh-rate %u", &refresh_rate))
1037  ;
1038  else if (unformat(input, "timeout %u", &timeout))
1039  ;
1040  else if (unformat(input, "pmtu %u", &pmtu))
1041  ;
1042  else if (unformat(input, "del"))
1043  enable = 0;
1044  else break;
1045  }
1046 
1047  if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) ||
1048  vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) {
1049  return clib_error_return (0, "Could not find the inside interface");
1050  }
1051  i_vrf = inside_sw_if_index;
1052  i_vrf_id = inside_sw_if_index;
1053 
1054  #if 0
1055  vlib_cli_output(vm, "ip 0x%x, port %u, refresh %u, "
1056  "timeout %u, pmtu %u enable %u\n",
1057  ip_addr, port, refresh_rate,
1058  timeout, pmtu, enable);
1059  #endif
1060  if (refresh_rate == 0) refresh_rate = 500; /* num of pkts */
1061  if (timeout == 0) timeout = 30; /* in mins */
1062 
1063  nfv9_conf.enable = enable;
1064  nfv9_conf.ipv4_address = ip_addr;
1065  nfv9_conf.i_vrf_id = inside_sw_if_index;
1066  nfv9_conf.i_vrf = inside_sw_if_index;
1067  nfv9_conf.port = port;
1068  nfv9_conf.refresh_rate = refresh_rate;
1069  nfv9_conf.timeout_rate = timeout;
1070  nfv9_conf.path_mtu = pmtu;
1071  nfv9_conf.nfv9_global_collector = 0;
1072  nfv9_conf.session_logging = 0;
1073 
1074  /*
1075  * At this point the NFv9 global information should already be
1076  * inited as we have called cnat_nfv9_logging_init()
1077  */
1078 
1079  if (nfv9_conf.nfv9_global_collector) {
1081  found = 1;
1082  my_nfv9_logging_info = cnat_nfv9_logging_info_pool +
1084  }
1085  } else {
1086  /* Do we already have a map for this VRF? */
1087  pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1088  if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) {
1089  nfv9_server_info_t *server = nfv9_server_info_pool +
1090  my_nfv9_logging_info->server_index;
1091  if((server->ipv4_address == (nfv9_conf.ipv4_address)) && (server->port == (nfv9_conf.port))) {
1092  found = 1;
1093  my_nfv9_logging_info_tmp = my_nfv9_logging_info;
1094  break;
1095  }
1096  }
1097  }));
1098  }
1099 
1100  if ((nfv9_conf.ipv4_address == 0) ||
1101  (nfv9_conf.port == 0)) {
1102  vlib_cli_output(vm,
1103  "Add NFv9 ivrf %d Logging Invalid values [IPv4 0x%x, PORT %d]\n",
1104  i_vrf,
1105  (nfv9_conf.ipv4_address),
1106  (nfv9_conf.port));
1107  goto done;
1108  }
1109 
1110  if (nfv9_conf.enable) {
1111  if ((nfv9_conf.ipv4_address == 0) ||
1112  (nfv9_conf.port == 0)) {
1113  nfv9_conf.rc = CNAT_ERR_PARSER;
1114  vlib_cli_output(vm,
1115  "NFV9_logging i_vrf %d, Invalid [v4_addr 0x%x port %d]\n",
1116  i_vrf,
1117  (nfv9_conf.ipv4_address),
1118  (nfv9_conf.port));
1119  goto done;
1120  }
1121 
1122  nfv9_server_info_t new_server_info;
1123  memset(&new_server_info, 0, sizeof(nfv9_server_info_t));
1124  new_server_info.ipv4_address =
1125  nfv9_conf.ipv4_address;
1126  new_server_info.port =
1127  (nfv9_conf.port);
1128  new_server_info.refresh_rate =
1129  (nfv9_conf.refresh_rate);
1130  /*
1131  * Store the timeout in seconds. User configures it in minutes
1132  */
1133  new_server_info.timeout_rate =
1134  60*(nfv9_conf.timeout_rate);
1135  if (found && my_nfv9_logging_info) {
1136  /*
1137  * Entry already present, change it
1138  */
1139  my_nfv9_logging_info->max_length_minus_max_record_size =
1141  ((nfv9_conf.path_mtu)));
1142  } else {
1143  pool_get(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1144  memset(my_nfv9_logging_info, 0, sizeof(*my_nfv9_logging_info));
1145  my_nfv9_logging_info->server_index = EMPTY;
1146  my_nfv9_logging_info->nfv9_logging_next_index = EMPTY;
1147  /*
1148  * Make the current and head logging context indeices as EMPTY.
1149  * When first logging happens, these get set correctly
1150  */
1151  my_nfv9_logging_info->current_logging_context = NULL;
1152  my_nfv9_logging_info->queued_logging_context = NULL;
1153 #if 0
1154  my_nfv9_logging_info->f = NULL;
1155  my_nfv9_logging_info->to_next = NULL;
1156  output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-input");
1157  my_nfv9_logging_info->ip4_input_node_index = output_node->index;
1158  printf("ip4_input_node_index %d\n", my_nfv9_logging_info->ip4_input_node_index);
1159 #endif
1160  my_nfv9_logging_info->i_vrf = i_vrf;
1161  my_nfv9_logging_info->i_vrf_id = i_vrf_id;
1162  my_nfv9_logging_info->max_length_minus_max_record_size =
1164  nfv9_conf.path_mtu);
1165 
1166  /* my_nfv9_logging_info will have a copy of logging_policy
1167  * because, it is quite possible that nfv9 config arrives before
1168  * the corresponding vrfmap is initialized. In such cases
1169  * this copy will be used to update the vrfmap entry
1170  */
1171  my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1172 
1173  if (nfv9_conf.nfv9_global_collector) {
1175  my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1176 
1177  pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1178  if (my_vrfmap->nfv9_logging_index == EMPTY) {
1179  my_vrfmap->nfv9_logging_index =
1180  cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1181  }
1182  }));
1183  } else {
1184  u32 my_vrfmap_found = 0;
1185 
1187  my_vrfmap = my_vrfmap_temp;
1188  if (my_vrfmap_found) {
1189  if(my_vrfmap->nfv9_logging_index == EMPTY) {
1190  my_vrfmap->nfv9_logging_index =
1191  my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1192  // my_vrfmap->nf_logging_policy = mp->session_logging;
1193  } else {
1194  cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index;
1195  while(my_nfv9_logging_info_temp->nfv9_logging_next_index != EMPTY){
1196  my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_nfv9_logging_info_temp->nfv9_logging_next_index;
1197  }
1198  my_nfv9_logging_info_temp->nfv9_logging_next_index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1199  }
1200  }
1201  }
1202  }
1203 
1204  /* Update logging policy */
1205  my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging;
1206  if (nfv9_conf.nfv9_global_collector) {
1207  if(PLATFORM_DBL_SUPPORT) {
1208  pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1209  if (my_vrfmap->nfv9_logging_index ==
1211  my_vrfmap->nf_logging_policy = nfv9_conf.session_logging;
1212  }
1213  }));
1214  } else {
1215  nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1216  }
1217  } else {
1218  if(PLATFORM_DBL_SUPPORT) {
1219  u32 my_vrfmap_found = 0;
1220  my_vrfmap_temp = NULL;
1222  my_vrfmap = my_vrfmap_temp;
1223  if (my_vrfmap_found) {
1224  // my_vrfmap->nf_logging_policy = mp->session_logging;
1225  }
1226  } else {
1227  nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB;
1228  }
1229  }
1230  u8 nfv9_logging_policy = 0;
1231  u32 my_vrfmap_found = 0;
1232  my_vrfmap_temp = NULL;
1234  my_vrfmap = my_vrfmap_temp;
1235  if (my_vrfmap_found) {
1236  u32 index_curr = my_vrfmap->nfv9_logging_index;
1237  cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1238  while(index_curr != EMPTY) {
1239  my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1240  nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1241  index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1242  }
1243  my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1244  }
1245  //vlib_cli_output(vm,"Netflow logging policy = %d\n", my_vrfmap->nf_logging_policy);
1246  if(nfv9_get_server_instance(my_nfv9_logging_info, &new_server_info)
1247  != CNAT_SUCCESS) {
1248  vlib_cli_output(vm, "Error to get server instance");
1249  nfv9_conf.rc = CNAT_ERR_PARSER;
1250  goto done;
1251  }
1252  nfv9_init_pkt_sent_data(my_nfv9_logging_info);
1253 
1254  vlib_cli_output(vm,"Adding NFv9 Logging Succeeded\n");
1255  nfv9_configured = 1;
1256 
1257  } else {
1258  /*Delete path*/
1259  if (found) {
1260  /* if found entry then we need to overwrite the my_nfv9_logging_info_tmp
1261  * to my_nfv9_logging_info
1262  */
1263  my_nfv9_logging_info = my_nfv9_logging_info_tmp;
1264  if (i_vrf == INVALID_UIDX) {
1265  /*
1266  * We are deleting a global collector. Mark the collectors
1267  * in those VRFs using the global collector
1268  */
1269  pool_foreach (my_vrfmap, cnat_map_by_vrf, ({
1270  if (my_vrfmap->nfv9_logging_index ==
1272  my_vrfmap->nfv9_logging_index = EMPTY;
1273  }
1274  }));
1275 
1277  } else {
1278  u32 my_vrfmap_found = 0;
1279  my_vrfmap_temp = NULL;
1281  my_vrfmap = my_vrfmap_temp;
1282  if (my_vrfmap_found) {
1283  // my_vrfmap->nfv9_logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index;
1284  }
1285  }
1286  if (my_nfv9_logging_info->queued_logging_context ||
1287  my_nfv9_logging_info->current_logging_context) {
1288  /*
1289  * If there is a pending context:
1290  * Set the deleted flag to 1. This will ensure
1291  * that the logging info structure gets freed after any
1292  * pending packet get sent
1293  */
1294  my_nfv9_logging_info->deleted = 1;
1295  } else {
1296  /*
1297  * No pending context, just free the logging info structure
1298  */
1299  u32 index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool;
1300  if(index == my_vrfmap->nfv9_logging_index) {
1301  /* Deleting the first sever */
1302  my_vrfmap->nfv9_logging_index = my_nfv9_logging_info->nfv9_logging_next_index;
1303  /* if(my_nfv9_logging_info->nfv9_logging_next_index != EMPTY){
1304  my_vrfmap->nf_logging_policy = (cnat_nfv9_logging_info_pool + my_nfv9_logging_info->nfv9_logging_next_index)->logging_policy;
1305  } else {
1306  my_vrfmap->nf_logging_policy = EMPTY;
1307  }*/
1308  } else {
1309  u32 index_curr = my_vrfmap->nfv9_logging_index;
1310  u32 index_prev = EMPTY;
1311  while(index_curr != EMPTY) {
1312  index_prev = index_curr;
1313  index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1314  if(index == index_curr)
1315  {
1316  (cnat_nfv9_logging_info_pool + index_prev)->nfv9_logging_next_index = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1317  break;
1318  }
1319  }
1320  }
1321  nfv9_delete_server_info(my_nfv9_logging_info);
1322  pool_put(cnat_nfv9_logging_info_pool, my_nfv9_logging_info);
1323  }
1324 
1325  vlib_cli_output(vm, "Deleting NFv9 Logging Succeeded\n");
1326  /*
1327  * Search across all vrf and check if nfv9 logging is configured.
1328  */
1329  nfv9_configured = 0;
1330  pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({
1331  nfv9_configured = 1;
1332  break;
1333  }));
1334  } else {
1335  nfv9_conf.rc = CNAT_NO_CONFIG;
1336  vlib_cli_output(vm, "Add NFv9 Logging Failed (2) Non Existent vrf %d\n",
1337  i_vrf);
1338 
1339  }
1340  u8 nfv9_logging_policy = 0;
1341  u32 my_vrfmap_found = 0;
1342  my_vrfmap_temp = NULL;
1344  my_vrfmap = my_vrfmap_temp;
1345  if (my_vrfmap_found) {
1346  u32 index_curr = my_vrfmap->nfv9_logging_index;
1347  cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp;
1348  while(index_curr != EMPTY) {
1349  my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr;
1350  nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy;
1351  index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index;
1352  }
1353  my_vrfmap->nf_logging_policy = nfv9_logging_policy;
1354  }
1355  }
1356 
1357 done:
1358  return 0;
1359 }
1360 
1361 /* config CLIs */
1362 VLIB_CLI_COMMAND (set_vcgn_map_command) = {
1363  .path = "set vcgn map",
1364  .short_help = "set vcgn map <lo-address> [- <hi-address>]",
1365  .function = set_vcgn_map_command_fn,
1366 };
1367 
1368 VLIB_CLI_COMMAND (set_vcgn_inside_command) = {
1369  .path = "set vcgn inside",
1370  .short_help = "set vcgn inside <inside intfc> outside <outside intfc>",
1371  .function = set_vcgn_inside_command_fn,
1372 };
1373 
1374 VLIB_CLI_COMMAND (set_vcgn_tcp_timeout_command) = {
1375  .path = "set vcgn tcp timeout",
1376  .short_help = "set vcgn tcp timeout active <1-65535> init <1-65535>",
1377  .function = set_vcgn_tcp_timeout_command_fn,
1378 };
1379 
1380 VLIB_CLI_COMMAND (set_vcgn_udp_timeout_command) = {
1381  .path = "set vcgn udp timeout",
1382  .short_help = "set vcgn udp timeout active <1-65535> init <1-65535>",
1383  .function = set_vcgn_udp_timeout_command_fn,
1384 };
1385 
1386 VLIB_CLI_COMMAND (set_vcgn_icmp_timeout_command) = {
1387  .path = "set vcgn icmp timeout",
1388  .short_help = "set vcgn icmp timeout <1-65535>",
1390 };
1391 
1392 VLIB_CLI_COMMAND (set_vcgn_protocol_default_timeout_command) = {
1393  .path = "set vcgn default timeout",
1394  .short_help = "set vcgn default timeout protocol <tcp/udp/icmp>",
1396 };
1397 
1398 VLIB_CLI_COMMAND (set_vcgn_dynamic_port_start_range_command) = {
1399  .path = "set vcgn dynamic port start",
1400  .short_help = "set vcgn dynamic port start <1-65535>",
1402 };
1403 
1404 VLIB_CLI_COMMAND (set_vcgn_port_limit_command) = {
1405  .path = "set vcgn port limit",
1406  .short_help = "set vcgn port limit <1-65535>",
1407  .function = set_vcgn_port_limit_command_fn,
1408 };
1409 
1410 VLIB_CLI_COMMAND (set_vcgn_nfv9_logging_cofig_command) = {
1411  .path = "set vcgn nfv9",
1412  .short_help = "set vcgn nfv9 [del] inside <interface> "
1413  "server <ip-addr> port <port> [refresh-rate <n>] "
1414  "[timeout <n>] [pmtu <n>]",
1416 };
1417 
1418 
1419 /* show CLIs */
1420 VLIB_CLI_COMMAND (show_vcgn_config_command) = {
1421  .path = "show vcgn config",
1422  .short_help = "show vcgn config",
1423  .function = show_vcgn_config_command_fn,
1424 };
1425 
1426 VLIB_CLI_COMMAND (show_vcgn_stat_command) = {
1427  .path = "show vcgn statistics",
1428  .short_help = "show vcgn statistics",
1429  .function = show_vcgn_stats_command_fn,
1430 };
1431 
1432 VLIB_CLI_COMMAND (show_vcgn_inside_translation_command) = {
1433  .path = "show vcgn inside-translation",
1434  .short_help = "show vcgn inside-translation protocol <tcp/udp/icmp> "
1435  "interface <inside-if> inside-addr <ip-addr> "
1436  "[start-port <n>] [end-port <n>]",
1438 };
1439 
1440 VLIB_CLI_COMMAND (show_vcgn_outside_translation_command) = {
1441  .path = "show vcgn outside-translation",
1442  .short_help = "show vcgn outside-translation protocol <tcp/udp/icmp> "
1443  "interface <outside-if> outside-addr <ip-addr> "
1444  "[start-port <n>] [end-port <n>]",
1446 };
1447 
1448 static clib_error_t *
1450 {
1451  clib_error_t * error = 0;
1452 
1453  if ((error = vlib_call_init_function
1454  (vm, vcgn_classify_init)))
1455  return error;
1456  if ((error = vlib_call_init_function
1458  return error;
1459  if ((error = vlib_call_init_function
1461  return error;
1462  if ((error = vlib_call_init_function
1464  return error;
1465  if ((error = vlib_call_init_function
1466  (vm, cnat_db_scanner_init)))
1467  return error;
1468  if ((error = vlib_call_init_function
1470  return error;
1471  if ((error = vlib_call_init_function
1473  return error;
1474  if ((error = vlib_call_init_function
1476  return error;
1477  if ((error = vlib_call_init_function
1479  return error;
1480  if ((error = vlib_call_init_function
1482  return error;
1483  if ((error = vlib_call_init_function
1485  return error;
1486  if ((error = vlib_call_init_function
1488  return error;
1489  if ((error = vlib_call_init_function
1491  return error;
1492 
1493  return error;
1494 }
1495 
1496 /*
1497  * This routine exists to convince the vlib plugin framework that
1498  * we haven't accidentally copied a random .dll into the plugin
1499  * directory. This is used in lieu of VLIB_INIT_FUNCTION(vcgn_init).
1500  *
1501  * Also collects global variable pointers passed from the vpp engine
1502  */
1503 clib_error_t *
1505  int from_early_init)
1506 {
1507  return vcgn_init(vm);
1508 }
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:459
clib_error_t * cnat_ipv4_icmp_e_inside_input_init(vlib_main_t *vm)
cnat_nfv9_global_info_t cnat_nfv9_global_info
Definition: cnat_logging.c:63
vmrglw vmrglh hi
static clib_error_t * set_vcgn_dynamic_port_start_range_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u32 error_heap_index
Definition: node.h:278
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
u8 nfv9_configured
Definition: cnat_global.c:30
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
static clib_error_t * set_vcgn_udp_timeout_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static u16 nfv9_get_max_length_minus_max_record_size(u16 path_mtu)
void cnat_scanner_db_process_turn_on(vlib_main_t *vm)
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static clib_error_t * set_vcgn_icmp_timeout_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
unformat_function_t unformat_pg_ip4_header
Definition: format.h:91
int vnet_hw_interface_rx_redirect_to_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: interface.c:1100
Fixed length block allocator.
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
#define NULL
Definition: clib.h:55
u16 cnat_static_port_range
Definition: cnat_config.c:53
static clib_error_t * vcgn_init(vlib_main_t *vm)
void cnat_v4_show_inside_entry_req_t_handler(spp_api_cnat_v4_show_inside_entry_req_t *mp, vlib_main_t *vm)
struct _vlib_node_registration vlib_node_registration_t
#define ICMPV4_ECHOREPLY
unformat_function_t unformat_vnet_sw_interface
#define CNAT_NFV9_MIN_RECORD_SIZE
Definition: cnat_logging.h:894
u16 udp_init_session_timeout
Definition: cnat_config.c:28
clib_error_t * cnat_ipv4_udp_inside_input_exc_init(vlib_main_t *vm)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
static uword vcgn_classify_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
format_function_t format_ip4_address
Definition: format.h:79
static clib_error_t * set_vcgn_map_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static void nfv9_init_pkt_sent_data(cnat_nfv9_logging_info_t *nfv9_info)
clib_error_t * cnat_ipv4_udp_inside_input_init(vlib_main_t *vm)
static u16 nfv9_get_server_instance(cnat_nfv9_logging_info_t *nfv9_info, nfv9_server_info_t *new_server_info)
u8 cnat_db_init_done
Definition: cnat_db_v2.c:43
static pg_node_t * pg_get_node(uword node_index)
Definition: pg.h:350
static clib_error_t * set_vcgn_tcp_timeout_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u16 cnat_main_db_max_ports_per_user
Definition: cnat_config.c:48
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
clib_error_t * cnat_ipv4_tcp_outside_input_init(vlib_main_t *vm)
clib_error_t * cnat_ipv4_udp_outside_input_init(vlib_main_t *vm)
#define PLATFORM_DEBUG_PRINT(...)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:194
clib_error_t * cnat_ipv4_icmp_q_outside_input_init(vlib_main_t *vm)
clib_error_t * cnat_db_scanner_init(vlib_main_t *vm)
ip4_address_t dst_address
Definition: ip4_packet.h:163
#define FIND_MY_VRF_USING_I_VRF_ID
Definition: vcgn_classify.c:60
static clib_error_t * set_vcgn_protocol_default_timeout_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
void cnat_nat44_set_protocol_timeout_value(u16 active, u16 init, u8 *proto, u8 reset, vlib_main_t *vm)
#define vlib_call_init_function(vm, x)
Definition: init.h:161
clib_error_t * cnat_ipv4_icmp_e_outside_input_init(vlib_main_t *vm)
void cnat_nat44_handle_show_stats(vlib_main_t *vm)
unformat_function_t unformat_ip4_address
Definition: format.h:76
#define CNAT_MAX_VRFMAP_ENTRIES
Definition: cnat_db.h:103
void cnat_nfv9_logging_init()
vlib_error_main_t error_main
Definition: main.h:124
nfv9_server_info_t * nfv9_server_info_pool
Definition: cnat_logging.c:95
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
#define PREDICT_FALSE(x)
Definition: clib.h:97
vlib_main_t * vlib_main
Definition: vcgn_classify.c:47
u16 icmp_session_timeout
Definition: cnat_config.c:30
u16 vrf_map_array[CNAT_MAX_VRFMAP_ENTRIES]
Definition: cnat_db_v2.c:225
struct _spp_api_cnat_v4_config_nfv9_logging spp_api_cnat_v4_config_nfv9_logging_t
static char * vcgn_classify_error_strings[]
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:350
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
static clib_error_t * set_vcgn_nfv9_logging_cofig_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
vcgn_classify_main_t vcgn_classify_main
Definition: vcgn_classify.c:85
clib_error_t * cnat_ipv4_tcp_inside_input_init(vlib_main_t *vm)
vcgn_classify_error_t
Definition: vcgn_classify.c:98
vcgn_classify_next_t
u64 * counters
Definition: error.h:78
void cnat_nat44_handle_show_config(vlib_main_t *vm)
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
#define INVALID_UIDX
Definition: cnat_db.h:419
void cnat_db_v2_init(void)
Definition: cnat_db_v2.c:3675
vlib_node_registration_t vcgn_classify_node
(constructor) VLIB_REGISTER_NODE (vcgn_classify_node)
Definition: vcgn_classify.c:87
#define clib_memcpy(a, b, c)
Definition: string.h:69
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:207
static u8 * format_swap_trace(u8 *s, va_list *args)
Definition: vcgn_classify.c:72
static clib_error_t * show_vcgn_config_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
unformat_function_t * unformat_edit
Definition: pg.h:307
struct _spp_api_cnat_v4_show_outside_entry_req spp_api_cnat_v4_show_outside_entry_req_t
struct _spp_api_cnat_v4_add_vrf_map spp_api_cnat_v4_add_vrf_map_t
#define ARRAY_LEN(x)
Definition: clib.h:59
u8 my_instance_number
Definition: cnat_ports.c:51
static void nfv9_delete_server_info(cnat_nfv9_logging_info_t *nfv9_info)
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u16 tcp_initial_setup_timeout
Definition: cnat_config.c:26
u16 cached_next_index
Definition: node.h:463
unsigned int u32
Definition: types.h:88
u16 tcp_active_timeout
Definition: cnat_config.c:27
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:361
#define PLATFORM_DBL_SUPPORT
#define ICMPV4_ECHO
struct _spp_api_cnat_v4_show_inside_entry_req spp_api_cnat_v4_show_inside_entry_req_t
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
#define foreach_vcgn_classify_error
Definition: vcgn_classify.c:89
void cnat_v4_show_outside_entry_req_t_handler(spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm)
cnat_nfv9_logging_info_t * cnat_nfv9_logging_info_pool
Definition: cnat_logging.c:93
#define VRF_MAP_ENTRY_EMPTY
Definition: cnat_db.h:506
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
clib_error_t * cnat_ipv4_tcp_inside_input_exc_init(vlib_main_t *vm)
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
unsigned short u16
Definition: types.h:57
cnat_vrfmap_t * cnat_map_by_vrf
Definition: cnat_db_v2.c:218
static clib_error_t * show_vcgn_stats_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
u16 udp_act_session_timeout
Definition: cnat_config.c:29
void cnat_nat44_add_vrf_map_t_handler(spp_api_cnat_v4_add_vrf_map_t *mp, vlib_main_t *vm)
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
static clib_error_t * show_vcgn_outside_translation_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:170
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
clib_error_t * vcgn_classify_init(vlib_main_t *vm)
clib_error_t * cnat_ipv4_icmp_q_inside_input_init(vlib_main_t *vm)
#define NFV9_PAD_VALUE
Definition: cnat_logging.h:912
u8 data[0]
Packet data.
Definition: buffer.h:158
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:58
#define EMPTY
Definition: index_list.h:24
vnet_main_t * vnet_main
Definition: vcgn_classify.c:48
#define clib_error_return(e, args...)
Definition: error.h:111
u8 ip_version_and_header_length
Definition: ip4_packet.h:131
struct _unformat_input_t unformat_input_t
#define NFV9_DEF_PATH_MTU
Definition: cnat_logging.h:36
#define CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH
Definition: cnat_logging.h:821
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:445
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
clib_error_t * cnat_ipv4_icmp_q_inside_input_exc_init(vlib_main_t *vm)
vlib_init_function_t *_vlib_init_function_vcgn_init **Also collects global variable pointers passed from the vpp engine *clib_error_t * vlib_plugin_register(vlib_main_t *vm, vnet_plugin_handoff_t *h, int from_early_init)
static clib_error_t * set_vcgn_inside_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static clib_error_t * set_vcgn_port_limit_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static clib_error_t * show_vcgn_inside_translation_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
Definition: pg.h:304
#define CNAT_TRANSLATION_ENTRY_DYNAMIC
Definition: defs.h:46
#define CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH
Definition: cnat_logging.h:871