FD.io VPP  v17.01.1-3-gc6833f8
Vector Packet Processing
cj.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * cj.c
4  *
5  * Copyright (c) 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 /**
21  * @file
22  * Circular joournal diagnostic mechanism.
23  *
24  * The @c cj thread-safe circular log buffer scheme is occasionally useful
25  * when chasing bugs. Calls to it should not be checked in.
26  */
27 /*? %%clicmd:group_label Circular Journal %% ?*/
28 /*? %%syscfg:group_label Circular Journal %% ?*/
29 
30 #include <stdio.h>
31 #include <vlib/vlib.h>
32 
33 #include <vlib/unix/cj.h>
34 
36 
37 void
38 cj_log (u32 type, void *data0, void *data1)
39 {
40  u64 new_tail;
41  cj_main_t *cjm = &cj_main;
42  cj_record_t *r;
43 
44  if (cjm->enable == 0)
45  return;
46 
47  new_tail = __sync_add_and_fetch (&cjm->tail, 1);
48 
49  r = (cj_record_t *) & (cjm->records[new_tail & (cjm->num_records - 1)]);
50  r->time = vlib_time_now (cjm->vlib_main);
51  r->cpu = os_get_cpu_number ();
52  r->type = type;
53  r->data[0] = pointer_to_uword (data0);
54  r->data[1] = pointer_to_uword (data1);
55 }
56 
57 void
58 cj_stop (void)
59 {
60  cj_main_t *cjm = &cj_main;
61 
62  cjm->enable = 0;
63 }
64 
65 
68 {
69  cj_main_t *cjm = &cj_main;
70 
71  cjm->vlib_main = vm;
72  return 0;
73 }
74 
76 
77 static clib_error_t *
79 {
80  cj_main_t *cjm = &cj_main;
81  int matched = 0;
82  int enable = 0;
83 
85  {
86  if (unformat (input, "records %d", &cjm->num_records))
87  matched = 1;
88  else if (unformat (input, "on"))
89  enable = 1;
90  else
91  return clib_error_return (0, "cj_config: unknown input '%U'",
92  format_unformat_error, input);
93  }
94 
95  if (matched == 0)
96  return 0;
97 
98  cjm->num_records = max_pow2 (cjm->num_records);
99  vec_validate (cjm->records, cjm->num_records - 1);
100  memset (cjm->records, 0xff, cjm->num_records * sizeof (cj_record_t));
101  cjm->tail = ~0;
102  cjm->enable = enable;
103 
104  return 0;
105 }
106 
107 /*?
108  * Configure the circular journal diagnostic mechanism. This is only useful
109  * if you, the deveoper, have written code to make use of the circular
110  * journal.
111  *
112  * @cfgcmd{records, &lt;number&gt;}
113  * Configure the number of records to allocate for the circular journal.
114  *
115  * @cfgcmd{on}
116  * Enable the collection of records in the circular journal at the
117  * earliest opportunity.
118 ?*/
120 
121 void
122 cj_enable_disable (int is_enable)
123 {
124  cj_main_t *cjm = &cj_main;
125 
126  if (cjm->num_records)
127  cjm->enable = is_enable;
128  else
129  vlib_cli_output (cjm->vlib_main, "CJ not configured...");
130 }
131 
132 static inline void
134 {
135  fprintf (stderr, "[%d]: %10.6f T%02d %llx %llx\n",
136  r->cpu, r->time, r->type, (long long unsigned int) r->data[0],
137  (long long unsigned int) r->data[1]);
138 }
139 
140 static void
141 cj_dump_internal (u8 filter0_enable, u64 filter0,
142  u8 filter1_enable, u64 filter1)
143 {
144  cj_main_t *cjm = &cj_main;
145  cj_record_t *r;
146  u32 i, index;
147 
148  if (cjm->num_records == 0)
149  {
150  fprintf (stderr, "CJ not configured...\n");
151  return;
152  }
153 
154  if (cjm->tail == (u64) ~ 0)
155  {
156  fprintf (stderr, "No data collected...\n");
157  return;
158  }
159 
160  /* Has the trace wrapped? */
161  index = (cjm->tail + 1) & (cjm->num_records - 1);
162  r = &(cjm->records[index]);
163 
164  if (r->cpu != (u32) ~ 0)
165  {
166  /* Yes, dump from tail + 1 to the end */
167  for (i = index; i < cjm->num_records; i++)
168  {
169  if (filter0_enable && (r->data[0] != filter0))
170  goto skip;
171  if (filter1_enable && (r->data[1] != filter1))
172  goto skip;
173  cj_dump_one_record (r);
174  skip:
175  r++;
176  }
177  }
178  /* dump from the beginning through the final tail */
179  r = cjm->records;
180  for (i = 0; i <= cjm->tail; i++)
181  {
182  if (filter0_enable && (r->data[0] != filter0))
183  goto skip2;
184  if (filter1_enable && (r->data[1] != filter1))
185  goto skip2;
186  cj_dump_one_record (r);
187  skip2:
188  r++;
189  }
190 }
191 
192 void
193 cj_dump (void)
194 {
195  cj_dump_internal (0, 0, 0, 0);
196 }
197 
198 void
200 {
201  cj_dump_internal (1 /* enable f0 */ , filter0, 0, 0);
202 }
203 
204 void
206 {
207  cj_dump_internal (0, 0, 1 /* enable f1 */ , filter1);
208 }
209 
210 void
211 cj_dump_filter_data12 (u64 filter0, u64 filter1)
212 {
213  cj_dump_internal (1, filter0, 1, filter1);
214 }
215 
216 static clib_error_t *
218  unformat_input_t * input, vlib_cli_command_t * cmd)
219 {
220  int is_enable = -1;
221  int is_dump = -1;
222 
224  {
225  if (unformat (input, "enable") || unformat (input, "on"))
226  is_enable = 1;
227  else if (unformat (input, "disable") || unformat (input, "off"))
228  is_enable = 0;
229  else if (unformat (input, "dump"))
230  is_dump = 1;
231  else
232  return clib_error_return (0, "unknown input `%U'",
233  format_unformat_error, input);
234  }
235 
236  if (is_enable >= 0)
237  cj_enable_disable (is_enable);
238 
239  if (is_dump > 0)
240  cj_dump ();
241 
242  return 0;
243 }
244 
245 /*?
246  * Enable, disable the collection of diagnostic data into a
247  * circular journal or dump the circular journal diagnostic data.
248  * This is only useful if you, the deveoper, have written code to make
249  * use of the circular journal.
250  *
251  * When dumping the data it is formatted and sent to @c stderr of the
252  * VPP process; when running VPP in <code>unix interactive</code> mode
253  * this is typically the same place as the Debug CLI.
254 ?*/
255 
256 /* *INDENT-OFF* */
257 VLIB_CLI_COMMAND (cj_command,static) = {
258  .path = "cj",
259  .short_help = "cj <enable | disable | dump>",
260  .function = cj_command_fn,
261 };
262 /* *INDENT-ON* */
263 
264 
265 /*
266  * fd.io coding-style-patch-verification: ON
267  *
268  * Local Variables:
269  * eval: (c-set-style "gnu")
270  * End:
271  */
void cj_dump_filter_data12(u64 filter0, u64 filter1)
Definition: cj.c:211
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
u32 cpu
Definition: cj.h:26
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
Definition: cj.h:31
static clib_error_t * cj_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cj.c:217
volatile u32 enable
Definition: cj.h:36
volatile u64 tail
Definition: cj.h:33
void cj_dump_filter_data1(u64 filter1)
Definition: cj.c:205
void cj_stop(void)
Definition: cj.c:58
void cj_enable_disable(int is_enable)
Definition: cj.c:122
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
f64 time
Definition: cj.h:25
unsigned long u64
Definition: types.h:89
void cj_log(u32 type, void *data0, void *data1)
Definition: cj.c:38
static uword pointer_to_uword(const void *p)
Definition: types.h:131
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
cj_main_t cj_main
Definition: cj.c:35
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:118
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
vlib_main_t * vlib_main
Definition: cj.h:38
static void cj_dump_one_record(cj_record_t *r)
Definition: cj.c:133
static uword max_pow2(uword x)
Definition: clib.h:257
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
void cj_dump_filter_data0(u64 filter0)
Definition: cj.c:199
clib_error_t * cj_init(vlib_main_t *vm)
Definition: cj.c:67
u64 data[2]
Definition: cj.h:28
Definition: cj.h:23
u32 type
Definition: cj.h:27
unsigned char u8
Definition: types.h:56
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
static void cj_dump_internal(u8 filter0_enable, u64 filter0, u8 filter1_enable, u64 filter1)
Definition: cj.c:141
u32 num_records
Definition: cj.h:35
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
cj_record_t * records
Definition: cj.h:34
void cj_dump(void)
Definition: cj.c:193
static clib_error_t * cj_config(vlib_main_t *vm, unformat_input_t *input)
Definition: cj.c:78