summaryrefslogtreecommitdiffstats
path: root/plugins/vcgn-plugin/vcgn/cnat_syslog.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/vcgn-plugin/vcgn/cnat_syslog.c')
-rw-r--r--plugins/vcgn-plugin/vcgn/cnat_syslog.c1787
1 files changed, 1787 insertions, 0 deletions
diff --git a/plugins/vcgn-plugin/vcgn/cnat_syslog.c b/plugins/vcgn-plugin/vcgn/cnat_syslog.c
new file mode 100644
index 00000000000..91758f141a9
--- /dev/null
+++ b/plugins/vcgn-plugin/vcgn/cnat_syslog.c
@@ -0,0 +1,1787 @@
+/*
+ *------------------------------------------------------------------
+ * cnat_syslog.c
+ *
+ * Copyright (c) 2011-2013 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *------------------------------------------------------------------
+ */
+
+#include <arpa/inet.h>
+#include "cnat_syslog.h"
+#include "platform_common.h"
+#include "cnat_db.h"
+#include "cnat_log_common.h"
+#include <vppinfra/pool.h>
+
+#define SYSLOG_DELIMITER ' '
+#define SYSLOG_FIELD_ABSENT '-'
+/* #define SHOW_SYSLOG_TIMESTAMP 1 TO DO. Remove this later */
+/*
+ * Defining the below macro here for now. Assumption is, syslog packets
+ * are sent out via same channel as that of NFV9.
+ * Has to be overridden if this assumption is false.
+ */
+#define PLATFORM_SYSLOG_DISP_NODE_IDX PLATFORM_NFV9_DISP_NODE_IDX
+
+cnat_syslog_global_info_t cnat_syslog_global_info;
+cnat_syslog_logging_info_t *cnat_syslog_logging_info_pool;
+cnat_syslog_global_counters_t cnat_syslog_global_counter;
+extern u32 syslog_debug_flag;
+
+#define CNAT_SYSLOG_DEBUG_CODE 2
+
+#if CNAT_SYSLOG_DEBUG_CODE > 3
+#define SYSLOG_COND if(my_instance_number == 0)
+
+#define SYSLOG_DEBUG_PRINTF1(a) SYSLOG_COND printf(a);
+#define SYSLOG_DEBUG_PRINTF2(a, b) SYSLOG_COND printf(a, b);
+#define SYSLOG_DEBUG_PRINTF3(a, b, c) SYSLOG_COND printf(a, b, c);
+#define SYSLOG_DEBUG_PRINTF4(a, b, c, d) SYSLOG_COND printf(a, b, c, d);
+
+#else
+
+#define SYSLOG_DEBUG_PRINTF1(a)
+#define SYSLOG_DEBUG_PRINTF2(a, b)
+#define SYSLOG_DEBUG_PRINTF3(a, b, c)
+#define SYSLOG_DEBUG_PRINTF4(a, b, c, d)
+
+#endif
+
+
+void syslog_params_show(u32 logging_index)
+{
+ cnat_syslog_logging_info_t *log_info __attribute__((unused));
+ if(logging_index == EMPTY) {
+ PLATFORM_DEBUG_PRINT("\nSyslog logging not configured\n");
+ return;
+ }
+
+ log_info = cnat_syslog_logging_info_pool + logging_index;
+
+ PLATFORM_DEBUG_PRINT("\nSyslog parameters --\n");
+ PLATFORM_DEBUG_PRINT("IPV4 address: %x, port %d, max log size %d\n",
+ log_info->ipv4_address,
+ log_info->port, log_info->max_length_minus_max_record_size);
+ PLATFORM_DEBUG_PRINT("Host name: %s, priority %d",
+ log_info->header_hostname, log_info->header_priority);
+
+}
+
+/* Util function to copy a number as ASCII in to a buf in a
+ * faster way (should be faster than sprintf)
+ */
+
+const unsigned char ascii_numbers[][3] =
+ { {'0', '0', '0'},
+ {'1', '0', '0'},
+ {'2', '0', '0'},
+ {'3', '0', '0'},
+ {'4', '0', '0'},
+ {'5', '0', '0'},
+ {'6', '0', '0'},
+ {'7', '0', '0'},
+ {'8', '0', '0'},
+ {'9', '0', '0'},
+ {'1', '0', '0'},
+ {'1', '1', '0'},
+ {'1', '2', '0'},
+ {'1', '3', '0'},
+ {'1', '4', '0'},
+ {'1', '5', '0'},
+ {'1', '6', '0'},
+ {'1', '7', '0'},
+ {'1', '8', '0'},
+ {'1', '9', '0'},
+ {'2', '0', '0'},
+ {'2', '1', '0'},
+ {'2', '2', '0'},
+ {'2', '3', '0'},
+ {'2', '4', '0'},
+ {'2', '5', '0'},
+ {'2', '6', '0'},
+ {'2', '7', '0'},
+ {'2', '8', '0'},
+ {'2', '9', '0'},
+ {'3', '0', '0'},
+ {'3', '1', '0'},
+ {'3', '2', '0'},
+ {'3', '3', '0'},
+ {'3', '4', '0'},
+ {'3', '5', '0'},
+ {'3', '6', '0'},
+ {'3', '7', '0'},
+ {'3', '8', '0'},
+ {'3', '9', '0'},
+ {'4', '0', '0'},
+ {'4', '1', '0'},
+ {'4', '2', '0'},
+ {'4', '3', '0'},
+ {'4', '4', '0'},
+ {'4', '5', '0'},
+ {'4', '6', '0'},
+ {'4', '7', '0'},
+ {'4', '8', '0'},
+ {'4', '9', '0'},
+ {'5', '0', '0'},
+ {'5', '1', '0'},
+ {'5', '2', '0'},
+ {'5', '3', '0'},
+ {'5', '4', '0'},
+ {'5', '5', '0'},
+ {'5', '6', '0'},
+ {'5', '7', '0'},
+ {'5', '8', '0'},
+ {'5', '9', '0'},
+ {'6', '0', '0'},
+ {'6', '1', '0'},
+ {'6', '2', '0'},
+ {'6', '3', '0'},
+ {'6', '4', '0'},
+ {'6', '5', '0'},
+ {'6', '6', '0'},
+ {'6', '7', '0'},
+ {'6', '8', '0'},
+ {'6', '9', '0'},
+ {'7', '0', '0'},
+ {'7', '1', '0'},
+ {'7', '2', '0'},
+ {'7', '3', '0'},
+ {'7', '4', '0'},
+ {'7', '5', '0'},
+ {'7', '6', '0'},
+ {'7', '7', '0'},
+ {'7', '8', '0'},
+ {'7', '9', '0'},
+ {'8', '0', '0'},
+ {'8', '1', '0'},
+ {'8', '2', '0'},
+ {'8', '3', '0'},
+ {'8', '4', '0'},
+ {'8', '5', '0'},
+ {'8', '6', '0'},
+ {'8', '7', '0'},
+ {'8', '8', '0'},
+ {'8', '9', '0'},
+ {'9', '0', '0'},
+ {'9', '1', '0'},
+ {'9', '2', '0'},
+ {'9', '3', '0'},
+ {'9', '4', '0'},
+ {'9', '5', '0'},
+ {'9', '6', '0'},
+ {'9', '7', '0'},
+ {'9', '8', '0'},
+ {'9', '9', '0'},
+ {'1', '0', '0'},
+ {'1', '0', '1'},
+ {'1', '0', '2'},
+ {'1', '0', '3'},
+ {'1', '0', '4'},
+ {'1', '0', '5'},
+ {'1', '0', '6'},
+ {'1', '0', '7'},
+ {'1', '0', '8'},
+ {'1', '0', '9'},
+ {'1', '1', '0'},
+ {'1', '1', '1'},
+ {'1', '1', '2'},
+ {'1', '1', '3'},
+ {'1', '1', '4'},
+ {'1', '1', '5'},
+ {'1', '1', '6'},
+ {'1', '1', '7'},
+ {'1', '1', '8'},
+ {'1', '1', '9'},
+ {'1', '2', '0'},
+ {'1', '2', '1'},
+ {'1', '2', '2'},
+ {'1', '2', '3'},
+ {'1', '2', '4'},
+ {'1', '2', '5'},
+ {'1', '2', '6'},
+ {'1', '2', '7'},
+ {'1', '2', '8'},
+ {'1', '2', '9'},
+ {'1', '3', '0'},
+ {'1', '3', '1'},
+ {'1', '3', '2'},
+ {'1', '3', '3'},
+ {'1', '3', '4'},
+ {'1', '3', '5'},
+ {'1', '3', '6'},
+ {'1', '3', '7'},
+ {'1', '3', '8'},
+ {'1', '3', '9'},
+ {'1', '4', '0'},
+ {'1', '4', '1'},
+ {'1', '4', '2'},
+ {'1', '4', '3'},
+ {'1', '4', '4'},
+ {'1', '4', '5'},
+ {'1', '4', '6'},
+ {'1', '4', '7'},
+ {'1', '4', '8'},
+ {'1', '4', '9'},
+ {'1', '5', '0'},
+ {'1', '5', '1'},
+ {'1', '5', '2'},
+ {'1', '5', '3'},
+ {'1', '5', '4'},
+ {'1', '5', '5'},
+ {'1', '5', '6'},
+ {'1', '5', '7'},
+ {'1', '5', '8'},
+ {'1', '5', '9'},
+ {'1', '6', '0'},
+ {'1', '6', '1'},
+ {'1', '6', '2'},
+ {'1', '6', '3'},
+ {'1', '6', '4'},
+ {'1', '6', '5'},
+ {'1', '6', '6'},
+ {'1', '6', '7'},
+ {'1', '6', '8'},
+ {'1', '6', '9'},
+ {'1', '7', '0'},
+ {'1', '7', '1'},
+ {'1', '7', '2'},
+ {'1', '7', '3'},
+ {'1', '7', '4'},
+ {'1', '7', '5'},
+ {'1', '7', '6'},
+ {'1', '7', '7'},
+ {'1', '7', '8'},
+ {'1', '7', '9'},
+ {'1', '8', '0'},
+ {'1', '8', '1'},
+ {'1', '8', '2'},
+ {'1', '8', '3'},
+ {'1', '8', '4'},
+ {'1', '8', '5'},
+ {'1', '8', '6'},
+ {'1', '8', '7'},
+ {'1', '8', '8'},
+ {'1', '8', '9'},
+ {'1', '9', '0'},
+ {'1', '9', '1'},
+ {'1', '9', '2'},
+ {'1', '9', '3'},
+ {'1', '9', '4'},
+ {'1', '9', '5'},
+ {'1', '9', '6'},
+ {'1', '9', '7'},
+ {'1', '9', '8'},
+ {'1', '9', '9'},
+ {'2', '0', '0'},
+ {'2', '0', '1'},
+ {'2', '0', '2'},
+ {'2', '0', '3'},
+ {'2', '0', '4'},
+ {'2', '0', '5'},
+ {'2', '0', '6'},
+ {'2', '0', '7'},
+ {'2', '0', '8'},
+ {'2', '0', '9'},
+ {'2', '1', '0'},
+ {'2', '1', '1'},
+ {'2', '1', '2'},
+ {'2', '1', '3'},
+ {'2', '1', '4'},
+ {'2', '1', '5'},
+ {'2', '1', '6'},
+ {'2', '1', '7'},
+ {'2', '1', '8'},
+ {'2', '1', '9'},
+ {'2', '2', '0'},
+ {'2', '2', '1'},
+ {'2', '2', '2'},
+ {'2', '2', '3'},
+ {'2', '2', '4'},
+ {'2', '2', '5'},
+ {'2', '2', '6'},
+ {'2', '2', '7'},
+ {'2', '2', '8'},
+ {'2', '2', '9'},
+ {'2', '3', '0'},
+ {'2', '3', '1'},
+ {'2', '3', '2'},
+ {'2', '3', '3'},
+ {'2', '3', '4'},
+ {'2', '3', '5'},
+ {'2', '3', '6'},
+ {'2', '3', '7'},
+ {'2', '3', '8'},
+ {'2', '3', '9'},
+ {'2', '4', '0'},
+ {'2', '4', '1'},
+ {'2', '4', '2'},
+ {'2', '4', '3'},
+ {'2', '4', '4'},
+ {'2', '4', '5'},
+ {'2', '4', '6'},
+ {'2', '4', '7'},
+ {'2', '4', '8'},
+ {'2', '4', '9'},
+ {'2', '5', '0'},
+ {'2', '5', '1'},
+ {'2', '5', '2'},
+ {'2', '5', '3'},
+ {'2', '5', '4'},
+ {'2', '5', '5'}
+ };
+
+inline static int
+byte_to_ascii_decimal_unaligned(
+ unsigned char *ptr, unsigned char num)
+{
+ *ptr++ = ascii_numbers[num][0];
+ if(PREDICT_FALSE(num < 10)) {
+ return 1;
+ }
+ *ptr++ = ascii_numbers[num][1];
+ if(PREDICT_FALSE(num < 100)) {
+ return 2;
+ }
+ *ptr++ = ascii_numbers[num][2];
+ return 3;
+}
+
+/* Copies the dotted decimal format of ipv4
+ * in to the space provided and
+ * returns the number of bytes copied
+ */
+inline static int __attribute__((unused))
+copy_ipv4_addr(unsigned char *ptr, u32 ipv4)
+{
+ unsigned char *temp = ptr;
+ temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 >> 24));
+ *temp++ = '.';
+ temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 16) & 0xFF));
+ *temp++ = '.';
+ temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 8) & 0xFF));
+ *temp++ = '.';
+ temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 & 0xFF));
+
+ return (temp - ptr);
+}
+
+#ifdef TOBE_PORTED
+/*
+ * edt: * * cnat_syslog_fill_ip_header
+ *
+ * Tries to fill the fields of the IP header before it
+ * is sent to the L3 infra node.
+ *
+ * Argument: cnat_syslog_logging_info_t *logging_info
+ * structure that contains the packet context
+ */
+inline
+void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info)
+{
+ spp_ctx_t *ctx;
+
+ /*
+ * Fill in the IP header and port number of the Netflow collector
+ * The L3 Infra node will fill in the rest of the fields
+ */
+ ctx = logging_info->current_logging_context;
+ fill_ip_n_udp_hdr(ctx, logging_info->ipv4_address,
+ logging_info->port, logging_info->pkt_length);
+
+}
+#else
+inline
+void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info)
+{
+ return;
+}
+#endif
+
+#ifndef TOBE_PORTED
+void cnat_syslog_logging_init()
+{
+ return;
+}
+
+void cnat_syslog_log_mapping_create(cnat_main_db_entry_t * db,
+ cnat_vrfmap_t *vrfmap)
+{
+ return;
+}
+
+void cnat_syslog_log_mapping_delete(cnat_main_db_entry_t * db,
+ cnat_vrfmap_t *vrfmap)
+{
+ return;
+}
+
+void cnat_syslog_ds_lite_port_limit_exceeded(
+ dslite_key_t * key,
+ dslite_table_entry_t *dslite_entry)
+{
+ return;
+}
+
+void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db,
+ cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb
+#ifndef NO_BULK_LOGGING
+ , int bulk_alloc
+#endif
+ )
+{
+ return;
+}
+
+/* Following are in cnat_util.c which are not ported */
+/* This function is defined in cnat_util.c which need to be ported */
+cnat_icmp_msg_t icmp_msg_gen_allowed ()
+{
+ return 1;
+}
+
+void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db,
+ cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb
+#ifndef NO_BULK_LOGGING
+ , int bulk_alloc
+#endif
+ )
+{
+ return;
+}
+
+u32
+cnat_get_unix_time_in_seconds (void)
+{
+ return 0;
+}
+#else /* TOBE_PORTED */
+void
+cnat_syslog_dump_logging_context (u32 value1,
+ cnat_syslog_logging_info_t *logging_info,
+ u32 value2)
+{
+ u8 *pkt_ptr;
+ u32 i;
+
+ if (PREDICT_TRUE(syslog_debug_flag == 0)) {
+ return;
+ }
+ /*
+ * Reduce the logging to few cores, to enable easier debugging
+ */
+ if ((my_instance_number & 0x7) != 0) {
+ return;
+ }
+ printf("\nDumping %s packet at locn %d: time 0x%x",
+ (value2 == 1) ? "CURRENT" : "QUEUED",
+ value1,
+ cnat_get_unix_time_in_seconds());
+
+ printf("\ni_vrf 0x%x, ip_address 0x%x, port %d, pkt len %d",
+ 0 /* TO DP Add vrf like nfv9_logging_info->i_vrf */,
+ logging_info->ipv4_address,
+ logging_info->port,
+ logging_info->pkt_length);
+ printf("\n");
+
+ if (value2 == 1) {
+ pkt_ptr = logging_info->current_logging_context->packet_data;
+ } else {
+ pkt_ptr = logging_info->queued_logging_context->packet_data;
+ }
+
+ /*
+ * Dump along with 8 bytes of SHIM header
+ */
+ for (i = 0; i <
+ (logging_info->pkt_length + CNAT_NFV9_IP_HDR_OFFSET);
+ i = i + 1) {
+ u8 c1, c2, c3;
+
+ if (i == 0) {
+ printf("\nL2_HEADER + SHIM_HEADER: \n");
+ } else if (i == CNAT_NFV9_IP_HDR_OFFSET) {
+ printf("\nIP_HEADER: \n");
+ } else if (i == CNAT_NFV9_UDP_HDR_OFFSET) {
+ printf("\nUDP_HEADER: \n");
+ } else if (i == CNAT_NFV9_HDR_OFFSET) {
+ printf("\nSyslog content..\n");
+ while(i <
+ (logging_info->pkt_length + CNAT_NFV9_HDR_OFFSET)) {
+ printf("%c", (u8)(*(pkt_ptr + i)));
+ i++;
+ if((u8)(*(pkt_ptr + i)) == '[') /* new record begins */
+ printf("\n");
+ }
+ return;
+ }
+
+ c3 = *(pkt_ptr + i);
+ c2 = c3 & 0xf;
+ c1 = (c3 >> 4) & 0xf;
+
+ printf("%c%c ",
+ ((c1 <= 9) ? (c1 + '0') : (c1 - 10 + 'a')),
+ ((c2 <= 9) ? (c2 + '0') : (c2 - 10 + 'a')));
+
+ }
+
+ printf("\n");
+}
+
+
+/*
+ * edt: * * cnat_syslog_send_pkt
+ *
+ * Tries to send a logging pkt. If the packet cannot be sent
+ * because of rewrite_output node cannot process it, queue
+ * it temporarily and try to send it later.
+ *
+ * Argument: cnat_syslog_logging_info_t *logging_info
+ * structure that contains the packet context
+ */
+inline
+void cnat_syslog_send_pkt (cnat_syslog_logging_info_t *logging_info)
+{
+ spp_node_t *output_node;
+
+ cnat_syslog_fill_ip_header(logging_info);
+
+ output_node = spp_get_nodes() +
+ cnat_syslog_global_info.cnat_syslog_disp_node_index;
+
+ cnat_syslog_dump_logging_context (2, logging_info, 1);
+
+ if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) {
+ /*
+ * Move the logging context to output node
+ */
+ logging_info->current_logging_context->current_length =
+ logging_info->pkt_length;
+ PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->current_logging_context, \
+ NODE_LOGGING);
+ spp_dispatch_make_node_runnable(output_node);
+ output_node->sf.ctxs[output_node->sf.nused++] =
+ logging_info->current_logging_context;
+
+ if(PREDICT_FALSE(syslog_debug_flag > 10))
+ printf("\nSyslog: 2. Sending Current packet\n");
+ } else {
+ /*
+ * Queue the context into the logging_info structure,
+ * We will try to send it later. Currently, we will
+ * restrict to only one context queued.
+ */
+ cnat_syslog_global_counter.downstream_constipation_count++;
+ if(PREDICT_FALSE(syslog_debug_flag > 10))
+ printf("\nSyslog: 2. Downstream congestion \n");
+
+ /*
+ * Attach the current logging context which is full to the
+ * queued context list in logging_info structure
+ */
+ logging_info->queued_logging_context =
+ logging_info->current_logging_context;
+ }
+
+ /*
+ * Whether the context is queued or not, set the current context index
+ * to EMPTY, as the earlier context can no more be used to send
+ * more logging records.
+ */
+ logging_info->current_logging_context = NULL;
+}
+
+
+/*
+ * edt: * * cnat_syslog_send_queued_pkt
+ *
+ * Tries to send a logging pkt that has been queued earlier
+ * because it could not be sent due to downstream constipation
+ *
+ * Argument: cnat_syslog_logging_info_t *logging_info
+ * structure that contains the packet context
+ */
+inline
+void cnat_syslog_send_queued_pkt (cnat_syslog_logging_info_t *logging_info)
+{
+ spp_node_t *output_node;
+
+ output_node = spp_get_nodes() +
+ cnat_syslog_global_info.cnat_syslog_disp_node_index;
+
+ cnat_syslog_dump_logging_context(1, logging_info, 2);
+
+ if(PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) {
+ /*
+ * Move the logging context to output node
+ */
+ /** This looks like a bug to me .. need to confirm *****
+ logging_info->queued_logging_context->current_length =
+ nfv9_logging_info->pkt_length; ***/
+ PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->queued_logging_context,
+ NODE_LOGGING)
+ spp_dispatch_make_node_runnable(output_node);
+ output_node->sf.ctxs[output_node->sf.nused++] =
+ logging_info->queued_logging_context;
+
+ SYSLOG_DEBUG_PRINTF1("\nSYSLOG: 1. Sending Queued packet\n")
+
+ /*
+ * Context has been queued, it will be freed after the pkt
+ * is sent. Clear this from the logging_context_info structure
+ */
+ logging_info->queued_logging_context = NULL;
+
+ } else {
+ cnat_syslog_global_counter.downstream_constipation_count++;
+ }
+}
+
+/*
+ * edt: * * handle_pending_syslog_pkts
+ *
+ * Timer handler for sending any pending syslog record
+ *
+ */
+inline
+void handle_pending_syslog_pkts()
+{
+ spp_node_t *output_node;
+ cnat_syslog_logging_info_t *my_logging_info = 0;
+ u32 current_timestamp = cnat_get_sys_up_time_in_ms();
+ i16 sf_nused;
+
+ output_node = spp_get_nodes() +
+ cnat_syslog_global_info.cnat_syslog_disp_node_index;
+
+ sf_nused = output_node->sf.nused;
+
+ pool_foreach (my_logging_info, cnat_syslog_logging_info_pool, ({
+ /*
+ * Check if no more logging contexts can be queued
+ */
+ if (PREDICT_FALSE(sf_nused >= SPP_MAXDISPATCH)) {
+ break;
+ }
+ if (my_logging_info->queued_logging_context)
+ cnat_syslog_send_queued_pkt (my_logging_info);
+
+ if(my_logging_info->current_logging_context &&
+ ((current_timestamp -
+ my_logging_info->current_logging_context_timestamp)
+ > 1000)) {
+ /*
+ * If there is a current logging context and timestamp
+ * indicates it is pending for long, send it out
+ * Also if there is a queued context send it out as well
+ */
+ SYSLOG_DEBUG_PRINTF4("\nLOG_TIMER: queued %p, curr %p, sf_nused %d",
+ my_logging_info->queued_logging_context,
+ my_logging_info->current_logging_context,
+ sf_nused);
+ cnat_syslog_send_pkt(my_logging_info);
+ }
+ }));
+}
+
+const unsigned char hex_numbers_single_digit[] =
+ { '0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+inline static int u16_to_ascii_decimal_aligned(
+ unsigned char *ptr, u16 num, u16 min_digits)
+{
+ /* The logic below is replicated in
+ * function u16_to_ascii_decimal_unaligned
+ * except the use of min_digits
+ * Replication is done to optimize run time
+ * if you fix a bug here, check u16_to_ascii_decimal_unaligned
+ * as well (and vice versa)
+ */
+ unsigned char *temp = ptr;
+ int no_leading_zeros = 0;
+
+ if(num > 9999 || min_digits == 5) {
+ *temp++ = hex_numbers_single_digit[num/10000];
+ num = num%10000;
+ no_leading_zeros = 1;
+ }
+
+ if(no_leading_zeros || num > 999 || min_digits == 4) {
+ *temp++ = hex_numbers_single_digit[num/1000];
+ num = num%1000;
+ no_leading_zeros = 1;
+ }
+
+ if(no_leading_zeros || num > 99 || min_digits == 3) {
+ *temp++ = hex_numbers_single_digit[num/100];
+ num = num%100;
+ no_leading_zeros = 1;
+ }
+
+ if(no_leading_zeros || num > 9 || min_digits == 2) {
+ *temp++ = hex_numbers_single_digit[num/10];
+ num = num%10;
+ }
+
+ *temp++ = hex_numbers_single_digit[num];
+
+ return temp-ptr;
+}
+
+inline static int u16_to_ascii_decimal_unaligned(
+ unsigned char *ptr, u16 num)
+{
+ /*
+ * return u16_to_ascii_decimal_aligned(ptr, num, 0);
+ * should do the job.. however, to opimize the run time
+ * the code of u16_to_ascii_decimal_aligned is being
+ * repeated here without the use of min_digits
+ * if you fix a bug here, please check
+ * u16_to_ascii_decimal_aligned as well (and vice versa)
+ */
+ unsigned char *temp = ptr;
+ int no_leading_zeros = 0;
+
+ if(num > 9999) {
+ *temp++ = hex_numbers_single_digit[num/10000];
+ num = num%10000;
+ no_leading_zeros = 1;
+ }
+
+ if(no_leading_zeros || num > 999) {
+ *temp++ = hex_numbers_single_digit[num/1000];
+ num = num%1000;
+ no_leading_zeros = 1;
+ }
+
+ if(no_leading_zeros || num > 99) {
+ *temp++ = hex_numbers_single_digit[num/100];
+ num = num%100;
+ no_leading_zeros = 1;
+ }
+
+ if(no_leading_zeros || num > 9) {
+ *temp++ = hex_numbers_single_digit[num/10];
+ num = num%10;
+ }
+
+ *temp++ = hex_numbers_single_digit[num];
+
+ return temp-ptr;
+}
+
+static int syslog_get_timestamp(unsigned char *ts)
+{
+ static const char *months[] = {"Jan ", "Feb ", "Mar ", "Apr ", "May ",
+ "Jun ", "Jul ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec " };
+
+ unsigned char *temp = ts;
+ /* Inserts time stamp in the syslog format and returns lenght
+ * assumes that ts has sufficient space
+ */
+ /* China Telecom has demanded that the time stamp has to be
+ * in the format '2011 Jun 7 12:34:08'
+ */
+ time_t time = (time_t)cnat_get_unix_time_in_seconds();
+ struct tm tm1;
+
+ gmtime_r(&time, &tm1);
+ /* Now put the pieces together */
+ /* Year */
+ ts += u16_to_ascii_decimal_unaligned(ts, (tm1.tm_year + 1900));
+ *ts++ = SYSLOG_DELIMITER;
+ /* Month */
+ clib_memcpy(ts, months[tm1.tm_mon], 4);
+ ts += 4; /* DELIMITER taken care */
+ /* day */
+ ts += u16_to_ascii_decimal_unaligned(ts, tm1.tm_mday);
+ *ts++ = SYSLOG_DELIMITER;
+ /* hours */
+ ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_hour, 2);
+ *ts++ = ':';
+ /* minutes */
+ ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_min, 2);
+ *ts++ = ':';
+ /* seconds */
+ ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_sec, 2);
+ return ts - temp;
+}
+
+/* Ensure that the order of the below array matches with
+ * syslog_service_type enum
+ */
+static char *syslog_service_string[] = { "NAT44", "DSLITE" };
+
+/* Ensure that the order of below array matches with
+ * syslog_event_type_t enum
+ */
+typedef struct {
+ char *event_name;
+ int name_length;
+} syslog_event_description_type;
+
+const static syslog_event_description_type sys_log_event[] = {
+ { "UserbasedA", 10 }, /* yes, 10 is strlen of "UserbasedA" */
+ { "UserbasedW", 10 },
+ { "SessionbasedA", 13 },
+ { "SessionbasedW", 13 },
+ { "SessionbasedAD", 14 },
+ { "SessionbasedWD", 14 },
+ { "Portblockrunout", 15 },
+ { "TCPseqmismatch", 14},
+ { "Invalid", 7 }
+};
+
+inline static int syslog_fill_header(const cnat_syslog_logging_info_t *log_info,
+ syslog_service_type_t s_type)
+{
+ /* Forms the syslog header and returns the lenght
+ * Assumes that header has sufficient space
+ */
+
+ /* Sample header (as agreed for China Telecom requirements --
+ * <134> 1 2011 May 31 10:30:45 192.168.2.3 - - NAT44 -
+ */
+
+ unsigned char *temp, *header;
+ int count;
+ temp = header = (unsigned char *)
+ &(log_info->current_logging_context->packet_data[CNAT_NFV9_HDR_OFFSET]);
+ *temp++ = '<';
+ temp += byte_to_ascii_decimal_unaligned(temp,
+ log_info->header_priority);
+ *temp++ = '>';
+ *temp++ = SYSLOG_DELIMITER;
+ *temp++ = '1'; /* Syslog version -- always set to 1 */
+ *temp++ = SYSLOG_DELIMITER;
+ temp += syslog_get_timestamp(temp);
+ *temp++ = SYSLOG_DELIMITER;
+ count = strlen(log_info->header_hostname);
+ clib_memcpy(temp, log_info->header_hostname, count);
+ temp += count;
+ *temp++ = SYSLOG_DELIMITER;
+ *temp++ = SYSLOG_FIELD_ABSENT; /* App name - nil value */
+ *temp++ = SYSLOG_DELIMITER;
+ *temp++ = SYSLOG_FIELD_ABSENT; /* Proc ID - nil value for now */
+ *temp++ = SYSLOG_DELIMITER;
+ /* Now the msg id */
+ count = strlen(syslog_service_string[s_type]);
+ clib_memcpy(temp, syslog_service_string[s_type], count);
+ temp += count;
+ *temp++ = SYSLOG_DELIMITER;
+ *temp++ = SYSLOG_FIELD_ABSENT; /* No structured elements */
+ *temp++ = SYSLOG_DELIMITER;
+#ifdef SHOW_SYSLOG_TIMESTAMP
+ printf("\nSysLog TS: %s : Length %d", header, temp - header);
+#endif /* SHOW_SYSLOG_TIMESTAMP */
+ return temp-header;
+}
+
+extern void cnat_logging_init();
+
+/* one time call at the beginning */
+void cnat_syslog_logging_init()
+{
+ if(PREDICT_TRUE(cnat_syslog_global_info.cnat_syslog_init_done))
+ return; /* Already done */
+
+ cnat_logging_init();
+ cnat_syslog_global_info.cnat_syslog_disp_node_index =
+ spp_lookup_node_index(PLATFORM_SYSLOG_DISP_NODE_IDX);
+ ASSERT(cnat_syslog_global_info.cnat_syslog_disp_node_index != (u16)~0);
+
+ cnat_syslog_global_info.cnat_syslog_init_done = 1;
+}
+
+/*
+ * edt: * * cnat_syslog_create_logging_context
+ *
+ * Tries to create a logging context with packet buffer
+ * to send a new logging packet
+ *
+ * Argument: cnat_syslog_logging_info_t *logging_info
+ * structure that contains the logging info and will store
+ * the packet context as well.
+ */
+inline
+void cnat_syslog_create_logging_context (
+ cnat_syslog_logging_info_t *logging_info,
+ syslog_service_type_t s_type)
+{
+ spp_ctx_t *ctx;
+
+ /*
+ * If queued_logging_context_index is non-EMPTY, we already have a logging
+ * packet queued to be sent. First try sending this before allocating
+ * a new context. We can have only one active packet context per
+ * logging_info structure
+ */
+
+ if (PREDICT_FALSE(logging_info->queued_logging_context != NULL)) {
+ cnat_syslog_send_queued_pkt(logging_info);
+ /*
+ * If we cannot still send the queued pkt, just return
+ * Downstream Constipation count would have increased anyway
+ */
+ if (logging_info->queued_logging_context != NULL) {
+ cnat_syslog_global_counter.logging_context_creation_deferred_count++;
+ return;
+ }
+ }
+
+ /*
+ * If no context can be allocated, return silently
+ * calling routine will handle updating the error counters
+ */
+ if (spp_ctx_alloc(&ctx, 1) < 1) {
+ cnat_syslog_global_counter.logging_context_creation_fail_count++;
+ SYSLOG_DEBUG_PRINTF1("\nCould not allocate ctx for syslog");
+ return;
+ }
+
+ // Allocate packet buffer (used for AVSM currently)
+ PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, 0);
+
+ logging_info->current_logging_context = ctx;
+
+ PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, NODE_LOGGING);
+
+ ctx->flags = SPP_CTX_END_OF_PACKET;
+ ctx->next_ctx_this_packet = (spp_ctx_t*) SPP_CTX_NO_NEXT_CTX;
+ ctx->current_header = &ctx->packet_data[CNAT_NFV9_HDR_OFFSET];
+
+ logging_info->pkt_length = syslog_fill_header(logging_info, s_type);
+ logging_info->pkt_length += (CNAT_NFV9_HDR_OFFSET -
+ CNAT_NFV9_IP_HDR_OFFSET);
+ logging_info->current_logging_context_timestamp =
+ cnat_get_sys_up_time_in_ms();
+
+}
+
+inline static int u16_to_ascii_hex_unaligned(
+ unsigned char *ptr, u16 num)
+{
+ unsigned char nibble, *temp;
+ int no_leading_zeros = 0;
+ temp = ptr;
+ nibble = (num >> 12);
+ if(nibble) {
+ *temp++ = hex_numbers_single_digit[nibble];
+ no_leading_zeros = 1;
+ }
+
+ nibble = (num >> 8) & 0xF;
+ if(nibble || no_leading_zeros) {
+ *temp++ = hex_numbers_single_digit[nibble];
+ no_leading_zeros = 1;
+ }
+
+ nibble = (num >> 4) & 0xF;
+ if(nibble || no_leading_zeros) {
+ *temp++ = hex_numbers_single_digit[nibble];
+ }
+
+ *temp++ = hex_numbers_single_digit[num & 0xF];
+
+ return temp-ptr;
+}
+
+inline static int ipv6_int_2_str(u32 ipv6[], unsigned char *ipv6_str)
+{
+/* DC stands for Double Colon.
+ * Refer http://tools.ietf.org/html/rfc5952 for
+ * more details on text representations of
+ * IPV6 address
+ */
+#define DC_NOT_USED_YET 0
+#define DC_IN_USE 1 /* Zeros are skipped */
+#define DC_ALREADY_USED 2 /* Cannot skip zeros anymore */
+ int i;
+ u16 *ipv6_temp = (u16 *)ipv6;
+ unsigned char *temp = ipv6_str;
+ int double_colon = DC_NOT_USED_YET;
+ for(i = 0; i < 7; i++) {
+ if(ipv6_temp[i]) {
+ ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[i]);
+ *ipv6_str++ = ':';
+ if(double_colon == DC_IN_USE) { /* Cannot use DC anymore */
+ double_colon = DC_ALREADY_USED;
+ }
+ } else {
+ if(double_colon == DC_IN_USE) {
+ /* Skip this zero as well */
+ continue;
+ } else if((ipv6_temp[i+1])
+ /* DC makes sense if there is more than one contiguous zero */
+ || (double_colon != DC_NOT_USED_YET)) {
+ ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str,
+ ipv6_temp[i]);
+ *ipv6_str++ = ':';
+ } else { /* Start using DC */
+ *ipv6_str++ = ':'; /* The 2nd colon */
+ double_colon = DC_IN_USE;
+ }
+ }
+ }
+ if(ipv6_temp[7]) {
+ ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[7]);
+ } else if(double_colon != DC_IN_USE) {
+ *ipv6_str++ = '0';
+ }
+ *ipv6_str = 0;
+
+ return ipv6_str - temp;
+}
+
+/* insert syslog record for nat44 */
+
+void cnat_syslog_insert_nat44_record(
+ cnat_syslog_logging_info_t *log_info,
+ cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap,
+ cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type)
+{
+ /* This record should like this -
+ * [EventName <L4> <Original Source IP> <Inside VRF Name>
+ * <Original Source IPv6> < Translated Source IP> <Original Port>
+ * <Translated First Source Port> <Translated Last Source Port>
+ * <Destination ip address> <destination port>]
+ */
+ u32 original_source = db->in2out_key.k.ipv4;
+ u32 translated_ip = db->out2in_key.k.ipv4;
+ cnat_user_db_entry_t *udb = cnat_user_db + db->user_index;
+ unsigned char *temp, *record;
+ u32 network_order_ipv6[4];
+
+ SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__);
+ temp = record = &(log_info->current_logging_context->packet_data[
+ CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
+
+ if (PREDICT_FALSE(!udb)) {
+ SYSLOG_DEBUG_PRINTF1("\nnull udb!");
+ return;
+ }
+
+ /* Now we point to the location where record needs to be inserted */
+ *record++ = '['; /* Open the record */
+
+ /* Copy the record type */
+ clib_memcpy(record, sys_log_event[e_type].event_name,
+ sys_log_event[e_type].name_length);
+ record += sys_log_event[e_type].name_length;
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the Protocol type */
+ if(PREDICT_FALSE(
+ e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
+ e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
+ u16 my_proto_mask;
+ my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK;
+ if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
+ *record++ = '6';
+ } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
+ *record++ = '1';
+ *record++ = '7';
+ } else if(PREDICT_TRUE(my_proto_mask == CNAT_ICMP)) {
+ *record++ = '1';
+ } else { /* Default, assume GRE (for PPTP) */
+ *record++ = '4';
+ *record++ = '7';
+ }
+ } else {
+ *record++ = SYSLOG_FIELD_ABSENT;
+ }
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the Original Source IP */
+ record += copy_ipv4_addr(record, original_source);
+ *record++ = SYSLOG_DELIMITER;
+
+ /* copy configured VRF NAME */
+ clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
+ record += log_info->vrf_name_len;
+ *record++ = SYSLOG_DELIMITER;
+
+ /* No IPV6 source address for nat44 */
+ *record++ = SYSLOG_FIELD_ABSENT;
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the translated IP address */
+ record += copy_ipv4_addr(record, translated_ip);
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the Original port */
+ if(e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
+ e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) {
+ record += u16_to_ascii_decimal_unaligned(
+ record, db->in2out_key.k.port);
+ } else {
+ *record++ = SYSLOG_FIELD_ABSENT;
+ }
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the start outside port */
+ record += u16_to_ascii_decimal_unaligned(record, bulk_alloc);
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the last outside port */
+ if(e_type == userbased_assign || e_type == userbased_withdraw) {
+ record += u16_to_ascii_decimal_unaligned(record,
+ (bulk_alloc + BULKSIZE_FROM_VRFMAP(vrfmap) - 1));
+ } else {
+ *record++ = SYSLOG_FIELD_ABSENT;
+ }
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy destination ip and port in case for DBL*/
+ if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
+ if(PREDICT_TRUE(sdb == NULL)) {
+ record += copy_ipv4_addr(record,db->dst_ipv4);
+ *record++ = SYSLOG_DELIMITER;
+ record += u16_to_ascii_decimal_unaligned(record, db->dst_port);
+ } else {
+ record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4);
+ *record++ = SYSLOG_DELIMITER;
+ record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port);
+ }
+ } else {
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+ *record++ = '-';
+ }
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = ']'; /* End of the reocrd */
+
+ log_info->pkt_length += record - temp;
+}
+
+void cnat_syslog_insert_record(
+ cnat_syslog_logging_info_t *log_info,
+ cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry,
+ cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type)
+{
+ /* This record should like this -
+ * [EventName <L4> <Original Source IP> <Inside VRF Name>
+ * <Original Source IPv6> < Translated Source IP> <Original Port>
+ * <Translated First Source Port> <Translated Last Source Port>
+ * <Destination ip address> <destination port>]
+ */
+ u32 original_source = db->in2out_key.k.ipv4;
+ u32 translated_ip = db->out2in_key.k.ipv4;
+ cnat_user_db_entry_t *udb = cnat_user_db + db->user_index;
+ unsigned char *temp, *record;
+ u32 network_order_ipv6[4];
+
+ temp = record = &(log_info->current_logging_context->packet_data[
+ CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
+
+ if (PREDICT_FALSE(!udb)) {
+ SYSLOG_DEBUG_PRINTF1("\nnull udb!");
+ return;
+ }
+
+ /* Now we point to the location where record needs to be inserted */
+ *record++ = '['; /* Open the record */
+
+ /* Copy the record type */
+ clib_memcpy(record, sys_log_event[e_type].event_name,
+ sys_log_event[e_type].name_length);
+ record += sys_log_event[e_type].name_length;
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the Protocol type */
+ if(PREDICT_FALSE(
+ e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
+ e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
+ u16 my_proto_mask;
+ my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK;
+ if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
+ *record++ = '6';
+ } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
+ *record++ = '1';
+ *record++ = '7';
+ } else {
+ *record++ = '1';
+ }
+ } else {
+ *record++ = SYSLOG_FIELD_ABSENT;
+ }
+
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the Original Source IP */
+#ifdef DSLITE_USER_IPV4
+ record += copy_ipv4_addr(record, original_source);
+#else
+ /*
+ * Do not include inside ipv4 address for B4 element level port limiting
+ */
+ *record++ = SYSLOG_FIELD_ABSENT;
+#endif
+ *record++ = SYSLOG_DELIMITER;
+
+ /* copy configured VRF NAME */
+ clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
+ record += log_info->vrf_name_len;
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the IPV6 source address */
+ /* CSCtt16960 Fix. */
+ network_order_ipv6[0] = htonl(udb->ipv6[0]);
+ network_order_ipv6[1] = htonl(udb->ipv6[1]);
+ network_order_ipv6[2] = htonl(udb->ipv6[2]);
+ network_order_ipv6[3] = htonl(udb->ipv6[3]);
+
+ inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN);
+ record += strlen(record);
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the translated IP address */
+ record += copy_ipv4_addr(record, translated_ip);
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the Original port */
+ if(e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
+ e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) {
+ record += u16_to_ascii_decimal_unaligned(
+ record, db->in2out_key.k.port);
+ } else {
+ *record++ = SYSLOG_FIELD_ABSENT;
+ }
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the start outside port */
+ record += u16_to_ascii_decimal_unaligned(record, bulk_alloc);
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the last outside port */
+ if(e_type == userbased_assign || e_type == userbased_withdraw) {
+ record += u16_to_ascii_decimal_unaligned(record,
+ (bulk_alloc + BULKSIZE_FROM_VRFMAP(dslite_entry) - 1));
+ } else {
+ *record++ = SYSLOG_FIELD_ABSENT;
+ }
+ *record++ = SYSLOG_DELIMITER;
+
+ if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
+ if(sdb == NULL) {
+ record += copy_ipv4_addr(record, db->dst_ipv4);
+ *record++ = SYSLOG_DELIMITER;
+ record += u16_to_ascii_decimal_unaligned(record, db->dst_port);
+ } else {
+ record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4);
+ *record++ = SYSLOG_DELIMITER;
+ record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port);
+ }
+ } else {
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+ *record++ = '-';
+ }
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = ']'; /* End of the reocrd */
+
+ log_info->pkt_length += record - temp;
+}
+
+#define SYSLOG_PRECHECK(entry, s_type) \
+ if(PREDICT_FALSE((entry)->syslog_logging_index == EMPTY)) { \
+ SYSLOG_DEBUG_PRINTF1("\n1. Log Mapping failed") \
+ return; \
+ } \
+ logging_info = \
+ cnat_syslog_logging_info_pool + (entry)->syslog_logging_index; \
+ if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \
+ cnat_syslog_create_logging_context(logging_info, s_type); \
+ if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \
+ SYSLOG_DEBUG_PRINTF1("\n2. Log Mapping failed") \
+ return; \
+ } \
+ }
+
+void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db,
+ cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb
+#ifndef NO_BULK_LOGGING
+ , int bulk_alloc
+#endif
+ )
+{
+ cnat_syslog_logging_info_t *logging_info = 0;
+ syslog_event_type_t e_type;
+ int start_port;
+
+ SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__);
+ SYSLOG_PRECHECK(vrfmap, NAT44)
+
+#ifndef NO_BULK_LOGGING
+ if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
+ e_type = userbased_assign;
+ start_port = bulk_alloc;
+ } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
+ return; /* No logging required.. bulk port usage */
+ }
+ else { /* Individual logging .. fall back to old method */
+#endif
+ if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) {
+ e_type = sessionbased_assignD;
+ } else {
+ e_type = sessionbased_assign;
+ }
+ start_port = db->out2in_key.k.port;
+#ifndef NO_BULK_LOGGING
+ }
+#endif
+
+ cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb,
+ start_port, e_type);
+
+ /*
+ * If we have exceeded the packet length, let us send the
+ * packet now. There is buffer of additional bytes beyond
+ * max_pkt_length to ensure that the last add/delete record
+ * can be stored safely.
+ */
+
+ if (PREDICT_FALSE(logging_info->pkt_length >
+ logging_info->max_length_minus_max_record_size)) {
+ cnat_syslog_send_pkt(logging_info);
+ }
+}
+
+void cnat_syslog_ds_lite_mapping_create(cnat_main_db_entry_t *db,
+ dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb
+#ifndef NO_BULK_LOGGING
+ , int bulk_alloc
+#endif
+ )
+{
+ cnat_syslog_logging_info_t *logging_info = 0;
+ syslog_event_type_t e_type;
+ int start_port;
+
+ SYSLOG_PRECHECK(dslite_entry, DSLite)
+
+#ifndef NO_BULK_LOGGING
+ if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
+ e_type = userbased_assign;
+ start_port = bulk_alloc;
+ } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
+ return; /* No logging required.. bulk port usage */
+ }
+ else { /* Individual logging .. fall back to old method */
+#endif
+ if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) {
+ e_type = sessionbased_assignD;
+ } else {
+ e_type = sessionbased_assign;
+ }
+ start_port = db->out2in_key.k.port;
+#ifndef NO_BULK_LOGGING
+ }
+#endif
+
+ cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb,
+ start_port, e_type);
+
+ /*
+ * If we have exceeded the packet length, let us send the
+ * packet now. There is buffer of additional bytes beyond
+ * max_pkt_length to ensure that the last add/delete record
+ * can be stored safely.
+ */
+
+ if (PREDICT_FALSE(logging_info->pkt_length >
+ logging_info->max_length_minus_max_record_size)) {
+ cnat_syslog_send_pkt(logging_info);
+ }
+}
+
+void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db,
+ cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb
+#ifndef NO_BULK_LOGGING
+ , int bulk_alloc
+#endif
+ )
+{
+ cnat_syslog_logging_info_t *logging_info = 0;
+ syslog_event_type_t e_type;
+ int start_port;
+
+ SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__);
+ SYSLOG_PRECHECK(vrfmap, NAT44)
+
+#ifndef NO_BULK_LOGGING
+ if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
+ e_type = userbased_withdraw;
+ start_port = bulk_alloc;
+ } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
+ return; /* No logging required.. bulk port usage */
+ }
+ else { /* Individual logging .. fall back to old method */
+#endif
+ if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) {
+ e_type = sessionbased_withdrawD;
+ } else {
+ e_type = sessionbased_withdraw;
+ }
+ start_port = db->out2in_key.k.port;
+#ifndef NO_BULK_LOGGING
+ }
+#endif
+ cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb,
+ start_port, e_type);
+ /*
+ * If we have exceeded the packet length, let us send the
+ * packet now. There is buffer of additional bytes beyond
+ * max_pkt_length to ensure that the last add/delete record
+ * can be stored safely.
+ */
+ if (PREDICT_FALSE(logging_info->pkt_length >
+ logging_info->max_length_minus_max_record_size)) {
+ cnat_syslog_send_pkt(logging_info);
+ }
+}
+
+void cnat_syslog_ds_lite_mapping_delete(cnat_main_db_entry_t *db,
+ dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb
+#ifndef NO_BULK_LOGGING
+ , int bulk_alloc
+#endif
+ )
+{
+ cnat_syslog_logging_info_t *logging_info = 0;
+ syslog_event_type_t e_type;
+ int start_port;
+
+ SYSLOG_PRECHECK(dslite_entry, DSLite)
+
+#ifndef NO_BULK_LOGGING
+ if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
+ e_type = userbased_withdraw;
+ start_port = bulk_alloc;
+ } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
+ return; /* No logging required.. bulk port usage */
+ }
+ else { /* Individual logging .. fall back to old method */
+#endif
+ if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) {
+ e_type = sessionbased_withdrawD;
+ } else {
+ e_type = sessionbased_withdraw;
+ }
+ start_port = db->out2in_key.k.port;
+#ifndef NO_BULK_LOGGING
+ }
+#endif
+ cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb,
+ start_port, e_type);
+
+ /*
+ * If we have exceeded the packet length, let us send the
+ * packet now. There is buffer of additional bytes beyond
+ * max_pkt_length to ensure that the last add/delete record
+ * can be stored safely.
+ */
+
+ if (PREDICT_FALSE(logging_info->pkt_length >
+ logging_info->max_length_minus_max_record_size)) {
+ cnat_syslog_send_pkt(logging_info);
+ }
+}
+
+void cnat_syslog_dslite_insert_port_exceeded(
+ cnat_syslog_logging_info_t *log_info,
+ dslite_key_t * key)
+{
+ /* This record should like this -
+ * [Portblockrunout <L4> <Original Source IP> <Inside VRF Name>
+ * <Original Source IPv6> - <Original Port> - - - -]
+ */
+ u32 network_order_ipv6[4];
+ unsigned char *temp, *record;
+
+ temp = record = &(log_info->current_logging_context->packet_data[
+ CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
+
+ /* Now we point to the location where record needs to be inserted */
+ *record++ = '['; /* Open the record */
+
+ /* Copy the record type */
+ clib_memcpy(record, sys_log_event[port_block_runout].event_name,
+ sys_log_event[port_block_runout].name_length);
+ record += sys_log_event[port_block_runout].name_length;
+ *record++ = SYSLOG_DELIMITER;
+
+ u16 my_proto_mask;
+ my_proto_mask = key->ipv4_key.k.vrf & CNAT_PRO_MASK;
+ if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
+ *record++ = '6';
+ } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
+ *record++ = '1';
+ *record++ = '7';
+ } else {
+ *record++ = '1';
+ }
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the Original Source IP */
+ record += copy_ipv4_addr(record, key->ipv4_key.k.ipv4);
+ *record++ = SYSLOG_DELIMITER;
+
+ /* copy configured VRF NAME */
+ clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
+ record += log_info->vrf_name_len;
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the IPV6 source address */
+ network_order_ipv6[0] = htonl(key->ipv6[0]);
+ network_order_ipv6[1] = htonl(key->ipv6[1]);
+ network_order_ipv6[2] = htonl(key->ipv6[2]);
+ network_order_ipv6[3] = htonl(key->ipv6[3]);
+
+ inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN);
+ record += strlen(record);
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = SYSLOG_FIELD_ABSENT; /* No translated source ip */
+ *record++ = SYSLOG_DELIMITER;
+
+ record += u16_to_ascii_decimal_unaligned(
+ record, key->ipv4_key.k.port);
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = SYSLOG_FIELD_ABSENT; /* No translated start port */
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = SYSLOG_FIELD_ABSENT; /* No translated end port */
+ *record++ = SYSLOG_DELIMITER;
+
+ /*No Destination Info*/
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = ']'; /* End of the reocrd */
+
+ log_info->pkt_length += record - temp;
+}
+
+void cnat_syslog_ds_lite_port_limit_exceeded(
+ dslite_key_t * key,
+ dslite_table_entry_t *dslite_entry)
+{
+ cnat_syslog_logging_info_t *logging_info = 0;
+
+ SYSLOG_PRECHECK(dslite_entry, DSLite)
+
+ cnat_syslog_dslite_insert_port_exceeded(logging_info, key);
+
+ /*
+ * If we have exceeded the packet length, let us send the
+ * packet now. There is buffer of additional bytes beyond
+ * max_pkt_length to ensure that the last add/delete record
+ * can be stored safely.
+ */
+
+ if (PREDICT_FALSE(logging_info->pkt_length >
+ logging_info->max_length_minus_max_record_size)) {
+ cnat_syslog_send_pkt(logging_info);
+ }
+}
+
+void cnat_syslog_nat44_insert_port_exceeded(
+ cnat_syslog_logging_info_t *log_info,
+ cnat_key_t * key)
+{
+ /* This record should like this -
+ * [Portblockrunout <L4> <Original Source IP> <Inside VRF Name>
+ * - - <Original Port> - - - -]
+ */
+ unsigned char *temp, *record;
+
+ temp = record = &(log_info->current_logging_context->packet_data[
+ CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
+
+ /* Now we point to the location where record needs to be inserted */
+ *record++ = '['; /* Open the record */
+
+ /* Copy the record type */
+ clib_memcpy(record, sys_log_event[port_block_runout].event_name,
+ sys_log_event[port_block_runout].name_length);
+ record += sys_log_event[port_block_runout].name_length;
+ *record++ = SYSLOG_DELIMITER;
+
+ u16 my_proto_mask;
+ my_proto_mask = key->k.vrf & CNAT_PRO_MASK;
+ if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
+ *record++ = '6';
+ } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
+ *record++ = '1';
+ *record++ = '7';
+ } else {
+ *record++ = '1';
+ }
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the Original Source IP */
+ record += copy_ipv4_addr(record, key->k.ipv4);
+ *record++ = SYSLOG_DELIMITER;
+
+ /* copy configured VRF NAME */
+ clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
+ record += log_info->vrf_name_len;
+ *record++ = SYSLOG_DELIMITER;
+
+ /* No IPV6 source address for nat44 */
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = '-'; /* No translated source ip */
+ *record++ = SYSLOG_DELIMITER;
+
+ record += u16_to_ascii_decimal_unaligned(
+ record, key->k.port);
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = '-'; /* No translated start port */
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = '-'; /* No translated end port */
+ *record++ = SYSLOG_DELIMITER;
+
+ /*No Destination Info*/
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = ']'; /* End of the reocrd */
+
+ log_info->pkt_length += record - temp;
+}
+
+void cnat_syslog_nat44_port_limit_exceeded(
+ cnat_key_t * key,
+ cnat_vrfmap_t *vrfmap)
+{
+ cnat_syslog_logging_info_t *logging_info = 0;
+
+ SYSLOG_PRECHECK(vrfmap, NAT44)
+
+ cnat_syslog_nat44_insert_port_exceeded(logging_info, key);
+
+ /*
+ * If we have exceeded the packet length, let us send the
+ * packet now. There is buffer of additional bytes beyond
+ * max_pkt_length to ensure that the last add/delete record
+ * can be stored safely.
+ */
+
+ if (PREDICT_FALSE(logging_info->pkt_length >
+ logging_info->max_length_minus_max_record_size)) {
+ cnat_syslog_send_pkt(logging_info);
+ }
+}
+
+void cnat_syslog_nat44_insert_tcp_seq_mismatch(
+ cnat_syslog_logging_info_t *log_info,
+ cnat_main_db_entry_t *db)
+{
+ /* This record should like this -
+ * [TCPseqmismatch <L4> <Original Source IP> <Inside VRF Name>
+ * - <Translated Source IP> <Original Port> <Translated Source Port> - - -]
+ */
+ unsigned char *temp, *record;
+
+ temp = record = &(log_info->current_logging_context->packet_data[
+ CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
+
+ /* Now we point to the location where record needs to be inserted */
+ *record++ = '['; /* Open the record */
+
+ /* Copy the record type */
+ clib_memcpy(record, sys_log_event[tcp_seq_mismatch].event_name,
+ sys_log_event[tcp_seq_mismatch].name_length);
+ record += sys_log_event[tcp_seq_mismatch].name_length;
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Next field is TCP */
+ *record++ = '6';
+ *record++ = SYSLOG_DELIMITER;
+
+ /* Copy the Original Source IP */
+ record += copy_ipv4_addr(record, db->in2out_key.k.ipv4);
+ *record++ = SYSLOG_DELIMITER;
+
+ /* copy configured VRF NAME */
+ clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
+ record += log_info->vrf_name_len;
+ *record++ = SYSLOG_DELIMITER;
+
+ /* No IPV6 source address for nat44 */
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+
+ record += copy_ipv4_addr(record, db->out2in_key.k.ipv4);
+ *record++ = SYSLOG_DELIMITER;
+
+ record += u16_to_ascii_decimal_unaligned(
+ record, db->in2out_key.k.port);
+ *record++ = SYSLOG_DELIMITER;
+
+ record += u16_to_ascii_decimal_unaligned(
+ record, db->out2in_key.k.port);
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = '-'; /* No translated end port */
+ *record++ = SYSLOG_DELIMITER;
+
+ /*No Destination Info*/
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+ *record++ = '-';
+ *record++ = SYSLOG_DELIMITER;
+
+ *record++ = ']'; /* End of the reocrd */
+
+ log_info->pkt_length += record - temp;
+}
+
+void cnat_syslog_nat44_tcp_seq_mismatch(
+ cnat_main_db_entry_t *db,
+ cnat_vrfmap_t *vrfmap)
+{
+ cnat_syslog_logging_info_t *logging_info = 0;
+
+ SYSLOG_PRECHECK(vrfmap, NAT44)
+
+ cnat_syslog_nat44_insert_tcp_seq_mismatch(logging_info, db);
+
+ /*
+ * If we have exceeded the packet length, let us send the
+ * packet now. There is buffer of additional bytes beyond
+ * max_pkt_length to ensure that the last add/delete record
+ * can be stored safely.
+ */
+
+ if (PREDICT_FALSE(logging_info->pkt_length >
+ logging_info->max_length_minus_max_record_size)) {
+ cnat_syslog_send_pkt(logging_info);
+ }
+}
+#endif