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>
21 #include <vnet/ip/punt.h>
23 typedef enum punt_next_t_
29 typedef struct punt_trace_t_
31 vlib_punt_reason_t pt_reason;
34 #define SW_IF_INDEX_PG0 1
35 #define SW_IF_INDEX_PG1 2
37 index_t *adjs[FIB_PROTOCOL_IP_MAX];
39 static vlib_punt_reason_t punt_reason_v4, punt_reason_v6;
40 static vlib_punt_hdl_t punt_hdl;
43 format_punt_trace (u8 * s, va_list * args)
45 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
46 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
47 punt_trace_t *t = va_arg (*args, punt_trace_t *);
49 s = format (s, "punt: %U", format_vlib_punt_reason, t->pt_reason);
55 punt_test_fwd (vlib_main_t * vm,
56 vlib_node_runtime_t * node,
57 vlib_frame_t * frame, fib_protocol_t fproto, u32 sw_if_index)
59 u32 n_left_from, *from, *to_next, next_index;
61 from = vlib_frame_vector_args (frame);
62 n_left_from = frame->n_vectors;
63 next_index = node->cached_next_index;
65 while (n_left_from > 0)
69 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
71 while (n_left_from > 0 && n_left_to_next > 0)
79 bi0 = to_next[0] = from[0];
85 b0 = vlib_get_buffer (vm, bi0);
86 vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index;
87 ai0 = adjs[fproto][sw_if_index];
90 ip0 = vlib_buffer_get_current (b0);
92 vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
93 vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
95 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
96 to_next, n_left_to_next, bi0, 0);
98 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
101 return frame->n_vectors;
105 punt_test_pg0_ip4 (vlib_main_t * vm,
106 vlib_node_runtime_t * node, vlib_frame_t * frame)
108 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP4, SW_IF_INDEX_PG0));
112 punt_test_pg1_ip4 (vlib_main_t * vm,
113 vlib_node_runtime_t * node, vlib_frame_t * frame)
115 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP4, SW_IF_INDEX_PG1));
119 punt_test_pg0_ip6 (vlib_main_t * vm,
120 vlib_node_runtime_t * node, vlib_frame_t * frame)
122 return (punt_test_fwd (vm, node, frame, FIB_PROTOCOL_IP6, SW_IF_INDEX_PG0));
126 punt_test_pg1_ip6 (vlib_main_t * vm,
127 vlib_node_runtime_t * node, vlib_frame_t * frame)
129 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,
157 typedef struct punt_feat_trace_t_
159 vlib_punt_reason_t pt_reason;
163 punt_test_feat_inline (vlib_main_t * vm,
164 vlib_node_runtime_t * node,
165 vlib_frame_t * frame, u8 is_ip4)
167 u32 n_left_from, *from, *to_next, next_index;
169 from = vlib_frame_vector_args (frame);
170 n_left_from = frame->n_vectors;
171 next_index = node->cached_next_index;
173 while (n_left_from > 0)
177 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
179 while (n_left_from > 0 && n_left_to_next > 0)
184 bi0 = to_next[0] = from[0];
191 b0 = vlib_get_buffer (vm, bi0);
194 b0->punt_reason = punt_reason_v4;
196 b0->punt_reason = punt_reason_v6;
198 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
200 punt_feat_trace_t *t;
202 b0 = vlib_get_buffer (vm, bi0);
204 t = vlib_add_trace (vm, node, b0, sizeof (*t));
205 t->pt_reason = b0->punt_reason;
207 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
208 to_next, n_left_to_next,
211 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
214 return frame->n_vectors;
218 format_punt_feat_trace (u8 * s, va_list * args)
220 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
221 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
222 punt_feat_trace_t *t = va_arg (*args, punt_feat_trace_t *);
224 s = format (s, "reason: %U", format_vlib_punt_reason, t->pt_reason);
230 punt_test_feat_ip4 (vlib_main_t * vm,
231 vlib_node_runtime_t * node, vlib_frame_t * frame)
233 return (punt_test_feat_inline (vm, node, frame, 1));
237 punt_test_feat_ip6 (vlib_main_t * vm,
238 vlib_node_runtime_t * node, vlib_frame_t * frame)
240 return (punt_test_feat_inline (vm, node, frame, 0));
243 VLIB_REGISTER_NODE (punt_test_feat_ip6_node) = {
244 .function = punt_test_feat_ip6,
245 .name = "punt-test-feat-ip6",
246 .vector_size = sizeof (u32),
247 .format_trace = format_punt_feat_trace,
250 [0] = "punt-dispatch"
253 VLIB_REGISTER_NODE (punt_test_feat_ip4_node) = {
254 .function = punt_test_feat_ip4,
255 .name = "punt-test-feat-ip4",
256 .vector_size = sizeof (u32),
257 .format_trace = format_punt_feat_trace,
260 [0] = "punt-dispatch"
263 VNET_FEATURE_INIT (punt_test_feat_ip6_feature, static) =
265 .arc_name = "ip6-unicast",
266 .node_name = "punt-test-feat-ip6",
268 VNET_FEATURE_INIT (punt_test_feat_ip4_feature, static) =
270 .arc_name = "ip4-unicast",
271 .node_name = "punt-test-feat-ip4",
274 static clib_error_t *
275 punt_test (vlib_main_t * vm,
276 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
278 ip46_address_t ip46 = ip46_address_initializer;
279 fib_protocol_t fproto;
284 vnm = vnet_get_main ();
285 fproto = FIB_PROTOCOL_IP4;
287 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
291 if (unformat (input, "%U", unformat_ip4_address, &ip46.ip4))
293 fproto = FIB_PROTOCOL_IP4;
295 else if (unformat (input, "%U", unformat_ip6_address, &ip46.ip6))
297 fproto = FIB_PROTOCOL_IP6;
299 else if (unformat (input, "clear"))
301 vnet_feature_enable_disable ("ip4-unicast",
302 "punt-test-feat-ip4",
303 sw_if_index, 0, NULL, 0);
304 vnet_feature_enable_disable ("ip6-unicast",
305 "punt-test-feat-ip6",
306 sw_if_index, 0, NULL, 0);
312 * allocate a client and a reason
314 punt_hdl = vlib_punt_client_register ("test");
316 rc = vlib_punt_reason_alloc (
317 punt_hdl, "reason-v4", NULL, NULL, &punt_reason_v4,
318 VNET_PUNT_REASON_F_IP4_PACKET, format_vnet_punt_reason_flags);
319 rc |= vlib_punt_reason_alloc (
320 punt_hdl, "reason-v6", NULL, NULL, &punt_reason_v6,
321 VNET_PUNT_REASON_F_IP6_PACKET, format_vnet_punt_reason_flags);
324 vnet_feature_enable_disable ("ip4-unicast",
325 "punt-test-feat-ip4",
326 sw_if_index, 1, NULL, 0);
327 vnet_feature_enable_disable ("ip6-unicast",
328 "punt-test-feat-ip6",
329 sw_if_index, 1, NULL, 0);
333 if (SW_IF_INDEX_PG0 == sw_if_index)
335 if (FIB_PROTOCOL_IP4 == fproto)
338 * register the node that will forward the punted packet
340 vlib_punt_register (punt_hdl, punt_reason_v4,
341 "punt-test-pg0-ip4");
342 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip4");
346 vlib_punt_register (punt_hdl, punt_reason_v6,
347 "punt-test-pg0-ip6");
348 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip6");
353 if (FIB_PROTOCOL_IP4 == fproto)
355 vlib_punt_register (punt_hdl, punt_reason_v4,
356 "punt-test-pg1-ip4");
357 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip4");
361 vlib_punt_register (punt_hdl, punt_reason_v6,
362 "punt-test-pg1-ip6");
363 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip6");
367 vlib_node_add_next (vm, from->index,
368 vnet_tx_node_index_for_sw_interface
371 vec_validate (adjs[fproto], sw_if_index);
373 adjs[fproto][sw_if_index] = adj_nbr_find (fproto,
374 fib_proto_to_link (fproto),
381 VLIB_CLI_COMMAND (test_fib_command, static) =
384 .short_help = "punt unit tests - DO NOT RUN ON A LIVE SYSTEM",
385 .function = punt_test,
389 * fd.io coding-style-patch-verification: ON
392 * eval: (c-set-style "gnu")