Initial commit of vpp code.
[vpp.git] / vnet / vnet / vcgn / spp_platform_trace_log.c
1 /*
2  *------------------------------------------------------------------
3  * spp_platform_trace_log.c 
4  *
5  * Copyright (c) 2008-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 <vlib/vlib.h>
21 #include <stdio.h>
22 #include <vppinfra/vec.h>
23 #include <vppinfra/bitmap.h>
24 #include <vppinfra/hash.h>
25 #include <vppinfra/pool.h>
26 #include <vppinfra/clib.h>
27 #include <vlib/main.h>
28
29 #include "tcp_header_definitions.h"
30 #include "platform_common.h"
31 #include "spp_platform_trace_log.h"
32
33 #define WORD_SIZE sizeof(u32)
34
35 int temperature_read_blocked = 1;
36
37 spp_cnat_logger_tbl_t spp_cnat_logger_table[] =
38 {
39   { CNAT_ERROR_SUCCESS,
40     3,
41     0,
42     {"i-vrf",
43     "ipv4 addr",
44      "port"}
45   },
46   { CNAT_NO_CONFIG_ERROR,
47     3,
48     180,
49     {"i-vrf",
50     "ipv4 addr",
51      "port"}
52   },
53   { CNAT_NO_VRF_RUN_ERROR,
54     3,
55     180,
56     {"i-vrf",
57     "ipv4 addr",
58      "port"}
59   },
60   { CNAT_NO_POOL_FOR_ANY_ERROR,
61     3,
62     180,
63     {"i-vrf",
64     "ipv4 addr",
65      "port"}
66   },
67   { CNAT_NO_PORT_FOR_ANY_ERROR,
68     3,
69     60,
70     {"i-vrf",
71     "ipv4 addr",
72      "port"}
73   },
74   { CNAT_BAD_INUSE_ANY_ERROR,
75     3,
76     60,
77     {"i-vrf",
78     "ipv4 addr",
79      "port"}
80   },
81   { CNAT_NOT_FOUND_ANY_ERROR,
82     3,
83     60,
84     {"i-vrf",
85     "ipv4 addr",
86      "port"}
87   },
88   { CNAT_INV_PORT_FOR_DIRECT_ERROR,
89     3,
90     60,
91     {"i-vrf",
92     "ipv4 addr",
93      "port"}
94   },
95   { CNAT_BAD_INUSE_DIRECT_ERROR,
96     3,
97     1,
98     {"i-vrf",
99     "ipv4 addr",
100      "port"}
101   },
102   { CNAT_NOT_FOUND_DIRECT_ERROR,
103     3,
104     1,
105     {"i-vrf",
106     "ipv4 addr",
107      "port"}
108   },
109   { CNAT_OUT_OF_PORT_LIMIT_ERROR,
110     3,
111     60,
112     {"i-vrf",
113     "ipv4 addr",
114      "port"}
115   },
116   { CNAT_MAIN_DB_CREATE_ERROR, 
117     0,
118     30,
119     {""}
120   },
121   { CNAT_LOOKUP_ERROR,
122     1,
123     30,
124     {"Type"}
125   },
126   { CNAT_INDEX_MISMATCH_ERROR,
127     2,
128     30,
129     {"in2out_index",
130      "out2in_index"}
131   },
132   { CNAT_PACKET_DROP_ERROR,
133     3,
134     15,
135     {"i-vrf",
136     "ipv4 addr",
137      "port"}
138   },
139   { CNAT_INV_UNUSED_USR_INDEX,
140     1,
141     10,
142     {"invalid/unused user index"}
143   },
144   { CNAT_INVALID_VRFMAP_INDEX,
145     0,
146     60,
147     {""}
148   },
149   { CNAT_USER_OUT_OF_PORTS,
150     2,
151     1800,
152     {"i-vrf",
153      "ipv4 addr"}
154   },
155   { CNAT_EXT_PORT_THRESH_EXCEEDED,
156     2,
157     180,
158     {"i-vrf",
159      "ipv4 address"}
160   },
161   { CNAT_EXT_PORT_THRESH_NORMAL,
162     2,
163     180,
164     {"vrf",
165      "ipv4 address"}
166   },
167   { CNAT_NO_EXT_PORT_AVAILABLE,
168     0,
169     1,
170     {"",}
171   },
172   { CNAT_SESSION_THRESH_EXCEEDED,
173     2,
174     1800, 
175     {"vrf",
176      "ipv4 address"}
177   },
178   { CNAT_SESSION_THRESH_NORMAL,
179     2,
180     30, /* changed to 30 */
181     {"vrf",
182      "ipv4 address"}
183   },
184   { WQE_ALLOCATION_ERROR,
185     0,
186     180, /* changed to 180 */
187     {""}
188   },
189   { ERROR_PKT_DROPPED,
190     2,
191     60, /* changed to 60 */
192     {"spi-port",
193      "error-code"}
194   },
195   { SYSMGR_PD_KEY_CREATION_ERROR,
196     0,
197     30,
198     {""}
199   },
200   { SYSMGR_PD_SHMEM_ID_ERROR,
201     0,
202     1,
203     {""}
204   },
205   { SYSMGR_PD_SHMEM_ATTACH_ERROR,
206     0,
207     1,
208     {""}
209   },
210   { OCTEON_CKHUM_SKIPPED,
211     2,
212     60, /* changed to 60 */
213     {"version",
214      "protocol"}
215   },
216   { PK0_SEND_STATUS,
217     1,
218     15,
219     {"status"}
220   },
221   { CMD_BUF_ALLOC_ERR,
222     0,
223     60,
224     {""}
225   },
226   { SPP_CTX_ALLOC_FAILED,
227     1,
228     300, /* every 5 min  */
229     {"node"}
230   },
231   { SPP_MAX_DISPATCH_REACHED,
232     1,
233     60,
234     {"node"}
235   },
236   { HA_SIGCHILD_RECV,
237     3,
238     1,
239     {"pid",
240     "uid",
241      "signal",}
242   },
243   { SIGACTION_ERR,
244     0,
245     1,
246     {""}
247   },
248   { HA_INVALID_SEQ_OR_CONFIG_OR_TYPE,
249     2,
250     10,
251     {"seq-id or config option",
252      "Type"}
253   },
254   { NODE_CREATION_ERROR,
255     1,
256     1,
257     {"node"}
258   },
259
260   { CNAT_CLI_INVALID_INPUT,
261       4,
262       0,
263     {"Error Type",
264       "Passed",
265       "Expected",
266      "Type"}
267   },
268   { CNAT_DUMMY_HANDLER_HIT,
269       1,
270       0,
271     {"Handler"}
272   },
273   { CNAT_CONFIG_ERROR,
274       5,
275       0,
276     {"Sub code",
277       "Param 1",
278       "Param 2",
279       "Param 3",
280      "Param 4"}
281   },
282   { CNAT_NFV9_ERROR,
283       1,
284       180, /* changed to 180 */
285     {"Sub code"}
286   },
287   { CNAT_CMVX_TWSI_READ_WRITE_FAIL,
288      3,
289      180,
290     {"Operation",
291      "Location",
292      "Data"}
293   },
294   { CNAT_TEMP_SENSOR_TIMEOUT,
295       0,
296       180,
297     {""}
298   },
299   { CNAT_TEMP_SENSOR_DATA_MISMATCH,
300       2,
301       180,
302     {"Actual",
303      "Expected"}
304   },
305   { CNAT_TEMP_SENSOR_CONFIG_FAILED,
306       1,
307       180,
308     {"Glik"}
309   },
310   { HA_APP_NOT_RESPONDING,
311       2,
312       180,
313     {"CPU",
314      "Core"}
315   },
316   { HA_DATA_PATH_TEST_FAILED,
317       0,
318       30,
319     {""}
320   },
321   { CNAT_WRONG_PORT_ALLOC_TYPE,
322       3,
323       60,
324     {"i-vrf",
325       "ipv4 addr",
326      "port"}
327   },
328   { CNAT_NEW_PORT_ALLOC_ERROR,
329       3,
330       60,
331     {"i-vrf",
332       "ipv4 addr",
333      "port"}
334   },
335   { CNAT_INVALID_INDEX_TO_FREE_PORT,
336       0,
337       60,
338     {""}
339   },
340   { CNAT_DELETE_DB_ENTRY_NO_PORTMAP,
341       0,
342       60,
343     {""}
344   },
345   { CNAT_MAIN_DB_LIMIT_ERROR,
346       0,
347       180,
348     {""}
349   },
350   { CNAT_USER_DB_LIMIT_ERROR,
351       0,
352       180,
353     {""}
354   },
355   { CNAT_FRAG_DB_ERROR,
356       1,
357       180,
358     {"Type"}
359   },
360
361   { DROP_PKT_DUMP,
362     0,
363     20,
364     {""}
365   }
366 };
367
368 #define LOG_TABLE_MAX_ENTRIES \
369    (sizeof(spp_cnat_logger_table)/sizeof(spp_cnat_logger_table[0]))
370
371 u32 error_code_timestamps[LOG_TABLE_MAX_ENTRIES];
372 spp_timer_t sensor_timer;
373 spp_trace_log_global_info_t spp_trace_log_global_info;
374 spp_global_counters_t spp_global_counters;
375
376 /*
377  * Logging information structures
378  */
379 spp_trace_log_info_t spp_default_trace_log_info;
380 spp_trace_log_info_t *spp_trace_log_info_pool;
381
382 #ifdef TOBE_PORTED
383 /*
384  * The following 2 functions are temporary hacks until
385  * we have RTC support from the PD nodes
386  */
387 inline
388 u32 spp_trace_log_get_sys_up_time_in_ms (void)
389 {
390     spp_node_main_vector_t *nmv;
391     u32 sys_up_time;
392
393     nmv = spp_get_node_main_vectorized_inline();
394                     
395     sys_up_time = (u32) (nmv->ticks / nmv->ticks_per_ms);
396
397     return (sys_up_time);
398 }
399
400 inline
401 u32 spp_trace_log_get_unix_time_in_seconds (void)
402 {
403     spp_node_main_vector_t *nmv;
404     u32 unix_time;
405
406     nmv = spp_get_node_main_vectorized_inline();
407                     
408     unix_time = (u32) (nmv->ticks / nmv->ticks_per_second);
409
410     return (unix_time);
411 }
412
413 /*
414  * edt: * * spp_trace_log_send_queued_pkt
415  *
416  * Tries to send a logging pkt that has been queued earlier
417  * because it could not be sent due to downstream constipation
418  *
419  * Argument: spp_trace_log_info_t *trace_logging_info
420  * structure that contains the packet context
421  */
422 inline
423 void spp_trace_log_send_queued_pkt (spp_trace_log_info_t *trace_logging_info)
424 {
425     spp_node_t                  *output_node;
426
427     output_node = spp_get_nodes() + 
428         spp_trace_log_global_info.spp_trace_log_disp_node_index;
429
430     if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) {
431         /*
432          * Move the logging context to output node
433          */
434         spp_dispatch_make_node_runnable(output_node);
435         output_node->sf.ctxs[output_node->sf.nused++] = 
436             trace_logging_info->queued_logging_context;
437
438         /*
439          * Context has been queued, it will be freed after the pkt
440          * is sent.  Clear this from the logging_context_info structure
441          */
442             trace_logging_info->queued_logging_context = NULL;
443
444     } else {
445             /*
446              * Can't do much, just return, may be we can send it later
447              */
448         spp_global_counters.spp_trace_log_downstream_constipation_count++;
449     }
450 }
451
452 /*
453  * edt: * * spp_trace_log_send_pkt
454  *
455  * Tries to send a logging pkt.  If the packet cannot be sent
456  * because of rewrite_output node cannot process it, queue
457  * it temporarily and try to send it later.
458  *
459  * Argument: spp_trace_log_info_t *trace_logging_info
460  * structure that contains the packet context
461  */
462 inline
463 void spp_trace_log_send_pkt (spp_trace_log_info_t *trace_logging_info)
464 {
465     spp_node_t                  *output_node;
466
467
468     output_node = spp_get_nodes() + 
469         spp_trace_log_global_info.spp_trace_log_disp_node_index;
470
471     if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) {
472         /*
473          * Move the logging context to output node
474          */
475         spp_dispatch_make_node_runnable(output_node);
476         output_node->sf.ctxs[output_node->sf.nused++] = 
477             trace_logging_info->current_logging_context;
478
479     } else {
480         /*
481              * Queue the context into the logging_info structure,
482              * We will try to send it later.  Currently, we will
483          * restrict to only one context queued.
484              */
485         spp_global_counters.spp_trace_log_downstream_constipation_count++;
486
487             /*
488              * Attach the current logging context which is full to the
489              * queued context list in trace_logging_info structure
490              */
491             trace_logging_info->queued_logging_context =
492                     trace_logging_info->current_logging_context;
493
494             /*
495              * Whether the context is queued or not, set the current context index
496              * to EMPTY, as the earlier context can no more be used to send
497              * more logging records.
498              */
499     }
500
501     trace_logging_info->current_logging_context = NULL;
502 }
503
504 /*
505  * edt: * * spp_trace_log_send_pkt_always_success
506  *
507  * Tries to send a logging pkt.  This cannot fail due to downstream
508  * constipation because we have already checked if the rewrite_output
509  * node can accept it.
510  *
511  * Argument: spp_trace_log_info_t *trace_logging_info
512  * structure that contains the packet context
513  *
514  * Argument: spp_node_t *output_node
515  * spp_node_t structure for rewrite_output node
516  */
517 inline
518 void spp_trace_log_send_pkt_always_success (
519                          spp_trace_log_info_t *trace_logging_info,
520                          spp_node_t               *output_node)
521 {
522     /*
523      * At this point we either have a current or queued logging context
524      */
525     if (PREDICT_TRUE(trace_logging_info->current_logging_context != NULL)) { 
526
527         output_node->sf.ctxs[output_node->sf.nused++] = 
528             trace_logging_info->current_logging_context;
529
530         trace_logging_info->current_logging_context = NULL;
531     } else {
532         /*
533          * For queued logging context
534              */
535             output_node->sf.ctxs[output_node->sf.nused++] = 
536                  trace_logging_info->queued_logging_context;
537
538             trace_logging_info->queued_logging_context = NULL;
539     }
540
541     /*
542      * Move the logging context to output node
543      */
544     spp_dispatch_make_node_runnable(output_node);
545
546 }
547
548 /*
549  * edt: * * spp_create_trace_log_context
550  *
551  * Tries to create a logging context with packet buffer
552  * to send a new logging packet
553  *
554  * Argument: spp_trace_log_info_t *trace_logging_info
555  * structure that contains the nfv9 logging info and will store
556  * the packet context as well.
557  */
558 inline
559 void spp_create_trace_log_context (
560                               spp_trace_log_info_t *trace_logging_info)
561 {
562     spp_ctx_t *ctx;
563
564     /*
565      * If queued_logging_context_index is non-EMPTY, we already have a logging
566      * packet queued to be sent.  First try sending this before allocating
567      * a new context.  We can have only one active packet context per
568      * trace_logging_info structure
569      */
570     if (PREDICT_FALSE(trace_logging_info->queued_logging_context != NULL)) {
571         spp_trace_log_send_queued_pkt(trace_logging_info);
572         /*
573          * If we cannot still send the queued pkt, just return 
574          * Downstream Constipation count would have increased anyway
575          */
576         if (trace_logging_info->queued_logging_context != NULL) {
577                 spp_global_counters.spp_trace_log_context_creation_deferred_count++;
578                 return;
579         }
580     }
581
582
583     /*
584      * No context can be allocated, return silently
585      * calling routine will handle updating the error counters
586      */
587     if (spp_ctx_alloc(&ctx, 1) < 1) {
588         spp_global_counters.spp_trace_log_context_creation_fail_count++;
589             return;
590     }
591
592     trace_logging_info->current_logging_context = ctx;
593     trace_logging_info->pkt_length = 0;
594
595     trace_logging_info->current_logging_context_timestamp =
596                        spp_trace_log_get_sys_up_time_in_ms();
597
598     ctx->flags = SPP_CTX_END_OF_PACKET;
599     ctx->ru.tx.from_node = NODE_TRACE_BACKUP;
600     ctx->ru.tx.dst_ip_port_idx = EXT_TRACE_BACKUP_INDEX;
601     ctx->next_ctx_this_packet = (spp_ctx_t*) SPP_CTX_NO_NEXT_CTX;
602     ctx->current_header = &ctx->packet_data[SPP_TRACE_LOG_HDR_OFFSET];
603     ctx->current_length = 0;
604
605     trace_logging_info->log_record = 0;
606     trace_logging_info->total_record_count = 0;
607     trace_logging_info->next_data_ptr = 
608         (u8 *) &ctx->packet_data[SPP_TRACE_LOG_HDR_OFFSET];
609
610 }
611
612 /*
613  * edt: * * spp_trace_log_add_record_create
614  *
615  * Tries to create an add record to the NFV9 packet
616  *
617  * Argument: spp_trace_log_info_t *trace_logging_info
618  * structure that contains the nfv9 logging info and will store
619  * the packet context as well.
620  */
621 inline
622 void spp_trace_log_add_record_create (spp_trace_log_info_t *trace_logging_info)
623 {
624
625     trace_logging_info->log_header =
626     (spp_trace_log_hdr_t *) (trace_logging_info->next_data_ptr);
627
628     /*
629      * Initialize the number of traces recorded
630      */
631     trace_logging_info->log_header->num_traces =
632     spp_host_to_net_byte_order_32(0);
633
634
635     trace_logging_info->log_record  =
636     (spp_trace_log_t *) (trace_logging_info->log_header + 1);
637
638     /*
639      * Update the length of the total pkt 
640      */
641     trace_logging_info->pkt_length +=
642         SPP_LOG_TRACE_HEADER_LENGTH; 
643
644     /*
645      * Set the data pointer beyond the trace header field
646      */
647     trace_logging_info->next_data_ptr =
648         (u8 *) (trace_logging_info->log_header + 1);
649
650 }
651
652 /*
653  * edt: * * spp_trace_logger
654  *
655  * Tries to log  spp/cnat event/errors
656  *
657  * Argument: u8 *error_code
658  *  Error code passed
659  *
660  * Argument: optional arguments
661  */
662 void spp_trace_logger (u16 error_code, u16 num_args, u32 *arg)
663 {
664     spp_trace_log_info_t *trace_logging_info = 0; 
665     u8 i;
666
667     trace_logging_info = 
668         spp_trace_log_info_pool + 
669         spp_trace_log_global_info.spp_log_pool_index[SPP_LOG_LTRACE];
670
671     if (PREDICT_FALSE(trace_logging_info->current_logging_context == NULL)) {
672         spp_create_trace_log_context(trace_logging_info);
673
674             /*
675              * If still empty, return after increasing the count
676              */
677             if (PREDICT_FALSE(trace_logging_info->current_logging_context == NULL)) {
678                 return;
679             }
680     }
681
682     if (PREDICT_FALSE(trace_logging_info->log_record == NULL)) {
683         spp_trace_log_add_record_create(trace_logging_info);
684     }
685
686     /*
687      * We should definitely have add_record now, no need to sanitize
688      */
689     trace_logging_info->log_record->error_code = 
690                     spp_host_to_net_byte_order_16(error_code);
691     trace_logging_info->log_record->num_args = 
692                     spp_host_to_net_byte_order_16(num_args);
693
694     for (i = 0; i < num_args; i++) {
695         trace_logging_info->log_record->arg[i] = 
696                 spp_host_to_net_byte_order_32(*(arg + i));
697     }
698
699     trace_logging_info->pkt_length += SPP_TRACE_LOG_RECORD_LENGTH + WORD_SIZE*num_args;
700     trace_logging_info->current_logging_context->current_length =
701                   trace_logging_info->pkt_length;
702     trace_logging_info->total_record_count += 1;
703
704     trace_logging_info->next_data_ptr =
705         (u8 *) (trace_logging_info->next_data_ptr + WORD_SIZE + WORD_SIZE*num_args);
706
707     trace_logging_info->log_record = 
708            (spp_trace_log_t *) (trace_logging_info->next_data_ptr);
709
710     /*
711      * Initialize the number of traces recorded
712      */
713     trace_logging_info->log_header->num_traces =
714              spp_host_to_net_byte_order_32(trace_logging_info->total_record_count);
715
716
717
718     /*
719      * If we have exceeded the packet length, let us send the
720      * packet now.  There is buffer of additional bytes beyond
721      * max_pkt_length to ensure that the last add/delete record
722      * can be stored safely.
723      */
724     if (trace_logging_info->pkt_length > 
725             trace_logging_info->max_length_minus_max_record_size) {
726             spp_trace_log_send_pkt(trace_logging_info);
727     }
728 }
729
730
731 /*
732  * edt: * * spp_trace_log_timer_handler
733  *
734  * Timer handler for sending any pending NFV9 record
735  *
736  * Argument: spp_timer_t * timer_p
737  * Timer handler structure
738  */
739 inline 
740 void spp_trace_log_timer_handler (spp_timer_t * timer_p)
741 {
742     spp_node_t *output_node;
743     spp_trace_log_info_t *trace_logging_info = 0;
744     u32 current_timestamp = spp_trace_log_get_sys_up_time_in_ms();
745     i16 sf_nused;
746     
747     output_node = spp_get_nodes() + 
748                       spp_trace_log_global_info.spp_trace_log_disp_node_index;
749
750     sf_nused = output_node->sf.nused;
751
752     pool_foreach (trace_logging_info, spp_trace_log_info_pool, ({
753         /*
754          * Check if no more logging contexts can be queued
755          */
756             if (PREDICT_FALSE(sf_nused >= SPP_MAXDISPATCH)) {
757                 break;
758             }
759
760             /*
761              * If there is a current logging context and timestamp
762              * indicates it is pending for long, send it out
763              * Also if there is a queued context send it out as well
764              */
765         if (trace_logging_info->queued_logging_context ||
766             (trace_logging_info->current_logging_context &&
767                 (current_timestamp - 
768                  trace_logging_info->current_logging_context_timestamp) 
769                                                                 > 1000)) {
770             spp_trace_log_send_pkt_always_success(trace_logging_info,
771                                                     output_node);
772             sf_nused++;
773         }
774     }));
775
776     timer_p->expires =
777         spp_timer_in_n_ms_inline(1000); /* every 1 sec */
778     spp_timer_start(timer_p);
779
780 }
781 inline
782 void spp_sensor_timer_handler (spp_timer_t * timer_p)
783 {
784 #ifdef TARGET_RODDICK
785     if (!temperature_read_blocked) {
786         Init_temperature_sensors();
787         read_octeon_sensors(TEMPERATURE_SENSOR_QUIET_MODE);
788     }
789
790     timer_p->expires =
791                 spp_timer_in_n_ms_inline(60000); /* every 1 sec */
792     spp_timer_start(timer_p);
793
794 #endif
795 }
796 void init_trace_log_buf_pool (void)
797 {   
798     spp_trace_log_info_t *my_spp_log_info;
799     u8            found;
800     spp_log_type_t log_type;
801
802     /* 
803      * Init SPP logging info as needed, this will be done only once
804      */
805     spp_trace_log_init();
806
807     found = 0;
808
809     for (log_type = SPP_LOG_LTRACE; log_type < SPP_LOG_MAX; log_type++ ) {
810         /* Do we already have a map for this log type? */
811         pool_foreach (my_spp_log_info, spp_trace_log_info_pool, ({
812             if (my_spp_log_info->log_type == log_type) {
813                 found = 1;
814                 break;
815             }
816         }));
817
818         /*
819          * Entry not present
820          */
821         if (!found) {
822             pool_get(spp_trace_log_info_pool, my_spp_log_info);
823             memset(my_spp_log_info, 0, sizeof(*my_spp_log_info));
824
825             /*
826              * Make the current and head logging context indeices as EMPTY.
827              * When first logging happens, these get set correctly
828              */
829             my_spp_log_info->current_logging_context = NULL;
830             my_spp_log_info->queued_logging_context  = NULL;
831
832             my_spp_log_info->log_type = log_type;
833             my_spp_log_info->max_length_minus_max_record_size =
834                                 SPP_TRACE_LOG_MAX_PKT_LENGTH;
835
836             spp_trace_log_global_info.spp_log_pool_index[log_type] = 
837                            my_spp_log_info - spp_trace_log_info_pool;
838         }
839
840     }
841
842     return;
843 }
844
845
846 /*
847  * one time function
848  * has to be called at the init time
849  */
850 void spp_trace_log_init (void)
851 {
852     if (!spp_trace_log_global_info.spp_trace_log_init_done) {
853
854 #ifdef TARGET_RODDICK
855             spp_trace_log_global_info.spp_trace_log_disp_node_index =
856                  spp_lookup_node_index("roddick_infra_l3_tx");
857 #elif defined(TARGET_BOOSTER)
858             spp_trace_log_global_info.spp_trace_log_disp_node_index =
859                  spp_lookup_node_index("booster_infra_l3_tx");
860 #endif
861             ASSERT(spp_trace_log_global_info.spp_trace_log_disp_node_index != (u16)~0);
862
863             spp_trace_log_global_info.log_timer.cb_index = 
864             spp_timer_register_callback(spp_trace_log_timer_handler);
865             spp_trace_log_global_info.log_timer.expires = 
866                  spp_timer_in_n_ms_inline(1000); /* every 1 sec */
867             spp_timer_start(&spp_trace_log_global_info.log_timer);
868
869         if (!my_core_id) {
870             sensor_timer.cb_index =
871                     spp_timer_register_callback(spp_sensor_timer_handler);
872             sensor_timer.expires =
873                     spp_timer_in_n_ms_inline(60000); /* every 1 sec */
874             spp_timer_start(&sensor_timer);
875         }
876
877             spp_trace_log_global_info.spp_trace_log_init_done = 1;
878
879         /*
880          *  Set MSC ip_addr, port values
881          */
882 #ifdef TARGET_RODDICK
883         dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].ipv4_address =
884                                         vpp_boot_params.msc_ip_address;
885         switch(vpp_boot_params.octeon_number) {
886             case 0:
887                     dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF;
888                     break;
889             case 1:
890                     dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF;
891                     break;
892             case 2:
893                     dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF;
894                     break;
895             case 3:
896                     dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF;
897                     break;
898         }
899 #else
900         dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].ipv4_address = 0x01020304;
901         dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF;
902 #endif
903
904     }
905 }
906
907 void spp_printf (u16 error_code, u16 num_args, u32 *arg)
908 {
909     u32 current_timestamp;
910     spp_node_main_vector_t *nmv;
911
912     if (PREDICT_FALSE(error_code >= LOG_TABLE_MAX_ENTRIES))
913     {
914        /*  printf("Error code invalid %d, %d, %d, %d\n",
915             error_code, LOG_TABLE_MAX_ENTRIES,
916             sizeof(spp_cnat_logger_table), sizeof(spp_cnat_logger_table[0]));
917             */
918         return; /* Should not happen */
919     }
920
921     nmv = spp_get_node_main_vectorized_inline();
922     current_timestamp = nmv->ticks / nmv->ticks_per_second;
923
924     /* Check if any further hashing is required */
925
926     if (PREDICT_FALSE(error_code == DUMP_PKT_IDX)) {
927 #ifdef TARGET_RODDICK || defined(TARGET_BOOSTER)
928         spp_trace_logger(error_code, num_args, arg);
929 #else
930         u8 j ;
931
932         printf("PKT DUMP :: ");
933         for (j = 0 ; j < num_args; j++) {
934             printf("0x%x ", arg[j]);
935             if (j == (num_args - 1)) {
936                 printf("\n");
937             }
938         }
939 #endif
940     } else if (PREDICT_TRUE((current_timestamp - error_code_timestamps[error_code]) >=  
941                spp_cnat_logger_table[error_code].rate_limit_time)) {
942         /* update timestamp */
943         error_code_timestamps[error_code] = current_timestamp;
944
945 #ifdef TARGET_RODDICK || defined(TARGET_BOOSTER)
946         spp_trace_logger(error_code, num_args, arg);     
947 #else
948         u8 j ;
949    
950         for (j = 0 ; j < num_args; j++) {
951             printf("%s: %d ", spp_cnat_logger_table[error_code].param_name[j], arg[j]);
952             if (j == (num_args - 1)) {
953                 printf("\n");
954             }
955         }
956 #endif
957     }
958 }
959     
960 #else /* TOBE_PORTEED */
961 void spp_trace_logger(u16 error_code, u16 num_args, u32 *arg)
962 {
963   /* To be filled */
964 }
965
966 void spp_trace_log_init(void)
967 {
968   /* To be filled */
969 }
970
971 void init_trace_log_buf_pool(void)
972 {
973   /* To be filled */
974 }
975
976 void spp_printf(u16 error_code, u16 num_args, u32 *arg)
977 {
978   /* To be filled */
979 }
980
981 inline
982 u32 spp_trace_log_get_unix_time_in_seconds (void)
983 {
984     vlib_main_t  *vlib_main;
985
986     vlib_main = vlib_get_main();
987     return(vlib_time_now((vlib_main_t *) vlib_main));
988 }
989
990 #endif /* TOBE_PORTED */
991