FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
sr_mpls_policy.c
Go to the documentation of this file.
1 /*
2  * sr_mpls_policy.c: SR-MPLS policies
3  *
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:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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
14  * under the License.
15  */
16 
17 /**
18  * @file
19  * @brief SR MPLS policy creation and application
20  *
21  * Create an SR policy.
22  * An SR policy can be either of 'default' type or 'spray' type
23  * An SR policy has attached a list of SID lists.
24  * In case the SR policy is a default one it will load balance among them.
25  * An SR policy has associated a BindingSID.
26  * In case any packet arrives with MPLS_label == BindingSID then the SR policy
27  * associated to such bindingSID will be applied to such packet.
28  * Also, a BSID can be associated with a (Next-Hop, Color)
29  *
30  */
31 
32 #include <vlib/vlib.h>
33 #include <vnet/vnet.h>
34 #include <vnet/srmpls/sr_mpls.h>
35 #include <vnet/fib/mpls_fib.h>
36 #include <vnet/dpo/dpo.h>
37 #include <vnet/ip/ip.h>
38 
39 #include <vppinfra/error.h>
40 #include <vppinfra/elog.h>
41 
43 
44 /*************************** SR LB helper functions **************************/
45 /**
46  * @brief Creates a Segment List and adds it to an SR policy
47  *
48  * Creates a Segment List and adds it to the SR policy. Notice that the SL are
49  * not necessarily unique. Hence there might be two Segment List within the
50  * same SR Policy with exactly the same segments and same weight.
51  *
52  * @param sr_policy is the SR policy where the SL will be added
53  * @param sl is a vector of IPv6 addresses composing the Segment List
54  * @param weight is the weight of the SegmentList (for load-balancing purposes)
55  * @param is_encap represents the mode (SRH insertion vs Encapsulation)
56  *
57  * @return pointer to the just created segment list
58  */
59 static inline mpls_sr_sl_t *
61 {
63  mpls_sr_sl_t *segment_list;
64  u32 ii;
65 
66  pool_get (sm->sid_lists, segment_list);
67  clib_memset (segment_list, 0, sizeof (*segment_list));
68 
69  vec_add1 (sr_policy->segments_lists, segment_list - sm->sid_lists);
70 
71  /* Fill in segment list */
72  segment_list->weight =
73  (weight != (u32) ~ 0 ? weight : SR_SEGMENT_LIST_WEIGHT_DEFAULT);
74  segment_list->segments = vec_dup (sl);
75 
76  mpls_eos_bit_t eos;
78  {
80  .frp_proto = DPO_PROTO_MPLS,
81  .frp_sw_if_index = ~0,
82  .frp_fib_index = 0,
83  .frp_weight = segment_list->weight,
84  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
85  .frp_label_stack = NULL,
86  .frp_local_label = sl[0],
87  };
88 
89  if (vec_len (sl) > 1)
90  {
91  vec_validate (path.frp_label_stack, vec_len (sl) - 2);
92  for (ii = 1; ii < vec_len (sl); ii++)
93  {
94  path.frp_label_stack[ii - 1].fml_value = sl[ii];
95  }
96  }
97  else
98  {
99  /*
100  * add an impliciet NULL label to allow non-eos recursion
101  */
102  fib_mpls_label_t lbl = {
104  };
105  vec_add1 (path.frp_label_stack, lbl);
106  }
107 
108  fib_route_path_t *paths = NULL;
109  vec_add1 (paths, path);
110 
111  /* *INDENT-OFF* */
112  fib_prefix_t pfx = {
113  .fp_len = 21,
114  .fp_proto = FIB_PROTOCOL_MPLS,
115  .fp_label = sr_policy->bsid,
116  .fp_eos = eos,
117  .fp_payload_proto = DPO_PROTO_MPLS,
118  };
119  /* *INDENT-ON* */
120 
122  &pfx,
124  (sr_policy->type == SR_POLICY_TYPE_DEFAULT ?
126  FIB_ENTRY_FLAG_MULTICAST), paths);
127  vec_free (paths);
128  }
129 
130  return segment_list;
131 }
132 
133 /******************************* SR rewrite API *******************************/
134 /*
135  * Three functions for handling sr policies: -> sr_mpls_policy_add ->
136  * sr_mpls_policy_del -> sr_mpls_policy_mod All of them are API. CLI function
137  * on sr_policy_command_fn
138  */
139 
140 /**
141  * @brief Create a new SR policy
142  *
143  * @param bsid is the bindingSID of the SR Policy
144  * @param segments is a vector of MPLS labels composing the segment list
145  * @param behavior is the behavior of the SR policy. (default//spray)
146  * @param fib_table is the VRF where to install the FIB entry for the BSID
147  * @param weight is the weight of this specific SID list
148  *
149  * @return 0 if correct, else error
150  */
151 int
153  u8 behavior, u32 weight)
154 {
156  mpls_sr_policy_t *sr_policy = 0;
157  uword *p;
158 
159  if (!sm->sr_policies_index_hash)
160  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
161 
162  /* MPLS SR policies cannot be created unless the MPLS table is present */
164  return (VNET_API_ERROR_NO_SUCH_TABLE);
165 
166  /* Search for existing keys (BSID) */
167  p = hash_get (sm->sr_policies_index_hash, bsid);
168  if (p)
169  {
170  /* Add SR policy that already exists; complain */
171  return -12;
172  }
173  /* Add an SR policy object */
174  pool_get (sm->sr_policies, sr_policy);
175  clib_memset (sr_policy, 0, sizeof (*sr_policy));
176 
177  /* the first policy needs to lock the MPLS table so it doesn't
178  * disappear with policies in it */
179  if (1 == pool_elts (sm->sr_policies))
182  FIB_SOURCE_SR);
183  sr_policy->bsid = bsid;
184  sr_policy->type = behavior;
185  sr_policy->endpoint_type = 0;
186  ip6_address_set_zero (&sr_policy->endpoint.ip6);
187  sr_policy->color = (u32) ~ 0;
188 
189  /* Copy the key */
190  hash_set (sm->sr_policies_index_hash, bsid, sr_policy - sm->sr_policies);
191 
192  /* Create a segment list and add the index to the SR policy */
193  create_sl (sr_policy, segments, weight);
194 
195  return 0;
196 }
197 
198 /**
199  * @brief Delete a SR policy
200  *
201  * @param bsid is the bindingSID of the SR Policy
202  * @param index is the index of the SR policy
203  *
204  * @return 0 if correct, else error
205  */
206 int
208 {
210  mpls_sr_policy_t *sr_policy = 0;
211  mpls_sr_sl_t *segment_list;
212  mpls_eos_bit_t eos;
213  u32 *sl_index;
214  uword *p;
215 
216  if (!sm->sr_policies_index_hash)
217  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
218 
219  p = hash_get (sm->sr_policies_index_hash, bsid);
220  if (p)
221  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
222  else
223  return -1;
224 
225  /* Clean SID Lists */
226  vec_foreach (sl_index, sr_policy->segments_lists)
227  {
228  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
229 
231  .frp_proto = DPO_PROTO_MPLS,
232  .frp_sw_if_index = ~0,
233  .frp_fib_index = 0,
234  .frp_weight = segment_list->weight,
235  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
236  .frp_local_label = segment_list->segments[0],
237  };
238 
239  vec_add (path.frp_label_stack, segment_list + 1,
240  vec_len (segment_list) - 1);
241 
242  fib_route_path_t *paths = NULL;
243  vec_add1 (paths, path);
244 
245  /* remove each of the MPLS routes */
247  {
248  /* *INDENT-OFF* */
249  fib_prefix_t pfx = {
250  .fp_len = 21,
251  .fp_proto = FIB_PROTOCOL_MPLS,
252  .fp_label = sr_policy->bsid,
253  .fp_eos = eos,
254  .fp_payload_proto = DPO_PROTO_MPLS,
255  };
256  /* *INDENT-ON* */
257 
259  }
260  vec_free (paths);
261  vec_free (segment_list->segments);
262  pool_put_index (sm->sid_lists, *sl_index);
263  }
264 
265  /* If there is still traces of TE, make sure locks are released */
266  if (sr_policy->endpoint_type != 0 && sr_policy->color != (u32) ~ 0)
267  {
268  sr_mpls_policy_assign_endpoint_color (bsid, NULL, 0, (u32) ~ 0);
269  }
270 
271  /* Remove SR policy entry */
272  hash_unset (sm->sr_policies_index_hash, sr_policy->bsid);
273  pool_put (sm->sr_policies, sr_policy);
274 
275  if (0 == pool_elts (sm->sr_policies))
278 
279  return 0;
280 }
281 
282 /**
283  * @brief Modify an existing SR policy
284  *
285  * The possible modifications are adding a new Segment List, modifying an
286  * existing Segment List (modify the weight only) and delete a given
287  * Segment List from the SR Policy.
288  *
289  * @param bsid is the bindingSID of the SR Policy
290  * @param fib_table is the VRF where to install the FIB entry for the BSID
291  * @param operation is the operation to perform (among the top ones)
292  * @param segments is a vector of IPv6 address composing the segment list
293  * @param sl_index is the index of the Segment List to modify/delete
294  * @param weight is the weight of the sid list. optional.
295  *
296  * @return 0 ok, >0 index of SL, <0 error
297  */
298 int
300  mpls_label_t * segments, u32 sl_index, u32 weight)
301 {
303  mpls_sr_policy_t *sr_policy = 0;
304  mpls_sr_sl_t *segment_list;
305  u32 *sl_index_iterate;
306  uword *p;
307 
308  if (!sm->sr_policies_index_hash)
309  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
310 
311  p = hash_get (sm->sr_policies_index_hash, bsid);
312  if (p)
313  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
314  else
315  return -1;
316 
317  if (operation == 1)
318  { /* Add SR List to an existing SR policy */
319  /* Create the new SL */
320  segment_list = create_sl (sr_policy, segments, weight);
321  return segment_list - sm->sid_lists;
322  }
323  else if (operation == 2)
324  { /* Delete SR List from an existing SR
325  * policy */
326  /* Check that currently there are more than one SID list */
327  if (vec_len (sr_policy->segments_lists) == 1)
328  return -21;
329 
330  /*
331  * Check that the SR list does exist and is assigned to the
332  * sr policy
333  */
334  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
335  if (*sl_index_iterate == sl_index)
336  break;
337 
338  if (*sl_index_iterate != sl_index)
339  return -22;
340 
341  /* Remove the lucky SR list that is being kicked out */
342  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
343 
344  mpls_eos_bit_t eos;
346  .frp_proto = DPO_PROTO_MPLS,
347  .frp_sw_if_index = ~0,
348  .frp_fib_index = 0,
349  .frp_weight = segment_list->weight,
350  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
351  .frp_local_label = segment_list->segments[0],
352  };
353 
354  vec_add (path.frp_label_stack, segment_list + 1,
355  vec_len (segment_list) - 1);
356 
357  fib_route_path_t *paths = NULL;
358  vec_add1 (paths, path);
359 
361  {
362  /* *INDENT-OFF* */
363  fib_prefix_t pfx = {
364  .fp_len = 21,
365  .fp_proto = FIB_PROTOCOL_MPLS,
366  .fp_label = sr_policy->bsid,
367  .fp_eos = eos,
368  .fp_payload_proto = DPO_PROTO_MPLS,
369  };
370  /* *INDENT-ON* */
371 
373  }
374 
375  vec_free (paths);
376  vec_free (segment_list->segments);
377  pool_put_index (sm->sid_lists, sl_index);
378  vec_del1 (sr_policy->segments_lists,
379  sl_index_iterate - sr_policy->segments_lists);
380  }
381  else if (operation == 3)
382  { /* Modify the weight of an existing
383  * SR List */
384  /* Find the corresponding SL */
385  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
386  if (*sl_index_iterate == sl_index)
387  break;
388 
389  if (*sl_index_iterate != sl_index)
390  return -32;
391 
392  /* Change the weight */
393  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
394 
395  /* Update LB */
396  mpls_eos_bit_t eos;
398  .frp_proto = DPO_PROTO_MPLS,
399  .frp_sw_if_index = ~0,
400  .frp_fib_index = 0,
401  .frp_weight = segment_list->weight,
402  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
403  .frp_local_label = segment_list->segments[0],
404  };
405 
406  vec_add (path.frp_label_stack, segment_list + 1,
407  vec_len (segment_list) - 1);
408 
409  fib_route_path_t *paths = NULL;
410  vec_add1 (paths, path);
411 
413  {
414  /* *INDENT-OFF* */
415  fib_prefix_t pfx = {
416  .fp_len = 21,
417  .fp_proto = FIB_PROTOCOL_MPLS,
418  .fp_label = sr_policy->bsid,
419  .fp_eos = eos,
420  .fp_payload_proto = DPO_PROTO_MPLS,
421  };
422  /* *INDENT-ON* */
423 
425  }
426 
427  segment_list->weight = weight;
428 
429  path.frp_weight = segment_list->weight;
430 
431  vec_free (paths);
432  paths = NULL;
433  vec_add1 (paths, path);
434 
436  {
437  /* *INDENT-OFF* */
438  fib_prefix_t pfx = {
439  .fp_len = 21,
440  .fp_proto = FIB_PROTOCOL_MPLS,
441  .fp_label = sr_policy->bsid,
442  .fp_eos = eos,
443  .fp_payload_proto = DPO_PROTO_MPLS,
444  };
445  /* *INDENT-ON* */
446 
448  &pfx,
450  (sr_policy->type ==
453  FIB_ENTRY_FLAG_MULTICAST), paths);
454  }
455  }
456  return 0;
457 }
458 
459 /**
460  * @brief CLI for 'sr mpls policies' command family
461  */
462 static clib_error_t *
464  vlib_cli_command_t * cmd)
465 {
466  int rv = -1;
467  char is_del = 0, is_add = 0, is_mod = 0;
468  char policy_set = 0;
469  mpls_label_t bsid, next_label;
470  u32 sl_index = (u32) ~ 0;
471  u32 weight = (u32) ~ 0;
472  mpls_label_t *segments = 0;
473  u8 operation = 0;
474  u8 is_spray = 0;
475 
477  {
478  if (!is_add && !is_mod && !is_del && unformat (input, "add"))
479  is_add = 1;
480  else if (!is_add && !is_mod && !is_del && unformat (input, "del"))
481  is_del = 1;
482  else if (!is_add && !is_mod && !is_del && unformat (input, "mod"))
483  is_mod = 1;
484  else if (!policy_set
485  && unformat (input, "bsid %U", unformat_mpls_unicast_label,
486  &bsid))
487  policy_set = 1;
488  else if (unformat (input, "weight %d", &weight));
489  else if (unformat
490  (input, "next %U", unformat_mpls_unicast_label, &next_label))
491  {
492  vec_add (segments, &next_label, 1);
493  }
494  else if (unformat (input, "add sl"))
495  operation = 1;
496  else if (unformat (input, "del sl index %d", &sl_index))
497  operation = 2;
498  else if (unformat (input, "mod sl index %d", &sl_index))
499  operation = 3;
500  else if (unformat (input, "spray"))
501  is_spray = 1;
502  else
503  break;
504  }
505 
506  if (!is_add && !is_mod && !is_del)
507  return clib_error_return (0, "Incorrect CLI");
508 
509  if (!policy_set)
510  return clib_error_return (0, "No SR policy BSID or index specified");
511 
512  if (is_add)
513  {
514  if (vec_len (segments) == 0)
515  return clib_error_return (0, "No Segment List specified");
516 
517  rv = sr_mpls_policy_add (bsid, segments,
518  (is_spray ? SR_POLICY_TYPE_SPRAY :
519  SR_POLICY_TYPE_DEFAULT), weight);
520  vec_free (segments);
521  }
522  else if (is_del)
523  rv = sr_mpls_policy_del (bsid);
524  else if (is_mod)
525  {
526  if (!operation)
527  return clib_error_return (0, "No SL modification specified");
528  if (operation != 1 && sl_index == (u32) ~ 0)
529  return clib_error_return (0, "No Segment List index specified");
530  if (operation == 1 && vec_len (segments) == 0)
531  return clib_error_return (0, "No Segment List specified");
532  if (operation == 3 && weight == (u32) ~ 0)
533  return clib_error_return (0, "No new weight for the SL specified");
534  rv = sr_mpls_policy_mod (bsid, operation, segments, sl_index, weight);
535  vec_free (segments);
536  }
537  switch (rv)
538  {
539  case 0:
540  break;
541  case 1:
542  return 0;
543  case -12:
544  return clib_error_return (0,
545  "There is already a FIB entry for the BindingSID address.\n"
546  "The SR policy could not be created.");
547  case -21:
548  return clib_error_return (0,
549  "The selected SR policy only contains ONE segment list. "
550  "Please remove the SR policy instead");
551  case -22:
552  return clib_error_return (0,
553  "Could not delete the segment list. "
554  "It is not associated with that SR policy.");
555  case -23:
556  return clib_error_return (0,
557  "Could not delete the segment list. "
558  "It is not associated with that SR policy.");
559  case -32:
560  return clib_error_return (0,
561  "Could not modify the segment list. "
562  "The given SL is not associated with such SR policy.");
563  case VNET_API_ERROR_NO_SUCH_TABLE:
564  return clib_error_return (0, "the Default MPLS table is not present");
565  default:
566  return clib_error_return (0, "BUG: sr policy returns %d", rv);
567  }
568  return 0;
569 }
570 
571 /* *INDENT-OFF* */
572 VLIB_CLI_COMMAND(sr_mpls_policy_command, static)=
573 {
574  .path = "sr mpls policy",
575  .short_help = "sr mpls policy [add||del||mod] bsid 2999 "
576  "next 10 next 20 next 30 (weight 1) (spray)",
577  .long_help = "TBD.\n",
578  .function = sr_mpls_policy_command_fn,
579 };
580 /* *INDENT-ON* */
581 
582 /**
583  * @brief CLI to display onscreen all the SR MPLS policies
584  */
585 static clib_error_t *
587  vlib_cli_command_t * cmd)
588 {
590  mpls_sr_sl_t *segment_list = 0;
591  mpls_sr_policy_t *sr_policy = 0;
592  mpls_sr_policy_t **vec_policies = 0;
594  u32 *sl_index;
595  u8 *s;
596  int i = 0;
597 
598  vlib_cli_output (vm, "SR MPLS policies:");
599 
600  /* *INDENT-OFF* */
601  pool_foreach(sr_policy, sm->sr_policies, {
602  vec_add1(vec_policies, sr_policy);
603  });
604  /* *INDENT-ON* */
605 
606  vec_foreach_index (i, vec_policies)
607  {
608  sr_policy = vec_policies[i];
609  vlib_cli_output (vm, "[%u].-\tBSID: %U",
610  (u32) (sr_policy - sm->sr_policies),
611  format_mpls_unicast_label, sr_policy->bsid);
612  switch (sr_policy->endpoint_type)
613  {
614  case SR_STEER_IPV6:
615  vlib_cli_output (vm, "\tEndpoint: %U", format_ip6_address,
616  &sr_policy->endpoint.ip6);
617  vlib_cli_output (vm, "\tColor: %u", sr_policy->color);
618  break;
619  case SR_STEER_IPV4:
620  vlib_cli_output (vm, "\tEndpoint: %U", format_ip4_address,
621  &sr_policy->endpoint.ip4);
622  vlib_cli_output (vm, "\tColor: %u", sr_policy->color);
623  break;
624  default:
625  vlib_cli_output (vm, "\tTE disabled");
626  }
627  vlib_cli_output (vm, "\tType: %s",
628  (sr_policy->type ==
629  SR_POLICY_TYPE_DEFAULT ? "Default" : "Spray"));
630  vlib_cli_output (vm, "\tSegment Lists:");
631  vec_foreach (sl_index, sr_policy->segments_lists)
632  {
633  s = NULL;
634  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
635  s = format (s, "\t[%u].- ", *sl_index);
636  s = format (s, "< ");
637  vec_foreach (label, segment_list->segments)
638  {
639  s = format (s, "%U, ", format_mpls_unicast_label, *label);
640  }
641  s = format (s, "\b\b > ");
642  vlib_cli_output (vm, " %s", s);
643  }
644  vlib_cli_output (vm, "-----------");
645  }
646  vec_free (vec_policies);
647  return 0;
648 }
649 
650 /* *INDENT-OFF* */
651 VLIB_CLI_COMMAND(show_sr_mpls_policies_command, static)=
652 {
653  .path = "show sr mpls policies",
654  .short_help = "show sr mpls policies",
656 };
657 /* *INDENT-ON* */
658 
659 /**
660  * @brief Update the Endpoint,Color tuple of an SR policy
661  *
662  * @param bsid is the bindingSID of the SR Policy
663  * @param endpoint represents the IP46 of the endpoint
664  * @param color represents the color (u32)
665  *
666  * To reset to NULL use ~0 as parameters.
667  *
668  * @return 0 if correct, else error
669  */
670 int
672  ip46_address_t * endpoint,
673  u8 endpoint_type, u32 color)
674 {
676  mpls_sr_policy_t *sr_policy = 0;
677  uword *endpoint_table, *p, *old_value;
678 
679  ip46_address_t any;
680  any.as_u64[0] = any.as_u64[1] = (u64) ~ 0;
681 
682  if (!sm->sr_policies_index_hash)
683  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
684 
685  p = hash_get (sm->sr_policies_index_hash, bsid);
686  if (p)
687  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
688  else
689  return -1;
690 
691  /* If previous Endpoint, color existed, remove (NH,C) and (ANY,C) */
692  if (sr_policy->endpoint_type)
693  {
694  endpoint_table =
695  mhash_get (&sm->sr_policies_c2e2eclabel_hash, &sr_policy->color);
696  if (!endpoint_table)
697  return -2;
698  old_value =
699  mhash_get ((mhash_t *) endpoint_table, &sr_policy->endpoint);
700 
701  /* CID 180995 This should never be NULL unless the two hash tables
702  * get out of sync */
703  ALWAYS_ASSERT (old_value != NULL);
704 
705  fib_prefix_t pfx = { 0 };
707  pfx.fp_len = 21;
708  pfx.fp_label = (u32) * old_value;
709 
710  mpls_eos_bit_t eos;
712  {
713  pfx.fp_eos = eos;
715  &pfx,
718  NULL,
719  ~0, 0, 1, FIB_ROUTE_PATH_FLAG_NONE);
720  }
721 
722  old_value = mhash_get ((mhash_t *) endpoint_table, &any);
723  pfx.fp_label = (u32) * old_value;
724 
726  {
727  pfx.fp_eos = eos;
729  &pfx,
732  NULL,
733  ~0, 0, 1, FIB_ROUTE_PATH_FLAG_NONE);
734  }
735 
736  /* Release the lock on (NH, Color) and (ANY, Color) */
737  internal_label_unlock (sr_policy->endpoint, sr_policy->color);
738  internal_label_unlock (any, sr_policy->color);
739 
740  /* Reset the values on the SR policy */
741  sr_policy->endpoint_type = 0;
742  sr_policy->endpoint.as_u64[0] = sr_policy->endpoint.as_u64[1] =
743  (u64) ~ 0;
744  sr_policy->color = (u32) ~ 0;
745  }
746 
747  if (endpoint_type)
748  {
749  sr_policy->endpoint_type = endpoint_type;
750  sr_policy->endpoint.as_u64[0] = endpoint->as_u64[0];
751  sr_policy->endpoint.as_u64[1] = endpoint->as_u64[1];
752  sr_policy->color = color;
753 
754  u32 label = find_or_create_internal_label (*endpoint, color);
755  internal_label_lock (*endpoint, sr_policy->color);
756 
757  /* If FIB doesnt exist, create them */
758  if (sm->fib_table_EC == (u32) ~ 0)
759  {
762  "SR-MPLS Traffic Engineering (NextHop,Color)");
763 
766  }
767 
768  fib_prefix_t pfx = { 0 };
770  pfx.fp_len = 21;
771 
773  .frp_proto = DPO_PROTO_MPLS,
774  .frp_sw_if_index = ~0,
775  .frp_fib_index = 0,
776  .frp_weight = 1,
777  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
778  .frp_label_stack = 0
779  };
780  path.frp_local_label = sr_policy->bsid;
781 
782  //Add the entry to ANY,Color
783  u32 any_label = find_or_create_internal_label (any, color);
784  internal_label_lock (any, sr_policy->color);
785 
786  pfx.fp_eos = MPLS_EOS;
787  path.frp_eos = MPLS_EOS;
788 
789  fib_route_path_t *paths = NULL;
790  vec_add1 (paths, path);
791 
792  pfx.fp_label = label;
794  &pfx,
797 
798  pfx.fp_label = any_label;
800  &pfx,
803 
804  fib_mpls_label_t fml = {
806  };
807 
808  vec_add1 (path.frp_label_stack, fml);
809  pfx.fp_eos = MPLS_NON_EOS;
810  path.frp_eos = MPLS_NON_EOS;
811 
812  paths = NULL;
813  vec_add1 (paths, path);
814 
815  pfx.fp_label = label;
817  &pfx,
820 
821  pfx.fp_label = any_label;
823  &pfx,
826  }
827  return 0;
828 }
829 
830 /**
831  * @brief CLI to modify the Endpoint,Color of an SR policy
832  */
833 static clib_error_t *
835  vlib_cli_command_t * cmd)
836 {
837  ip46_address_t endpoint;
838  u32 color = (u32) ~ 0;
839  mpls_label_t bsid;
840  u8 endpoint_type = 0;
841  char clear = 0, color_set = 0, bsid_set = 0;
842 
843  clib_memset (&endpoint, 0, sizeof (ip46_address_t));
844 
845  int rv;
847  {
848  if (!endpoint_type
849  && unformat (input, "endpoint %U", unformat_ip6_address,
850  &endpoint.ip6))
851  endpoint_type = SR_STEER_IPV6;
852  else if (!endpoint_type
853  && unformat (input, "endpoint %U", unformat_ip4_address,
854  &endpoint.ip4))
855  endpoint_type = SR_STEER_IPV4;
856  else if (!color_set && unformat (input, "color %u", &color))
857  color_set = 1;
858  else if (!bsid_set
859  && unformat (input, "bsid %U", unformat_mpls_unicast_label,
860  &bsid))
861  bsid_set = 1;
862  else if (!clear && unformat (input, "clear"))
863  clear = 1;
864  else
865  break;
866  }
867 
868  if (!bsid_set)
869  return clib_error_return (0, "No BSID specified");
870  if (!endpoint_type && !clear)
871  return clib_error_return (0, "No Endpoint specified");
872  if (!color_set && !clear)
873  return clib_error_return (0, "No Color set");
874 
875  /* In case its a cleanup */
876  if (clear)
877  {
878  ip6_address_set_zero (&endpoint.ip6);
879  color = (u32) ~ 0;
880  }
881  rv =
882  sr_mpls_policy_assign_endpoint_color (bsid, &endpoint, endpoint_type,
883  color);
884 
885  if (rv)
886  clib_error_return (0, "Error on Endpoint,Color");
887 
888  return 0;
889 }
890 
891 /* *INDENT-OFF* */
892 VLIB_CLI_COMMAND(cli_sr_mpls_policy_ec_command, static)=
893 {
894  .path = "sr mpls policy te",
895  .short_help = "sr mpls policy te bsid xxxxx endpoint x.x.x.x color 12341234",
897 };
898 /* *INDENT-ON* */
899 
900 /********************* SR MPLS Policy initialization ***********************/
901 /**
902  * @brief SR MPLS Policy initialization
903  */
904 clib_error_t *
906 {
908 
909  /* Init memory for sr policy keys (bsid <-> ip6_address_t) */
910  sm->sr_policies_index_hash = NULL;
912  return 0;
913 }
914 
916 
917 /*
918  * fd.io coding-style-patch-verification: ON
919  *
920  * Local Variables: eval: (c-set-style "gnu") End:
921  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
Definition: mhash.h:46
static clib_error_t * sr_mpls_policy_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI for &#39;sr mpls policies&#39; command family.
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define SR_STEER_IPV6
Definition: sr_mpls.h:42
#define hash_set(h, key, value)
Definition: hash.h:255
#define SR_STEER_IPV4
Definition: sr_mpls.h:41
mpls_eos_bit_t frp_eos
EOS bit for the resolving label.
Definition: fib_types.h:517
#define hash_unset(h, key)
Definition: hash.h:261
int sr_mpls_policy_del(mpls_label_t bsid)
Delete a SR policy.
A representation of a path as described by a route producer.
Definition: fib_types.h:490
unsigned long u64
Definition: types.h:89
fib_node_index_t fib_table_entry_update(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, fib_route_path_t *paths)
Update an entry to have a new set of paths.
Definition: fib_table.c:756
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:26
fib_node_index_t fib_table_entry_path_add2(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, fib_route_path_t *rpaths)
Add n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:591
#define MPLS_IETF_IMPLICIT_NULL_LABEL
Definition: mpls_types.h:30
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
word any
Definition: types.h:139
int sr_mpls_policy_assign_endpoint_color(mpls_label_t bsid, ip46_address_t *endpoint, u8 endpoint_type, u32 color)
Update the Endpoint,Color tuple of an SR policy.
vlib_main_t * vm
Definition: in2out_ed.c:1582
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
vl_api_fib_path_t path
Definition: mfib_types.api:34
SR Segment List (SID list)
Definition: sr_mpls.h:52
Definition: fib_entry.h:121
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:252
unsigned char u8
Definition: types.h:56
u32 sl_index
Definition: sr.api:35
unformat_function_t unformat_mpls_unicast_label
Definition: mpls.h:81
static clib_error_t * cli_sr_mpls_policy_ec_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI to modify the Endpoint,Color of an SR policy.
u8 weight
Definition: fib_types.api:120
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:668
Definition: fib_entry.h:120
format_function_t format_ip4_address
Definition: format.h:73
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
unformat_function_t unformat_ip4_address
Definition: format.h:68
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
clib_error_t * sr_mpls_policy_rewrite_init(vlib_main_t *vm)
SR MPLS Policy initialization.
void fib_table_flush(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Flush all entries from a table for the source.
Definition: fib_table.c:1398
Aggregate type for a prefix.
Definition: fib_types.h:203
#define clib_error_return(e, args...)
Definition: error.h:99
mpls_sr_sl_t * sid_lists
Definition: sr_mpls.h:109
#define ALWAYS_ASSERT(truth)
unsigned int u32
Definition: types.h:88
mpls_sr_main_t sr_mpls_main
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1097
u16 fp_len
The mask length.
Definition: fib_types.h:207
Definition: fib_entry.h:112
#define SR_POLICY_TYPE_DEFAULT
Definition: sr_mpls.h:36
#define hash_get(h, key)
Definition: hash.h:249
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:429
Configuration for each label value in the output-stack.
Definition: fib_types.h:445
fib_mpls_label_t * frp_label_stack
The outgoing MPLS label Stack.
Definition: fib_types.h:551
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:875
u32 label
Definition: fib_types.api:25
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1291
mpls_label_t bsid
BindingSID (key)
Definition: sr_mpls.h:66
int sr_mpls_policy_add(mpls_label_t bsid, mpls_label_t *segments, u8 behavior, u32 weight)
Create a new SR policy.
static clib_error_t * show_sr_mpls_policies_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI to display onscreen all the SR MPLS policies.
unformat_function_t unformat_ip6_address
Definition: format.h:89
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
int sr_mpls_policy_mod(mpls_label_t bsid, u8 operation, mpls_label_t *segments, u32 sl_index, u32 weight)
Modify an existing SR policy.
#define MPLS_FIB_DEFAULT_TABLE_ID
Definition: mpls_fib.h:28
vl_api_address_t endpoint
Definition: wireguard.api:101
void fib_table_entry_path_remove2(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_route_path_t *rpaths)
Remove n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:640
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
SRv6 and SR-MPLS.
Definition: fib_source.h:60
format_function_t format_ip6_address
Definition: format.h:91
static void ip6_address_set_zero(ip6_address_t *a)
Definition: ip6_packet.h:203
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
mpls_label_t fml_value
The label value.
Definition: fib_types.h:450
mpls_sr_policy_t * sr_policies
Definition: sr_mpls.h:112
static mpls_sr_sl_t * create_sl(mpls_sr_policy_t *sr_policy, mpls_label_t *sl, u32 weight)
Creates a Segment List and adds it to an SR policy.
mpls_label_t fp_label
Definition: fib_types.h:229
vl_api_fib_path_t paths[n_paths]
Definition: ip.api:146
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
#define FOR_EACH_MPLS_EOS_BIT(_eos)
Definition: packet.h:73
#define hash_create(elts, value_bytes)
Definition: hash.h:696
Segment Routing main datastructure.
Definition: sr_mpls.h:106
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:331
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
void internal_label_lock(ip46_address_t endpoint, u32 color)
lock the label for (NH, C) endpoint might be NULL or ANY NULL = 0, ANY=~0
#define SR_POLICY_TYPE_SPRAY
Definition: sr_mpls.h:37
ip46_address_t endpoint
Optional NH for SR TE.
Definition: sr_mpls.h:73
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, fib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1156
uword * sr_policies_index_hash
Definition: sr_mpls.h:115
u32 find_or_create_internal_label(ip46_address_t endpoint, u32 color)
find the corresponding label for (endpoint, color) and lock it endpoint might be NULL or ANY NULL = 0...
uword * hash
Definition: mhash.h:69
void fib_table_entry_path_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_route_path_flags_t path_flags)
remove one path to an entry (aka route) in the FIB.
Definition: fib_table.c:722
#define SR_SEGMENT_LIST_WEIGHT_DEFAULT
Definition: sr_mpls.h:39
format_function_t format_mpls_unicast_label
Definition: mpls.h:71
mpls_label_t frp_local_label
The MPLS local Label to reursively resolve through.
Definition: fib_types.h:513
mhash_t sr_policies_c2e2eclabel_hash
SR TE.
Definition: sr_mpls.h:125
u32 color
Optional color for SR TE.
Definition: sr_mpls.h:75
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
u8 type
Type (default is 0)
Definition: sr_mpls.h:68
Segment Routing MPLS data structures definitions.
mpls_label_t * segments
Definition: sr_mpls.h:55
u32 * segments_lists
Pool of SID lists indexes.
Definition: sr_mpls.h:64
#define vec_foreach(var, vec)
Vector iterator.
Special sources.
Definition: fib_source.h:42
u32 fib_table_EC
Definition: sr_mpls.h:127
u8 frp_weight
[un]equal cost path weight
Definition: fib_types.h:590
void internal_label_unlock(ip46_address_t endpoint, u32 color)
Release lock on label for (endpoint, color) endpoint might be NULL or ANY NULL = 0, ANY=~0.
u32 fib_table_create_and_lock(fib_protocol_t proto, fib_source_t src, const char *const fmt,...)
Create a new table with no table ID.
Definition: fib_table.c:1175
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
mpls_eos_bit_t fp_eos
Definition: fib_types.h:230
u32 weight
Definition: sr_mpls.h:58
enum mpls_eos_bit_t_ mpls_eos_bit_t
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128