FD.io VPP  v18.07-rc0-415-g6c78436
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 
65  pool_get (sm->sid_lists, segment_list);
66  memset (segment_list, 0, sizeof (*segment_list));
67 
68  vec_add1 (sr_policy->segments_lists, segment_list - sm->sid_lists);
69 
70  /* Fill in segment list */
71  segment_list->weight =
72  (weight != (u32) ~ 0 ? weight : SR_SEGMENT_LIST_WEIGHT_DEFAULT);
73  segment_list->segments = vec_dup (sl);
74 
75  mpls_eos_bit_t eos;
77  {
78  fib_route_path_t path = {
80  .frp_sw_if_index = ~0,
81  .frp_fib_index = 0,
82  .frp_weight = segment_list->weight,
83  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
84  .frp_label_stack = NULL,
85  .frp_local_label = sl[0],
86  };
87 
88  vec_add (path.frp_label_stack, sl + 1, vec_len (sl) - 1);
89 
90  fib_route_path_t *paths = NULL;
91  vec_add1 (paths, path);
92 
93  /* *INDENT-OFF* */
94  fib_prefix_t pfx = {
95  .fp_len = 21,
96  .fp_proto = FIB_PROTOCOL_MPLS,
97  .fp_label = sr_policy->bsid,
98  .fp_eos = eos,
99  .fp_payload_proto = DPO_PROTO_MPLS,
100  };
101  /* *INDENT-ON* */
102 
104  &pfx,
106  (sr_policy->type == SR_POLICY_TYPE_DEFAULT ?
108  FIB_ENTRY_FLAG_MULTICAST), paths);
109  vec_free (paths);
110  }
111 
112  return segment_list;
113 }
114 
115 /******************************* SR rewrite API *******************************/
116 /*
117  * Three functions for handling sr policies: -> sr_mpls_policy_add ->
118  * sr_mpls_policy_del -> sr_mpls_policy_mod All of them are API. CLI function
119  * on sr_policy_command_fn
120  */
121 
122 /**
123  * @brief Create a new SR policy
124  *
125  * @param bsid is the bindingSID of the SR Policy
126  * @param segments is a vector of MPLS labels composing the segment list
127  * @param behavior is the behavior of the SR policy. (default//spray)
128  * @param fib_table is the VRF where to install the FIB entry for the BSID
129  * @param weight is the weight of this specific SID list
130  *
131  * @return 0 if correct, else error
132  */
133 int
135  u8 behavior, u32 weight)
136 {
138  mpls_sr_policy_t *sr_policy = 0;
139  uword *p;
140 
141  if (!sm->sr_policies_index_hash)
142  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
143 
144  /* Search for existing keys (BSID) */
145  p = hash_get (sm->sr_policies_index_hash, bsid);
146  if (p)
147  {
148  /* Add SR policy that already exists; complain */
149  return -12;
150  }
151  /* Add an SR policy object */
152  pool_get (sm->sr_policies, sr_policy);
153  memset (sr_policy, 0, sizeof (*sr_policy));
154  sr_policy->bsid = bsid;
155  sr_policy->type = behavior;
156  sr_policy->endpoint_type = 0;
157  ip6_address_set_zero (&sr_policy->endpoint.ip6);
158  sr_policy->color = (u32) ~ 0;
159 
160  /* Copy the key */
161  hash_set (sm->sr_policies_index_hash, bsid, sr_policy - sm->sr_policies);
162 
163  /* Create a segment list and add the index to the SR policy */
164  create_sl (sr_policy, segments, weight);
165 
166  return 0;
167 }
168 
169 /**
170  * @brief Delete a SR policy
171  *
172  * @param bsid is the bindingSID of the SR Policy
173  * @param index is the index of the SR policy
174  *
175  * @return 0 if correct, else error
176  */
177 int
179 {
181  mpls_sr_policy_t *sr_policy = 0;
182  mpls_sr_sl_t *segment_list;
183  mpls_eos_bit_t eos;
184  u32 *sl_index;
185  uword *p;
186 
187  if (!sm->sr_policies_index_hash)
188  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
189 
190  p = hash_get (sm->sr_policies_index_hash, bsid);
191  if (p)
192  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
193  else
194  return -1;
195 
196  /* Clean SID Lists */
197  vec_foreach (sl_index, sr_policy->segments_lists)
198  {
199  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
200 
201  fib_route_path_t path = {
203  .frp_sw_if_index = ~0,
204  .frp_fib_index = 0,
205  .frp_weight = segment_list->weight,
206  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
207  .frp_local_label = segment_list->segments[0],
208  };
209 
210  vec_add (path.frp_label_stack, segment_list + 1,
211  vec_len (segment_list) - 1);
212 
213  fib_route_path_t *paths = NULL;
214  vec_add1 (paths, path);
215 
216  /* remove each of the MPLS routes */
218  {
219  /* *INDENT-OFF* */
220  fib_prefix_t pfx = {
221  .fp_len = 21,
222  .fp_proto = FIB_PROTOCOL_MPLS,
223  .fp_label = sr_policy->bsid,
224  .fp_eos = eos,
225  .fp_payload_proto = DPO_PROTO_MPLS,
226  };
227  /* *INDENT-ON* */
228 
230  }
231  vec_free (paths);
232  vec_free (segment_list->segments);
233  pool_put_index (sm->sid_lists, *sl_index);
234  }
235 
236  /* If there is still traces of TE, make sure locks are released */
237  if (sr_policy->endpoint_type != 0 && sr_policy->color != (u32) ~ 0)
238  {
240  }
241 
242  /* Remove SR policy entry */
243  hash_unset (sm->sr_policies_index_hash, sr_policy->bsid);
244  pool_put (sm->sr_policies, sr_policy);
245 
246  return 0;
247 }
248 
249 /**
250  * @brief Modify an existing SR policy
251  *
252  * The possible modifications are adding a new Segment List, modifying an
253  * existing Segment List (modify the weight only) and delete a given
254  * Segment List from the SR Policy.
255  *
256  * @param bsid is the bindingSID of the SR Policy
257  * @param fib_table is the VRF where to install the FIB entry for the BSID
258  * @param operation is the operation to perform (among the top ones)
259  * @param segments is a vector of IPv6 address composing the segment list
260  * @param sl_index is the index of the Segment List to modify/delete
261  * @param weight is the weight of the sid list. optional.
262  *
263  * @return 0 ok, >0 index of SL, <0 error
264  */
265 int
267  mpls_label_t * segments, u32 sl_index, u32 weight)
268 {
270  mpls_sr_policy_t *sr_policy = 0;
271  mpls_sr_sl_t *segment_list;
272  u32 *sl_index_iterate;
273  uword *p;
274 
275  if (!sm->sr_policies_index_hash)
276  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
277 
278  p = hash_get (sm->sr_policies_index_hash, bsid);
279  if (p)
280  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
281  else
282  return -1;
283 
284  if (operation == 1)
285  { /* Add SR List to an existing SR policy */
286  /* Create the new SL */
287  segment_list = create_sl (sr_policy, segments, weight);
288  return segment_list - sm->sid_lists;
289  }
290  else if (operation == 2)
291  { /* Delete SR List from an existing SR
292  * policy */
293  /* Check that currently there are more than one SID list */
294  if (vec_len (sr_policy->segments_lists) == 1)
295  return -21;
296 
297  /*
298  * Check that the SR list does exist and is assigned to the
299  * sr policy
300  */
301  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
302  if (*sl_index_iterate == sl_index)
303  break;
304 
305  if (*sl_index_iterate != sl_index)
306  return -22;
307 
308  /* Remove the lucky SR list that is being kicked out */
309  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
310 
311  mpls_eos_bit_t eos;
312  fib_route_path_t path = {
314  .frp_sw_if_index = ~0,
315  .frp_fib_index = 0,
316  .frp_weight = segment_list->weight,
317  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
318  .frp_local_label = segment_list->segments[0],
319  };
320 
321  vec_add (path.frp_label_stack, segment_list + 1,
322  vec_len (segment_list) - 1);
323 
324  fib_route_path_t *paths = NULL;
325  vec_add1 (paths, path);
326 
328  {
329  /* *INDENT-OFF* */
330  fib_prefix_t pfx = {
331  .fp_len = 21,
332  .fp_proto = FIB_PROTOCOL_MPLS,
333  .fp_label = sr_policy->bsid,
334  .fp_eos = eos,
335  .fp_payload_proto = DPO_PROTO_MPLS,
336  };
337  /* *INDENT-ON* */
338 
340  }
341 
342  vec_free (paths);
343  vec_free (segment_list->segments);
344  pool_put_index (sm->sid_lists, sl_index);
345  vec_del1 (sr_policy->segments_lists,
346  sl_index_iterate - sr_policy->segments_lists);
347  }
348  else if (operation == 3)
349  { /* Modify the weight of an existing
350  * SR List */
351  /* Find the corresponding SL */
352  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
353  if (*sl_index_iterate == sl_index)
354  break;
355 
356  if (*sl_index_iterate != sl_index)
357  return -32;
358 
359  /* Change the weight */
360  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
361 
362  /* Update LB */
363  mpls_eos_bit_t eos;
364  fib_route_path_t path = {
366  .frp_sw_if_index = ~0,
367  .frp_fib_index = 0,
368  .frp_weight = segment_list->weight,
369  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
370  .frp_local_label = segment_list->segments[0],
371  };
372 
373  vec_add (path.frp_label_stack, segment_list + 1,
374  vec_len (segment_list) - 1);
375 
376  fib_route_path_t *paths = NULL;
377  vec_add1 (paths, path);
378 
380  {
381  /* *INDENT-OFF* */
382  fib_prefix_t pfx = {
383  .fp_len = 21,
384  .fp_proto = FIB_PROTOCOL_MPLS,
385  .fp_label = sr_policy->bsid,
386  .fp_eos = eos,
387  .fp_payload_proto = DPO_PROTO_MPLS,
388  };
389  /* *INDENT-ON* */
390 
392  }
393 
394  segment_list->weight = weight;
395 
396  path.frp_weight = segment_list->weight;
397 
398  vec_free (paths);
399  paths = NULL;
400  vec_add1 (paths, path);
401 
403  {
404  /* *INDENT-OFF* */
405  fib_prefix_t pfx = {
406  .fp_len = 21,
407  .fp_proto = FIB_PROTOCOL_MPLS,
408  .fp_label = sr_policy->bsid,
409  .fp_eos = eos,
410  .fp_payload_proto = DPO_PROTO_MPLS,
411  };
412  /* *INDENT-ON* */
413 
415  &pfx,
417  (sr_policy->type ==
420  FIB_ENTRY_FLAG_MULTICAST), paths);
421  }
422  }
423  return 0;
424 }
425 
426 /**
427  * @brief CLI for 'sr mpls policies' command family
428  */
429 static clib_error_t *
431  vlib_cli_command_t * cmd)
432 {
433  int rv = -1;
434  char is_del = 0, is_add = 0, is_mod = 0;
435  char policy_set = 0;
436  mpls_label_t bsid, next_label;
437  u32 sl_index = (u32) ~ 0;
438  u32 weight = (u32) ~ 0;
439  mpls_label_t *segments = 0;
440  u8 operation = 0;
441  u8 is_spray = 0;
442 
444  {
445  if (!is_add && !is_mod && !is_del && unformat (input, "add"))
446  is_add = 1;
447  else if (!is_add && !is_mod && !is_del && unformat (input, "del"))
448  is_del = 1;
449  else if (!is_add && !is_mod && !is_del && unformat (input, "mod"))
450  is_mod = 1;
451  else if (!policy_set
452  && unformat (input, "bsid %U", unformat_mpls_unicast_label,
453  &bsid))
454  policy_set = 1;
455  else if (unformat (input, "weight %d", &weight));
456  else if (unformat
457  (input, "next %U", unformat_mpls_unicast_label, &next_label))
458  {
459  vec_add (segments, &next_label, 1);
460  }
461  else if (unformat (input, "add sl"))
462  operation = 1;
463  else if (unformat (input, "del sl index %d", &sl_index))
464  operation = 2;
465  else if (unformat (input, "mod sl index %d", &sl_index))
466  operation = 3;
467  else if (unformat (input, "spray"))
468  is_spray = 1;
469  else
470  break;
471  }
472 
473  if (!is_add && !is_mod && !is_del)
474  return clib_error_return (0, "Incorrect CLI");
475 
476  if (!policy_set)
477  return clib_error_return (0, "No SR policy BSID or index specified");
478 
479  if (is_add)
480  {
481  if (vec_len (segments) == 0)
482  return clib_error_return (0, "No Segment List specified");
483 
484  rv = sr_mpls_policy_add (bsid, segments,
485  (is_spray ? SR_POLICY_TYPE_SPRAY :
486  SR_POLICY_TYPE_DEFAULT), weight);
487  }
488  else if (is_del)
489  rv = sr_mpls_policy_del (bsid);
490  else if (is_mod)
491  {
492  if (!operation)
493  return clib_error_return (0, "No SL modification specified");
494  if (operation != 1 && sl_index == (u32) ~ 0)
495  return clib_error_return (0, "No Segment List index specified");
496  if (operation == 1 && vec_len (segments) == 0)
497  return clib_error_return (0, "No Segment List specified");
498  if (operation == 3 && weight == (u32) ~ 0)
499  return clib_error_return (0, "No new weight for the SL specified");
500  rv = sr_mpls_policy_mod (bsid, operation, segments, sl_index, weight);
501  }
502  switch (rv)
503  {
504  case 0:
505  break;
506  case 1:
507  return 0;
508  case -12:
509  return clib_error_return (0,
510  "There is already a FIB entry for the BindingSID address.\n"
511  "The SR policy could not be created.");
512  case -21:
513  return clib_error_return (0,
514  "The selected SR policy only contains ONE segment list. "
515  "Please remove the SR policy instead");
516  case -22:
517  return clib_error_return (0,
518  "Could not delete the segment list. "
519  "It is not associated with that SR policy.");
520  case -23:
521  return clib_error_return (0,
522  "Could not delete the segment list. "
523  "It is not associated with that SR policy.");
524  case -32:
525  return clib_error_return (0,
526  "Could not modify the segment list. "
527  "The given SL is not associated with such SR policy.");
528  default:
529  return clib_error_return (0, "BUG: sr policy returns %d", rv);
530  }
531  return 0;
532 }
533 
534 /* *INDENT-OFF* */
535 VLIB_CLI_COMMAND(sr_mpls_policy_command, static)=
536 {
537  .path = "sr mpls policy",
538  .short_help = "sr mpls policy [add||del||mod] bsid 2999 "
539  "next 10 next 20 next 30 (weight 1) (spray)",
540  .long_help = "TBD.\n",
541  .function = sr_mpls_policy_command_fn,
542 };
543 /* *INDENT-ON* */
544 
545 /**
546  * @brief CLI to display onscreen all the SR MPLS policies
547  */
548 static clib_error_t *
550  vlib_cli_command_t * cmd)
551 {
553  mpls_sr_sl_t *segment_list = 0;
554  mpls_sr_policy_t *sr_policy = 0;
555  mpls_sr_policy_t **vec_policies = 0;
556  mpls_label_t *label;
557  u32 *sl_index;
558  u8 *s;
559  int i = 0;
560 
561  vlib_cli_output (vm, "SR MPLS policies:");
562 
563  /* *INDENT-OFF* */
564  pool_foreach(sr_policy, sm->sr_policies, {
565  vec_add1(vec_policies, sr_policy);
566  });
567  /* *INDENT-ON* */
568 
569  vec_foreach_index (i, vec_policies)
570  {
571  sr_policy = vec_policies[i];
572  vlib_cli_output (vm, "[%u].-\tBSID: %U",
573  (u32) (sr_policy - sm->sr_policies),
574  format_mpls_unicast_label, sr_policy->bsid);
575  switch (sr_policy->endpoint_type)
576  {
577  case SR_STEER_IPV6:
578  vlib_cli_output (vm, "\tEndpoint: %U", format_ip6_address,
579  &sr_policy->endpoint.ip6);
580  vlib_cli_output (vm, "\tColor: %u", sr_policy->color);
581  break;
582  case SR_STEER_IPV4:
583  vlib_cli_output (vm, "\tEndpoint: %U", format_ip4_address,
584  &sr_policy->endpoint.ip4);
585  vlib_cli_output (vm, "\tColor: %u", sr_policy->color);
586  break;
587  default:
588  vlib_cli_output (vm, "\tTE disabled");
589  }
590  vlib_cli_output (vm, "\tType: %s",
591  (sr_policy->type ==
592  SR_POLICY_TYPE_DEFAULT ? "Default" : "Spray"));
593  vlib_cli_output (vm, "\tSegment Lists:");
594  vec_foreach (sl_index, sr_policy->segments_lists)
595  {
596  s = NULL;
597  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
598  s = format (s, "\t[%u].- ", *sl_index);
599  s = format (s, "< ");
600  vec_foreach (label, segment_list->segments)
601  {
602  s = format (s, "%U, ", format_mpls_unicast_label, *label);
603  }
604  s = format (s, "\b\b > ");
605  vlib_cli_output (vm, " %s", s);
606  }
607  vlib_cli_output (vm, "-----------");
608  }
609  vec_free (vec_policies);
610  return 0;
611 }
612 
613 /* *INDENT-OFF* */
614 VLIB_CLI_COMMAND(show_sr_mpls_policies_command, static)=
615 {
616  .path = "show sr mpls policies",
617  .short_help = "show sr mpls policies",
619 };
620 /* *INDENT-ON* */
621 
622 /**
623  * @brief Update the Endpoint,Color tuple of an SR policy
624  *
625  * @param bsid is the bindingSID of the SR Policy
626  * @param endpoint represents the IP46 of the endpoint
627  * @param color represents the color (u32)
628  *
629  * To reset to NULL use ~0 as parameters.
630  *
631  * @return 0 if correct, else error
632  */
633 int
635  ip46_address_t * endpoint,
636  u8 endpoint_type, u32 color)
637 {
639  mpls_sr_policy_t *sr_policy = 0;
640  uword *endpoint_table, *p, *old_value;
641 
642  ip46_address_t any;
643  any.as_u64[0] = any.as_u64[1] = (u64) ~ 0;
644 
645  if (!sm->sr_policies_index_hash)
646  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
647 
648  p = hash_get (sm->sr_policies_index_hash, bsid);
649  if (p)
650  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
651  else
652  return -1;
653 
654  /* If previous Endpoint, color existed, remove (NH,C) and (ANY,C) */
655  if (sr_policy->endpoint_type)
656  {
657  endpoint_table =
658  mhash_get (&sm->sr_policies_c2e2eclabel_hash, &sr_policy->color);
659  if (!endpoint_table)
660  return -2;
661  old_value =
662  mhash_get ((mhash_t *) endpoint_table, &sr_policy->endpoint);
663 
664  /* CID 180995 This should never be NULL unless the two hash tables
665  * get out of sync */
666  ASSERT (old_value != NULL);
667 
668  fib_prefix_t pfx = { 0 };
670  pfx.fp_len = 21;
671  pfx.fp_label = (u32) * old_value;
672 
673  mpls_eos_bit_t eos;
675  {
676  pfx.fp_eos = eos;
678  &pfx,
681  NULL,
682  ~0, 0, 1, FIB_ROUTE_PATH_FLAG_NONE);
683  }
684 
685  old_value = mhash_get ((mhash_t *) endpoint_table, &any);
686  pfx.fp_label = (u32) * old_value;
687 
689  {
690  pfx.fp_eos = eos;
692  &pfx,
695  NULL,
696  ~0, 0, 1, FIB_ROUTE_PATH_FLAG_NONE);
697  }
698 
699  /* Release the lock on (NH, Color) and (ANY, Color) */
700  internal_label_unlock (sr_policy->endpoint, sr_policy->color);
701  internal_label_unlock (any, sr_policy->color);
702 
703  /* Reset the values on the SR policy */
704  sr_policy->endpoint_type = 0;
705  sr_policy->endpoint.as_u64[0] = sr_policy->endpoint.as_u64[1] =
706  (u64) ~ 0;
707  sr_policy->color = (u32) ~ 0;
708  }
709 
710  if (endpoint_type)
711  {
712  sr_policy->endpoint_type = endpoint_type;
713  sr_policy->endpoint.as_u64[0] = endpoint->as_u64[0];
714  sr_policy->endpoint.as_u64[1] = endpoint->as_u64[1];
715  sr_policy->color = color;
716 
717  u32 label = find_or_create_internal_label (*endpoint, color);
718  internal_label_lock (*endpoint, sr_policy->color);
719 
720  /* If FIB doesnt exist, create them */
721  if (sm->fib_table_EC == (u32) ~ 0)
722  {
725  "SR-MPLS Traffic Engineering (NextHop,Color)");
726 
729  }
730 
731  fib_prefix_t pfx = { 0 };
733  pfx.fp_len = 21;
734 
735  fib_route_path_t path = {
737  .frp_sw_if_index = ~0,
738  .frp_fib_index = 0,
739  .frp_weight = 1,
740  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
741  .frp_label_stack = 0
742  };
743  path.frp_local_label = sr_policy->bsid;
744 
745  //Add the entry to ANY,Color
746  u32 any_label = find_or_create_internal_label (any, color);
747  internal_label_lock (any, sr_policy->color);
748 
749  pfx.fp_eos = MPLS_EOS;
750  path.frp_eos = MPLS_EOS;
751 
752  fib_route_path_t *paths = NULL;
753  vec_add1 (paths, path);
754 
755  pfx.fp_label = label;
757  &pfx,
760 
761  pfx.fp_label = any_label;
763  &pfx,
766 
767  fib_mpls_label_t fml = {
769  };
770 
771  vec_add1 (path.frp_label_stack, fml);
772  pfx.fp_eos = MPLS_NON_EOS;
773  path.frp_eos = MPLS_NON_EOS;
774 
775  paths = NULL;
776  vec_add1 (paths, path);
777 
778  pfx.fp_label = label;
780  &pfx,
783 
784  pfx.fp_label = any_label;
786  &pfx,
789  }
790  return 0;
791 }
792 
793 /**
794  * @brief CLI to modify the Endpoint,Color of an SR policy
795  */
796 static clib_error_t *
798  vlib_cli_command_t * cmd)
799 {
800  ip46_address_t endpoint;
801  u32 color = (u32) ~ 0;
802  mpls_label_t bsid;
803  u8 endpoint_type = 0;
804  char clear = 0, color_set = 0, bsid_set = 0;
805 
806  memset (&endpoint, 0, sizeof (ip46_address_t));
807 
808  int rv;
810  {
811  if (!endpoint_type
812  && unformat (input, "endpoint %U", unformat_ip6_address,
813  &endpoint.ip6))
814  endpoint_type = SR_STEER_IPV6;
815  else if (!endpoint_type
816  && unformat (input, "endpoint %U", unformat_ip4_address,
817  &endpoint.ip4))
818  endpoint_type = SR_STEER_IPV4;
819  else if (!color_set && unformat (input, "color %u", &color))
820  color_set = 1;
821  else if (!bsid_set
822  && unformat (input, "bsid %U", unformat_mpls_unicast_label,
823  &bsid))
824  bsid_set = 1;
825  else if (!clear && unformat (input, "clear"))
826  clear = 1;
827  else
828  break;
829  }
830 
831  if (!bsid_set)
832  return clib_error_return (0, "No BSID specified");
833  if (!endpoint_type && !clear)
834  return clib_error_return (0, "No Endpoint specified");
835  if (!color_set && !clear)
836  return clib_error_return (0, "No Color set");
837 
838  /* In case its a cleanup */
839  if (clear)
840  {
841  ip6_address_set_zero (&endpoint.ip6);
842  color = (u32) ~ 0;
843  }
844  rv =
845  sr_mpls_policy_assign_endpoint_color (bsid, &endpoint, endpoint_type,
846  color);
847 
848  if (rv)
849  clib_error_return (0, "Error on Endpoint,Color");
850 
851  return 0;
852 }
853 
854 /* *INDENT-OFF* */
855 VLIB_CLI_COMMAND(cli_sr_mpls_policy_ec_command, static)=
856 {
857  .path = "sr mpls policy te",
858  .short_help = "sr mpls policy te bsid xxxxx endpoint x.x.x.x color 12341234",
860 };
861 /* *INDENT-ON* */
862 
863 /********************* SR MPLS Policy initialization ***********************/
864 /**
865  * @brief SR MPLS Policy initialization
866  */
867 clib_error_t *
869 {
871 
872  /* Init memory for sr policy keys (bsid <-> ip6_address_t) */
875  return 0;
876 }
877 
879 
880 /*
881  * fd.io coding-style-patch-verification: ON
882  *
883  * Local Variables: eval: (c-set-style "gnu") End:
884  */
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:279
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:227
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:278
format_function_t format_ip4_address
Definition: format.h:81
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:440
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:270
#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:461
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:273
#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:143
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:296
#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:169
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