blob: dc113f513866c948204c0d82c44540739b4e2b76 [file] [log] [blame]
Neale Ranns92207752019-06-03 13:21:40 +00001/*
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#include <vnet/ip/ip.h>
17#include <vnet/ip/ip_punt_drop.h>
Neale Ranns92207752019-06-03 13:21:40 +000018#include <vnet/fib/fib_path_list.h>
19
20ip_punt_redirect_cfg_t ip_punt_redirect_cfg;
21
22u8 *
23format_ip_punt_redirect_trace (u8 * s, va_list * args)
24{
25 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
26 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
27 ip_punt_redirect_trace_t *t = va_arg (*args, ip_punt_redirect_trace_t *);
28
29 if (INDEX_INVALID == t->rrxi)
Neale Ranns03c254e2020-03-17 14:25:10 +000030 s = format (s, "ignore");
Neale Ranns92207752019-06-03 13:21:40 +000031 else
32 s = format (s, "via redirect:%d", t->rrxi);
33
34 return s;
35}
36
37static void
38ip_punt_redirect_stack (ip_punt_redirect_rx_t * ipr)
39{
40 dpo_id_t dpo = DPO_INVALID;
41 vlib_node_t *pnode;
42
43 fib_path_list_contribute_forwarding (ipr->pl,
44 ipr->payload_type,
45 FIB_PATH_LIST_FWD_FLAG_COLLAPSE, &dpo);
46
47 if (FIB_PROTOCOL_IP4 == ipr->fproto)
48 pnode =
49 vlib_get_node_by_name (vlib_get_main (), (u8 *) "ip4-punt-redirect");
50 else
51 pnode =
52 vlib_get_node_by_name (vlib_get_main (), (u8 *) "ip6-punt-redirect");
53
54 dpo_stack_from_node (pnode->index, &ipr->dpo, &dpo);
55 dpo_reset (&dpo);
56}
57
58index_t
59ip_punt_redirect_find (fib_protocol_t fproto, u32 rx_sw_if_index)
60{
61 index_t *rxs;
62
63 rxs = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
64
65 if (vec_len (rxs) <= rx_sw_if_index)
66 return (INDEX_INVALID);
67
68 return rxs[rx_sw_if_index];
69}
70
71void
Nathan Skrzypczak2a1783f2021-08-10 15:05:29 +020072ip_punt_redirect_add (fib_protocol_t fproto, u32 rx_sw_if_index,
73 fib_forward_chain_type_t ct,
74 const fib_route_path_t *rpaths)
Neale Ranns92207752019-06-03 13:21:40 +000075{
76 ip_punt_redirect_rx_t *ipr;
77 index_t ipri;
78
79 if (~0 == rx_sw_if_index)
80 rx_sw_if_index = 0;
81
82 vec_validate_init_empty (ip_punt_redirect_cfg.redirect_by_rx_sw_if_index
83 [fproto], rx_sw_if_index, INDEX_INVALID);
84
85 pool_get (ip_punt_redirect_cfg.pool, ipr);
86 ipri = ipr - ip_punt_redirect_cfg.pool;
87
88 ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto][rx_sw_if_index] =
89 ipri;
90
91 fib_node_init (&ipr->node, FIB_NODE_TYPE_IP_PUNT_REDIRECT);
92 ipr->fproto = fproto;
93 ipr->payload_type = ct;
94
95 ipr->pl = fib_path_list_create (FIB_PATH_LIST_FLAG_NO_URPF, rpaths);
96
97 ipr->sibling = fib_path_list_child_add (ipr->pl,
98 FIB_NODE_TYPE_IP_PUNT_REDIRECT,
99 ipri);
100
101 ip_punt_redirect_stack (ipr);
102}
103
104void
105ip_punt_redirect_del (fib_protocol_t fproto, u32 rx_sw_if_index)
106{
107 ip_punt_redirect_rx_t *ipr;
108 index_t *rxs;
109
110 if (~0 == rx_sw_if_index)
111 rx_sw_if_index = 0;
112
113 rxs = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
114
115 if ((vec_len (rxs) <= rx_sw_if_index) ||
116 (INDEX_INVALID == rxs[rx_sw_if_index]))
117 return;
118
119 ipr = ip_punt_redirect_get (rxs[rx_sw_if_index]);
120
121 fib_path_list_child_remove (ipr->pl, ipr->sibling);
122 dpo_reset (&ipr->dpo);
123 pool_put (ip_punt_redirect_cfg.pool, ipr);
124
125 rxs[rx_sw_if_index] = INDEX_INVALID;
126}
127
128u8 *
129format_ip_punt_redirect (u8 * s, va_list * args)
130{
131 fib_protocol_t fproto = va_arg (*args, int);
132 ip_punt_redirect_rx_t *rx;
133 index_t *rxs;
134 u32 rx_sw_if_index;
135 vnet_main_t *vnm = vnet_get_main ();
136
137 rxs = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
138
139 vec_foreach_index (rx_sw_if_index, rxs)
140 {
141 if (INDEX_INVALID == rxs[rx_sw_if_index])
142 continue;
143
144 rx = ip_punt_redirect_get (rxs[rx_sw_if_index]);
145
Vladislav Grishenkofb9d1ac2022-08-04 20:36:45 +0500146 s = format (s, " rx %U via:\n", format_vnet_sw_if_index_name, vnm,
147 rx_sw_if_index);
Neale Ranns92207752019-06-03 13:21:40 +0000148 s = format (s, " %U", format_fib_path_list, rx->pl, 2);
149 s = format (s, " forwarding\n", format_dpo_id, &rx->dpo, 0);
150 s = format (s, " %U\n", format_dpo_id, &rx->dpo, 0);
151 }
152
153 return (s);
154}
155
156void
157ip_punt_redirect_walk (fib_protocol_t fproto,
158 ip_punt_redirect_walk_cb_t cb, void *ctx)
159{
160 ip_punt_redirect_rx_t *rx;
161 u32 ii, rx_sw_if_index;
162 index_t *rxs;
163
164 rxs = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
165
166 vec_foreach_index (ii, rxs)
167 {
168 if (INDEX_INVALID == rxs[ii])
169 continue;
170
171 rx = ip_punt_redirect_get (rxs[ii]);
172
173 rx_sw_if_index = (ii == 0 ? ~0 : ii);
174 cb (rx_sw_if_index, rx, ctx);
175 }
176}
177
178static fib_node_t *
179ip_punt_redirect_get_node (fib_node_index_t index)
180{
181 ip_punt_redirect_rx_t *ipr = ip_punt_redirect_get (index);
182 return (&(ipr->node));
183}
184
185static ip_punt_redirect_rx_t *
186ip_punt_redirect_get_from_node (fib_node_t * node)
187{
188 return ((ip_punt_redirect_rx_t *) (((char *) node) -
189 STRUCT_OFFSET_OF (ip_punt_redirect_rx_t,
190 node)));
191}
192
193static void
194ip_punt_redirect_last_lock_gone (fib_node_t * node)
195{
196 /*
197 * the lifetime of the entry is managed by the table.
198 */
199 ASSERT (0);
200}
201
202/*
203 * A back walk has reached this BIER entry
204 */
205static fib_node_back_walk_rc_t
206ip_punt_redirect_back_walk_notify (fib_node_t * node,
207 fib_node_back_walk_ctx_t * ctx)
208{
209 /*
210 * re-populate the ECMP tables with new choices
211 */
212 ip_punt_redirect_rx_t *ipr = ip_punt_redirect_get_from_node (node);
213
214 ip_punt_redirect_stack (ipr);
215
216 /*
217 * no need to propagate further up the graph, since there's nothing there
218 */
219 return (FIB_NODE_BACK_WALK_CONTINUE);
220}
221
222/*
223 * The BIER fmask's graph node virtual function table
224 */
225static const fib_node_vft_t ip_punt_redirect_vft = {
226 .fnv_get = ip_punt_redirect_get_node,
227 .fnv_last_lock = ip_punt_redirect_last_lock_gone,
228 .fnv_back_walk = ip_punt_redirect_back_walk_notify,
229};
230
231static clib_error_t *
232ip_punt_drop_init (vlib_main_t * vm)
233{
234 fib_node_register_type (FIB_NODE_TYPE_IP_PUNT_REDIRECT,
235 &ip_punt_redirect_vft);
236
Brian Russellbaebb222021-01-19 16:48:56 +0000237 ip4_punt_policer_cfg.fq_index =
238 vlib_frame_queue_main_init (ip4_punt_policer_node.index, 0);
239 ip6_punt_policer_cfg.fq_index =
240 vlib_frame_queue_main_init (ip6_punt_policer_node.index, 0);
241
Neale Ranns92207752019-06-03 13:21:40 +0000242 return (NULL);
243}
244
245VLIB_INIT_FUNCTION (ip_punt_drop_init);
246
247/*
248 * fd.io coding-style-patch-verification: ON
249 *
250 * Local Variables:
251 * eval: (c-set-style "gnu")
252 * End:
253 */