blob: 82f5e3b7c1e331d788623b6b526d4321e963053f [file] [log] [blame]
Pablo Camarillofb380952016-12-07 18:34:18 +01001/*
2 * sr_localsid.c: ipv6 segment routing Endpoint behaviors
3 *
4 * Copyright (c) 2016 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/**
19 * @file
20 * @brief Processing of packets with a SRH
21 *
22 * CLI to define new Segment Routing End processing functions.
23 * Graph node to support such functions.
24 *
25 * Each function associates an SRv6 segment (IPv6 address) with an specific
26 * Segment Routing function.
27 *
28 */
29
30#include <vlib/vlib.h>
31#include <vnet/vnet.h>
Pablo Camarillo5d73eec2017-04-24 17:51:56 +020032#include <vnet/srv6/sr.h>
Pablo Camarillofb380952016-12-07 18:34:18 +010033#include <vnet/ip/ip.h>
Pablo Camarillo5d73eec2017-04-24 17:51:56 +020034#include <vnet/srv6/sr_packet.h>
Pablo Camarillofb380952016-12-07 18:34:18 +010035#include <vnet/ip/ip6_packet.h>
36#include <vnet/fib/ip6_fib.h>
37#include <vnet/dpo/dpo.h>
38#include <vnet/adj/adj.h>
39
40#include <vppinfra/error.h>
41#include <vppinfra/elog.h>
42
43/**
44 * @brief Dynamically added SR localsid DPO type
45 */
46static dpo_type_t sr_localsid_dpo_type;
47static dpo_type_t sr_localsid_d_dpo_type;
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -070048static dpo_type_t sr_localsid_un_dpo_type;
49static dpo_type_t sr_localsid_un_perf_dpo_type;
50
51static void
52sr_localsid_key_create (sr_localsid_key_t * key, ip6_address_t * addr,
53 u16 pref_len)
54{
55 clib_memset (key, 0, sizeof (sr_localsid_key_t));
56 clib_memcpy (&key->address, addr, sizeof (ip6_address_t));
57 key->pref_len = pref_len;
58}
Pablo Camarillofb380952016-12-07 18:34:18 +010059
60/**
61 * @brief SR localsid add/del
62 *
63 * Function to add or delete SR LocalSIDs.
64 *
65 * @param is_del Boolean of whether its a delete instruction
66 * @param localsid_addr IPv6 address of the localsid
67 * @param is_decap Boolean of whether decapsulation is allowed in this function
68 * @param behavior Type of behavior (function) for this localsid
69 * @param sw_if_index Only for L2/L3 xconnect. OIF. In VRF variant the fib_table.
70 * @param vlan_index Only for L2 xconnect. Outgoing VLAN tag.
71 * @param fib_table FIB table in which we should install the localsid entry
72 * @param nh_addr Next Hop IPv4/IPv6 address. Only for L2/L3 xconnect.
73 *
74 * @return 0 on success, error otherwise.
75 */
76int
Pablo Camarillo79bfd272019-12-18 17:13:13 +000077sr_cli_localsid (char is_del, ip6_address_t * localsid_addr,
78 u16 localsid_prefix_len, char end_psp, u8 behavior,
79 u32 sw_if_index, u32 vlan_index, u32 fib_table,
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -070080 ip46_address_t * nh_addr, int usid_len, void *ls_plugin_mem)
Pablo Camarillofb380952016-12-07 18:34:18 +010081{
82 ip6_sr_main_t *sm = &sr_main;
83 uword *p;
84 int rv;
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -080085 u8 pref_length = 128;
86 sr_localsid_fn_registration_t *plugin = 0;
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -070087 sr_localsid_key_t key;
Pablo Camarillofb380952016-12-07 18:34:18 +010088
89 ip6_sr_localsid_t *ls = 0;
Pablo Camarillofb380952016-12-07 18:34:18 +010090
91 dpo_id_t dpo = DPO_INVALID;
92
93 /* Search for the item */
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -070094 sr_localsid_key_create (&key, localsid_addr, localsid_prefix_len);
95 p = mhash_get (&sm->sr_localsids_index_hash, &key);
Pablo Camarillofb380952016-12-07 18:34:18 +010096
97 if (p)
98 {
99 if (is_del)
100 {
Pablo Camarillofb380952016-12-07 18:34:18 +0100101 /* Retrieve localsid */
102 ls = pool_elt_at_index (sm->localsids, p[0]);
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800103 if (ls->behavior >= SR_BEHAVIOR_LAST)
104 {
105 plugin = pool_elt_at_index (sm->plugin_functions,
106 ls->behavior - SR_BEHAVIOR_LAST);
107 pref_length = plugin->prefix_length;
108 }
109
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000110 if (localsid_prefix_len != 0)
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800111 {
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000112 pref_length = localsid_prefix_len;
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800113 }
114
Pablo Camarillofb380952016-12-07 18:34:18 +0100115 /* Delete FIB entry */
116 fib_prefix_t pfx = {
117 .fp_proto = FIB_PROTOCOL_IP6,
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800118 .fp_len = pref_length,
Pablo Camarillofb380952016-12-07 18:34:18 +0100119 .fp_addr = {
120 .ip6 = *localsid_addr,
121 }
122 };
123
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800124 fib_table_entry_delete (fib_table_find
125 (FIB_PROTOCOL_IP6, fib_table), &pfx,
126 FIB_SOURCE_SR);
Pablo Camarillofb380952016-12-07 18:34:18 +0100127
128 /* In case it is a Xconnect iface remove the (OIF, NHOP) adj */
129 if (ls->behavior == SR_BEHAVIOR_X || ls->behavior == SR_BEHAVIOR_DX6
130 || ls->behavior == SR_BEHAVIOR_DX4)
131 adj_unlock (ls->nh_adj);
132
133 if (ls->behavior >= SR_BEHAVIOR_LAST)
134 {
Pablo Camarillofb380952016-12-07 18:34:18 +0100135 /* Callback plugin removal function */
136 rv = plugin->removal (ls);
137 }
138
139 /* Delete localsid registry */
140 pool_put (sm->localsids, ls);
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700141 mhash_unset (&sm->sr_localsids_index_hash, &key, NULL);
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200142 return 0;
Pablo Camarillofb380952016-12-07 18:34:18 +0100143 }
144 else /* create with function already existing; complain */
145 return -1;
146 }
147 else
148 /* delete; localsid does not exist; complain */
149 if (is_del)
150 return -2;
151
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800152 if (behavior >= SR_BEHAVIOR_LAST)
153 {
154 sr_localsid_fn_registration_t *plugin = 0;
155 plugin =
156 pool_elt_at_index (sm->plugin_functions, behavior - SR_BEHAVIOR_LAST);
157 pref_length = plugin->prefix_length;
158 }
159
Tetsuya Murakami0d90ed92020-03-21 14:47:02 -0700160 if (localsid_prefix_len != 0)
161 {
162 pref_length = localsid_prefix_len;
163 }
164
Pablo Camarillofb380952016-12-07 18:34:18 +0100165 /* Check whether there exists a FIB entry with such address */
166 fib_prefix_t pfx = {
167 .fp_proto = FIB_PROTOCOL_IP6,
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800168 .fp_len = pref_length,
Pablo Camarillofb380952016-12-07 18:34:18 +0100169 };
170
171 pfx.fp_addr.as_u64[0] = localsid_addr->as_u64[0];
172 pfx.fp_addr.as_u64[1] = localsid_addr->as_u64[1];
Tetsuya Murakami0d90ed92020-03-21 14:47:02 -0700173 pfx.fp_len = pref_length;
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800174
Pablo Camarillofb380952016-12-07 18:34:18 +0100175 /* Lookup the FIB index associated to the table id provided */
Neale Ranns107e7d42017-04-11 09:55:19 -0700176 u32 fib_index = fib_table_find (FIB_PROTOCOL_IP6, fib_table);
Pablo Camarillofb380952016-12-07 18:34:18 +0100177 if (fib_index == ~0)
178 return -3;
179
180 /* Lookup the localsid in such FIB table */
181 fib_node_index_t fei = fib_table_lookup_exact_match (fib_index, &pfx);
182 if (FIB_NODE_INDEX_INVALID != fei)
183 return -4; //There is an entry for such address (the localsid addr)
184
185 /* Create a new localsid registry */
186 pool_get (sm->localsids, ls);
Dave Barachb7b92992018-10-17 10:38:51 -0400187 clib_memset (ls, 0, sizeof (*ls));
Pablo Camarillofb380952016-12-07 18:34:18 +0100188
189 clib_memcpy (&ls->localsid, localsid_addr, sizeof (ip6_address_t));
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000190 ls->localsid_prefix_len = pref_length;
Pablo Camarillofb380952016-12-07 18:34:18 +0100191 ls->end_psp = end_psp;
192 ls->behavior = behavior;
193 ls->nh_adj = (u32) ~ 0;
194 ls->fib_table = fib_table;
195 switch (behavior)
196 {
197 case SR_BEHAVIOR_END:
198 break;
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700199 case SR_BEHAVIOR_END_UN:
200 case SR_BEHAVIOR_END_UN_PERF:
201 if (usid_len)
202 {
203 int usid_width;
204 clib_memcpy (&ls->usid_block, localsid_addr,
205 sizeof (ip6_address_t));
206
207 usid_width = pref_length - usid_len;
208 ip6_address_mask_from_width (&ls->usid_block_mask, usid_width);
209
210 ls->usid_index = usid_width / 8;
211 ls->usid_len = usid_len / 8;
212 ls->usid_next_index = ls->usid_index + ls->usid_len;
213 ls->usid_next_len = 16 - ls->usid_next_index;
214 }
215 break;
Pablo Camarillofb380952016-12-07 18:34:18 +0100216 case SR_BEHAVIOR_X:
217 ls->sw_if_index = sw_if_index;
218 clib_memcpy (&ls->next_hop.ip6, &nh_addr->ip6, sizeof (ip6_address_t));
219 break;
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200220 case SR_BEHAVIOR_T:
Neale Ranns10e36992018-02-25 12:39:37 -0800221 ls->vrf_index = fib_table_find (FIB_PROTOCOL_IP6, sw_if_index);
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200222 break;
Pablo Camarillofb380952016-12-07 18:34:18 +0100223 case SR_BEHAVIOR_DX4:
224 ls->sw_if_index = sw_if_index;
225 clib_memcpy (&ls->next_hop.ip4, &nh_addr->ip4, sizeof (ip4_address_t));
226 break;
227 case SR_BEHAVIOR_DX6:
228 ls->sw_if_index = sw_if_index;
229 clib_memcpy (&ls->next_hop.ip6, &nh_addr->ip6, sizeof (ip6_address_t));
230 break;
231 case SR_BEHAVIOR_DT6:
Neale Ranns10e36992018-02-25 12:39:37 -0800232 ls->vrf_index = fib_table_find (FIB_PROTOCOL_IP6, sw_if_index);
Pablo Camarillofb380952016-12-07 18:34:18 +0100233 break;
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200234 case SR_BEHAVIOR_DT4:
Neale Ranns10e36992018-02-25 12:39:37 -0800235 ls->vrf_index = fib_table_find (FIB_PROTOCOL_IP4, sw_if_index);
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200236 break;
Pablo Camarillofb380952016-12-07 18:34:18 +0100237 case SR_BEHAVIOR_DX2:
238 ls->sw_if_index = sw_if_index;
239 ls->vlan_index = vlan_index;
240 break;
241 }
242
243 /* Figure out the adjacency magic for Xconnect variants */
244 if (ls->behavior == SR_BEHAVIOR_X || ls->behavior == SR_BEHAVIOR_DX4
245 || ls->behavior == SR_BEHAVIOR_DX6)
246 {
247 adj_index_t nh_adj_index = ADJ_INDEX_INVALID;
248
249 /* Retrieve the adjacency corresponding to the (OIF, next_hop) */
250 if (ls->behavior == SR_BEHAVIOR_DX6 || ls->behavior == SR_BEHAVIOR_X)
251 nh_adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6,
252 nh_addr, sw_if_index);
253
254 else if (ls->behavior == SR_BEHAVIOR_DX4)
255 nh_adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4, VNET_LINK_IP4,
256 nh_addr, sw_if_index);
257
258 /* Check for ADJ creation error. If so panic */
259 if (nh_adj_index == ADJ_INDEX_INVALID)
260 {
261 pool_put (sm->localsids, ls);
262 return -5;
263 }
264
265 ls->nh_adj = nh_adj_index;
266 }
267
268 /* Set DPO */
Ahmed Abdelsalam0ae1d802019-07-25 13:45:55 -0500269 if (ls->behavior == SR_BEHAVIOR_END || ls->behavior == SR_BEHAVIOR_X
270 || ls->behavior == SR_BEHAVIOR_T)
Pablo Camarillofb380952016-12-07 18:34:18 +0100271 dpo_set (&dpo, sr_localsid_dpo_type, DPO_PROTO_IP6, ls - sm->localsids);
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700272 else if (ls->behavior == SR_BEHAVIOR_END_UN)
273 dpo_set (&dpo, sr_localsid_un_dpo_type, DPO_PROTO_IP6,
274 ls - sm->localsids);
275 else if (ls->behavior == SR_BEHAVIOR_END_UN_PERF)
276 dpo_set (&dpo, sr_localsid_un_perf_dpo_type, DPO_PROTO_IP6,
277 ls - sm->localsids);
Pablo Camarillofb380952016-12-07 18:34:18 +0100278 else if (ls->behavior > SR_BEHAVIOR_D_FIRST
279 && ls->behavior < SR_BEHAVIOR_LAST)
280 dpo_set (&dpo, sr_localsid_d_dpo_type, DPO_PROTO_IP6, ls - sm->localsids);
281 else if (ls->behavior >= SR_BEHAVIOR_LAST)
282 {
283 sr_localsid_fn_registration_t *plugin = 0;
284 plugin = pool_elt_at_index (sm->plugin_functions,
285 ls->behavior - SR_BEHAVIOR_LAST);
286 /* Copy the unformat memory result */
287 ls->plugin_mem = ls_plugin_mem;
288 /* Callback plugin creation function */
289 rv = plugin->creation (ls);
290 if (rv)
291 {
292 pool_put (sm->localsids, ls);
293 return -6;
294 }
295 dpo_set (&dpo, plugin->dpo, DPO_PROTO_IP6, ls - sm->localsids);
296 }
297
298 /* Set hash key for searching localsid by address */
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700299 mhash_set (&sm->sr_localsids_index_hash, &key, ls - sm->localsids, NULL);
Pablo Camarillofb380952016-12-07 18:34:18 +0100300
301 fib_table_entry_special_dpo_add (fib_index, &pfx, FIB_SOURCE_SR,
302 FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
303 dpo_reset (&dpo);
304
305 /* Set counter to zero */
306 vlib_validate_combined_counter (&(sm->sr_ls_valid_counters),
307 ls - sm->localsids);
308 vlib_validate_combined_counter (&(sm->sr_ls_invalid_counters),
309 ls - sm->localsids);
310
311 vlib_zero_combined_counter (&(sm->sr_ls_valid_counters),
312 ls - sm->localsids);
313 vlib_zero_combined_counter (&(sm->sr_ls_invalid_counters),
314 ls - sm->localsids);
315
316 return 0;
317}
318
319/**
320 * @brief SR LocalSID CLI function.
321 *
322 * @see sr_cli_localsid
323 */
324static clib_error_t *
325sr_cli_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input,
326 vlib_cli_command_t * cmd)
327{
328 vnet_main_t *vnm = vnet_get_main ();
329 ip6_sr_main_t *sm = &sr_main;
330 u32 sw_if_index = (u32) ~ 0, vlan_index = (u32) ~ 0, fib_index = 0;
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800331 u16 prefix_len = 0;
Pablo Camarillofb380952016-12-07 18:34:18 +0100332 int is_del = 0;
333 int end_psp = 0;
334 ip6_address_t resulting_address;
335 ip46_address_t next_hop;
336 char address_set = 0;
337 char behavior = 0;
338 void *ls_plugin_mem = 0;
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700339 int usid_size = 0;
Pablo Camarillofb380952016-12-07 18:34:18 +0100340
341 int rv;
342
Dave Barachb7b92992018-10-17 10:38:51 -0400343 clib_memset (&resulting_address, 0, sizeof (ip6_address_t));
Pablo Camarillofb380952016-12-07 18:34:18 +0100344 ip46_address_reset (&next_hop);
345
346 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
347 {
348 if (unformat (input, "del"))
349 is_del = 1;
350 else if (!address_set
Tetsuya Murakamib24e2872020-03-24 13:12:13 -0700351 && unformat (input, "prefix %U/%u", unformat_ip6_address,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000352 &resulting_address, &prefix_len))
Pablo Camarillofb380952016-12-07 18:34:18 +0100353 address_set = 1;
354 else if (!address_set
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000355 && unformat (input, "address %U", unformat_ip6_address,
356 &resulting_address))
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800357 address_set = 1;
358 else if (!address_set
Pablo Camarillofb380952016-12-07 18:34:18 +0100359 && unformat (input, "addr %U", unformat_ip6_address,
360 &resulting_address))
361 address_set = 1;
362 else if (unformat (input, "fib-table %u", &fib_index));
363 else if (vlan_index == (u32) ~ 0
364 && unformat (input, "vlan %u", &vlan_index));
365 else if (!behavior && unformat (input, "behavior"))
366 {
367 if (unformat (input, "end.x %U %U",
368 unformat_vnet_sw_interface, vnm, &sw_if_index,
369 unformat_ip6_address, &next_hop.ip6))
370 behavior = SR_BEHAVIOR_X;
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200371 else if (unformat (input, "end.t %u", &sw_if_index))
372 behavior = SR_BEHAVIOR_T;
Pablo Camarillofb380952016-12-07 18:34:18 +0100373 else if (unformat (input, "end.dx6 %U %U",
374 unformat_vnet_sw_interface, vnm, &sw_if_index,
375 unformat_ip6_address, &next_hop.ip6))
376 behavior = SR_BEHAVIOR_DX6;
377 else if (unformat (input, "end.dx4 %U %U",
378 unformat_vnet_sw_interface, vnm, &sw_if_index,
379 unformat_ip4_address, &next_hop.ip4))
380 behavior = SR_BEHAVIOR_DX4;
381 else if (unformat (input, "end.dx2 %U",
382 unformat_vnet_sw_interface, vnm, &sw_if_index))
383 behavior = SR_BEHAVIOR_DX2;
384 else if (unformat (input, "end.dt6 %u", &sw_if_index))
385 behavior = SR_BEHAVIOR_DT6;
386 else if (unformat (input, "end.dt4 %u", &sw_if_index))
387 behavior = SR_BEHAVIOR_DT4;
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700388 else if (unformat (input, "un %u", &usid_size))
389 behavior = SR_BEHAVIOR_END_UN_PERF;
390 else if (unformat (input, "un.flex %u", &usid_size))
391 behavior = SR_BEHAVIOR_END_UN;
Pablo Camarillofb380952016-12-07 18:34:18 +0100392 else
393 {
394 /* Loop over all the plugin behavior format functions */
395 sr_localsid_fn_registration_t *plugin = 0, **vec_plugins = 0;
396 sr_localsid_fn_registration_t **plugin_it = 0;
397
398 /* Create a vector out of the plugin pool as recommended */
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800399 /* *INDENT-OFF* */
400 pool_foreach (plugin, sm->plugin_functions,
401 {
402 vec_add1 (vec_plugins, plugin);
403 });
404 /* *INDENT-ON* */
Pablo Camarillofb380952016-12-07 18:34:18 +0100405
406 vec_foreach (plugin_it, vec_plugins)
407 {
408 if (unformat
409 (input, "%U", (*plugin_it)->ls_unformat, &ls_plugin_mem))
410 {
411 behavior = (*plugin_it)->sr_localsid_function_number;
412 break;
413 }
414 }
415 }
416
417 if (!behavior)
418 {
419 if (unformat (input, "end"))
420 behavior = SR_BEHAVIOR_END;
421 else
422 break;
423 }
424 }
425 else if (!end_psp && unformat (input, "psp"))
426 end_psp = 1;
427 else
428 break;
429 }
430
431 if (!behavior && end_psp)
432 behavior = SR_BEHAVIOR_END;
433
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700434 if (usid_size)
435 {
436 if (prefix_len < usid_size)
437 return clib_error_return (0,
438 "Error: Prefix length must be greater"
439 " than uSID length.");
440
441 if (usid_size != 16 && usid_size != 32)
442 return clib_error_return (0,
443 "Error: Invalid uSID length (16 or 32).");
444
445 if ((prefix_len - usid_size) & 0x7)
446 return clib_error_return (0,
447 "Error: Prefix Length must be multiple of 8.");
448 }
449
Pablo Camarillofb380952016-12-07 18:34:18 +0100450 if (!address_set)
451 return clib_error_return (0,
452 "Error: SRv6 LocalSID address is mandatory.");
453 if (!is_del && !behavior)
454 return clib_error_return (0,
455 "Error: SRv6 LocalSID behavior is mandatory.");
456 if (vlan_index != (u32) ~ 0)
457 return clib_error_return (0,
458 "Error: SRv6 End.DX2 with rewrite VLAN tag not supported by now.");
459 if (end_psp && !(behavior == SR_BEHAVIOR_END || behavior == SR_BEHAVIOR_X))
460 return clib_error_return (0,
461 "Error: SRv6 PSP only compatible with End and End.X");
462
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -0800463 rv =
464 sr_cli_localsid (is_del, &resulting_address, prefix_len, end_psp,
465 behavior, sw_if_index, vlan_index, fib_index, &next_hop,
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700466 usid_size, ls_plugin_mem);
467
468 if (behavior == SR_BEHAVIOR_END_UN_PERF)
469 {
470 if (rv == 0)
471 {
472 u16 perf_len;
473 perf_len = prefix_len + usid_size;
474 rv = sr_cli_localsid (is_del, &resulting_address, perf_len, end_psp,
475 SR_BEHAVIOR_END, sw_if_index, vlan_index,
476 fib_index, &next_hop, 0, ls_plugin_mem);
477 }
478 }
Pablo Camarillofb380952016-12-07 18:34:18 +0100479
480 switch (rv)
481 {
482 case 0:
483 break;
484 case 1:
485 return 0;
486 case -1:
487 return clib_error_return (0,
488 "Identical localsid already exists. Requested localsid not created.");
489 case -2:
490 return clib_error_return (0,
491 "The requested localsid could not be deleted. SR localsid not found");
492 case -3:
493 return clib_error_return (0, "FIB table %u does not exist", fib_index);
494 case -4:
495 return clib_error_return (0, "There is already one FIB entry for the"
496 "requested localsid non segment routing related");
497 case -5:
498 return clib_error_return (0,
499 "Could not create ARP/ND entry for such next_hop. Internal error.");
500 case -6:
501 return clib_error_return (0,
502 "Error on the plugin based localsid creation.");
503 default:
504 return clib_error_return (0, "BUG: sr localsid returns %d", rv);
505 }
506 return 0;
507}
508
509/* *INDENT-OFF* */
510VLIB_CLI_COMMAND (sr_localsid_command, static) = {
511 .path = "sr localsid",
512 .short_help = "sr localsid (del) address XX:XX::YY:YY"
513 "(fib-table 8) behavior STRING",
514 .long_help =
515 "Create SR LocalSID and binds it to a particular behavior\n"
516 "Arguments:\n"
517 "\tlocalSID IPv6_addr(128b) LocalSID IPv6 address\n"
518 "\t(fib-table X) Optional. VRF where to install SRv6 localsid\n"
519 "\tbehavior STRING Specifies the behavior\n"
520 "\n\tBehaviors:\n"
521 "\tEnd\t-> Endpoint.\n"
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700522 "\tEnd.uN\t-> Endpoint with uSID.\n"
Pablo Camarillofb380952016-12-07 18:34:18 +0100523 "\tEnd.X\t-> Endpoint with decapsulation and Layer-3 cross-connect.\n"
524 "\t\tParameters: '<iface> <ip6_next_hop>'\n"
525 "\tEnd.DX2\t-> Endpoint with decapsulation and Layer-2 cross-connect.\n"
526 "\t\tParameters: '<iface>'\n"
527 "\tEnd.DX6\t-> Endpoint with decapsulation and IPv6 cross-connect.\n"
528 "\t\tParameters: '<iface> <ip6_next_hop>'\n"
529 "\tEnd.DX4\t-> Endpoint with decapsulation and IPv4 cross-connect.\n"
530 "\t\tParameters: '<iface> <ip4_next_hop>'\n"
531 "\tEnd.DT6\t-> Endpoint with decapsulation and specific IPv6 table lookup.\n"
532 "\t\tParameters: '<ip6_fib_table>'\n"
533 "\tEnd.DT4\t-> Endpoint with decapsulation and specific IPv4 table lookup.\n"
534 "\t\tParameters: '<ip4_fib_table>'\n",
535 .function = sr_cli_localsid_command_fn,
536};
537/* *INDENT-ON* */
538
539/**
540 * @brief CLI function to 'show' all SR LocalSIDs on console.
541 */
542static clib_error_t *
543show_sr_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input,
544 vlib_cli_command_t * cmd)
545{
546 vnet_main_t *vnm = vnet_get_main ();
547 ip6_sr_main_t *sm = &sr_main;
548 ip6_sr_localsid_t **localsid_list = 0;
549 ip6_sr_localsid_t *ls;
550 int i;
551
552 vlib_cli_output (vm, "SRv6 - My LocalSID Table:");
553 vlib_cli_output (vm, "=========================");
554 /* *INDENT-OFF* */
555 pool_foreach (ls, sm->localsids, ({ vec_add1 (localsid_list, ls); }));
556 /* *INDENT-ON* */
557 for (i = 0; i < vec_len (localsid_list); i++)
558 {
559 ls = localsid_list[i];
560 switch (ls->behavior)
561 {
562 case SR_BEHAVIOR_END:
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700563 vlib_cli_output (vm, "\tAddress: \t%U\n\tBehavior: \tEnd",
564 format_ip6_address, &ls->localsid);
565 break;
566 case SR_BEHAVIOR_END_UN:
567 vlib_cli_output (vm,
568 "\tAddress: \t%U\n\tBehavior: \tEnd (flex) [uSID:\t%U/%d, length: %d]",
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000569 format_ip6_address, &ls->localsid,
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700570 format_ip6_address, &ls->usid_block,
571 ls->usid_index * 8, ls->usid_len * 8);
572 break;
573 case SR_BEHAVIOR_END_UN_PERF:
574 vlib_cli_output (vm,
575 "\tAddress: \t%U\n\tBehavior: \tEnd [uSID:\t%U/%d, length: %d]",
576 format_ip6_address, &ls->localsid,
577 format_ip6_address, &ls->usid_block,
578 ls->usid_index * 8, ls->usid_len * 8);
Pablo Camarillofb380952016-12-07 18:34:18 +0100579 break;
580 case SR_BEHAVIOR_X:
581 vlib_cli_output (vm,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000582 "\tAddress: \t%U/%u\n\tBehavior: \tX (Endpoint with Layer-3 cross-connect)"
Pablo Camarillofb380952016-12-07 18:34:18 +0100583 "\n\tIface: \t%U\n\tNext hop: \t%U",
584 format_ip6_address, &ls->localsid,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000585 ls->localsid_prefix_len,
Pablo Camarillofb380952016-12-07 18:34:18 +0100586 format_vnet_sw_if_index_name, vnm, ls->sw_if_index,
587 format_ip6_address, &ls->next_hop.ip6);
588 break;
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200589 case SR_BEHAVIOR_T:
590 vlib_cli_output (vm,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000591 "\tAddress: \t%U/%u\n\tBehavior: \tT (Endpoint with specific IPv6 table lookup)"
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200592 "\n\tTable: \t%u",
Ahmed Abdelsalam13e6fce2019-12-08 12:58:27 +0100593 format_ip6_address, &ls->localsid,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000594 ls->localsid_prefix_len,
Ahmed Abdelsalam13e6fce2019-12-08 12:58:27 +0100595 fib_table_get_table_id (ls->vrf_index,
596 FIB_PROTOCOL_IP6));
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200597 break;
Pablo Camarillofb380952016-12-07 18:34:18 +0100598 case SR_BEHAVIOR_DX4:
599 vlib_cli_output (vm,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000600 "\tAddress: \t%U/%u\n\tBehavior: \tDX4 (Endpoint with decapsulation and IPv4 cross-connect)"
Pablo Camarillofb380952016-12-07 18:34:18 +0100601 "\n\tIface: \t%U\n\tNext hop: \t%U",
602 format_ip6_address, &ls->localsid,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000603 ls->localsid_prefix_len,
Pablo Camarillofb380952016-12-07 18:34:18 +0100604 format_vnet_sw_if_index_name, vnm, ls->sw_if_index,
605 format_ip4_address, &ls->next_hop.ip4);
606 break;
607 case SR_BEHAVIOR_DX6:
608 vlib_cli_output (vm,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000609 "\tAddress: \t%U/%u\n\tBehavior: \tDX6 (Endpoint with decapsulation and IPv6 cross-connect)"
Pablo Camarillofb380952016-12-07 18:34:18 +0100610 "\n\tIface: \t%U\n\tNext hop: \t%U",
611 format_ip6_address, &ls->localsid,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000612 ls->localsid_prefix_len,
Pablo Camarillofb380952016-12-07 18:34:18 +0100613 format_vnet_sw_if_index_name, vnm, ls->sw_if_index,
614 format_ip6_address, &ls->next_hop.ip6);
615 break;
616 case SR_BEHAVIOR_DX2:
617 if (ls->vlan_index == (u32) ~ 0)
618 vlib_cli_output (vm,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000619 "\tAddress: \t%U/%u\n\tBehavior: \tDX2 (Endpoint with decapulation and Layer-2 cross-connect)"
Pablo Camarillofb380952016-12-07 18:34:18 +0100620 "\n\tIface: \t%U", format_ip6_address,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000621 &ls->localsid, ls->localsid_prefix_len,
622 format_vnet_sw_if_index_name, vnm,
Pablo Camarillofb380952016-12-07 18:34:18 +0100623 ls->sw_if_index);
624 else
625 vlib_cli_output (vm,
626 "Unsupported yet. (DX2 with egress VLAN rewrite)");
627 break;
628 case SR_BEHAVIOR_DT6:
629 vlib_cli_output (vm,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000630 "\tAddress: \t%U/%u\n\tBehavior: \tDT6 (Endpoint with decapsulation and specific IPv6 table lookup)"
Pablo Camarillofb380952016-12-07 18:34:18 +0100631 "\n\tTable: %u", format_ip6_address, &ls->localsid,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000632 ls->localsid_prefix_len,
Ahmed Abdelsalam13e6fce2019-12-08 12:58:27 +0100633 fib_table_get_table_id (ls->vrf_index,
634 FIB_PROTOCOL_IP6));
Pablo Camarillofb380952016-12-07 18:34:18 +0100635 break;
636 case SR_BEHAVIOR_DT4:
637 vlib_cli_output (vm,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000638 "\tAddress: \t%U/%u\n\tBehavior: \tDT4 (Endpoint with decapsulation and specific IPv4 table lookup)"
Pablo Camarillofb380952016-12-07 18:34:18 +0100639 "\n\tTable: \t%u", format_ip6_address,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000640 &ls->localsid, ls->localsid_prefix_len,
Ahmed Abdelsalam13e6fce2019-12-08 12:58:27 +0100641 fib_table_get_table_id (ls->vrf_index,
642 FIB_PROTOCOL_IP4));
Pablo Camarillofb380952016-12-07 18:34:18 +0100643 break;
644 default:
645 if (ls->behavior >= SR_BEHAVIOR_LAST)
646 {
647 sr_localsid_fn_registration_t *plugin =
648 pool_elt_at_index (sm->plugin_functions,
649 ls->behavior - SR_BEHAVIOR_LAST);
650
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000651 vlib_cli_output (vm, "\tAddress: \t%U/%u\n"
Pablo Camarillofb380952016-12-07 18:34:18 +0100652 "\tBehavior: \t%s (%s)\n\t%U",
653 format_ip6_address, &ls->localsid,
Pablo Camarillo79bfd272019-12-18 17:13:13 +0000654 ls->localsid_prefix_len, plugin->keyword_str,
655 plugin->def_str, plugin->ls_format,
656 ls->plugin_mem);
Pablo Camarillofb380952016-12-07 18:34:18 +0100657 }
658 else
659 //Should never get here...
660 vlib_cli_output (vm, "Internal error");
661 break;
662 }
663 if (ls->end_psp)
664 vlib_cli_output (vm, "\tPSP: \tTrue\n");
665
666 /* Print counters */
667 vlib_counter_t valid, invalid;
668 vlib_get_combined_counter (&(sm->sr_ls_valid_counters), i, &valid);
669 vlib_get_combined_counter (&(sm->sr_ls_invalid_counters), i, &invalid);
670 vlib_cli_output (vm, "\tGood traffic: \t[%Ld packets : %Ld bytes]\n",
671 valid.packets, valid.bytes);
672 vlib_cli_output (vm, "\tBad traffic: \t[%Ld packets : %Ld bytes]\n",
673 invalid.packets, invalid.bytes);
674 vlib_cli_output (vm, "--------------------");
675 }
676 return 0;
677}
678
679/* *INDENT-OFF* */
680VLIB_CLI_COMMAND (show_sr_localsid_command, static) = {
681 .path = "show sr localsids",
682 .short_help = "show sr localsids",
683 .function = show_sr_localsid_command_fn,
684};
685/* *INDENT-ON* */
686
687/**
688 * @brief Function to 'clear' ALL SR localsid counters
689 */
690static clib_error_t *
691clear_sr_localsid_counters_command_fn (vlib_main_t * vm,
692 unformat_input_t * input,
693 vlib_cli_command_t * cmd)
694{
695 ip6_sr_main_t *sm = &sr_main;
696
697 vlib_clear_combined_counters (&(sm->sr_ls_valid_counters));
698 vlib_clear_combined_counters (&(sm->sr_ls_invalid_counters));
699
700 return 0;
701}
702
703/* *INDENT-OFF* */
704VLIB_CLI_COMMAND (clear_sr_localsid_counters_command, static) = {
Francois Clad4abc5c32018-02-01 14:51:33 +0100705 .path = "clear sr localsid-counters",
706 .short_help = "clear sr localsid-counters",
Pablo Camarillofb380952016-12-07 18:34:18 +0100707 .function = clear_sr_localsid_counters_command_fn,
708};
709/* *INDENT-ON* */
710
711/************************ SR LocalSID graphs node ****************************/
712/**
713 * @brief SR localsid node trace
714 */
715typedef struct
716{
Kris Michielsen91074432017-06-22 13:00:20 +0200717 ip6_address_t localsid;
718 u16 behavior;
Pablo Camarillofb380952016-12-07 18:34:18 +0100719 u8 sr[256];
720 u8 num_segments;
721 u8 segments_left;
Pablo Camarillofb380952016-12-07 18:34:18 +0100722} sr_localsid_trace_t;
723
724#define foreach_sr_localsid_error \
725_(NO_INNER_HEADER, "(SR-Error) No inner IP header") \
726_(NO_MORE_SEGMENTS, "(SR-Error) No more segments") \
727_(NO_SRH, "(SR-Error) No SR header") \
728_(NO_PSP, "(SR-Error) PSP Not available (segments left > 0)") \
729_(NOT_LS, "(SR-Error) Decaps not available (segments left > 0)") \
730_(L2, "(SR-Error) SRv6 decapsulated a L2 frame without dest")
731
732typedef enum
733{
734#define _(sym,str) SR_LOCALSID_ERROR_##sym,
735 foreach_sr_localsid_error
736#undef _
737 SR_LOCALSID_N_ERROR,
738} sr_localsid_error_t;
739
740static char *sr_localsid_error_strings[] = {
741#define _(sym,string) string,
742 foreach_sr_localsid_error
743#undef _
744};
745
746#define foreach_sr_localsid_next \
747_(ERROR, "error-drop") \
748_(IP6_LOOKUP, "ip6-lookup") \
749_(IP4_LOOKUP, "ip4-lookup") \
750_(IP6_REWRITE, "ip6-rewrite") \
751_(IP4_REWRITE, "ip4-rewrite") \
752_(INTERFACE_OUTPUT, "interface-output")
753
754typedef enum
755{
756#define _(s,n) SR_LOCALSID_NEXT_##s,
757 foreach_sr_localsid_next
758#undef _
759 SR_LOCALSID_N_NEXT,
760} sr_localsid_next_t;
761
762/**
763 * @brief SR LocalSID graph node trace function
764 *
765 * @see sr_localsid
766 */
767u8 *
768format_sr_localsid_trace (u8 * s, va_list * args)
769{
770 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
771 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
Pablo Camarillofb380952016-12-07 18:34:18 +0100772 sr_localsid_trace_t *t = va_arg (*args, sr_localsid_trace_t *);
773
Pablo Camarillofb380952016-12-07 18:34:18 +0100774 s =
775 format (s, "SR-LOCALSID:\n\tLocalsid: %U\n", format_ip6_address,
Kris Michielsen91074432017-06-22 13:00:20 +0200776 &t->localsid);
777 switch (t->behavior)
Pablo Camarillofb380952016-12-07 18:34:18 +0100778 {
779 case SR_BEHAVIOR_END:
780 s = format (s, "\tBehavior: End\n");
781 break;
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700782 case SR_BEHAVIOR_END_UN:
783 s = format (s, "\tBehavior: End.uN (flex)\n");
784 break;
785 case SR_BEHAVIOR_END_UN_PERF:
786 s = format (s, "\tBehavior: End.uN\n");
787 break;
Pablo Camarillofb380952016-12-07 18:34:18 +0100788 case SR_BEHAVIOR_DX6:
789 s = format (s, "\tBehavior: Decapsulation with IPv6 L3 xconnect\n");
790 break;
791 case SR_BEHAVIOR_DX4:
792 s = format (s, "\tBehavior: Decapsulation with IPv4 L3 xconnect\n");
793 break;
794 case SR_BEHAVIOR_X:
795 s = format (s, "\tBehavior: IPv6 L3 xconnect\n");
796 break;
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200797 case SR_BEHAVIOR_T:
798 s = format (s, "\tBehavior: IPv6 specific table lookup\n");
799 break;
Pablo Camarillofb380952016-12-07 18:34:18 +0100800 case SR_BEHAVIOR_DT6:
801 s = format (s, "\tBehavior: Decapsulation with IPv6 Table lookup\n");
802 break;
803 case SR_BEHAVIOR_DT4:
804 s = format (s, "\tBehavior: Decapsulation with IPv4 Table lookup\n");
805 break;
806 case SR_BEHAVIOR_DX2:
807 s = format (s, "\tBehavior: Decapsulation with L2 xconnect\n");
808 break;
809 default:
810 s = format (s, "\tBehavior: defined in plugin\n"); //TODO
811 break;
812 }
813 if (t->num_segments != 0xFF)
814 {
815 if (t->num_segments > 0)
816 {
Kris Michielsen91074432017-06-22 13:00:20 +0200817 s = format (s, "\tSegments left: %d\n", t->segments_left);
Pablo Camarillofb380952016-12-07 18:34:18 +0100818 s = format (s, "\tSID list: [in ietf order]");
819 int i = 0;
820 for (i = 0; i < t->num_segments; i++)
821 {
822 s = format (s, "\n\t-> %U", format_ip6_address,
823 (ip6_address_t *) & t->sr[i *
824 sizeof (ip6_address_t)]);
825 }
826 }
827 }
828 return s;
829}
830
831/**
832 * @brief Function doing End processing.
833 */
834static_always_inline void
835end_srh_processing (vlib_node_runtime_t * node,
836 vlib_buffer_t * b0,
837 ip6_header_t * ip0,
838 ip6_sr_header_t * sr0,
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200839 ip6_sr_localsid_t * ls0,
840 u32 * next0, u8 psp, ip6_ext_header_t * prev0)
Pablo Camarillofb380952016-12-07 18:34:18 +0100841{
842 ip6_address_t *new_dst0;
843
Ignas Baciusbd5c49a2020-01-03 15:05:46 +0200844 if (PREDICT_TRUE (sr0 && sr0->type == ROUTING_HEADER_TYPE_SR))
Pablo Camarillofb380952016-12-07 18:34:18 +0100845 {
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200846 if (sr0->segments_left == 1 && psp)
847 {
848 u32 new_l0, sr_len;
849 u64 *copy_dst0, *copy_src0;
850 u32 copy_len_u64s0 = 0;
851
852 ip0->dst_address.as_u64[0] = sr0->segments->as_u64[0];
853 ip0->dst_address.as_u64[1] = sr0->segments->as_u64[1];
854
855 /* Remove the SRH taking care of the rest of IPv6 ext header */
856 if (prev0)
857 prev0->next_hdr = sr0->protocol;
858 else
859 ip0->protocol = sr0->protocol;
860
861 sr_len = ip6_ext_header_len (sr0);
862 vlib_buffer_advance (b0, sr_len);
863 new_l0 = clib_net_to_host_u16 (ip0->payload_length) - sr_len;
864 ip0->payload_length = clib_host_to_net_u16 (new_l0);
865 copy_src0 = (u64 *) ip0;
866 copy_dst0 = copy_src0 + (sr0->length + 1);
867 /* number of 8 octet units to copy
868 * By default in absence of extension headers it is equal to length of ip6 header
869 * With extension headers it number of 8 octet units of ext headers preceding
870 * SR header
871 */
872 copy_len_u64s0 =
873 (((u8 *) sr0 - (u8 *) ip0) - sizeof (ip6_header_t)) >> 3;
874 copy_dst0[4 + copy_len_u64s0] = copy_src0[4 + copy_len_u64s0];
875 copy_dst0[3 + copy_len_u64s0] = copy_src0[3 + copy_len_u64s0];
876 copy_dst0[2 + copy_len_u64s0] = copy_src0[2 + copy_len_u64s0];
877 copy_dst0[1 + copy_len_u64s0] = copy_src0[1 + copy_len_u64s0];
878 copy_dst0[0 + copy_len_u64s0] = copy_src0[0 + copy_len_u64s0];
879
880 int i;
881 for (i = copy_len_u64s0 - 1; i >= 0; i--)
882 {
883 copy_dst0[i] = copy_src0[i];
884 }
885
886 if (ls0->behavior == SR_BEHAVIOR_X)
887 {
888 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0->nh_adj;
889 *next0 = SR_LOCALSID_NEXT_IP6_REWRITE;
890 }
891 else if (ls0->behavior == SR_BEHAVIOR_T)
892 {
893 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->vrf_index;
894 }
895 }
896 else if (PREDICT_TRUE (sr0->segments_left > 0))
Pablo Camarillofb380952016-12-07 18:34:18 +0100897 {
898 sr0->segments_left -= 1;
899 new_dst0 = (ip6_address_t *) (sr0->segments);
900 new_dst0 += sr0->segments_left;
901 ip0->dst_address.as_u64[0] = new_dst0->as_u64[0];
902 ip0->dst_address.as_u64[1] = new_dst0->as_u64[1];
903
904 if (ls0->behavior == SR_BEHAVIOR_X)
905 {
906 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0->nh_adj;
907 *next0 = SR_LOCALSID_NEXT_IP6_REWRITE;
908 }
Pablo Camarillo7a4e0922017-06-06 15:18:12 +0200909 else if (ls0->behavior == SR_BEHAVIOR_T)
910 {
911 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->vrf_index;
912 }
Pablo Camarillofb380952016-12-07 18:34:18 +0100913 }
914 else
915 {
916 *next0 = SR_LOCALSID_NEXT_ERROR;
917 b0->error = node->errors[SR_LOCALSID_ERROR_NO_MORE_SEGMENTS];
918 }
919 }
920 else
921 {
922 /* Error. Routing header of type != SR */
923 *next0 = SR_LOCALSID_NEXT_ERROR;
924 b0->error = node->errors[SR_LOCALSID_ERROR_NO_SRH];
925 }
926}
927
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -0700928/**
929 * @brief Function doing End uN processing.
930 */
931static_always_inline void
932end_un_srh_processing (vlib_node_runtime_t * node,
933 vlib_buffer_t * b0,
934 ip6_header_t * ip0,
935 ip6_sr_header_t * sr0,
936 ip6_sr_localsid_t * ls0,
937 u32 * next0, u8 psp, ip6_ext_header_t * prev0)
938{
939 ip6_address_t *new_dst0;
940 bool next_usid = false;
941 u8 next_usid_index;
942 u8 usid_len;
943 u8 index;
944
945 usid_len = ls0->usid_len;
946 next_usid_index = ls0->usid_next_index;
947
948 /* uSID */
949 for (index = 0; index < usid_len; index++)
950 {
951 if (ip0->dst_address.as_u8[next_usid_index + index] != 0)
952 {
953 next_usid = true;
954 break;
955 }
956 }
957
958 if (PREDICT_TRUE (next_usid))
959 {
960 u8 offset;
961
962 index = ls0->usid_index;
963
964 /* advance next usid */
965 for (offset = 0; offset < ls0->usid_next_len; offset++)
966 {
967 ip0->dst_address.as_u8[index + offset] =
968 ip0->dst_address.as_u8[next_usid_index + offset];
969 }
970
971 for (index = 16 - usid_len; index < 16; index++)
972 {
973 ip0->dst_address.as_u8[index] = 0;
974 }
975
976 return;
977 }
978
979 if (PREDICT_TRUE (sr0 && sr0->type == ROUTING_HEADER_TYPE_SR))
980 {
981 if (sr0->segments_left == 1 && psp)
982 {
983 u32 new_l0, sr_len;
984 u64 *copy_dst0, *copy_src0;
985 u32 copy_len_u64s0 = 0;
986
987 ip0->dst_address.as_u64[0] = sr0->segments->as_u64[0];
988 ip0->dst_address.as_u64[1] = sr0->segments->as_u64[1];
989
990 /* Remove the SRH taking care of the rest of IPv6 ext header */
991 if (prev0)
992 prev0->next_hdr = sr0->protocol;
993 else
994 ip0->protocol = sr0->protocol;
995
996 sr_len = ip6_ext_header_len (sr0);
997 vlib_buffer_advance (b0, sr_len);
998 new_l0 = clib_net_to_host_u16 (ip0->payload_length) - sr_len;
999 ip0->payload_length = clib_host_to_net_u16 (new_l0);
1000 copy_src0 = (u64 *) ip0;
1001 copy_dst0 = copy_src0 + (sr0->length + 1);
1002 /* number of 8 octet units to copy
1003 * By default in absence of extension headers it is equal to length of ip6 header
1004 * With extension headers it number of 8 octet units of ext headers preceding
1005 * SR header
1006 */
1007 copy_len_u64s0 =
1008 (((u8 *) sr0 - (u8 *) ip0) - sizeof (ip6_header_t)) >> 3;
1009 copy_dst0[4 + copy_len_u64s0] = copy_src0[4 + copy_len_u64s0];
1010 copy_dst0[3 + copy_len_u64s0] = copy_src0[3 + copy_len_u64s0];
1011 copy_dst0[2 + copy_len_u64s0] = copy_src0[2 + copy_len_u64s0];
1012 copy_dst0[1 + copy_len_u64s0] = copy_src0[1 + copy_len_u64s0];
1013 copy_dst0[0 + copy_len_u64s0] = copy_src0[0 + copy_len_u64s0];
1014
1015 int i;
1016 for (i = copy_len_u64s0 - 1; i >= 0; i--)
1017 {
1018 copy_dst0[i] = copy_src0[i];
1019 }
1020 }
1021 else if (PREDICT_TRUE (sr0->segments_left > 0))
1022 {
1023 sr0->segments_left -= 1;
1024 new_dst0 = (ip6_address_t *) (sr0->segments);
1025 new_dst0 += sr0->segments_left;
1026 ip0->dst_address.as_u64[0] = new_dst0->as_u64[0];
1027 ip0->dst_address.as_u64[1] = new_dst0->as_u64[1];
1028 }
1029 else
1030 {
1031 *next0 = SR_LOCALSID_NEXT_ERROR;
1032 b0->error = node->errors[SR_LOCALSID_ERROR_NO_MORE_SEGMENTS];
1033 }
1034 }
1035 else
1036 {
1037 /* Error. Routing header of type != SR */
1038 *next0 = SR_LOCALSID_NEXT_ERROR;
1039 b0->error = node->errors[SR_LOCALSID_ERROR_NO_SRH];
1040 }
1041}
1042
1043static_always_inline void
1044end_un_processing (ip6_header_t * ip0, ip6_sr_localsid_t * ls0)
1045{
1046 u8 next_usid_index;
1047 u8 index;
1048 u8 offset;
1049
1050 /* uSID */
1051 index = ls0->usid_index;
1052 next_usid_index = ls0->usid_next_index;
1053
1054 /* advance next usid */
1055 for (offset = 0; offset < ls0->usid_next_len; offset++)
1056 {
1057 ip0->dst_address.as_u8[index + offset] =
1058 ip0->dst_address.as_u8[next_usid_index + offset];
1059 }
1060
1061 for (index = 16 - ls0->usid_len; index < 16; index++)
1062 {
1063 ip0->dst_address.as_u8[index] = 0;
1064 }
1065
1066 return;
1067}
1068
Pablo Camarillofb380952016-12-07 18:34:18 +01001069/*
1070 * @brief Function doing SRH processing for D* variants
1071 */
Pablo Camarillofb380952016-12-07 18:34:18 +01001072static_always_inline void
1073end_decaps_srh_processing (vlib_node_runtime_t * node,
1074 vlib_buffer_t * b0,
1075 ip6_header_t * ip0,
1076 ip6_sr_header_t * sr0,
1077 ip6_sr_localsid_t * ls0, u32 * next0)
1078{
1079 /* Compute the size of the IPv6 header with all Ext. headers */
1080 u8 next_proto;
1081 ip6_ext_header_t *next_ext_header;
1082 u16 total_size = 0;
1083
1084 next_proto = ip0->protocol;
1085 next_ext_header = (void *) (ip0 + 1);
1086 total_size = sizeof (ip6_header_t);
1087 while (ip6_ext_hdr (next_proto))
1088 {
1089 total_size += ip6_ext_header_len (next_ext_header);
1090 next_proto = next_ext_header->next_hdr;
1091 next_ext_header = ip6_ext_next_header (next_ext_header);
1092 }
1093
1094 /* Ensure this is the last segment. Otherwise drop. */
1095 if (sr0 && sr0->segments_left != 0)
1096 {
1097 *next0 = SR_LOCALSID_NEXT_ERROR;
1098 b0->error = node->errors[SR_LOCALSID_ERROR_NOT_LS];
1099 return;
1100 }
1101
1102 switch (next_proto)
1103 {
1104 case IP_PROTOCOL_IPV6:
1105 /* Encap-End IPv6. Pop outer IPv6 header. */
1106 if (ls0->behavior == SR_BEHAVIOR_DX6)
1107 {
1108 vlib_buffer_advance (b0, total_size);
1109 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0->nh_adj;
1110 *next0 = SR_LOCALSID_NEXT_IP6_REWRITE;
1111 return;
1112 }
1113 else if (ls0->behavior == SR_BEHAVIOR_DT6)
1114 {
1115 vlib_buffer_advance (b0, total_size);
Pablo Camarillo7a4e0922017-06-06 15:18:12 +02001116 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->vrf_index;
Pablo Camarillofb380952016-12-07 18:34:18 +01001117 return;
1118 }
1119 break;
1120 case IP_PROTOCOL_IP_IN_IP:
1121 /* Encap-End IPv4. Pop outer IPv6 header */
1122 if (ls0->behavior == SR_BEHAVIOR_DX4)
1123 {
1124 vlib_buffer_advance (b0, total_size);
1125 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0->nh_adj;
1126 *next0 = SR_LOCALSID_NEXT_IP4_REWRITE;
1127 return;
1128 }
1129 else if (ls0->behavior == SR_BEHAVIOR_DT4)
1130 {
1131 vlib_buffer_advance (b0, total_size);
Pablo Camarillo7a4e0922017-06-06 15:18:12 +02001132 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->vrf_index;
Pablo Camarillofb380952016-12-07 18:34:18 +01001133 *next0 = SR_LOCALSID_NEXT_IP4_LOOKUP;
1134 return;
1135 }
1136 break;
pcamaril30e76712020-02-04 08:36:51 +01001137 case IP_PROTOCOL_IP6_ETHERNET:
Pablo Camarillofb380952016-12-07 18:34:18 +01001138 /* L2 encaps */
1139 if (ls0->behavior == SR_BEHAVIOR_DX2)
1140 {
1141 vlib_buffer_advance (b0, total_size);
1142 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->sw_if_index;
1143 *next0 = SR_LOCALSID_NEXT_INTERFACE_OUTPUT;
1144 return;
1145 }
1146 break;
1147 }
1148 *next0 = SR_LOCALSID_NEXT_ERROR;
1149 b0->error = node->errors[SR_LOCALSID_ERROR_NO_INNER_HEADER];
1150 return;
1151}
1152
1153/**
Kris Michielsen91074432017-06-22 13:00:20 +02001154 * @brief SR LocalSID graph node. Supports all default SR Endpoint variants with decaps
Pablo Camarillofb380952016-12-07 18:34:18 +01001155 */
1156static uword
1157sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1158 vlib_frame_t * from_frame)
1159{
1160 u32 n_left_from, next_index, *from, *to_next;
1161 ip6_sr_main_t *sm = &sr_main;
1162 from = vlib_frame_vector_args (from_frame);
1163 n_left_from = from_frame->n_vectors;
1164 next_index = node->cached_next_index;
Damjan Marion067cd622018-07-11 12:47:43 +02001165 u32 thread_index = vm->thread_index;
Pablo Camarillofb380952016-12-07 18:34:18 +01001166
1167 while (n_left_from > 0)
1168 {
1169 u32 n_left_to_next;
1170 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1171
1172 /* Quad - Loop */
1173 while (n_left_from >= 8 && n_left_to_next >= 4)
1174 {
1175 u32 bi0, bi1, bi2, bi3;
1176 vlib_buffer_t *b0, *b1, *b2, *b3;
1177 ip6_header_t *ip0, *ip1, *ip2, *ip3;
Pablo Camarillofb380952016-12-07 18:34:18 +01001178 ip6_sr_header_t *sr0, *sr1, *sr2, *sr3;
1179 u32 next0, next1, next2, next3;
1180 next0 = next1 = next2 = next3 = SR_LOCALSID_NEXT_IP6_LOOKUP;
1181 ip6_sr_localsid_t *ls0, *ls1, *ls2, *ls3;
1182
1183 /* Prefetch next iteration. */
1184 {
1185 vlib_buffer_t *p4, *p5, *p6, *p7;
1186
1187 p4 = vlib_get_buffer (vm, from[4]);
1188 p5 = vlib_get_buffer (vm, from[5]);
1189 p6 = vlib_get_buffer (vm, from[6]);
1190 p7 = vlib_get_buffer (vm, from[7]);
1191
1192 /* Prefetch the buffer header and packet for the N+4 loop iteration */
1193 vlib_prefetch_buffer_header (p4, LOAD);
1194 vlib_prefetch_buffer_header (p5, LOAD);
1195 vlib_prefetch_buffer_header (p6, LOAD);
1196 vlib_prefetch_buffer_header (p7, LOAD);
1197
1198 CLIB_PREFETCH (p4->data, CLIB_CACHE_LINE_BYTES, STORE);
1199 CLIB_PREFETCH (p5->data, CLIB_CACHE_LINE_BYTES, STORE);
1200 CLIB_PREFETCH (p6->data, CLIB_CACHE_LINE_BYTES, STORE);
1201 CLIB_PREFETCH (p7->data, CLIB_CACHE_LINE_BYTES, STORE);
1202 }
1203
1204 to_next[0] = bi0 = from[0];
1205 to_next[1] = bi1 = from[1];
1206 to_next[2] = bi2 = from[2];
1207 to_next[3] = bi3 = from[3];
1208 from += 4;
1209 to_next += 4;
1210 n_left_from -= 4;
1211 n_left_to_next -= 4;
1212
1213 b0 = vlib_get_buffer (vm, bi0);
1214 b1 = vlib_get_buffer (vm, bi1);
1215 b2 = vlib_get_buffer (vm, bi2);
1216 b3 = vlib_get_buffer (vm, bi3);
1217
1218 ls0 =
1219 pool_elt_at_index (sm->localsids,
1220 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1221 ls1 =
1222 pool_elt_at_index (sm->localsids,
Francois Cladc82b3582018-07-12 09:56:23 +02001223 vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
Pablo Camarillofb380952016-12-07 18:34:18 +01001224 ls2 =
1225 pool_elt_at_index (sm->localsids,
Francois Cladc82b3582018-07-12 09:56:23 +02001226 vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
Pablo Camarillofb380952016-12-07 18:34:18 +01001227 ls3 =
1228 pool_elt_at_index (sm->localsids,
Francois Cladc82b3582018-07-12 09:56:23 +02001229 vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
Pablo Camarillofb380952016-12-07 18:34:18 +01001230
1231 ip0 = vlib_buffer_get_current (b0);
1232 ip1 = vlib_buffer_get_current (b1);
1233 ip2 = vlib_buffer_get_current (b2);
1234 ip3 = vlib_buffer_get_current (b3);
1235
Klement Sekera769145c2019-03-06 11:59:57 +01001236 sr0 =
1237 ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, NULL);
1238 sr1 =
1239 ip6_ext_header_find (vm, b1, ip1, IP_PROTOCOL_IPV6_ROUTE, NULL);
1240 sr2 =
1241 ip6_ext_header_find (vm, b2, ip2, IP_PROTOCOL_IPV6_ROUTE, NULL);
1242 sr3 =
1243 ip6_ext_header_find (vm, b3, ip3, IP_PROTOCOL_IPV6_ROUTE, NULL);
Pablo Camarillofb380952016-12-07 18:34:18 +01001244
1245 end_decaps_srh_processing (node, b0, ip0, sr0, ls0, &next0);
1246 end_decaps_srh_processing (node, b1, ip1, sr1, ls1, &next1);
1247 end_decaps_srh_processing (node, b2, ip2, sr2, ls2, &next2);
1248 end_decaps_srh_processing (node, b3, ip3, sr3, ls3, &next3);
1249
Kris Michielsen91074432017-06-22 13:00:20 +02001250 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1251 {
1252 sr_localsid_trace_t *tr =
1253 vlib_add_trace (vm, node, b0, sizeof (*tr));
1254 tr->num_segments = 0;
1255 clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8,
1256 sizeof (tr->localsid.as_u8));
1257 tr->behavior = ls0->behavior;
1258 if (ip0 == vlib_buffer_get_current (b0))
1259 {
1260 if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE
1261 && sr0->type == ROUTING_HEADER_TYPE_SR)
1262 {
1263 clib_memcpy (tr->sr, sr0->segments, sr0->length * 8);
1264 tr->num_segments =
1265 sr0->length * 8 / sizeof (ip6_address_t);
1266 tr->segments_left = sr0->segments_left;
1267 }
1268 }
1269 else
1270 tr->num_segments = 0xFF;
1271 }
1272
1273 if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
1274 {
1275 sr_localsid_trace_t *tr =
1276 vlib_add_trace (vm, node, b1, sizeof (*tr));
1277 tr->num_segments = 0;
1278 clib_memcpy (tr->localsid.as_u8, ls1->localsid.as_u8,
1279 sizeof (tr->localsid.as_u8));
1280 tr->behavior = ls1->behavior;
1281 if (ip1 == vlib_buffer_get_current (b1))
1282 {
1283 if (ip1->protocol == IP_PROTOCOL_IPV6_ROUTE
1284 && sr1->type == ROUTING_HEADER_TYPE_SR)
1285 {
1286 clib_memcpy (tr->sr, sr1->segments, sr1->length * 8);
1287 tr->num_segments =
1288 sr1->length * 8 / sizeof (ip6_address_t);
1289 tr->segments_left = sr1->segments_left;
1290 }
1291 }
1292 else
1293 tr->num_segments = 0xFF;
1294 }
1295
1296 if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
1297 {
1298 sr_localsid_trace_t *tr =
1299 vlib_add_trace (vm, node, b2, sizeof (*tr));
1300 tr->num_segments = 0;
1301 clib_memcpy (tr->localsid.as_u8, ls2->localsid.as_u8,
1302 sizeof (tr->localsid.as_u8));
1303 tr->behavior = ls2->behavior;
1304 if (ip2 == vlib_buffer_get_current (b2))
1305 {
1306 if (ip2->protocol == IP_PROTOCOL_IPV6_ROUTE
1307 && sr2->type == ROUTING_HEADER_TYPE_SR)
1308 {
1309 clib_memcpy (tr->sr, sr2->segments, sr2->length * 8);
1310 tr->num_segments =
1311 sr2->length * 8 / sizeof (ip6_address_t);
1312 tr->segments_left = sr2->segments_left;
1313 }
1314 }
1315 else
1316 tr->num_segments = 0xFF;
1317 }
1318
1319 if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
1320 {
1321 sr_localsid_trace_t *tr =
1322 vlib_add_trace (vm, node, b3, sizeof (*tr));
1323 tr->num_segments = 0;
1324 clib_memcpy (tr->localsid.as_u8, ls3->localsid.as_u8,
1325 sizeof (tr->localsid.as_u8));
1326 tr->behavior = ls3->behavior;
1327 if (ip3 == vlib_buffer_get_current (b3))
1328 {
1329 if (ip3->protocol == IP_PROTOCOL_IPV6_ROUTE
1330 && sr3->type == ROUTING_HEADER_TYPE_SR)
1331 {
1332 clib_memcpy (tr->sr, sr3->segments, sr3->length * 8);
1333 tr->num_segments =
1334 sr3->length * 8 / sizeof (ip6_address_t);
1335 tr->segments_left = sr3->segments_left;
1336 }
1337 }
1338 else
1339 tr->num_segments = 0xFF;
1340 }
Pablo Camarillofb380952016-12-07 18:34:18 +01001341
1342 vlib_increment_combined_counter
1343 (((next0 ==
1344 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001345 &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids,
1346 1, vlib_buffer_length_in_chain (vm, b0));
Pablo Camarillofb380952016-12-07 18:34:18 +01001347
1348 vlib_increment_combined_counter
1349 (((next1 ==
1350 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001351 &(sm->sr_ls_valid_counters)), thread_index, ls1 - sm->localsids,
1352 1, vlib_buffer_length_in_chain (vm, b1));
Pablo Camarillofb380952016-12-07 18:34:18 +01001353
1354 vlib_increment_combined_counter
1355 (((next2 ==
1356 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001357 &(sm->sr_ls_valid_counters)), thread_index, ls2 - sm->localsids,
1358 1, vlib_buffer_length_in_chain (vm, b2));
Pablo Camarillofb380952016-12-07 18:34:18 +01001359
1360 vlib_increment_combined_counter
1361 (((next3 ==
1362 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001363 &(sm->sr_ls_valid_counters)), thread_index, ls3 - sm->localsids,
1364 1, vlib_buffer_length_in_chain (vm, b3));
Pablo Camarillofb380952016-12-07 18:34:18 +01001365
1366 vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
1367 n_left_to_next, bi0, bi1, bi2, bi3,
1368 next0, next1, next2, next3);
1369 }
1370
1371 /* Single loop for potentially the last three packets */
1372 while (n_left_from > 0 && n_left_to_next > 0)
1373 {
1374 u32 bi0;
1375 vlib_buffer_t *b0;
1376 ip6_header_t *ip0;
Pablo Camarillofb380952016-12-07 18:34:18 +01001377 ip6_sr_header_t *sr0;
1378 u32 next0 = SR_LOCALSID_NEXT_IP6_LOOKUP;
1379 ip6_sr_localsid_t *ls0;
1380
1381 bi0 = from[0];
1382 to_next[0] = bi0;
1383 from += 1;
1384 to_next += 1;
1385 n_left_from -= 1;
1386 n_left_to_next -= 1;
1387
1388 b0 = vlib_get_buffer (vm, bi0);
1389 ip0 = vlib_buffer_get_current (b0);
1390
1391 /* Lookup the SR End behavior based on IP DA (adj) */
1392 ls0 =
1393 pool_elt_at_index (sm->localsids,
1394 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1395
1396 /* Find SRH as well as previous header */
Klement Sekera769145c2019-03-06 11:59:57 +01001397 sr0 =
1398 ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, NULL);
Pablo Camarillofb380952016-12-07 18:34:18 +01001399
1400 /* SRH processing and End variants */
1401 end_decaps_srh_processing (node, b0, ip0, sr0, ls0, &next0);
1402
1403 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1404 {
1405 sr_localsid_trace_t *tr =
1406 vlib_add_trace (vm, node, b0, sizeof (*tr));
1407 tr->num_segments = 0;
Kris Michielsen91074432017-06-22 13:00:20 +02001408 clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8,
1409 sizeof (tr->localsid.as_u8));
1410 tr->behavior = ls0->behavior;
Pablo Camarillofb380952016-12-07 18:34:18 +01001411 if (ip0 == vlib_buffer_get_current (b0))
1412 {
Pablo Camarillofb380952016-12-07 18:34:18 +01001413 if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE
1414 && sr0->type == ROUTING_HEADER_TYPE_SR)
1415 {
1416 clib_memcpy (tr->sr, sr0->segments, sr0->length * 8);
1417 tr->num_segments =
1418 sr0->length * 8 / sizeof (ip6_address_t);
1419 tr->segments_left = sr0->segments_left;
1420 }
1421 }
1422 else
1423 tr->num_segments = 0xFF;
1424 }
1425
1426 /* Increase the counters */
1427 vlib_increment_combined_counter
1428 (((next0 ==
1429 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001430 &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids,
1431 1, vlib_buffer_length_in_chain (vm, b0));
Pablo Camarillofb380952016-12-07 18:34:18 +01001432
1433 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1434 n_left_to_next, bi0, next0);
1435 }
1436 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1437 }
1438 return from_frame->n_vectors;
1439}
1440
1441/* *INDENT-OFF* */
1442VLIB_REGISTER_NODE (sr_localsid_d_node) = {
1443 .function = sr_localsid_d_fn,
1444 .name = "sr-localsid-d",
1445 .vector_size = sizeof (u32),
1446 .format_trace = format_sr_localsid_trace,
1447 .type = VLIB_NODE_TYPE_INTERNAL,
1448 .n_errors = SR_LOCALSID_N_ERROR,
1449 .error_strings = sr_localsid_error_strings,
1450 .n_next_nodes = SR_LOCALSID_N_NEXT,
1451 .next_nodes = {
1452#define _(s,n) [SR_LOCALSID_NEXT_##s] = n,
1453 foreach_sr_localsid_next
1454#undef _
1455 },
1456};
1457/* *INDENT-ON* */
1458
1459/**
Kris Michielsen91074432017-06-22 13:00:20 +02001460 * @brief SR LocalSID graph node. Supports all default SR Endpoint without decaps
Pablo Camarillofb380952016-12-07 18:34:18 +01001461 */
1462static uword
1463sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1464 vlib_frame_t * from_frame)
1465{
1466 u32 n_left_from, next_index, *from, *to_next;
1467 ip6_sr_main_t *sm = &sr_main;
1468 from = vlib_frame_vector_args (from_frame);
1469 n_left_from = from_frame->n_vectors;
1470 next_index = node->cached_next_index;
Damjan Marion067cd622018-07-11 12:47:43 +02001471 u32 thread_index = vm->thread_index;
Pablo Camarillofb380952016-12-07 18:34:18 +01001472
1473 while (n_left_from > 0)
1474 {
1475 u32 n_left_to_next;
1476 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1477
1478 /* Quad - Loop */
1479 while (n_left_from >= 8 && n_left_to_next >= 4)
1480 {
1481 u32 bi0, bi1, bi2, bi3;
1482 vlib_buffer_t *b0, *b1, *b2, *b3;
1483 ip6_header_t *ip0, *ip1, *ip2, *ip3;
1484 ip6_sr_header_t *sr0, *sr1, *sr2, *sr3;
1485 ip6_ext_header_t *prev0, *prev1, *prev2, *prev3;
1486 u32 next0, next1, next2, next3;
1487 next0 = next1 = next2 = next3 = SR_LOCALSID_NEXT_IP6_LOOKUP;
1488 ip6_sr_localsid_t *ls0, *ls1, *ls2, *ls3;
1489
1490 /* Prefetch next iteration. */
1491 {
1492 vlib_buffer_t *p4, *p5, *p6, *p7;
1493
1494 p4 = vlib_get_buffer (vm, from[4]);
1495 p5 = vlib_get_buffer (vm, from[5]);
1496 p6 = vlib_get_buffer (vm, from[6]);
1497 p7 = vlib_get_buffer (vm, from[7]);
1498
1499 /* Prefetch the buffer header and packet for the N+2 loop iteration */
1500 vlib_prefetch_buffer_header (p4, LOAD);
1501 vlib_prefetch_buffer_header (p5, LOAD);
1502 vlib_prefetch_buffer_header (p6, LOAD);
1503 vlib_prefetch_buffer_header (p7, LOAD);
1504
1505 CLIB_PREFETCH (p4->data, CLIB_CACHE_LINE_BYTES, STORE);
1506 CLIB_PREFETCH (p5->data, CLIB_CACHE_LINE_BYTES, STORE);
1507 CLIB_PREFETCH (p6->data, CLIB_CACHE_LINE_BYTES, STORE);
1508 CLIB_PREFETCH (p7->data, CLIB_CACHE_LINE_BYTES, STORE);
1509 }
1510
1511 to_next[0] = bi0 = from[0];
1512 to_next[1] = bi1 = from[1];
1513 to_next[2] = bi2 = from[2];
1514 to_next[3] = bi3 = from[3];
1515 from += 4;
1516 to_next += 4;
1517 n_left_from -= 4;
1518 n_left_to_next -= 4;
1519
1520 b0 = vlib_get_buffer (vm, bi0);
1521 b1 = vlib_get_buffer (vm, bi1);
1522 b2 = vlib_get_buffer (vm, bi2);
1523 b3 = vlib_get_buffer (vm, bi3);
1524
1525 ip0 = vlib_buffer_get_current (b0);
1526 ip1 = vlib_buffer_get_current (b1);
1527 ip2 = vlib_buffer_get_current (b2);
1528 ip3 = vlib_buffer_get_current (b3);
1529
Klement Sekera769145c2019-03-06 11:59:57 +01001530 sr0 =
1531 ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, &prev0);
1532 sr1 =
1533 ip6_ext_header_find (vm, b1, ip1, IP_PROTOCOL_IPV6_ROUTE, &prev1);
1534 sr2 =
1535 ip6_ext_header_find (vm, b2, ip2, IP_PROTOCOL_IPV6_ROUTE, &prev2);
1536 sr3 =
1537 ip6_ext_header_find (vm, b3, ip3, IP_PROTOCOL_IPV6_ROUTE, &prev3);
Pablo Camarillofb380952016-12-07 18:34:18 +01001538
1539 ls0 =
1540 pool_elt_at_index (sm->localsids,
1541 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1542 ls1 =
1543 pool_elt_at_index (sm->localsids,
Francois Cladc82b3582018-07-12 09:56:23 +02001544 vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
Pablo Camarillofb380952016-12-07 18:34:18 +01001545 ls2 =
1546 pool_elt_at_index (sm->localsids,
Francois Cladc82b3582018-07-12 09:56:23 +02001547 vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
Pablo Camarillofb380952016-12-07 18:34:18 +01001548 ls3 =
1549 pool_elt_at_index (sm->localsids,
Francois Cladc82b3582018-07-12 09:56:23 +02001550 vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
Pablo Camarillofb380952016-12-07 18:34:18 +01001551
Pablo Camarillo7a4e0922017-06-06 15:18:12 +02001552 end_srh_processing (node, b0, ip0, sr0, ls0, &next0, ls0->end_psp,
1553 prev0);
1554 end_srh_processing (node, b1, ip1, sr1, ls1, &next1, ls1->end_psp,
1555 prev1);
1556 end_srh_processing (node, b2, ip2, sr2, ls2, &next2, ls2->end_psp,
1557 prev2);
1558 end_srh_processing (node, b3, ip3, sr3, ls3, &next3, ls3->end_psp,
1559 prev3);
Pablo Camarillofb380952016-12-07 18:34:18 +01001560
Kris Michielsen91074432017-06-22 13:00:20 +02001561 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1562 {
1563 sr_localsid_trace_t *tr =
1564 vlib_add_trace (vm, node, b0, sizeof (*tr));
1565 tr->num_segments = 0;
1566 clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8,
1567 sizeof (tr->localsid.as_u8));
1568 tr->behavior = ls0->behavior;
1569 if (ip0 == vlib_buffer_get_current (b0))
1570 {
1571 if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE
1572 && sr0->type == ROUTING_HEADER_TYPE_SR)
1573 {
1574 clib_memcpy (tr->sr, sr0->segments, sr0->length * 8);
1575 tr->num_segments =
1576 sr0->length * 8 / sizeof (ip6_address_t);
1577 tr->segments_left = sr0->segments_left;
1578 }
1579 }
1580 else
1581 tr->num_segments = 0xFF;
1582 }
1583
1584 if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
1585 {
1586 sr_localsid_trace_t *tr =
1587 vlib_add_trace (vm, node, b1, sizeof (*tr));
1588 tr->num_segments = 0;
1589 clib_memcpy (tr->localsid.as_u8, ls1->localsid.as_u8,
1590 sizeof (tr->localsid.as_u8));
1591 tr->behavior = ls1->behavior;
1592 if (ip1 == vlib_buffer_get_current (b1))
1593 {
1594 if (ip1->protocol == IP_PROTOCOL_IPV6_ROUTE
1595 && sr1->type == ROUTING_HEADER_TYPE_SR)
1596 {
1597 clib_memcpy (tr->sr, sr1->segments, sr1->length * 8);
1598 tr->num_segments =
1599 sr1->length * 8 / sizeof (ip6_address_t);
1600 tr->segments_left = sr1->segments_left;
1601 }
1602 }
1603 else
1604 tr->num_segments = 0xFF;
1605 }
1606
1607 if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
1608 {
1609 sr_localsid_trace_t *tr =
1610 vlib_add_trace (vm, node, b2, sizeof (*tr));
1611 tr->num_segments = 0;
1612 clib_memcpy (tr->localsid.as_u8, ls2->localsid.as_u8,
1613 sizeof (tr->localsid.as_u8));
1614 tr->behavior = ls2->behavior;
1615 if (ip2 == vlib_buffer_get_current (b2))
1616 {
1617 if (ip2->protocol == IP_PROTOCOL_IPV6_ROUTE
1618 && sr2->type == ROUTING_HEADER_TYPE_SR)
1619 {
1620 clib_memcpy (tr->sr, sr2->segments, sr2->length * 8);
1621 tr->num_segments =
1622 sr2->length * 8 / sizeof (ip6_address_t);
1623 tr->segments_left = sr2->segments_left;
1624 }
1625 }
1626 else
1627 tr->num_segments = 0xFF;
1628 }
1629
1630 if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
1631 {
1632 sr_localsid_trace_t *tr =
1633 vlib_add_trace (vm, node, b3, sizeof (*tr));
1634 tr->num_segments = 0;
1635 clib_memcpy (tr->localsid.as_u8, ls3->localsid.as_u8,
1636 sizeof (tr->localsid.as_u8));
1637 tr->behavior = ls3->behavior;
1638 if (ip3 == vlib_buffer_get_current (b3))
1639 {
1640 if (ip3->protocol == IP_PROTOCOL_IPV6_ROUTE
1641 && sr3->type == ROUTING_HEADER_TYPE_SR)
1642 {
1643 clib_memcpy (tr->sr, sr3->segments, sr3->length * 8);
1644 tr->num_segments =
1645 sr3->length * 8 / sizeof (ip6_address_t);
1646 tr->segments_left = sr3->segments_left;
1647 }
1648 }
1649 else
1650 tr->num_segments = 0xFF;
1651 }
Pablo Camarillofb380952016-12-07 18:34:18 +01001652
1653 vlib_increment_combined_counter
1654 (((next0 ==
1655 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001656 &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids,
1657 1, vlib_buffer_length_in_chain (vm, b0));
Pablo Camarillofb380952016-12-07 18:34:18 +01001658
1659 vlib_increment_combined_counter
1660 (((next1 ==
1661 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001662 &(sm->sr_ls_valid_counters)), thread_index, ls1 - sm->localsids,
1663 1, vlib_buffer_length_in_chain (vm, b1));
Pablo Camarillofb380952016-12-07 18:34:18 +01001664
1665 vlib_increment_combined_counter
1666 (((next2 ==
1667 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001668 &(sm->sr_ls_valid_counters)), thread_index, ls2 - sm->localsids,
1669 1, vlib_buffer_length_in_chain (vm, b2));
Pablo Camarillofb380952016-12-07 18:34:18 +01001670
1671 vlib_increment_combined_counter
1672 (((next3 ==
1673 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001674 &(sm->sr_ls_valid_counters)), thread_index, ls3 - sm->localsids,
1675 1, vlib_buffer_length_in_chain (vm, b3));
Pablo Camarillofb380952016-12-07 18:34:18 +01001676
1677 vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
1678 n_left_to_next, bi0, bi1, bi2, bi3,
1679 next0, next1, next2, next3);
1680 }
1681
1682 /* Single loop for potentially the last three packets */
1683 while (n_left_from > 0 && n_left_to_next > 0)
1684 {
1685 u32 bi0;
1686 vlib_buffer_t *b0;
1687 ip6_header_t *ip0 = 0;
1688 ip6_ext_header_t *prev0;
1689 ip6_sr_header_t *sr0;
1690 u32 next0 = SR_LOCALSID_NEXT_IP6_LOOKUP;
1691 ip6_sr_localsid_t *ls0;
1692
1693 bi0 = from[0];
1694 to_next[0] = bi0;
1695 from += 1;
1696 to_next += 1;
1697 n_left_from -= 1;
1698 n_left_to_next -= 1;
1699
1700 b0 = vlib_get_buffer (vm, bi0);
1701 ip0 = vlib_buffer_get_current (b0);
Klement Sekera769145c2019-03-06 11:59:57 +01001702 sr0 =
1703 ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, &prev0);
Pablo Camarillofb380952016-12-07 18:34:18 +01001704
1705 /* Lookup the SR End behavior based on IP DA (adj) */
1706 ls0 =
1707 pool_elt_at_index (sm->localsids,
1708 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1709
1710 /* SRH processing */
Pablo Camarillo7a4e0922017-06-06 15:18:12 +02001711 end_srh_processing (node, b0, ip0, sr0, ls0, &next0, ls0->end_psp,
1712 prev0);
Pablo Camarillofb380952016-12-07 18:34:18 +01001713
1714 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1715 {
1716 sr_localsid_trace_t *tr =
1717 vlib_add_trace (vm, node, b0, sizeof (*tr));
1718 tr->num_segments = 0;
Kris Michielsen91074432017-06-22 13:00:20 +02001719 clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8,
1720 sizeof (tr->localsid.as_u8));
1721 tr->behavior = ls0->behavior;
Pablo Camarillofb380952016-12-07 18:34:18 +01001722 if (ip0 == vlib_buffer_get_current (b0))
1723 {
Pablo Camarillofb380952016-12-07 18:34:18 +01001724 if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE
1725 && sr0->type == ROUTING_HEADER_TYPE_SR)
1726 {
1727 clib_memcpy (tr->sr, sr0->segments, sr0->length * 8);
1728 tr->num_segments =
1729 sr0->length * 8 / sizeof (ip6_address_t);
1730 tr->segments_left = sr0->segments_left;
1731 }
1732 }
1733 else
Kris Michielsen91074432017-06-22 13:00:20 +02001734 tr->num_segments = 0xFF;
Pablo Camarillofb380952016-12-07 18:34:18 +01001735 }
1736
1737 vlib_increment_combined_counter
1738 (((next0 ==
1739 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
Damjan Marion586afd72017-04-05 19:18:20 +02001740 &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids,
1741 1, vlib_buffer_length_in_chain (vm, b0));
Pablo Camarillofb380952016-12-07 18:34:18 +01001742
1743 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1744 n_left_to_next, bi0, next0);
1745 }
1746 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1747 }
1748 return from_frame->n_vectors;
1749}
1750
1751/* *INDENT-OFF* */
1752VLIB_REGISTER_NODE (sr_localsid_node) = {
1753 .function = sr_localsid_fn,
1754 .name = "sr-localsid",
1755 .vector_size = sizeof (u32),
1756 .format_trace = format_sr_localsid_trace,
1757 .type = VLIB_NODE_TYPE_INTERNAL,
1758 .n_errors = SR_LOCALSID_N_ERROR,
1759 .error_strings = sr_localsid_error_strings,
1760 .n_next_nodes = SR_LOCALSID_N_NEXT,
1761 .next_nodes = {
1762#define _(s,n) [SR_LOCALSID_NEXT_##s] = n,
1763 foreach_sr_localsid_next
1764#undef _
1765 },
1766};
1767/* *INDENT-ON* */
1768
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -07001769/**
1770 * @brief SR LocalSID uN graph node. Supports all default SR Endpoint without decaps
1771 */
1772static uword
1773sr_localsid_un_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
1774 vlib_frame_t * from_frame)
1775{
1776 u32 n_left_from, next_index, *from, *to_next;
1777 ip6_sr_main_t *sm = &sr_main;
1778 from = vlib_frame_vector_args (from_frame);
1779 n_left_from = from_frame->n_vectors;
1780 next_index = node->cached_next_index;
1781 u32 thread_index = vm->thread_index;
1782
1783 while (n_left_from > 0)
1784 {
1785 u32 n_left_to_next;
1786 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1787
1788 /* Quad - Loop */
1789 while (n_left_from >= 8 && n_left_to_next >= 4)
1790 {
1791 u32 bi0, bi1, bi2, bi3;
1792 vlib_buffer_t *b0, *b1, *b2, *b3;
1793 ip6_header_t *ip0, *ip1, *ip2, *ip3;
1794 ip6_sr_header_t *sr0, *sr1, *sr2, *sr3;
1795 ip6_ext_header_t *prev0, *prev1, *prev2, *prev3;
1796 u32 next0, next1, next2, next3;
1797 next0 = next1 = next2 = next3 = SR_LOCALSID_NEXT_IP6_LOOKUP;
1798 ip6_sr_localsid_t *ls0, *ls1, *ls2, *ls3;
1799
1800 /* Prefetch next iteration. */
1801 {
1802 vlib_buffer_t *p4, *p5, *p6, *p7;
1803
1804 p4 = vlib_get_buffer (vm, from[4]);
1805 p5 = vlib_get_buffer (vm, from[5]);
1806 p6 = vlib_get_buffer (vm, from[6]);
1807 p7 = vlib_get_buffer (vm, from[7]);
1808
1809 /* Prefetch the buffer header and packet for the N+2 loop iteration */
1810 vlib_prefetch_buffer_header (p4, LOAD);
1811 vlib_prefetch_buffer_header (p5, LOAD);
1812 vlib_prefetch_buffer_header (p6, LOAD);
1813 vlib_prefetch_buffer_header (p7, LOAD);
1814
1815 CLIB_PREFETCH (p4->data, CLIB_CACHE_LINE_BYTES, STORE);
1816 CLIB_PREFETCH (p5->data, CLIB_CACHE_LINE_BYTES, STORE);
1817 CLIB_PREFETCH (p6->data, CLIB_CACHE_LINE_BYTES, STORE);
1818 CLIB_PREFETCH (p7->data, CLIB_CACHE_LINE_BYTES, STORE);
1819 }
1820
1821 to_next[0] = bi0 = from[0];
1822 to_next[1] = bi1 = from[1];
1823 to_next[2] = bi2 = from[2];
1824 to_next[3] = bi3 = from[3];
1825 from += 4;
1826 to_next += 4;
1827 n_left_from -= 4;
1828 n_left_to_next -= 4;
1829
1830 b0 = vlib_get_buffer (vm, bi0);
1831 b1 = vlib_get_buffer (vm, bi1);
1832 b2 = vlib_get_buffer (vm, bi2);
1833 b3 = vlib_get_buffer (vm, bi3);
1834
1835 ip0 = vlib_buffer_get_current (b0);
1836 ip1 = vlib_buffer_get_current (b1);
1837 ip2 = vlib_buffer_get_current (b2);
1838 ip3 = vlib_buffer_get_current (b3);
1839
1840 sr0 =
1841 ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, &prev0);
1842 sr1 =
1843 ip6_ext_header_find (vm, b1, ip1, IP_PROTOCOL_IPV6_ROUTE, &prev1);
1844 sr2 =
1845 ip6_ext_header_find (vm, b2, ip2, IP_PROTOCOL_IPV6_ROUTE, &prev2);
1846 sr3 =
1847 ip6_ext_header_find (vm, b3, ip3, IP_PROTOCOL_IPV6_ROUTE, &prev3);
1848
1849 ls0 =
1850 pool_elt_at_index (sm->localsids,
1851 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1852 ls1 =
1853 pool_elt_at_index (sm->localsids,
1854 vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
1855 ls2 =
1856 pool_elt_at_index (sm->localsids,
1857 vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
1858 ls3 =
1859 pool_elt_at_index (sm->localsids,
1860 vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
1861
1862 end_un_srh_processing (node, b0, ip0, sr0, ls0, &next0,
1863 ls0->end_psp, prev0);
1864 end_un_srh_processing (node, b1, ip1, sr1, ls1, &next1,
1865 ls1->end_psp, prev1);
1866 end_un_srh_processing (node, b2, ip2, sr2, ls2, &next2,
1867 ls2->end_psp, prev2);
1868 end_un_srh_processing (node, b3, ip3, sr3, ls3, &next3,
1869 ls3->end_psp, prev3);
1870
1871 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1872 {
1873 sr_localsid_trace_t *tr =
1874 vlib_add_trace (vm, node, b0, sizeof (*tr));
1875 tr->num_segments = 0;
1876 clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8,
1877 sizeof (tr->localsid.as_u8));
1878 tr->behavior = ls0->behavior;
1879 if (ip0 == vlib_buffer_get_current (b0))
1880 {
1881 if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE
1882 && sr0->type == ROUTING_HEADER_TYPE_SR)
1883 {
1884 clib_memcpy (tr->sr, sr0->segments, sr0->length * 8);
1885 tr->num_segments =
1886 sr0->length * 8 / sizeof (ip6_address_t);
1887 tr->segments_left = sr0->segments_left;
1888 }
1889 }
1890 else
1891 tr->num_segments = 0xFF;
1892 }
1893
1894 if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
1895 {
1896 sr_localsid_trace_t *tr =
1897 vlib_add_trace (vm, node, b1, sizeof (*tr));
1898 tr->num_segments = 0;
1899 clib_memcpy (tr->localsid.as_u8, ls1->localsid.as_u8,
1900 sizeof (tr->localsid.as_u8));
1901 tr->behavior = ls1->behavior;
1902 if (ip1 == vlib_buffer_get_current (b1))
1903 {
1904 if (ip1->protocol == IP_PROTOCOL_IPV6_ROUTE
1905 && sr1->type == ROUTING_HEADER_TYPE_SR)
1906 {
1907 clib_memcpy (tr->sr, sr1->segments, sr1->length * 8);
1908 tr->num_segments =
1909 sr1->length * 8 / sizeof (ip6_address_t);
1910 tr->segments_left = sr1->segments_left;
1911 }
1912 }
1913 else
1914 tr->num_segments = 0xFF;
1915 }
1916
1917 if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
1918 {
1919 sr_localsid_trace_t *tr =
1920 vlib_add_trace (vm, node, b2, sizeof (*tr));
1921 tr->num_segments = 0;
1922 clib_memcpy (tr->localsid.as_u8, ls2->localsid.as_u8,
1923 sizeof (tr->localsid.as_u8));
1924 tr->behavior = ls2->behavior;
1925 if (ip2 == vlib_buffer_get_current (b2))
1926 {
1927 if (ip2->protocol == IP_PROTOCOL_IPV6_ROUTE
1928 && sr2->type == ROUTING_HEADER_TYPE_SR)
1929 {
1930 clib_memcpy (tr->sr, sr2->segments, sr2->length * 8);
1931 tr->num_segments =
1932 sr2->length * 8 / sizeof (ip6_address_t);
1933 tr->segments_left = sr2->segments_left;
1934 }
1935 }
1936 else
1937 tr->num_segments = 0xFF;
1938 }
1939
1940 if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
1941 {
1942 sr_localsid_trace_t *tr =
1943 vlib_add_trace (vm, node, b3, sizeof (*tr));
1944 tr->num_segments = 0;
1945 clib_memcpy (tr->localsid.as_u8, ls3->localsid.as_u8,
1946 sizeof (tr->localsid.as_u8));
1947 tr->behavior = ls3->behavior;
1948 if (ip3 == vlib_buffer_get_current (b3))
1949 {
1950 if (ip3->protocol == IP_PROTOCOL_IPV6_ROUTE
1951 && sr3->type == ROUTING_HEADER_TYPE_SR)
1952 {
1953 clib_memcpy (tr->sr, sr3->segments, sr3->length * 8);
1954 tr->num_segments =
1955 sr3->length * 8 / sizeof (ip6_address_t);
1956 tr->segments_left = sr3->segments_left;
1957 }
1958 }
1959 else
1960 tr->num_segments = 0xFF;
1961 }
1962
1963 vlib_increment_combined_counter
1964 (((next0 ==
1965 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
1966 &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids,
1967 1, vlib_buffer_length_in_chain (vm, b0));
1968
1969 vlib_increment_combined_counter
1970 (((next1 ==
1971 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
1972 &(sm->sr_ls_valid_counters)), thread_index, ls1 - sm->localsids,
1973 1, vlib_buffer_length_in_chain (vm, b1));
1974
1975 vlib_increment_combined_counter
1976 (((next2 ==
1977 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
1978 &(sm->sr_ls_valid_counters)), thread_index, ls2 - sm->localsids,
1979 1, vlib_buffer_length_in_chain (vm, b2));
1980
1981 vlib_increment_combined_counter
1982 (((next3 ==
1983 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
1984 &(sm->sr_ls_valid_counters)), thread_index, ls3 - sm->localsids,
1985 1, vlib_buffer_length_in_chain (vm, b3));
1986
1987 vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
1988 n_left_to_next, bi0, bi1, bi2, bi3,
1989 next0, next1, next2, next3);
1990 }
1991
1992 /* Single loop for potentially the last three packets */
1993 while (n_left_from > 0 && n_left_to_next > 0)
1994 {
1995 u32 bi0;
1996 vlib_buffer_t *b0;
1997 ip6_header_t *ip0 = 0;
1998 ip6_ext_header_t *prev0;
1999 ip6_sr_header_t *sr0;
2000 u32 next0 = SR_LOCALSID_NEXT_IP6_LOOKUP;
2001 ip6_sr_localsid_t *ls0;
2002
2003 bi0 = from[0];
2004 to_next[0] = bi0;
2005 from += 1;
2006 to_next += 1;
2007 n_left_from -= 1;
2008 n_left_to_next -= 1;
2009
2010 b0 = vlib_get_buffer (vm, bi0);
2011 ip0 = vlib_buffer_get_current (b0);
2012 sr0 =
2013 ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, &prev0);
2014
2015 /* Lookup the SR End behavior based on IP DA (adj) */
2016 ls0 =
2017 pool_elt_at_index (sm->localsids,
2018 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2019
2020 /* SRH processing */
2021 end_un_srh_processing (node, b0, ip0, sr0, ls0, &next0,
2022 ls0->end_psp, prev0);
2023
2024 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2025 {
2026 sr_localsid_trace_t *tr =
2027 vlib_add_trace (vm, node, b0, sizeof (*tr));
2028 tr->num_segments = 0;
2029 clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8,
2030 sizeof (tr->localsid.as_u8));
2031 tr->behavior = ls0->behavior;
2032 if (ip0 == vlib_buffer_get_current (b0))
2033 {
2034 if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE
2035 && sr0->type == ROUTING_HEADER_TYPE_SR)
2036 {
2037 clib_memcpy (tr->sr, sr0->segments, sr0->length * 8);
2038 tr->num_segments =
2039 sr0->length * 8 / sizeof (ip6_address_t);
2040 tr->segments_left = sr0->segments_left;
2041 }
2042 }
2043 else
2044 tr->num_segments = 0xFF;
2045 }
2046
2047 vlib_increment_combined_counter
2048 (((next0 ==
2049 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
2050 &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids,
2051 1, vlib_buffer_length_in_chain (vm, b0));
2052
2053 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2054 n_left_to_next, bi0, next0);
2055 }
2056 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2057 }
2058 return from_frame->n_vectors;
2059}
2060
2061/* *INDENT-OFF* */
2062VLIB_REGISTER_NODE (sr_localsid_un_node) = {
2063 .function = sr_localsid_un_fn,
2064 .name = "sr-localsid-un",
2065 .vector_size = sizeof (u32),
2066 .format_trace = format_sr_localsid_trace,
2067 .type = VLIB_NODE_TYPE_INTERNAL,
2068 .n_errors = SR_LOCALSID_N_ERROR,
2069 .error_strings = sr_localsid_error_strings,
2070 .n_next_nodes = SR_LOCALSID_N_NEXT,
2071 .next_nodes = {
2072#define _(s,n) [SR_LOCALSID_NEXT_##s] = n,
2073 foreach_sr_localsid_next
2074#undef _
2075 },
2076};
2077/* *INDENT-ON* */
2078
2079static uword
2080sr_localsid_un_perf_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
2081 vlib_frame_t * from_frame)
2082{
2083 u32 n_left_from, next_index, *from, *to_next;
2084 ip6_sr_main_t *sm = &sr_main;
2085 from = vlib_frame_vector_args (from_frame);
2086 n_left_from = from_frame->n_vectors;
2087 next_index = node->cached_next_index;
2088 u32 thread_index = vm->thread_index;
2089
2090 while (n_left_from > 0)
2091 {
2092 u32 n_left_to_next;
2093 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2094
2095 /* Quad - Loop */
2096 while (n_left_from >= 8 && n_left_to_next >= 4)
2097 {
2098 u32 bi0, bi1, bi2, bi3;
2099 vlib_buffer_t *b0, *b1, *b2, *b3;
2100 ip6_header_t *ip0, *ip1, *ip2, *ip3;
2101 u32 next0, next1, next2, next3;
2102 next0 = next1 = next2 = next3 = SR_LOCALSID_NEXT_IP6_LOOKUP;
2103 ip6_sr_localsid_t *ls0, *ls1, *ls2, *ls3;
2104
2105 /* Prefetch next iteration. */
2106 {
2107 vlib_buffer_t *p4, *p5, *p6, *p7;
2108
2109 p4 = vlib_get_buffer (vm, from[4]);
2110 p5 = vlib_get_buffer (vm, from[5]);
2111 p6 = vlib_get_buffer (vm, from[6]);
2112 p7 = vlib_get_buffer (vm, from[7]);
2113
2114 /* Prefetch the buffer header and packet for the N+2 loop iteration */
2115 vlib_prefetch_buffer_header (p4, LOAD);
2116 vlib_prefetch_buffer_header (p5, LOAD);
2117 vlib_prefetch_buffer_header (p6, LOAD);
2118 vlib_prefetch_buffer_header (p7, LOAD);
2119
2120 CLIB_PREFETCH (p4->data, CLIB_CACHE_LINE_BYTES, STORE);
2121 CLIB_PREFETCH (p5->data, CLIB_CACHE_LINE_BYTES, STORE);
2122 CLIB_PREFETCH (p6->data, CLIB_CACHE_LINE_BYTES, STORE);
2123 CLIB_PREFETCH (p7->data, CLIB_CACHE_LINE_BYTES, STORE);
2124 }
2125
2126 to_next[0] = bi0 = from[0];
2127 to_next[1] = bi1 = from[1];
2128 to_next[2] = bi2 = from[2];
2129 to_next[3] = bi3 = from[3];
2130 from += 4;
2131 to_next += 4;
2132 n_left_from -= 4;
2133 n_left_to_next -= 4;
2134
2135 b0 = vlib_get_buffer (vm, bi0);
2136 b1 = vlib_get_buffer (vm, bi1);
2137 b2 = vlib_get_buffer (vm, bi2);
2138 b3 = vlib_get_buffer (vm, bi3);
2139
2140 ip0 = vlib_buffer_get_current (b0);
2141 ip1 = vlib_buffer_get_current (b1);
2142 ip2 = vlib_buffer_get_current (b2);
2143 ip3 = vlib_buffer_get_current (b3);
2144
2145 ls0 =
2146 pool_elt_at_index (sm->localsids,
2147 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2148 ls1 =
2149 pool_elt_at_index (sm->localsids,
2150 vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
2151 ls2 =
2152 pool_elt_at_index (sm->localsids,
2153 vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
2154 ls3 =
2155 pool_elt_at_index (sm->localsids,
2156 vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
2157
2158 end_un_processing (ip0, ls0);
2159 end_un_processing (ip1, ls1);
2160 end_un_processing (ip2, ls2);
2161 end_un_processing (ip3, ls3);
2162
2163 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2164 {
2165 sr_localsid_trace_t *tr =
2166 vlib_add_trace (vm, node, b0, sizeof (*tr));
2167 tr->num_segments = 0;
2168 clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8,
2169 sizeof (tr->localsid.as_u8));
2170 tr->behavior = ls0->behavior;
2171 }
2172
2173 if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
2174 {
2175 sr_localsid_trace_t *tr =
2176 vlib_add_trace (vm, node, b1, sizeof (*tr));
2177 tr->num_segments = 0;
2178 clib_memcpy (tr->localsid.as_u8, ls1->localsid.as_u8,
2179 sizeof (tr->localsid.as_u8));
2180 tr->behavior = ls1->behavior;
2181 }
2182
2183 if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
2184 {
2185 sr_localsid_trace_t *tr =
2186 vlib_add_trace (vm, node, b2, sizeof (*tr));
2187 tr->num_segments = 0;
2188 clib_memcpy (tr->localsid.as_u8, ls2->localsid.as_u8,
2189 sizeof (tr->localsid.as_u8));
2190 tr->behavior = ls2->behavior;
2191 }
2192
2193 if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
2194 {
2195 sr_localsid_trace_t *tr =
2196 vlib_add_trace (vm, node, b3, sizeof (*tr));
2197 tr->num_segments = 0;
2198 clib_memcpy (tr->localsid.as_u8, ls3->localsid.as_u8,
2199 sizeof (tr->localsid.as_u8));
2200 tr->behavior = ls3->behavior;
2201 }
2202
2203 vlib_increment_combined_counter
2204 (((next0 ==
2205 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
2206 &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids,
2207 1, vlib_buffer_length_in_chain (vm, b0));
2208
2209 vlib_increment_combined_counter
2210 (((next1 ==
2211 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
2212 &(sm->sr_ls_valid_counters)), thread_index, ls1 - sm->localsids,
2213 1, vlib_buffer_length_in_chain (vm, b1));
2214
2215 vlib_increment_combined_counter
2216 (((next2 ==
2217 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
2218 &(sm->sr_ls_valid_counters)), thread_index, ls2 - sm->localsids,
2219 1, vlib_buffer_length_in_chain (vm, b2));
2220
2221 vlib_increment_combined_counter
2222 (((next3 ==
2223 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
2224 &(sm->sr_ls_valid_counters)), thread_index, ls3 - sm->localsids,
2225 1, vlib_buffer_length_in_chain (vm, b3));
2226
2227 vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
2228 n_left_to_next, bi0, bi1, bi2, bi3,
2229 next0, next1, next2, next3);
2230 }
2231
2232 /* Single loop for potentially the last three packets */
2233 while (n_left_from > 0 && n_left_to_next > 0)
2234 {
2235 u32 bi0;
2236 vlib_buffer_t *b0;
2237 ip6_header_t *ip0 = 0;
2238 u32 next0 = SR_LOCALSID_NEXT_IP6_LOOKUP;
2239 ip6_sr_localsid_t *ls0;
2240
2241 bi0 = from[0];
2242 to_next[0] = bi0;
2243 from += 1;
2244 to_next += 1;
2245 n_left_from -= 1;
2246 n_left_to_next -= 1;
2247
2248 b0 = vlib_get_buffer (vm, bi0);
2249 ip0 = vlib_buffer_get_current (b0);
2250
2251 /* Lookup the SR End behavior based on IP DA (adj) */
2252 ls0 =
2253 pool_elt_at_index (sm->localsids,
2254 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2255
2256 /* SRH processing */
2257 end_un_processing (ip0, ls0);
2258
2259 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2260 {
2261 sr_localsid_trace_t *tr =
2262 vlib_add_trace (vm, node, b0, sizeof (*tr));
2263 tr->num_segments = 0;
2264 clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8,
2265 sizeof (tr->localsid.as_u8));
2266 tr->behavior = ls0->behavior;
2267 }
2268
2269 vlib_increment_combined_counter
2270 (((next0 ==
2271 SR_LOCALSID_NEXT_ERROR) ? &(sm->sr_ls_invalid_counters) :
2272 &(sm->sr_ls_valid_counters)), thread_index, ls0 - sm->localsids,
2273 1, vlib_buffer_length_in_chain (vm, b0));
2274
2275 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2276 n_left_to_next, bi0, next0);
2277 }
2278 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2279 }
2280 return from_frame->n_vectors;
2281}
2282
2283/* *INDENT-OFF* */
2284VLIB_REGISTER_NODE (sr_localsid_un_perf_node) = {
2285 .function = sr_localsid_un_perf_fn,
2286 .name = "sr-localsid-un-perf",
2287 .vector_size = sizeof (u32),
2288 .format_trace = format_sr_localsid_trace,
2289 .type = VLIB_NODE_TYPE_INTERNAL,
2290 .n_errors = SR_LOCALSID_N_ERROR,
2291 .error_strings = sr_localsid_error_strings,
2292 .n_next_nodes = SR_LOCALSID_N_NEXT,
2293 .next_nodes = {
2294#define _(s,n) [SR_LOCALSID_NEXT_##s] = n,
2295 foreach_sr_localsid_next
2296#undef _
2297 },
2298};
2299/* *INDENT-ON* */
2300
Pablo Camarillofb380952016-12-07 18:34:18 +01002301static u8 *
2302format_sr_dpo (u8 * s, va_list * args)
2303{
2304 index_t index = va_arg (*args, index_t);
2305 CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
2306
2307 return (format (s, "SR: localsid_index:[%d]", index));
2308}
2309
2310const static dpo_vft_t sr_loc_vft = {
2311 .dv_lock = sr_dpo_lock,
2312 .dv_unlock = sr_dpo_unlock,
2313 .dv_format = format_sr_dpo,
2314};
2315
2316const static char *const sr_loc_ip6_nodes[] = {
2317 "sr-localsid",
2318 NULL,
2319};
2320
2321const static char *const *const sr_loc_nodes[DPO_PROTO_NUM] = {
2322 [DPO_PROTO_IP6] = sr_loc_ip6_nodes,
2323};
2324
2325const static char *const sr_loc_d_ip6_nodes[] = {
2326 "sr-localsid-d",
2327 NULL,
2328};
2329
2330const static char *const *const sr_loc_d_nodes[DPO_PROTO_NUM] = {
2331 [DPO_PROTO_IP6] = sr_loc_d_ip6_nodes,
2332};
2333
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -07002334const static char *const sr_loc_un_ip6_nodes[] = {
2335 "sr-localsid-un",
2336 NULL,
2337};
2338
2339const static char *const *const sr_loc_un_nodes[DPO_PROTO_NUM] = {
2340 [DPO_PROTO_IP6] = sr_loc_un_ip6_nodes,
2341};
2342
2343const static char *const sr_loc_un_perf_ip6_nodes[] = {
2344 "sr-localsid-un-perf",
2345 NULL,
2346};
2347
2348const static char *const *const sr_loc_un_perf_nodes[DPO_PROTO_NUM] = {
2349 [DPO_PROTO_IP6] = sr_loc_un_perf_ip6_nodes,
2350};
Pablo Camarillofb380952016-12-07 18:34:18 +01002351
2352/*************************** SR LocalSID plugins ******************************/
2353/**
2354 * @brief SR LocalSID plugin registry
2355 */
2356int
2357sr_localsid_register_function (vlib_main_t * vm, u8 * fn_name,
2358 u8 * keyword_str, u8 * def_str,
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -08002359 u8 * params_str, u8 prefix_length,
2360 dpo_type_t * dpo,
Pablo Camarillofb380952016-12-07 18:34:18 +01002361 format_function_t * ls_format,
2362 unformat_function_t * ls_unformat,
2363 sr_plugin_callback_t * creation_fn,
2364 sr_plugin_callback_t * removal_fn)
2365{
2366 ip6_sr_main_t *sm = &sr_main;
2367 uword *p;
2368
2369 sr_localsid_fn_registration_t *plugin;
2370
2371 /* Did this function exist? If so update it */
2372 p = hash_get_mem (sm->plugin_functions_by_key, fn_name);
2373 if (p)
2374 {
2375 plugin = pool_elt_at_index (sm->plugin_functions, p[0]);
2376 }
2377 /* Else create a new one and set hash key */
2378 else
2379 {
2380 pool_get (sm->plugin_functions, plugin);
2381 hash_set_mem (sm->plugin_functions_by_key, fn_name,
2382 plugin - sm->plugin_functions);
2383 }
2384
Dave Barachb7b92992018-10-17 10:38:51 -04002385 clib_memset (plugin, 0, sizeof (*plugin));
Pablo Camarillofb380952016-12-07 18:34:18 +01002386
2387 plugin->sr_localsid_function_number = (plugin - sm->plugin_functions);
2388 plugin->sr_localsid_function_number += SR_BEHAVIOR_LAST;
Tetsuya Murakami1b81e6e2019-11-06 11:05:51 -08002389 plugin->prefix_length = prefix_length;
Pablo Camarillofb380952016-12-07 18:34:18 +01002390 plugin->ls_format = ls_format;
2391 plugin->ls_unformat = ls_unformat;
2392 plugin->creation = creation_fn;
2393 plugin->removal = removal_fn;
2394 clib_memcpy (&plugin->dpo, dpo, sizeof (dpo_type_t));
2395 plugin->function_name = format (0, "%s%c", fn_name, 0);
2396 plugin->keyword_str = format (0, "%s%c", keyword_str, 0);
2397 plugin->def_str = format (0, "%s%c", def_str, 0);
2398 plugin->params_str = format (0, "%s%c", params_str, 0);
2399
2400 return plugin->sr_localsid_function_number;
2401}
2402
2403/**
2404 * @brief CLI function to 'show' all available SR LocalSID behaviors
2405 */
2406static clib_error_t *
2407show_sr_localsid_behaviors_command_fn (vlib_main_t * vm,
2408 unformat_input_t * input,
2409 vlib_cli_command_t * cmd)
2410{
2411 ip6_sr_main_t *sm = &sr_main;
2412 sr_localsid_fn_registration_t *plugin;
2413 sr_localsid_fn_registration_t **plugins_vec = 0;
2414 int i;
2415
2416 vlib_cli_output (vm,
2417 "SR LocalSIDs behaviors:\n-----------------------\n\n");
2418
2419 /* *INDENT-OFF* */
2420 pool_foreach (plugin, sm->plugin_functions,
2421 ({ vec_add1 (plugins_vec, plugin); }));
2422 /* *INDENT-ON* */
2423
2424 /* Print static behaviors */
2425 vlib_cli_output (vm, "Default behaviors:\n"
2426 "\tEnd\t-> Endpoint.\n"
Pablo Camarillo7a4e0922017-06-06 15:18:12 +02002427 "\tEnd.X\t-> Endpoint with Layer-3 cross-connect.\n"
Pablo Camarillofb380952016-12-07 18:34:18 +01002428 "\t\tParameters: '<iface> <ip6_next_hop>'\n"
Pablo Camarillo7a4e0922017-06-06 15:18:12 +02002429 "\tEnd.T\t-> Endpoint with specific IPv6 table lookup.\n"
2430 "\t\tParameters: '<fib_table>'\n"
Pablo Camarillofb380952016-12-07 18:34:18 +01002431 "\tEnd.DX2\t-> Endpoint with decapsulation and Layer-2 cross-connect.\n"
2432 "\t\tParameters: '<iface>'\n"
2433 "\tEnd.DX6\t-> Endpoint with decapsulation and IPv6 cross-connect.\n"
2434 "\t\tParameters: '<iface> <ip6_next_hop>'\n"
2435 "\tEnd.DX4\t-> Endpoint with decapsulation and IPv4 cross-connect.\n"
2436 "\t\tParameters: '<iface> <ip4_next_hop>'\n"
2437 "\tEnd.DT6\t-> Endpoint with decapsulation and specific IPv6 table lookup.\n"
2438 "\t\tParameters: '<ip6_fib_table>'\n"
2439 "\tEnd.DT4\t-> Endpoint with decapsulation and specific IPv4 table lookup.\n"
2440 "\t\tParameters: '<ip4_fib_table>'\n");
2441 vlib_cli_output (vm, "Plugin behaviors:\n");
2442 for (i = 0; i < vec_len (plugins_vec); i++)
2443 {
2444 plugin = plugins_vec[i];
2445 vlib_cli_output (vm, "\t%s\t-> %s.\n", plugin->keyword_str,
2446 plugin->def_str);
2447 vlib_cli_output (vm, "\t\tParameters: '%s'\n", plugin->params_str);
2448 }
2449 return 0;
2450}
2451
2452/* *INDENT-OFF* */
2453VLIB_CLI_COMMAND (show_sr_localsid_behaviors_command, static) = {
2454 .path = "show sr localsids behaviors",
2455 .short_help = "show sr localsids behaviors",
2456 .function = show_sr_localsid_behaviors_command_fn,
2457};
2458/* *INDENT-ON* */
2459
2460/**
2461 * @brief SR LocalSID initialization
2462 */
2463clib_error_t *
2464sr_localsids_init (vlib_main_t * vm)
2465{
2466 /* Init memory for function keys */
2467 ip6_sr_main_t *sm = &sr_main;
Pablo Camarillo4521afa2017-03-16 10:43:05 +01002468 mhash_init (&sm->sr_localsids_index_hash, sizeof (uword),
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -07002469 sizeof (sr_localsid_key_t));
Pablo Camarillofb380952016-12-07 18:34:18 +01002470 /* Init SR behaviors DPO type */
2471 sr_localsid_dpo_type = dpo_register_new_type (&sr_loc_vft, sr_loc_nodes);
2472 /* Init SR behaviors DPO type */
2473 sr_localsid_d_dpo_type =
2474 dpo_register_new_type (&sr_loc_vft, sr_loc_d_nodes);
Tetsuya Murakamiec9cb962020-03-23 16:10:28 -07002475 /* Init SR bhaviors DPO type */
2476 sr_localsid_un_dpo_type =
2477 dpo_register_new_type (&sr_loc_vft, sr_loc_un_nodes);
2478 sr_localsid_un_perf_dpo_type =
2479 dpo_register_new_type (&sr_loc_vft, sr_loc_un_perf_nodes);
Pablo Camarillofb380952016-12-07 18:34:18 +01002480 /* Init memory for localsid plugins */
2481 sm->plugin_functions_by_key = hash_create_string (0, sizeof (uword));
2482 return 0;
2483}
2484
2485VLIB_INIT_FUNCTION (sr_localsids_init);
2486/*
2487* fd.io coding-style-patch-verification: ON
2488*
2489* Local Variables:
2490* eval: (c-set-style "gnu")
2491* End:
2492*/