2 * Copyright (c) 2018 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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vnet/vnet.h>
17 #include <vnet/adj/rewrite.h>
18 #include <vnet/ethernet/ethernet.h>
19 #include <vnet/adj/adj.h>
20 #include <vnet/ip/ip.h>
22 typedef enum punt_next_t_
28 typedef struct punt_trace_t_
30 vlib_punt_reason_t pt_reason;
33 #define SW_IF_INDEX_PG0 1
34 #define SW_IF_INDEX_PG1 2
36 index_t *adjs[FIB_PROTOCOL_IP_MAX];
38 static vlib_punt_reason_t punt_reason_v4, punt_reason_v6;
39 static vlib_punt_hdl_t punt_hdl;
42 format_punt_trace (u8 * s, va_list * args)
44 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
45 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
46 punt_trace_t *t = va_arg (*args, punt_trace_t *);
48 s = format (s, "punt: %U", format_vlib_punt_reason, t->pt_reason);
54 punt_test_fwd (vlib_main_t * vm,
55 vlib_node_runtime_t * node,
56 vlib_frame_t * frame, fib_protocol_t fproto, u32 sw_if_index)
58 u32 n_left_from, *from, *to_next, next_index;
60 from = vlib_frame_vector_args (frame);
61 n_left_from = frame->n_vectors;
62 next_index = node->cached_next_index;
64 while (n_left_from > 0)
68 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
70 while (n_left_from > 0 && n_left_to_next > 0)
78 bi0 = to_next[0] = from[0];
84 b0 = vlib_get_buffer (vm, bi0);
85 vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index;
86 ai0 = adjs[fproto][sw_if_index];
89 ip0 = vlib_buffer_get_current (b0);
91 vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
92 vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
94 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
95 to_next, n_left_to_next, bi0, 0);
97 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
100 return frame->n_vectors;
104 punt_test_pg0_ip4 (vlib_main_t * vm,
105 vlib_node_runtime_t * node, vlib_frame_t * frame)
107 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP4, SW_IF_INDEX_PG0));
111 punt_test_pg1_ip4 (vlib_main_t * vm,
112 vlib_node_runtime_t * node, vlib_frame_t * frame)
114 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP4, SW_IF_INDEX_PG1));
118 punt_test_pg0_ip6 (vlib_main_t * vm,
119 vlib_node_runtime_t * node, vlib_frame_t * frame)
121 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP6, SW_IF_INDEX_PG0));
125 punt_test_pg1_ip6 (vlib_main_t * vm,
126 vlib_node_runtime_t * node, vlib_frame_t * frame)
128 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP6, SW_IF_INDEX_PG1));
132 VLIB_REGISTER_NODE (punt_test_pg0_ip4_node) = {
133 .function = punt_test_pg0_ip4,
134 .name = "punt-test-pg0-ip4",
135 .vector_size = sizeof (u32),
136 .format_trace = format_punt_trace,
138 VLIB_REGISTER_NODE (punt_test_pg1_ip4_node) = {
139 .function = punt_test_pg1_ip4,
140 .name = "punt-test-pg1-ip4",
141 .vector_size = sizeof (u32),
142 .format_trace = format_punt_trace,
144 VLIB_REGISTER_NODE (punt_test_pg0_ip6_node) = {
145 .function = punt_test_pg0_ip6,
146 .name = "punt-test-pg0-ip6",
147 .vector_size = sizeof (u32),
148 .format_trace = format_punt_trace,
150 VLIB_REGISTER_NODE (punt_test_pg1_ip6_node) = {
151 .function = punt_test_pg1_ip6,
152 .name = "punt-test-pg1-ip6",
153 .vector_size = sizeof (u32),
154 .format_trace = format_punt_trace,
158 typedef struct punt_feat_trace_t_
160 vlib_punt_reason_t pt_reason;
164 punt_test_feat_inline (vlib_main_t * vm,
165 vlib_node_runtime_t * node,
166 vlib_frame_t * frame, u8 is_ip4)
168 u32 n_left_from, *from, *to_next, next_index;
170 from = vlib_frame_vector_args (frame);
171 n_left_from = frame->n_vectors;
172 next_index = node->cached_next_index;
174 while (n_left_from > 0)
178 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
180 while (n_left_from > 0 && n_left_to_next > 0)
185 bi0 = to_next[0] = from[0];
192 b0 = vlib_get_buffer (vm, bi0);
195 b0->punt_reason = punt_reason_v4;
197 b0->punt_reason = punt_reason_v6;
199 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
201 punt_feat_trace_t *t;
203 b0 = vlib_get_buffer (vm, bi0);
205 t = vlib_add_trace (vm, node, b0, sizeof (*t));
206 t->pt_reason = b0->punt_reason;
208 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
209 to_next, n_left_to_next,
212 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
215 return frame->n_vectors;
219 format_punt_feat_trace (u8 * s, va_list * args)
221 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
222 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
223 punt_feat_trace_t *t = va_arg (*args, punt_feat_trace_t *);
225 s = format (s, "reason: %U", format_vlib_punt_reason, t->pt_reason);
231 punt_test_feat_ip4 (vlib_main_t * vm,
232 vlib_node_runtime_t * node, vlib_frame_t * frame)
234 return (punt_test_feat_inline (vm, node, frame, 1));
238 punt_test_feat_ip6 (vlib_main_t * vm,
239 vlib_node_runtime_t * node, vlib_frame_t * frame)
241 return (punt_test_feat_inline (vm, node, frame, 0));
245 VLIB_REGISTER_NODE (punt_test_feat_ip6_node) = {
246 .function = punt_test_feat_ip6,
247 .name = "punt-test-feat-ip6",
248 .vector_size = sizeof (u32),
249 .format_trace = format_punt_feat_trace,
252 [0] = "punt-dispatch"
255 VLIB_REGISTER_NODE (punt_test_feat_ip4_node) = {
256 .function = punt_test_feat_ip4,
257 .name = "punt-test-feat-ip4",
258 .vector_size = sizeof (u32),
259 .format_trace = format_punt_feat_trace,
262 [0] = "punt-dispatch"
265 VNET_FEATURE_INIT (punt_test_feat_ip6_feature, static) =
267 .arc_name = "ip6-unicast",
268 .node_name = "punt-test-feat-ip6",
270 VNET_FEATURE_INIT (punt_test_feat_ip4_feature, static) =
272 .arc_name = "ip4-unicast",
273 .node_name = "punt-test-feat-ip4",
277 static clib_error_t *
278 punt_test (vlib_main_t * vm,
279 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
281 ip46_address_t ip46 = ip46_address_initializer;
282 fib_protocol_t fproto;
287 vnm = vnet_get_main ();
288 fproto = FIB_PROTOCOL_IP4;
290 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
294 if (unformat (input, "%U", unformat_ip4_address, &ip46.ip4))
296 fproto = FIB_PROTOCOL_IP4;
298 else if (unformat (input, "%U", unformat_ip6_address, &ip46.ip6))
300 fproto = FIB_PROTOCOL_IP6;
302 else if (unformat (input, "clear"))
304 vnet_feature_enable_disable ("ip4-unicast",
305 "punt-test-feat-ip4",
306 sw_if_index, 0, NULL, 0);
307 vnet_feature_enable_disable ("ip6-unicast",
308 "punt-test-feat-ip6",
309 sw_if_index, 0, NULL, 0);
315 * allocate a client and a reason
317 punt_hdl = vlib_punt_client_register ("test");
320 vlib_punt_reason_alloc (punt_hdl, "reason-v4", &punt_reason_v4);
322 vlib_punt_reason_alloc (punt_hdl, "reason-v6", &punt_reason_v6);
325 vnet_feature_enable_disable ("ip4-unicast",
326 "punt-test-feat-ip4",
327 sw_if_index, 1, NULL, 0);
328 vnet_feature_enable_disable ("ip6-unicast",
329 "punt-test-feat-ip6",
330 sw_if_index, 1, NULL, 0);
334 if (SW_IF_INDEX_PG0 == sw_if_index)
336 if (FIB_PROTOCOL_IP4 == fproto)
339 * register the node that will forward the punted packet
341 vlib_punt_register (punt_hdl, punt_reason_v4,
342 "punt-test-pg0-ip4");
343 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip4");
347 vlib_punt_register (punt_hdl, punt_reason_v6,
348 "punt-test-pg0-ip6");
349 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip6");
354 if (FIB_PROTOCOL_IP4 == fproto)
356 vlib_punt_register (punt_hdl, punt_reason_v4,
357 "punt-test-pg1-ip4");
358 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip4");
362 vlib_punt_register (punt_hdl, punt_reason_v6,
363 "punt-test-pg1-ip6");
364 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip6");
368 vlib_node_add_next (vm, from->index,
369 vnet_tx_node_index_for_sw_interface
372 vec_validate (adjs[fproto], sw_if_index);
374 adjs[fproto][sw_if_index] = adj_nbr_find (fproto,
375 fib_proto_to_link (fproto),
383 VLIB_CLI_COMMAND (test_fib_command, static) =
386 .short_help = "punt unit tests - DO NOT RUN ON A LIVE SYSTEM",
387 .function = punt_test,
392 * fd.io coding-style-patch-verification: ON
395 * eval: (c-set-style "gnu")