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;
34 * Per-thread clone vectors
38 #define SW_IF_INDEX_PG0 1
39 #define SW_IF_INDEX_PG1 2
41 index_t *adjs[FIB_PROTOCOL_IP_MAX];
43 static vlib_punt_reason_t punt_reason_v4, punt_reason_v6;
44 static vlib_punt_hdl_t punt_hdl;
47 format_punt_trace (u8 * s, va_list * args)
49 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
50 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
51 punt_trace_t *t = va_arg (*args, punt_trace_t *);
53 s = format (s, "punt: %U", format_vlib_punt_reason, t->pt_reason);
59 punt_test_fwd (vlib_main_t * vm,
60 vlib_node_runtime_t * node,
61 vlib_frame_t * frame, fib_protocol_t fproto, u32 sw_if_index)
63 u32 n_left_from, *from, *to_next, next_index;
65 from = vlib_frame_vector_args (frame);
66 n_left_from = frame->n_vectors;
67 next_index = node->cached_next_index;
69 while (n_left_from > 0)
73 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
75 while (n_left_from > 0 && n_left_to_next > 0)
83 bi0 = to_next[0] = from[0];
89 b0 = vlib_get_buffer (vm, bi0);
90 vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index;
91 ai0 = adjs[fproto][sw_if_index];
94 ip0 = vlib_buffer_get_current (b0);
96 vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
97 vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
99 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
100 to_next, n_left_to_next, bi0, 0);
102 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
105 return frame->n_vectors;
109 punt_test_pg0_ip4 (vlib_main_t * vm,
110 vlib_node_runtime_t * node, vlib_frame_t * frame)
112 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP4, SW_IF_INDEX_PG0));
116 punt_test_pg1_ip4 (vlib_main_t * vm,
117 vlib_node_runtime_t * node, vlib_frame_t * frame)
119 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP4, SW_IF_INDEX_PG1));
123 punt_test_pg0_ip6 (vlib_main_t * vm,
124 vlib_node_runtime_t * node, vlib_frame_t * frame)
126 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP6, SW_IF_INDEX_PG0));
130 punt_test_pg1_ip6 (vlib_main_t * vm,
131 vlib_node_runtime_t * node, vlib_frame_t * frame)
133 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP6, SW_IF_INDEX_PG1));
137 VLIB_REGISTER_NODE (punt_test_pg0_ip4_node) = {
138 .function = punt_test_pg0_ip4,
139 .name = "punt-test-pg0-ip4",
140 .vector_size = sizeof (u32),
141 .format_trace = format_punt_trace,
143 VLIB_REGISTER_NODE (punt_test_pg1_ip4_node) = {
144 .function = punt_test_pg1_ip4,
145 .name = "punt-test-pg1-ip4",
146 .vector_size = sizeof (u32),
147 .format_trace = format_punt_trace,
149 VLIB_REGISTER_NODE (punt_test_pg0_ip6_node) = {
150 .function = punt_test_pg0_ip6,
151 .name = "punt-test-pg0-ip6",
152 .vector_size = sizeof (u32),
153 .format_trace = format_punt_trace,
155 VLIB_REGISTER_NODE (punt_test_pg1_ip6_node) = {
156 .function = punt_test_pg1_ip6,
157 .name = "punt-test-pg1-ip6",
158 .vector_size = sizeof (u32),
159 .format_trace = format_punt_trace,
163 typedef struct punt_feat_trace_t_
165 vlib_punt_reason_t pt_reason;
169 punt_test_feat_inline (vlib_main_t * vm,
170 vlib_node_runtime_t * node,
171 vlib_frame_t * frame, u8 is_ip4)
173 u32 n_left_from, *from, *to_next, next_index;
175 from = vlib_frame_vector_args (frame);
176 n_left_from = frame->n_vectors;
177 next_index = node->cached_next_index;
179 while (n_left_from > 0)
183 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
185 while (n_left_from > 0 && n_left_to_next > 0)
190 bi0 = to_next[0] = from[0];
197 b0 = vlib_get_buffer (vm, bi0);
200 b0->punt_reason = punt_reason_v4;
202 b0->punt_reason = punt_reason_v6;
204 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
206 punt_feat_trace_t *t;
208 b0 = vlib_get_buffer (vm, bi0);
210 t = vlib_add_trace (vm, node, b0, sizeof (*t));
211 t->pt_reason = b0->punt_reason;
213 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
214 to_next, n_left_to_next,
217 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
220 return frame->n_vectors;
224 format_punt_feat_trace (u8 * s, va_list * args)
226 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
227 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
228 punt_feat_trace_t *t = va_arg (*args, punt_feat_trace_t *);
230 s = format (s, "reason: %U", format_vlib_punt_reason, t->pt_reason);
236 punt_test_feat_ip4 (vlib_main_t * vm,
237 vlib_node_runtime_t * node, vlib_frame_t * frame)
239 return (punt_test_feat_inline (vm, node, frame, 1));
243 punt_test_feat_ip6 (vlib_main_t * vm,
244 vlib_node_runtime_t * node, vlib_frame_t * frame)
246 return (punt_test_feat_inline (vm, node, frame, 0));
250 VLIB_REGISTER_NODE (punt_test_feat_ip6_node) = {
251 .function = punt_test_feat_ip6,
252 .name = "punt-test-feat-ip6",
253 .vector_size = sizeof (u32),
254 .format_trace = format_punt_feat_trace,
257 [0] = "punt-dispatch"
260 VLIB_REGISTER_NODE (punt_test_feat_ip4_node) = {
261 .function = punt_test_feat_ip4,
262 .name = "punt-test-feat-ip4",
263 .vector_size = sizeof (u32),
264 .format_trace = format_punt_feat_trace,
267 [0] = "punt-dispatch"
270 VNET_FEATURE_INIT (punt_test_feat_ip6_feature, static) =
272 .arc_name = "ip6-unicast",
273 .node_name = "punt-test-feat-ip6",
275 VNET_FEATURE_INIT (punt_test_feat_ip4_feature, static) =
277 .arc_name = "ip4-unicast",
278 .node_name = "punt-test-feat-ip4",
282 static clib_error_t *
283 punt_test (vlib_main_t * vm,
284 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
286 ip46_address_t ip46 = ip46_address_initializer;
287 fib_protocol_t fproto;
292 vnm = vnet_get_main ();
293 fproto = FIB_PROTOCOL_IP4;
295 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
299 if (unformat (input, "%U", unformat_ip4_address, &ip46.ip4))
301 fproto = FIB_PROTOCOL_IP4;
303 else if (unformat (input, "%U", unformat_ip6_address, &ip46.ip6))
305 fproto = FIB_PROTOCOL_IP6;
307 else if (unformat (input, "clear"))
309 vnet_feature_enable_disable ("ip4-unicast",
310 "punt-test-feat-ip4",
311 sw_if_index, 0, NULL, 0);
312 vnet_feature_enable_disable ("ip6-unicast",
313 "punt-test-feat-ip6",
314 sw_if_index, 0, NULL, 0);
320 * allocate a client and a reason
322 punt_hdl = vlib_punt_client_register ("test");
325 vlib_punt_reason_alloc (punt_hdl, "reason-v4", &punt_reason_v4);
327 vlib_punt_reason_alloc (punt_hdl, "reason-v6", &punt_reason_v6);
330 vnet_feature_enable_disable ("ip4-unicast",
331 "punt-test-feat-ip4",
332 sw_if_index, 1, NULL, 0);
333 vnet_feature_enable_disable ("ip6-unicast",
334 "punt-test-feat-ip6",
335 sw_if_index, 1, NULL, 0);
339 if (SW_IF_INDEX_PG0 == sw_if_index)
341 if (FIB_PROTOCOL_IP4 == fproto)
344 * register the node that will forward the punted packet
346 vlib_punt_register (punt_hdl, punt_reason_v4,
347 "punt-test-pg0-ip4");
348 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip4");
352 vlib_punt_register (punt_hdl, punt_reason_v6,
353 "punt-test-pg0-ip6");
354 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip6");
359 if (FIB_PROTOCOL_IP4 == fproto)
361 vlib_punt_register (punt_hdl, punt_reason_v4,
362 "punt-test-pg1-ip4");
363 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip4");
367 vlib_punt_register (punt_hdl, punt_reason_v6,
368 "punt-test-pg1-ip6");
369 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip6");
373 vlib_node_add_next (vm, from->index,
374 vnet_tx_node_index_for_sw_interface
377 vec_validate (adjs[fproto], sw_if_index);
379 adjs[fproto][sw_if_index] = adj_nbr_find (fproto,
380 fib_proto_to_link (fproto),
388 VLIB_CLI_COMMAND (test_fib_command, static) =
391 .short_help = "punt unit tests - DO NOT RUN ON A LIVE SYSTEM",
392 .function = punt_test,
397 * fd.io coding-style-patch-verification: ON
400 * eval: (c-set-style "gnu")