FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
cnat_syslog.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * cnat_syslog.c
4  *
5  * Copyright (c) 2011-2013 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <arpa/inet.h>
21 #include "cnat_syslog.h"
22 #include "platform_common.h"
23 #include "cnat_db.h"
24 #include "cnat_log_common.h"
25 #include <vppinfra/pool.h>
26 
27 #define SYSLOG_DELIMITER ' '
28 #define SYSLOG_FIELD_ABSENT '-'
29 /* #define SHOW_SYSLOG_TIMESTAMP 1 TO DO. Remove this later */
30 /*
31  * Defining the below macro here for now. Assumption is, syslog packets
32  * are sent out via same channel as that of NFV9.
33  * Has to be overridden if this assumption is false.
34  */
35 #define PLATFORM_SYSLOG_DISP_NODE_IDX PLATFORM_NFV9_DISP_NODE_IDX
36 
40 extern u32 syslog_debug_flag;
41 
42 #define CNAT_SYSLOG_DEBUG_CODE 2
43 
44 #if CNAT_SYSLOG_DEBUG_CODE > 3
45 #define SYSLOG_COND if(my_instance_number == 0)
46 
47 #define SYSLOG_DEBUG_PRINTF1(a) SYSLOG_COND printf(a);
48 #define SYSLOG_DEBUG_PRINTF2(a, b) SYSLOG_COND printf(a, b);
49 #define SYSLOG_DEBUG_PRINTF3(a, b, c) SYSLOG_COND printf(a, b, c);
50 #define SYSLOG_DEBUG_PRINTF4(a, b, c, d) SYSLOG_COND printf(a, b, c, d);
51 
52 #else
53 
54 #define SYSLOG_DEBUG_PRINTF1(a)
55 #define SYSLOG_DEBUG_PRINTF2(a, b)
56 #define SYSLOG_DEBUG_PRINTF3(a, b, c)
57 #define SYSLOG_DEBUG_PRINTF4(a, b, c, d)
58 
59 #endif
60 
61 
62 void syslog_params_show(u32 logging_index)
63 {
64  cnat_syslog_logging_info_t *log_info __attribute__((unused));
65  if(logging_index == EMPTY) {
66  PLATFORM_DEBUG_PRINT("\nSyslog logging not configured\n");
67  return;
68  }
69 
70  log_info = cnat_syslog_logging_info_pool + logging_index;
71 
72  PLATFORM_DEBUG_PRINT("\nSyslog parameters --\n");
73  PLATFORM_DEBUG_PRINT("IPV4 address: %x, port %d, max log size %d\n",
74  log_info->ipv4_address,
75  log_info->port, log_info->max_length_minus_max_record_size);
76  PLATFORM_DEBUG_PRINT("Host name: %s, priority %d",
77  log_info->header_hostname, log_info->header_priority);
78 
79 }
80 
81 /* Util function to copy a number as ASCII in to a buf in a
82  * faster way (should be faster than sprintf)
83  */
84 
85 const unsigned char ascii_numbers[][3] =
86  { {'0', '0', '0'},
87  {'1', '0', '0'},
88  {'2', '0', '0'},
89  {'3', '0', '0'},
90  {'4', '0', '0'},
91  {'5', '0', '0'},
92  {'6', '0', '0'},
93  {'7', '0', '0'},
94  {'8', '0', '0'},
95  {'9', '0', '0'},
96  {'1', '0', '0'},
97  {'1', '1', '0'},
98  {'1', '2', '0'},
99  {'1', '3', '0'},
100  {'1', '4', '0'},
101  {'1', '5', '0'},
102  {'1', '6', '0'},
103  {'1', '7', '0'},
104  {'1', '8', '0'},
105  {'1', '9', '0'},
106  {'2', '0', '0'},
107  {'2', '1', '0'},
108  {'2', '2', '0'},
109  {'2', '3', '0'},
110  {'2', '4', '0'},
111  {'2', '5', '0'},
112  {'2', '6', '0'},
113  {'2', '7', '0'},
114  {'2', '8', '0'},
115  {'2', '9', '0'},
116  {'3', '0', '0'},
117  {'3', '1', '0'},
118  {'3', '2', '0'},
119  {'3', '3', '0'},
120  {'3', '4', '0'},
121  {'3', '5', '0'},
122  {'3', '6', '0'},
123  {'3', '7', '0'},
124  {'3', '8', '0'},
125  {'3', '9', '0'},
126  {'4', '0', '0'},
127  {'4', '1', '0'},
128  {'4', '2', '0'},
129  {'4', '3', '0'},
130  {'4', '4', '0'},
131  {'4', '5', '0'},
132  {'4', '6', '0'},
133  {'4', '7', '0'},
134  {'4', '8', '0'},
135  {'4', '9', '0'},
136  {'5', '0', '0'},
137  {'5', '1', '0'},
138  {'5', '2', '0'},
139  {'5', '3', '0'},
140  {'5', '4', '0'},
141  {'5', '5', '0'},
142  {'5', '6', '0'},
143  {'5', '7', '0'},
144  {'5', '8', '0'},
145  {'5', '9', '0'},
146  {'6', '0', '0'},
147  {'6', '1', '0'},
148  {'6', '2', '0'},
149  {'6', '3', '0'},
150  {'6', '4', '0'},
151  {'6', '5', '0'},
152  {'6', '6', '0'},
153  {'6', '7', '0'},
154  {'6', '8', '0'},
155  {'6', '9', '0'},
156  {'7', '0', '0'},
157  {'7', '1', '0'},
158  {'7', '2', '0'},
159  {'7', '3', '0'},
160  {'7', '4', '0'},
161  {'7', '5', '0'},
162  {'7', '6', '0'},
163  {'7', '7', '0'},
164  {'7', '8', '0'},
165  {'7', '9', '0'},
166  {'8', '0', '0'},
167  {'8', '1', '0'},
168  {'8', '2', '0'},
169  {'8', '3', '0'},
170  {'8', '4', '0'},
171  {'8', '5', '0'},
172  {'8', '6', '0'},
173  {'8', '7', '0'},
174  {'8', '8', '0'},
175  {'8', '9', '0'},
176  {'9', '0', '0'},
177  {'9', '1', '0'},
178  {'9', '2', '0'},
179  {'9', '3', '0'},
180  {'9', '4', '0'},
181  {'9', '5', '0'},
182  {'9', '6', '0'},
183  {'9', '7', '0'},
184  {'9', '8', '0'},
185  {'9', '9', '0'},
186  {'1', '0', '0'},
187  {'1', '0', '1'},
188  {'1', '0', '2'},
189  {'1', '0', '3'},
190  {'1', '0', '4'},
191  {'1', '0', '5'},
192  {'1', '0', '6'},
193  {'1', '0', '7'},
194  {'1', '0', '8'},
195  {'1', '0', '9'},
196  {'1', '1', '0'},
197  {'1', '1', '1'},
198  {'1', '1', '2'},
199  {'1', '1', '3'},
200  {'1', '1', '4'},
201  {'1', '1', '5'},
202  {'1', '1', '6'},
203  {'1', '1', '7'},
204  {'1', '1', '8'},
205  {'1', '1', '9'},
206  {'1', '2', '0'},
207  {'1', '2', '1'},
208  {'1', '2', '2'},
209  {'1', '2', '3'},
210  {'1', '2', '4'},
211  {'1', '2', '5'},
212  {'1', '2', '6'},
213  {'1', '2', '7'},
214  {'1', '2', '8'},
215  {'1', '2', '9'},
216  {'1', '3', '0'},
217  {'1', '3', '1'},
218  {'1', '3', '2'},
219  {'1', '3', '3'},
220  {'1', '3', '4'},
221  {'1', '3', '5'},
222  {'1', '3', '6'},
223  {'1', '3', '7'},
224  {'1', '3', '8'},
225  {'1', '3', '9'},
226  {'1', '4', '0'},
227  {'1', '4', '1'},
228  {'1', '4', '2'},
229  {'1', '4', '3'},
230  {'1', '4', '4'},
231  {'1', '4', '5'},
232  {'1', '4', '6'},
233  {'1', '4', '7'},
234  {'1', '4', '8'},
235  {'1', '4', '9'},
236  {'1', '5', '0'},
237  {'1', '5', '1'},
238  {'1', '5', '2'},
239  {'1', '5', '3'},
240  {'1', '5', '4'},
241  {'1', '5', '5'},
242  {'1', '5', '6'},
243  {'1', '5', '7'},
244  {'1', '5', '8'},
245  {'1', '5', '9'},
246  {'1', '6', '0'},
247  {'1', '6', '1'},
248  {'1', '6', '2'},
249  {'1', '6', '3'},
250  {'1', '6', '4'},
251  {'1', '6', '5'},
252  {'1', '6', '6'},
253  {'1', '6', '7'},
254  {'1', '6', '8'},
255  {'1', '6', '9'},
256  {'1', '7', '0'},
257  {'1', '7', '1'},
258  {'1', '7', '2'},
259  {'1', '7', '3'},
260  {'1', '7', '4'},
261  {'1', '7', '5'},
262  {'1', '7', '6'},
263  {'1', '7', '7'},
264  {'1', '7', '8'},
265  {'1', '7', '9'},
266  {'1', '8', '0'},
267  {'1', '8', '1'},
268  {'1', '8', '2'},
269  {'1', '8', '3'},
270  {'1', '8', '4'},
271  {'1', '8', '5'},
272  {'1', '8', '6'},
273  {'1', '8', '7'},
274  {'1', '8', '8'},
275  {'1', '8', '9'},
276  {'1', '9', '0'},
277  {'1', '9', '1'},
278  {'1', '9', '2'},
279  {'1', '9', '3'},
280  {'1', '9', '4'},
281  {'1', '9', '5'},
282  {'1', '9', '6'},
283  {'1', '9', '7'},
284  {'1', '9', '8'},
285  {'1', '9', '9'},
286  {'2', '0', '0'},
287  {'2', '0', '1'},
288  {'2', '0', '2'},
289  {'2', '0', '3'},
290  {'2', '0', '4'},
291  {'2', '0', '5'},
292  {'2', '0', '6'},
293  {'2', '0', '7'},
294  {'2', '0', '8'},
295  {'2', '0', '9'},
296  {'2', '1', '0'},
297  {'2', '1', '1'},
298  {'2', '1', '2'},
299  {'2', '1', '3'},
300  {'2', '1', '4'},
301  {'2', '1', '5'},
302  {'2', '1', '6'},
303  {'2', '1', '7'},
304  {'2', '1', '8'},
305  {'2', '1', '9'},
306  {'2', '2', '0'},
307  {'2', '2', '1'},
308  {'2', '2', '2'},
309  {'2', '2', '3'},
310  {'2', '2', '4'},
311  {'2', '2', '5'},
312  {'2', '2', '6'},
313  {'2', '2', '7'},
314  {'2', '2', '8'},
315  {'2', '2', '9'},
316  {'2', '3', '0'},
317  {'2', '3', '1'},
318  {'2', '3', '2'},
319  {'2', '3', '3'},
320  {'2', '3', '4'},
321  {'2', '3', '5'},
322  {'2', '3', '6'},
323  {'2', '3', '7'},
324  {'2', '3', '8'},
325  {'2', '3', '9'},
326  {'2', '4', '0'},
327  {'2', '4', '1'},
328  {'2', '4', '2'},
329  {'2', '4', '3'},
330  {'2', '4', '4'},
331  {'2', '4', '5'},
332  {'2', '4', '6'},
333  {'2', '4', '7'},
334  {'2', '4', '8'},
335  {'2', '4', '9'},
336  {'2', '5', '0'},
337  {'2', '5', '1'},
338  {'2', '5', '2'},
339  {'2', '5', '3'},
340  {'2', '5', '4'},
341  {'2', '5', '5'}
342  };
343 
344 inline static int
346  unsigned char *ptr, unsigned char num)
347 {
348  *ptr++ = ascii_numbers[num][0];
349  if(PREDICT_FALSE(num < 10)) {
350  return 1;
351  }
352  *ptr++ = ascii_numbers[num][1];
353  if(PREDICT_FALSE(num < 100)) {
354  return 2;
355  }
356  *ptr++ = ascii_numbers[num][2];
357  return 3;
358 }
359 
360 /* Copies the dotted decimal format of ipv4
361  * in to the space provided and
362  * returns the number of bytes copied
363  */
364 inline static int __attribute__((unused))
365 copy_ipv4_addr(unsigned char *ptr, u32 ipv4)
366 {
367  unsigned char *temp = ptr;
368  temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 >> 24));
369  *temp++ = '.';
370  temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 16) & 0xFF));
371  *temp++ = '.';
372  temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 8) & 0xFF));
373  *temp++ = '.';
374  temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 & 0xFF));
375 
376  return (temp - ptr);
377 }
378 
379 #ifdef TOBE_PORTED
380 /*
381  * edt: * * cnat_syslog_fill_ip_header
382  *
383  * Tries to fill the fields of the IP header before it
384  * is sent to the L3 infra node.
385  *
386  * Argument: cnat_syslog_logging_info_t *logging_info
387  * structure that contains the packet context
388  */
389 inline
391 {
392  spp_ctx_t *ctx;
393 
394  /*
395  * Fill in the IP header and port number of the Netflow collector
396  * The L3 Infra node will fill in the rest of the fields
397  */
398  ctx = logging_info->current_logging_context;
399  fill_ip_n_udp_hdr(ctx, logging_info->ipv4_address,
400  logging_info->port, logging_info->pkt_length);
401 
402 }
403 #else
404 inline
406 {
407  return;
408 }
409 #endif
410 
411 #ifndef TOBE_PORTED
413 {
414  return;
415 }
416 
418  cnat_vrfmap_t *vrfmap)
419 {
420  return;
421 }
422 
424  cnat_vrfmap_t *vrfmap)
425 {
426  return;
427 }
428 
430  dslite_key_t * key,
431  dslite_table_entry_t *dslite_entry)
432 {
433  return;
434 }
435 
437  cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb
438 #ifndef NO_BULK_LOGGING
439  , int bulk_alloc
440 #endif
441  )
442 {
443  return;
444 }
445 
446 /* Following are in cnat_util.c which are not ported */
447 /* This function is defined in cnat_util.c which need to be ported */
449 {
450  return 1;
451 }
452 
454  cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb
455 #ifndef NO_BULK_LOGGING
456  , int bulk_alloc
457 #endif
458  )
459 {
460  return;
461 }
462 
463 u32
465 {
466  return 0;
467 }
468 #else /* TOBE_PORTED */
469 void
470 cnat_syslog_dump_logging_context (u32 value1,
471  cnat_syslog_logging_info_t *logging_info,
472  u32 value2)
473 {
474  u8 *pkt_ptr;
475  u32 i;
476 
477  if (PREDICT_TRUE(syslog_debug_flag == 0)) {
478  return;
479  }
480  /*
481  * Reduce the logging to few cores, to enable easier debugging
482  */
483  if ((my_instance_number & 0x7) != 0) {
484  return;
485  }
486  printf("\nDumping %s packet at locn %d: time 0x%x",
487  (value2 == 1) ? "CURRENT" : "QUEUED",
488  value1,
490 
491  printf("\ni_vrf 0x%x, ip_address 0x%x, port %d, pkt len %d",
492  0 /* TO DP Add vrf like nfv9_logging_info->i_vrf */,
493  logging_info->ipv4_address,
494  logging_info->port,
495  logging_info->pkt_length);
496  printf("\n");
497 
498  if (value2 == 1) {
499  pkt_ptr = logging_info->current_logging_context->packet_data;
500  } else {
501  pkt_ptr = logging_info->queued_logging_context->packet_data;
502  }
503 
504  /*
505  * Dump along with 8 bytes of SHIM header
506  */
507  for (i = 0; i <
508  (logging_info->pkt_length + CNAT_NFV9_IP_HDR_OFFSET);
509  i = i + 1) {
510  u8 c1, c2, c3;
511 
512  if (i == 0) {
513  printf("\nL2_HEADER + SHIM_HEADER: \n");
514  } else if (i == CNAT_NFV9_IP_HDR_OFFSET) {
515  printf("\nIP_HEADER: \n");
516  } else if (i == CNAT_NFV9_UDP_HDR_OFFSET) {
517  printf("\nUDP_HEADER: \n");
518  } else if (i == CNAT_NFV9_HDR_OFFSET) {
519  printf("\nSyslog content..\n");
520  while(i <
521  (logging_info->pkt_length + CNAT_NFV9_HDR_OFFSET)) {
522  printf("%c", (u8)(*(pkt_ptr + i)));
523  i++;
524  if((u8)(*(pkt_ptr + i)) == '[') /* new record begins */
525  printf("\n");
526  }
527  return;
528  }
529 
530  c3 = *(pkt_ptr + i);
531  c2 = c3 & 0xf;
532  c1 = (c3 >> 4) & 0xf;
533 
534  printf("%c%c ",
535  ((c1 <= 9) ? (c1 + '0') : (c1 - 10 + 'a')),
536  ((c2 <= 9) ? (c2 + '0') : (c2 - 10 + 'a')));
537 
538  }
539 
540  printf("\n");
541 }
542 
543 
544 /*
545  * edt: * * cnat_syslog_send_pkt
546  *
547  * Tries to send a logging pkt. If the packet cannot be sent
548  * because of rewrite_output node cannot process it, queue
549  * it temporarily and try to send it later.
550  *
551  * Argument: cnat_syslog_logging_info_t *logging_info
552  * structure that contains the packet context
553  */
554 inline
555 void cnat_syslog_send_pkt (cnat_syslog_logging_info_t *logging_info)
556 {
557  spp_node_t *output_node;
558 
559  cnat_syslog_fill_ip_header(logging_info);
560 
561  output_node = spp_get_nodes() +
562  cnat_syslog_global_info.cnat_syslog_disp_node_index;
563 
564  cnat_syslog_dump_logging_context (2, logging_info, 1);
565 
566  if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) {
567  /*
568  * Move the logging context to output node
569  */
570  logging_info->current_logging_context->current_length =
571  logging_info->pkt_length;
573  NODE_LOGGING);
574  spp_dispatch_make_node_runnable(output_node);
575  output_node->sf.ctxs[output_node->sf.nused++] =
576  logging_info->current_logging_context;
577 
579  printf("\nSyslog: 2. Sending Current packet\n");
580  } else {
581  /*
582  * Queue the context into the logging_info structure,
583  * We will try to send it later. Currently, we will
584  * restrict to only one context queued.
585  */
586  cnat_syslog_global_counter.downstream_constipation_count++;
588  printf("\nSyslog: 2. Downstream congestion \n");
589 
590  /*
591  * Attach the current logging context which is full to the
592  * queued context list in logging_info structure
593  */
594  logging_info->queued_logging_context =
595  logging_info->current_logging_context;
596  }
597 
598  /*
599  * Whether the context is queued or not, set the current context index
600  * to EMPTY, as the earlier context can no more be used to send
601  * more logging records.
602  */
603  logging_info->current_logging_context = NULL;
604 }
605 
606 
607 /*
608  * edt: * * cnat_syslog_send_queued_pkt
609  *
610  * Tries to send a logging pkt that has been queued earlier
611  * because it could not be sent due to downstream constipation
612  *
613  * Argument: cnat_syslog_logging_info_t *logging_info
614  * structure that contains the packet context
615  */
616 inline
617 void cnat_syslog_send_queued_pkt (cnat_syslog_logging_info_t *logging_info)
618 {
619  spp_node_t *output_node;
620 
621  output_node = spp_get_nodes() +
622  cnat_syslog_global_info.cnat_syslog_disp_node_index;
623 
624  cnat_syslog_dump_logging_context(1, logging_info, 2);
625 
626  if(PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) {
627  /*
628  * Move the logging context to output node
629  */
630  /** This looks like a bug to me .. need to confirm *****
631  logging_info->queued_logging_context->current_length =
632  nfv9_logging_info->pkt_length; ***/
634  NODE_LOGGING)
635  spp_dispatch_make_node_runnable(output_node);
636  output_node->sf.ctxs[output_node->sf.nused++] =
637  logging_info->queued_logging_context;
638 
639  SYSLOG_DEBUG_PRINTF1("\nSYSLOG: 1. Sending Queued packet\n")
640 
641  /*
642  * Context has been queued, it will be freed after the pkt
643  * is sent. Clear this from the logging_context_info structure
644  */
645  logging_info->queued_logging_context = NULL;
646 
647  } else {
648  cnat_syslog_global_counter.downstream_constipation_count++;
649  }
650 }
651 
652 /*
653  * edt: * * handle_pending_syslog_pkts
654  *
655  * Timer handler for sending any pending syslog record
656  *
657  */
658 inline
659 void handle_pending_syslog_pkts()
660 {
661  spp_node_t *output_node;
662  cnat_syslog_logging_info_t *my_logging_info = 0;
663  u32 current_timestamp = cnat_get_sys_up_time_in_ms();
664  i16 sf_nused;
665 
666  output_node = spp_get_nodes() +
667  cnat_syslog_global_info.cnat_syslog_disp_node_index;
668 
669  sf_nused = output_node->sf.nused;
670 
671  pool_foreach (my_logging_info, cnat_syslog_logging_info_pool, ({
672  /*
673  * Check if no more logging contexts can be queued
674  */
675  if (PREDICT_FALSE(sf_nused >= SPP_MAXDISPATCH)) {
676  break;
677  }
678  if (my_logging_info->queued_logging_context)
679  cnat_syslog_send_queued_pkt (my_logging_info);
680 
681  if(my_logging_info->current_logging_context &&
682  ((current_timestamp -
683  my_logging_info->current_logging_context_timestamp)
684  > 1000)) {
685  /*
686  * If there is a current logging context and timestamp
687  * indicates it is pending for long, send it out
688  * Also if there is a queued context send it out as well
689  */
690  SYSLOG_DEBUG_PRINTF4("\nLOG_TIMER: queued %p, curr %p, sf_nused %d",
691  my_logging_info->queued_logging_context,
692  my_logging_info->current_logging_context,
693  sf_nused);
694  cnat_syslog_send_pkt(my_logging_info);
695  }
696  }));
697 }
698 
699 const unsigned char hex_numbers_single_digit[] =
700  { '0', '1', '2', '3', '4', '5', '6', '7', '8',
701  '9', 'a', 'b', 'c', 'd', 'e', 'f' };
702 
703 inline static int u16_to_ascii_decimal_aligned(
704  unsigned char *ptr, u16 num, u16 min_digits)
705 {
706  /* The logic below is replicated in
707  * function u16_to_ascii_decimal_unaligned
708  * except the use of min_digits
709  * Replication is done to optimize run time
710  * if you fix a bug here, check u16_to_ascii_decimal_unaligned
711  * as well (and vice versa)
712  */
713  unsigned char *temp = ptr;
714  int no_leading_zeros = 0;
715 
716  if(num > 9999 || min_digits == 5) {
717  *temp++ = hex_numbers_single_digit[num/10000];
718  num = num%10000;
719  no_leading_zeros = 1;
720  }
721 
722  if(no_leading_zeros || num > 999 || min_digits == 4) {
723  *temp++ = hex_numbers_single_digit[num/1000];
724  num = num%1000;
725  no_leading_zeros = 1;
726  }
727 
728  if(no_leading_zeros || num > 99 || min_digits == 3) {
729  *temp++ = hex_numbers_single_digit[num/100];
730  num = num%100;
731  no_leading_zeros = 1;
732  }
733 
734  if(no_leading_zeros || num > 9 || min_digits == 2) {
735  *temp++ = hex_numbers_single_digit[num/10];
736  num = num%10;
737  }
738 
739  *temp++ = hex_numbers_single_digit[num];
740 
741  return temp-ptr;
742 }
743 
744 inline static int u16_to_ascii_decimal_unaligned(
745  unsigned char *ptr, u16 num)
746 {
747  /*
748  * return u16_to_ascii_decimal_aligned(ptr, num, 0);
749  * should do the job.. however, to opimize the run time
750  * the code of u16_to_ascii_decimal_aligned is being
751  * repeated here without the use of min_digits
752  * if you fix a bug here, please check
753  * u16_to_ascii_decimal_aligned as well (and vice versa)
754  */
755  unsigned char *temp = ptr;
756  int no_leading_zeros = 0;
757 
758  if(num > 9999) {
759  *temp++ = hex_numbers_single_digit[num/10000];
760  num = num%10000;
761  no_leading_zeros = 1;
762  }
763 
764  if(no_leading_zeros || num > 999) {
765  *temp++ = hex_numbers_single_digit[num/1000];
766  num = num%1000;
767  no_leading_zeros = 1;
768  }
769 
770  if(no_leading_zeros || num > 99) {
771  *temp++ = hex_numbers_single_digit[num/100];
772  num = num%100;
773  no_leading_zeros = 1;
774  }
775 
776  if(no_leading_zeros || num > 9) {
777  *temp++ = hex_numbers_single_digit[num/10];
778  num = num%10;
779  }
780 
781  *temp++ = hex_numbers_single_digit[num];
782 
783  return temp-ptr;
784 }
785 
786 static int syslog_get_timestamp(unsigned char *ts)
787 {
788  static const char *months[] = {"Jan ", "Feb ", "Mar ", "Apr ", "May ",
789  "Jun ", "Jul ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec " };
790 
791  unsigned char *temp = ts;
792  /* Inserts time stamp in the syslog format and returns lenght
793  * assumes that ts has sufficient space
794  */
795  /* China Telecom has demanded that the time stamp has to be
796  * in the format '2011 Jun 7 12:34:08'
797  */
798  time_t time = (time_t)cnat_get_unix_time_in_seconds();
799  struct tm tm1;
800 
801  gmtime_r(&time, &tm1);
802  /* Now put the pieces together */
803  /* Year */
804  ts += u16_to_ascii_decimal_unaligned(ts, (tm1.tm_year + 1900));
805  *ts++ = SYSLOG_DELIMITER;
806  /* Month */
807  clib_memcpy(ts, months[tm1.tm_mon], 4);
808  ts += 4; /* DELIMITER taken care */
809  /* day */
810  ts += u16_to_ascii_decimal_unaligned(ts, tm1.tm_mday);
811  *ts++ = SYSLOG_DELIMITER;
812  /* hours */
813  ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_hour, 2);
814  *ts++ = ':';
815  /* minutes */
816  ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_min, 2);
817  *ts++ = ':';
818  /* seconds */
819  ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_sec, 2);
820  return ts - temp;
821 }
822 
823 /* Ensure that the order of the below array matches with
824  * syslog_service_type enum
825  */
826 static char *syslog_service_string[] = { "NAT44", "DSLITE" };
827 
828 /* Ensure that the order of below array matches with
829  * syslog_event_type_t enum
830  */
831 typedef struct {
832  char *event_name;
833  int name_length;
834 } syslog_event_description_type;
835 
836 const static syslog_event_description_type sys_log_event[] = {
837  { "UserbasedA", 10 }, /* yes, 10 is strlen of "UserbasedA" */
838  { "UserbasedW", 10 },
839  { "SessionbasedA", 13 },
840  { "SessionbasedW", 13 },
841  { "SessionbasedAD", 14 },
842  { "SessionbasedWD", 14 },
843  { "Portblockrunout", 15 },
844  { "TCPseqmismatch", 14},
845  { "Invalid", 7 }
846 };
847 
848 inline static int syslog_fill_header(const cnat_syslog_logging_info_t *log_info,
849  syslog_service_type_t s_type)
850 {
851  /* Forms the syslog header and returns the lenght
852  * Assumes that header has sufficient space
853  */
854 
855  /* Sample header (as agreed for China Telecom requirements --
856  * <134> 1 2011 May 31 10:30:45 192.168.2.3 - - NAT44 -
857  */
858 
859  unsigned char *temp, *header;
860  int count;
861  temp = header = (unsigned char *)
862  &(log_info->current_logging_context->packet_data[CNAT_NFV9_HDR_OFFSET]);
863  *temp++ = '<';
864  temp += byte_to_ascii_decimal_unaligned(temp,
865  log_info->header_priority);
866  *temp++ = '>';
867  *temp++ = SYSLOG_DELIMITER;
868  *temp++ = '1'; /* Syslog version -- always set to 1 */
869  *temp++ = SYSLOG_DELIMITER;
870  temp += syslog_get_timestamp(temp);
871  *temp++ = SYSLOG_DELIMITER;
872  count = strlen(log_info->header_hostname);
873  clib_memcpy(temp, log_info->header_hostname, count);
874  temp += count;
875  *temp++ = SYSLOG_DELIMITER;
876  *temp++ = SYSLOG_FIELD_ABSENT; /* App name - nil value */
877  *temp++ = SYSLOG_DELIMITER;
878  *temp++ = SYSLOG_FIELD_ABSENT; /* Proc ID - nil value for now */
879  *temp++ = SYSLOG_DELIMITER;
880  /* Now the msg id */
881  count = strlen(syslog_service_string[s_type]);
882  clib_memcpy(temp, syslog_service_string[s_type], count);
883  temp += count;
884  *temp++ = SYSLOG_DELIMITER;
885  *temp++ = SYSLOG_FIELD_ABSENT; /* No structured elements */
886  *temp++ = SYSLOG_DELIMITER;
887 #ifdef SHOW_SYSLOG_TIMESTAMP
888  printf("\nSysLog TS: %s : Length %d", header, temp - header);
889 #endif /* SHOW_SYSLOG_TIMESTAMP */
890  return temp-header;
891 }
892 
893 extern void cnat_logging_init();
894 
895 /* one time call at the beginning */
897 {
898  if(PREDICT_TRUE(cnat_syslog_global_info.cnat_syslog_init_done))
899  return; /* Already done */
900 
901  cnat_logging_init();
902  cnat_syslog_global_info.cnat_syslog_disp_node_index =
903  spp_lookup_node_index(PLATFORM_SYSLOG_DISP_NODE_IDX);
904  ASSERT(cnat_syslog_global_info.cnat_syslog_disp_node_index != (u16)~0);
905 
906  cnat_syslog_global_info.cnat_syslog_init_done = 1;
907 }
908 
909 /*
910  * edt: * * cnat_syslog_create_logging_context
911  *
912  * Tries to create a logging context with packet buffer
913  * to send a new logging packet
914  *
915  * Argument: cnat_syslog_logging_info_t *logging_info
916  * structure that contains the logging info and will store
917  * the packet context as well.
918  */
919 inline
920 void cnat_syslog_create_logging_context (
921  cnat_syslog_logging_info_t *logging_info,
922  syslog_service_type_t s_type)
923 {
924  spp_ctx_t *ctx;
925 
926  /*
927  * If queued_logging_context_index is non-EMPTY, we already have a logging
928  * packet queued to be sent. First try sending this before allocating
929  * a new context. We can have only one active packet context per
930  * logging_info structure
931  */
932 
933  if (PREDICT_FALSE(logging_info->queued_logging_context != NULL)) {
934  cnat_syslog_send_queued_pkt(logging_info);
935  /*
936  * If we cannot still send the queued pkt, just return
937  * Downstream Constipation count would have increased anyway
938  */
939  if (logging_info->queued_logging_context != NULL) {
940  cnat_syslog_global_counter.logging_context_creation_deferred_count++;
941  return;
942  }
943  }
944 
945  /*
946  * If no context can be allocated, return silently
947  * calling routine will handle updating the error counters
948  */
949  if (spp_ctx_alloc(&ctx, 1) < 1) {
950  cnat_syslog_global_counter.logging_context_creation_fail_count++;
951  SYSLOG_DEBUG_PRINTF1("\nCould not allocate ctx for syslog");
952  return;
953  }
954 
955  // Allocate packet buffer (used for AVSM currently)
957 
958  logging_info->current_logging_context = ctx;
959 
961 
962  ctx->flags = SPP_CTX_END_OF_PACKET;
963  ctx->next_ctx_this_packet = (spp_ctx_t*) SPP_CTX_NO_NEXT_CTX;
964  ctx->current_header = &ctx->packet_data[CNAT_NFV9_HDR_OFFSET];
965 
966  logging_info->pkt_length = syslog_fill_header(logging_info, s_type);
967  logging_info->pkt_length += (CNAT_NFV9_HDR_OFFSET -
969  logging_info->current_logging_context_timestamp =
971 
972 }
973 
974 inline static int u16_to_ascii_hex_unaligned(
975  unsigned char *ptr, u16 num)
976 {
977  unsigned char nibble, *temp;
978  int no_leading_zeros = 0;
979  temp = ptr;
980  nibble = (num >> 12);
981  if(nibble) {
982  *temp++ = hex_numbers_single_digit[nibble];
983  no_leading_zeros = 1;
984  }
985 
986  nibble = (num >> 8) & 0xF;
987  if(nibble || no_leading_zeros) {
988  *temp++ = hex_numbers_single_digit[nibble];
989  no_leading_zeros = 1;
990  }
991 
992  nibble = (num >> 4) & 0xF;
993  if(nibble || no_leading_zeros) {
994  *temp++ = hex_numbers_single_digit[nibble];
995  }
996 
997  *temp++ = hex_numbers_single_digit[num & 0xF];
998 
999  return temp-ptr;
1000 }
1001 
1002 inline static int ipv6_int_2_str(u32 ipv6[], unsigned char *ipv6_str)
1003 {
1004 /* DC stands for Double Colon.
1005  * Refer http://tools.ietf.org/html/rfc5952 for
1006  * more details on text representations of
1007  * IPV6 address
1008  */
1009 #define DC_NOT_USED_YET 0
1010 #define DC_IN_USE 1 /* Zeros are skipped */
1011 #define DC_ALREADY_USED 2 /* Cannot skip zeros anymore */
1012  int i;
1013  u16 *ipv6_temp = (u16 *)ipv6;
1014  unsigned char *temp = ipv6_str;
1015  int double_colon = DC_NOT_USED_YET;
1016  for(i = 0; i < 7; i++) {
1017  if(ipv6_temp[i]) {
1018  ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[i]);
1019  *ipv6_str++ = ':';
1020  if(double_colon == DC_IN_USE) { /* Cannot use DC anymore */
1021  double_colon = DC_ALREADY_USED;
1022  }
1023  } else {
1024  if(double_colon == DC_IN_USE) {
1025  /* Skip this zero as well */
1026  continue;
1027  } else if((ipv6_temp[i+1])
1028  /* DC makes sense if there is more than one contiguous zero */
1029  || (double_colon != DC_NOT_USED_YET)) {
1030  ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str,
1031  ipv6_temp[i]);
1032  *ipv6_str++ = ':';
1033  } else { /* Start using DC */
1034  *ipv6_str++ = ':'; /* The 2nd colon */
1035  double_colon = DC_IN_USE;
1036  }
1037  }
1038  }
1039  if(ipv6_temp[7]) {
1040  ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[7]);
1041  } else if(double_colon != DC_IN_USE) {
1042  *ipv6_str++ = '0';
1043  }
1044  *ipv6_str = 0;
1045 
1046  return ipv6_str - temp;
1047 }
1048 
1049 /* insert syslog record for nat44 */
1050 
1051 void cnat_syslog_insert_nat44_record(
1052  cnat_syslog_logging_info_t *log_info,
1053  cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap,
1054  cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type)
1055 {
1056  /* This record should like this -
1057  * [EventName <L4> <Original Source IP> <Inside VRF Name>
1058  * <Original Source IPv6> < Translated Source IP> <Original Port>
1059  * <Translated First Source Port> <Translated Last Source Port>
1060  * <Destination ip address> <destination port>]
1061  */
1062  u32 original_source = db->in2out_key.k.ipv4;
1063  u32 translated_ip = db->out2in_key.k.ipv4;
1065  unsigned char *temp, *record;
1066  u32 network_order_ipv6[4];
1067 
1068  SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__);
1069  temp = record = &(log_info->current_logging_context->packet_data[
1070  CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
1071 
1072  if (PREDICT_FALSE(!udb)) {
1073  SYSLOG_DEBUG_PRINTF1("\nnull udb!");
1074  return;
1075  }
1076 
1077  /* Now we point to the location where record needs to be inserted */
1078  *record++ = '['; /* Open the record */
1079 
1080  /* Copy the record type */
1081  clib_memcpy(record, sys_log_event[e_type].event_name,
1082  sys_log_event[e_type].name_length);
1083  record += sys_log_event[e_type].name_length;
1084  *record++ = SYSLOG_DELIMITER;
1085 
1086  /* Copy the Protocol type */
1087  if(PREDICT_FALSE(
1088  e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
1089  e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
1090  u16 my_proto_mask;
1091  my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK;
1092  if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
1093  *record++ = '6';
1094  } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
1095  *record++ = '1';
1096  *record++ = '7';
1097  } else if(PREDICT_TRUE(my_proto_mask == CNAT_ICMP)) {
1098  *record++ = '1';
1099  } else { /* Default, assume GRE (for PPTP) */
1100  *record++ = '4';
1101  *record++ = '7';
1102  }
1103  } else {
1104  *record++ = SYSLOG_FIELD_ABSENT;
1105  }
1106  *record++ = SYSLOG_DELIMITER;
1107 
1108  /* Copy the Original Source IP */
1109  record += copy_ipv4_addr(record, original_source);
1110  *record++ = SYSLOG_DELIMITER;
1111 
1112  /* copy configured VRF NAME */
1113  clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
1114  record += log_info->vrf_name_len;
1115  *record++ = SYSLOG_DELIMITER;
1116 
1117  /* No IPV6 source address for nat44 */
1118  *record++ = SYSLOG_FIELD_ABSENT;
1119  *record++ = SYSLOG_DELIMITER;
1120 
1121  /* Copy the translated IP address */
1122  record += copy_ipv4_addr(record, translated_ip);
1123  *record++ = SYSLOG_DELIMITER;
1124 
1125  /* Copy the Original port */
1126  if(e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
1127  e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) {
1128  record += u16_to_ascii_decimal_unaligned(
1129  record, db->in2out_key.k.port);
1130  } else {
1131  *record++ = SYSLOG_FIELD_ABSENT;
1132  }
1133  *record++ = SYSLOG_DELIMITER;
1134 
1135  /* Copy the start outside port */
1136  record += u16_to_ascii_decimal_unaligned(record, bulk_alloc);
1137  *record++ = SYSLOG_DELIMITER;
1138 
1139  /* Copy the last outside port */
1140  if(e_type == userbased_assign || e_type == userbased_withdraw) {
1141  record += u16_to_ascii_decimal_unaligned(record,
1142  (bulk_alloc + BULKSIZE_FROM_VRFMAP(vrfmap) - 1));
1143  } else {
1144  *record++ = SYSLOG_FIELD_ABSENT;
1145  }
1146  *record++ = SYSLOG_DELIMITER;
1147 
1148  /* Copy destination ip and port in case for DBL*/
1149  if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
1150  if(PREDICT_TRUE(sdb == NULL)) {
1151  record += copy_ipv4_addr(record,db->dst_ipv4);
1152  *record++ = SYSLOG_DELIMITER;
1153  record += u16_to_ascii_decimal_unaligned(record, db->dst_port);
1154  } else {
1155  record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4);
1156  *record++ = SYSLOG_DELIMITER;
1157  record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port);
1158  }
1159  } else {
1160  *record++ = '-';
1161  *record++ = SYSLOG_DELIMITER;
1162  *record++ = '-';
1163  }
1164  *record++ = SYSLOG_DELIMITER;
1165 
1166  *record++ = ']'; /* End of the reocrd */
1167 
1168  log_info->pkt_length += record - temp;
1169 }
1170 
1171 void cnat_syslog_insert_record(
1172  cnat_syslog_logging_info_t *log_info,
1173  cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry,
1174  cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type)
1175 {
1176  /* This record should like this -
1177  * [EventName <L4> <Original Source IP> <Inside VRF Name>
1178  * <Original Source IPv6> < Translated Source IP> <Original Port>
1179  * <Translated First Source Port> <Translated Last Source Port>
1180  * <Destination ip address> <destination port>]
1181  */
1182  u32 original_source = db->in2out_key.k.ipv4;
1183  u32 translated_ip = db->out2in_key.k.ipv4;
1185  unsigned char *temp, *record;
1186  u32 network_order_ipv6[4];
1187 
1188  temp = record = &(log_info->current_logging_context->packet_data[
1189  CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
1190 
1191  if (PREDICT_FALSE(!udb)) {
1192  SYSLOG_DEBUG_PRINTF1("\nnull udb!");
1193  return;
1194  }
1195 
1196  /* Now we point to the location where record needs to be inserted */
1197  *record++ = '['; /* Open the record */
1198 
1199  /* Copy the record type */
1200  clib_memcpy(record, sys_log_event[e_type].event_name,
1201  sys_log_event[e_type].name_length);
1202  record += sys_log_event[e_type].name_length;
1203  *record++ = SYSLOG_DELIMITER;
1204 
1205  /* Copy the Protocol type */
1206  if(PREDICT_FALSE(
1207  e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
1208  e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
1209  u16 my_proto_mask;
1210  my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK;
1211  if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
1212  *record++ = '6';
1213  } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
1214  *record++ = '1';
1215  *record++ = '7';
1216  } else {
1217  *record++ = '1';
1218  }
1219  } else {
1220  *record++ = SYSLOG_FIELD_ABSENT;
1221  }
1222 
1223  *record++ = SYSLOG_DELIMITER;
1224 
1225  /* Copy the Original Source IP */
1226 #ifdef DSLITE_USER_IPV4
1227  record += copy_ipv4_addr(record, original_source);
1228 #else
1229  /*
1230  * Do not include inside ipv4 address for B4 element level port limiting
1231  */
1232  *record++ = SYSLOG_FIELD_ABSENT;
1233 #endif
1234  *record++ = SYSLOG_DELIMITER;
1235 
1236  /* copy configured VRF NAME */
1237  clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
1238  record += log_info->vrf_name_len;
1239  *record++ = SYSLOG_DELIMITER;
1240 
1241  /* Copy the IPV6 source address */
1242  /* CSCtt16960 Fix. */
1243  network_order_ipv6[0] = htonl(udb->ipv6[0]);
1244  network_order_ipv6[1] = htonl(udb->ipv6[1]);
1245  network_order_ipv6[2] = htonl(udb->ipv6[2]);
1246  network_order_ipv6[3] = htonl(udb->ipv6[3]);
1247 
1248  inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN);
1249  record += strlen(record);
1250  *record++ = SYSLOG_DELIMITER;
1251 
1252  /* Copy the translated IP address */
1253  record += copy_ipv4_addr(record, translated_ip);
1254  *record++ = SYSLOG_DELIMITER;
1255 
1256  /* Copy the Original port */
1257  if(e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
1258  e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) {
1259  record += u16_to_ascii_decimal_unaligned(
1260  record, db->in2out_key.k.port);
1261  } else {
1262  *record++ = SYSLOG_FIELD_ABSENT;
1263  }
1264  *record++ = SYSLOG_DELIMITER;
1265 
1266  /* Copy the start outside port */
1267  record += u16_to_ascii_decimal_unaligned(record, bulk_alloc);
1268  *record++ = SYSLOG_DELIMITER;
1269 
1270  /* Copy the last outside port */
1271  if(e_type == userbased_assign || e_type == userbased_withdraw) {
1272  record += u16_to_ascii_decimal_unaligned(record,
1273  (bulk_alloc + BULKSIZE_FROM_VRFMAP(dslite_entry) - 1));
1274  } else {
1275  *record++ = SYSLOG_FIELD_ABSENT;
1276  }
1277  *record++ = SYSLOG_DELIMITER;
1278 
1279  if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
1280  if(sdb == NULL) {
1281  record += copy_ipv4_addr(record, db->dst_ipv4);
1282  *record++ = SYSLOG_DELIMITER;
1283  record += u16_to_ascii_decimal_unaligned(record, db->dst_port);
1284  } else {
1285  record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4);
1286  *record++ = SYSLOG_DELIMITER;
1287  record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port);
1288  }
1289  } else {
1290  *record++ = '-';
1291  *record++ = SYSLOG_DELIMITER;
1292  *record++ = '-';
1293  }
1294  *record++ = SYSLOG_DELIMITER;
1295 
1296  *record++ = ']'; /* End of the reocrd */
1297 
1298  log_info->pkt_length += record - temp;
1299 }
1300 
1301 #define SYSLOG_PRECHECK(entry, s_type) \
1302  if(PREDICT_FALSE((entry)->syslog_logging_index == EMPTY)) { \
1303  SYSLOG_DEBUG_PRINTF1("\n1. Log Mapping failed") \
1304  return; \
1305  } \
1306  logging_info = \
1307  cnat_syslog_logging_info_pool + (entry)->syslog_logging_index; \
1308  if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \
1309  cnat_syslog_create_logging_context(logging_info, s_type); \
1310  if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \
1311  SYSLOG_DEBUG_PRINTF1("\n2. Log Mapping failed") \
1312  return; \
1313  } \
1314  }
1315 
1317  cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb
1318 #ifndef NO_BULK_LOGGING
1319  , int bulk_alloc
1320 #endif
1321  )
1322 {
1323  cnat_syslog_logging_info_t *logging_info = 0;
1324  syslog_event_type_t e_type;
1325  int start_port;
1326 
1327  SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__);
1328  SYSLOG_PRECHECK(vrfmap, NAT44)
1329 
1330 #ifndef NO_BULK_LOGGING
1331  if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
1332  e_type = userbased_assign;
1333  start_port = bulk_alloc;
1334  } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
1335  return; /* No logging required.. bulk port usage */
1336  }
1337  else { /* Individual logging .. fall back to old method */
1338 #endif
1339  if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) {
1340  e_type = sessionbased_assignD;
1341  } else {
1342  e_type = sessionbased_assign;
1343  }
1344  start_port = db->out2in_key.k.port;
1345 #ifndef NO_BULK_LOGGING
1346  }
1347 #endif
1348 
1349  cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb,
1350  start_port, e_type);
1351 
1352  /*
1353  * If we have exceeded the packet length, let us send the
1354  * packet now. There is buffer of additional bytes beyond
1355  * max_pkt_length to ensure that the last add/delete record
1356  * can be stored safely.
1357  */
1358 
1359  if (PREDICT_FALSE(logging_info->pkt_length >
1360  logging_info->max_length_minus_max_record_size)) {
1361  cnat_syslog_send_pkt(logging_info);
1362  }
1363 }
1364 
1366  dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb
1367 #ifndef NO_BULK_LOGGING
1368  , int bulk_alloc
1369 #endif
1370  )
1371 {
1372  cnat_syslog_logging_info_t *logging_info = 0;
1373  syslog_event_type_t e_type;
1374  int start_port;
1375 
1376  SYSLOG_PRECHECK(dslite_entry, DSLite)
1377 
1378 #ifndef NO_BULK_LOGGING
1379  if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
1380  e_type = userbased_assign;
1381  start_port = bulk_alloc;
1382  } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
1383  return; /* No logging required.. bulk port usage */
1384  }
1385  else { /* Individual logging .. fall back to old method */
1386 #endif
1388  e_type = sessionbased_assignD;
1389  } else {
1390  e_type = sessionbased_assign;
1391  }
1392  start_port = db->out2in_key.k.port;
1393 #ifndef NO_BULK_LOGGING
1394  }
1395 #endif
1396 
1397  cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb,
1398  start_port, e_type);
1399 
1400  /*
1401  * If we have exceeded the packet length, let us send the
1402  * packet now. There is buffer of additional bytes beyond
1403  * max_pkt_length to ensure that the last add/delete record
1404  * can be stored safely.
1405  */
1406 
1407  if (PREDICT_FALSE(logging_info->pkt_length >
1408  logging_info->max_length_minus_max_record_size)) {
1409  cnat_syslog_send_pkt(logging_info);
1410  }
1411 }
1412 
1414  cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb
1415 #ifndef NO_BULK_LOGGING
1416  , int bulk_alloc
1417 #endif
1418  )
1419 {
1420  cnat_syslog_logging_info_t *logging_info = 0;
1421  syslog_event_type_t e_type;
1422  int start_port;
1423 
1424  SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__);
1425  SYSLOG_PRECHECK(vrfmap, NAT44)
1426 
1427 #ifndef NO_BULK_LOGGING
1428  if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
1429  e_type = userbased_withdraw;
1430  start_port = bulk_alloc;
1431  } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
1432  return; /* No logging required.. bulk port usage */
1433  }
1434  else { /* Individual logging .. fall back to old method */
1435 #endif
1436  if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) {
1437  e_type = sessionbased_withdrawD;
1438  } else {
1439  e_type = sessionbased_withdraw;
1440  }
1441  start_port = db->out2in_key.k.port;
1442 #ifndef NO_BULK_LOGGING
1443  }
1444 #endif
1445  cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb,
1446  start_port, e_type);
1447  /*
1448  * If we have exceeded the packet length, let us send the
1449  * packet now. There is buffer of additional bytes beyond
1450  * max_pkt_length to ensure that the last add/delete record
1451  * can be stored safely.
1452  */
1453  if (PREDICT_FALSE(logging_info->pkt_length >
1454  logging_info->max_length_minus_max_record_size)) {
1455  cnat_syslog_send_pkt(logging_info);
1456  }
1457 }
1458 
1459 void cnat_syslog_ds_lite_mapping_delete(cnat_main_db_entry_t *db,
1460  dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb
1461 #ifndef NO_BULK_LOGGING
1462  , int bulk_alloc
1463 #endif
1464  )
1465 {
1466  cnat_syslog_logging_info_t *logging_info = 0;
1467  syslog_event_type_t e_type;
1468  int start_port;
1469 
1470  SYSLOG_PRECHECK(dslite_entry, DSLite)
1471 
1472 #ifndef NO_BULK_LOGGING
1473  if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
1474  e_type = userbased_withdraw;
1475  start_port = bulk_alloc;
1476  } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
1477  return; /* No logging required.. bulk port usage */
1478  }
1479  else { /* Individual logging .. fall back to old method */
1480 #endif
1482  e_type = sessionbased_withdrawD;
1483  } else {
1484  e_type = sessionbased_withdraw;
1485  }
1486  start_port = db->out2in_key.k.port;
1487 #ifndef NO_BULK_LOGGING
1488  }
1489 #endif
1490  cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb,
1491  start_port, e_type);
1492 
1493  /*
1494  * If we have exceeded the packet length, let us send the
1495  * packet now. There is buffer of additional bytes beyond
1496  * max_pkt_length to ensure that the last add/delete record
1497  * can be stored safely.
1498  */
1499 
1500  if (PREDICT_FALSE(logging_info->pkt_length >
1501  logging_info->max_length_minus_max_record_size)) {
1502  cnat_syslog_send_pkt(logging_info);
1503  }
1504 }
1505 
1506 void cnat_syslog_dslite_insert_port_exceeded(
1507  cnat_syslog_logging_info_t *log_info,
1508  dslite_key_t * key)
1509 {
1510  /* This record should like this -
1511  * [Portblockrunout <L4> <Original Source IP> <Inside VRF Name>
1512  * <Original Source IPv6> - <Original Port> - - - -]
1513  */
1514  u32 network_order_ipv6[4];
1515  unsigned char *temp, *record;
1516 
1517  temp = record = &(log_info->current_logging_context->packet_data[
1518  CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
1519 
1520  /* Now we point to the location where record needs to be inserted */
1521  *record++ = '['; /* Open the record */
1522 
1523  /* Copy the record type */
1524  clib_memcpy(record, sys_log_event[port_block_runout].event_name,
1525  sys_log_event[port_block_runout].name_length);
1526  record += sys_log_event[port_block_runout].name_length;
1527  *record++ = SYSLOG_DELIMITER;
1528 
1529  u16 my_proto_mask;
1530  my_proto_mask = key->ipv4_key.k.vrf & CNAT_PRO_MASK;
1531  if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
1532  *record++ = '6';
1533  } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
1534  *record++ = '1';
1535  *record++ = '7';
1536  } else {
1537  *record++ = '1';
1538  }
1539  *record++ = SYSLOG_DELIMITER;
1540 
1541  /* Copy the Original Source IP */
1542  record += copy_ipv4_addr(record, key->ipv4_key.k.ipv4);
1543  *record++ = SYSLOG_DELIMITER;
1544 
1545  /* copy configured VRF NAME */
1546  clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
1547  record += log_info->vrf_name_len;
1548  *record++ = SYSLOG_DELIMITER;
1549 
1550  /* Copy the IPV6 source address */
1551  network_order_ipv6[0] = htonl(key->ipv6[0]);
1552  network_order_ipv6[1] = htonl(key->ipv6[1]);
1553  network_order_ipv6[2] = htonl(key->ipv6[2]);
1554  network_order_ipv6[3] = htonl(key->ipv6[3]);
1555 
1556  inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN);
1557  record += strlen(record);
1558  *record++ = SYSLOG_DELIMITER;
1559 
1560  *record++ = SYSLOG_FIELD_ABSENT; /* No translated source ip */
1561  *record++ = SYSLOG_DELIMITER;
1562 
1563  record += u16_to_ascii_decimal_unaligned(
1564  record, key->ipv4_key.k.port);
1565  *record++ = SYSLOG_DELIMITER;
1566 
1567  *record++ = SYSLOG_FIELD_ABSENT; /* No translated start port */
1568  *record++ = SYSLOG_DELIMITER;
1569 
1570  *record++ = SYSLOG_FIELD_ABSENT; /* No translated end port */
1571  *record++ = SYSLOG_DELIMITER;
1572 
1573  /*No Destination Info*/
1574  *record++ = '-';
1575  *record++ = SYSLOG_DELIMITER;
1576  *record++ = '-';
1577  *record++ = SYSLOG_DELIMITER;
1578 
1579  *record++ = ']'; /* End of the reocrd */
1580 
1581  log_info->pkt_length += record - temp;
1582 }
1583 
1585  dslite_key_t * key,
1586  dslite_table_entry_t *dslite_entry)
1587 {
1588  cnat_syslog_logging_info_t *logging_info = 0;
1589 
1590  SYSLOG_PRECHECK(dslite_entry, DSLite)
1591 
1592  cnat_syslog_dslite_insert_port_exceeded(logging_info, key);
1593 
1594  /*
1595  * If we have exceeded the packet length, let us send the
1596  * packet now. There is buffer of additional bytes beyond
1597  * max_pkt_length to ensure that the last add/delete record
1598  * can be stored safely.
1599  */
1600 
1601  if (PREDICT_FALSE(logging_info->pkt_length >
1602  logging_info->max_length_minus_max_record_size)) {
1603  cnat_syslog_send_pkt(logging_info);
1604  }
1605 }
1606 
1607 void cnat_syslog_nat44_insert_port_exceeded(
1608  cnat_syslog_logging_info_t *log_info,
1609  cnat_key_t * key)
1610 {
1611  /* This record should like this -
1612  * [Portblockrunout <L4> <Original Source IP> <Inside VRF Name>
1613  * - - <Original Port> - - - -]
1614  */
1615  unsigned char *temp, *record;
1616 
1617  temp = record = &(log_info->current_logging_context->packet_data[
1618  CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
1619 
1620  /* Now we point to the location where record needs to be inserted */
1621  *record++ = '['; /* Open the record */
1622 
1623  /* Copy the record type */
1624  clib_memcpy(record, sys_log_event[port_block_runout].event_name,
1625  sys_log_event[port_block_runout].name_length);
1626  record += sys_log_event[port_block_runout].name_length;
1627  *record++ = SYSLOG_DELIMITER;
1628 
1629  u16 my_proto_mask;
1630  my_proto_mask = key->k.vrf & CNAT_PRO_MASK;
1631  if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
1632  *record++ = '6';
1633  } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
1634  *record++ = '1';
1635  *record++ = '7';
1636  } else {
1637  *record++ = '1';
1638  }
1639  *record++ = SYSLOG_DELIMITER;
1640 
1641  /* Copy the Original Source IP */
1642  record += copy_ipv4_addr(record, key->k.ipv4);
1643  *record++ = SYSLOG_DELIMITER;
1644 
1645  /* copy configured VRF NAME */
1646  clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
1647  record += log_info->vrf_name_len;
1648  *record++ = SYSLOG_DELIMITER;
1649 
1650  /* No IPV6 source address for nat44 */
1651  *record++ = '-';
1652  *record++ = SYSLOG_DELIMITER;
1653 
1654  *record++ = '-'; /* No translated source ip */
1655  *record++ = SYSLOG_DELIMITER;
1656 
1657  record += u16_to_ascii_decimal_unaligned(
1658  record, key->k.port);
1659  *record++ = SYSLOG_DELIMITER;
1660 
1661  *record++ = '-'; /* No translated start port */
1662  *record++ = SYSLOG_DELIMITER;
1663 
1664  *record++ = '-'; /* No translated end port */
1665  *record++ = SYSLOG_DELIMITER;
1666 
1667  /*No Destination Info*/
1668  *record++ = '-';
1669  *record++ = SYSLOG_DELIMITER;
1670  *record++ = '-';
1671  *record++ = SYSLOG_DELIMITER;
1672 
1673  *record++ = ']'; /* End of the reocrd */
1674 
1675  log_info->pkt_length += record - temp;
1676 }
1677 
1678 void cnat_syslog_nat44_port_limit_exceeded(
1679  cnat_key_t * key,
1680  cnat_vrfmap_t *vrfmap)
1681 {
1682  cnat_syslog_logging_info_t *logging_info = 0;
1683 
1684  SYSLOG_PRECHECK(vrfmap, NAT44)
1685 
1686  cnat_syslog_nat44_insert_port_exceeded(logging_info, key);
1687 
1688  /*
1689  * If we have exceeded the packet length, let us send the
1690  * packet now. There is buffer of additional bytes beyond
1691  * max_pkt_length to ensure that the last add/delete record
1692  * can be stored safely.
1693  */
1694 
1695  if (PREDICT_FALSE(logging_info->pkt_length >
1696  logging_info->max_length_minus_max_record_size)) {
1697  cnat_syslog_send_pkt(logging_info);
1698  }
1699 }
1700 
1701 void cnat_syslog_nat44_insert_tcp_seq_mismatch(
1702  cnat_syslog_logging_info_t *log_info,
1704 {
1705  /* This record should like this -
1706  * [TCPseqmismatch <L4> <Original Source IP> <Inside VRF Name>
1707  * - <Translated Source IP> <Original Port> <Translated Source Port> - - -]
1708  */
1709  unsigned char *temp, *record;
1710 
1711  temp = record = &(log_info->current_logging_context->packet_data[
1712  CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
1713 
1714  /* Now we point to the location where record needs to be inserted */
1715  *record++ = '['; /* Open the record */
1716 
1717  /* Copy the record type */
1718  clib_memcpy(record, sys_log_event[tcp_seq_mismatch].event_name,
1719  sys_log_event[tcp_seq_mismatch].name_length);
1720  record += sys_log_event[tcp_seq_mismatch].name_length;
1721  *record++ = SYSLOG_DELIMITER;
1722 
1723  /* Next field is TCP */
1724  *record++ = '6';
1725  *record++ = SYSLOG_DELIMITER;
1726 
1727  /* Copy the Original Source IP */
1728  record += copy_ipv4_addr(record, db->in2out_key.k.ipv4);
1729  *record++ = SYSLOG_DELIMITER;
1730 
1731  /* copy configured VRF NAME */
1732  clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
1733  record += log_info->vrf_name_len;
1734  *record++ = SYSLOG_DELIMITER;
1735 
1736  /* No IPV6 source address for nat44 */
1737  *record++ = '-';
1738  *record++ = SYSLOG_DELIMITER;
1739 
1740  record += copy_ipv4_addr(record, db->out2in_key.k.ipv4);
1741  *record++ = SYSLOG_DELIMITER;
1742 
1743  record += u16_to_ascii_decimal_unaligned(
1744  record, db->in2out_key.k.port);
1745  *record++ = SYSLOG_DELIMITER;
1746 
1747  record += u16_to_ascii_decimal_unaligned(
1748  record, db->out2in_key.k.port);
1749  *record++ = SYSLOG_DELIMITER;
1750 
1751  *record++ = '-'; /* No translated end port */
1752  *record++ = SYSLOG_DELIMITER;
1753 
1754  /*No Destination Info*/
1755  *record++ = '-';
1756  *record++ = SYSLOG_DELIMITER;
1757  *record++ = '-';
1758  *record++ = SYSLOG_DELIMITER;
1759 
1760  *record++ = ']'; /* End of the reocrd */
1761 
1762  log_info->pkt_length += record - temp;
1763 }
1764 
1765 void cnat_syslog_nat44_tcp_seq_mismatch(
1767  cnat_vrfmap_t *vrfmap)
1768 {
1769  cnat_syslog_logging_info_t *logging_info = 0;
1770 
1771  SYSLOG_PRECHECK(vrfmap, NAT44)
1772 
1773  cnat_syslog_nat44_insert_tcp_seq_mismatch(logging_info, db);
1774 
1775  /*
1776  * If we have exceeded the packet length, let us send the
1777  * packet now. There is buffer of additional bytes beyond
1778  * max_pkt_length to ensure that the last add/delete record
1779  * can be stored safely.
1780  */
1781 
1782  if (PREDICT_FALSE(logging_info->pkt_length >
1783  logging_info->max_length_minus_max_record_size)) {
1784  cnat_syslog_send_pkt(logging_info);
1785  }
1786 }
1787 #endif
u32 cnat_get_sys_up_time_in_ms(void)
Definition: cnat_logging.c:100
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
syslog_event_type_t
Definition: cnat_syslog.h:101
u32 ipv6[4]
Definition: cnat_db.h:118
cnat_syslog_global_counters_t cnat_syslog_global_counter
Definition: cnat_syslog.c:39
static int copy_ipv4_addr(unsigned char *ptr, u32 ipv4)
Definition: cnat_syslog.c:365
u32 user_index
Definition: cnat_db.h:195
u32 syslog_debug_flag
#define PREDICT_TRUE(x)
Definition: clib.h:98
Fixed length block allocator.
#define NULL
Definition: clib.h:55
cnat_syslog_global_info_t cnat_syslog_global_info
Definition: cnat_syslog.c:37
#define CNAT_NFV9_HDR_OFFSET
Definition: cnat_db.h:153
void cnat_syslog_ds_lite_mapping_create(cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb, int bulk_alloc)
#define SYSLOG_DEBUG_PRINTF1(a)
Definition: cnat_syslog.c:54
void syslog_params_show(u32 logging_index)
Definition: cnat_syslog.c:62
cnat_key_t v4_dest_key
Definition: cnat_db.h:345
#define SYSLOG_DELIMITER
Definition: cnat_syslog.c:27
spp_ctx_t * current_logging_context
Definition: cnat_syslog.h:159
#define PLATFORM_DEBUG_PRINT(...)
Definition: dslite_defs.h:106
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
syslog_service_type_t
Definition: cnat_syslog.h:96
void cnat_syslog_logging_init()
Definition: cnat_syslog.c:412
#define CNAT_PRO_MASK
Definition: cnat_db.h:97
#define PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, to_lc_cpu)
u16 dst_port
Definition: cnat_db.h:257
u32 cnat_get_unix_time_in_seconds(void)
Definition: cnat_syslog.c:464
void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb, int bulk_alloc)
Definition: cnat_syslog.c:453
spp_ctx_t * queued_logging_context
Definition: cnat_syslog.h:160
void cnat_syslog_fill_ip_header(cnat_syslog_logging_info_t *logging_info)
Definition: cnat_syslog.c:405
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define CACHE_ALLOC_NO_LOG_REQUIRED
#define CNAT_UDP
Definition: cnat_db.h:93
#define SYSLOG_FIELD_ABSENT
Definition: cnat_syslog.c:28
void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb, int bulk_alloc)
Definition: cnat_syslog.c:436
cnat_user_db_entry_t * cnat_user_db
Definition: cnat_db_v2.c:202
#define CNAT_ICMP
Definition: cnat_db.h:95
#define PLATFORM_SYSLOG_DISP_NODE_IDX
Definition: cnat_syslog.c:35
#define SESSION_LOG_ENABLE
Definition: cnat_db.h:693
void cnat_syslog_ds_lite_port_limit_exceeded(dslite_key_t *key, dslite_table_entry_t *dslite_entry)
Definition: cnat_syslog.c:429
#define clib_memcpy(a, b, c)
Definition: string.h:64
void cnat_syslog_log_mapping_create(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap)
Definition: cnat_syslog.c:417
u8 my_instance_number
Definition: cnat_ports.c:51
cnat_db_key_t k
Definition: cnat_db.h:108
u8 syslog_logging_policy
Definition: dslite_defs.h:161
#define BULKSIZE_FROM_VRFMAP(vrfmap)
cnat_key_t ipv4_key
Definition: cnat_db.h:119
u32 ipv6[4]
Definition: cnat_db.h:310
Definition: cnat_db.h:285
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
cnat_icmp_msg_t
Definition: cnat_db.h:522
#define SYSLOG_CONFIG_DEBUG_PRINTF(level,...)
Definition: cnat_syslog.h:33
void fill_ip_n_udp_hdr(u32 ipv4_addr, u16 port, cnat_nfv9_logging_info_t *nfv9_logging_info)
Definition: cnat_logging.c:359
static int byte_to_ascii_decimal_unaligned(unsigned char *ptr, unsigned char num)
Definition: cnat_syslog.c:345
cnat_key_t out2in_key
Definition: cnat_db.h:198
char vrf_name[VRF_NAME_LEN_STORED]
Definition: cnat_syslog.h:153
#define CNAT_TCP
Definition: cnat_db.h:94
cnat_syslog_logging_info_t * cnat_syslog_logging_info_pool
Definition: cnat_syslog.c:38
cnat_icmp_msg_t icmp_msg_gen_allowed()
Definition: cnat_syslog.c:448
Definition: cnat_db.h:336
unsigned short u16
Definition: types.h:57
u8 syslog_logging_policy
Definition: cnat_db.h:441
unsigned char u8
Definition: types.h:56
u32 dst_ipv4
Definition: cnat_db.h:254
struct _spp_ctx spp_ctx_t
#define PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, value)
short i16
Definition: types.h:46
#define EMPTY
Definition: index_list.h:24
void cnat_syslog_log_mapping_delete(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap)
Definition: cnat_syslog.c:423
char header_hostname[MAX_SYSLOG_HOSTNAME_LEN]
Definition: cnat_syslog.h:152
#define CNAT_NFV9_IP_HDR_OFFSET
#define CNAT_NFV9_UDP_HDR_OFFSET
cnat_key_t in2out_key
Definition: cnat_db.h:201
const unsigned char ascii_numbers[][3]
Definition: cnat_syslog.c:85