Initial commit of vpp code.
[vpp.git] / vnet / vnet / vcgn / cnat_syslog.c
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
37 cnat_syslog_global_info_t cnat_syslog_global_info;
38 cnat_syslog_logging_info_t *cnat_syslog_logging_info_pool;
39 cnat_syslog_global_counters_t   cnat_syslog_global_counter;
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 
345 byte_to_ascii_decimal_unaligned(
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 
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
390 void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info)
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
405 void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info)
406 {
407     return;
408 }
409 #endif
410
411 #ifndef TOBE_PORTED
412 void cnat_syslog_logging_init()
413 {
414     return;
415 }
416
417 void cnat_syslog_log_mapping_create(cnat_main_db_entry_t * db,
418                                   cnat_vrfmap_t *vrfmap)
419 {
420     return;
421 }
422
423 void cnat_syslog_log_mapping_delete(cnat_main_db_entry_t * db,
424                                   cnat_vrfmap_t *vrfmap)
425 {
426     return;
427 }
428
429 void cnat_syslog_ds_lite_port_limit_exceeded(
430    dslite_key_t   * key,
431    dslite_table_entry_t *dslite_entry)
432 {
433     return;
434 }
435
436 void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db,
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 */
448 cnat_icmp_msg_t icmp_msg_gen_allowed ()
449 {
450     return 1;
451 }
452
453 void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db,
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
464 cnat_get_unix_time_in_seconds (void)
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,
489             cnat_get_unix_time_in_seconds());
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;
572         PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->current_logging_context, \
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
578         if(PREDICT_FALSE(syslog_debug_flag > 10))
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++;
587         if(PREDICT_FALSE(syslog_debug_flag > 10)) 
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; ***/
633         PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->queued_logging_context, 
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     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     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     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 */
896 void cnat_syslog_logging_init() 
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)
956     PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, 0); 
957
958     logging_info->current_logging_context = ctx;
959
960     PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, NODE_LOGGING);
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 - 
968                                     CNAT_NFV9_IP_HDR_OFFSET); 
969     logging_info->current_logging_context_timestamp =
970         cnat_get_sys_up_time_in_ms();
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;
1064     cnat_user_db_entry_t  *udb = cnat_user_db + db->user_index;
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     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     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;
1184     cnat_user_db_entry_t  *udb = cnat_user_db + db->user_index;
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     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     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
1316 void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db,
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
1365 void cnat_syslog_ds_lite_mapping_create(cnat_main_db_entry_t *db,
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
1387     if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) {
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
1413 void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db,
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
1481     if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) {
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     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     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
1584 void cnat_syslog_ds_lite_port_limit_exceeded(
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     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     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,
1703      cnat_main_db_entry_t *db)
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     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     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(
1766         cnat_main_db_entry_t *db,
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