2 * sr_steering.c: ipv6 segment routing steering into SR policy
4 * Copyright (c) 2016 Cisco and/or its affiliates. Licensed under the Apache
5 * License, Version 2.0 (the "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
19 * @brief Packet steering into SR-MPLS Policies
21 * This file is in charge of handling the FIB appropiatly to steer packets
22 * through SR Policies as defined in 'sr_mpls_policy.c'. Notice that here
23 * we are only doing steering. SR policy application is done in
27 * - Steering of IPv6 traffic Destination Address based through BSID
28 * - Steering of IPv4 traffic Destination Address based through BSID
29 * - Steering of IPv4 and IPv6 traffic through N,C (SR CP)
32 #include <vlib/vlib.h>
33 #include <vnet/vnet.h>
34 #include <vnet/srmpls/sr_mpls.h>
35 #include <vnet/ip/ip4_packet.h>
36 #include <vnet/ip/ip6_packet.h>
37 #include <vnet/fib/mpls_fib.h>
39 #include <vppinfra/error.h>
40 #include <vppinfra/elog.h>
42 #define SRMPLS_TE_OFFSET 50
45 * @brief function to sort the colors in descending order
48 sort_color_descent (const u32 * x, u32 * y)
53 /********************* Internal (NH, C) labels *******************************/
55 * @brief find the corresponding label for (endpoint, color) and lock it
56 * endpoint might be NULL or ANY
60 find_or_create_internal_label (ip46_address_t endpoint, u32 color)
62 mpls_sr_main_t *sm = &sr_mpls_main;
63 uword *color_table, *result_label;
65 if (!sm->sr_policies_c2e2eclabel_hash.hash)
66 mhash_init (&sm->sr_policies_c2e2eclabel_hash, sizeof (mhash_t),
69 color_table = mhash_get (&sm->sr_policies_c2e2eclabel_hash, &color);
73 memset (&color_t, 0, sizeof (mhash_t));
74 mhash_init (&color_t, sizeof (u32), sizeof (ip46_address_t));
75 mhash_set_mem (&sm->sr_policies_c2e2eclabel_hash, &color,
76 (uword *) & color_t, NULL);
77 color_table = mhash_get (&sm->sr_policies_c2e2eclabel_hash, &color);
80 result_label = mhash_get ((mhash_t *) color_table, &endpoint);
83 return (u32) * result_label;
85 /* Create and set a new internal label */
86 u32 *new_internal_label = 0;
87 pool_get (sm->ec_labels, new_internal_label);
88 *new_internal_label = 0;
89 mhash_set ((mhash_t *) color_table, &endpoint,
90 (new_internal_label - sm->ec_labels) + SRMPLS_TE_OFFSET, NULL);
92 return (new_internal_label - sm->ec_labels) + SRMPLS_TE_OFFSET;
96 internal_label_lock_co (ip46_address_t endpoint, u32 color, char co_bits)
98 ip46_address_t zero, any;
99 ip46_address_reset (&zero);
100 any.as_u64[0] = any.as_u64[1] = (u64) ~ 0;
103 case SR_TE_CO_BITS_10:
104 internal_label_lock (endpoint, color);
105 internal_label_lock (zero, color);
106 internal_label_lock (any, color);
108 case SR_TE_CO_BITS_01:
109 internal_label_lock (endpoint, color);
110 internal_label_lock (zero, color);
112 case SR_TE_CO_BITS_00:
113 case SR_TE_CO_BITS_11:
114 internal_label_lock (endpoint, color);
120 * @brief lock the label for (NH, C)
121 * endpoint might be NULL or ANY
125 internal_label_lock (ip46_address_t endpoint, u32 color)
127 mpls_sr_main_t *sm = &sr_mpls_main;
128 uword *color_table, *result_label;
130 if (!sm->sr_policies_c2e2eclabel_hash.hash)
133 color_table = mhash_get (&sm->sr_policies_c2e2eclabel_hash, &color);
137 result_label = mhash_get ((mhash_t *) color_table, &endpoint);
144 pool_elt_at_index (sm->ec_labels, *result_label - SRMPLS_TE_OFFSET);
150 internal_label_unlock_co (ip46_address_t endpoint, u32 color, char co_bits)
152 ip46_address_t zero, any;
153 ip46_address_reset (&zero);
154 any.as_u64[0] = any.as_u64[1] = (u64) ~ 0;
157 case SR_TE_CO_BITS_10:
158 internal_label_unlock (endpoint, color);
159 internal_label_unlock (zero, color);
160 internal_label_unlock (any, color);
162 case SR_TE_CO_BITS_01:
163 internal_label_unlock (endpoint, color);
164 internal_label_unlock (zero, color);
166 case SR_TE_CO_BITS_00:
167 case SR_TE_CO_BITS_11:
168 internal_label_unlock (endpoint, color);
174 * @brief Release lock on label for (endpoint, color)
175 * endpoint might be NULL or ANY
179 internal_label_unlock (ip46_address_t endpoint, u32 color)
181 mpls_sr_main_t *sm = &sr_mpls_main;
182 uword *color_table, *result_label;
184 if (!sm->sr_policies_c2e2eclabel_hash.hash)
187 color_table = mhash_get (&sm->sr_policies_c2e2eclabel_hash, &color);
191 result_label = mhash_get ((mhash_t *) color_table, &endpoint);
197 pool_elt_at_index (sm->ec_labels, *result_label - SRMPLS_TE_OFFSET);
200 if (*label_lock == 0)
202 pool_put (sm->ec_labels, label_lock);
203 mhash_unset ((mhash_t *) color_table, &endpoint, NULL);
204 if (mhash_elts ((mhash_t *) color_table) == 0)
206 mhash_free ((mhash_t *) color_table);
207 mhash_unset (&sm->sr_policies_c2e2eclabel_hash, &color, NULL);
208 if (mhash_elts (&sm->sr_policies_c2e2eclabel_hash) == 0)
210 mhash_free (&sm->sr_policies_c2e2eclabel_hash);
211 sm->sr_policies_c2e2eclabel_hash.hash = NULL;
212 fib_table_unlock (sm->fib_table_EC, FIB_PROTOCOL_MPLS,
214 sm->fib_table_EC = (u32) ~ 0;
220 /********************* steering computation *********************************/
222 * @brief function to update the FIB
225 compute_sr_te_automated_steering_fib_entry (mpls_sr_steering_policy_t *
228 mpls_sr_main_t *sm = &sr_mpls_main;
229 fib_prefix_t pfx = { 0 };
231 u32 *internal_labels = 0;
232 ip46_address_t zero, any;
233 ip46_address_reset (&zero);
234 any.as_u64[0] = any.as_u64[1] = (u64) ~ 0;
237 vec_foreach (color_i, steer_pl->color)
239 switch (steer_pl->co_bits)
241 case SR_TE_CO_BITS_10:
242 vec_add1 (internal_labels,
243 find_or_create_internal_label (steer_pl->next_hop,
245 vec_add1 (internal_labels,
246 find_or_create_internal_label (zero, *color_i));
247 vec_add1 (internal_labels,
248 find_or_create_internal_label (any, *color_i));
250 case SR_TE_CO_BITS_01:
251 vec_add1 (internal_labels,
252 find_or_create_internal_label (steer_pl->next_hop,
254 vec_add1 (internal_labels,
255 find_or_create_internal_label (zero, *color_i));
257 case SR_TE_CO_BITS_00:
258 case SR_TE_CO_BITS_11:
259 vec_add1 (internal_labels,
260 find_or_create_internal_label (steer_pl->next_hop,
266 /* Does hidden FIB already exist? */
267 if (sm->fib_table_EC == (u32) ~ 0)
269 sm->fib_table_EC = fib_table_create_and_lock (FIB_PROTOCOL_MPLS,
271 "SR-MPLS Traffic Engineering (NextHop,Color)");
273 fib_table_flush (sm->fib_table_EC, FIB_PROTOCOL_MPLS,
277 /* Add the corresponding FIB entries */
278 fib_route_path_t path = {
279 .frp_proto = DPO_PROTO_MPLS,
281 .frp_sw_if_index = ~0,
282 .frp_fib_index = sm->fib_table_EC,
284 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
287 fib_route_path_t *paths = NULL;
289 if (steer_pl->classify.traffic_type == SR_STEER_IPV6)
291 pfx.fp_proto = FIB_PROTOCOL_IP6;
292 pfx.fp_len = steer_pl->classify.mask_width;
293 pfx.fp_addr.ip6 = steer_pl->classify.prefix.ip6;
295 else if (steer_pl->classify.traffic_type == SR_STEER_IPV4)
297 pfx.fp_proto = FIB_PROTOCOL_IP4;
298 pfx.fp_len = steer_pl->classify.mask_width;
299 pfx.fp_addr.ip4 = steer_pl->classify.prefix.ip4;
302 if (steer_pl->vpn_label != (u32) ~ 0)
304 fib_mpls_label_t fml = {
305 .fml_value = steer_pl->vpn_label,
307 vec_add1 (path.frp_label_stack, fml);
308 path.frp_eos = MPLS_NON_EOS;
312 vec_foreach_index (label_i, internal_labels)
314 path.frp_local_label = internal_labels[label_i];
315 path.frp_preference = label_i;
316 vec_add1 (paths, path);
319 /* Finally we must add to FIB IGP to N */
320 clib_memcpy (&path.frp_addr, &steer_pl->next_hop,
321 sizeof (steer_pl->next_hop));
322 path.frp_preference = vec_len (internal_labels);
323 path.frp_label_stack = NULL;
325 if (steer_pl->nh_type == SR_STEER_IPV6)
327 path.frp_proto = DPO_PROTO_IP6;
329 fib_table_find (FIB_PROTOCOL_IP6,
330 (steer_pl->classify.fib_table !=
331 (u32) ~ 0 ? steer_pl->classify.fib_table : 0));
333 else if (steer_pl->nh_type == SR_STEER_IPV4)
335 path.frp_proto = DPO_PROTO_IP4;
337 fib_table_find (FIB_PROTOCOL_IP4,
338 (steer_pl->classify.fib_table !=
339 (u32) ~ 0 ? steer_pl->classify.fib_table : 0));
342 vec_add1 (paths, path);
343 if (steer_pl->classify.traffic_type == SR_STEER_IPV6)
344 fib_table_entry_update (fib_table_find
346 (steer_pl->classify.fib_table !=
347 (u32) ~ 0 ? steer_pl->classify.fib_table : 0)),
349 FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT, paths);
350 else if (steer_pl->classify.traffic_type == SR_STEER_IPV4)
351 fib_table_entry_update (fib_table_find
353 (steer_pl->classify.fib_table !=
354 (u32) ~ 0 ? steer_pl->classify.fib_table : 0)),
356 FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT, paths);
363 * @brief Steer traffic L3 traffic through a given SR-MPLS policy
366 * @param bsid is the bindingSID of the SR Policy (alt to sr_policy_index)
367 * @param sr_policy is the index of the SR Policy (alt to bsid)
368 * @param table_id is the VRF where to install the FIB entry for the BSID
369 * @param prefix is the IPv4/v6 address for L3 traffic type
370 * @param mask_width is the mask for L3 traffic type
371 * @param traffic_type describes the type of traffic
372 * @param next_hop SR TE Next-Hop
373 * @param nh_type is the AF of Next-Hop
374 * @param color SR TE color
375 * @param co_bits SR TE color-only bits
377 * @return 0 if correct, else error
380 sr_mpls_steering_policy_add (mpls_label_t bsid, u32 table_id,
381 ip46_address_t * prefix, u32 mask_width,
382 u8 traffic_type, ip46_address_t * next_hop,
383 u8 nh_type, u32 color, char co_bits,
384 mpls_label_t vpn_label)
386 mpls_sr_main_t *sm = &sr_mpls_main;
387 sr_mpls_steering_key_t key;
388 mpls_sr_steering_policy_t *steer_pl;
389 fib_prefix_t pfx = { 0 };
391 mpls_sr_policy_t *sr_policy = 0;
394 memset (&key, 0, sizeof (sr_mpls_steering_key_t));
396 /* Compute the steer policy key */
397 if (traffic_type == SR_STEER_IPV4 || traffic_type == SR_STEER_IPV6)
399 key.prefix.as_u64[0] = prefix->as_u64[0];
400 key.prefix.as_u64[1] = prefix->as_u64[1];
401 key.mask_width = mask_width;
402 key.fib_table = (table_id != (u32) ~ 0 ? table_id : 0);
407 key.traffic_type = traffic_type;
409 if (traffic_type != SR_STEER_IPV4 && traffic_type != SR_STEER_IPV6)
413 * Search for steering policy. If already exists we are adding a new
416 if (!sm->sr_steer_policies_hash.hash)
417 mhash_init (&sm->sr_steer_policies_hash, sizeof (uword),
418 sizeof (sr_mpls_steering_key_t));
420 p = mhash_get (&sm->sr_steer_policies_hash, &key);
423 steer_pl = pool_elt_at_index (sm->steer_policies, p[0]);
424 if (steer_pl->bsid != (u32) ~ 0)
425 return -1; //Means we are rewritting the steering. Not allowed.
427 /* Means we are adding a color. Check that NH match. */
428 if (ip46_address_cmp (&steer_pl->next_hop, next_hop))
430 if (vec_search (steer_pl->color, color) != ~0)
432 if (steer_pl->co_bits != co_bits)
433 return -4; /* CO colors should be the same */
434 if (steer_pl->vpn_label != vpn_label)
435 return -5; /* VPN label should be the same */
437 /* Remove the steering and ReDo it */
438 vec_add1 (steer_pl->color, color);
439 vec_sort_with_function (steer_pl->color, sort_color_descent);
440 compute_sr_te_automated_steering_fib_entry (steer_pl);
441 internal_label_lock_co (steer_pl->next_hop, color, steer_pl->co_bits);
445 /* Create a new steering policy */
446 pool_get (sm->steer_policies, steer_pl);
447 memset (steer_pl, 0, sizeof (*steer_pl));
448 clib_memcpy (&steer_pl->classify.prefix, prefix, sizeof (ip46_address_t));
449 clib_memcpy (&steer_pl->next_hop, next_hop, sizeof (ip46_address_t));
450 steer_pl->nh_type = nh_type;
451 steer_pl->co_bits = co_bits;
452 steer_pl->classify.mask_width = mask_width;
453 steer_pl->classify.fib_table = (table_id != (u32) ~ 0 ? table_id : 0);
454 steer_pl->classify.traffic_type = traffic_type;
455 steer_pl->color = NULL;
456 steer_pl->vpn_label = vpn_label;
458 /* Create and store key */
459 mhash_set (&sm->sr_steer_policies_hash, &key, steer_pl - sm->steer_policies,
463 if (bsid != (u32) ~ 0)
465 if (!sm->sr_policies_index_hash)
466 sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
467 steer_pl->bsid = bsid;
468 p = hash_get (sm->sr_policies_index_hash, bsid);
471 sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
473 fib_route_path_t path = {
474 .frp_proto = DPO_PROTO_MPLS,
475 .frp_local_label = sr_policy->bsid,
477 .frp_sw_if_index = ~0,
480 .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
483 fib_route_path_t *paths = NULL;
485 if (steer_pl->vpn_label != (u32) ~ 0)
487 fib_mpls_label_t fml = {
488 .fml_value = steer_pl->vpn_label,
490 vec_add1 (path.frp_label_stack, fml);
493 /* FIB API calls - Recursive route through the BindingSID */
494 if (traffic_type == SR_STEER_IPV6)
496 pfx.fp_proto = FIB_PROTOCOL_IP6;
497 pfx.fp_len = steer_pl->classify.mask_width;
498 pfx.fp_addr.ip6 = steer_pl->classify.prefix.ip6;
499 path.frp_fib_index = 0;
500 path.frp_preference = 0;
501 vec_add1 (paths, path);
502 fib_table_entry_path_add2 (fib_table_find
504 (table_id != (u32) ~ 0 ? table_id : 0)),
506 FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT, paths);
509 else if (traffic_type == SR_STEER_IPV4)
511 pfx.fp_proto = FIB_PROTOCOL_IP4;
512 pfx.fp_len = steer_pl->classify.mask_width;
513 pfx.fp_addr.ip4 = steer_pl->classify.prefix.ip4;
514 path.frp_fib_index = 0;
515 path.frp_preference = 0;
516 vec_add1 (paths, path);
517 fib_table_entry_path_add2 (fib_table_find
519 (table_id != (u32) ~ 0 ? table_id : 0)),
521 FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT, paths);
525 /* Automated steering */
528 steer_pl->bsid = (u32) ~ 0;
529 vec_add1 (steer_pl->color, color);
530 compute_sr_te_automated_steering_fib_entry (steer_pl);
531 internal_label_lock_co (steer_pl->next_hop, color, steer_pl->co_bits);
537 * @brief Delete steering rule for an SR-MPLS policy
540 * @param bsid is the bindingSID of the SR Policy (alt to sr_policy_index)
541 * @param sr_policy is the index of the SR Policy (alt to bsid)
542 * @param table_id is the VRF where to install the FIB entry for the BSID
543 * @param prefix is the IPv4/v6 address for L3 traffic type
544 * @param mask_width is the mask for L3 traffic type
545 * @param traffic_type describes the type of traffic
546 * @param next_hop SR TE Next-HOP
547 * @param nh_type is the AF of Next-Hop
548 * @param color SR TE color
550 * @return 0 if correct, else error
553 sr_mpls_steering_policy_del (ip46_address_t * prefix, u32 mask_width,
554 u8 traffic_type, u32 table_id, u32 color)
556 mpls_sr_main_t *sm = &sr_mpls_main;
557 sr_mpls_steering_key_t key;
558 mpls_sr_steering_policy_t *steer_pl;
559 fib_prefix_t pfx = { 0 };
562 memset (&key, 0, sizeof (sr_mpls_steering_key_t));
564 /* Compute the steer policy key */
565 if (traffic_type != SR_STEER_IPV4 && traffic_type != SR_STEER_IPV6)
568 key.prefix.as_u64[0] = prefix->as_u64[0];
569 key.prefix.as_u64[1] = prefix->as_u64[1];
570 key.mask_width = mask_width;
571 key.fib_table = (table_id != (u32) ~ 0 ? table_id : 0);
572 key.traffic_type = traffic_type;
574 if (!sm->sr_steer_policies_hash.hash)
575 mhash_init (&sm->sr_steer_policies_hash, sizeof (uword),
576 sizeof (sr_mpls_steering_key_t));
578 /* Search for the item */
579 p = mhash_get (&sm->sr_steer_policies_hash, &key);
584 /* Retrieve Steer Policy function */
585 steer_pl = pool_elt_at_index (sm->steer_policies, p[0]);
587 if (steer_pl->bsid == (u32) ~ 0)
589 /* Remove the color from the color vector */
590 vec_del1 (steer_pl->color, vec_search (steer_pl->color, color));
592 if (vec_len (steer_pl->color))
595 vec_sort_with_function (steer_pl->color, sort_color_descent);
596 compute_sr_te_automated_steering_fib_entry (steer_pl);
597 /* Remove all the locks for this ones... */
598 internal_label_unlock_co (steer_pl->next_hop, color,
604 vec_free (steer_pl->color);
605 /* Remove FIB entry */
606 if (steer_pl->classify.traffic_type == SR_STEER_IPV6)
608 pfx.fp_proto = FIB_PROTOCOL_IP6;
609 pfx.fp_len = steer_pl->classify.mask_width;
610 pfx.fp_addr.ip6 = steer_pl->classify.prefix.ip6;
611 fib_table_entry_delete (fib_table_find
613 steer_pl->classify.fib_table), &pfx,
616 else if (steer_pl->classify.traffic_type == SR_STEER_IPV4)
618 pfx.fp_proto = FIB_PROTOCOL_IP4;
619 pfx.fp_len = steer_pl->classify.mask_width;
620 pfx.fp_addr.ip4 = steer_pl->classify.prefix.ip4;
621 fib_table_entry_delete (fib_table_find
623 steer_pl->classify.fib_table), &pfx,
626 /* Remove all the locks for this ones... */
627 internal_label_unlock_co (steer_pl->next_hop, color,
631 else //Remove by BSID
633 if (steer_pl->classify.traffic_type == SR_STEER_IPV6)
635 pfx.fp_proto = FIB_PROTOCOL_IP6;
636 pfx.fp_len = steer_pl->classify.mask_width;
637 pfx.fp_addr.ip6 = steer_pl->classify.prefix.ip6;
638 fib_table_entry_delete (fib_table_find
640 steer_pl->classify.fib_table), &pfx,
643 else if (steer_pl->classify.traffic_type == SR_STEER_IPV4)
645 pfx.fp_proto = FIB_PROTOCOL_IP4;
646 pfx.fp_len = steer_pl->classify.mask_width;
647 pfx.fp_addr.ip4 = steer_pl->classify.prefix.ip4;
648 fib_table_entry_delete (fib_table_find
650 steer_pl->classify.fib_table), &pfx,
654 /* Delete SR steering policy entry */
655 pool_put (sm->steer_policies, steer_pl);
656 mhash_unset (&sm->sr_steer_policies_hash, &key, NULL);
657 if (mhash_elts (&sm->sr_steer_policies_hash) == 0)
659 mhash_free (&sm->sr_steer_policies_hash);
660 sm->sr_steer_policies_hash.hash = NULL;
665 static clib_error_t *
666 sr_mpls_steer_policy_command_fn (vlib_main_t * vm, unformat_input_t * input,
667 vlib_cli_command_t * cmd)
671 ip46_address_t prefix, nh;
672 u32 dst_mask_width = 0;
675 u32 fib_table = (u32) ~ 0, color = (u32) ~ 0;
678 mpls_label_t bsid, vpn_label = (u32) ~ 0;
680 u8 sr_policy_set = 0;
682 memset (&prefix, 0, sizeof (ip46_address_t));
683 memset (&nh, 0, sizeof (ip46_address_t));
686 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
688 if (unformat (input, "del"))
690 else if (!traffic_type
691 && unformat (input, "l3 %U/%d", unformat_ip6_address,
692 &prefix.ip6, &dst_mask_width))
693 traffic_type = SR_STEER_IPV6;
694 else if (!traffic_type
695 && unformat (input, "l3 %U/%d", unformat_ip4_address,
696 &prefix.ip4, &dst_mask_width))
697 traffic_type = SR_STEER_IPV4;
698 else if (!sr_policy_set
699 && unformat (input, "via sr policy bsid %U",
700 unformat_mpls_unicast_label, &bsid))
702 else if (!sr_policy_set
703 && unformat (input, "via next-hop %U color %d co %d",
704 unformat_ip4_address, &nh.ip4, &color, &co_bits))
707 nh_type = SR_STEER_IPV4;
709 else if (!sr_policy_set
710 && unformat (input, "via next-hop %U color %d co %d",
711 unformat_ip6_address, &nh.ip6, &color, &co_bits))
714 nh_type = SR_STEER_IPV6;
716 else if (fib_table == (u32) ~ 0
717 && unformat (input, "fib-table %d", &fib_table));
718 else if (unformat (input, "vpn-label %U",
719 unformat_mpls_unicast_label, &vpn_label));
725 return clib_error_return (0, "No L3 traffic specified");
727 return clib_error_return (0, "No SR policy specified");
729 /* Make sure that the prefixes are clean */
730 if (traffic_type == SR_STEER_IPV4)
733 (dst_mask_width ? (0xFFFFFFFFu >> (32 - dst_mask_width)) : 0);
734 prefix.ip4.as_u32 &= mask;
736 else if (traffic_type == SR_STEER_IPV6)
739 ip6_address_mask_from_width (&mask, dst_mask_width);
740 ip6_address_mask (&prefix.ip6, &mask);
748 sr_mpls_steering_policy_del (&prefix, dst_mask_width,
749 traffic_type, fib_table, color);
753 sr_mpls_steering_policy_add (bsid, fib_table, &prefix, dst_mask_width,
754 traffic_type, &nh, nh_type, color, co_bits,
764 return clib_error_return (0, "Incorrect API usage.");
766 return clib_error_return (0, "The Next-Hop does not match.");
768 return clib_error_return (0, "The color already exists.");
770 return clib_error_return (0, "The co-bits do not match.");
772 return clib_error_return (0, "The VPN-labels do not match.");
774 return clib_error_return (0, "BUG: sr steer policy returns %d", rv);
780 VLIB_CLI_COMMAND(sr_mpls_steer_policy_command, static)=
782 .path = "sr mpls steer",
783 .short_help = "sr mpls steer (del) l3 <ip_addr/mask> "
784 "via [sr policy bsid <mpls_label> || next-hop <ip46_addr> color <u32> co <0|1|2|3> ](fib-table <fib_table_index>)(vpn-label 500)",
786 "\tSteer L3 traffic through an existing SR policy.\n"
788 "\t\tsr steer l3 2001::/64 via sr_policy bsid 29999\n"
789 "\t\tsr steer del l3 2001::/64 via sr_policy bsid 29999\n"
790 "\t\tsr steer l3 2001::/64 via next-hop 1.1.1.1 color 1234 co 0\n"
791 "\t\tsr steer l3 2001::/64 via next-hop 2001::1 color 1234 co 2 vpn-label 500\n",
792 .function = sr_mpls_steer_policy_command_fn,
796 static clib_error_t *
797 show_sr_mpls_steering_policies_command_fn (vlib_main_t * vm,
798 unformat_input_t * input,
799 vlib_cli_command_t * cmd)
801 mpls_sr_main_t *sm = &sr_mpls_main;
802 mpls_sr_steering_policy_t **steer_policies = 0;
803 mpls_sr_steering_policy_t *steer_pl;
807 vlib_cli_output (vm, "SR MPLS steering policies:");
809 pool_foreach(steer_pl, sm->steer_policies, ({
810 vec_add1(steer_policies, steer_pl);
813 for (i = 0; i < vec_len (steer_policies); i++)
815 vlib_cli_output (vm, "==========================");
816 steer_pl = steer_policies[i];
817 if (steer_pl->classify.traffic_type == SR_STEER_IPV4)
819 vlib_cli_output (vm, "Prefix: %U/%d via:",
821 &steer_pl->classify.prefix.ip4,
822 steer_pl->classify.mask_width);
824 else if (steer_pl->classify.traffic_type == SR_STEER_IPV6)
826 vlib_cli_output (vm, "Prefix: %U/%d via:",
828 &steer_pl->classify.prefix.ip6,
829 steer_pl->classify.mask_width);
832 if (steer_pl->bsid != (u32) ~ 0)
834 vlib_cli_output (vm, "· BSID %U",
835 format_mpls_unicast_label, steer_pl->bsid);
839 if (steer_pl->nh_type == SR_STEER_IPV4)
841 vlib_cli_output (vm, "· Next-hop %U",
842 format_ip4_address, &steer_pl->next_hop.ip4);
844 else if (steer_pl->nh_type == SR_STEER_IPV6)
846 vlib_cli_output (vm, "· Next-hop %U",
847 format_ip6_address, &steer_pl->next_hop.ip6);
852 s = format (s, "[ ");
853 vec_foreach (color_i, steer_pl->color)
855 s = format (s, "%d, ", *color_i);
857 s = format (s, "\b\b ]");
858 vlib_cli_output (vm, "· Color %s", s);
860 switch (steer_pl->co_bits)
862 case SR_TE_CO_BITS_00:
863 vlib_cli_output (vm, "· CO-bits: 00");
865 case SR_TE_CO_BITS_01:
866 vlib_cli_output (vm, "· CO-bits: 01");
868 case SR_TE_CO_BITS_10:
869 vlib_cli_output (vm, "· CO-bits: 10");
871 case SR_TE_CO_BITS_11:
872 vlib_cli_output (vm, "· CO-bits: 11");
881 VLIB_CLI_COMMAND(show_sr_mpls_steering_policies_command, static)=
883 .path = "show sr mpls steering policies",
884 .short_help = "show sr mpls steering policies",
885 .function = show_sr_mpls_steering_policies_command_fn,
890 sr_mpls_steering_init (vlib_main_t * vm)
892 mpls_sr_main_t *sm = &sr_mpls_main;
894 /* Init memory for function keys */
895 sm->sr_steer_policies_hash.hash = NULL;
897 sm->fib_table_EC = (u32) ~ 0;
904 VLIB_INIT_FUNCTION(sr_mpls_steering_init);
908 * fd.io coding-style-patch-verification: ON
910 * Local Variables: eval: (c-set-style "gnu") End: