FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
sr_policy_rewrite.c
Go to the documentation of this file.
1 /*
2  * sr_policy_rewrite.c: ipv6 sr policy creation
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 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 IPv6 DA == BindingSID then the SR policy
28  * associated to such bindingSID will be applied to such packet.
29  *
30  * SR policies can be applied either by using IPv6 encapsulation or
31  * SRH insertion. Both methods can be found on this file.
32  *
33  * Traffic input usually is IPv6 packets. However it is possible to have
34  * IPv4 packets or L2 frames. (that are encapsulated into IPv6 with SRH)
35  *
36  * This file provides the appropiates VPP graph nodes to do any of these
37  * methods.
38  *
39  */
40 
41 #include <vlib/vlib.h>
42 #include <vnet/vnet.h>
43 #include <vnet/srv6/sr.h>
44 #include <vnet/ip/ip4_inlines.h>
45 #include <vnet/ip/ip6_inlines.h>
46 #include <vnet/srv6/sr_packet.h>
47 #include <vnet/fib/ip6_fib.h>
48 #include <vnet/dpo/dpo.h>
49 #include <vnet/dpo/replicate_dpo.h>
50 
51 #include <vppinfra/error.h>
52 #include <vppinfra/elog.h>
53 
54 /**
55  * @brief SR policy rewrite trace
56  */
57 typedef struct
58 {
59  ip6_address_t src, dst;
61 
62 /* Graph arcs */
63 #define foreach_sr_policy_rewrite_next \
64 _(IP6_LOOKUP, "ip6-lookup") \
65 _(ERROR, "error-drop")
66 
67 typedef enum
68 {
69 #define _(s,n) SR_POLICY_REWRITE_NEXT_##s,
71 #undef _
74 
75 /* SR rewrite errors */
76 #define foreach_sr_policy_rewrite_error \
77 _(INTERNAL_ERROR, "Segment Routing undefined error") \
78 _(BSID_ZERO, "BSID with SL = 0") \
79 _(COUNTER_TOTAL, "SR steered IPv6 packets") \
80 _(COUNTER_ENCAP, "SR: Encaps packets") \
81 _(COUNTER_INSERT, "SR: SRH inserted packets") \
82 _(COUNTER_BSID, "SR: BindingSID steered packets")
83 
84 typedef enum
85 {
86 #define _(sym,str) SR_POLICY_REWRITE_ERROR_##sym,
88 #undef _
91 
93 #define _(sym,string) string,
95 #undef _
96 };
97 
98 /**
99  * @brief Dynamically added SR SL DPO type
100  */
105 
106 /**
107  * @brief IPv6 SA for encapsulated packets
108  */
109 static ip6_address_t sr_pr_encaps_src;
111 
112 /******************* SR rewrite set encaps IPv6 source addr *******************/
113 /* Note: This is temporal. We don't know whether to follow this path or
114  take the ip address of a loopback interface or even the OIF */
115 
116 void
117 sr_set_source (ip6_address_t * address)
118 {
120 }
121 
122 ip6_address_t *
124 {
125  return &sr_pr_encaps_src;
126 }
127 
128 static clib_error_t *
130  vlib_cli_command_t * cmd)
131 {
133  {
134  if (unformat
135  (input, "addr %U", unformat_ip6_address, &sr_pr_encaps_src))
136  return 0;
137  else
138  return clib_error_return (0, "No address specified");
139  }
140  return clib_error_return (0, "No address specified");
141 }
142 
143 /* *INDENT-OFF* */
145  .path = "set sr encaps source",
146  .short_help = "set sr encaps source addr <ip6_addr>",
147  .function = set_sr_src_command_fn,
148 };
149 /* *INDENT-ON* */
150 
151 /******************** SR rewrite set encaps IPv6 hop-limit ********************/
152 
153 void
155 {
157 }
158 
159 u8
161 {
162  return sr_pr_encaps_hop_limit;
163 }
164 
165 static clib_error_t *
167  vlib_cli_command_t * cmd)
168 {
169  int hop_limit = sr_get_hop_limit ();
170 
172  return clib_error_return (0, "No value specified");
173  if (!unformat (input, "%d", &hop_limit))
174  return clib_error_return (0, "Invalid value");
175  if (hop_limit <= 0 || hop_limit > 255)
176  return clib_error_return (0, "Value out of range [1-255]");
178  return 0;
179 }
180 
181 /* *INDENT-OFF* */
183  .path = "set sr encaps hop-limit",
184  .short_help = "set sr encaps hop-limit <value>",
185  .function = set_sr_hop_limit_command_fn,
186 };
187 /* *INDENT-ON* */
188 
189 /*********************** SR rewrite string computation ************************/
190 /**
191  * @brief SR rewrite string computation for IPv6 encapsulation (inline)
192  *
193  * @param sl is a vector of IPv6 addresses composing the Segment List
194  *
195  * @return precomputed rewrite string for encapsulation
196  */
197 static inline u8 *
198 compute_rewrite_encaps (ip6_address_t * sl)
199 {
200  ip6_header_t *iph;
201  ip6_sr_header_t *srh;
202  ip6_address_t *addrp, *this_address;
203  u32 header_length = 0;
204  u8 *rs = NULL;
205 
206  header_length = 0;
207  header_length += IPv6_DEFAULT_HEADER_LENGTH;
208  if (vec_len (sl) > 1)
209  {
210  header_length += sizeof (ip6_sr_header_t);
211  header_length += vec_len (sl) * sizeof (ip6_address_t);
212  }
213 
214  vec_validate (rs, header_length - 1);
215 
216  iph = (ip6_header_t *) rs;
218  clib_host_to_net_u32 (0 | ((6 & 0xF) << 28));
219  iph->src_address.as_u64[0] = sr_pr_encaps_src.as_u64[0];
220  iph->src_address.as_u64[1] = sr_pr_encaps_src.as_u64[1];
221  iph->payload_length = header_length - IPv6_DEFAULT_HEADER_LENGTH;
222  iph->protocol = IP_PROTOCOL_IPV6;
224 
225  if (vec_len (sl) > 1)
226  {
227  srh = (ip6_sr_header_t *) (iph + 1);
228  iph->protocol = IP_PROTOCOL_IPV6_ROUTE;
229  srh->protocol = IP_PROTOCOL_IPV6;
231  srh->segments_left = vec_len (sl) - 1;
232  srh->last_entry = vec_len (sl) - 1;
233  srh->length = ((sizeof (ip6_sr_header_t) +
234  (vec_len (sl) * sizeof (ip6_address_t))) / 8) - 1;
235  srh->flags = 0x00;
236  srh->tag = 0x0000;
237  addrp = srh->segments + vec_len (sl) - 1;
238  vec_foreach (this_address, sl)
239  {
240  clib_memcpy_fast (addrp->as_u8, this_address->as_u8,
241  sizeof (ip6_address_t));
242  addrp--;
243  }
244  }
245  iph->dst_address.as_u64[0] = sl->as_u64[0];
246  iph->dst_address.as_u64[1] = sl->as_u64[1];
247  return rs;
248 }
249 
250 /**
251  * @brief SR rewrite string computation for SRH insertion (inline)
252  *
253  * @param sl is a vector of IPv6 addresses composing the Segment List
254  *
255  * @return precomputed rewrite string for SRH insertion
256  */
257 static inline u8 *
258 compute_rewrite_insert (ip6_address_t * sl)
259 {
260  ip6_sr_header_t *srh;
261  ip6_address_t *addrp, *this_address;
262  u32 header_length = 0;
263  u8 *rs = NULL;
264 
265  header_length = 0;
266  header_length += sizeof (ip6_sr_header_t);
267  header_length += (vec_len (sl) + 1) * sizeof (ip6_address_t);
268 
269  vec_validate (rs, header_length - 1);
270 
271  srh = (ip6_sr_header_t *) rs;
273  srh->segments_left = vec_len (sl);
274  srh->last_entry = vec_len (sl);
275  srh->length = ((sizeof (ip6_sr_header_t) +
276  ((vec_len (sl) + 1) * sizeof (ip6_address_t))) / 8) - 1;
277  srh->flags = 0x00;
278  srh->tag = 0x0000;
279  addrp = srh->segments + vec_len (sl);
280  vec_foreach (this_address, sl)
281  {
282  clib_memcpy_fast (addrp->as_u8, this_address->as_u8,
283  sizeof (ip6_address_t));
284  addrp--;
285  }
286  return rs;
287 }
288 
289 /**
290  * @brief SR rewrite string computation for SRH insertion with BSID (inline)
291  *
292  * @param sl is a vector of IPv6 addresses composing the Segment List
293  *
294  * @return precomputed rewrite string for SRH insertion with BSID
295  */
296 static inline u8 *
297 compute_rewrite_bsid (ip6_address_t * sl)
298 {
299  ip6_sr_header_t *srh;
300  ip6_address_t *addrp, *this_address;
301  u32 header_length = 0;
302  u8 *rs = NULL;
303 
304  header_length = 0;
305  header_length += sizeof (ip6_sr_header_t);
306  header_length += vec_len (sl) * sizeof (ip6_address_t);
307 
308  vec_validate (rs, header_length - 1);
309 
310  srh = (ip6_sr_header_t *) rs;
312  srh->segments_left = vec_len (sl) - 1;
313  srh->last_entry = vec_len (sl) - 1;
314  srh->length = ((sizeof (ip6_sr_header_t) +
315  (vec_len (sl) * sizeof (ip6_address_t))) / 8) - 1;
316  srh->flags = 0x00;
317  srh->tag = 0x0000;
318  addrp = srh->segments + vec_len (sl) - 1;
319  vec_foreach (this_address, sl)
320  {
321  clib_memcpy_fast (addrp->as_u8, this_address->as_u8,
322  sizeof (ip6_address_t));
323  addrp--;
324  }
325  return rs;
326 }
327 
328 /*************************** SR LB helper functions **************************/
329 /**
330  * @brief Creates a Segment List and adds it to an SR policy
331  *
332  * Creates a Segment List and adds it to the SR policy. Notice that the SL are
333  * not necessarily unique. Hence there might be two Segment List within the
334  * same SR Policy with exactly the same segments and same weight.
335  *
336  * @param sr_policy is the SR policy where the SL will be added
337  * @param sl is a vector of IPv6 addresses composing the Segment List
338  * @param weight is the weight of the SegmentList (for load-balancing purposes)
339  * @param is_encap represents the mode (SRH insertion vs Encapsulation)
340  *
341  * @return pointer to the just created segment list
342  */
343 static inline ip6_sr_sl_t *
344 create_sl (ip6_sr_policy_t * sr_policy, ip6_address_t * sl, u32 weight,
345  u8 is_encap)
346 {
347  ip6_sr_main_t *sm = &sr_main;
348  ip6_sr_sl_t *segment_list;
349  sr_policy_fn_registration_t *plugin = 0;
350 
351  pool_get (sm->sid_lists, segment_list);
352  clib_memset (segment_list, 0, sizeof (*segment_list));
353 
354  vec_add1 (sr_policy->segments_lists, segment_list - sm->sid_lists);
355 
356  /* Fill in segment list */
357  segment_list->weight =
359 
360  segment_list->segments = vec_dup (sl);
361 
362  segment_list->egress_fib_table =
364 
365  if (is_encap)
366  {
367  segment_list->rewrite = compute_rewrite_encaps (sl);
368  segment_list->rewrite_bsid = segment_list->rewrite;
369  }
370  else
371  {
372  segment_list->rewrite = compute_rewrite_insert (sl);
373  segment_list->rewrite_bsid = compute_rewrite_bsid (sl);
374  }
375 
376  if (sr_policy->plugin)
377  {
378  plugin =
380  sr_policy->plugin - SR_BEHAVIOR_LAST);
381 
382  segment_list->plugin = sr_policy->plugin;
383  segment_list->plugin_mem = sr_policy->plugin_mem;
384 
385  plugin->creation (sr_policy);
386  }
387 
388  /* Create DPO */
389  dpo_reset (&segment_list->bsid_dpo);
390  dpo_reset (&segment_list->ip6_dpo);
391  dpo_reset (&segment_list->ip4_dpo);
392 
393  if (is_encap)
394  {
395  if (!sr_policy->plugin)
396  {
397  dpo_set (&segment_list->ip6_dpo, sr_pr_encaps_dpo_type,
398  DPO_PROTO_IP6, segment_list - sm->sid_lists);
399  dpo_set (&segment_list->ip4_dpo, sr_pr_encaps_dpo_type,
400  DPO_PROTO_IP4, segment_list - sm->sid_lists);
402  DPO_PROTO_IP6, segment_list - sm->sid_lists);
403  }
404  else
405  {
406  dpo_set (&segment_list->ip6_dpo, plugin->dpo, DPO_PROTO_IP6,
407  segment_list - sm->sid_lists);
408  dpo_set (&segment_list->ip4_dpo, plugin->dpo, DPO_PROTO_IP4,
409  segment_list - sm->sid_lists);
410  dpo_set (&segment_list->bsid_dpo, plugin->dpo, DPO_PROTO_IP6,
411  segment_list - sm->sid_lists);
412  }
413  }
414  else
415  {
416  if (!sr_policy->plugin)
417  {
418  dpo_set (&segment_list->ip6_dpo, sr_pr_insert_dpo_type,
419  DPO_PROTO_IP6, segment_list - sm->sid_lists);
421  DPO_PROTO_IP6, segment_list - sm->sid_lists);
422  }
423  else
424  {
425  dpo_set (&segment_list->ip6_dpo, plugin->dpo, DPO_PROTO_IP6,
426  segment_list - sm->sid_lists);
427  dpo_set (&segment_list->bsid_dpo, plugin->dpo, DPO_PROTO_IP6,
428  segment_list - sm->sid_lists);
429  }
430  }
431 
432  return segment_list;
433 }
434 
435 /**
436  * @brief Updates the Load Balancer after an SR Policy change
437  *
438  * @param sr_policy is the modified SR Policy
439  */
440 static inline void
442 {
443  flow_hash_config_t fhc;
444  u32 *sl_index;
445  ip6_sr_sl_t *segment_list;
446  ip6_sr_main_t *sm = &sr_main;
448  path.path_index = FIB_NODE_INDEX_INVALID;
449  load_balance_path_t *ip4_path_vector = 0;
450  load_balance_path_t *ip6_path_vector = 0;
451  load_balance_path_t *b_path_vector = 0;
452 
453  /* In case LB does not exist, create it */
454  if (!dpo_id_is_valid (&sr_policy->bsid_dpo))
455  {
456  fib_prefix_t pfx = {
458  .fp_len = 128,
459  .fp_addr = {
460  .ip6 = sr_policy->bsid,
461  }
462  };
463 
464  /* Add FIB entry for BSID */
465  fhc = fib_table_get_flow_hash_config (sr_policy->fib_table,
467 
470 
473 
474  /* Update FIB entry's to point to the LB DPO in the main FIB and hidden one */
476  sr_policy->fib_table),
477  &pfx, FIB_SOURCE_SR,
479  &sr_policy->bsid_dpo);
480 
482  &pfx,
485  &sr_policy->ip6_dpo);
486 
487  if (sr_policy->is_encap)
488  {
491 
493  &pfx,
496  &sr_policy->ip4_dpo);
497  }
498 
499  }
500 
501  /* Create the LB path vector */
502  vec_foreach (sl_index, sr_policy->segments_lists)
503  {
504  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
505  path.path_dpo = segment_list->bsid_dpo;
506  path.path_weight = segment_list->weight;
507  vec_add1 (b_path_vector, path);
508  path.path_dpo = segment_list->ip6_dpo;
509  vec_add1 (ip6_path_vector, path);
510  if (sr_policy->is_encap)
511  {
512  path.path_dpo = segment_list->ip4_dpo;
513  vec_add1 (ip4_path_vector, path);
514  }
515  }
516 
517  /* Update LB multipath */
518  load_balance_multipath_update (&sr_policy->bsid_dpo, b_path_vector,
520  load_balance_multipath_update (&sr_policy->ip6_dpo, ip6_path_vector,
522  if (sr_policy->is_encap)
523  load_balance_multipath_update (&sr_policy->ip4_dpo, ip4_path_vector,
525 
526  /* Cleanup */
527  vec_free (b_path_vector);
528  vec_free (ip6_path_vector);
529  vec_free (ip4_path_vector);
530 }
531 
532 /**
533  * @brief Updates the Replicate DPO after an SR Policy change
534  *
535  * @param sr_policy is the modified SR Policy (type spray)
536  */
537 static inline void
539 {
540  u32 *sl_index;
541  ip6_sr_sl_t *segment_list;
542  ip6_sr_main_t *sm = &sr_main;
544  path.path_index = FIB_NODE_INDEX_INVALID;
545  load_balance_path_t *b_path_vector = 0;
546  load_balance_path_t *ip6_path_vector = 0;
547  load_balance_path_t *ip4_path_vector = 0;
548 
549  /* In case LB does not exist, create it */
550  if (!dpo_id_is_valid (&sr_policy->bsid_dpo))
551  {
552  dpo_set (&sr_policy->bsid_dpo, DPO_REPLICATE,
554 
555  dpo_set (&sr_policy->ip6_dpo, DPO_REPLICATE,
557 
558  /* Update FIB entry's DPO to point to SR without LB */
559  fib_prefix_t pfx = {
561  .fp_len = 128,
562  .fp_addr = {
563  .ip6 = sr_policy->bsid,
564  }
565  };
567  sr_policy->fib_table),
568  &pfx, FIB_SOURCE_SR,
570  &sr_policy->bsid_dpo);
571 
573  &pfx,
576  &sr_policy->ip6_dpo);
577 
578  if (sr_policy->is_encap)
579  {
582 
584  &pfx,
587  &sr_policy->ip4_dpo);
588  }
589 
590  }
591 
592  /* Create the replicate path vector */
593  path.path_weight = 1;
594  vec_foreach (sl_index, sr_policy->segments_lists)
595  {
596  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
597  path.path_dpo = segment_list->bsid_dpo;
598  vec_add1 (b_path_vector, path);
599  path.path_dpo = segment_list->ip6_dpo;
600  vec_add1 (ip6_path_vector, path);
601  if (sr_policy->is_encap)
602  {
603  path.path_dpo = segment_list->ip4_dpo;
604  vec_add1 (ip4_path_vector, path);
605  }
606  }
607 
608  /* Update replicate multipath */
609  replicate_multipath_update (&sr_policy->bsid_dpo, b_path_vector);
610  replicate_multipath_update (&sr_policy->ip6_dpo, ip6_path_vector);
611  if (sr_policy->is_encap)
612  replicate_multipath_update (&sr_policy->ip4_dpo, ip4_path_vector);
613 }
614 
615 /******************************* SR rewrite API *******************************/
616 /* Three functions for handling sr policies:
617  * -> sr_policy_add
618  * -> sr_policy_del
619  * -> sr_policy_mod
620  * All of them are API. CLI function on sr_policy_command_fn */
621 
622 /**
623  * @brief Create a new SR policy
624  *
625  * @param bsid is the bindingSID of the SR Policy
626  * @param segments is a vector of IPv6 address composing the segment list
627  * @param weight is the weight of the sid list. optional.
628  * @param behavior is the behavior of the SR policy. (default//spray)
629  * @param fib_table is the VRF where to install the FIB entry for the BSID
630  * @param is_encap (bool) whether SR policy should behave as Encap/SRH Insertion
631  *
632  * @return 0 if correct, else error
633  */
634 int
635 sr_policy_add (ip6_address_t * bsid, ip6_address_t * segments,
636  u32 weight, u8 behavior, u32 fib_table, u8 is_encap,
637  u16 plugin, void *ls_plugin_mem)
638 {
639  ip6_sr_main_t *sm = &sr_main;
640  ip6_sr_policy_t *sr_policy = 0;
641  uword *p;
642 
643  /* Search for existing keys (BSID) */
644  p = mhash_get (&sm->sr_policies_index_hash, bsid);
645  if (p)
646  {
647  /* Add SR policy that already exists; complain */
648  return -12;
649  }
650 
651  /* Search collision in FIB entries */
652  /* Explanation: It might be possible that some other entity has already
653  * created a route for the BSID. This in theory is impossible, but in
654  * practise we could see it. Assert it and scream if needed */
655  fib_prefix_t pfx = {
657  .fp_len = 128,
658  .fp_addr = {
659  .ip6 = *bsid,
660  }
661  };
662 
663  /* Lookup the FIB index associated to the table selected */
664  u32 fib_index = fib_table_find (FIB_PROTOCOL_IP6,
665  (fib_table != (u32) ~ 0 ? fib_table : 0));
666  if (fib_index == ~0)
667  return -13;
668 
669  /* Lookup whether there exists an entry for the BSID */
670  fib_node_index_t fei = fib_table_lookup_exact_match (fib_index, &pfx);
671  if (FIB_NODE_INDEX_INVALID != fei)
672  return -12; //There is an entry for such lookup
673 
674  /* Add an SR policy object */
675  pool_get (sm->sr_policies, sr_policy);
676  clib_memset (sr_policy, 0, sizeof (*sr_policy));
677  clib_memcpy_fast (&sr_policy->bsid, bsid, sizeof (ip6_address_t));
678  sr_policy->type = behavior;
679  sr_policy->fib_table = (fib_table != (u32) ~ 0 ? fib_table : 0); //Is default FIB 0 ?
680  sr_policy->is_encap = is_encap;
681 
682  if (plugin)
683  {
684  sr_policy->plugin = plugin;
685  sr_policy->plugin_mem = ls_plugin_mem;
686  }
687 
688  /* Copy the key */
689  mhash_set (&sm->sr_policies_index_hash, bsid, sr_policy - sm->sr_policies,
690  NULL);
691 
692  /* Create a segment list and add the index to the SR policy */
693  create_sl (sr_policy, segments, weight, is_encap);
694 
695  /* If FIB doesnt exist, create them */
696  if (sm->fib_table_ip6 == (u32) ~ 0)
697  {
700  "SRv6 steering of IP6 prefixes through BSIDs");
703  "SRv6 steering of IP4 prefixes through BSIDs");
704  }
705 
706  /* Create IPv6 FIB for the BindingSID attached to the DPO of the only SL */
707  if (sr_policy->type == SR_POLICY_TYPE_DEFAULT)
708  update_lb (sr_policy);
709  else if (sr_policy->type == SR_POLICY_TYPE_SPRAY)
710  update_replicate (sr_policy);
711  return 0;
712 }
713 
714 /**
715  * @brief Delete a SR policy
716  *
717  * @param bsid is the bindingSID of the SR Policy
718  * @param index is the index of the SR policy
719  *
720  * @return 0 if correct, else error
721  */
722 int
723 sr_policy_del (ip6_address_t * bsid, u32 index)
724 {
725  ip6_sr_main_t *sm = &sr_main;
726  ip6_sr_policy_t *sr_policy = 0;
727  ip6_sr_sl_t *segment_list;
728  u32 *sl_index;
729  uword *p;
730 
731  if (bsid)
732  {
733  p = mhash_get (&sm->sr_policies_index_hash, bsid);
734  if (p)
735  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
736  else
737  return -1;
738  }
739  else
740  {
741  sr_policy = pool_elt_at_index (sm->sr_policies, index);
742  if (!sr_policy)
743  return -1;
744  }
745 
746  /* Remove BindingSID FIB entry */
747  fib_prefix_t pfx = {
749  .fp_len = 128,
750  .fp_addr = {
751  .ip6 = sr_policy->bsid,
752  }
753  ,
754  };
755 
757  sr_policy->fib_table),
758  &pfx, FIB_SOURCE_SR);
759 
761 
762  if (sr_policy->is_encap)
764 
765  if (dpo_id_is_valid (&sr_policy->bsid_dpo))
766  {
767  dpo_reset (&sr_policy->bsid_dpo);
768  dpo_reset (&sr_policy->ip4_dpo);
769  dpo_reset (&sr_policy->ip6_dpo);
770  }
771 
772  /* Clean SID Lists */
773  vec_foreach (sl_index, sr_policy->segments_lists)
774  {
775  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
776  vec_free (segment_list->segments);
777  vec_free (segment_list->rewrite);
778  if (!sr_policy->is_encap)
779  vec_free (segment_list->rewrite_bsid);
781  }
782 
783  if (sr_policy->plugin)
784  {
785  sr_policy_fn_registration_t *plugin = 0;
786 
787  plugin =
789  sr_policy->plugin - SR_BEHAVIOR_LAST);
790 
791  plugin->removal (sr_policy);
792  sr_policy->plugin = 0;
793  sr_policy->plugin_mem = NULL;
794  }
795 
796  /* Remove SR policy entry */
797  mhash_unset (&sm->sr_policies_index_hash, &sr_policy->bsid, NULL);
798  pool_put (sm->sr_policies, sr_policy);
799 
800  /* If FIB empty unlock it */
801  if (!pool_elts (sm->sr_policies) && !pool_elts (sm->steer_policies))
802  {
805  sm->fib_table_ip6 = (u32) ~ 0;
806  sm->fib_table_ip4 = (u32) ~ 0;
807  }
808 
809  return 0;
810 }
811 
812 /**
813  * @brief Modify an existing SR policy
814  *
815  * The possible modifications are adding a new Segment List, modifying an
816  * existing Segment List (modify the weight only) and delete a given
817  * Segment List from the SR Policy.
818  *
819  * @param bsid is the bindingSID of the SR Policy
820  * @param index is the index of the SR policy
821  * @param fib_table is the VRF where to install the FIB entry for the BSID
822  * @param operation is the operation to perform (among the top ones)
823  * @param segments is a vector of IPv6 address composing the segment list
824  * @param sl_index is the index of the Segment List to modify/delete
825  * @param weight is the weight of the sid list. optional.
826  * @param is_encap Mode. Encapsulation or SRH insertion.
827  *
828  * @return 0 if correct, else error
829  */
830 int
831 sr_policy_mod (ip6_address_t * bsid, u32 index, u32 fib_table,
832  u8 operation, ip6_address_t * segments, u32 sl_index,
833  u32 weight)
834 {
835  ip6_sr_main_t *sm = &sr_main;
836  ip6_sr_policy_t *sr_policy = 0;
837  ip6_sr_sl_t *segment_list;
838  u32 *sl_index_iterate;
839  uword *p;
840 
841  if (bsid)
842  {
843  p = mhash_get (&sm->sr_policies_index_hash, bsid);
844  if (p)
845  sr_policy = pool_elt_at_index (sm->sr_policies, p[0]);
846  else
847  return -1;
848  }
849  else
850  {
851  sr_policy = pool_elt_at_index (sm->sr_policies, index);
852  if (!sr_policy)
853  return -1;
854  }
855 
856  if (operation == 1) /* Add SR List to an existing SR policy */
857  {
858  /* Create the new SL */
859  segment_list =
860  create_sl (sr_policy, segments, weight, sr_policy->is_encap);
861 
862  /* Create a new LB DPO */
863  if (sr_policy->type == SR_POLICY_TYPE_DEFAULT)
864  update_lb (sr_policy);
865  else if (sr_policy->type == SR_POLICY_TYPE_SPRAY)
866  update_replicate (sr_policy);
867  }
868  else if (operation == 2) /* Delete SR List from an existing SR policy */
869  {
870  /* Check that currently there are more than one SID list */
871  if (vec_len (sr_policy->segments_lists) == 1)
872  return -21;
873 
874  /* Check that the SR list does exist and is assigned to the sr policy */
875  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
876  if (*sl_index_iterate == sl_index)
877  break;
878 
879  if (*sl_index_iterate != sl_index)
880  return -22;
881 
882  /* Remove the lucky SR list that is being kicked out */
883  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
884  vec_free (segment_list->segments);
885  vec_free (segment_list->rewrite);
886  if (!sr_policy->is_encap)
887  vec_free (segment_list->rewrite_bsid);
889  vec_del1 (sr_policy->segments_lists,
890  sl_index_iterate - sr_policy->segments_lists);
891 
892  /* Create a new LB DPO */
893  if (sr_policy->type == SR_POLICY_TYPE_DEFAULT)
894  update_lb (sr_policy);
895  else if (sr_policy->type == SR_POLICY_TYPE_SPRAY)
896  update_replicate (sr_policy);
897  }
898  else if (operation == 3) /* Modify the weight of an existing SR List */
899  {
900  /* Find the corresponding SL */
901  vec_foreach (sl_index_iterate, sr_policy->segments_lists)
902  if (*sl_index_iterate == sl_index)
903  break;
904 
905  if (*sl_index_iterate != sl_index)
906  return -32;
907 
908  /* Change the weight */
909  segment_list = pool_elt_at_index (sm->sid_lists, sl_index);
910  segment_list->weight = weight;
911 
912  /* Update LB */
913  if (sr_policy->type == SR_POLICY_TYPE_DEFAULT)
914  update_lb (sr_policy);
915  }
916  else /* Incorrect op. */
917  return -1;
918 
919  return 0;
920 }
921 
922 /**
923  * @brief CLI for 'sr policies' command family
924  */
925 static clib_error_t *
927  vlib_cli_command_t * cmd)
928 {
929  ip6_sr_main_t *sm = &sr_main;
930  int rv = -1;
931  char is_del = 0, is_add = 0, is_mod = 0;
932  char policy_set = 0;
933  ip6_address_t bsid, next_address;
934  u32 sr_policy_index = (u32) ~ 0, sl_index = (u32) ~ 0;
935  u32 weight = (u32) ~ 0, fib_table = (u32) ~ 0;
936  ip6_address_t *segments = 0, *this_seg;
937  u8 operation = 0;
938  char is_encap = 1;
939  char is_spray = 0;
940  u16 behavior = 0;
941  void *ls_plugin_mem = 0;
942 
944  {
945  if (!is_add && !is_mod && !is_del && unformat (input, "add"))
946  is_add = 1;
947  else if (!is_add && !is_mod && !is_del && unformat (input, "del"))
948  is_del = 1;
949  else if (!is_add && !is_mod && !is_del && unformat (input, "mod"))
950  is_mod = 1;
951  else if (!policy_set
952  && unformat (input, "bsid %U", unformat_ip6_address, &bsid))
953  policy_set = 1;
954  else if (!is_add && !policy_set
955  && unformat (input, "index %d", &sr_policy_index))
956  policy_set = 1;
957  else if (unformat (input, "weight %d", &weight));
958  else
959  if (unformat (input, "next %U", unformat_ip6_address, &next_address))
960  {
961  vec_add2 (segments, this_seg, 1);
962  clib_memcpy_fast (this_seg->as_u8, next_address.as_u8,
963  sizeof (*this_seg));
964  }
965  else if (unformat (input, "add sl"))
966  operation = 1;
967  else if (unformat (input, "del sl index %d", &sl_index))
968  operation = 2;
969  else if (unformat (input, "mod sl index %d", &sl_index))
970  operation = 3;
971  else if (fib_table == (u32) ~ 0
972  && unformat (input, "fib-table %d", &fib_table));
973  else if (unformat (input, "encap"))
974  is_encap = 1;
975  else if (unformat (input, "insert"))
976  is_encap = 0;
977  else if (unformat (input, "spray"))
978  is_spray = 1;
979  else if (!behavior && unformat (input, "behavior"))
980  {
981  sr_policy_fn_registration_t *plugin = 0, **vec_plugins = 0;
982  sr_policy_fn_registration_t **plugin_it = 0;
983 
984  /* *INDENT-OFF* */
986  {
987  vec_add1 (vec_plugins, plugin);
988  }
989  /* *INDENT-ON* */
990 
991  vec_foreach (plugin_it, vec_plugins)
992  {
993  if (unformat
994  (input, "%U", (*plugin_it)->ls_unformat, &ls_plugin_mem))
995  {
996  behavior = (*plugin_it)->sr_policy_function_number;
997  break;
998  }
999  }
1000 
1001  if (!behavior)
1002  {
1003  return clib_error_return (0, "Invalid behavior");
1004  }
1005  }
1006  else
1007  break;
1008  }
1009 
1010  if (!is_add && !is_mod && !is_del)
1011  return clib_error_return (0, "Incorrect CLI");
1012 
1013  if (!policy_set)
1014  return clib_error_return (0, "No SR policy BSID or index specified");
1015 
1016  if (is_add)
1017  {
1018  if (behavior && vec_len (segments) == 0)
1019  {
1020  vec_add2 (segments, this_seg, 1);
1021  clib_memset (this_seg, 0, sizeof (*this_seg));
1022  }
1023 
1024  if (vec_len (segments) == 0)
1025  return clib_error_return (0, "No Segment List specified");
1026 
1027  rv = sr_policy_add (&bsid, segments, weight,
1028  (is_spray ? SR_POLICY_TYPE_SPRAY :
1029  SR_POLICY_TYPE_DEFAULT), fib_table, is_encap,
1030  behavior, ls_plugin_mem);
1031 
1032  vec_free (segments);
1033  }
1034  else if (is_del)
1035  rv = sr_policy_del ((sr_policy_index != (u32) ~ 0 ? NULL : &bsid),
1036  sr_policy_index);
1037  else if (is_mod)
1038  {
1039  if (!operation)
1040  return clib_error_return (0, "No SL modification specified");
1041  if (operation != 1 && sl_index == (u32) ~ 0)
1042  return clib_error_return (0, "No Segment List index specified");
1043  if (operation == 1 && vec_len (segments) == 0)
1044  return clib_error_return (0, "No Segment List specified");
1045  if (operation == 3 && weight == (u32) ~ 0)
1046  return clib_error_return (0, "No new weight for the SL specified");
1047 
1048  rv = sr_policy_mod ((sr_policy_index != (u32) ~ 0 ? NULL : &bsid),
1049  sr_policy_index, fib_table, operation, segments,
1050  sl_index, weight);
1051 
1052  if (segments)
1053  vec_free (segments);
1054  }
1055 
1056  switch (rv)
1057  {
1058  case 0:
1059  break;
1060  case 1:
1061  return 0;
1062  case -12:
1063  return clib_error_return (0,
1064  "There is already a FIB entry for the BindingSID address.\n"
1065  "The SR policy could not be created.");
1066  case -13:
1067  return clib_error_return (0, "The specified FIB table does not exist.");
1068  case -21:
1069  return clib_error_return (0,
1070  "The selected SR policy only contains ONE segment list. "
1071  "Please remove the SR policy instead");
1072  case -22:
1073  return clib_error_return (0,
1074  "Could not delete the segment list. "
1075  "It is not associated with that SR policy.");
1076  case -32:
1077  return clib_error_return (0,
1078  "Could not modify the segment list. "
1079  "The given SL is not associated with such SR policy.");
1080  default:
1081  return clib_error_return (0, "BUG: sr policy returns %d", rv);
1082  }
1083  return 0;
1084 }
1085 
1086 /* *INDENT-OFF* */
1088  .path = "sr policy",
1089  .short_help = "sr policy [add||del||mod] [bsid 2001::1||index 5] "
1090  "next A:: next B:: next C:: (weight 1) (fib-table 2) (encap|insert)",
1091  .long_help =
1092  "Manipulation of SR policies.\n"
1093  "A Segment Routing policy may contain several SID lists. Each SID list has\n"
1094  "an associated weight (default 1), which will result in wECMP (uECMP).\n"
1095  "Segment Routing policies might be of type encapsulation or srh insertion\n"
1096  "Each SR policy will be associated with a unique BindingSID.\n"
1097  "A BindingSID is a locally allocated SegmentID. For every packet that arrives\n"
1098  "with IPv6_DA:BSID such traffic will be steered into the SR policy.\n"
1099  "The add command will create a SR policy with its first segment list (sl)\n"
1100  "The mod command allows you to add, remove, or modify the existing segment lists\n"
1101  "within an SR policy.\n"
1102  "The del command allows you to delete a SR policy along with all its associated\n"
1103  "SID lists.\n",
1104  .function = sr_policy_command_fn,
1105 };
1106 /* *INDENT-ON* */
1107 
1108 /**
1109  * @brief CLI to display onscreen all the SR policies
1110  */
1111 static clib_error_t *
1113  vlib_cli_command_t * cmd)
1114 {
1115  ip6_sr_main_t *sm = &sr_main;
1116  u32 *sl_index;
1117  ip6_sr_sl_t *segment_list = 0;
1118  ip6_sr_policy_t *sr_policy = 0;
1119  ip6_sr_policy_t **vec_policies = 0;
1120  ip6_address_t *addr;
1121  u8 *s;
1122  int i = 0;
1123 
1124  vlib_cli_output (vm, "SR policies:");
1125 
1126  /* *INDENT-OFF* */
1127  pool_foreach (sr_policy, sm->sr_policies)
1128  {vec_add1 (vec_policies, sr_policy); }
1129  /* *INDENT-ON* */
1130 
1131  vec_foreach_index (i, vec_policies)
1132  {
1133  sr_policy = vec_policies[i];
1134  vlib_cli_output (vm, "[%u].-\tBSID: %U",
1135  (u32) (sr_policy - sm->sr_policies),
1136  format_ip6_address, &sr_policy->bsid);
1137  vlib_cli_output (vm, "\tBehavior: %s",
1138  (sr_policy->is_encap ? "Encapsulation" :
1139  "SRH insertion"));
1140  vlib_cli_output (vm, "\tType: %s",
1141  (sr_policy->type ==
1142  SR_POLICY_TYPE_DEFAULT ? "Default" : "Spray"));
1143  vlib_cli_output (vm, "\tFIB table: %u",
1144  (sr_policy->fib_table !=
1145  (u32) ~ 0 ? sr_policy->fib_table : 0));
1146  vlib_cli_output (vm, "\tSegment Lists:");
1147  vec_foreach (sl_index, sr_policy->segments_lists)
1148  {
1149  s = NULL;
1150  s = format (s, "\t[%u].- ", *sl_index);
1151  segment_list = pool_elt_at_index (sm->sid_lists, *sl_index);
1152  s = format (s, "< ");
1153  vec_foreach (addr, segment_list->segments)
1154  {
1155  s = format (s, "%U, ", format_ip6_address, addr);
1156  }
1157  s = format (s, "\b\b > ");
1158  s = format (s, "weight: %u", segment_list->weight);
1159  vlib_cli_output (vm, " %v", s);
1160  }
1161  vlib_cli_output (vm, "-----------");
1162  }
1163  return 0;
1164 }
1165 
1166 /* *INDENT-OFF* */
1168  .path = "show sr policies",
1169  .short_help = "show sr policies",
1170  .function = show_sr_policies_command_fn,
1171 };
1172 /* *INDENT-ON* */
1173 
1174 /**
1175  * @brief CLI to display onscreen the SR encaps source addr
1176  */
1177 static clib_error_t *
1179  vlib_cli_command_t * cmd)
1180 {
1181  vlib_cli_output (vm, "SR encaps source addr = %U", format_ip6_address,
1183 
1184  return 0;
1185 }
1186 
1187 /* *INDENT-OFF* */
1189  .path = "show sr encaps source addr",
1190  .short_help = "show sr encaps source addr",
1192 };
1193 /* *INDENT-ON* */
1194 
1195 /**
1196  * @brief CLI to display onscreen the hop-limit value used for SRv6 encapsulation
1197  */
1198 static clib_error_t *
1200  unformat_input_t * input,
1201  vlib_cli_command_t * cmd)
1202 {
1203  vlib_cli_output (vm, "SR encaps hop-limit = %u", sr_get_hop_limit ());
1204 
1205  return 0;
1206 }
1207 
1208 /* *INDENT-OFF* */
1210  .path = "show sr encaps hop-limit",
1211  .short_help = "show sr encaps hop-limit",
1213 };
1214 /* *INDENT-ON* */
1215 
1216 /*************************** SR rewrite graph node ****************************/
1217 /**
1218  * @brief Trace for the SR Policy Rewrite graph node
1219  */
1220 static u8 *
1221 format_sr_policy_rewrite_trace (u8 * s, va_list * args)
1222 {
1223  //TODO
1224  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1225  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1227 
1228  s = format
1229  (s, "SR-policy-rewrite: src %U dst %U",
1231 
1232  return s;
1233 }
1234 
1235 /**
1236  * @brief IPv6 encapsulation processing as per RFC2473
1237  */
1240  vlib_buffer_t * b0,
1241  ip6_header_t * ip0, ip6_header_t * ip0_encap)
1242 {
1243  u32 new_l0;
1244  u32 flow_label;
1245 
1246  ip0_encap->hop_limit -= 1;
1247  new_l0 =
1248  ip0->payload_length + sizeof (ip6_header_t) +
1249  clib_net_to_host_u16 (ip0_encap->payload_length);
1250  ip0->payload_length = clib_host_to_net_u16 (new_l0);
1251 
1252  flow_label = ip6_compute_flow_hash (ip0_encap, IP_FLOW_HASH_DEFAULT);
1253  ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
1254  0 |
1255  (clib_net_to_host_u32 (
1257  0xfff00000) |
1258  (flow_label & 0x0000ffff));
1259 }
1260 
1261 /**
1262  * @brief Graph node for applying a SR policy into an IPv6 packet. Encapsulation
1263  */
1264 static uword
1267 {
1268  ip6_sr_main_t *sm = &sr_main;
1269  u32 n_left_from, next_index, *from, *to_next;
1270 
1272  n_left_from = from_frame->n_vectors;
1273 
1274  next_index = node->cached_next_index;
1275 
1276  int encap_pkts = 0, bsid_pkts = 0;
1277 
1278  while (n_left_from > 0)
1279  {
1280  u32 n_left_to_next;
1281 
1282  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1283 
1284  /* Quad - Loop */
1285  while (n_left_from >= 8 && n_left_to_next >= 4)
1286  {
1287  u32 bi0, bi1, bi2, bi3;
1288  vlib_buffer_t *b0, *b1, *b2, *b3;
1289  u32 next0, next1, next2, next3;
1290  next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1291  ip6_header_t *ip0, *ip1, *ip2, *ip3;
1292  ip6_header_t *ip0_encap, *ip1_encap, *ip2_encap, *ip3_encap;
1293  ip6_sr_sl_t *sl0, *sl1, *sl2, *sl3;
1294 
1295  /* Prefetch next iteration. */
1296  {
1297  vlib_buffer_t *p4, *p5, *p6, *p7;
1298 
1299  p4 = vlib_get_buffer (vm, from[4]);
1300  p5 = vlib_get_buffer (vm, from[5]);
1301  p6 = vlib_get_buffer (vm, from[6]);
1302  p7 = vlib_get_buffer (vm, from[7]);
1303 
1304  /* Prefetch the buffer header and packet for the N+2 loop iteration */
1305  vlib_prefetch_buffer_header (p4, LOAD);
1306  vlib_prefetch_buffer_header (p5, LOAD);
1307  vlib_prefetch_buffer_header (p6, LOAD);
1308  vlib_prefetch_buffer_header (p7, LOAD);
1309 
1314  }
1315 
1316  to_next[0] = bi0 = from[0];
1317  to_next[1] = bi1 = from[1];
1318  to_next[2] = bi2 = from[2];
1319  to_next[3] = bi3 = from[3];
1320  from += 4;
1321  to_next += 4;
1322  n_left_from -= 4;
1323  n_left_to_next -= 4;
1324 
1325  b0 = vlib_get_buffer (vm, bi0);
1326  b1 = vlib_get_buffer (vm, bi1);
1327  b2 = vlib_get_buffer (vm, bi2);
1328  b3 = vlib_get_buffer (vm, bi3);
1329 
1330  sl0 =
1332  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1333  sl1 =
1335  vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
1336  sl2 =
1338  vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
1339  sl3 =
1341  vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
1342 
1344  vec_len (sl0->rewrite));
1346  vec_len (sl1->rewrite));
1348  vec_len (sl2->rewrite));
1350  vec_len (sl3->rewrite));
1351 
1352  ip0_encap = vlib_buffer_get_current (b0);
1353  ip1_encap = vlib_buffer_get_current (b1);
1354  ip2_encap = vlib_buffer_get_current (b2);
1355  ip3_encap = vlib_buffer_get_current (b3);
1356 
1357  clib_memcpy_fast (((u8 *) ip0_encap) - vec_len (sl0->rewrite),
1358  sl0->rewrite, vec_len (sl0->rewrite));
1359  clib_memcpy_fast (((u8 *) ip1_encap) - vec_len (sl1->rewrite),
1360  sl1->rewrite, vec_len (sl1->rewrite));
1361  clib_memcpy_fast (((u8 *) ip2_encap) - vec_len (sl2->rewrite),
1362  sl2->rewrite, vec_len (sl2->rewrite));
1363  clib_memcpy_fast (((u8 *) ip3_encap) - vec_len (sl3->rewrite),
1364  sl3->rewrite, vec_len (sl3->rewrite));
1365 
1366  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
1367  vlib_buffer_advance (b1, -(word) vec_len (sl1->rewrite));
1368  vlib_buffer_advance (b2, -(word) vec_len (sl2->rewrite));
1369  vlib_buffer_advance (b3, -(word) vec_len (sl3->rewrite));
1370 
1371  ip0 = vlib_buffer_get_current (b0);
1372  ip1 = vlib_buffer_get_current (b1);
1373  ip2 = vlib_buffer_get_current (b2);
1374  ip3 = vlib_buffer_get_current (b3);
1375 
1376  encaps_processing_v6 (node, b0, ip0, ip0_encap);
1377  encaps_processing_v6 (node, b1, ip1, ip1_encap);
1378  encaps_processing_v6 (node, b2, ip2, ip2_encap);
1379  encaps_processing_v6 (node, b3, ip3, ip3_encap);
1380 
1381  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sl0->egress_fib_table;
1382  vnet_buffer (b1)->sw_if_index[VLIB_TX] = sl1->egress_fib_table;
1383  vnet_buffer (b2)->sw_if_index[VLIB_TX] = sl2->egress_fib_table;
1384  vnet_buffer (b3)->sw_if_index[VLIB_TX] = sl3->egress_fib_table;
1385 
1386  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
1387  {
1388  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1389  {
1391  vlib_add_trace (vm, node, b0, sizeof (*tr));
1392  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
1393  sizeof (tr->src.as_u8));
1394  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
1395  sizeof (tr->dst.as_u8));
1396  }
1397 
1398  if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
1399  {
1401  vlib_add_trace (vm, node, b1, sizeof (*tr));
1402  clib_memcpy_fast (tr->src.as_u8, ip1->src_address.as_u8,
1403  sizeof (tr->src.as_u8));
1404  clib_memcpy_fast (tr->dst.as_u8, ip1->dst_address.as_u8,
1405  sizeof (tr->dst.as_u8));
1406  }
1407 
1408  if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
1409  {
1411  vlib_add_trace (vm, node, b2, sizeof (*tr));
1412  clib_memcpy_fast (tr->src.as_u8, ip2->src_address.as_u8,
1413  sizeof (tr->src.as_u8));
1414  clib_memcpy_fast (tr->dst.as_u8, ip2->dst_address.as_u8,
1415  sizeof (tr->dst.as_u8));
1416  }
1417 
1418  if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
1419  {
1421  vlib_add_trace (vm, node, b3, sizeof (*tr));
1422  clib_memcpy_fast (tr->src.as_u8, ip3->src_address.as_u8,
1423  sizeof (tr->src.as_u8));
1424  clib_memcpy_fast (tr->dst.as_u8, ip3->dst_address.as_u8,
1425  sizeof (tr->dst.as_u8));
1426  }
1427  }
1428 
1429  encap_pkts += 4;
1431  n_left_to_next, bi0, bi1, bi2, bi3,
1432  next0, next1, next2, next3);
1433  }
1434 
1435  /* Single loop for potentially the last three packets */
1436  while (n_left_from > 0 && n_left_to_next > 0)
1437  {
1438  u32 bi0;
1439  vlib_buffer_t *b0;
1440  ip6_header_t *ip0 = 0, *ip0_encap = 0;
1441  ip6_sr_sl_t *sl0;
1442  u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1443 
1444  bi0 = from[0];
1445  to_next[0] = bi0;
1446  from += 1;
1447  to_next += 1;
1448  n_left_from -= 1;
1449  n_left_to_next -= 1;
1450  b0 = vlib_get_buffer (vm, bi0);
1451 
1452  sl0 =
1454  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1456  vec_len (sl0->rewrite));
1457 
1458  ip0_encap = vlib_buffer_get_current (b0);
1459 
1460  clib_memcpy_fast (((u8 *) ip0_encap) - vec_len (sl0->rewrite),
1461  sl0->rewrite, vec_len (sl0->rewrite));
1462  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
1463 
1464  ip0 = vlib_buffer_get_current (b0);
1465 
1466  encaps_processing_v6 (node, b0, ip0, ip0_encap);
1467 
1468  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sl0->egress_fib_table;
1469 
1470  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1471  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1472  {
1474  vlib_add_trace (vm, node, b0, sizeof (*tr));
1475  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
1476  sizeof (tr->src.as_u8));
1477  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
1478  sizeof (tr->dst.as_u8));
1479  }
1480 
1481  encap_pkts++;
1483  n_left_to_next, bi0, next0);
1484  }
1485 
1486  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1487  }
1488 
1489  /* Update counters */
1491  SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
1492  encap_pkts);
1494  SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
1495  bsid_pkts);
1496 
1497  return from_frame->n_vectors;
1498 }
1499 
1500 /* *INDENT-OFF* */
1502  .function = sr_policy_rewrite_encaps,
1503  .name = "sr-pl-rewrite-encaps",
1504  .vector_size = sizeof (u32),
1505  .format_trace = format_sr_policy_rewrite_trace,
1507  .n_errors = SR_POLICY_REWRITE_N_ERROR,
1508  .error_strings = sr_policy_rewrite_error_strings,
1509  .n_next_nodes = SR_POLICY_REWRITE_N_NEXT,
1510  .next_nodes = {
1511 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n,
1513 #undef _
1514  },
1515 };
1516 /* *INDENT-ON* */
1517 
1518 /**
1519  * @brief IPv4 encapsulation processing as per RFC2473
1520  */
1523  vlib_buffer_t * b0,
1524  ip6_header_t * ip0, ip4_header_t * ip0_encap)
1525 {
1526  u32 new_l0;
1527  ip6_sr_header_t *sr0;
1528 
1529  u32 checksum0;
1530  u32 flow_label;
1531 
1532  /* Inner IPv4: Decrement TTL & update checksum */
1533  ip0_encap->ttl -= 1;
1534  checksum0 = ip0_encap->checksum + clib_host_to_net_u16 (0x0100);
1535  checksum0 += checksum0 >= 0xffff;
1536  ip0_encap->checksum = checksum0;
1537 
1538  /* Outer IPv6: Update length, FL, proto */
1539  new_l0 = ip0->payload_length + clib_net_to_host_u16 (ip0_encap->length);
1540  ip0->payload_length = clib_host_to_net_u16 (new_l0);
1541  flow_label = ip4_compute_flow_hash (ip0_encap, IP_FLOW_HASH_DEFAULT);
1542  ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
1543  0 | ((6 & 0xF) << 28) | ((ip0_encap->tos & 0xFF) << 20) |
1544  (flow_label & 0x0000ffff));
1545  if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE)
1546  {
1547  sr0 = (void *) (ip0 + 1);
1548  sr0->protocol = IP_PROTOCOL_IP_IN_IP;
1549  }
1550  else
1551  ip0->protocol = IP_PROTOCOL_IP_IN_IP;
1552 }
1553 
1554 /**
1555  * @brief Graph node for applying a SR policy into an IPv4 packet. Encapsulation
1556  */
1557 static uword
1560 {
1561  ip6_sr_main_t *sm = &sr_main;
1562  u32 n_left_from, next_index, *from, *to_next;
1563 
1565  n_left_from = from_frame->n_vectors;
1566 
1567  next_index = node->cached_next_index;
1568 
1569  int encap_pkts = 0, bsid_pkts = 0;
1570 
1571  while (n_left_from > 0)
1572  {
1573  u32 n_left_to_next;
1574 
1575  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1576 
1577  /* Quad - Loop */
1578  while (n_left_from >= 8 && n_left_to_next >= 4)
1579  {
1580  u32 bi0, bi1, bi2, bi3;
1581  vlib_buffer_t *b0, *b1, *b2, *b3;
1582  u32 next0, next1, next2, next3;
1583  next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1584  ip6_header_t *ip0, *ip1, *ip2, *ip3;
1585  ip4_header_t *ip0_encap, *ip1_encap, *ip2_encap, *ip3_encap;
1586  ip6_sr_sl_t *sl0, *sl1, *sl2, *sl3;
1587 
1588  /* Prefetch next iteration. */
1589  {
1590  vlib_buffer_t *p4, *p5, *p6, *p7;
1591 
1592  p4 = vlib_get_buffer (vm, from[4]);
1593  p5 = vlib_get_buffer (vm, from[5]);
1594  p6 = vlib_get_buffer (vm, from[6]);
1595  p7 = vlib_get_buffer (vm, from[7]);
1596 
1597  /* Prefetch the buffer header and packet for the N+2 loop iteration */
1598  vlib_prefetch_buffer_header (p4, LOAD);
1599  vlib_prefetch_buffer_header (p5, LOAD);
1600  vlib_prefetch_buffer_header (p6, LOAD);
1601  vlib_prefetch_buffer_header (p7, LOAD);
1602 
1607  }
1608 
1609  to_next[0] = bi0 = from[0];
1610  to_next[1] = bi1 = from[1];
1611  to_next[2] = bi2 = from[2];
1612  to_next[3] = bi3 = from[3];
1613  from += 4;
1614  to_next += 4;
1615  n_left_from -= 4;
1616  n_left_to_next -= 4;
1617 
1618  b0 = vlib_get_buffer (vm, bi0);
1619  b1 = vlib_get_buffer (vm, bi1);
1620  b2 = vlib_get_buffer (vm, bi2);
1621  b3 = vlib_get_buffer (vm, bi3);
1622 
1623  sl0 =
1625  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1626  sl1 =
1628  vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
1629  sl2 =
1631  vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
1632  sl3 =
1634  vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
1636  vec_len (sl0->rewrite));
1638  vec_len (sl1->rewrite));
1640  vec_len (sl2->rewrite));
1642  vec_len (sl3->rewrite));
1643 
1644  ip0_encap = vlib_buffer_get_current (b0);
1645  ip1_encap = vlib_buffer_get_current (b1);
1646  ip2_encap = vlib_buffer_get_current (b2);
1647  ip3_encap = vlib_buffer_get_current (b3);
1648 
1649  clib_memcpy_fast (((u8 *) ip0_encap) - vec_len (sl0->rewrite),
1650  sl0->rewrite, vec_len (sl0->rewrite));
1651  clib_memcpy_fast (((u8 *) ip1_encap) - vec_len (sl1->rewrite),
1652  sl1->rewrite, vec_len (sl1->rewrite));
1653  clib_memcpy_fast (((u8 *) ip2_encap) - vec_len (sl2->rewrite),
1654  sl2->rewrite, vec_len (sl2->rewrite));
1655  clib_memcpy_fast (((u8 *) ip3_encap) - vec_len (sl3->rewrite),
1656  sl3->rewrite, vec_len (sl3->rewrite));
1657 
1658  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
1659  vlib_buffer_advance (b1, -(word) vec_len (sl1->rewrite));
1660  vlib_buffer_advance (b2, -(word) vec_len (sl2->rewrite));
1661  vlib_buffer_advance (b3, -(word) vec_len (sl3->rewrite));
1662 
1663  ip0 = vlib_buffer_get_current (b0);
1664  ip1 = vlib_buffer_get_current (b1);
1665  ip2 = vlib_buffer_get_current (b2);
1666  ip3 = vlib_buffer_get_current (b3);
1667 
1668  encaps_processing_v4 (node, b0, ip0, ip0_encap);
1669  encaps_processing_v4 (node, b1, ip1, ip1_encap);
1670  encaps_processing_v4 (node, b2, ip2, ip2_encap);
1671  encaps_processing_v4 (node, b3, ip3, ip3_encap);
1672 
1673  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sl0->egress_fib_table;
1674  vnet_buffer (b1)->sw_if_index[VLIB_TX] = sl1->egress_fib_table;
1675  vnet_buffer (b2)->sw_if_index[VLIB_TX] = sl2->egress_fib_table;
1676  vnet_buffer (b3)->sw_if_index[VLIB_TX] = sl3->egress_fib_table;
1677 
1678  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
1679  {
1680  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1681  {
1683  vlib_add_trace (vm, node, b0, sizeof (*tr));
1684  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
1685  sizeof (tr->src.as_u8));
1686  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
1687  sizeof (tr->dst.as_u8));
1688  }
1689 
1690  if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
1691  {
1693  vlib_add_trace (vm, node, b1, sizeof (*tr));
1694  clib_memcpy_fast (tr->src.as_u8, ip1->src_address.as_u8,
1695  sizeof (tr->src.as_u8));
1696  clib_memcpy_fast (tr->dst.as_u8, ip1->dst_address.as_u8,
1697  sizeof (tr->dst.as_u8));
1698  }
1699 
1700  if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
1701  {
1703  vlib_add_trace (vm, node, b2, sizeof (*tr));
1704  clib_memcpy_fast (tr->src.as_u8, ip2->src_address.as_u8,
1705  sizeof (tr->src.as_u8));
1706  clib_memcpy_fast (tr->dst.as_u8, ip2->dst_address.as_u8,
1707  sizeof (tr->dst.as_u8));
1708  }
1709 
1710  if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
1711  {
1713  vlib_add_trace (vm, node, b3, sizeof (*tr));
1714  clib_memcpy_fast (tr->src.as_u8, ip3->src_address.as_u8,
1715  sizeof (tr->src.as_u8));
1716  clib_memcpy_fast (tr->dst.as_u8, ip3->dst_address.as_u8,
1717  sizeof (tr->dst.as_u8));
1718  }
1719  }
1720 
1721  encap_pkts += 4;
1723  n_left_to_next, bi0, bi1, bi2, bi3,
1724  next0, next1, next2, next3);
1725  }
1726 
1727  /* Single loop for potentially the last three packets */
1728  while (n_left_from > 0 && n_left_to_next > 0)
1729  {
1730  u32 bi0;
1731  vlib_buffer_t *b0;
1732  ip6_header_t *ip0 = 0;
1733  ip4_header_t *ip0_encap = 0;
1734  ip6_sr_sl_t *sl0;
1735  u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1736 
1737  bi0 = from[0];
1738  to_next[0] = bi0;
1739  from += 1;
1740  to_next += 1;
1741  n_left_from -= 1;
1742  n_left_to_next -= 1;
1743  b0 = vlib_get_buffer (vm, bi0);
1744 
1745  sl0 =
1747  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1749  vec_len (sl0->rewrite));
1750 
1751  ip0_encap = vlib_buffer_get_current (b0);
1752 
1753  clib_memcpy_fast (((u8 *) ip0_encap) - vec_len (sl0->rewrite),
1754  sl0->rewrite, vec_len (sl0->rewrite));
1755  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
1756 
1757  ip0 = vlib_buffer_get_current (b0);
1758 
1759  encaps_processing_v4 (node, b0, ip0, ip0_encap);
1760 
1761  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sl0->egress_fib_table;
1762 
1763  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
1764  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
1765  {
1767  vlib_add_trace (vm, node, b0, sizeof (*tr));
1768  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
1769  sizeof (tr->src.as_u8));
1770  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
1771  sizeof (tr->dst.as_u8));
1772  }
1773 
1774  encap_pkts++;
1776  n_left_to_next, bi0, next0);
1777  }
1778 
1779  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1780  }
1781 
1782  /* Update counters */
1784  SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
1785  encap_pkts);
1787  SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
1788  bsid_pkts);
1789 
1790  return from_frame->n_vectors;
1791 }
1792 
1793 /* *INDENT-OFF* */
1795  .function = sr_policy_rewrite_encaps_v4,
1796  .name = "sr-pl-rewrite-encaps-v4",
1797  .vector_size = sizeof (u32),
1798  .format_trace = format_sr_policy_rewrite_trace,
1800  .n_errors = SR_POLICY_REWRITE_N_ERROR,
1801  .error_strings = sr_policy_rewrite_error_strings,
1802  .n_next_nodes = SR_POLICY_REWRITE_N_NEXT,
1803  .next_nodes = {
1804 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n,
1806 #undef _
1807  },
1808 };
1809 /* *INDENT-ON* */
1810 
1813 {
1814  ip4_header_t *iph = (ip4_header_t *) data;
1815 
1816  if ((iph->ip_version_and_header_length & 0xF0) == 0x40)
1818  else
1820 }
1821 
1824 {
1825  return (*((u64 *) m) & 0xffffffffffff);
1826 }
1827 
1830 {
1831  ethernet_header_t *eh;
1832  u64 a, b, c;
1833  uword is_ip, eh_size;
1834  u16 eh_type;
1835 
1836  eh = vlib_buffer_get_current (b0);
1837  eh_type = clib_net_to_host_u16 (eh->type);
1838  eh_size = ethernet_buffer_header_size (b0);
1839 
1840  is_ip = (eh_type == ETHERNET_TYPE_IP4 || eh_type == ETHERNET_TYPE_IP6);
1841 
1842  /* since we have 2 cache lines, use them */
1843  if (is_ip)
1844  a = ip_flow_hash ((u8 *) vlib_buffer_get_current (b0) + eh_size);
1845  else
1846  a = eh->type;
1847 
1848  b = mac_to_u64 ((u8 *) eh->dst_address);
1849  c = mac_to_u64 ((u8 *) eh->src_address);
1850  hash_mix64 (a, b, c);
1851 
1852  return (u32) c;
1853 }
1854 
1855 /**
1856  * @brief Graph node for applying a SR policy into a L2 frame
1857  */
1858 static uword
1861 {
1862  ip6_sr_main_t *sm = &sr_main;
1863  u32 n_left_from, next_index, *from, *to_next;
1864 
1866  n_left_from = from_frame->n_vectors;
1867 
1868  next_index = node->cached_next_index;
1869 
1870  int encap_pkts = 0, bsid_pkts = 0;
1871 
1872  while (n_left_from > 0)
1873  {
1874  u32 n_left_to_next;
1875 
1876  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1877 
1878  /* Quad - Loop */
1879  while (n_left_from >= 8 && n_left_to_next >= 4)
1880  {
1881  u32 bi0, bi1, bi2, bi3;
1882  vlib_buffer_t *b0, *b1, *b2, *b3;
1883  u32 next0, next1, next2, next3;
1884  next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1885  ethernet_header_t *en0, *en1, *en2, *en3;
1886  ip6_header_t *ip0, *ip1, *ip2, *ip3;
1887  ip6_sr_header_t *sr0, *sr1, *sr2, *sr3;
1888  ip6_sr_policy_t *sp0, *sp1, *sp2, *sp3;
1889  ip6_sr_sl_t *sl0, *sl1, *sl2, *sl3;
1890  u32 flow_label0, flow_label1, flow_label2, flow_label3;
1891 
1892  /* Prefetch next iteration. */
1893  {
1894  vlib_buffer_t *p4, *p5, *p6, *p7;
1895 
1896  p4 = vlib_get_buffer (vm, from[4]);
1897  p5 = vlib_get_buffer (vm, from[5]);
1898  p6 = vlib_get_buffer (vm, from[6]);
1899  p7 = vlib_get_buffer (vm, from[7]);
1900 
1901  /* Prefetch the buffer header and packet for the N+2 loop iteration */
1902  vlib_prefetch_buffer_header (p4, LOAD);
1903  vlib_prefetch_buffer_header (p5, LOAD);
1904  vlib_prefetch_buffer_header (p6, LOAD);
1905  vlib_prefetch_buffer_header (p7, LOAD);
1906 
1911  }
1912 
1913  to_next[0] = bi0 = from[0];
1914  to_next[1] = bi1 = from[1];
1915  to_next[2] = bi2 = from[2];
1916  to_next[3] = bi3 = from[3];
1917  from += 4;
1918  to_next += 4;
1919  n_left_from -= 4;
1920  n_left_to_next -= 4;
1921 
1922  b0 = vlib_get_buffer (vm, bi0);
1923  b1 = vlib_get_buffer (vm, bi1);
1924  b2 = vlib_get_buffer (vm, bi2);
1925  b3 = vlib_get_buffer (vm, bi3);
1926 
1927  sp0 = pool_elt_at_index (sm->sr_policies,
1929  (b0)->sw_if_index
1930  [VLIB_RX]]);
1931 
1932  sp1 = pool_elt_at_index (sm->sr_policies,
1934  (b1)->sw_if_index
1935  [VLIB_RX]]);
1936 
1937  sp2 = pool_elt_at_index (sm->sr_policies,
1939  (b2)->sw_if_index
1940  [VLIB_RX]]);
1941 
1942  sp3 = pool_elt_at_index (sm->sr_policies,
1944  (b3)->sw_if_index
1945  [VLIB_RX]]);
1946  flow_label0 = l2_flow_hash (b0);
1947  flow_label1 = l2_flow_hash (b1);
1948  flow_label2 = l2_flow_hash (b2);
1949  flow_label3 = l2_flow_hash (b3);
1950 
1951  if (vec_len (sp0->segments_lists) == 1)
1952  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = sp0->segments_lists[0];
1953  else
1954  {
1955  vnet_buffer (b0)->ip.flow_hash = flow_label0;
1956  vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
1957  sp0->segments_lists[(vnet_buffer (b0)->ip.flow_hash &
1958  (vec_len (sp0->segments_lists) - 1))];
1959  }
1960 
1961  if (vec_len (sp1->segments_lists) == 1)
1962  vnet_buffer (b1)->ip.adj_index[VLIB_TX] = sp1->segments_lists[1];
1963  else
1964  {
1965  vnet_buffer (b1)->ip.flow_hash = flow_label1;
1966  vnet_buffer (b1)->ip.adj_index[VLIB_TX] =
1967  sp1->segments_lists[(vnet_buffer (b1)->ip.flow_hash &
1968  (vec_len (sp1->segments_lists) - 1))];
1969  }
1970 
1971  if (vec_len (sp2->segments_lists) == 1)
1972  vnet_buffer (b2)->ip.adj_index[VLIB_TX] = sp2->segments_lists[2];
1973  else
1974  {
1975  vnet_buffer (b2)->ip.flow_hash = flow_label2;
1976  vnet_buffer (b2)->ip.adj_index[VLIB_TX] =
1977  sp2->segments_lists[(vnet_buffer (b2)->ip.flow_hash &
1978  (vec_len (sp2->segments_lists) - 1))];
1979  }
1980 
1981  if (vec_len (sp3->segments_lists) == 1)
1982  vnet_buffer (b3)->ip.adj_index[VLIB_TX] = sp3->segments_lists[3];
1983  else
1984  {
1985  vnet_buffer (b3)->ip.flow_hash = flow_label3;
1986  vnet_buffer (b3)->ip.adj_index[VLIB_TX] =
1987  sp3->segments_lists[(vnet_buffer (b3)->ip.flow_hash &
1988  (vec_len (sp3->segments_lists) - 1))];
1989  }
1990 
1991  sl0 =
1993  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
1994  sl1 =
1996  vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
1997  sl2 =
1999  vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
2000  sl3 =
2002  vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
2003 
2005  vec_len (sl0->rewrite));
2007  vec_len (sl1->rewrite));
2009  vec_len (sl2->rewrite));
2011  vec_len (sl3->rewrite));
2012 
2013  en0 = vlib_buffer_get_current (b0);
2014  en1 = vlib_buffer_get_current (b1);
2015  en2 = vlib_buffer_get_current (b2);
2016  en3 = vlib_buffer_get_current (b3);
2017 
2018  clib_memcpy_fast (((u8 *) en0) - vec_len (sl0->rewrite),
2019  sl0->rewrite, vec_len (sl0->rewrite));
2020  clib_memcpy_fast (((u8 *) en1) - vec_len (sl1->rewrite),
2021  sl1->rewrite, vec_len (sl1->rewrite));
2022  clib_memcpy_fast (((u8 *) en2) - vec_len (sl2->rewrite),
2023  sl2->rewrite, vec_len (sl2->rewrite));
2024  clib_memcpy_fast (((u8 *) en3) - vec_len (sl3->rewrite),
2025  sl3->rewrite, vec_len (sl3->rewrite));
2026 
2027  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
2028  vlib_buffer_advance (b1, -(word) vec_len (sl1->rewrite));
2029  vlib_buffer_advance (b2, -(word) vec_len (sl2->rewrite));
2030  vlib_buffer_advance (b3, -(word) vec_len (sl3->rewrite));
2031 
2032  ip0 = vlib_buffer_get_current (b0);
2033  ip1 = vlib_buffer_get_current (b1);
2034  ip2 = vlib_buffer_get_current (b2);
2035  ip3 = vlib_buffer_get_current (b3);
2036 
2037  ip0->payload_length =
2038  clib_host_to_net_u16 (b0->current_length - sizeof (ip6_header_t));
2039  ip1->payload_length =
2040  clib_host_to_net_u16 (b1->current_length - sizeof (ip6_header_t));
2041  ip2->payload_length =
2042  clib_host_to_net_u16 (b2->current_length - sizeof (ip6_header_t));
2043  ip3->payload_length =
2044  clib_host_to_net_u16 (b3->current_length - sizeof (ip6_header_t));
2045 
2046  if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE)
2047  {
2048  sr0 = (void *) (ip0 + 1);
2050  }
2051  else
2053 
2054  if (ip1->protocol == IP_PROTOCOL_IPV6_ROUTE)
2055  {
2056  sr1 = (void *) (ip1 + 1);
2058  }
2059  else
2061 
2062  if (ip2->protocol == IP_PROTOCOL_IPV6_ROUTE)
2063  {
2064  sr2 = (void *) (ip2 + 1);
2066  }
2067  else
2069 
2070  if (ip3->protocol == IP_PROTOCOL_IPV6_ROUTE)
2071  {
2072  sr3 = (void *) (ip3 + 1);
2074  }
2075  else
2077 
2078  /* TC is set to 0 for all ethernet frames, should be taken from COS
2079  * od DSCP of encapsulated packet in the future */
2080  ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
2081  0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label0 & 0xffff));
2082  ip1->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
2083  0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label1 & 0xffff));
2084  ip2->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
2085  0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label2 & 0xffff));
2086  ip3->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
2087  0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label3 & 0xffff));
2088 
2089  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
2090  {
2091  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2092  {
2094  vlib_add_trace (vm, node, b0, sizeof (*tr));
2095  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
2096  sizeof (tr->src.as_u8));
2097  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
2098  sizeof (tr->dst.as_u8));
2099  }
2100 
2101  if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
2102  {
2104  vlib_add_trace (vm, node, b1, sizeof (*tr));
2105  clib_memcpy_fast (tr->src.as_u8, ip1->src_address.as_u8,
2106  sizeof (tr->src.as_u8));
2107  clib_memcpy_fast (tr->dst.as_u8, ip1->dst_address.as_u8,
2108  sizeof (tr->dst.as_u8));
2109  }
2110 
2111  if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
2112  {
2114  vlib_add_trace (vm, node, b2, sizeof (*tr));
2115  clib_memcpy_fast (tr->src.as_u8, ip2->src_address.as_u8,
2116  sizeof (tr->src.as_u8));
2117  clib_memcpy_fast (tr->dst.as_u8, ip2->dst_address.as_u8,
2118  sizeof (tr->dst.as_u8));
2119  }
2120 
2121  if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
2122  {
2124  vlib_add_trace (vm, node, b3, sizeof (*tr));
2125  clib_memcpy_fast (tr->src.as_u8, ip3->src_address.as_u8,
2126  sizeof (tr->src.as_u8));
2127  clib_memcpy_fast (tr->dst.as_u8, ip3->dst_address.as_u8,
2128  sizeof (tr->dst.as_u8));
2129  }
2130  }
2131 
2132  encap_pkts += 4;
2134  n_left_to_next, bi0, bi1, bi2, bi3,
2135  next0, next1, next2, next3);
2136  }
2137 
2138  /* Single loop for potentially the last three packets */
2139  while (n_left_from > 0 && n_left_to_next > 0)
2140  {
2141  u32 bi0;
2142  vlib_buffer_t *b0;
2143  ip6_header_t *ip0 = 0;
2144  ip6_sr_header_t *sr0;
2145  ethernet_header_t *en0;
2146  ip6_sr_policy_t *sp0;
2147  ip6_sr_sl_t *sl0;
2148  u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2149  u32 flow_label0;
2150 
2151  bi0 = from[0];
2152  to_next[0] = bi0;
2153  from += 1;
2154  to_next += 1;
2155  n_left_from -= 1;
2156  n_left_to_next -= 1;
2157  b0 = vlib_get_buffer (vm, bi0);
2158 
2159  /* Find the SR policy */
2160  sp0 = pool_elt_at_index (sm->sr_policies,
2162  (b0)->sw_if_index
2163  [VLIB_RX]]);
2164  flow_label0 = l2_flow_hash (b0);
2165 
2166  /* In case there is more than one SL, LB among them */
2167  if (vec_len (sp0->segments_lists) == 1)
2168  vnet_buffer (b0)->ip.adj_index[VLIB_TX] = sp0->segments_lists[0];
2169  else
2170  {
2171  vnet_buffer (b0)->ip.flow_hash = flow_label0;
2172  vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
2173  sp0->segments_lists[(vnet_buffer (b0)->ip.flow_hash &
2174  (vec_len (sp0->segments_lists) - 1))];
2175  }
2176  sl0 =
2178  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2180  vec_len (sl0->rewrite));
2181 
2182  en0 = vlib_buffer_get_current (b0);
2183 
2184  clib_memcpy_fast (((u8 *) en0) - vec_len (sl0->rewrite),
2185  sl0->rewrite, vec_len (sl0->rewrite));
2186 
2187  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
2188 
2189  ip0 = vlib_buffer_get_current (b0);
2190 
2191  ip0->payload_length =
2192  clib_host_to_net_u16 (b0->current_length - sizeof (ip6_header_t));
2193 
2194  if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE)
2195  {
2196  sr0 = (void *) (ip0 + 1);
2198  }
2199  else
2201 
2202  ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (
2203  0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label0 & 0xffff));
2204 
2205  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2206  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2207  {
2209  vlib_add_trace (vm, node, b0, sizeof (*tr));
2210  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
2211  sizeof (tr->src.as_u8));
2212  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
2213  sizeof (tr->dst.as_u8));
2214  }
2215 
2216  encap_pkts++;
2218  n_left_to_next, bi0, next0);
2219  }
2220 
2221  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2222  }
2223 
2224  /* Update counters */
2226  SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
2227  encap_pkts);
2229  SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
2230  bsid_pkts);
2231 
2232  return from_frame->n_vectors;
2233 }
2234 
2235 /* *INDENT-OFF* */
2237  .function = sr_policy_rewrite_encaps_l2,
2238  .name = "sr-pl-rewrite-encaps-l2",
2239  .vector_size = sizeof (u32),
2240  .format_trace = format_sr_policy_rewrite_trace,
2242  .n_errors = SR_POLICY_REWRITE_N_ERROR,
2243  .error_strings = sr_policy_rewrite_error_strings,
2244  .n_next_nodes = SR_POLICY_REWRITE_N_NEXT,
2245  .next_nodes = {
2246 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n,
2248 #undef _
2249  },
2250 };
2251 /* *INDENT-ON* */
2252 
2253 /**
2254  * @brief Graph node for applying a SR policy into a packet. SRH insertion.
2255  */
2256 static uword
2259 {
2260  ip6_sr_main_t *sm = &sr_main;
2261  u32 n_left_from, next_index, *from, *to_next;
2262 
2264  n_left_from = from_frame->n_vectors;
2265 
2266  next_index = node->cached_next_index;
2267 
2268  int insert_pkts = 0, bsid_pkts = 0;
2269 
2270  while (n_left_from > 0)
2271  {
2272  u32 n_left_to_next;
2273 
2274  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2275 
2276  /* Quad - Loop */
2277  while (n_left_from >= 8 && n_left_to_next >= 4)
2278  {
2279  u32 bi0, bi1, bi2, bi3;
2280  vlib_buffer_t *b0, *b1, *b2, *b3;
2281  u32 next0, next1, next2, next3;
2282  next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2283  ip6_header_t *ip0, *ip1, *ip2, *ip3;
2284  ip6_sr_header_t *sr0, *sr1, *sr2, *sr3;
2285  ip6_sr_sl_t *sl0, *sl1, *sl2, *sl3;
2286  u16 new_l0, new_l1, new_l2, new_l3;
2287 
2288  /* Prefetch next iteration. */
2289  {
2290  vlib_buffer_t *p4, *p5, *p6, *p7;
2291 
2292  p4 = vlib_get_buffer (vm, from[4]);
2293  p5 = vlib_get_buffer (vm, from[5]);
2294  p6 = vlib_get_buffer (vm, from[6]);
2295  p7 = vlib_get_buffer (vm, from[7]);
2296 
2297  /* Prefetch the buffer header and packet for the N+2 loop iteration */
2298  vlib_prefetch_buffer_header (p4, LOAD);
2299  vlib_prefetch_buffer_header (p5, LOAD);
2300  vlib_prefetch_buffer_header (p6, LOAD);
2301  vlib_prefetch_buffer_header (p7, LOAD);
2302 
2307  }
2308 
2309  to_next[0] = bi0 = from[0];
2310  to_next[1] = bi1 = from[1];
2311  to_next[2] = bi2 = from[2];
2312  to_next[3] = bi3 = from[3];
2313  from += 4;
2314  to_next += 4;
2315  n_left_from -= 4;
2316  n_left_to_next -= 4;
2317 
2318  b0 = vlib_get_buffer (vm, bi0);
2319  b1 = vlib_get_buffer (vm, bi1);
2320  b2 = vlib_get_buffer (vm, bi2);
2321  b3 = vlib_get_buffer (vm, bi3);
2322 
2323  sl0 =
2325  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2326  sl1 =
2328  vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
2329  sl2 =
2331  vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
2332  sl3 =
2334  vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
2336  vec_len (sl0->rewrite));
2338  vec_len (sl1->rewrite));
2340  vec_len (sl2->rewrite));
2342  vec_len (sl3->rewrite));
2343 
2344  ip0 = vlib_buffer_get_current (b0);
2345  ip1 = vlib_buffer_get_current (b1);
2346  ip2 = vlib_buffer_get_current (b2);
2347  ip3 = vlib_buffer_get_current (b3);
2348 
2349  if (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2350  sr0 =
2351  (ip6_sr_header_t *) (((void *) (ip0 + 1)) +
2352  ip6_ext_header_len (ip0 + 1));
2353  else
2354  sr0 = (ip6_sr_header_t *) (ip0 + 1);
2355 
2356  if (ip1->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2357  sr1 =
2358  (ip6_sr_header_t *) (((void *) (ip1 + 1)) +
2359  ip6_ext_header_len (ip1 + 1));
2360  else
2361  sr1 = (ip6_sr_header_t *) (ip1 + 1);
2362 
2363  if (ip2->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2364  sr2 =
2365  (ip6_sr_header_t *) (((void *) (ip2 + 1)) +
2366  ip6_ext_header_len (ip2 + 1));
2367  else
2368  sr2 = (ip6_sr_header_t *) (ip2 + 1);
2369 
2370  if (ip3->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2371  sr3 =
2372  (ip6_sr_header_t *) (((void *) (ip3 + 1)) +
2373  ip6_ext_header_len (ip3 + 1));
2374  else
2375  sr3 = (ip6_sr_header_t *) (ip3 + 1);
2376 
2377  clib_memcpy_fast ((u8 *) ip0 - vec_len (sl0->rewrite), (u8 *) ip0,
2378  (void *) sr0 - (void *) ip0);
2379  clib_memcpy_fast ((u8 *) ip1 - vec_len (sl1->rewrite), (u8 *) ip1,
2380  (void *) sr1 - (void *) ip1);
2381  clib_memcpy_fast ((u8 *) ip2 - vec_len (sl2->rewrite), (u8 *) ip2,
2382  (void *) sr2 - (void *) ip2);
2383  clib_memcpy_fast ((u8 *) ip3 - vec_len (sl3->rewrite), (u8 *) ip3,
2384  (void *) sr3 - (void *) ip3);
2385 
2386  clib_memcpy_fast (((u8 *) sr0 - vec_len (sl0->rewrite)),
2387  sl0->rewrite, vec_len (sl0->rewrite));
2388  clib_memcpy_fast (((u8 *) sr1 - vec_len (sl1->rewrite)),
2389  sl1->rewrite, vec_len (sl1->rewrite));
2390  clib_memcpy_fast (((u8 *) sr2 - vec_len (sl2->rewrite)),
2391  sl2->rewrite, vec_len (sl2->rewrite));
2392  clib_memcpy_fast (((u8 *) sr3 - vec_len (sl3->rewrite)),
2393  sl3->rewrite, vec_len (sl3->rewrite));
2394 
2395  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
2396  vlib_buffer_advance (b1, -(word) vec_len (sl1->rewrite));
2397  vlib_buffer_advance (b2, -(word) vec_len (sl2->rewrite));
2398  vlib_buffer_advance (b3, -(word) vec_len (sl3->rewrite));
2399 
2400  ip0 = ((void *) ip0) - vec_len (sl0->rewrite);
2401  ip1 = ((void *) ip1) - vec_len (sl1->rewrite);
2402  ip2 = ((void *) ip2) - vec_len (sl2->rewrite);
2403  ip3 = ((void *) ip3) - vec_len (sl3->rewrite);
2404 
2405  ip0->hop_limit -= 1;
2406  ip1->hop_limit -= 1;
2407  ip2->hop_limit -= 1;
2408  ip3->hop_limit -= 1;
2409 
2410  new_l0 =
2411  clib_net_to_host_u16 (ip0->payload_length) +
2412  vec_len (sl0->rewrite);
2413  new_l1 =
2414  clib_net_to_host_u16 (ip1->payload_length) +
2415  vec_len (sl1->rewrite);
2416  new_l2 =
2417  clib_net_to_host_u16 (ip2->payload_length) +
2418  vec_len (sl2->rewrite);
2419  new_l3 =
2420  clib_net_to_host_u16 (ip3->payload_length) +
2421  vec_len (sl3->rewrite);
2422 
2423  ip0->payload_length = clib_host_to_net_u16 (new_l0);
2424  ip1->payload_length = clib_host_to_net_u16 (new_l1);
2425  ip2->payload_length = clib_host_to_net_u16 (new_l2);
2426  ip3->payload_length = clib_host_to_net_u16 (new_l3);
2427 
2428  sr0 = ((void *) sr0) - vec_len (sl0->rewrite);
2429  sr1 = ((void *) sr1) - vec_len (sl1->rewrite);
2430  sr2 = ((void *) sr2) - vec_len (sl2->rewrite);
2431  sr3 = ((void *) sr3) - vec_len (sl3->rewrite);
2432 
2433  sr0->segments->as_u64[0] = ip0->dst_address.as_u64[0];
2434  sr0->segments->as_u64[1] = ip0->dst_address.as_u64[1];
2435  sr1->segments->as_u64[0] = ip1->dst_address.as_u64[0];
2436  sr1->segments->as_u64[1] = ip1->dst_address.as_u64[1];
2437  sr2->segments->as_u64[0] = ip2->dst_address.as_u64[0];
2438  sr2->segments->as_u64[1] = ip2->dst_address.as_u64[1];
2439  sr3->segments->as_u64[0] = ip3->dst_address.as_u64[0];
2440  sr3->segments->as_u64[1] = ip3->dst_address.as_u64[1];
2441 
2442  ip0->dst_address.as_u64[0] =
2443  (sr0->segments + sr0->segments_left)->as_u64[0];
2444  ip0->dst_address.as_u64[1] =
2445  (sr0->segments + sr0->segments_left)->as_u64[1];
2446  ip1->dst_address.as_u64[0] =
2447  (sr1->segments + sr1->segments_left)->as_u64[0];
2448  ip1->dst_address.as_u64[1] =
2449  (sr1->segments + sr1->segments_left)->as_u64[1];
2450  ip2->dst_address.as_u64[0] =
2451  (sr2->segments + sr2->segments_left)->as_u64[0];
2452  ip2->dst_address.as_u64[1] =
2453  (sr2->segments + sr2->segments_left)->as_u64[1];
2454  ip3->dst_address.as_u64[0] =
2455  (sr3->segments + sr3->segments_left)->as_u64[0];
2456  ip3->dst_address.as_u64[1] =
2457  (sr3->segments + sr3->segments_left)->as_u64[1];
2458 
2459  ip6_ext_header_t *ip_ext;
2460  if (ip0 + 1 == (void *) sr0)
2461  {
2462  sr0->protocol = ip0->protocol;
2463  ip0->protocol = IP_PROTOCOL_IPV6_ROUTE;
2464  }
2465  else
2466  {
2467  ip_ext = (void *) (ip0 + 1);
2468  sr0->protocol = ip_ext->next_hdr;
2469  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2470  }
2471 
2472  if (ip1 + 1 == (void *) sr1)
2473  {
2474  sr1->protocol = ip1->protocol;
2475  ip1->protocol = IP_PROTOCOL_IPV6_ROUTE;
2476  }
2477  else
2478  {
2479  ip_ext = (void *) (ip2 + 1);
2480  sr2->protocol = ip_ext->next_hdr;
2481  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2482  }
2483 
2484  if (ip2 + 1 == (void *) sr2)
2485  {
2486  sr2->protocol = ip2->protocol;
2487  ip2->protocol = IP_PROTOCOL_IPV6_ROUTE;
2488  }
2489  else
2490  {
2491  ip_ext = (void *) (ip2 + 1);
2492  sr2->protocol = ip_ext->next_hdr;
2493  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2494  }
2495 
2496  if (ip3 + 1 == (void *) sr3)
2497  {
2498  sr3->protocol = ip3->protocol;
2499  ip3->protocol = IP_PROTOCOL_IPV6_ROUTE;
2500  }
2501  else
2502  {
2503  ip_ext = (void *) (ip3 + 1);
2504  sr3->protocol = ip_ext->next_hdr;
2505  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2506  }
2507 
2508  insert_pkts += 4;
2509 
2510  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
2511  {
2512  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2513  {
2515  vlib_add_trace (vm, node, b0, sizeof (*tr));
2516  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
2517  sizeof (tr->src.as_u8));
2518  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
2519  sizeof (tr->dst.as_u8));
2520  }
2521 
2522  if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
2523  {
2525  vlib_add_trace (vm, node, b1, sizeof (*tr));
2526  clib_memcpy_fast (tr->src.as_u8, ip1->src_address.as_u8,
2527  sizeof (tr->src.as_u8));
2528  clib_memcpy_fast (tr->dst.as_u8, ip1->dst_address.as_u8,
2529  sizeof (tr->dst.as_u8));
2530  }
2531 
2532  if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
2533  {
2535  vlib_add_trace (vm, node, b2, sizeof (*tr));
2536  clib_memcpy_fast (tr->src.as_u8, ip2->src_address.as_u8,
2537  sizeof (tr->src.as_u8));
2538  clib_memcpy_fast (tr->dst.as_u8, ip2->dst_address.as_u8,
2539  sizeof (tr->dst.as_u8));
2540  }
2541 
2542  if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
2543  {
2545  vlib_add_trace (vm, node, b3, sizeof (*tr));
2546  clib_memcpy_fast (tr->src.as_u8, ip3->src_address.as_u8,
2547  sizeof (tr->src.as_u8));
2548  clib_memcpy_fast (tr->dst.as_u8, ip3->dst_address.as_u8,
2549  sizeof (tr->dst.as_u8));
2550  }
2551  }
2552 
2554  n_left_to_next, bi0, bi1, bi2, bi3,
2555  next0, next1, next2, next3);
2556  }
2557 
2558  /* Single loop for potentially the last three packets */
2559  while (n_left_from > 0 && n_left_to_next > 0)
2560  {
2561  u32 bi0;
2562  vlib_buffer_t *b0;
2563  ip6_header_t *ip0 = 0;
2564  ip6_sr_header_t *sr0 = 0;
2565  ip6_sr_sl_t *sl0;
2566  u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2567  u16 new_l0 = 0;
2568 
2569  bi0 = from[0];
2570  to_next[0] = bi0;
2571  from += 1;
2572  to_next += 1;
2573  n_left_from -= 1;
2574  n_left_to_next -= 1;
2575 
2576  b0 = vlib_get_buffer (vm, bi0);
2577  sl0 =
2579  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2581  vec_len (sl0->rewrite));
2582 
2583  ip0 = vlib_buffer_get_current (b0);
2584 
2585  if (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2586  sr0 =
2587  (ip6_sr_header_t *) (((void *) (ip0 + 1)) +
2588  ip6_ext_header_len (ip0 + 1));
2589  else
2590  sr0 = (ip6_sr_header_t *) (ip0 + 1);
2591 
2592  clib_memcpy_fast ((u8 *) ip0 - vec_len (sl0->rewrite), (u8 *) ip0,
2593  (void *) sr0 - (void *) ip0);
2594  clib_memcpy_fast (((u8 *) sr0 - vec_len (sl0->rewrite)),
2595  sl0->rewrite, vec_len (sl0->rewrite));
2596 
2597  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
2598 
2599  ip0 = ((void *) ip0) - vec_len (sl0->rewrite);
2600  ip0->hop_limit -= 1;
2601  new_l0 =
2602  clib_net_to_host_u16 (ip0->payload_length) +
2603  vec_len (sl0->rewrite);
2604  ip0->payload_length = clib_host_to_net_u16 (new_l0);
2605 
2606  sr0 = ((void *) sr0) - vec_len (sl0->rewrite);
2607  sr0->segments->as_u64[0] = ip0->dst_address.as_u64[0];
2608  sr0->segments->as_u64[1] = ip0->dst_address.as_u64[1];
2609 
2610  ip0->dst_address.as_u64[0] =
2611  (sr0->segments + sr0->segments_left)->as_u64[0];
2612  ip0->dst_address.as_u64[1] =
2613  (sr0->segments + sr0->segments_left)->as_u64[1];
2614 
2615  if (ip0 + 1 == (void *) sr0)
2616  {
2617  sr0->protocol = ip0->protocol;
2618  ip0->protocol = IP_PROTOCOL_IPV6_ROUTE;
2619  }
2620  else
2621  {
2622  ip6_ext_header_t *ip_ext = (void *) (ip0 + 1);
2623  sr0->protocol = ip_ext->next_hdr;
2624  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2625  }
2626 
2627  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
2628  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2629  {
2631  vlib_add_trace (vm, node, b0, sizeof (*tr));
2632  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
2633  sizeof (tr->src.as_u8));
2634  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
2635  sizeof (tr->dst.as_u8));
2636  }
2637 
2638  insert_pkts++;
2639 
2641  n_left_to_next, bi0, next0);
2642  }
2643 
2644  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2645  }
2646 
2647  /* Update counters */
2649  SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
2650  insert_pkts);
2652  SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
2653  bsid_pkts);
2654  return from_frame->n_vectors;
2655 }
2656 
2657 /* *INDENT-OFF* */
2659  .function = sr_policy_rewrite_insert,
2660  .name = "sr-pl-rewrite-insert",
2661  .vector_size = sizeof (u32),
2662  .format_trace = format_sr_policy_rewrite_trace,
2664  .n_errors = SR_POLICY_REWRITE_N_ERROR,
2665  .error_strings = sr_policy_rewrite_error_strings,
2666  .n_next_nodes = SR_POLICY_REWRITE_N_NEXT,
2667  .next_nodes = {
2668 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n,
2670 #undef _
2671  },
2672 };
2673 /* *INDENT-ON* */
2674 
2675 /**
2676  * @brief Graph node for applying a SR policy into a packet. BSID - SRH insertion.
2677  */
2678 static uword
2681 {
2682  ip6_sr_main_t *sm = &sr_main;
2683  u32 n_left_from, next_index, *from, *to_next;
2684 
2686  n_left_from = from_frame->n_vectors;
2687 
2688  next_index = node->cached_next_index;
2689 
2690  int insert_pkts = 0, bsid_pkts = 0;
2691 
2692  while (n_left_from > 0)
2693  {
2694  u32 n_left_to_next;
2695 
2696  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2697 
2698  /* Quad - Loop */
2699  while (n_left_from >= 8 && n_left_to_next >= 4)
2700  {
2701  u32 bi0, bi1, bi2, bi3;
2702  vlib_buffer_t *b0, *b1, *b2, *b3;
2703  u32 next0, next1, next2, next3;
2704  next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2705  ip6_header_t *ip0, *ip1, *ip2, *ip3;
2706  ip6_sr_header_t *sr0, *sr1, *sr2, *sr3;
2707  ip6_sr_sl_t *sl0, *sl1, *sl2, *sl3;
2708  u16 new_l0, new_l1, new_l2, new_l3;
2709 
2710  /* Prefetch next iteration. */
2711  {
2712  vlib_buffer_t *p4, *p5, *p6, *p7;
2713 
2714  p4 = vlib_get_buffer (vm, from[4]);
2715  p5 = vlib_get_buffer (vm, from[5]);
2716  p6 = vlib_get_buffer (vm, from[6]);
2717  p7 = vlib_get_buffer (vm, from[7]);
2718 
2719  /* Prefetch the buffer header and packet for the N+2 loop iteration */
2720  vlib_prefetch_buffer_header (p4, LOAD);
2721  vlib_prefetch_buffer_header (p5, LOAD);
2722  vlib_prefetch_buffer_header (p6, LOAD);
2723  vlib_prefetch_buffer_header (p7, LOAD);
2724 
2729  }
2730 
2731  to_next[0] = bi0 = from[0];
2732  to_next[1] = bi1 = from[1];
2733  to_next[2] = bi2 = from[2];
2734  to_next[3] = bi3 = from[3];
2735  from += 4;
2736  to_next += 4;
2737  n_left_from -= 4;
2738  n_left_to_next -= 4;
2739 
2740  b0 = vlib_get_buffer (vm, bi0);
2741  b1 = vlib_get_buffer (vm, bi1);
2742  b2 = vlib_get_buffer (vm, bi2);
2743  b3 = vlib_get_buffer (vm, bi3);
2744 
2745  sl0 =
2747  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2748  sl1 =
2750  vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
2751  sl2 =
2753  vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
2754  sl3 =
2756  vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
2758  vec_len (sl0->rewrite_bsid));
2760  vec_len (sl1->rewrite_bsid));
2762  vec_len (sl2->rewrite_bsid));
2764  vec_len (sl3->rewrite_bsid));
2765 
2766  ip0 = vlib_buffer_get_current (b0);
2767  ip1 = vlib_buffer_get_current (b1);
2768  ip2 = vlib_buffer_get_current (b2);
2769  ip3 = vlib_buffer_get_current (b3);
2770 
2771  if (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2772  sr0 =
2773  (ip6_sr_header_t *) (((void *) (ip0 + 1)) +
2774  ip6_ext_header_len (ip0 + 1));
2775  else
2776  sr0 = (ip6_sr_header_t *) (ip0 + 1);
2777 
2778  if (ip1->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2779  sr1 =
2780  (ip6_sr_header_t *) (((void *) (ip1 + 1)) +
2781  ip6_ext_header_len (ip1 + 1));
2782  else
2783  sr1 = (ip6_sr_header_t *) (ip1 + 1);
2784 
2785  if (ip2->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2786  sr2 =
2787  (ip6_sr_header_t *) (((void *) (ip2 + 1)) +
2788  ip6_ext_header_len (ip2 + 1));
2789  else
2790  sr2 = (ip6_sr_header_t *) (ip2 + 1);
2791 
2792  if (ip3->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2793  sr3 =
2794  (ip6_sr_header_t *) (((void *) (ip3 + 1)) +
2795  ip6_ext_header_len (ip3 + 1));
2796  else
2797  sr3 = (ip6_sr_header_t *) (ip3 + 1);
2798 
2799  clib_memcpy_fast ((u8 *) ip0 - vec_len (sl0->rewrite_bsid),
2800  (u8 *) ip0, (void *) sr0 - (void *) ip0);
2801  clib_memcpy_fast ((u8 *) ip1 - vec_len (sl1->rewrite_bsid),
2802  (u8 *) ip1, (void *) sr1 - (void *) ip1);
2803  clib_memcpy_fast ((u8 *) ip2 - vec_len (sl2->rewrite_bsid),
2804  (u8 *) ip2, (void *) sr2 - (void *) ip2);
2805  clib_memcpy_fast ((u8 *) ip3 - vec_len (sl3->rewrite_bsid),
2806  (u8 *) ip3, (void *) sr3 - (void *) ip3);
2807 
2808  clib_memcpy_fast (((u8 *) sr0 - vec_len (sl0->rewrite_bsid)),
2809  sl0->rewrite_bsid, vec_len (sl0->rewrite_bsid));
2810  clib_memcpy_fast (((u8 *) sr1 - vec_len (sl1->rewrite_bsid)),
2811  sl1->rewrite_bsid, vec_len (sl1->rewrite_bsid));
2812  clib_memcpy_fast (((u8 *) sr2 - vec_len (sl2->rewrite_bsid)),
2813  sl2->rewrite_bsid, vec_len (sl2->rewrite_bsid));
2814  clib_memcpy_fast (((u8 *) sr3 - vec_len (sl3->rewrite_bsid)),
2815  sl3->rewrite_bsid, vec_len (sl3->rewrite_bsid));
2816 
2817  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite_bsid));
2818  vlib_buffer_advance (b1, -(word) vec_len (sl1->rewrite_bsid));
2819  vlib_buffer_advance (b2, -(word) vec_len (sl2->rewrite_bsid));
2820  vlib_buffer_advance (b3, -(word) vec_len (sl3->rewrite_bsid));
2821 
2822  ip0 = ((void *) ip0) - vec_len (sl0->rewrite_bsid);
2823  ip1 = ((void *) ip1) - vec_len (sl1->rewrite_bsid);
2824  ip2 = ((void *) ip2) - vec_len (sl2->rewrite_bsid);
2825  ip3 = ((void *) ip3) - vec_len (sl3->rewrite_bsid);
2826 
2827  ip0->hop_limit -= 1;
2828  ip1->hop_limit -= 1;
2829  ip2->hop_limit -= 1;
2830  ip3->hop_limit -= 1;
2831 
2832  new_l0 =
2833  clib_net_to_host_u16 (ip0->payload_length) +
2834  vec_len (sl0->rewrite_bsid);
2835  new_l1 =
2836  clib_net_to_host_u16 (ip1->payload_length) +
2837  vec_len (sl1->rewrite_bsid);
2838  new_l2 =
2839  clib_net_to_host_u16 (ip2->payload_length) +
2840  vec_len (sl2->rewrite_bsid);
2841  new_l3 =
2842  clib_net_to_host_u16 (ip3->payload_length) +
2843  vec_len (sl3->rewrite_bsid);
2844 
2845  ip0->payload_length = clib_host_to_net_u16 (new_l0);
2846  ip1->payload_length = clib_host_to_net_u16 (new_l1);
2847  ip2->payload_length = clib_host_to_net_u16 (new_l2);
2848  ip3->payload_length = clib_host_to_net_u16 (new_l3);
2849 
2850  sr0 = ((void *) sr0) - vec_len (sl0->rewrite_bsid);
2851  sr1 = ((void *) sr1) - vec_len (sl1->rewrite_bsid);
2852  sr2 = ((void *) sr2) - vec_len (sl2->rewrite_bsid);
2853  sr3 = ((void *) sr3) - vec_len (sl3->rewrite_bsid);
2854 
2855  ip0->dst_address.as_u64[0] =
2856  (sr0->segments + sr0->segments_left)->as_u64[0];
2857  ip0->dst_address.as_u64[1] =
2858  (sr0->segments + sr0->segments_left)->as_u64[1];
2859  ip1->dst_address.as_u64[0] =
2860  (sr1->segments + sr1->segments_left)->as_u64[0];
2861  ip1->dst_address.as_u64[1] =
2862  (sr1->segments + sr1->segments_left)->as_u64[1];
2863  ip2->dst_address.as_u64[0] =
2864  (sr2->segments + sr2->segments_left)->as_u64[0];
2865  ip2->dst_address.as_u64[1] =
2866  (sr2->segments + sr2->segments_left)->as_u64[1];
2867  ip3->dst_address.as_u64[0] =
2868  (sr3->segments + sr3->segments_left)->as_u64[0];
2869  ip3->dst_address.as_u64[1] =
2870  (sr3->segments + sr3->segments_left)->as_u64[1];
2871 
2872  ip6_ext_header_t *ip_ext;
2873  if (ip0 + 1 == (void *) sr0)
2874  {
2875  sr0->protocol = ip0->protocol;
2876  ip0->protocol = IP_PROTOCOL_IPV6_ROUTE;
2877  }
2878  else
2879  {
2880  ip_ext = (void *) (ip0 + 1);
2881  sr0->protocol = ip_ext->next_hdr;
2882  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2883  }
2884 
2885  if (ip1 + 1 == (void *) sr1)
2886  {
2887  sr1->protocol = ip1->protocol;
2888  ip1->protocol = IP_PROTOCOL_IPV6_ROUTE;
2889  }
2890  else
2891  {
2892  ip_ext = (void *) (ip2 + 1);
2893  sr2->protocol = ip_ext->next_hdr;
2894  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2895  }
2896 
2897  if (ip2 + 1 == (void *) sr2)
2898  {
2899  sr2->protocol = ip2->protocol;
2900  ip2->protocol = IP_PROTOCOL_IPV6_ROUTE;
2901  }
2902  else
2903  {
2904  ip_ext = (void *) (ip2 + 1);
2905  sr2->protocol = ip_ext->next_hdr;
2906  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2907  }
2908 
2909  if (ip3 + 1 == (void *) sr3)
2910  {
2911  sr3->protocol = ip3->protocol;
2912  ip3->protocol = IP_PROTOCOL_IPV6_ROUTE;
2913  }
2914  else
2915  {
2916  ip_ext = (void *) (ip3 + 1);
2917  sr3->protocol = ip_ext->next_hdr;
2918  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2919  }
2920 
2921  insert_pkts += 4;
2922 
2923  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
2924  {
2925  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
2926  {
2928  vlib_add_trace (vm, node, b0, sizeof (*tr));
2929  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
2930  sizeof (tr->src.as_u8));
2931  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
2932  sizeof (tr->dst.as_u8));
2933  }
2934 
2935  if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
2936  {
2938  vlib_add_trace (vm, node, b1, sizeof (*tr));
2939  clib_memcpy_fast (tr->src.as_u8, ip1->src_address.as_u8,
2940  sizeof (tr->src.as_u8));
2941  clib_memcpy_fast (tr->dst.as_u8, ip1->dst_address.as_u8,
2942  sizeof (tr->dst.as_u8));
2943  }
2944 
2945  if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
2946  {
2948  vlib_add_trace (vm, node, b2, sizeof (*tr));
2949  clib_memcpy_fast (tr->src.as_u8, ip2->src_address.as_u8,
2950  sizeof (tr->src.as_u8));
2951  clib_memcpy_fast (tr->dst.as_u8, ip2->dst_address.as_u8,
2952  sizeof (tr->dst.as_u8));
2953  }
2954 
2955  if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
2956  {
2958  vlib_add_trace (vm, node, b3, sizeof (*tr));
2959  clib_memcpy_fast (tr->src.as_u8, ip3->src_address.as_u8,
2960  sizeof (tr->src.as_u8));
2961  clib_memcpy_fast (tr->dst.as_u8, ip3->dst_address.as_u8,
2962  sizeof (tr->dst.as_u8));
2963  }
2964  }
2965 
2967  n_left_to_next, bi0, bi1, bi2, bi3,
2968  next0, next1, next2, next3);
2969  }
2970 
2971  /* Single loop for potentially the last three packets */
2972  while (n_left_from > 0 && n_left_to_next > 0)
2973  {
2974  u32 bi0;
2975  vlib_buffer_t *b0;
2976  ip6_header_t *ip0 = 0;
2977  ip6_sr_header_t *sr0 = 0;
2978  ip6_sr_sl_t *sl0;
2979  u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2980  u16 new_l0 = 0;
2981 
2982  bi0 = from[0];
2983  to_next[0] = bi0;
2984  from += 1;
2985  to_next += 1;
2986  n_left_from -= 1;
2987  n_left_to_next -= 1;
2988 
2989  b0 = vlib_get_buffer (vm, bi0);
2990  sl0 =
2992  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
2994  vec_len (sl0->rewrite_bsid));
2995 
2996  ip0 = vlib_buffer_get_current (b0);
2997 
2998  if (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2999  sr0 =
3000  (ip6_sr_header_t *) (((void *) (ip0 + 1)) +
3001  ip6_ext_header_len (ip0 + 1));
3002  else
3003  sr0 = (ip6_sr_header_t *) (ip0 + 1);
3004 
3005  clib_memcpy_fast ((u8 *) ip0 - vec_len (sl0->rewrite_bsid),
3006  (u8 *) ip0, (void *) sr0 - (void *) ip0);
3007  clib_memcpy_fast (((u8 *) sr0 - vec_len (sl0->rewrite_bsid)),
3008  sl0->rewrite_bsid, vec_len (sl0->rewrite_bsid));
3009 
3010  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite_bsid));
3011 
3012  ip0 = ((void *) ip0) - vec_len (sl0->rewrite_bsid);
3013  ip0->hop_limit -= 1;
3014  new_l0 =
3015  clib_net_to_host_u16 (ip0->payload_length) +
3016  vec_len (sl0->rewrite_bsid);
3017  ip0->payload_length = clib_host_to_net_u16 (new_l0);
3018 
3019  sr0 = ((void *) sr0) - vec_len (sl0->rewrite_bsid);
3020 
3021  ip0->dst_address.as_u64[0] =
3022  (sr0->segments + sr0->segments_left)->as_u64[0];
3023  ip0->dst_address.as_u64[1] =
3024  (sr0->segments + sr0->segments_left)->as_u64[1];
3025 
3026  if (ip0 + 1 == (void *) sr0)
3027  {
3028  sr0->protocol = ip0->protocol;
3029  ip0->protocol = IP_PROTOCOL_IPV6_ROUTE;
3030  }
3031  else
3032  {
3033  ip6_ext_header_t *ip_ext = (void *) (ip0 + 1);
3034  sr0->protocol = ip_ext->next_hdr;
3035  ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
3036  }
3037 
3038  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
3039  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
3040  {
3042  vlib_add_trace (vm, node, b0, sizeof (*tr));
3043  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
3044  sizeof (tr->src.as_u8));
3045  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
3046  sizeof (tr->dst.as_u8));
3047  }
3048 
3049  insert_pkts++;
3050 
3052  n_left_to_next, bi0, next0);
3053  }
3054 
3055  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
3056  }
3057 
3058  /* Update counters */
3060  SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
3061  insert_pkts);
3063  SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
3064  bsid_pkts);
3065  return from_frame->n_vectors;
3066 }
3067 
3068 /* *INDENT-OFF* */
3070  .function = sr_policy_rewrite_b_insert,
3071  .name = "sr-pl-rewrite-b-insert",
3072  .vector_size = sizeof (u32),
3073  .format_trace = format_sr_policy_rewrite_trace,
3075  .n_errors = SR_POLICY_REWRITE_N_ERROR,
3076  .error_strings = sr_policy_rewrite_error_strings,
3077  .n_next_nodes = SR_POLICY_REWRITE_N_NEXT,
3078  .next_nodes = {
3079 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n,
3081 #undef _
3082  },
3083 };
3084 /* *INDENT-ON* */
3085 
3086 /**
3087  * @brief Function BSID encapsulation
3088  */
3091  vlib_buffer_t * b0,
3092  ip6_header_t * ip0,
3093  ip6_sr_header_t * sr0, u32 * next0)
3094 {
3095  ip6_address_t *new_dst0;
3096 
3097  if (PREDICT_FALSE (!sr0))
3098  goto error_bsid_encaps;
3099 
3101  {
3102  if (PREDICT_TRUE (sr0->segments_left != 0))
3103  {
3104  sr0->segments_left -= 1;
3105  new_dst0 = (ip6_address_t *) (sr0->segments);
3106  new_dst0 += sr0->segments_left;
3107  ip0->dst_address.as_u64[0] = new_dst0->as_u64[0];
3108  ip0->dst_address.as_u64[1] = new_dst0->as_u64[1];
3109  return;
3110  }
3111  }
3112 
3113 error_bsid_encaps:
3114  *next0 = SR_POLICY_REWRITE_NEXT_ERROR;
3115  b0->error = node->errors[SR_POLICY_REWRITE_ERROR_BSID_ZERO];
3116 }
3117 
3118 /**
3119  * @brief Graph node for applying a SR policy BSID - Encapsulation
3120  */
3121 static uword
3124 {
3125  ip6_sr_main_t *sm = &sr_main;
3126  u32 n_left_from, next_index, *from, *to_next;
3127 
3129  n_left_from = from_frame->n_vectors;
3130 
3131  next_index = node->cached_next_index;
3132 
3133  int encap_pkts = 0, bsid_pkts = 0;
3134 
3135  while (n_left_from > 0)
3136  {
3137  u32 n_left_to_next;
3138 
3139  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
3140 
3141  /* Quad - Loop */
3142  while (n_left_from >= 8 && n_left_to_next >= 4)
3143  {
3144  u32 bi0, bi1, bi2, bi3;
3145  vlib_buffer_t *b0, *b1, *b2, *b3;
3146  u32 next0, next1, next2, next3;
3147  next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
3148  ip6_header_t *ip0, *ip1, *ip2, *ip3;
3149  ip6_header_t *ip0_encap, *ip1_encap, *ip2_encap, *ip3_encap;
3150  ip6_sr_header_t *sr0, *sr1, *sr2, *sr3;
3151  ip6_sr_sl_t *sl0, *sl1, *sl2, *sl3;
3152 
3153  /* Prefetch next iteration. */
3154  {
3155  vlib_buffer_t *p4, *p5, *p6, *p7;
3156 
3157  p4 = vlib_get_buffer (vm, from[4]);
3158  p5 = vlib_get_buffer (vm, from[5]);
3159  p6 = vlib_get_buffer (vm, from[6]);
3160  p7 = vlib_get_buffer (vm, from[7]);
3161 
3162  /* Prefetch the buffer header and packet for the N+2 loop iteration */
3163  vlib_prefetch_buffer_header (p4, LOAD);
3164  vlib_prefetch_buffer_header (p5, LOAD);
3165  vlib_prefetch_buffer_header (p6, LOAD);
3166  vlib_prefetch_buffer_header (p7, LOAD);
3167 
3172  }
3173 
3174  to_next[0] = bi0 = from[0];
3175  to_next[1] = bi1 = from[1];
3176  to_next[2] = bi2 = from[2];
3177  to_next[3] = bi3 = from[3];
3178  from += 4;
3179  to_next += 4;
3180  n_left_from -= 4;
3181  n_left_to_next -= 4;
3182 
3183  b0 = vlib_get_buffer (vm, bi0);
3184  b1 = vlib_get_buffer (vm, bi1);
3185  b2 = vlib_get_buffer (vm, bi2);
3186  b3 = vlib_get_buffer (vm, bi3);
3187 
3188  sl0 =
3190  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
3191  sl1 =
3193  vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
3194  sl2 =
3196  vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
3197  sl3 =
3199  vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
3201  vec_len (sl0->rewrite));
3203  vec_len (sl1->rewrite));
3205  vec_len (sl2->rewrite));
3207  vec_len (sl3->rewrite));
3208 
3209  ip0_encap = vlib_buffer_get_current (b0);
3210  ip1_encap = vlib_buffer_get_current (b1);
3211  ip2_encap = vlib_buffer_get_current (b2);
3212  ip3_encap = vlib_buffer_get_current (b3);
3213 
3214  sr0 =
3215  ip6_ext_header_find (vm, b0, ip0_encap, IP_PROTOCOL_IPV6_ROUTE,
3216  NULL);
3217  sr1 =
3218  ip6_ext_header_find (vm, b1, ip1_encap, IP_PROTOCOL_IPV6_ROUTE,
3219  NULL);
3220  sr2 =
3221  ip6_ext_header_find (vm, b2, ip2_encap, IP_PROTOCOL_IPV6_ROUTE,
3222  NULL);
3223  sr3 =
3224  ip6_ext_header_find (vm, b3, ip3_encap, IP_PROTOCOL_IPV6_ROUTE,
3225  NULL);
3226 
3227  end_bsid_encaps_srh_processing (node, b0, ip0_encap, sr0, &next0);
3228  end_bsid_encaps_srh_processing (node, b1, ip1_encap, sr1, &next1);
3229  end_bsid_encaps_srh_processing (node, b2, ip2_encap, sr2, &next2);
3230  end_bsid_encaps_srh_processing (node, b3, ip3_encap, sr3, &next3);
3231 
3232  clib_memcpy_fast (((u8 *) ip0_encap) - vec_len (sl0->rewrite),
3233  sl0->rewrite, vec_len (sl0->rewrite));
3234  clib_memcpy_fast (((u8 *) ip1_encap) - vec_len (sl1->rewrite),
3235  sl1->rewrite, vec_len (sl1->rewrite));
3236  clib_memcpy_fast (((u8 *) ip2_encap) - vec_len (sl2->rewrite),
3237  sl2->rewrite, vec_len (sl2->rewrite));
3238  clib_memcpy_fast (((u8 *) ip3_encap) - vec_len (sl3->rewrite),
3239  sl3->rewrite, vec_len (sl3->rewrite));
3240 
3241  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
3242  vlib_buffer_advance (b1, -(word) vec_len (sl1->rewrite));
3243  vlib_buffer_advance (b2, -(word) vec_len (sl2->rewrite));
3244  vlib_buffer_advance (b3, -(word) vec_len (sl3->rewrite));
3245 
3246  ip0 = vlib_buffer_get_current (b0);
3247  ip1 = vlib_buffer_get_current (b1);
3248  ip2 = vlib_buffer_get_current (b2);
3249  ip3 = vlib_buffer_get_current (b3);
3250 
3251  encaps_processing_v6 (node, b0, ip0, ip0_encap);
3252  encaps_processing_v6 (node, b1, ip1, ip1_encap);
3253  encaps_processing_v6 (node, b2, ip2, ip2_encap);
3254  encaps_processing_v6 (node, b3, ip3, ip3_encap);
3255 
3256  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
3257  {
3258  if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
3259  {
3261  vlib_add_trace (vm, node, b0, sizeof (*tr));
3262  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
3263  sizeof (tr->src.as_u8));
3264  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
3265  sizeof (tr->dst.as_u8));
3266  }
3267 
3268  if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
3269  {
3271  vlib_add_trace (vm, node, b1, sizeof (*tr));
3272  clib_memcpy_fast (tr->src.as_u8, ip1->src_address.as_u8,
3273  sizeof (tr->src.as_u8));
3274  clib_memcpy_fast (tr->dst.as_u8, ip1->dst_address.as_u8,
3275  sizeof (tr->dst.as_u8));
3276  }
3277 
3278  if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
3279  {
3281  vlib_add_trace (vm, node, b2, sizeof (*tr));
3282  clib_memcpy_fast (tr->src.as_u8, ip2->src_address.as_u8,
3283  sizeof (tr->src.as_u8));
3284  clib_memcpy_fast (tr->dst.as_u8, ip2->dst_address.as_u8,
3285  sizeof (tr->dst.as_u8));
3286  }
3287 
3288  if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
3289  {
3291  vlib_add_trace (vm, node, b3, sizeof (*tr));
3292  clib_memcpy_fast (tr->src.as_u8, ip3->src_address.as_u8,
3293  sizeof (tr->src.as_u8));
3294  clib_memcpy_fast (tr->dst.as_u8, ip3->dst_address.as_u8,
3295  sizeof (tr->dst.as_u8));
3296  }
3297  }
3298 
3299  encap_pkts += 4;
3301  n_left_to_next, bi0, bi1, bi2, bi3,
3302  next0, next1, next2, next3);
3303  }
3304 
3305  /* Single loop for potentially the last three packets */
3306  while (n_left_from > 0 && n_left_to_next > 0)
3307  {
3308  u32 bi0;
3309  vlib_buffer_t *b0;
3310  ip6_header_t *ip0 = 0, *ip0_encap = 0;
3311  ip6_sr_header_t *sr0;
3312  ip6_sr_sl_t *sl0;
3313  u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
3314 
3315  bi0 = from[0];
3316  to_next[0] = bi0;
3317  from += 1;
3318  to_next += 1;
3319  n_left_from -= 1;
3320  n_left_to_next -= 1;
3321  b0 = vlib_get_buffer (vm, bi0);
3322 
3323  sl0 =
3325  vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
3327  vec_len (sl0->rewrite));
3328 
3329  ip0_encap = vlib_buffer_get_current (b0);
3330  sr0 =
3331  ip6_ext_header_find (vm, b0, ip0_encap, IP_PROTOCOL_IPV6_ROUTE,
3332  NULL);
3333  end_bsid_encaps_srh_processing (node, b0, ip0_encap, sr0, &next0);
3334 
3335  clib_memcpy_fast (((u8 *) ip0_encap) - vec_len (sl0->rewrite),
3336  sl0->rewrite, vec_len (sl0->rewrite));
3337  vlib_buffer_advance (b0, -(word) vec_len (sl0->rewrite));
3338 
3339  ip0 = vlib_buffer_get_current (b0);
3340 
3341  encaps_processing_v6 (node, b0, ip0, ip0_encap);
3342 
3343  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
3344  PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
3345  {
3347  vlib_add_trace (vm, node, b0, sizeof (*tr));
3348  clib_memcpy_fast (tr->src.as_u8, ip0->src_address.as_u8,
3349  sizeof (tr->src.as_u8));
3350  clib_memcpy_fast (tr->dst.as_u8, ip0->dst_address.as_u8,
3351  sizeof (tr->dst.as_u8));
3352  }
3353 
3354  encap_pkts++;
3356  n_left_to_next, bi0, next0);
3357  }
3358 
3359  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
3360  }
3361 
3362  /* Update counters */
3364  SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
3365  encap_pkts);
3367  SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
3368  bsid_pkts);
3369 
3370  return from_frame->n_vectors;
3371 }
3372 
3373 /* *INDENT-OFF* */
3375  .function = sr_policy_rewrite_b_encaps,
3376  .name = "sr-pl-rewrite-b-encaps",
3377  .vector_size = sizeof (u32),
3378  .format_trace = format_sr_policy_rewrite_trace,
3380  .n_errors = SR_POLICY_REWRITE_N_ERROR,
3381  .error_strings = sr_policy_rewrite_error_strings,
3382  .n_next_nodes = SR_POLICY_REWRITE_N_NEXT,
3383  .next_nodes = {
3384 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n,
3386 #undef _
3387  },
3388 };
3389 /* *INDENT-ON* */
3390 
3391 /*************************** SR Policy plugins ******************************/
3392 /**
3393  * @brief SR Policy plugin registry
3394  */
3395 int
3397  u8 * keyword_str, u8 * def_str,
3398  u8 * params_str, u8 prefix_length,
3399  dpo_type_t * dpo,
3400  format_function_t * ls_format,
3401  unformat_function_t * ls_unformat,
3402  sr_p_plugin_callback_t * creation_fn,
3403  sr_p_plugin_callback_t * removal_fn)
3404 {
3405  ip6_sr_main_t *sm = &sr_main;
3406  uword *p;
3407 
3409 
3410  /* Did this function exist? If so update it */
3412  if (p)
3413  {
3414  plugin = pool_elt_at_index (sm->policy_plugin_functions, p[0]);
3415  }
3416  /* Else create a new one and set hash key */
3417  else
3418  {
3419  pool_get (sm->policy_plugin_functions, plugin);
3421  plugin - sm->policy_plugin_functions);
3422  }
3423 
3424  clib_memset (plugin, 0, sizeof (*plugin));
3425 
3426  plugin->sr_policy_function_number = (plugin - sm->policy_plugin_functions);
3428  plugin->prefix_length = prefix_length;
3429  plugin->ls_format = ls_format;
3430  plugin->ls_unformat = ls_unformat;
3431  plugin->creation = creation_fn;
3432  plugin->removal = removal_fn;
3433  clib_memcpy (&plugin->dpo, dpo, sizeof (dpo_type_t));
3434  plugin->function_name = format (0, "%s%c", fn_name, 0);
3435  plugin->keyword_str = format (0, "%s%c", keyword_str, 0);
3436  plugin->def_str = format (0, "%s%c", def_str, 0);
3437  plugin->params_str = format (0, "%s%c", params_str, 0);
3438 
3439  return plugin->sr_policy_function_number;
3440 }
3441 
3442 /**
3443  * @brief CLI function to 'show' all available SR LocalSID behaviors
3444  */
3445 static clib_error_t *
3447  unformat_input_t * input,
3448  vlib_cli_command_t * cmd)
3449 {
3450  ip6_sr_main_t *sm = &sr_main;
3452  sr_policy_fn_registration_t **plugins_vec = 0;
3453  int i;
3454 
3455  vlib_cli_output (vm, "SR Policy behaviors:\n-----------------------\n\n");
3456 
3457  /* *INDENT-OFF* */
3459  { vec_add1 (plugins_vec, plugin); }
3460  /* *INDENT-ON* */
3461 
3462  vlib_cli_output (vm, "Plugin behaviors:\n");
3463  for (i = 0; i < vec_len (plugins_vec); i++)
3464  {
3465  plugin = plugins_vec[i];
3466  vlib_cli_output (vm, "\t%s\t-> %s.\n", plugin->keyword_str,
3467  plugin->def_str);
3468  vlib_cli_output (vm, "\t\tParameters: '%s'\n", plugin->params_str);
3469  }
3470  return 0;
3471 }
3472 
3473 /* *INDENT-OFF* */
3475  .path = "show sr policy behaviors",
3476  .short_help = "show sr policy behaviors",
3478 };
3479 /* *INDENT-ON* */
3480 
3481 /*************************** SR Segment Lists DPOs ****************************/
3482 static u8 *
3483 format_sr_segment_list_dpo (u8 * s, va_list * args)
3484 {
3485  ip6_sr_main_t *sm = &sr_main;
3486  ip6_address_t *addr;
3487  ip6_sr_sl_t *sl;
3488 
3489  index_t index = va_arg (*args, index_t);
3490  CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
3491  s = format (s, "SR: Segment List index:[%d]", index);
3492  s = format (s, "\n\tSegments:");
3493 
3494  sl = pool_elt_at_index (sm->sid_lists, index);
3495 
3496  s = format (s, "< ");
3497  vec_foreach (addr, sl->segments)
3498  {
3499  s = format (s, "%U, ", format_ip6_address, addr);
3500  }
3501  s = format (s, "\b\b > - ");
3502  s = format (s, "Weight: %u", sl->weight);
3503 
3504  return s;
3505 }
3506 
3508  .dv_lock = sr_dpo_lock,
3509  .dv_unlock = sr_dpo_unlock,
3510  .dv_format = format_sr_segment_list_dpo,
3511 };
3512 
3513 const static char *const sr_pr_encaps_ip6_nodes[] = {
3514  "sr-pl-rewrite-encaps",
3515  NULL,
3516 };
3517 
3518 const static char *const sr_pr_encaps_ip4_nodes[] = {
3519  "sr-pl-rewrite-encaps-v4",
3520  NULL,
3521 };
3522 
3523 const static char *const *const sr_pr_encaps_nodes[DPO_PROTO_NUM] = {
3526 };
3527 
3528 const static char *const sr_pr_insert_ip6_nodes[] = {
3529  "sr-pl-rewrite-insert",
3530  NULL,
3531 };
3532 
3533 const static char *const *const sr_pr_insert_nodes[DPO_PROTO_NUM] = {
3535 };
3536 
3537 const static char *const sr_pr_bsid_insert_ip6_nodes[] = {
3538  "sr-pl-rewrite-b-insert",
3539  NULL,
3540 };
3541 
3542 const static char *const *const sr_pr_bsid_insert_nodes[DPO_PROTO_NUM] = {
3544 };
3545 
3546 const static char *const sr_pr_bsid_encaps_ip6_nodes[] = {
3547  "sr-pl-rewrite-b-encaps",
3548  NULL,
3549 };
3550 
3551 const static char *const *const sr_pr_bsid_encaps_nodes[DPO_PROTO_NUM] = {
3553 };
3554 
3555 /********************* SR Policy Rewrite initialization ***********************/
3556 /**
3557  * @brief SR Policy Rewrite initialization
3558  */
3559 clib_error_t *
3561 {
3562  ip6_sr_main_t *sm = &sr_main;
3563 
3564  /* Init memory for sr policy keys (bsid <-> ip6_address_t) */
3565  mhash_init (&sm->sr_policies_index_hash, sizeof (uword),
3566  sizeof (ip6_address_t));
3567 
3568  /* Init SR VPO DPOs type */
3571 
3574 
3577 
3580 
3581  /* Register the L2 encaps node used in HW redirect */
3583 
3584  sm->fib_table_ip6 = (u32) ~ 0;
3585  sm->fib_table_ip4 = (u32) ~ 0;
3586 
3587  return 0;
3588 }
3589 
3591 
3592 
3593 /*
3594 * fd.io coding-style-patch-verification: ON
3595 *
3596 * Local Variables:
3597 * eval: (c-set-style "gnu")
3598 * End:
3599 */
show_sr_policy_behaviors_command_fn
static clib_error_t * show_sr_policy_behaviors_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI function to 'show' all available SR LocalSID behaviors.
Definition: sr_policy_rewrite.c:3446
vlib.h
ip6_sr_header_t::protocol
u8 protocol
Definition: sr_packet.h:122
show_sr_policies_command_fn
static clib_error_t * show_sr_policies_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI to display onscreen all the SR policies.
Definition: sr_policy_rewrite.c:1112
ip6_sr_policy_t::is_encap
u8 is_encap
Mode (0 is SRH insert, 1 Encaps)
Definition: sr.h:111
weight
u8 weight
Definition: fib_types.api:120
ip_flow_hash
static u32 ip_flow_hash(void *data)
Definition: sr_policy_rewrite.c:1812
dpo_register_new_type
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type.
Definition: dpo.c:349
update_lb
static void update_lb(ip6_sr_policy_t *sr_policy)
Updates the Load Balancer after an SR Policy change.
Definition: sr_policy_rewrite.c:441
SR_POLICY_REWRITE_N_NEXT
@ SR_POLICY_REWRITE_N_NEXT
Definition: sr_policy_rewrite.c:72
sr_policy_rewrite_b_encaps
static uword sr_policy_rewrite_b_encaps(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy BSID - Encapsulation.
Definition: sr_policy_rewrite.c:3122
set_sr_hop_limit_command
static vlib_cli_command_t set_sr_hop_limit_command
(constructor) VLIB_CLI_COMMAND (set_sr_hop_limit_command)
Definition: sr_policy_rewrite.c:182
vlib_prefetch_buffer_header
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
show_sr_policy_behaviors_command
static vlib_cli_command_t show_sr_policy_behaviors_command
(constructor) VLIB_CLI_COMMAND (show_sr_policy_behaviors_command)
Definition: sr_policy_rewrite.c:3474
show_sr_policies_command
static vlib_cli_command_t show_sr_policies_command
(constructor) VLIB_CLI_COMMAND (show_sr_policies_command)
Definition: sr_policy_rewrite.c:1167
clib_memcpy
#define clib_memcpy(d, s, n)
Definition: string.h:197
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
elog.h
sr_policy_add
int sr_policy_add(ip6_address_t *bsid, ip6_address_t *segments, u32 weight, u8 behavior, u32 fib_table, u8 is_encap, u16 plugin, void *ls_plugin_mem)
Create a new SR policy.
Definition: sr_policy_rewrite.c:635
sr_policy_fn_registration_t::ls_unformat
unformat_function_t * ls_unformat
LocalSID unformat function.
Definition: sr.h:209
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
sr_policy_rewrite_b_insert
static uword sr_policy_rewrite_b_insert(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into a packet.
Definition: sr_policy_rewrite.c:2679
create_sl
static ip6_sr_sl_t * create_sl(ip6_sr_policy_t *sr_policy, ip6_address_t *sl, u32 weight, u8 is_encap)
Creates a Segment List and adds it to an SR policy.
Definition: sr_policy_rewrite.c:344
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
ip6_sr_main_t::l2_sr_policy_rewrite_index
u32 l2_sr_policy_rewrite_index
Definition: sr.h:260
ip6_header_t::protocol
u8 protocol
Definition: ip6_packet.h:304
ip4_inlines.h
SR_POLICY_REWRITE_N_ERROR
@ SR_POLICY_REWRITE_N_ERROR
Definition: sr_policy_rewrite.c:89
sl_index
u32 sl_index
Definition: sr.api:35
ethernet_header_t::dst_address
u8 dst_address[6]
Definition: packet.h:55
ethernet_header_t::src_address
u8 src_address[6]
Definition: packet.h:56
show_sr_encaps_hop_limit_command
static vlib_cli_command_t show_sr_encaps_hop_limit_command
(constructor) VLIB_CLI_COMMAND (show_sr_encaps_hop_limit_command)
Definition: sr_policy_rewrite.c:1209
sr_policy_fn_registration_t::creation
sr_p_plugin_callback_t * creation
Function within plugin that will be called after localsid creation.
Definition: sr.h:211
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
ip6_ext_header_len
#define ip6_ext_header_len(p)
Definition: ip6_packet.h:545
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
ip6_header_t::hop_limit
u8 hop_limit
Definition: ip6_packet.h:307
path
vl_api_fib_path_t path
Definition: mfib_types.api:44
show_sr_encaps_source_command
static vlib_cli_command_t show_sr_encaps_source_command
(constructor) VLIB_CLI_COMMAND (show_sr_encaps_source_command)
Definition: sr_policy_rewrite.c:1188
encaps_processing_v6
static_always_inline void encaps_processing_v6(vlib_node_runtime_t *node, vlib_buffer_t *b0, ip6_header_t *ip0, ip6_header_t *ip0_encap)
IPv6 encapsulation processing as per RFC2473.
Definition: sr_policy_rewrite.c:1239
sr_policy_rewrite_vft
const static dpo_vft_t sr_policy_rewrite_vft
Definition: sr_policy_rewrite.c:3507
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
u8
#define u8
Padding.
Definition: clib.h:121
vlib_cli_command_t::path
char * path
Definition: cli.h:96
ip6_sr_sl_t::plugin
u16 plugin
Definition: sr.h:85
sr_policy_register_function
int sr_policy_register_function(vlib_main_t *vm, u8 *fn_name, u8 *keyword_str, u8 *def_str, u8 *params_str, u8 prefix_length, dpo_type_t *dpo, format_function_t *ls_format, unformat_function_t *ls_unformat, sr_p_plugin_callback_t *creation_fn, sr_p_plugin_callback_t *removal_fn)
SR Policy plugin registry.
Definition: sr_policy_rewrite.c:3396
load_balance_create
index_t load_balance_create(u32 n_buckets, dpo_proto_t lb_proto, flow_hash_config_t fhc)
Definition: load_balance.c:266
FIB_NODE_INDEX_INVALID
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:30
sr_policy_rewrite_b_encaps_node
vlib_node_registration_t sr_policy_rewrite_b_encaps_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_b_encaps_node)
Definition: sr_policy_rewrite.c:3374
ip6_sr_main_t::steer_policies
ip6_sr_steering_policy_t * steer_policies
Definition: sr.h:278
vlib_validate_buffer_enqueue_x4
#define vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, bi2, bi3, next0, next1, next2, next3)
Finish enqueueing four buffers forward in the graph.
Definition: buffer_node.h:140
sr_policy_rewrite_encaps_l2
static uword sr_policy_rewrite_encaps_l2(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into a L2 frame.
Definition: sr_policy_rewrite.c:1859
sr_policy_mod
int sr_policy_mod(ip6_address_t *bsid, u32 index, u32 fib_table, u8 operation, ip6_address_t *segments, u32 sl_index, u32 weight)
Modify an existing SR policy.
Definition: sr_policy_rewrite.c:831
sr_policy_rewrite_insert
static uword sr_policy_rewrite_insert(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into a packet.
Definition: sr_policy_rewrite.c:2257
u16
unsigned short u16
Definition: types.h:57
sr_pr_bsid_encaps_nodes
const static char *const *const sr_pr_bsid_encaps_nodes[DPO_PROTO_NUM]
Definition: sr_policy_rewrite.c:3551
sr_policy_rewrite_encaps_v4_node
vlib_node_registration_t sr_policy_rewrite_encaps_v4_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_v4_node)
Definition: sr_policy_rewrite.c:1794
pool_put
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
mhash_get
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
ethernet_header_t::type
u16 type
Definition: packet.h:59
SR_POLICY_TYPE_DEFAULT
#define SR_POLICY_TYPE_DEFAULT
Definition: sr_mpls.h:36
ip6_sr_sl_t::plugin_mem
void * plugin_mem
Definition: sr.h:86
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
set_sr_src_command_fn
static clib_error_t * set_sr_src_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: sr_policy_rewrite.c:129
ip6_sr_main_t::sw_iface_sr_policies
u32 * sw_iface_sr_policies
Definition: sr.h:284
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
compute_rewrite_bsid
static u8 * compute_rewrite_bsid(ip6_address_t *sl)
SR rewrite string computation for SRH insertion with BSID (inline)
Definition: sr_policy_rewrite.c:297
l2_flow_hash
static u32 l2_flow_hash(vlib_buffer_t *b0)
Definition: sr_policy_rewrite.c:1829
IP_PROTOCOL_IP6_ETHERNET
#define IP_PROTOCOL_IP6_ETHERNET
Definition: mobile.h:37
ip6_sr_main_t::policy_plugin_functions_by_key
uword * policy_plugin_functions_by_key
Definition: sr.h:299
def_str
unsigned char def_str[64]
Definition: srv6_localsid_sample.c:30
from_frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * from_frame
Definition: esp_encrypt.c:1328
FIB_ENTRY_FLAG_EXCLUSIVE
@ FIB_ENTRY_FLAG_EXCLUSIVE
Definition: fib_entry.h:116
format_sr_segment_list_dpo
static u8 * format_sr_segment_list_dpo(u8 *s, va_list *args)
Definition: sr_policy_rewrite.c:3483
sr_policy_fn_registration_t::ls_format
format_function_t * ls_format
LocalSID format function.
Definition: sr.h:207
unformat_input_t
struct _unformat_input_t unformat_input_t
ip6_sr_sl_t::rewrite
u8 * rewrite
Precomputed rewrite header.
Definition: sr.h:76
sr_policy_rewrite_trace_t
SR policy rewrite trace.
Definition: sr_policy_rewrite.c:57
addr
vhost_vring_addr_t addr
Definition: vhost_user.h:130
mhash_init
__clib_export void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
vlib_frame_t
Definition: node.h:372
sr_policy_rewrite_trace_t::dst
ip6_address_t dst
Definition: sr_policy_rewrite.c:59
ip6_fib_index_from_table_id
static u32 ip6_fib_index_from_table_id(u32 table_id)
Definition: ip6_fib.h:220
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
pool_put_index
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:337
SR_POLICY_TYPE_SPRAY
#define SR_POLICY_TYPE_SPRAY
Definition: sr_mpls.h:37
ip4_header_t
Definition: ip4_packet.h:87
ip6_sr_header_t::segments
ip6_address_t segments[0]
Definition: sr_packet.h:149
sr_policy_rewrite_encaps_l2_node
vlib_node_registration_t sr_policy_rewrite_encaps_l2_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_l2_node)
Definition: sr_policy_rewrite.c:2236
replicate_dpo.h
ip4_header_t::tos
ip_dscp_t tos
Definition: ip4_packet.h:96
mac_to_u64
static u64 mac_to_u64(u8 *m)
Definition: sr_policy_rewrite.c:1823
sr_policy_fn_registration_t::removal
sr_p_plugin_callback_t * removal
Function within plugin that will be called before localsid removal.
Definition: sr.h:213
ip4_header_t::length
u16 length
Definition: ip4_packet.h:99
fib_table_entry_special_dpo_update
fib_node_index_t fib_table_entry_special_dpo_update(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Update a 'special' entry to the FIB that links to the DPO passed A special entry is an entry that the...
Definition: fib_table.c:363
sr_packet.h
sr_set_hop_limit
void sr_set_hop_limit(u8 hop_limit)
Definition: sr_policy_rewrite.c:154
sr_policy_rewrite_encaps_node
vlib_node_registration_t sr_policy_rewrite_encaps_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_node)
Definition: sr_policy_rewrite.c:1501
ip6_sr_header_t::type
u8 type
Definition: sr_packet.h:130
load_balance_multipath_update
void load_balance_multipath_update(const dpo_id_t *dpo, const load_balance_path_t *raw_nhs, load_balance_flags_t flags)
Definition: load_balance.c:629
ip6_sr_sl_t::ip4_dpo
dpo_id_t ip4_dpo
DPO for Encaps IPv6.
Definition: sr.h:83
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
ip6_sr_policy_t::plugin_mem
void * plugin_mem
Definition: sr.h:114
ip6_sr_policy_t
SR Policy.
Definition: sr.h:95
CLIB_PREFETCH
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
sr.h
Segment Routing data structures definitions.
vlib_buffer_t::current_data
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:119
fib_table_entry_special_remove
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a 'special' entry from the FIB.
Definition: fib_table.c:424
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
SR_BEHAVIOR_LAST
#define SR_BEHAVIOR_LAST
Definition: sr.h:48
vlib_buffer_advance
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
sr_policy_rewrite_b_insert_node
vlib_node_registration_t sr_policy_rewrite_b_insert_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_b_insert_node)
Definition: sr_policy_rewrite.c:3069
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
vlib_buffer_t::error
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
sr_pr_encaps_ip4_nodes
const static char *const sr_pr_encaps_ip4_nodes[]
Definition: sr_policy_rewrite.c:3518
error.h
dpo.h
sr_policy_rewrite_encaps
static uword sr_policy_rewrite_encaps(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into an IPv6 packet.
Definition: sr_policy_rewrite.c:1265
fn_name
static u8 fn_name[]
Definition: gtp4_d.c:66
vec_add2
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:644
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
ip6_sr_sl_t::egress_fib_table
u32 egress_fib_table
Egress FIB table for encap packet.
Definition: sr.h:79
sr_pr_bsid_insert_dpo_type
static dpo_type_t sr_pr_bsid_insert_dpo_type
Definition: sr_policy_rewrite.c:104
ip6_sr_sl_t
SR Segment List (SID list)
Definition: sr.h:70
sr_policy_rewrite_insert_node
vlib_node_registration_t sr_policy_rewrite_insert_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_insert_node)
Definition: sr_policy_rewrite.c:2658
ip6_compute_flow_hash
static u32 ip6_compute_flow_hash(const ip6_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip6_inlines.h:49
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:437
vec_dup
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:444
sr_p_plugin_callback_t
int() sr_p_plugin_callback_t(ip6_sr_policy_t *sr)
Definition: sr.h:117
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
sr_pr_bsid_insert_ip6_nodes
const static char *const sr_pr_bsid_insert_ip6_nodes[]
Definition: sr_policy_rewrite.c:3537
ip6_sr_header_t::flags
u8 flags
Definition: sr_packet.h:145
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
compute_rewrite_encaps
static u8 * compute_rewrite_encaps(ip6_address_t *sl)
SR rewrite string computation for IPv6 encapsulation (inline)
Definition: sr_policy_rewrite.c:198
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
unformat_check_input
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
sr_policy_del
int sr_policy_del(ip6_address_t *bsid, u32 index)
Delete a SR policy.
Definition: sr_policy_rewrite.c:723
flow_hash_config_t
enum flow_hash_config_t_ flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
ip6_ext_header_find
static void * ip6_ext_header_find(vlib_main_t *vm, vlib_buffer_t *b, ip6_header_t *ip6_header, u8 header_type, ip6_ext_header_t **prev_ext_header)
Definition: ip6_packet.h:575
ip6_sr_policy_t::segments_lists
u32 * segments_lists
SID lists indexes (vector)
Definition: sr.h:97
c
svmdb_client_t * c
Definition: vpp_get_metrics.c:48
index_t
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:43
static_always_inline
#define static_always_inline
Definition: clib.h:112
ethernet_buffer_header_size
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
Definition: ethernet.h:463
ip6_sr_header_t::segments_left
u8 segments_left
Definition: sr_packet.h:133
IP_FLOW_HASH_DEFAULT
#define IP_FLOW_HASH_DEFAULT
Default: 5-tuple + flowlabel without the "reverse" bit.
Definition: ip_flow_hash.h:22
fib_node_index_t
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
vec_foreach_index
#define vec_foreach_index(var, v)
Iterate over vector indices.
Definition: vec_bootstrap.h:220
LOAD_BALANCE_FLAG_NONE
@ LOAD_BALANCE_FLAG_NONE
Definition: load_balance.h:96
uword
u64 uword
Definition: types.h:112
sr_policy_command
static vlib_cli_command_t sr_policy_command
(constructor) VLIB_CLI_COMMAND (sr_policy_command)
Definition: sr_policy_rewrite.c:1087
ip6_sr_main_t::policy_plugin_functions
sr_policy_fn_registration_t * policy_plugin_functions
Definition: sr.h:296
sr_dpo_unlock
void sr_dpo_unlock(dpo_id_t *dpo)
no-op unlock function.
Definition: sr.c:47
ethernet_header_t
Definition: packet.h:52
sr_policy_rewrite_encaps_v4
static uword sr_policy_rewrite_encaps_v4(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into an IPv4 packet.
Definition: sr_policy_rewrite.c:1558
sr_policy_fn_registration_t::function_name
u8 * function_name
Function name.
Definition: sr.h:195
hash_set_mem
#define hash_set_mem(h, key, value)
Definition: hash.h:275
update_replicate
static void update_replicate(ip6_sr_policy_t *sr_policy)
Updates the Replicate DPO after an SR Policy change.
Definition: sr_policy_rewrite.c:538
sr_set_source
void sr_set_source(ip6_address_t *address)
Definition: sr_policy_rewrite.c:117
dpo_id_is_valid
static int dpo_id_is_valid(const dpo_id_t *dpoi)
Return true if the DPO object is valid, i.e.
Definition: dpo.h:216
vlib_node_increment_counter
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1244
dpo_type_t
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type()
i
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
ip6_sr_sl_t::weight
u32 weight
SID list weight (wECMP / UCMP)
Definition: sr.h:74
show_sr_encaps_source_command_fn
static clib_error_t * show_sr_encaps_source_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI to display onscreen the SR encaps source addr.
Definition: sr_policy_rewrite.c:1178
ip6_header_t::dst_address
ip6_address_t dst_address
Definition: ip6_packet.h:310
replicate_create
index_t replicate_create(u32 n_buckets, dpo_proto_t rep_proto)
Definition: replicate_dpo.c:192
pool_get
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
address
manual_print typedef address
Definition: ip_types.api:96
VLIB_CLI_COMMAND
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
ip4_header_t::checksum
u16 checksum
Definition: ip4_packet.h:118
ip6_sr_policy_t::bsid_dpo
dpo_id_t bsid_dpo
SR Policy specific DPO - BSID.
Definition: sr.h:105
dpo_vft_t_::dv_lock
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:428
ip6_sr_policy_t::ip4_dpo
dpo_id_t ip4_dpo
SR Policy specific DPO - IPv6.
Definition: sr.h:106
hop_limit
u8 hop_limit
Definition: tunnel_types.api:88
sr_pr_encaps_hop_limit
static u8 sr_pr_encaps_hop_limit
Definition: sr_policy_rewrite.c:110
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
ip6_sr_header_t::length
u8 length
Definition: sr_packet.h:127
format_sr_policy_rewrite_trace
static u8 * format_sr_policy_rewrite_trace(u8 *s, va_list *args)
Trace for the SR Policy Rewrite graph node.
Definition: sr_policy_rewrite.c:1221
sr_policy_fn_registration_t::prefix_length
u8 prefix_length
Definition: sr.h:203
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
FIB_SOURCE_SR
@ FIB_SOURCE_SR
SRv6 and SR-MPLS.
Definition: fib_source.h:63
vlib_cli_output
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
sr_policy_rewrite_error_t
sr_policy_rewrite_error_t
Definition: sr_policy_rewrite.c:84
ip6_inlines.h
sr_pr_insert_ip6_nodes
const static char *const sr_pr_insert_ip6_nodes[]
Definition: sr_policy_rewrite.c:3528
set_sr_hop_limit_command_fn
static clib_error_t * set_sr_hop_limit_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: sr_policy_rewrite.c:166
set_sr_src_command
static vlib_cli_command_t set_sr_src_command
(constructor) VLIB_CLI_COMMAND (set_sr_src_command)
Definition: sr_policy_rewrite.c:144
vlib_buffer_t::current_length
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
params_str
unsigned char params_str[32]
Definition: srv6_localsid_sample.c:31
sr_main
ip6_sr_main_t sr_main
Definition: sr.c:31
sr_pr_encaps_nodes
const static char *const *const sr_pr_encaps_nodes[DPO_PROTO_NUM]
Definition: sr_policy_rewrite.c:3523
sr_pr_insert_nodes
const static char *const *const sr_pr_insert_nodes[DPO_PROTO_NUM]
Definition: sr_policy_rewrite.c:3533
keyword_str
unsigned char keyword_str[32]
Definition: srv6_localsid_sample.c:29
IPv6_DEFAULT_HEADER_LENGTH
#define IPv6_DEFAULT_HEADER_LENGTH
Definition: sr.h:33
data
u8 data[128]
Definition: ipsec_types.api:92
fib_table_get_flow_hash_config
flow_hash_config_t fib_table_get_flow_hash_config(u32 fib_index, fib_protocol_t proto)
Get the flow hash configured used by the table.
Definition: fib_table.c:1014
sr_policy_fn_registration_t::keyword_str
u8 * keyword_str
Behavior keyword (i.e.
Definition: sr.h:197
fib_table_lookup_exact_match
fib_node_index_t fib_table_lookup_exact_match(u32 fib_index, const fib_prefix_t *prefix)
Perfom an exact match in the non-forwarding table.
Definition: fib_table.c:97
DPO_LOAD_BALANCE
@ DPO_LOAD_BALANCE
load-balancing over a choice of [un]equal cost paths
Definition: dpo.h:104
ip6_sr_header_t::last_entry
u8 last_entry
Definition: sr_packet.h:136
format_function_t
u8 *() format_function_t(u8 *s, va_list *args)
Definition: format.h:48
ip6_sr_main_t
Segment Routing main datastructure.
Definition: sr.h:257
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
vlib_validate_buffer_enqueue_x1
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
index
u32 index
Definition: flow_types.api:221
end_bsid_encaps_srh_processing
static_always_inline void end_bsid_encaps_srh_processing(vlib_node_runtime_t *node, vlib_buffer_t *b0, ip6_header_t *ip0, ip6_sr_header_t *sr0, u32 *next0)
Function BSID encapsulation.
Definition: sr_policy_rewrite.c:3090
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
sr_dpo_lock
void sr_dpo_lock(dpo_id_t *dpo)
no-op lock function.
Definition: sr.c:38
ip6_sr_policy_t::bsid
ip6_address_t bsid
BindingSID (key)
Definition: sr.h:99
hash_get_mem
#define hash_get_mem(h, key)
Definition: hash.h:269
ip6_sr_policy_t::type
u8 type
Type (default is 0)
Definition: sr.h:101
sr_pr_encaps_ip6_nodes
const static char *const sr_pr_encaps_ip6_nodes[]
Definition: sr_policy_rewrite.c:3513
u64
unsigned long u64
Definition: types.h:89
foreach_sr_policy_rewrite_next
#define foreach_sr_policy_rewrite_next
Definition: sr_policy_rewrite.c:63
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
sr_policy_fn_registration_t::dpo
dpo_type_t dpo
DPO type registration.
Definition: sr.h:205
sr_policy_rewrite_init
clib_error_t * sr_policy_rewrite_init(vlib_main_t *vm)
SR Policy Rewrite initialization.
Definition: sr_policy_rewrite.c:3560
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
DPO_PROTO_IP6
@ DPO_PROTO_IP6
Definition: dpo.h:65
fib_table_create_and_lock
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:1184
ip6_sr_sl_t::segments
ip6_address_t * segments
SIDs (key)
Definition: sr.h:72
VLIB_BUFFER_PRE_DATA_SIZE
#define VLIB_BUFFER_PRE_DATA_SIZE
Definition: buffer.h:51
sr_pr_encaps_dpo_type
static dpo_type_t sr_pr_encaps_dpo_type
Dynamically added SR SL DPO type.
Definition: sr_policy_rewrite.c:101
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
ip4_header_t::ttl
u8 ttl
Definition: ip4_packet.h:112
FIB_PROTOCOL_IP6
@ FIB_PROTOCOL_IP6
Definition: fib_types.h:37
dst
vl_api_ip4_address_t dst
Definition: pnat.api:41
vec_foreach
#define vec_foreach(var, vec)
Vector iterator.
Definition: vec_bootstrap.h:213
sr_policy_rewrite_trace_t::src
ip6_address_t src
Definition: sr_policy_rewrite.c:59
ROUTING_HEADER_TYPE_SR
#define ROUTING_HEADER_TYPE_SR
Definition: sr_packet.h:117
sr_pr_bsid_insert_nodes
const static char *const *const sr_pr_bsid_insert_nodes[DPO_PROTO_NUM]
Definition: sr_policy_rewrite.c:3542
as_u64
u64 as_u64
Definition: bihash_doc.h:63
unformat_function_t
uword() unformat_function_t(unformat_input_t *input, va_list *args)
Definition: format.h:225
pool_elts
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127
fib_prefix_t_::fp_proto
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:211
hash_mix64
#define hash_mix64(a0, b0, c0)
Definition: hash.h:530
ip4_compute_flow_hash
static u32 ip4_compute_flow_hash(const ip4_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip4_inlines.h:51
ip6_sr_header_t
Definition: sr_packet.h:119
ip6_header_t
Definition: ip6_packet.h:294
sr_pr_insert_dpo_type
static dpo_type_t sr_pr_insert_dpo_type
Definition: sr_policy_rewrite.c:102
ip6_fib.h
sr_get_encaps_source
ip6_address_t * sr_get_encaps_source()
Definition: sr_policy_rewrite.c:123
ip6_header_t::src_address
ip6_address_t src_address
Definition: ip6_packet.h:310
sr_policy_fn_registration_t::def_str
u8 * def_str
Behavior definition (i.e.
Definition: sr.h:199
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
ip4_header_t::ip_version_and_header_length
u8 ip_version_and_header_length
Definition: ip4_packet.h:93
vlib_node_t
Definition: node.h:247
dpo_vft_t_
A virtual function table regisitered for a DPO type.
Definition: dpo.h:423
vlib_add_trace
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
encaps_processing_v4
static_always_inline void encaps_processing_v4(vlib_node_runtime_t *node, vlib_buffer_t *b0, ip6_header_t *ip0, ip4_header_t *ip0_encap)
IPv4 encapsulation processing as per RFC2473.
Definition: sr_policy_rewrite.c:1522
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
a
a
Definition: bitmap.h:544
ip6_sr_main_t::fib_table_ip6
u32 fib_table_ip6
Definition: sr.h:306
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
ip
vl_api_address_t ip
Definition: l2.api:558
ip6_sr_sl_t::ip6_dpo
dpo_id_t ip6_dpo
DPO for Encaps/Insert IPv6.
Definition: sr.h:82
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
format_ip6_address
format_function_t format_ip6_address
Definition: format.h:91
vlib_buffer_t::data
u8 data[]
Packet data.
Definition: buffer.h:204
fib_table_unlock
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1336
ip6_sr_header_t::tag
u16 tag
Definition: sr_packet.h:146
DPO_PROTO_IP4
@ DPO_PROTO_IP4
Definition: dpo.h:64
show_sr_encaps_hop_limit_command_fn
static clib_error_t * show_sr_encaps_hop_limit_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI to display onscreen the hop-limit value used for SRv6 encapsulation.
Definition: sr_policy_rewrite.c:1199
sr_policy_fn_registration_t
SR Policy behavior registration.
Definition: sr.h:191
sr_pr_bsid_encaps_dpo_type
static dpo_type_t sr_pr_bsid_encaps_dpo_type
Definition: sr_policy_rewrite.c:103
ip6_sr_policy_t::fib_table
u32 fib_table
FIB table.
Definition: sr.h:109
ip6_sr_main_t::sr_policies
ip6_sr_policy_t * sr_policies
Definition: sr.h:266
word
i64 word
Definition: types.h:111
ip6_sr_policy_t::ip6_dpo
dpo_id_t ip6_dpo
SR Policy specific DPO - IPv4.
Definition: sr.h:107
unformat_ip6_address
unformat_function_t unformat_ip6_address
Definition: format.h:89
sr_policy_fn_registration_t::params_str
u8 * params_str
Behavior parameters (i.e.
Definition: sr.h:201
rv
int __clib_unused rv
Definition: application.c:491
sr_policy_fn_registration_t::sr_policy_function_number
u16 sr_policy_function_number
SR Policy plugin function.
Definition: sr.h:193
vnet.h
dpo_set
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:188
ip6_header_t::payload_length
u16 payload_length
Definition: ip6_packet.h:301
vlib_node_runtime_t
Definition: node.h:454
sr_get_hop_limit
u8 sr_get_hop_limit(void)
Definition: sr_policy_rewrite.c:160
vlib_cli_command_t
Definition: cli.h:92
ip6_sr_sl_t::bsid_dpo
dpo_id_t bsid_dpo
DPO for Encaps/Insert for BSID.
Definition: sr.h:81
from
from
Definition: nat44_ei_hairpinning.c:415
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
ip6_sr_main_t::sid_lists
ip6_sr_sl_t * sid_lists
Definition: sr.h:263
fib_table_find
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1106
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
vlib_get_next_frame
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:395
load_balance_path_t_
One path from an [EU]CMP set that the client wants to add to a load-balance object.
Definition: load_balance.h:62
replicate_multipath_update
void replicate_multipath_update(const dpo_id_t *dpo, load_balance_path_t *next_hops)
Definition: replicate_dpo.c:318
sr_policy_rewrite_error_strings
static char * sr_policy_rewrite_error_strings[]
Definition: sr_policy_rewrite.c:92
IPv6_DEFAULT_HOP_LIMIT
#define IPv6_DEFAULT_HOP_LIMIT
Definition: sr.h:34
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
ip6_sr_main_t::sr_policies_index_hash
mhash_t sr_policies_index_hash
Definition: sr.h:269
ip6_sr_main_t::fib_table_ip4
u32 fib_table_ip4
Definition: sr.h:307
dpo_reset
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:234
SR_SEGMENT_LIST_WEIGHT_DEFAULT
#define SR_SEGMENT_LIST_WEIGHT_DEFAULT
Definition: sr_mpls.h:39
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
DPO_PROTO_NUM
#define DPO_PROTO_NUM
Definition: dpo.h:72
mhash_unset
__clib_export uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:346
ip6_header_t::ip_version_traffic_class_and_flow_label
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:297
compute_rewrite_insert
static u8 * compute_rewrite_insert(ip6_address_t *sl)
SR rewrite string computation for SRH insertion (inline)
Definition: sr_policy_rewrite.c:258
fib_prefix_t_
Aggregate type for a prefix.
Definition: fib_types.h:202
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
ip6_sr_policy_t::plugin
u16 plugin
Definition: sr.h:113
sr_policy_command_fn
static clib_error_t * sr_policy_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI for 'sr policies' command family.
Definition: sr_policy_rewrite.c:926
vec_del1
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:896
sr_pr_bsid_encaps_ip6_nodes
const static char *const sr_pr_bsid_encaps_ip6_nodes[]
Definition: sr_policy_rewrite.c:3546
UNFORMAT_END_OF_INPUT
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
ip6_sr_sl_t::rewrite_bsid
u8 * rewrite_bsid
Precomputed rewrite header for bindingSID.
Definition: sr.h:77
mhash_set
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
sr_pr_encaps_src
static ip6_address_t sr_pr_encaps_src
IPv6 SA for encapsulated packets.
Definition: sr_policy_rewrite.c:109
foreach_sr_policy_rewrite_error
#define foreach_sr_policy_rewrite_error
Definition: sr_policy_rewrite.c:76
sr_policy_rewrite_next_t
sr_policy_rewrite_next_t
Definition: sr_policy_rewrite.c:67
DPO_REPLICATE
@ DPO_REPLICATE
Definition: dpo.h:105
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169