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