FD.io VPP  v18.07-34-g55fbdb9
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 *
60 create_sl (mpls_sr_policy_t * sr_policy, mpls_label_t * sl, u32 weight)
61 {
63  mpls_sr_sl_t *segment_list;
64  u32 ii;
65 
66  pool_get (sm->sid_lists, segment_list);
67  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  {
79  fib_route_path_t path = {
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  /* Search for existing keys (BSID) */
163  p = hash_get (sm->sr_policies_index_hash, bsid);
164  if (p)
165  {
166  /* Add SR policy that already exists; complain */
167  return -12;
168  }
169  /* Add an SR policy object */
170  pool_get (sm->sr_policies, sr_policy);
171  memset (sr_policy, 0, sizeof (*sr_policy));
172  sr_policy->bsid = bsid;
173  sr_policy->type = behavior;
174  sr_policy->endpoint_type = 0;
175  ip6_address_set_zero (&sr_policy->endpoint.ip6);
176  sr_policy->color = (u32) ~ 0;
177 
178  /* Copy the key */
179  hash_set (sm->sr_policies_index_hash, bsid, sr_policy - sm->sr_policies);
180 
181  /* Create a segment list and add the index to the SR policy */
182  create_sl (sr_policy, segments, weight);
183 
184  return 0;
185 }
186 
187 /**
188  * @brief Delete a SR policy
189  *
190  * @param bsid is the bindingSID of the SR Policy
191  * @param index is the index of the SR policy
192  *
193  * @return 0 if correct, else error
194  */
195 int
197 {
199  mpls_sr_policy_t *sr_policy = 0;
200  mpls_sr_sl_t *segment_list;
201  mpls_eos_bit_t eos;
202  u32 *sl_index;
203  uword *p;
204 
205  if (!sm->sr_policies_index_hash)
206  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
207 
208  p = hash_get (sm->sr_policies_index_hash, bsid);
209  if (p)
210  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
211  else
212  return -1;
213 
214  /* Clean SID Lists */
215  vec_foreach (sl_index, sr_policy->segments_lists)
216  {
217  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
218 
219  fib_route_path_t path = {
221  .frp_sw_if_index = ~0,
222  .frp_fib_index = 0,
223  .frp_weight = segment_list->weight,
224  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
225  .frp_local_label = segment_list->segments[0],
226  };
227 
228  vec_add (path.frp_label_stack, segment_list + 1,
229  vec_len (segment_list) - 1);
230 
231  fib_route_path_t *paths = NULL;
232  vec_add1 (paths, path);
233 
234  /* remove each of the MPLS routes */
236  {
237  /* *INDENT-OFF* */
238  fib_prefix_t pfx = {
239  .fp_len = 21,
240  .fp_proto = FIB_PROTOCOL_MPLS,
241  .fp_label = sr_policy->bsid,
242  .fp_eos = eos,
243  .fp_payload_proto = DPO_PROTO_MPLS,
244  };
245  /* *INDENT-ON* */
246 
248  }
249  vec_free (paths);
250  vec_free (segment_list->segments);
251  pool_put_index (sm->sid_lists, *sl_index);
252  }
253 
254  /* If there is still traces of TE, make sure locks are released */
255  if (sr_policy->endpoint_type != 0 && sr_policy->color != (u32) ~ 0)
256  {
258  }
259 
260  /* Remove SR policy entry */
261  hash_unset (sm->sr_policies_index_hash, sr_policy->bsid);
262  pool_put (sm->sr_policies, sr_policy);
263 
264  return 0;
265 }
266 
267 /**
268  * @brief Modify an existing SR policy
269  *
270  * The possible modifications are adding a new Segment List, modifying an
271  * existing Segment List (modify the weight only) and delete a given
272  * Segment List from the SR Policy.
273  *
274  * @param bsid is the bindingSID of the SR Policy
275  * @param fib_table is the VRF where to install the FIB entry for the BSID
276  * @param operation is the operation to perform (among the top ones)
277  * @param segments is a vector of IPv6 address composing the segment list
278  * @param sl_index is the index of the Segment List to modify/delete
279  * @param weight is the weight of the sid list. optional.
280  *
281  * @return 0 ok, >0 index of SL, <0 error
282  */
283 int
285  mpls_label_t * segments, u32 sl_index, u32 weight)
286 {
288  mpls_sr_policy_t *sr_policy = 0;
289  mpls_sr_sl_t *segment_list;
290  u32 *sl_index_iterate;
291  uword *p;
292 
293  if (!sm->sr_policies_index_hash)
294  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
295 
296  p = hash_get (sm->sr_policies_index_hash, bsid);
297  if (p)
298  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
299  else
300  return -1;
301 
302  if (operation == 1)
303  { /* Add SR List to an existing SR policy */
304  /* Create the new SL */
305  segment_list = create_sl (sr_policy, segments, weight);
306  return segment_list - sm->sid_lists;
307  }
308  else if (operation == 2)
309  { /* Delete SR List from an existing SR
310  * policy */
311  /* Check that currently there are more than one SID list */
312  if (vec_len (sr_policy->segments_lists) == 1)
313  return -21;
314 
315  /*
316  * Check that the SR list does exist and is assigned to the
317  * sr policy
318  */
319  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
320  if (*sl_index_iterate == sl_index)
321  break;
322 
323  if (*sl_index_iterate != sl_index)
324  return -22;
325 
326  /* Remove the lucky SR list that is being kicked out */
327  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
328 
329  mpls_eos_bit_t eos;
330  fib_route_path_t path = {
332  .frp_sw_if_index = ~0,
333  .frp_fib_index = 0,
334  .frp_weight = segment_list->weight,
335  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
336  .frp_local_label = segment_list->segments[0],
337  };
338 
339  vec_add (path.frp_label_stack, segment_list + 1,
340  vec_len (segment_list) - 1);
341 
342  fib_route_path_t *paths = NULL;
343  vec_add1 (paths, path);
344 
346  {
347  /* *INDENT-OFF* */
348  fib_prefix_t pfx = {
349  .fp_len = 21,
350  .fp_proto = FIB_PROTOCOL_MPLS,
351  .fp_label = sr_policy->bsid,
352  .fp_eos = eos,
353  .fp_payload_proto = DPO_PROTO_MPLS,
354  };
355  /* *INDENT-ON* */
356 
358  }
359 
360  vec_free (paths);
361  vec_free (segment_list->segments);
362  pool_put_index (sm->sid_lists, sl_index);
363  vec_del1 (sr_policy->segments_lists,
364  sl_index_iterate - sr_policy->segments_lists);
365  }
366  else if (operation == 3)
367  { /* Modify the weight of an existing
368  * SR List */
369  /* Find the corresponding SL */
370  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
371  if (*sl_index_iterate == sl_index)
372  break;
373 
374  if (*sl_index_iterate != sl_index)
375  return -32;
376 
377  /* Change the weight */
378  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
379 
380  /* Update LB */
381  mpls_eos_bit_t eos;
382  fib_route_path_t path = {
384  .frp_sw_if_index = ~0,
385  .frp_fib_index = 0,
386  .frp_weight = segment_list->weight,
387  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
388  .frp_local_label = segment_list->segments[0],
389  };
390 
391  vec_add (path.frp_label_stack, segment_list + 1,
392  vec_len (segment_list) - 1);
393 
394  fib_route_path_t *paths = NULL;
395  vec_add1 (paths, path);
396 
398  {
399  /* *INDENT-OFF* */
400  fib_prefix_t pfx = {
401  .fp_len = 21,
402  .fp_proto = FIB_PROTOCOL_MPLS,
403  .fp_label = sr_policy->bsid,
404  .fp_eos = eos,
405  .fp_payload_proto = DPO_PROTO_MPLS,
406  };
407  /* *INDENT-ON* */
408 
410  }
411 
412  segment_list->weight = weight;
413 
414  path.frp_weight = segment_list->weight;
415 
416  vec_free (paths);
417  paths = NULL;
418  vec_add1 (paths, path);
419 
421  {
422  /* *INDENT-OFF* */
423  fib_prefix_t pfx = {
424  .fp_len = 21,
425  .fp_proto = FIB_PROTOCOL_MPLS,
426  .fp_label = sr_policy->bsid,
427  .fp_eos = eos,
428  .fp_payload_proto = DPO_PROTO_MPLS,
429  };
430  /* *INDENT-ON* */
431 
433  &pfx,
435  (sr_policy->type ==
438  FIB_ENTRY_FLAG_MULTICAST), paths);
439  }
440  }
441  return 0;
442 }
443 
444 /**
445  * @brief CLI for 'sr mpls policies' command family
446  */
447 static clib_error_t *
449  vlib_cli_command_t * cmd)
450 {
451  int rv = -1;
452  char is_del = 0, is_add = 0, is_mod = 0;
453  char policy_set = 0;
454  mpls_label_t bsid, next_label;
455  u32 sl_index = (u32) ~ 0;
456  u32 weight = (u32) ~ 0;
457  mpls_label_t *segments = 0;
458  u8 operation = 0;
459  u8 is_spray = 0;
460 
462  {
463  if (!is_add && !is_mod && !is_del && unformat (input, "add"))
464  is_add = 1;
465  else if (!is_add && !is_mod && !is_del && unformat (input, "del"))
466  is_del = 1;
467  else if (!is_add && !is_mod && !is_del && unformat (input, "mod"))
468  is_mod = 1;
469  else if (!policy_set
470  && unformat (input, "bsid %U", unformat_mpls_unicast_label,
471  &bsid))
472  policy_set = 1;
473  else if (unformat (input, "weight %d", &weight));
474  else if (unformat
475  (input, "next %U", unformat_mpls_unicast_label, &next_label))
476  {
477  vec_add (segments, &next_label, 1);
478  }
479  else if (unformat (input, "add sl"))
480  operation = 1;
481  else if (unformat (input, "del sl index %d", &sl_index))
482  operation = 2;
483  else if (unformat (input, "mod sl index %d", &sl_index))
484  operation = 3;
485  else if (unformat (input, "spray"))
486  is_spray = 1;
487  else
488  break;
489  }
490 
491  if (!is_add && !is_mod && !is_del)
492  return clib_error_return (0, "Incorrect CLI");
493 
494  if (!policy_set)
495  return clib_error_return (0, "No SR policy BSID or index specified");
496 
497  if (is_add)
498  {
499  if (vec_len (segments) == 0)
500  return clib_error_return (0, "No Segment List specified");
501 
502  rv = sr_mpls_policy_add (bsid, segments,
503  (is_spray ? SR_POLICY_TYPE_SPRAY :
504  SR_POLICY_TYPE_DEFAULT), weight);
505  }
506  else if (is_del)
507  rv = sr_mpls_policy_del (bsid);
508  else if (is_mod)
509  {
510  if (!operation)
511  return clib_error_return (0, "No SL modification specified");
512  if (operation != 1 && sl_index == (u32) ~ 0)
513  return clib_error_return (0, "No Segment List index specified");
514  if (operation == 1 && vec_len (segments) == 0)
515  return clib_error_return (0, "No Segment List specified");
516  if (operation == 3 && weight == (u32) ~ 0)
517  return clib_error_return (0, "No new weight for the SL specified");
518  rv = sr_mpls_policy_mod (bsid, operation, segments, sl_index, weight);
519  }
520  switch (rv)
521  {
522  case 0:
523  break;
524  case 1:
525  return 0;
526  case -12:
527  return clib_error_return (0,
528  "There is already a FIB entry for the BindingSID address.\n"
529  "The SR policy could not be created.");
530  case -21:
531  return clib_error_return (0,
532  "The selected SR policy only contains ONE segment list. "
533  "Please remove the SR policy instead");
534  case -22:
535  return clib_error_return (0,
536  "Could not delete the segment list. "
537  "It is not associated with that SR policy.");
538  case -23:
539  return clib_error_return (0,
540  "Could not delete the segment list. "
541  "It is not associated with that SR policy.");
542  case -32:
543  return clib_error_return (0,
544  "Could not modify the segment list. "
545  "The given SL is not associated with such SR policy.");
546  default:
547  return clib_error_return (0, "BUG: sr policy returns %d", rv);
548  }
549  return 0;
550 }
551 
552 /* *INDENT-OFF* */
553 VLIB_CLI_COMMAND(sr_mpls_policy_command, static)=
554 {
555  .path = "sr mpls policy",
556  .short_help = "sr mpls policy [add||del||mod] bsid 2999 "
557  "next 10 next 20 next 30 (weight 1) (spray)",
558  .long_help = "TBD.\n",
559  .function = sr_mpls_policy_command_fn,
560 };
561 /* *INDENT-ON* */
562 
563 /**
564  * @brief CLI to display onscreen all the SR MPLS policies
565  */
566 static clib_error_t *
568  vlib_cli_command_t * cmd)
569 {
571  mpls_sr_sl_t *segment_list = 0;
572  mpls_sr_policy_t *sr_policy = 0;
573  mpls_sr_policy_t **vec_policies = 0;
574  mpls_label_t *label;
575  u32 *sl_index;
576  u8 *s;
577  int i = 0;
578 
579  vlib_cli_output (vm, "SR MPLS policies:");
580 
581  /* *INDENT-OFF* */
582  pool_foreach(sr_policy, sm->sr_policies, {
583  vec_add1(vec_policies, sr_policy);
584  });
585  /* *INDENT-ON* */
586 
587  vec_foreach_index (i, vec_policies)
588  {
589  sr_policy = vec_policies[i];
590  vlib_cli_output (vm, "[%u].-\tBSID: %U",
591  (u32) (sr_policy - sm->sr_policies),
592  format_mpls_unicast_label, sr_policy->bsid);
593  switch (sr_policy->endpoint_type)
594  {
595  case SR_STEER_IPV6:
596  vlib_cli_output (vm, "\tEndpoint: %U", format_ip6_address,
597  &sr_policy->endpoint.ip6);
598  vlib_cli_output (vm, "\tColor: %u", sr_policy->color);
599  break;
600  case SR_STEER_IPV4:
601  vlib_cli_output (vm, "\tEndpoint: %U", format_ip4_address,
602  &sr_policy->endpoint.ip4);
603  vlib_cli_output (vm, "\tColor: %u", sr_policy->color);
604  break;
605  default:
606  vlib_cli_output (vm, "\tTE disabled");
607  }
608  vlib_cli_output (vm, "\tType: %s",
609  (sr_policy->type ==
610  SR_POLICY_TYPE_DEFAULT ? "Default" : "Spray"));
611  vlib_cli_output (vm, "\tSegment Lists:");
612  vec_foreach (sl_index, sr_policy->segments_lists)
613  {
614  s = NULL;
615  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
616  s = format (s, "\t[%u].- ", *sl_index);
617  s = format (s, "< ");
618  vec_foreach (label, segment_list->segments)
619  {
620  s = format (s, "%U, ", format_mpls_unicast_label, *label);
621  }
622  s = format (s, "\b\b > ");
623  vlib_cli_output (vm, " %s", s);
624  }
625  vlib_cli_output (vm, "-----------");
626  }
627  vec_free (vec_policies);
628  return 0;
629 }
630 
631 /* *INDENT-OFF* */
632 VLIB_CLI_COMMAND(show_sr_mpls_policies_command, static)=
633 {
634  .path = "show sr mpls policies",
635  .short_help = "show sr mpls policies",
637 };
638 /* *INDENT-ON* */
639 
640 /**
641  * @brief Update the Endpoint,Color tuple of an SR policy
642  *
643  * @param bsid is the bindingSID of the SR Policy
644  * @param endpoint represents the IP46 of the endpoint
645  * @param color represents the color (u32)
646  *
647  * To reset to NULL use ~0 as parameters.
648  *
649  * @return 0 if correct, else error
650  */
651 int
653  ip46_address_t * endpoint,
654  u8 endpoint_type, u32 color)
655 {
657  mpls_sr_policy_t *sr_policy = 0;
658  uword *endpoint_table, *p, *old_value;
659 
660  ip46_address_t any;
661  any.as_u64[0] = any.as_u64[1] = (u64) ~ 0;
662 
663  if (!sm->sr_policies_index_hash)
664  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
665 
666  p = hash_get (sm->sr_policies_index_hash, bsid);
667  if (p)
668  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
669  else
670  return -1;
671 
672  /* If previous Endpoint, color existed, remove (NH,C) and (ANY,C) */
673  if (sr_policy->endpoint_type)
674  {
675  endpoint_table =
676  mhash_get (&sm->sr_policies_c2e2eclabel_hash, &sr_policy->color);
677  if (!endpoint_table)
678  return -2;
679  old_value =
680  mhash_get ((mhash_t *) endpoint_table, &sr_policy->endpoint);
681 
682  /* CID 180995 This should never be NULL unless the two hash tables
683  * get out of sync */
684  ASSERT (old_value != NULL);
685 
686  fib_prefix_t pfx = { 0 };
688  pfx.fp_len = 21;
689  pfx.fp_label = (u32) * old_value;
690 
691  mpls_eos_bit_t eos;
693  {
694  pfx.fp_eos = eos;
696  &pfx,
699  NULL,
700  ~0, 0, 1, FIB_ROUTE_PATH_FLAG_NONE);
701  }
702 
703  old_value = mhash_get ((mhash_t *) endpoint_table, &any);
704  pfx.fp_label = (u32) * old_value;
705 
707  {
708  pfx.fp_eos = eos;
710  &pfx,
713  NULL,
714  ~0, 0, 1, FIB_ROUTE_PATH_FLAG_NONE);
715  }
716 
717  /* Release the lock on (NH, Color) and (ANY, Color) */
718  internal_label_unlock (sr_policy->endpoint, sr_policy->color);
719  internal_label_unlock (any, sr_policy->color);
720 
721  /* Reset the values on the SR policy */
722  sr_policy->endpoint_type = 0;
723  sr_policy->endpoint.as_u64[0] = sr_policy->endpoint.as_u64[1] =
724  (u64) ~ 0;
725  sr_policy->color = (u32) ~ 0;
726  }
727 
728  if (endpoint_type)
729  {
730  sr_policy->endpoint_type = endpoint_type;
731  sr_policy->endpoint.as_u64[0] = endpoint->as_u64[0];
732  sr_policy->endpoint.as_u64[1] = endpoint->as_u64[1];
733  sr_policy->color = color;
734 
735  u32 label = find_or_create_internal_label (*endpoint, color);
736  internal_label_lock (*endpoint, sr_policy->color);
737 
738  /* If FIB doesnt exist, create them */
739  if (sm->fib_table_EC == (u32) ~ 0)
740  {
743  "SR-MPLS Traffic Engineering (NextHop,Color)");
744 
747  }
748 
749  fib_prefix_t pfx = { 0 };
751  pfx.fp_len = 21;
752 
753  fib_route_path_t path = {
755  .frp_sw_if_index = ~0,
756  .frp_fib_index = 0,
757  .frp_weight = 1,
758  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
759  .frp_label_stack = 0
760  };
761  path.frp_local_label = sr_policy->bsid;
762 
763  //Add the entry to ANY,Color
764  u32 any_label = find_or_create_internal_label (any, color);
765  internal_label_lock (any, sr_policy->color);
766 
767  pfx.fp_eos = MPLS_EOS;
768  path.frp_eos = MPLS_EOS;
769 
770  fib_route_path_t *paths = NULL;
771  vec_add1 (paths, path);
772 
773  pfx.fp_label = label;
775  &pfx,
778 
779  pfx.fp_label = any_label;
781  &pfx,
784 
785  fib_mpls_label_t fml = {
787  };
788 
789  vec_add1 (path.frp_label_stack, fml);
790  pfx.fp_eos = MPLS_NON_EOS;
791  path.frp_eos = MPLS_NON_EOS;
792 
793  paths = NULL;
794  vec_add1 (paths, path);
795 
796  pfx.fp_label = label;
798  &pfx,
801 
802  pfx.fp_label = any_label;
804  &pfx,
807  }
808  return 0;
809 }
810 
811 /**
812  * @brief CLI to modify the Endpoint,Color of an SR policy
813  */
814 static clib_error_t *
816  vlib_cli_command_t * cmd)
817 {
818  ip46_address_t endpoint;
819  u32 color = (u32) ~ 0;
820  mpls_label_t bsid;
821  u8 endpoint_type = 0;
822  char clear = 0, color_set = 0, bsid_set = 0;
823 
824  memset (&endpoint, 0, sizeof (ip46_address_t));
825 
826  int rv;
828  {
829  if (!endpoint_type
830  && unformat (input, "endpoint %U", unformat_ip6_address,
831  &endpoint.ip6))
832  endpoint_type = SR_STEER_IPV6;
833  else if (!endpoint_type
834  && unformat (input, "endpoint %U", unformat_ip4_address,
835  &endpoint.ip4))
836  endpoint_type = SR_STEER_IPV4;
837  else if (!color_set && unformat (input, "color %u", &color))
838  color_set = 1;
839  else if (!bsid_set
840  && unformat (input, "bsid %U", unformat_mpls_unicast_label,
841  &bsid))
842  bsid_set = 1;
843  else if (!clear && unformat (input, "clear"))
844  clear = 1;
845  else
846  break;
847  }
848 
849  if (!bsid_set)
850  return clib_error_return (0, "No BSID specified");
851  if (!endpoint_type && !clear)
852  return clib_error_return (0, "No Endpoint specified");
853  if (!color_set && !clear)
854  return clib_error_return (0, "No Color set");
855 
856  /* In case its a cleanup */
857  if (clear)
858  {
859  ip6_address_set_zero (&endpoint.ip6);
860  color = (u32) ~ 0;
861  }
862  rv =
863  sr_mpls_policy_assign_endpoint_color (bsid, &endpoint, endpoint_type,
864  color);
865 
866  if (rv)
867  clib_error_return (0, "Error on Endpoint,Color");
868 
869  return 0;
870 }
871 
872 /* *INDENT-OFF* */
873 VLIB_CLI_COMMAND(cli_sr_mpls_policy_ec_command, static)=
874 {
875  .path = "sr mpls policy te",
876  .short_help = "sr mpls policy te bsid xxxxx endpoint x.x.x.x color 12341234",
878 };
879 /* *INDENT-ON* */
880 
881 /********************* SR MPLS Policy initialization ***********************/
882 /**
883  * @brief SR MPLS Policy initialization
884  */
885 clib_error_t *
887 {
889 
890  /* Init memory for sr policy keys (bsid <-> ip6_address_t) */
893  return 0;
894 }
895 
897 
898 /*
899  * fd.io coding-style-patch-verification: ON
900  *
901  * Local Variables: eval: (c-set-style "gnu") End:
902  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:197
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:482
#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:455
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:723
#define NULL
Definition: clib.h:55
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 *rpath)
Add n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:556
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:24
#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:523
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.
int i
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
dpo_proto_t frp_proto
The protocol of the address below.
Definition: fib_types.h:460
SR Segment List (SID list)
Definition: sr_mpls.h:52
Definition: fib_entry.h:284
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
unsigned char u8
Definition: types.h:56
unformat_function_t unformat_mpls_unicast_label
Definition: mpls.h:79
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.
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:600
Definition: fib_entry.h:283
format_function_t format_ip4_address
Definition: format.h:81
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:443
unformat_function_t unformat_ip4_address
Definition: format.h:76
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:156
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:1326
Aggregrate type for a prefix.
Definition: fib_types.h:188
#define clib_error_return(e, args...)
Definition: error.h:99
mpls_sr_sl_t * sid_lists
Definition: sr_mpls.h:109
unsigned int u32
Definition: types.h:88
mpls_sr_main_t sr_mpls_main
u16 fp_len
The mask length.
Definition: fib_types.h:192
Definition: fib_entry.h:275
#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:464
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:373
void fib_table_entry_path_remove2(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_route_path_t *rpath)
Remove n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:600
Configuration for each label value in the output-stack.
Definition: fib_types.h:410
fib_mpls_label_t * frp_label_stack
The outgoing MPLS label Stack.
Definition: fib_types.h:510
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:806
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:97
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 UNFORMAT_END_OF_INPUT
Definition: format.h:144
format_function_t format_ip6_address
Definition: format.h:99
vlib_main_t * vm
Definition: buffer.c:294
static void ip6_address_set_zero(ip6_address_t *a)
Definition: ip6_packet.h:249
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
mpls_label_t fml_value
The label value.
Definition: fib_types.h:415
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:214
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define FOR_EACH_MPLS_EOS_BIT(_eos)
Definition: packet.h:71
#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:299
#define ASSERT(truth)
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
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:682
#define SR_SEGMENT_LIST_WEIGHT_DEFAULT
Definition: sr_mpls.h:39
format_function_t format_mpls_unicast_label
Definition: mpls.h:69
mpls_label_t frp_local_label
The MPLS local Label to reursively resolve through.
Definition: fib_types.h:478
mhash_t sr_policies_c2e2eclabel_hash
SR TE.
Definition: sr_mpls.h:125
SRv6 and SR-MPLS.
Definition: fib_entry.h:58
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.
Special sources.
Definition: fib_entry.h:40
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.
u32 fib_table_EC
Definition: sr_mpls.h:127
u8 frp_weight
[un]equal cost path weight
Definition: fib_types.h:537
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:1134
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:681
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
mpls_eos_bit_t fp_eos
Definition: fib_types.h:215
u32 weight
Definition: sr_mpls.h:58
enum mpls_eos_bit_t_ mpls_eos_bit_t