blob: 665a13fa4f59c0c257b68a341a719805a6737815 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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#include <stdio.h>
21#include <vlib/vlib.h>
22
23#include <vlib/unix/cj.h>
24
25cj_main_t cj_main;
26
27void
28cj_log (u32 type, void * data0, void * data1)
29{
30 u64 new_tail;
31 cj_main_t * cjm = &cj_main;
32 cj_record_t * r;
33
34 if (cjm->enable == 0)
35 return;
36
37 new_tail = __sync_add_and_fetch (&cjm->tail, 1);
38
39 r = (cj_record_t *) &(cjm->records[new_tail & (cjm->num_records - 1)]);
40 r->time = vlib_time_now (cjm->vlib_main);
41 r->cpu = os_get_cpu_number();
42 r->type = type;
43 r->data[0] = (u64) data0;
44 r->data[1] = (u64) data1;
45}
46
47void cj_stop(void)
48{
49 cj_main_t * cjm = &cj_main;
50
51 cjm->enable = 0;
52}
53
54
55clib_error_t * cj_init (vlib_main_t * vm)
56{
57 cj_main_t * cjm = &cj_main;
58
59 cjm->vlib_main = vm;
60 return 0;
61}
62VLIB_INIT_FUNCTION (cj_init);
63
64static clib_error_t *
65cj_config (vlib_main_t * vm, unformat_input_t * input)
66{
67 cj_main_t * cjm = &cj_main;
68 int matched = 0;
69 int enable = 0;
70
71 while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
72 {
73 if (unformat (input, "records %d", &cjm->num_records))
74 matched = 1;
75 else if (unformat (input, "on"))
76 enable = 1;
77 else
78 return clib_error_return (0, "cj_config: unknown input '%U'",
79 format_unformat_error, input);
80 }
81
82 if (matched == 0)
83 return 0;
84
85 cjm->num_records = max_pow2 (cjm->num_records);
86 vec_validate (cjm->records, cjm->num_records-1);
87 memset (cjm->records, 0xff, cjm->num_records * sizeof (cj_record_t));
88 cjm->tail = ~0;
89 cjm->enable = enable;
90
91 return 0;
92}
93
94VLIB_CONFIG_FUNCTION (cj_config, "cj");
95
96void cj_enable_disable (int is_enable)
97{
98 cj_main_t * cjm = &cj_main;
99
100 if (cjm->num_records)
101 cjm->enable = is_enable;
102 else
103 vlib_cli_output (cjm->vlib_main, "CJ not configured...");
104}
105
106static inline void cj_dump_one_record (cj_record_t * r)
107{
108 fprintf (stderr, "[%d]: %10.6f T%02d %llx %llx\n",
109 r->cpu, r->time, r->type, (long long unsigned int) r->data[0],
110 (long long unsigned int) r->data[1]);
111}
112
113static void cj_dump_internal (u8 filter0_enable, u64 filter0,
114 u8 filter1_enable, u64 filter1)
115{
116 cj_main_t * cjm = &cj_main;
117 cj_record_t * r;
118 u32 i, index;
119
120 if (cjm->num_records == 0)
121 {
122 fprintf (stderr, "CJ not configured...\n");
123 return;
124 }
125
126 if (cjm->tail == (u64)~0)
127 {
128 fprintf (stderr, "No data collected...\n");
129 return;
130 }
131
132 /* Has the trace wrapped? */
133 index = (cjm->tail+1) & (cjm->num_records - 1);
134 r = &(cjm->records[index]);
135
136 if (r->cpu != (u32)~0)
137 {
138 /* Yes, dump from tail + 1 to the end */
139 for (i = index; i < cjm->num_records; i++)
140 {
141 if (filter0_enable && (r->data[0] != filter0))
142 goto skip;
143 if (filter1_enable && (r->data[1] != filter1))
144 goto skip;
145 cj_dump_one_record (r);
146 skip:
147 r++;
148 }
149 }
150 /* dump from the beginning through the final tail */
151 r = cjm->records;
152 for (i = 0; i <= cjm->tail; i++)
153 {
154 if (filter0_enable && (r->data[0] != filter0))
155 goto skip2;
156 if (filter1_enable && (r->data[1] != filter1))
157 goto skip2;
158 cj_dump_one_record (r);
159 skip2:
160 r++;
161 }
162}
163
164void cj_dump (void)
165{
166 cj_dump_internal (0, 0, 0, 0);
167}
168
169void cj_dump_filter_data0 (u64 filter0)
170{
171 cj_dump_internal (1/* enable f0 */, filter0, 0, 0);
172}
173
174void cj_dump_filter_data1 (u64 filter1)
175{
176 cj_dump_internal (0, 0, 1 /* enable f1 */, filter1);
177}
178
179void cj_dump_filter_data12 (u64 filter0, u64 filter1)
180{
181 cj_dump_internal (1, filter0, 1, filter1);
182}
183
184static clib_error_t *
185cj_command_fn (vlib_main_t * vm,
186 unformat_input_t * input,
187 vlib_cli_command_t * cmd)
188{
189 int is_enable = -1;
190 int is_dump = -1;
191
192 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
193 if (unformat (input, "enable") || unformat (input, "on"))
194 is_enable = 1;
195 else if (unformat (input, "disable") || unformat (input, "off"))
196 is_enable = 0;
197 else if (unformat (input, "dump"))
198 is_dump = 1;
199 else
200 return clib_error_return (0, "unknown input `%U'",
201 format_unformat_error, input);
202 }
203
204 if (is_enable >= 0)
205 cj_enable_disable (is_enable);
206
207 if (is_dump > 0)
208 cj_dump ();
209
210 return 0;
211}
212
213VLIB_CLI_COMMAND (cj_command,static) = {
214 .path = "cj",
215 .short_help = "cj",
216 .function = cj_command_fn,
217};
218