blob: 3f45cb9f0ef5282c4e24d5b360b1c0e21e5b2873 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 * interface_output.c: interface output node
17 *
18 * Copyright (c) 2008 Eliot Dresselhaus
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining
21 * a copy of this software and associated documentation files (the
22 * "Software"), to deal in the Software without restriction, including
23 * without limitation the rights to use, copy, modify, merge, publish,
24 * distribute, sublicense, and/or sell copies of the Software, and to
25 * permit persons to whom the Software is furnished to do so, subject to
26 * the following conditions:
27 *
28 * The above copyright notice and this permission notice shall be
29 * included in all copies or substantial portions of the Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 */
39
40#include <vnet/vnet.h>
Damjan Marion152e21d2016-11-29 14:55:43 +010041#include <vnet/feature/feature.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070042
Dave Barachba868bb2016-08-08 09:51:21 -040043typedef struct
44{
Ed Warnickecb9cada2015-12-08 15:45:58 -070045 u32 sw_if_index;
Chris Luke1c9f6ce2016-04-26 10:55:52 -040046 u8 data[128 - sizeof (u32)];
Dave Barachba868bb2016-08-08 09:51:21 -040047}
48interface_output_trace_t;
Ed Warnickecb9cada2015-12-08 15:45:58 -070049
Dave Barachba868bb2016-08-08 09:51:21 -040050u8 *
51format_vnet_interface_output_trace (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070052{
53 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
Dave Barachba868bb2016-08-08 09:51:21 -040054 vlib_node_t *node = va_arg (*va, vlib_node_t *);
55 interface_output_trace_t *t = va_arg (*va, interface_output_trace_t *);
56 vnet_main_t *vnm = vnet_get_main ();
57 vnet_sw_interface_t *si;
Ed Warnickecb9cada2015-12-08 15:45:58 -070058 uword indent;
59
Dave Barachba868bb2016-08-08 09:51:21 -040060 if (t->sw_if_index != (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -070061 {
Ed Warnickecb9cada2015-12-08 15:45:58 -070062 indent = format_get_indent (s);
Dave Barachba868bb2016-08-08 09:51:21 -040063
Neale Ranns177bbdc2016-11-15 09:46:51 +000064 if (pool_is_free_index
65 (vnm->interface_main.sw_interfaces, t->sw_if_index))
66 {
67 /* the interface may have been deleted by the time the trace is printed */
68 s = format (s, "sw_if_index: %d\n%U%U",
69 t->sw_if_index,
70 format_white_space, indent,
71 node->format_buffer ? node->
72 format_buffer : format_hex_bytes, t->data,
73 sizeof (t->data));
74 }
75 else
76 {
77 si = vnet_get_sw_interface (vnm, t->sw_if_index);
78
79 s = format (s, "%U\n%U%U",
80 format_vnet_sw_interface_name, vnm, si,
81 format_white_space, indent,
82 node->format_buffer ? node->
83 format_buffer : format_hex_bytes, t->data,
84 sizeof (t->data));
85 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070086 }
87 return s;
88}
89
90static void
91vnet_interface_output_trace (vlib_main_t * vm,
92 vlib_node_runtime_t * node,
Dave Barachba868bb2016-08-08 09:51:21 -040093 vlib_frame_t * frame, uword n_buffers)
Ed Warnickecb9cada2015-12-08 15:45:58 -070094{
Dave Barachba868bb2016-08-08 09:51:21 -040095 u32 n_left, *from;
Ed Warnickecb9cada2015-12-08 15:45:58 -070096
97 n_left = n_buffers;
98 from = vlib_frame_args (frame);
Dave Barachba868bb2016-08-08 09:51:21 -040099
Ed Warnickecb9cada2015-12-08 15:45:58 -0700100 while (n_left >= 4)
101 {
102 u32 bi0, bi1;
Dave Barachba868bb2016-08-08 09:51:21 -0400103 vlib_buffer_t *b0, *b1;
104 interface_output_trace_t *t0, *t1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105
106 /* Prefetch next iteration. */
107 vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
108 vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
109
110 bi0 = from[0];
111 bi1 = from[1];
112
113 b0 = vlib_get_buffer (vm, bi0);
114 b1 = vlib_get_buffer (vm, bi1);
115
116 if (b0->flags & VLIB_BUFFER_IS_TRACED)
117 {
118 t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
119 t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
Damjan Marionf1213b82016-03-13 02:22:06 +0100120 clib_memcpy (t0->data, vlib_buffer_get_current (b0),
Dave Barachba868bb2016-08-08 09:51:21 -0400121 sizeof (t0->data));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700122 }
123 if (b1->flags & VLIB_BUFFER_IS_TRACED)
124 {
125 t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
126 t1->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_TX];
Damjan Marionf1213b82016-03-13 02:22:06 +0100127 clib_memcpy (t1->data, vlib_buffer_get_current (b1),
Dave Barachba868bb2016-08-08 09:51:21 -0400128 sizeof (t1->data));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700129 }
130 from += 2;
131 n_left -= 2;
132 }
133
134 while (n_left >= 1)
135 {
136 u32 bi0;
Dave Barachba868bb2016-08-08 09:51:21 -0400137 vlib_buffer_t *b0;
138 interface_output_trace_t *t0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700139
140 bi0 = from[0];
141
142 b0 = vlib_get_buffer (vm, bi0);
143
144 if (b0->flags & VLIB_BUFFER_IS_TRACED)
145 {
146 t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
147 t0->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
Damjan Marionf1213b82016-03-13 02:22:06 +0100148 clib_memcpy (t0->data, vlib_buffer_get_current (b0),
Dave Barachba868bb2016-08-08 09:51:21 -0400149 sizeof (t0->data));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700150 }
151 from += 1;
152 n_left -= 1;
153 }
154}
155
156static never_inline u32
157slow_path (vlib_main_t * vm,
158 u32 bi,
159 vlib_buffer_t * b,
Dave Barachba868bb2016-08-08 09:51:21 -0400160 u32 n_left_to_tx, u32 * to_tx, u32 * n_slow_bytes_result)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700161{
162 /* We've already enqueued a single buffer. */
163 u32 n_buffers = 0;
164 u32 n_slow_bytes = 0;
165
166 while (n_left_to_tx > 0)
167 {
168 to_tx[0] = bi;
169 to_tx += 1;
170 n_left_to_tx -= 1;
171 n_buffers += 1;
172 n_slow_bytes += vlib_buffer_length_in_chain (vm, b);
173
174 /* Be grumpy about zero length buffers for benefit of
Dave Barachba868bb2016-08-08 09:51:21 -0400175 driver tx function. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700176 ASSERT (b->current_length > 0);
177
Dave Barachba868bb2016-08-08 09:51:21 -0400178 if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700179 break;
180
181 bi = b->next_buffer;
182 b = vlib_get_buffer (vm, bi);
183 }
184
185 /* Ran out of space in next frame trying to enqueue buffers? */
186 if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
187 return 0;
188
189 *n_slow_bytes_result = n_slow_bytes;
190 return n_buffers;
191}
192
Dave Barachba868bb2016-08-08 09:51:21 -0400193/*
194 * Increment TX stats. Roll up consecutive increments to the same sw_if_index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195 * into one increment.
196 */
Dave Barachba868bb2016-08-08 09:51:21 -0400197static_always_inline void
198incr_output_stats (vnet_main_t * vnm,
Damjan Marion586afd72017-04-05 19:18:20 +0200199 u32 thread_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400200 u32 length,
201 u32 sw_if_index,
202 u32 * last_sw_if_index, u32 * n_packets, u32 * n_bytes)
203{
204 vnet_interface_main_t *im;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700205
Dave Barachba868bb2016-08-08 09:51:21 -0400206 if (PREDICT_TRUE (sw_if_index == *last_sw_if_index))
207 {
208 *n_packets += 1;
209 *n_bytes += length;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210 }
Dave Barachba868bb2016-08-08 09:51:21 -0400211 else
212 {
213 if (PREDICT_TRUE (*last_sw_if_index != ~0))
214 {
215 im = &vnm->interface_main;
216
217 vlib_increment_combined_counter (im->combined_sw_if_counters
218 + VNET_INTERFACE_COUNTER_TX,
Damjan Marion586afd72017-04-05 19:18:20 +0200219 thread_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400220 *last_sw_if_index,
221 *n_packets, *n_bytes);
222 }
223 *last_sw_if_index = sw_if_index;
224 *n_packets = 1;
225 *n_bytes = length;
226 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700227}
228
229
230/* Interface output functions. */
231uword
Damjan Marion8b2247d2016-12-02 08:09:45 +0100232vnet_interface_output_node_flatten (vlib_main_t * vm,
233 vlib_node_runtime_t * node,
234 vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700235{
Dave Barachba868bb2016-08-08 09:51:21 -0400236 vnet_main_t *vnm = vnet_get_main ();
237 vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
238 vnet_sw_interface_t *si;
239 vnet_hw_interface_t *hi;
240 u32 n_left_to_tx, *from, *from_end, *to_tx;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241 u32 n_bytes, n_buffers, n_packets;
242 u32 last_sw_if_index;
Damjan Marion586afd72017-04-05 19:18:20 +0200243 u32 thread_index = vm->thread_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700244
245 n_buffers = frame->n_vectors;
246
247 if (node->flags & VLIB_NODE_FLAG_TRACE)
248 vnet_interface_output_trace (vm, node, frame, n_buffers);
249
250 from = vlib_frame_args (frame);
251
252 if (rt->is_deleted)
Dave Barachba868bb2016-08-08 09:51:21 -0400253 return vlib_error_drop_buffers (vm, node, from,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700254 /* buffer stride */ 1,
255 n_buffers,
256 VNET_INTERFACE_OUTPUT_NEXT_DROP,
257 node->node_index,
258 VNET_INTERFACE_OUTPUT_ERROR_INTERFACE_DELETED);
259
260 si = vnet_get_sw_interface (vnm, rt->sw_if_index);
261 hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400262 if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ||
263 !(hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700264 {
Dave Barachba868bb2016-08-08 09:51:21 -0400265 vlib_simple_counter_main_t *cm;
266
Ed Warnickecb9cada2015-12-08 15:45:58 -0700267 cm = vec_elt_at_index (vnm->interface_main.sw_if_counters,
Dave Barachba868bb2016-08-08 09:51:21 -0400268 VNET_INTERFACE_COUNTER_TX_ERROR);
Damjan Marion586afd72017-04-05 19:18:20 +0200269 vlib_increment_simple_counter (cm, thread_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400270 rt->sw_if_index, n_buffers);
271 return vlib_error_drop_buffers (vm, node, from,
272 /* buffer stride */ 1,
273 n_buffers,
274 VNET_INTERFACE_OUTPUT_NEXT_DROP,
275 node->node_index,
276 VNET_INTERFACE_OUTPUT_ERROR_INTERFACE_DOWN);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700277 }
278
279 from_end = from + n_buffers;
280
281 /* Total byte count of all buffers. */
282 n_bytes = 0;
283 n_packets = 0;
284 last_sw_if_index = ~0;
285
286 while (from < from_end)
287 {
288 /* Get new next frame since previous incomplete frame may have less
Dave Barachba868bb2016-08-08 09:51:21 -0400289 than VNET_FRAME_SIZE vectors in it. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700290 vlib_get_new_next_frame (vm, node, VNET_INTERFACE_OUTPUT_NEXT_TX,
291 to_tx, n_left_to_tx);
292
293 while (from + 4 <= from_end && n_left_to_tx >= 2)
294 {
295 u32 bi0, bi1;
Dave Barachba868bb2016-08-08 09:51:21 -0400296 vlib_buffer_t *b0, *b1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700297
298 /* Prefetch next iteration. */
299 vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
300 vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
301
302 bi0 = from[0];
303 bi1 = from[1];
304 to_tx[0] = bi0;
305 to_tx[1] = bi1;
306 from += 2;
307 to_tx += 2;
308 n_left_to_tx -= 2;
309
310 b0 = vlib_get_buffer (vm, bi0);
311 b1 = vlib_get_buffer (vm, bi1);
312
313 /* Be grumpy about zero length buffers for benefit of
314 driver tx function. */
315 ASSERT (b0->current_length > 0);
316 ASSERT (b1->current_length > 0);
317
Dave Barachba868bb2016-08-08 09:51:21 -0400318 if (PREDICT_FALSE
319 ((b0->flags | b1->flags) & VLIB_BUFFER_NEXT_PRESENT))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700320 {
321 u32 n_buffers, n_slow_bytes, i;
322
323 /* Undo. */
324 from -= 2;
325 to_tx -= 2;
326 n_left_to_tx += 2;
327
328 /* Do slow path two times. */
329 for (i = 0; i < 2; i++)
330 {
331 u32 bi = i ? bi1 : bi0;
Dave Barachba868bb2016-08-08 09:51:21 -0400332 vlib_buffer_t *b = i ? b1 : b0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700333
334 n_buffers = slow_path (vm, bi, b,
335 n_left_to_tx, to_tx, &n_slow_bytes);
336
337 /* Not enough room for single packet? */
338 if (n_buffers == 0)
339 goto put;
340
341 from += 1;
342 to_tx += n_buffers;
343 n_left_to_tx -= n_buffers;
Damjan Marion586afd72017-04-05 19:18:20 +0200344 incr_output_stats (vnm, thread_index, n_slow_bytes,
Dave Barachba868bb2016-08-08 09:51:21 -0400345 vnet_buffer (b)->sw_if_index[VLIB_TX],
346 &last_sw_if_index, &n_packets, &n_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700347 }
Dave Barachba868bb2016-08-08 09:51:21 -0400348 }
349 else
350 {
Damjan Marion586afd72017-04-05 19:18:20 +0200351 incr_output_stats (vnm, thread_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400352 vlib_buffer_length_in_chain (vm, b0),
353 vnet_buffer (b0)->sw_if_index[VLIB_TX],
354 &last_sw_if_index, &n_packets, &n_bytes);
Damjan Marion586afd72017-04-05 19:18:20 +0200355 incr_output_stats (vnm, thread_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400356 vlib_buffer_length_in_chain (vm, b0),
357 vnet_buffer (b1)->sw_if_index[VLIB_TX],
358 &last_sw_if_index, &n_packets, &n_bytes);
359 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700360 }
361
362 while (from + 1 <= from_end && n_left_to_tx >= 1)
363 {
364 u32 bi0;
Dave Barachba868bb2016-08-08 09:51:21 -0400365 vlib_buffer_t *b0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700366
367 bi0 = from[0];
368 to_tx[0] = bi0;
369 from += 1;
370 to_tx += 1;
371 n_left_to_tx -= 1;
372
373 b0 = vlib_get_buffer (vm, bi0);
374
375 /* Be grumpy about zero length buffers for benefit of
376 driver tx function. */
377 ASSERT (b0->current_length > 0);
378
379 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_NEXT_PRESENT))
380 {
381 u32 n_buffers, n_slow_bytes;
382
383 /* Undo. */
384 from -= 1;
385 to_tx -= 1;
386 n_left_to_tx += 1;
387
388 n_buffers = slow_path (vm, bi0, b0,
389 n_left_to_tx, to_tx, &n_slow_bytes);
390
391 /* Not enough room for single packet? */
392 if (n_buffers == 0)
393 goto put;
394
395 from += 1;
396 to_tx += n_buffers;
397 n_left_to_tx -= n_buffers;
398 }
Damjan Marion586afd72017-04-05 19:18:20 +0200399 incr_output_stats (vnm, thread_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400400 vlib_buffer_length_in_chain (vm, b0),
401 vnet_buffer (b0)->sw_if_index[VLIB_TX],
402 &last_sw_if_index, &n_packets, &n_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700403 }
404
405 put:
Dave Barachba868bb2016-08-08 09:51:21 -0400406 vlib_put_next_frame (vm, node, VNET_INTERFACE_OUTPUT_NEXT_TX,
407 n_left_to_tx);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700408 }
409
410 /* Final update of interface stats. */
Damjan Marion586afd72017-04-05 19:18:20 +0200411 incr_output_stats (vnm, thread_index, 0, ~0, /* ~0 will flush stats */
Dave Barachba868bb2016-08-08 09:51:21 -0400412 &last_sw_if_index, &n_packets, &n_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700413
414 return n_buffers;
415}
416
Damjan Marion8b2247d2016-12-02 08:09:45 +0100417VLIB_NODE_FUNCTION_MULTIARCH_CLONE (vnet_interface_output_node_flatten);
418CLIB_MULTIARCH_SELECT_FN (vnet_interface_output_node_flatten);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700419
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100420uword
Damjan Marion8b2247d2016-12-02 08:09:45 +0100421vnet_interface_output_node (vlib_main_t * vm,
422 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700423{
Dave Barachba868bb2016-08-08 09:51:21 -0400424 vnet_main_t *vnm = vnet_get_main ();
425 vnet_interface_output_runtime_t *rt = (void *) node->runtime_data;
426 vnet_sw_interface_t *si;
427 vnet_hw_interface_t *hi;
428 u32 n_left_to_tx, *from, *from_end, *to_tx;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700429 u32 n_bytes, n_buffers, n_packets;
Damjan Marion363640d2017-03-06 11:53:10 +0100430 u32 n_bytes_b0, n_bytes_b1, n_bytes_b2, n_bytes_b3;
Damjan Marion586afd72017-04-05 19:18:20 +0200431 u32 thread_index = vm->thread_index;
Dave Barachba868bb2016-08-08 09:51:21 -0400432 vnet_interface_main_t *im = &vnm->interface_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700433 u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
Damjan Marion152e21d2016-11-29 14:55:43 +0100434 u32 current_config_index = ~0;
435 u8 arc = im->output_feature_arc_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700436
437 n_buffers = frame->n_vectors;
438
439 if (node->flags & VLIB_NODE_FLAG_TRACE)
440 vnet_interface_output_trace (vm, node, frame, n_buffers);
441
442 from = vlib_frame_args (frame);
443
444 if (rt->is_deleted)
Dave Barachba868bb2016-08-08 09:51:21 -0400445 return vlib_error_drop_buffers (vm, node, from,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700446 /* buffer stride */ 1,
447 n_buffers,
448 VNET_INTERFACE_OUTPUT_NEXT_DROP,
449 node->node_index,
450 VNET_INTERFACE_OUTPUT_ERROR_INTERFACE_DELETED);
451
452 si = vnet_get_sw_interface (vnm, rt->sw_if_index);
453 hi = vnet_get_sup_hw_interface (vnm, rt->sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400454 if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ||
455 !(hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700456 {
Dave Barachba868bb2016-08-08 09:51:21 -0400457 vlib_simple_counter_main_t *cm;
458
Ed Warnickecb9cada2015-12-08 15:45:58 -0700459 cm = vec_elt_at_index (vnm->interface_main.sw_if_counters,
Dave Barachba868bb2016-08-08 09:51:21 -0400460 VNET_INTERFACE_COUNTER_TX_ERROR);
Damjan Marion586afd72017-04-05 19:18:20 +0200461 vlib_increment_simple_counter (cm, thread_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400462 rt->sw_if_index, n_buffers);
463
464 return vlib_error_drop_buffers (vm, node, from,
465 /* buffer stride */ 1,
466 n_buffers,
467 VNET_INTERFACE_OUTPUT_NEXT_DROP,
468 node->node_index,
469 VNET_INTERFACE_OUTPUT_ERROR_INTERFACE_DOWN);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700470 }
471
472 from_end = from + n_buffers;
473
474 /* Total byte count of all buffers. */
475 n_bytes = 0;
476 n_packets = 0;
477
Damjan Marion152e21d2016-11-29 14:55:43 +0100478 /* interface-output feature arc handling */
479 if (PREDICT_FALSE (vnet_have_features (arc, rt->sw_if_index)))
480 {
481 vnet_feature_config_main_t *fcm;
482 fcm = vnet_feature_get_config_main (arc);
483 current_config_index = vnet_get_feature_config_index (arc,
484 rt->sw_if_index);
485 vnet_get_config_data (&fcm->config_main, &current_config_index,
486 &next_index, 0);
487 }
488
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489 while (from < from_end)
490 {
491 /* Get new next frame since previous incomplete frame may have less
Dave Barachba868bb2016-08-08 09:51:21 -0400492 than VNET_FRAME_SIZE vectors in it. */
493 vlib_get_new_next_frame (vm, node, next_index, to_tx, n_left_to_tx);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700494
Damjan Marion363640d2017-03-06 11:53:10 +0100495 while (from + 8 <= from_end && n_left_to_tx >= 4)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700496 {
Damjan Marion363640d2017-03-06 11:53:10 +0100497 u32 bi0, bi1, bi2, bi3;
498 vlib_buffer_t *b0, *b1, *b2, *b3;
499 u32 tx_swif0, tx_swif1, tx_swif2, tx_swif3;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700500
501 /* Prefetch next iteration. */
Damjan Marion363640d2017-03-06 11:53:10 +0100502 vlib_prefetch_buffer_with_index (vm, from[4], LOAD);
503 vlib_prefetch_buffer_with_index (vm, from[5], LOAD);
504 vlib_prefetch_buffer_with_index (vm, from[6], LOAD);
505 vlib_prefetch_buffer_with_index (vm, from[7], LOAD);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700506
507 bi0 = from[0];
508 bi1 = from[1];
Damjan Marion363640d2017-03-06 11:53:10 +0100509 bi2 = from[2];
510 bi3 = from[3];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700511 to_tx[0] = bi0;
512 to_tx[1] = bi1;
Damjan Marion363640d2017-03-06 11:53:10 +0100513 to_tx[2] = bi2;
514 to_tx[3] = bi3;
515 from += 4;
516 to_tx += 4;
517 n_left_to_tx -= 4;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700518
519 b0 = vlib_get_buffer (vm, bi0);
520 b1 = vlib_get_buffer (vm, bi1);
Damjan Marion363640d2017-03-06 11:53:10 +0100521 b2 = vlib_get_buffer (vm, bi2);
522 b3 = vlib_get_buffer (vm, bi3);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700523
524 /* Be grumpy about zero length buffers for benefit of
525 driver tx function. */
526 ASSERT (b0->current_length > 0);
527 ASSERT (b1->current_length > 0);
Damjan Marion363640d2017-03-06 11:53:10 +0100528 ASSERT (b2->current_length > 0);
529 ASSERT (b3->current_length > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700530
Dave Barachba868bb2016-08-08 09:51:21 -0400531 n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
532 n_bytes_b1 = vlib_buffer_length_in_chain (vm, b1);
Damjan Marion363640d2017-03-06 11:53:10 +0100533 n_bytes_b2 = vlib_buffer_length_in_chain (vm, b2);
534 n_bytes_b3 = vlib_buffer_length_in_chain (vm, b3);
Dave Barachba868bb2016-08-08 09:51:21 -0400535 tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
536 tx_swif1 = vnet_buffer (b1)->sw_if_index[VLIB_TX];
Damjan Marion363640d2017-03-06 11:53:10 +0100537 tx_swif2 = vnet_buffer (b2)->sw_if_index[VLIB_TX];
538 tx_swif3 = vnet_buffer (b3)->sw_if_index[VLIB_TX];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700539
540 n_bytes += n_bytes_b0 + n_bytes_b1;
Damjan Marion363640d2017-03-06 11:53:10 +0100541 n_bytes += n_bytes_b2 + n_bytes_b3;
542 n_packets += 4;
Dave Barachba868bb2016-08-08 09:51:21 -0400543
Damjan Marion152e21d2016-11-29 14:55:43 +0100544 if (PREDICT_FALSE (current_config_index != ~0))
545 {
546 b0->feature_arc_index = arc;
547 b1->feature_arc_index = arc;
Damjan Marion363640d2017-03-06 11:53:10 +0100548 b2->feature_arc_index = arc;
549 b3->feature_arc_index = arc;
Damjan Marion152e21d2016-11-29 14:55:43 +0100550 b0->current_config_index = current_config_index;
551 b1->current_config_index = current_config_index;
Damjan Marion363640d2017-03-06 11:53:10 +0100552 b2->current_config_index = current_config_index;
553 b3->current_config_index = current_config_index;
Damjan Marion152e21d2016-11-29 14:55:43 +0100554 }
555
Damjan Marion363640d2017-03-06 11:53:10 +0100556 /* update vlan subif tx counts, if required */
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100557 if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
Dave Barachba868bb2016-08-08 09:51:21 -0400558 {
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100559 vlib_increment_combined_counter (im->combined_sw_if_counters +
560 VNET_INTERFACE_COUNTER_TX,
Damjan Marion586afd72017-04-05 19:18:20 +0200561 thread_index, tx_swif0, 1,
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100562 n_bytes_b0);
Dave Barachba868bb2016-08-08 09:51:21 -0400563 }
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100564
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100565 if (PREDICT_FALSE (tx_swif1 != rt->sw_if_index))
566 {
567
568 vlib_increment_combined_counter (im->combined_sw_if_counters +
569 VNET_INTERFACE_COUNTER_TX,
Damjan Marion586afd72017-04-05 19:18:20 +0200570 thread_index, tx_swif1, 1,
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100571 n_bytes_b1);
572 }
Damjan Marion363640d2017-03-06 11:53:10 +0100573
574 if (PREDICT_FALSE (tx_swif2 != rt->sw_if_index))
575 {
576
577 vlib_increment_combined_counter (im->combined_sw_if_counters +
578 VNET_INTERFACE_COUNTER_TX,
Damjan Marion586afd72017-04-05 19:18:20 +0200579 thread_index, tx_swif2, 1,
Damjan Marion363640d2017-03-06 11:53:10 +0100580 n_bytes_b2);
581 }
582 if (PREDICT_FALSE (tx_swif3 != rt->sw_if_index))
583 {
584
585 vlib_increment_combined_counter (im->combined_sw_if_counters +
586 VNET_INTERFACE_COUNTER_TX,
Damjan Marion586afd72017-04-05 19:18:20 +0200587 thread_index, tx_swif3, 1,
Damjan Marion363640d2017-03-06 11:53:10 +0100588 n_bytes_b3);
589 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700590 }
591
592 while (from + 1 <= from_end && n_left_to_tx >= 1)
593 {
594 u32 bi0;
Dave Barachba868bb2016-08-08 09:51:21 -0400595 vlib_buffer_t *b0;
596 u32 tx_swif0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700597
598 bi0 = from[0];
599 to_tx[0] = bi0;
600 from += 1;
601 to_tx += 1;
602 n_left_to_tx -= 1;
603
604 b0 = vlib_get_buffer (vm, bi0);
605
606 /* Be grumpy about zero length buffers for benefit of
607 driver tx function. */
608 ASSERT (b0->current_length > 0);
609
Dave Barachba868bb2016-08-08 09:51:21 -0400610 n_bytes_b0 = vlib_buffer_length_in_chain (vm, b0);
611 tx_swif0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700612 n_bytes += n_bytes_b0;
613 n_packets += 1;
614
Damjan Marion152e21d2016-11-29 14:55:43 +0100615 if (PREDICT_FALSE (current_config_index != ~0))
616 {
617 b0->feature_arc_index = arc;
618 b0->current_config_index = current_config_index;
619 }
620
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100621 if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
Dave Barachba868bb2016-08-08 09:51:21 -0400622 {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700623
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100624 vlib_increment_combined_counter (im->combined_sw_if_counters +
625 VNET_INTERFACE_COUNTER_TX,
Damjan Marion586afd72017-04-05 19:18:20 +0200626 thread_index, tx_swif0, 1,
Damjan Marion9c6ae5f2016-11-15 23:20:01 +0100627 n_bytes_b0);
Dave Barachba868bb2016-08-08 09:51:21 -0400628 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700629 }
630
Dave Barachba868bb2016-08-08 09:51:21 -0400631 vlib_put_next_frame (vm, node, next_index, n_left_to_tx);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700632 }
633
634 /* Update main interface stats. */
635 vlib_increment_combined_counter (im->combined_sw_if_counters
Dave Barachba868bb2016-08-08 09:51:21 -0400636 + VNET_INTERFACE_COUNTER_TX,
Damjan Marion586afd72017-04-05 19:18:20 +0200637 thread_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400638 rt->sw_if_index, n_packets, n_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700639 return n_buffers;
640}
641
Damjan Marion8b2247d2016-12-02 08:09:45 +0100642VLIB_NODE_FUNCTION_MULTIARCH_CLONE (vnet_interface_output_node);
643CLIB_MULTIARCH_SELECT_FN (vnet_interface_output_node);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700644
645/* Use buffer's sw_if_index[VNET_TX] to choose output interface. */
646static uword
647vnet_per_buffer_interface_output (vlib_main_t * vm,
648 vlib_node_runtime_t * node,
649 vlib_frame_t * frame)
650{
Dave Barachba868bb2016-08-08 09:51:21 -0400651 vnet_main_t *vnm = vnet_get_main ();
652 u32 n_left_to_next, *from, *to_next;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700653 u32 n_left_from, next_index;
654
655 n_left_from = frame->n_vectors;
656
657 from = vlib_frame_args (frame);
658 next_index = node->cached_next_index;
659
660 while (n_left_from > 0)
661 {
662 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
663
664 while (n_left_from >= 4 && n_left_to_next >= 2)
665 {
666 u32 bi0, bi1, next0, next1;
Dave Barachba868bb2016-08-08 09:51:21 -0400667 vlib_buffer_t *b0, *b1;
668 vnet_hw_interface_t *hi0, *hi1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700669
670 /* Prefetch next iteration. */
671 vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
672 vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
673
674 bi0 = from[0];
675 bi1 = from[1];
676 to_next[0] = bi0;
677 to_next[1] = bi1;
678 from += 2;
679 to_next += 2;
680 n_left_to_next -= 2;
681 n_left_from -= 2;
682
683 b0 = vlib_get_buffer (vm, bi0);
684 b1 = vlib_get_buffer (vm, bi1);
685
Dave Barachba868bb2016-08-08 09:51:21 -0400686 hi0 =
687 vnet_get_sup_hw_interface (vnm,
688 vnet_buffer (b0)->sw_if_index
689 [VLIB_TX]);
690 hi1 =
691 vnet_get_sup_hw_interface (vnm,
692 vnet_buffer (b1)->sw_if_index
693 [VLIB_TX]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700694
695 next0 = hi0->hw_if_index;
696 next1 = hi1->hw_if_index;
697
Dave Barachba868bb2016-08-08 09:51:21 -0400698 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
699 n_left_to_next, bi0, bi1, next0,
700 next1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700701 }
702
703 while (n_left_from > 0 && n_left_to_next > 0)
704 {
705 u32 bi0, next0;
Dave Barachba868bb2016-08-08 09:51:21 -0400706 vlib_buffer_t *b0;
707 vnet_hw_interface_t *hi0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700708
709 bi0 = from[0];
710 to_next[0] = bi0;
711 from += 1;
712 to_next += 1;
713 n_left_to_next -= 1;
714 n_left_from -= 1;
715
716 b0 = vlib_get_buffer (vm, bi0);
717
Dave Barachba868bb2016-08-08 09:51:21 -0400718 hi0 =
719 vnet_get_sup_hw_interface (vnm,
720 vnet_buffer (b0)->sw_if_index
721 [VLIB_TX]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700722
723 next0 = hi0->hw_if_index;
724
Dave Barachba868bb2016-08-08 09:51:21 -0400725 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
726 n_left_to_next, bi0, next0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700727 }
728
729 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
730 }
731
732 return frame->n_vectors;
733}
734
735always_inline u32
736counter_index (vlib_main_t * vm, vlib_error_t e)
737{
Dave Barachba868bb2016-08-08 09:51:21 -0400738 vlib_node_t *n;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700739 u32 ci, ni;
740
741 ni = vlib_error_get_node (e);
742 n = vlib_get_node (vm, ni);
743
744 ci = vlib_error_get_code (e);
745 ASSERT (ci < n->n_errors);
746
747 ci += n->error_heap_index;
748
749 return ci;
750}
751
Dave Barachba868bb2016-08-08 09:51:21 -0400752static u8 *
753format_vnet_error_trace (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700754{
Dave Barachba868bb2016-08-08 09:51:21 -0400755 vlib_main_t *vm = va_arg (*va, vlib_main_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700756 CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
Dave Barachba868bb2016-08-08 09:51:21 -0400757 vlib_error_t *e = va_arg (*va, vlib_error_t *);
758 vlib_node_t *error_node;
759 vlib_error_main_t *em = &vm->error_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700760 u32 i;
761
762 error_node = vlib_get_node (vm, vlib_error_get_node (e[0]));
763 i = counter_index (vm, e[0]);
764 s = format (s, "%v: %s", error_node->name, em->error_strings_heap[i]);
765
766 return s;
767}
768
769static void
770trace_errors_with_buffers (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400771 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700772{
Dave Barachba868bb2016-08-08 09:51:21 -0400773 u32 n_left, *buffers;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700774
775 buffers = vlib_frame_vector_args (frame);
776 n_left = frame->n_vectors;
Dave Barachba868bb2016-08-08 09:51:21 -0400777
Ed Warnickecb9cada2015-12-08 15:45:58 -0700778 while (n_left >= 4)
779 {
780 u32 bi0, bi1;
Dave Barachba868bb2016-08-08 09:51:21 -0400781 vlib_buffer_t *b0, *b1;
782 vlib_error_t *t0, *t1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700783
784 /* Prefetch next iteration. */
785 vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
786 vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
787
788 bi0 = buffers[0];
789 bi1 = buffers[1];
790
791 b0 = vlib_get_buffer (vm, bi0);
792 b1 = vlib_get_buffer (vm, bi1);
793
794 if (b0->flags & VLIB_BUFFER_IS_TRACED)
795 {
796 t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
797 t0[0] = b0->error;
798 }
799 if (b1->flags & VLIB_BUFFER_IS_TRACED)
800 {
801 t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
802 t1[0] = b1->error;
803 }
804 buffers += 2;
805 n_left -= 2;
806 }
807
808 while (n_left >= 1)
809 {
810 u32 bi0;
Dave Barachba868bb2016-08-08 09:51:21 -0400811 vlib_buffer_t *b0;
812 vlib_error_t *t0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700813
814 bi0 = buffers[0];
815
816 b0 = vlib_get_buffer (vm, bi0);
817
818 if (b0->flags & VLIB_BUFFER_IS_TRACED)
819 {
820 t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
821 t0[0] = b0->error;
822 }
823 buffers += 1;
824 n_left -= 1;
825 }
826}
827
828static u8 *
829validate_error (vlib_main_t * vm, vlib_error_t * e, u32 index)
830{
831 uword node_index = vlib_error_get_node (e[0]);
832 uword code = vlib_error_get_code (e[0]);
Dave Barachba868bb2016-08-08 09:51:21 -0400833 vlib_node_t *n;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700834
835 if (node_index >= vec_len (vm->node_main.nodes))
836 return format (0, "[%d], node index out of range 0x%x, error 0x%x",
837 index, node_index, e[0]);
838
839 n = vlib_get_node (vm, node_index);
840 if (code >= n->n_errors)
841 return format (0, "[%d], code %d out of range for node %v",
842 index, code, n->name);
843
844 return 0;
845}
846
847static u8 *
848validate_error_frame (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400849 vlib_node_runtime_t * node, vlib_frame_t * f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700850{
Dave Barachba868bb2016-08-08 09:51:21 -0400851 u32 *buffers = vlib_frame_args (f);
852 vlib_buffer_t *b;
853 u8 *msg = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700854 uword i;
855
856 for (i = 0; i < f->n_vectors; i++)
857 {
858 b = vlib_get_buffer (vm, buffers[i]);
859 msg = validate_error (vm, &b->error, i);
860 if (msg)
861 return msg;
862 }
863
864 return msg;
865}
866
Dave Barachba868bb2016-08-08 09:51:21 -0400867typedef enum
868{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700869 VNET_ERROR_DISPOSITION_DROP,
870 VNET_ERROR_DISPOSITION_PUNT,
871 VNET_ERROR_N_DISPOSITION,
872} vnet_error_disposition_t;
873
874always_inline void
875do_packet (vlib_main_t * vm, vlib_error_t a)
876{
Dave Barachba868bb2016-08-08 09:51:21 -0400877 vlib_error_main_t *em = &vm->error_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700878 u32 i = counter_index (vm, a);
879 em->counters[i] += 1;
880 vlib_error_elog_count (vm, i, 1);
881}
Dave Barachba868bb2016-08-08 09:51:21 -0400882
Ed Warnickecb9cada2015-12-08 15:45:58 -0700883static_always_inline uword
884process_drop_punt (vlib_main_t * vm,
885 vlib_node_runtime_t * node,
Dave Barachba868bb2016-08-08 09:51:21 -0400886 vlib_frame_t * frame, vnet_error_disposition_t disposition)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700887{
Dave Barachba868bb2016-08-08 09:51:21 -0400888 vnet_main_t *vnm = vnet_get_main ();
889 vlib_error_main_t *em = &vm->error_main;
890 u32 *buffers, *first_buffer;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700891 vlib_error_t current_error;
892 u32 current_counter_index, n_errors_left;
893 u32 current_sw_if_index, n_errors_current_sw_if_index;
894 u64 current_counter;
Dave Barachba868bb2016-08-08 09:51:21 -0400895 vlib_simple_counter_main_t *cm;
Damjan Marion586afd72017-04-05 19:18:20 +0200896 u32 thread_index = vm->thread_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700897
898 static vlib_error_t memory[VNET_ERROR_N_DISPOSITION];
899 static char memory_init[VNET_ERROR_N_DISPOSITION];
900
901 buffers = vlib_frame_args (frame);
902 first_buffer = buffers;
903
904 {
Dave Barachba868bb2016-08-08 09:51:21 -0400905 vlib_buffer_t *b = vlib_get_buffer (vm, first_buffer[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700906
Dave Barachba868bb2016-08-08 09:51:21 -0400907 if (!memory_init[disposition])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700908 {
909 memory_init[disposition] = 1;
910 memory[disposition] = b->error;
911 }
912
913 current_sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
914 n_errors_current_sw_if_index = 0;
915 }
916
917 current_error = memory[disposition];
918 current_counter_index = counter_index (vm, memory[disposition]);
919 current_counter = em->counters[current_counter_index];
920
921 if (node->flags & VLIB_NODE_FLAG_TRACE)
922 trace_errors_with_buffers (vm, node, frame);
Dave Barachba868bb2016-08-08 09:51:21 -0400923
Ed Warnickecb9cada2015-12-08 15:45:58 -0700924 n_errors_left = frame->n_vectors;
925 cm = vec_elt_at_index (vnm->interface_main.sw_if_counters,
926 (disposition == VNET_ERROR_DISPOSITION_PUNT
927 ? VNET_INTERFACE_COUNTER_PUNT
928 : VNET_INTERFACE_COUNTER_DROP));
929
930 while (n_errors_left >= 2)
931 {
Dave Barachba868bb2016-08-08 09:51:21 -0400932 vlib_buffer_t *b0, *b1;
933 vnet_sw_interface_t *sw_if0, *sw_if1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700934 vlib_error_t e0, e1;
935 u32 bi0, bi1;
936 u32 sw_if_index0, sw_if_index1;
937
938 bi0 = buffers[0];
939 bi1 = buffers[1];
940
941 buffers += 2;
942 n_errors_left -= 2;
943
944 b0 = vlib_get_buffer (vm, bi0);
945 b1 = vlib_get_buffer (vm, bi1);
946
947 e0 = b0->error;
948 e1 = b1->error;
949
950 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
951 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
952
953 /* Speculate that sw_if_index == sw_if_index[01]. */
954 n_errors_current_sw_if_index += 2;
955
956 /* Speculatively assume all 2 (node, code) pairs are equal
Dave Barachba868bb2016-08-08 09:51:21 -0400957 to current (node, code). */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700958 current_counter += 2;
959
960 if (PREDICT_FALSE (e0 != current_error
961 || e1 != current_error
962 || sw_if_index0 != current_sw_if_index
963 || sw_if_index1 != current_sw_if_index))
964 {
965 current_counter -= 2;
966 n_errors_current_sw_if_index -= 2;
967
Damjan Marion586afd72017-04-05 19:18:20 +0200968 vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
969 vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700970
971 /* Increment super-interface drop/punt counters for
972 sub-interfaces. */
973 sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
974 vlib_increment_simple_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200975 (cm, thread_index, sw_if0->sup_sw_if_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400976 sw_if0->sup_sw_if_index != sw_if_index0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700977
978 sw_if1 = vnet_get_sw_interface (vnm, sw_if_index1);
979 vlib_increment_simple_counter
Damjan Marion586afd72017-04-05 19:18:20 +0200980 (cm, thread_index, sw_if1->sup_sw_if_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400981 sw_if1->sup_sw_if_index != sw_if_index1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700982
983 em->counters[current_counter_index] = current_counter;
984 do_packet (vm, e0);
985 do_packet (vm, e1);
986
987 /* For 2 repeated errors, change current error. */
988 if (e0 == e1 && e1 != current_error)
989 {
990 current_error = e0;
991 current_counter_index = counter_index (vm, e0);
992 }
993 current_counter = em->counters[current_counter_index];
994 }
995 }
996
997 while (n_errors_left >= 1)
998 {
Dave Barachba868bb2016-08-08 09:51:21 -0400999 vlib_buffer_t *b0;
1000 vnet_sw_interface_t *sw_if0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001001 vlib_error_t e0;
1002 u32 bi0, sw_if_index0;
1003
1004 bi0 = buffers[0];
1005
1006 buffers += 1;
1007 n_errors_left -= 1;
1008 current_counter += 1;
1009
1010 b0 = vlib_get_buffer (vm, bi0);
1011 e0 = b0->error;
1012
1013 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1014
1015 /* Increment drop/punt counters. */
Damjan Marion586afd72017-04-05 19:18:20 +02001016 vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001017
1018 /* Increment super-interface drop/punt counters for sub-interfaces. */
1019 sw_if0 = vnet_get_sw_interface (vnm, sw_if_index0);
Damjan Marion586afd72017-04-05 19:18:20 +02001020 vlib_increment_simple_counter (cm, thread_index,
1021 sw_if0->sup_sw_if_index,
Ed Warnickecb9cada2015-12-08 15:45:58 -07001022 sw_if0->sup_sw_if_index != sw_if_index0);
1023
1024 if (PREDICT_FALSE (e0 != current_error))
1025 {
1026 current_counter -= 1;
1027
1028 vlib_error_elog_count (vm, current_counter_index,
1029 (current_counter
1030 - em->counters[current_counter_index]));
Dave Barachba868bb2016-08-08 09:51:21 -04001031
Ed Warnickecb9cada2015-12-08 15:45:58 -07001032 em->counters[current_counter_index] = current_counter;
1033
1034 do_packet (vm, e0);
1035 current_error = e0;
1036 current_counter_index = counter_index (vm, e0);
1037 current_counter = em->counters[current_counter_index];
1038 }
1039 }
1040
1041 if (n_errors_current_sw_if_index > 0)
1042 {
Dave Barachba868bb2016-08-08 09:51:21 -04001043 vnet_sw_interface_t *si;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001044
Damjan Marion586afd72017-04-05 19:18:20 +02001045 vlib_increment_simple_counter (cm, thread_index, current_sw_if_index,
Ed Warnickecb9cada2015-12-08 15:45:58 -07001046 n_errors_current_sw_if_index);
1047
1048 si = vnet_get_sw_interface (vnm, current_sw_if_index);
1049 if (si->sup_sw_if_index != current_sw_if_index)
Damjan Marion586afd72017-04-05 19:18:20 +02001050 vlib_increment_simple_counter (cm, thread_index, si->sup_sw_if_index,
Dave Barachba868bb2016-08-08 09:51:21 -04001051 n_errors_current_sw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001052 }
1053
1054 vlib_error_elog_count (vm, current_counter_index,
1055 (current_counter
1056 - em->counters[current_counter_index]));
1057
1058 /* Return cached counter. */
1059 em->counters[current_counter_index] = current_counter;
1060
1061 /* Save memory for next iteration. */
1062 memory[disposition] = current_error;
1063
Dave Barachba868bb2016-08-08 09:51:21 -04001064 if (disposition == VNET_ERROR_DISPOSITION_DROP || !vm->os_punt_frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001065 {
Dave Barachba868bb2016-08-08 09:51:21 -04001066 vlib_buffer_free (vm, first_buffer, frame->n_vectors);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001067
1068 /* If there is no punt function, free the frame as well. */
Dave Barachba868bb2016-08-08 09:51:21 -04001069 if (disposition == VNET_ERROR_DISPOSITION_PUNT && !vm->os_punt_frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001070 vlib_frame_free (vm, node, frame);
1071 }
1072 else
1073 vm->os_punt_frame (vm, node, frame);
1074
1075 return frame->n_vectors;
1076}
1077
Dave Barachba868bb2016-08-08 09:51:21 -04001078static inline void
1079pcap_drop_trace (vlib_main_t * vm,
1080 vnet_interface_main_t * im, vlib_frame_t * f)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001081{
Dave Barachba868bb2016-08-08 09:51:21 -04001082 u32 *from;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001083 u32 n_left = f->n_vectors;
Dave Barachba868bb2016-08-08 09:51:21 -04001084 vlib_buffer_t *b0, *p1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001085 u32 bi0;
1086 i16 save_current_data;
1087 u16 save_current_length;
1088
1089 from = vlib_frame_vector_args (f);
1090
1091 while (n_left > 0)
1092 {
1093 if (PREDICT_TRUE (n_left > 1))
Dave Barachba868bb2016-08-08 09:51:21 -04001094 {
1095 p1 = vlib_get_buffer (vm, from[1]);
1096 vlib_prefetch_buffer_header (p1, LOAD);
1097 }
1098
Ed Warnickecb9cada2015-12-08 15:45:58 -07001099 bi0 = from[0];
1100 b0 = vlib_get_buffer (vm, bi0);
1101 from++;
1102 n_left--;
Dave Barachba868bb2016-08-08 09:51:21 -04001103
Ed Warnickecb9cada2015-12-08 15:45:58 -07001104 /* See if we're pointedly ignoring this specific error */
Dave Barachba868bb2016-08-08 09:51:21 -04001105 if (im->pcap_drop_filter_hash
1106 && hash_get (im->pcap_drop_filter_hash, b0->error))
1107 continue;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001108
1109 /* Trace all drops, or drops received on a specific interface */
1110 if (im->pcap_sw_if_index == 0 ||
Dave Barachba868bb2016-08-08 09:51:21 -04001111 im->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
1112 {
1113 save_current_data = b0->current_data;
1114 save_current_length = b0->current_length;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001115
Dave Barachba868bb2016-08-08 09:51:21 -04001116 /*
1117 * Typically, we'll need to rewind the buffer
1118 */
1119 if (b0->current_data > 0)
1120 vlib_buffer_advance (b0, (word) - b0->current_data);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001121
Dave Barachba868bb2016-08-08 09:51:21 -04001122 pcap_add_buffer (&im->pcap_main, vm, bi0, 512);
1123
1124 b0->current_data = save_current_data;
1125 b0->current_length = save_current_length;
1126 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001127 }
1128}
1129
Dave Barachba868bb2016-08-08 09:51:21 -04001130void
1131vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001132{
Dave Barachba868bb2016-08-08 09:51:21 -04001133 vnet_interface_main_t *im = &vnet_get_main ()->interface_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001134
1135 if (im->pcap_drop_filter_hash == 0)
Dave Barachba868bb2016-08-08 09:51:21 -04001136 im->pcap_drop_filter_hash = hash_create (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001137
1138 if (is_add)
1139 hash_set (im->pcap_drop_filter_hash, error_index, 1);
1140 else
1141 hash_unset (im->pcap_drop_filter_hash, error_index);
1142}
1143
1144static uword
1145process_drop (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -04001146 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001147{
Dave Barachba868bb2016-08-08 09:51:21 -04001148 vnet_interface_main_t *im = &vnet_get_main ()->interface_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001149
1150 if (PREDICT_FALSE (im->drop_pcap_enable))
1151 pcap_drop_trace (vm, im, frame);
1152
1153 return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
1154}
1155
1156static uword
1157process_punt (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -04001158 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001159{
1160 return process_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_PUNT);
1161}
1162
Dave Barachba868bb2016-08-08 09:51:21 -04001163/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001164VLIB_REGISTER_NODE (drop_buffers,static) = {
1165 .function = process_drop,
1166 .name = "error-drop",
1167 .flags = VLIB_NODE_FLAG_IS_DROP,
1168 .vector_size = sizeof (u32),
1169 .format_trace = format_vnet_error_trace,
1170 .validate_frame = validate_error_frame,
1171};
Dave Barachba868bb2016-08-08 09:51:21 -04001172/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001173
Dave Barachba868bb2016-08-08 09:51:21 -04001174VLIB_NODE_FUNCTION_MULTIARCH (drop_buffers, process_drop);
Damjan Marion1c80e832016-05-11 23:07:18 +02001175
Dave Barachba868bb2016-08-08 09:51:21 -04001176/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001177VLIB_REGISTER_NODE (punt_buffers,static) = {
1178 .function = process_punt,
1179 .flags = (VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
1180 | VLIB_NODE_FLAG_IS_PUNT),
1181 .name = "error-punt",
1182 .vector_size = sizeof (u32),
1183 .format_trace = format_vnet_error_trace,
1184 .validate_frame = validate_error_frame,
1185};
Dave Barachba868bb2016-08-08 09:51:21 -04001186/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001187
Dave Barachba868bb2016-08-08 09:51:21 -04001188VLIB_NODE_FUNCTION_MULTIARCH (punt_buffers, process_punt);
Damjan Marion1c80e832016-05-11 23:07:18 +02001189
Dave Barachba868bb2016-08-08 09:51:21 -04001190/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001191VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node,static) = {
1192 .function = vnet_per_buffer_interface_output,
1193 .name = "interface-output",
1194 .vector_size = sizeof (u32),
1195};
Dave Barachba868bb2016-08-08 09:51:21 -04001196/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001197
Dave Barachba868bb2016-08-08 09:51:21 -04001198VLIB_NODE_FUNCTION_MULTIARCH (vnet_per_buffer_interface_output_node,
1199 vnet_per_buffer_interface_output);
Damjan Marion1c80e832016-05-11 23:07:18 +02001200
Damjan Marion152e21d2016-11-29 14:55:43 +01001201static uword
1202interface_tx_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1203 vlib_frame_t * from_frame)
1204{
1205 vnet_main_t *vnm = vnet_get_main ();
1206 u32 last_sw_if_index = ~0;
1207 vlib_frame_t *to_frame = 0;
1208 vnet_hw_interface_t *hw = 0;
1209 u32 *from, *to_next = 0;
1210 u32 n_left_from;
1211
1212 from = vlib_frame_vector_args (from_frame);
1213 n_left_from = from_frame->n_vectors;
1214 while (n_left_from > 0)
1215 {
1216 u32 bi0;
1217 vlib_buffer_t *b0;
1218 u32 sw_if_index0;
1219
1220 bi0 = from[0];
1221 from++;
1222 n_left_from--;
1223 b0 = vlib_get_buffer (vm, bi0);
1224 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
1225
1226 if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
1227 {
1228 if (to_frame)
1229 {
1230 hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
1231 vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1232 }
1233 last_sw_if_index = sw_if_index0;
1234 hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1235 to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
1236 to_next = vlib_frame_vector_args (to_frame);
1237 }
1238
1239 to_next[0] = bi0;
1240 to_next++;
1241 to_frame->n_vectors++;
1242 }
1243 vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
1244 return from_frame->n_vectors;
1245}
1246
1247/* *INDENT-OFF* */
1248VLIB_REGISTER_NODE (interface_tx, static) = {
1249 .function = interface_tx_node_fn,
1250 .name = "interface-tx",
1251 .vector_size = sizeof (u32),
1252 .n_next_nodes = 1,
1253 .next_nodes = {
1254 [0] = "error-drop",
1255 },
1256};
1257
1258VNET_FEATURE_ARC_INIT (interface_output, static) =
1259{
1260 .arc_name = "interface-output",
1261 .start_nodes = VNET_FEATURES (0),
1262 .arc_index_ptr = &vnet_main.interface_main.output_feature_arc_index,
1263};
1264
Pavel Kotucek3a2a1c42016-12-06 10:10:10 +01001265VNET_FEATURE_INIT (span_tx, static) = {
1266 .arc_name = "interface-output",
1267 .node_name = "span-output",
1268 .runs_before = VNET_FEATURES ("interface-tx"),
1269};
1270
Damjan Marion152e21d2016-11-29 14:55:43 +01001271VNET_FEATURE_INIT (interface_tx, static) = {
1272 .arc_name = "interface-output",
1273 .node_name = "interface-tx",
1274 .runs_before = 0,
1275};
1276/* *INDENT-ON* */
1277
Ed Warnickecb9cada2015-12-08 15:45:58 -07001278clib_error_t *
1279vnet_per_buffer_interface_output_hw_interface_add_del (vnet_main_t * vnm,
1280 u32 hw_if_index,
1281 u32 is_create)
1282{
Dave Barachba868bb2016-08-08 09:51:21 -04001283 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001284 u32 next_index;
1285
1286 next_index = vlib_node_add_next_with_slot
1287 (vnm->vlib_main, vnet_per_buffer_interface_output_node.index,
1288 hi->output_node_index,
1289 /* next_index */ hw_if_index);
1290
1291 ASSERT (next_index == hw_if_index);
1292
1293 return 0;
1294}
1295
Dave Barachba868bb2016-08-08 09:51:21 -04001296VNET_HW_INTERFACE_ADD_DEL_FUNCTION
1297 (vnet_per_buffer_interface_output_hw_interface_add_del);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001298
1299static clib_error_t *
1300pcap_drop_trace_command_fn (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -04001301 unformat_input_t * input,
1302 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001303{
Dave Barachba868bb2016-08-08 09:51:21 -04001304 vnet_main_t *vnm = vnet_get_main ();
1305 vnet_interface_main_t *im = &vnm->interface_main;
1306 u8 *filename;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001307 u32 max;
1308 int matched = 0;
Dave Barachba868bb2016-08-08 09:51:21 -04001309 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001310
Dave Barachba868bb2016-08-08 09:51:21 -04001311 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001312 {
1313 if (unformat (input, "on"))
Dave Barachba868bb2016-08-08 09:51:21 -04001314 {
1315 if (im->drop_pcap_enable == 0)
1316 {
1317 if (im->pcap_filename == 0)
1318 im->pcap_filename = format (0, "/tmp/drop.pcap%c", 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001319
Dave Barachba868bb2016-08-08 09:51:21 -04001320 memset (&im->pcap_main, 0, sizeof (im->pcap_main));
1321 im->pcap_main.file_name = (char *) im->pcap_filename;
1322 im->pcap_main.n_packets_to_capture = 100;
1323 if (im->pcap_pkts_to_capture)
1324 im->pcap_main.n_packets_to_capture = im->pcap_pkts_to_capture;
1325
1326 im->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
1327 im->drop_pcap_enable = 1;
1328 matched = 1;
1329 vlib_cli_output (vm, "pcap drop capture on...");
1330 }
1331 else
1332 {
1333 vlib_cli_output (vm, "pcap drop capture already on...");
1334 }
1335 matched = 1;
1336 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001337 else if (unformat (input, "off"))
Dave Barachba868bb2016-08-08 09:51:21 -04001338 {
1339 matched = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001340
Dave Barachba868bb2016-08-08 09:51:21 -04001341 if (im->drop_pcap_enable)
1342 {
1343 vlib_cli_output (vm, "captured %d pkts...",
1344 im->pcap_main.n_packets_captured);
1345 if (im->pcap_main.n_packets_captured)
1346 {
1347 im->pcap_main.n_packets_to_capture =
1348 im->pcap_main.n_packets_captured;
1349 error = pcap_write (&im->pcap_main);
1350 if (error)
1351 clib_error_report (error);
1352 else
1353 vlib_cli_output (vm, "saved to %s...", im->pcap_filename);
1354 }
1355 }
1356 else
1357 {
1358 vlib_cli_output (vm, "pcap drop capture already off...");
1359 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001360
Dave Barachba868bb2016-08-08 09:51:21 -04001361 im->drop_pcap_enable = 0;
1362 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001363 else if (unformat (input, "max %d", &max))
Dave Barachba868bb2016-08-08 09:51:21 -04001364 {
1365 im->pcap_pkts_to_capture = max;
1366 matched = 1;
1367 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001368
Dave Barachba868bb2016-08-08 09:51:21 -04001369 else if (unformat (input, "intfc %U",
1370 unformat_vnet_sw_interface, vnm,
1371 &im->pcap_sw_if_index))
1372 matched = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001373 else if (unformat (input, "intfc any"))
Dave Barachba868bb2016-08-08 09:51:21 -04001374 {
1375 im->pcap_sw_if_index = 0;
1376 matched = 1;
1377 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001378 else if (unformat (input, "file %s", &filename))
Dave Barachba868bb2016-08-08 09:51:21 -04001379 {
1380 u8 *chroot_filename;
1381 /* Brain-police user path input */
1382 if (strstr ((char *) filename, "..")
1383 || index ((char *) filename, '/'))
1384 {
1385 vlib_cli_output (vm, "illegal characters in filename '%s'",
1386 filename);
1387 continue;
1388 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001389
Dave Barachba868bb2016-08-08 09:51:21 -04001390 chroot_filename = format (0, "/tmp/%s%c", filename, 0);
1391 vec_free (filename);
1392
1393 if (im->pcap_filename)
1394 vec_free (im->pcap_filename);
Dave Barachba868bb2016-08-08 09:51:21 -04001395 im->pcap_filename = chroot_filename;
jerryian361abef2017-04-10 18:48:07 +08001396 im->pcap_main.file_name = (char *) im->pcap_filename;
Dave Barachba868bb2016-08-08 09:51:21 -04001397 matched = 1;
1398 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001399 else if (unformat (input, "status"))
Dave Barachba868bb2016-08-08 09:51:21 -04001400 {
1401 if (im->drop_pcap_enable == 0)
1402 {
1403 vlib_cli_output (vm, "pcap drop capture is off...");
1404 continue;
1405 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001406
Dave Barachba868bb2016-08-08 09:51:21 -04001407 vlib_cli_output (vm, "pcap drop capture: %d of %d pkts...",
1408 im->pcap_main.n_packets_captured,
1409 im->pcap_main.n_packets_to_capture);
1410 matched = 1;
1411 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001412
1413 else
Dave Barachba868bb2016-08-08 09:51:21 -04001414 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001415 }
1416
1417 if (matched == 0)
Dave Barachba868bb2016-08-08 09:51:21 -04001418 return clib_error_return (0, "unknown input `%U'",
1419 format_unformat_error, input);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001420
1421 return 0;
1422}
1423
Dave Barachba868bb2016-08-08 09:51:21 -04001424/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001425VLIB_CLI_COMMAND (pcap_trace_command, static) = {
Dave Barachba868bb2016-08-08 09:51:21 -04001426 .path = "pcap drop trace",
1427 .short_help =
1428 "pcap drop trace on off max <nn> intfc <intfc> file <name> status",
1429 .function = pcap_drop_trace_command_fn,
Ed Warnickecb9cada2015-12-08 15:45:58 -07001430};
Dave Barachba868bb2016-08-08 09:51:21 -04001431/* *INDENT-ON* */
1432
1433/*
1434 * fd.io coding-style-patch-verification: ON
1435 *
1436 * Local Variables:
1437 * eval: (c-set-style "gnu")
1438 * End:
1439 */