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));
133 VLIB_REGISTER_NODE (punt_test_pg0_ip4_node) = {
134 .function = punt_test_pg0_ip4,
135 .name = "punt-test-pg0-ip4",
136 .vector_size = sizeof (u32),
137 .format_trace = format_punt_trace,
139 VLIB_REGISTER_NODE (punt_test_pg1_ip4_node) = {
140 .function = punt_test_pg1_ip4,
141 .name = "punt-test-pg1-ip4",
142 .vector_size = sizeof (u32),
143 .format_trace = format_punt_trace,
145 VLIB_REGISTER_NODE (punt_test_pg0_ip6_node) = {
146 .function = punt_test_pg0_ip6,
147 .name = "punt-test-pg0-ip6",
148 .vector_size = sizeof (u32),
149 .format_trace = format_punt_trace,
151 VLIB_REGISTER_NODE (punt_test_pg1_ip6_node) = {
152 .function = punt_test_pg1_ip6,
153 .name = "punt-test-pg1-ip6",
154 .vector_size = sizeof (u32),
155 .format_trace = format_punt_trace,
159 typedef struct punt_feat_trace_t_
161 vlib_punt_reason_t pt_reason;
165 punt_test_feat_inline (vlib_main_t * vm,
166 vlib_node_runtime_t * node,
167 vlib_frame_t * frame, u8 is_ip4)
169 u32 n_left_from, *from, *to_next, next_index;
171 from = vlib_frame_vector_args (frame);
172 n_left_from = frame->n_vectors;
173 next_index = node->cached_next_index;
175 while (n_left_from > 0)
179 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
181 while (n_left_from > 0 && n_left_to_next > 0)
186 bi0 = to_next[0] = from[0];
193 b0 = vlib_get_buffer (vm, bi0);
196 b0->punt_reason = punt_reason_v4;
198 b0->punt_reason = punt_reason_v6;
200 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
202 punt_feat_trace_t *t;
204 b0 = vlib_get_buffer (vm, bi0);
206 t = vlib_add_trace (vm, node, b0, sizeof (*t));
207 t->pt_reason = b0->punt_reason;
209 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
210 to_next, n_left_to_next,
213 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
216 return frame->n_vectors;
220 format_punt_feat_trace (u8 * s, va_list * args)
222 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
223 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
224 punt_feat_trace_t *t = va_arg (*args, punt_feat_trace_t *);
226 s = format (s, "reason: %U", format_vlib_punt_reason, t->pt_reason);
232 punt_test_feat_ip4 (vlib_main_t * vm,
233 vlib_node_runtime_t * node, vlib_frame_t * frame)
235 return (punt_test_feat_inline (vm, node, frame, 1));
239 punt_test_feat_ip6 (vlib_main_t * vm,
240 vlib_node_runtime_t * node, vlib_frame_t * frame)
242 return (punt_test_feat_inline (vm, node, frame, 0));
246 VLIB_REGISTER_NODE (punt_test_feat_ip6_node) = {
247 .function = punt_test_feat_ip6,
248 .name = "punt-test-feat-ip6",
249 .vector_size = sizeof (u32),
250 .format_trace = format_punt_feat_trace,
253 [0] = "punt-dispatch"
256 VLIB_REGISTER_NODE (punt_test_feat_ip4_node) = {
257 .function = punt_test_feat_ip4,
258 .name = "punt-test-feat-ip4",
259 .vector_size = sizeof (u32),
260 .format_trace = format_punt_feat_trace,
263 [0] = "punt-dispatch"
266 VNET_FEATURE_INIT (punt_test_feat_ip6_feature, static) =
268 .arc_name = "ip6-unicast",
269 .node_name = "punt-test-feat-ip6",
271 VNET_FEATURE_INIT (punt_test_feat_ip4_feature, static) =
273 .arc_name = "ip4-unicast",
274 .node_name = "punt-test-feat-ip4",
278 static clib_error_t *
279 punt_test (vlib_main_t * vm,
280 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
282 ip46_address_t ip46 = ip46_address_initializer;
283 fib_protocol_t fproto;
288 vnm = vnet_get_main ();
289 fproto = FIB_PROTOCOL_IP4;
291 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
295 if (unformat (input, "%U", unformat_ip4_address, &ip46.ip4))
297 fproto = FIB_PROTOCOL_IP4;
299 else if (unformat (input, "%U", unformat_ip6_address, &ip46.ip6))
301 fproto = FIB_PROTOCOL_IP6;
303 else if (unformat (input, "clear"))
305 vnet_feature_enable_disable ("ip4-unicast",
306 "punt-test-feat-ip4",
307 sw_if_index, 0, NULL, 0);
308 vnet_feature_enable_disable ("ip6-unicast",
309 "punt-test-feat-ip6",
310 sw_if_index, 0, NULL, 0);
316 * allocate a client and a reason
318 punt_hdl = vlib_punt_client_register ("test");
320 rc = vlib_punt_reason_alloc (
321 punt_hdl, "reason-v4", NULL, NULL, &punt_reason_v4,
322 VNET_PUNT_REASON_F_IP4_PACKET, format_vnet_punt_reason_flags);
323 rc |= vlib_punt_reason_alloc (
324 punt_hdl, "reason-v6", NULL, NULL, &punt_reason_v6,
325 VNET_PUNT_REASON_F_IP6_PACKET, format_vnet_punt_reason_flags);
328 vnet_feature_enable_disable ("ip4-unicast",
329 "punt-test-feat-ip4",
330 sw_if_index, 1, NULL, 0);
331 vnet_feature_enable_disable ("ip6-unicast",
332 "punt-test-feat-ip6",
333 sw_if_index, 1, NULL, 0);
337 if (SW_IF_INDEX_PG0 == sw_if_index)
339 if (FIB_PROTOCOL_IP4 == fproto)
342 * register the node that will forward the punted packet
344 vlib_punt_register (punt_hdl, punt_reason_v4,
345 "punt-test-pg0-ip4");
346 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip4");
350 vlib_punt_register (punt_hdl, punt_reason_v6,
351 "punt-test-pg0-ip6");
352 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg0-ip6");
357 if (FIB_PROTOCOL_IP4 == fproto)
359 vlib_punt_register (punt_hdl, punt_reason_v4,
360 "punt-test-pg1-ip4");
361 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip4");
365 vlib_punt_register (punt_hdl, punt_reason_v6,
366 "punt-test-pg1-ip6");
367 from = vlib_get_node_by_name (vm, (u8 *) "punt-test-pg1-ip6");
371 vlib_node_add_next (vm, from->index,
372 vnet_tx_node_index_for_sw_interface
375 vec_validate (adjs[fproto], sw_if_index);
377 adjs[fproto][sw_if_index] = adj_nbr_find (fproto,
378 fib_proto_to_link (fproto),
386 VLIB_CLI_COMMAND (test_fib_command, static) =
389 .short_help = "punt unit tests - DO NOT RUN ON A LIVE SYSTEM",
390 .function = punt_test,
395 * fd.io coding-style-patch-verification: ON
398 * eval: (c-set-style "gnu")