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