FD.io VPP  v17.07-30-g839fa73
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.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /**
19  * @file
20  * @brief SR MPLS policy creation and application
21  *
22  * Create an SR policy.
23  * An SR policy can be either of 'default' type or 'spray' type
24  * An SR policy has attached a list of SID lists.
25  * In case the SR policy is a default one it will load balance among them.
26  * An SR policy has associated a BindingSID.
27  * In case any packet arrives with MPLS_label == BindingSID then the SR policy
28  * associated to such bindingSID will be applied to such packet.
29  *
30  */
31 
32 #include <vlib/vlib.h>
33 #include <vnet/vnet.h>
34 #include <vnet/srmpls/sr.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 
41 #include <vppinfra/error.h>
42 #include <vppinfra/elog.h>
43 
45 
46 /*************************** SR LB helper functions **************************/
47 /**
48  * @brief Creates a Segment List and adds it to an SR policy
49  *
50  * Creates a Segment List and adds it to the SR policy. Notice that the SL are
51  * not necessarily unique. Hence there might be two Segment List within the
52  * same SR Policy with exactly the same segments and same weight.
53  *
54  * @param sr_policy is the SR policy where the SL will be added
55  * @param sl is a vector of IPv6 addresses composing the Segment List
56  * @param weight is the weight of the SegmentList (for load-balancing purposes)
57  * @param is_encap represents the mode (SRH insertion vs Encapsulation)
58  *
59  * @return pointer to the just created segment list
60  */
61 static inline mpls_sr_sl_t *
62 create_sl (mpls_sr_policy_t * sr_policy, mpls_label_t * sl, u32 weight)
63 {
65  mpls_sr_sl_t *segment_list;
66 
67  pool_get (sm->sid_lists, segment_list);
68  memset (segment_list, 0, sizeof (*segment_list));
69 
70  vec_add1 (sr_policy->segments_lists, segment_list - sm->sid_lists);
71 
72  /* Fill in segment list */
73  segment_list->weight =
74  (weight != (u32) ~ 0 ? weight : SR_SEGMENT_LIST_WEIGHT_DEFAULT);
75  segment_list->segments = vec_dup (sl);
76 
77  fib_route_path_t path = {
79  .frp_sw_if_index = ~0,
80  .frp_fib_index = 0,
81  .frp_weight = segment_list->weight,
82  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
83  .frp_label_stack = NULL,
84  .frp_local_label = sl[0],
85  };
86 
87  vec_add (path.frp_label_stack, sl + 1, vec_len (sl) - 1);
88 
89  fib_route_path_t *paths = NULL;
90  vec_add1 (paths, path);
91 
92  mpls_eos_bit_t eos;
94  {
95  /* *INDENT-OFF* */
96  fib_prefix_t pfx = {
97  .fp_len = 21,
98  .fp_proto = FIB_PROTOCOL_MPLS,
99  .fp_label = sr_policy->bsid,
100  .fp_eos = eos,
101  .fp_payload_proto = DPO_PROTO_MPLS,
102  };
103  /* *INDENT-ON* */
104 
106  &pfx,
108  (sr_policy->type == SR_POLICY_TYPE_DEFAULT ?
110  FIB_ENTRY_FLAG_MULTICAST), paths);
111  }
112 
113  vec_free (paths);
114 
115  return segment_list;
116 }
117 
118 /******************************* SR rewrite API *******************************/
119 /* Three functions for handling sr policies:
120  * -> sr_mpls_policy_add
121  * -> sr_mpls_policy_del
122  * -> sr_mpls_policy_mod
123  * All of them are API. CLI function on sr_policy_command_fn */
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  /* 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 
152  /* Add an SR policy object */
153  pool_get (sm->sr_policies, sr_policy);
154  memset (sr_policy, 0, sizeof (*sr_policy));
155  sr_policy->bsid = bsid;
156  sr_policy->type = behavior;
157 
158  /* Copy the key */
159  hash_set (sm->sr_policies_index_hash, bsid, sr_policy - sm->sr_policies);
160 
161  /* Create a segment list and add the index to the SR policy */
162  create_sl (sr_policy, segments, weight);
163 
164  return 0;
165 }
166 
167 /**
168  * @brief Delete a SR policy
169  *
170  * @param bsid is the bindingSID of the SR Policy
171  * @param index is the index of the SR policy
172  *
173  * @return 0 if correct, else error
174  */
175 int
177 {
179  mpls_sr_policy_t *sr_policy = 0;
180  mpls_sr_sl_t *segment_list;
181  mpls_eos_bit_t eos;
182  u32 *sl_index;
183  uword *p;
184 
185  if (bsid)
186  {
187  p = hash_get (sm->sr_policies_index_hash, bsid);
188  if (p)
189  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
190  else
191  return -1;
192  }
193  else
194  {
195  sr_policy = pool_elt_at_index (sm->sr_policies, index);
196  if (!sr_policy)
197  return -1;
198  }
199 
200  /* Clean SID Lists */
201  vec_foreach (sl_index, sr_policy->segments_lists)
202  {
203  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
204 
205  fib_route_path_t path = {
207  .frp_sw_if_index = ~0,
208  .frp_fib_index = 0,
209  .frp_weight = segment_list->weight,
210  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
211  .frp_local_label = segment_list->segments[0],
212  };
213 
214  fib_route_path_t *paths = NULL;
215  vec_add1 (paths, path);
216 
217  /* remove each of the MPLS routes */
219  {
220  /* *INDENT-OFF* */
221  fib_prefix_t pfx = {
222  .fp_len = 21,
223  .fp_proto = FIB_PROTOCOL_MPLS,
224  .fp_label = sr_policy->bsid,
225  .fp_eos = eos,
226  .fp_payload_proto = DPO_PROTO_MPLS,
227  };
228  /* *INDENT-ON* */
229 
231  }
232  vec_free (paths);
233  vec_free (segment_list->segments);
234  pool_put_index (sm->sid_lists, *sl_index);
235  }
236 
237  /* Remove SR policy entry */
238  hash_unset (sm->sr_policies_index_hash, sr_policy->bsid);
239  pool_put (sm->sr_policies, sr_policy);
240 
241  return 0;
242 }
243 
244 /**
245  * @brief Modify an existing SR policy
246  *
247  * The possible modifications are adding a new Segment List, modifying an
248  * existing Segment List (modify the weight only) and delete a given
249  * Segment List from the SR Policy.
250  *
251  * @param bsid is the bindingSID of the SR Policy
252  * @param index is the index of the SR policy
253  * @param fib_table is the VRF where to install the FIB entry for the BSID
254  * @param operation is the operation to perform (among the top ones)
255  * @param segments is a vector of IPv6 address composing the segment list
256  * @param sl_index is the index of the Segment List to modify/delete
257  * @param weight is the weight of the sid list. optional.
258  *
259  * @return 0 if correct, else error
260  */
261 int
262 sr_mpls_policy_mod (mpls_label_t bsid, u32 index, u8 operation,
263  mpls_label_t * segments, u32 sl_index, u32 weight)
264 {
266  mpls_sr_policy_t *sr_policy = 0;
267  mpls_sr_sl_t *segment_list;
268  u32 *sl_index_iterate;
269  uword *p;
270 
271  if (bsid)
272  {
273  p = hash_get (sm->sr_policies_index_hash, bsid);
274  if (p)
275  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
276  else
277  return -1;
278  }
279  else
280  {
281  sr_policy = pool_elt_at_index (sm->sr_policies, index);
282  if (!sr_policy)
283  return -1;
284  }
285 
286  if (operation == 1) /* Add SR List to an existing SR policy */
287  {
288  /* Create the new SL */
289  segment_list = create_sl (sr_policy, segments, weight);
290 
291  }
292  else if (operation == 2) /* Delete SR List from an existing SR policy */
293  {
294  /* Check that currently there are more than one SID list */
295  if (vec_len (sr_policy->segments_lists) == 1)
296  return -21;
297 
298  /* Check that the SR list does exist and is assigned to the sr policy */
299  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
300  if (*sl_index_iterate == sl_index)
301  break;
302 
303  if (*sl_index_iterate != sl_index)
304  return -22;
305 
306  /* Remove the lucky SR list that is being kicked out */
307  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
308 
309  mpls_eos_bit_t eos;
310  fib_route_path_t path = {
312  .frp_sw_if_index = ~0,
313  .frp_fib_index = 0,
314  .frp_weight = segment_list->weight,
315  .frp_flags = FIB_ROUTE_PATH_FLAG_NONE,
316  .frp_local_label = segment_list->segments[0],
317  };
318 
319  fib_route_path_t *paths = NULL;
320  vec_add1 (paths, path);
321 
323  {
324  /* *INDENT-OFF* */
325  fib_prefix_t pfx = {
326  .fp_len = 21,
327  .fp_proto = FIB_PROTOCOL_MPLS,
328  .fp_label = sr_policy->bsid,
329  .fp_eos = eos,
330  .fp_payload_proto = DPO_PROTO_MPLS,
331  };
332  /* *INDENT-ON* */
333 
335  }
336 
337  vec_free (paths);
338  vec_free (segment_list->segments);
339  pool_put_index (sm->sid_lists, sl_index);
340  vec_del1 (sr_policy->segments_lists,
341  sl_index_iterate - sr_policy->segments_lists);
342  }
343  else if (operation == 3) /* Modify the weight of an existing SR List */
344  {
345  /* Find the corresponding SL */
346  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
347  if (*sl_index_iterate == sl_index)
348  break;
349 
350  if (*sl_index_iterate != sl_index)
351  return -32;
352 
353  /* Change the weight */
354  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
355  segment_list->weight = weight;
356 
357  /* Update LB */
358  //FIXME
359  }
360  return 0;
361 }
362 
363 /**
364  * @brief CLI for 'sr mpls policies' command family
365  */
366 static clib_error_t *
368  vlib_cli_command_t * cmd)
369 {
370  int rv = -1;
371  char is_del = 0, is_add = 0, is_mod = 0;
372  char policy_set = 0;
373  mpls_label_t bsid, next_label;
374  u32 sr_policy_index = (u32) ~ 0, sl_index = (u32) ~ 0;
375  u32 weight = (u32) ~ 0;
376  mpls_label_t *segments = 0;
377  u8 operation = 0;
378  u8 is_spray = 0;
379 
381  {
382  if (!is_add && !is_mod && !is_del && unformat (input, "add"))
383  is_add = 1;
384  else if (!is_add && !is_mod && !is_del && unformat (input, "del"))
385  is_del = 1;
386  else if (!is_add && !is_mod && !is_del && unformat (input, "mod"))
387  is_mod = 1;
388  else if (!policy_set
389  && unformat (input, "bsid %U", unformat_mpls_unicast_label,
390  &bsid))
391  policy_set = 1;
392  else if (!is_add && !policy_set
393  && unformat (input, "index %d", &sr_policy_index))
394  policy_set = 1;
395  else if (unformat (input, "weight %d", &weight));
396  else
397  if (unformat
398  (input, "next %U", unformat_mpls_unicast_label, &next_label))
399  {
400  vec_add (segments, &next_label, 1);
401  }
402  else if (unformat (input, "add sl"))
403  operation = 1;
404  else if (unformat (input, "del sl index %d", &sl_index))
405  operation = 2;
406  else if (unformat (input, "mod sl index %d", &sl_index))
407  operation = 3;
408  else if (unformat (input, "spray"))
409  is_spray = 1;
410  else
411  break;
412  }
413 
414  if (!is_add && !is_mod && !is_del)
415  return clib_error_return (0, "Incorrect CLI");
416 
417  if (!policy_set)
418  return clib_error_return (0, "No SR policy BSID or index specified");
419 
420  if (is_add)
421  {
422  if (vec_len (segments) == 0)
423  return clib_error_return (0, "No Segment List specified");
424 
425  rv = sr_mpls_policy_add (bsid, segments,
426  (is_spray ? SR_POLICY_TYPE_SPRAY :
427  SR_POLICY_TYPE_DEFAULT), weight);
428  }
429  else if (is_del)
430  rv =
431  sr_mpls_policy_del ((sr_policy_index != (u32) ~ 0 ? (u32) ~ 0 : bsid),
432  sr_policy_index);
433  else if (is_mod)
434  {
435  if (!operation)
436  return clib_error_return (0, "No SL modification specified");
437  if (operation != 1 && sl_index == (u32) ~ 0)
438  return clib_error_return (0, "No Segment List index specified");
439  if (operation == 1 && vec_len (segments) == 0)
440  return clib_error_return (0, "No Segment List specified");
441  if (operation == 3 && weight == (u32) ~ 0)
442  return clib_error_return (0, "No new weight for the SL specified");
443  rv =
444  sr_mpls_policy_mod ((sr_policy_index != (u32) ~ 0 ? (u32) ~ 0 : bsid),
445  sr_policy_index, operation, segments,
446  sl_index, weight);
447  }
448 
449  switch (rv)
450  {
451  case 0:
452  break;
453  case 1:
454  return 0;
455  case -12:
456  return clib_error_return (0,
457  "There is already a FIB entry for the BindingSID address.\n"
458  "The SR policy could not be created.");
459  case -21:
460  return clib_error_return (0,
461  "The selected SR policy only contains ONE segment list. "
462  "Please remove the SR policy instead");
463  case -22:
464  return clib_error_return (0,
465  "Could not delete the segment list. "
466  "It is not associated with that SR policy.");
467  case -32:
468  return clib_error_return (0,
469  "Could not modify the segment list. "
470  "The given SL is not associated with such SR policy.");
471  default:
472  return clib_error_return (0, "BUG: sr policy returns %d", rv);
473  }
474  return 0;
475 }
476 
477 /* *INDENT-OFF* */
478 VLIB_CLI_COMMAND (sr_mpls_policy_command, static) = {
479  .path = "sr mpls policy",
480  .short_help = "sr mpls policy [add||del||mod] bsid 2999 "
481  "next 10 next 20 next 30 (weight 1) (spray)",
482  .long_help = "TBD.\n",
483  .function = sr_mpls_policy_command_fn,
484 };
485 /* *INDENT-ON* */
486 
487 /**
488  * @brief CLI to display onscreen all the SR MPLS policies
489  */
490 static clib_error_t *
492  vlib_cli_command_t * cmd)
493 {
495  mpls_sr_sl_t *segment_list = 0;
496  mpls_sr_policy_t *sr_policy = 0;
497  mpls_sr_policy_t **vec_policies = 0;
498  mpls_label_t *label;
499  u32 *sl_index;
500  u8 *s;
501  int i = 0;
502 
503  vlib_cli_output (vm, "SR MPLS policies:");
504 
505  /* *INDENT-OFF* */
506  pool_foreach (sr_policy, sm->sr_policies, {vec_add1 (vec_policies, sr_policy); } );
507  /* *INDENT-ON* */
508 
509  vec_foreach_index (i, vec_policies)
510  {
511  sr_policy = vec_policies[i];
512  vlib_cli_output (vm, "[%u].-\tBSID: %U",
513  (u32) (sr_policy - sm->sr_policies),
514  format_mpls_unicast_label, sr_policy->bsid);
515  vlib_cli_output (vm, "\tType: %s",
516  (sr_policy->type ==
517  SR_POLICY_TYPE_DEFAULT ? "Default" : "Spray"));
518  vlib_cli_output (vm, "\tSegment Lists:");
519  vec_foreach (sl_index, sr_policy->segments_lists)
520  {
521  s = NULL;
522  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
523  s = format (s, "\t[%u].- ", *sl_index);
524  s = format (s, "< ");
525  vec_foreach (label, segment_list->segments)
526  {
527  s = format (s, "%U, ", format_mpls_unicast_label, *label);
528  }
529  s = format (s, "\b\b > ");
530  vlib_cli_output (vm, " %s", s);
531  }
532  vlib_cli_output (vm, "-----------");
533  }
534  vec_free (vec_policies);
535  return 0;
536 }
537 
538 /* *INDENT-OFF* */
539 VLIB_CLI_COMMAND (show_sr_mpls_policies_command, static) = {
540  .path = "show sr mpls policies",
541  .short_help = "show sr mpls policies",
543 };
544 /* *INDENT-ON* */
545 
546 /********************* SR MPLS Policy initialization ***********************/
547 /**
548  * @brief SR MPLS Policy initialization
549  */
550 clib_error_t *
552 {
554 
555  /* Init memory for sr policy keys (bsid <-> ip6_address_t) */
556  sm->sr_policies_index_hash = hash_create (0, sizeof (mpls_label_t));
557 
558  return 0;
559 }
560 
562 
563 /*
564 * fd.io coding-style-patch-verification: ON
565 *
566 * Local Variables:
567 * eval: (c-set-style "gnu")
568 * End:
569 */
#define SR_POLICY_TYPE_DEFAULT
Definition: sr.h:37
fib_protocol_t frp_proto
The protocol of the address below.
Definition: fib_types.h:341
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 hash_set(h, key, value)
Definition: hash.h:254
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
#define hash_unset(h, key)
Definition: hash.h:260
A representation of a path as described by a route producer.
Definition: fib_types.h:336
#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:538
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:24
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
SR Segment List (SID list)
Definition: sr.h:48
Definition: fib_entry.h:241
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
unformat_function_t unformat_mpls_unicast_label
Definition: mpls.h:83
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:599
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
mpls_label_t * frp_label_stack
The outgoing MPLS label Stack.
Definition: fib_types.h:391
#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.
Aggregrate type for a prefix.
Definition: fib_types.h:160
#define clib_error_return(e, args...)
Definition: error.h:99
mpls_sr_sl_t * sid_lists
SR SID lists.
Definition: sr.h:103
#define SR_POLICY_TYPE_SPRAY
Definition: sr.h:38
mpls_sr_main_t sr_mpls_main
u16 fp_len
The mask length.
Definition: fib_types.h:164
Definition: fib_entry.h:233
#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:397
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:374
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:582
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:805
mpls_label_t bsid
BindingSID (key)
Definition: sr.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.
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
mpls_sr_policy_t * sr_policies
SR MPLS policies.
Definition: sr.h:108
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.
#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:658
Segment Routing main datastructure.
Definition: sr.h:98
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:255
unsigned int u32
Definition: types.h:88
uword * sr_policies_index_hash
Hash table mapping BindingSID to SR MPLS policy.
Definition: sr.h:113
format_function_t format_mpls_unicast_label
Definition: mpls.h:71
u64 uword
Definition: types.h:112
SRv6 and SR-MPLS.
Definition: fib_entry.h:54
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define SR_SEGMENT_LIST_WEIGHT_DEFAULT
Definition: sr.h:40
unsigned char u8
Definition: types.h:56
u8 type
Type (default is 0)
Definition: sr.h:68
Segment Routing MPLS data structures definitions.
mpls_label_t * segments
SIDs (key)
Definition: sr.h:53
u32 * segments_lists
Pool of SID lists indexes.
Definition: sr.h:64
#define vec_foreach(var, vec)
Vector iterator.
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
int sr_mpls_policy_mod(mpls_label_t bsid, u32 index, u8 operation, mpls_label_t *segments, u32 sl_index, u32 weight)
Modify an existing SR policy.
int sr_mpls_policy_del(mpls_label_t bsid, u32 index)
Delete a SR policy.
u32 weight
SID list weight (wECMP / UCMP)
Definition: sr.h:58
enum mpls_eos_bit_t_ mpls_eos_bit_t