Line data Source code
1 : /*
2 : * Copyright (c) 2015 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : /*
16 : *------------------------------------------------------------------
17 : * as.c - SRv6 Static Proxy (AS) function
18 : *------------------------------------------------------------------
19 : */
20 :
21 : #include <vnet/vnet.h>
22 : #include <vnet/adj/adj.h>
23 : #include <vnet/plugin/plugin.h>
24 : #include <vpp/app/version.h>
25 : #include <srv6-as/as.h>
26 :
27 : #define SID_CREATE_IFACE_FEATURE_ERROR -1
28 : #define SID_CREATE_INVALID_IFACE_TYPE -3
29 : #define SID_CREATE_INVALID_IFACE_INDEX -4
30 : #define SID_CREATE_INVALID_ADJ_INDEX -5
31 :
32 : unsigned char function_name[] = "SRv6-AS-plugin";
33 : unsigned char keyword_str[] = "End.AS";
34 : unsigned char def_str[] =
35 : "Endpoint with static proxy to SR-unaware appliance";
36 : unsigned char params_str[] =
37 : "nh <next-hop> oif <iface-out> iif <iface-in> src <src-addr> next <sid> [next <sid> ...]";
38 :
39 : srv6_as_main_t srv6_as_main;
40 :
41 : static inline u8 *
42 6 : prepare_rewrite (ip6_address_t src_addr, ip6_address_t * sid_list,
43 : u8 protocol)
44 : {
45 6 : u8 *rewrite_str = NULL;
46 6 : u32 rewrite_len = IPv6_DEFAULT_HEADER_LENGTH;
47 :
48 6 : u8 num_sids = vec_len (sid_list);
49 6 : u32 sr_hdr_len = 0;
50 :
51 6 : if (num_sids > 1)
52 : {
53 3 : sr_hdr_len =
54 3 : sizeof (ip6_sr_header_t) + num_sids * sizeof (ip6_address_t);
55 3 : rewrite_len += sr_hdr_len;
56 : }
57 :
58 6 : vec_validate (rewrite_str, rewrite_len - 1);
59 :
60 : /* Fill IP header */
61 6 : ip6_header_t *iph = (ip6_header_t *) rewrite_str;
62 6 : iph->ip_version_traffic_class_and_flow_label =
63 6 : clib_host_to_net_u32 (0 | ((6 & 0xF) << 28));
64 6 : iph->src_address = src_addr;
65 6 : iph->dst_address = sid_list[0];
66 6 : iph->payload_length = sr_hdr_len;
67 6 : iph->hop_limit = sr_get_hop_limit ();
68 :
69 6 : if (num_sids > 1)
70 : {
71 : /* Set Next Header value to Routing Extension */
72 3 : iph->protocol = IP_PROTOCOL_IPV6_ROUTE;
73 :
74 : /* Fill SR header */
75 3 : ip6_sr_header_t *srh = (ip6_sr_header_t *) (iph + 1);
76 3 : srh->protocol = protocol;
77 3 : srh->length = sr_hdr_len / 8 - 1;
78 3 : srh->type = ROUTING_HEADER_TYPE_SR;
79 3 : srh->segments_left = num_sids - 1;
80 3 : srh->last_entry = num_sids - 1;
81 3 : srh->flags = 0x00;
82 3 : srh->tag = 0x0000;
83 :
84 : /* Fill segment list */
85 : ip6_address_t *this_address;
86 3 : ip6_address_t *addrp = srh->segments + srh->last_entry;
87 9 : vec_foreach (this_address, sid_list)
88 : {
89 6 : *addrp = *this_address;
90 6 : addrp--;
91 : }
92 : }
93 : else
94 : {
95 : /* Set Next Header value to inner protocol */
96 3 : iph->protocol = protocol;
97 : }
98 :
99 6 : return rewrite_str;
100 : }
101 :
102 : static inline void
103 6 : free_ls_mem (srv6_as_localsid_t * ls_mem)
104 : {
105 6 : vec_free (ls_mem->rewrite);
106 6 : vec_free (ls_mem->sid_list);
107 6 : clib_mem_free (ls_mem);
108 6 : }
109 :
110 :
111 : /*****************************************/
112 : /* SRv6 LocalSID instantiation and removal functions */
113 : static int
114 6 : srv6_as_localsid_creation_fn (ip6_sr_localsid_t * localsid)
115 : {
116 6 : ip6_sr_main_t *srm = &sr_main;
117 6 : srv6_as_main_t *sm = &srv6_as_main;
118 6 : srv6_as_localsid_t *ls_mem = localsid->plugin_mem;
119 6 : u32 localsid_index = localsid - srm->localsids;
120 :
121 : /* Step 1: Prepare xconnect adjacency for sending packets to the VNF */
122 :
123 : /* Retrieve the adjacency corresponding to the (OIF, next_hop) */
124 6 : adj_index_t nh_adj_index = ADJ_INDEX_INVALID;
125 6 : if (ls_mem->inner_type != AS_TYPE_L2)
126 : {
127 4 : if (ls_mem->inner_type == AS_TYPE_IP4)
128 2 : nh_adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4,
129 2 : VNET_LINK_IP4, &ls_mem->nh_addr,
130 : ls_mem->sw_if_index_out);
131 2 : else if (ls_mem->inner_type == AS_TYPE_IP6)
132 2 : nh_adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP6,
133 2 : VNET_LINK_IP6, &ls_mem->nh_addr,
134 : ls_mem->sw_if_index_out);
135 4 : if (nh_adj_index == ADJ_INDEX_INVALID)
136 : {
137 0 : free_ls_mem (ls_mem);
138 0 : return SID_CREATE_INVALID_ADJ_INDEX;
139 : }
140 : }
141 :
142 6 : ls_mem->nh_adj = nh_adj_index;
143 :
144 :
145 : /* Step 2: Prepare inbound policy for packets returning from the VNF */
146 :
147 : /* Make sure the provided incoming interface index is valid */
148 6 : if (pool_is_free_index (sm->vnet_main->interface_main.sw_interfaces,
149 6 : ls_mem->sw_if_index_in))
150 : {
151 0 : adj_unlock (ls_mem->nh_adj);
152 0 : free_ls_mem (ls_mem);
153 0 : return SID_CREATE_INVALID_IFACE_INDEX;
154 : }
155 :
156 : /* Retrieve associated interface structure */
157 6 : vnet_sw_interface_t *sw = vnet_get_sw_interface (sm->vnet_main,
158 : ls_mem->sw_if_index_in);
159 6 : if (sw->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
160 : {
161 0 : adj_unlock (ls_mem->nh_adj);
162 0 : free_ls_mem (ls_mem);
163 0 : return SID_CREATE_INVALID_IFACE_TYPE;
164 : }
165 :
166 6 : if (ls_mem->inner_type == AS_TYPE_L2)
167 : {
168 : /* Enable End.AS2 rewrite node for this interface */
169 : int ret =
170 2 : vnet_feature_enable_disable ("device-input", "srv6-as2-rewrite",
171 : ls_mem->sw_if_index_in, 1, 0, 0);
172 2 : if (ret != 0)
173 : {
174 0 : free_ls_mem (ls_mem);
175 0 : return SID_CREATE_IFACE_FEATURE_ERROR;
176 : }
177 :
178 : /* Set interface in promiscuous mode */
179 2 : vnet_main_t *vnm = vnet_get_main ();
180 : vnet_hw_interface_t *hi =
181 2 : vnet_get_sup_hw_interface (vnm, ls_mem->sw_if_index_in);
182 : /* Make sure it is main interface */
183 2 : if (hi->sw_if_index == ls_mem->sw_if_index_in)
184 2 : ethernet_set_flags (vnm, hi->hw_if_index,
185 : ETHERNET_INTERFACE_FLAG_ACCEPT_ALL);
186 :
187 : /* Prepare rewrite string */
188 2 : ls_mem->rewrite = prepare_rewrite (ls_mem->src_addr, ls_mem->sid_list,
189 : IP_PROTOCOL_IP6_ETHERNET);
190 :
191 : /* Associate local SID index to this interface (resize vector if needed) */
192 2 : if (ls_mem->sw_if_index_in >= vec_len (sm->sw_iface_localsid2))
193 : {
194 1 : vec_resize (sm->sw_iface_localsid2,
195 : (pool_len (sm->vnet_main->interface_main.sw_interfaces)
196 : - vec_len (sm->sw_iface_localsid2)));
197 : }
198 2 : sm->sw_iface_localsid2[ls_mem->sw_if_index_in] = localsid_index;
199 : }
200 4 : else if (ls_mem->inner_type == AS_TYPE_IP4)
201 : {
202 : /* Enable End.AS4 rewrite node for this interface */
203 : int ret =
204 2 : vnet_feature_enable_disable ("ip4-unicast", "srv6-as4-rewrite",
205 : ls_mem->sw_if_index_in, 1, 0, 0);
206 2 : if (ret != 0)
207 : {
208 0 : adj_unlock (ls_mem->nh_adj);
209 0 : free_ls_mem (ls_mem);
210 0 : return SID_CREATE_IFACE_FEATURE_ERROR;
211 : }
212 :
213 : /* Prepare rewrite string */
214 2 : ls_mem->rewrite = prepare_rewrite (ls_mem->src_addr, ls_mem->sid_list,
215 : IP_PROTOCOL_IP_IN_IP);
216 :
217 : /* Associate local SID index to this interface (resize vector if needed) */
218 2 : if (ls_mem->sw_if_index_in >= vec_len (sm->sw_iface_localsid4))
219 : {
220 1 : vec_resize (sm->sw_iface_localsid4,
221 : (pool_len (sm->vnet_main->interface_main.sw_interfaces)
222 : - vec_len (sm->sw_iface_localsid4)));
223 : }
224 2 : sm->sw_iface_localsid4[ls_mem->sw_if_index_in] = localsid_index;
225 : }
226 2 : else if (ls_mem->inner_type == AS_TYPE_IP6)
227 : {
228 : /* Enable End.AS6 rewrite node for this interface */
229 : int ret =
230 2 : vnet_feature_enable_disable ("ip6-unicast", "srv6-as6-rewrite",
231 : ls_mem->sw_if_index_in, 1, 0, 0);
232 2 : if (ret != 0)
233 : {
234 0 : adj_unlock (ls_mem->nh_adj);
235 0 : free_ls_mem (ls_mem);
236 0 : return SID_CREATE_IFACE_FEATURE_ERROR;
237 : }
238 :
239 : /* Prepare rewrite string */
240 2 : ls_mem->rewrite = prepare_rewrite (ls_mem->src_addr, ls_mem->sid_list,
241 : IP_PROTOCOL_IPV6);
242 :
243 : /* Associate local SID index to this interface (resize vector if needed) */
244 2 : if (ls_mem->sw_if_index_in >= vec_len (sm->sw_iface_localsid6))
245 : {
246 1 : vec_resize (sm->sw_iface_localsid6,
247 : (pool_len (sm->vnet_main->interface_main.sw_interfaces)
248 : - vec_len (sm->sw_iface_localsid6)));
249 : }
250 2 : sm->sw_iface_localsid6[ls_mem->sw_if_index_in] = localsid_index;
251 : }
252 :
253 : /* Step 3: Initialize rewrite counters */
254 : srv6_as_localsid_t **ls_p;
255 6 : pool_get (sm->sids, ls_p);
256 6 : *ls_p = ls_mem;
257 6 : ls_mem->index = ls_p - sm->sids;
258 :
259 6 : vlib_validate_combined_counter (&(sm->valid_counters), ls_mem->index);
260 6 : vlib_validate_combined_counter (&(sm->invalid_counters), ls_mem->index);
261 :
262 6 : vlib_zero_combined_counter (&(sm->valid_counters), ls_mem->index);
263 6 : vlib_zero_combined_counter (&(sm->invalid_counters), ls_mem->index);
264 :
265 6 : return 0;
266 : }
267 :
268 : static int
269 6 : srv6_as_localsid_removal_fn (ip6_sr_localsid_t * localsid)
270 : {
271 6 : srv6_as_main_t *sm = &srv6_as_main;
272 6 : srv6_as_localsid_t *ls_mem = localsid->plugin_mem;
273 :
274 6 : if (ls_mem->inner_type == AS_TYPE_L2)
275 : {
276 : /* Disable End.AS2 rewrite node for this interface */
277 : int ret;
278 2 : ret = vnet_feature_enable_disable ("device-input", "srv6-as2-rewrite",
279 : ls_mem->sw_if_index_in, 0, 0, 0);
280 2 : if (ret != 0)
281 0 : return -1;
282 :
283 : /* Disable promiscuous mode on the interface */
284 2 : vnet_main_t *vnm = vnet_get_main ();
285 : vnet_hw_interface_t *hi =
286 2 : vnet_get_sup_hw_interface (vnm, ls_mem->sw_if_index_in);
287 : /* Make sure it is main interface */
288 2 : if (hi->sw_if_index == ls_mem->sw_if_index_in)
289 2 : ethernet_set_flags (vnm, hi->hw_if_index, 0);
290 :
291 : /* Remove local SID index from interface table */
292 2 : sm->sw_iface_localsid2[ls_mem->sw_if_index_in] = ~(u32) 0;
293 : }
294 4 : else if (ls_mem->inner_type == AS_TYPE_IP4)
295 : {
296 : /* Disable End.AS4 rewrite node for this interface */
297 : int ret;
298 2 : ret = vnet_feature_enable_disable ("ip4-unicast", "srv6-as4-rewrite",
299 : ls_mem->sw_if_index_in, 0, 0, 0);
300 2 : if (ret != 0)
301 0 : return -1;
302 :
303 : /* Remove local SID index from interface table */
304 2 : sm->sw_iface_localsid4[ls_mem->sw_if_index_in] = ~(u32) 0;
305 : }
306 2 : else if (ls_mem->inner_type == AS_TYPE_IP6)
307 : {
308 : /* Disable End.AS6 rewrite node for this interface */
309 : int ret;
310 2 : ret = vnet_feature_enable_disable ("ip6-unicast", "srv6-as6-rewrite",
311 : ls_mem->sw_if_index_in, 0, 0, 0);
312 2 : if (ret != 0)
313 0 : return -1;
314 :
315 : /* Remove local SID index from interface table */
316 2 : sm->sw_iface_localsid6[ls_mem->sw_if_index_in] = ~(u32) 0;
317 : }
318 :
319 :
320 : /* Unlock (OIF, NHOP) adjacency (from sr_localsid.c:103) */
321 6 : adj_unlock (ls_mem->nh_adj);
322 :
323 : /* Delete SID entry */
324 6 : pool_put (sm->sids, pool_elt_at_index (sm->sids, ls_mem->index));
325 :
326 : /* Clean up local SID memory */
327 6 : free_ls_mem (ls_mem);
328 :
329 6 : return 0;
330 : }
331 :
332 : /**********************************/
333 : /* SRv6 LocalSID format functions */
334 : /*
335 : * Prints nicely the parameters of a localsid
336 : * Example: print "Table 5"
337 : */
338 : u8 *
339 18 : format_srv6_as_localsid (u8 * s, va_list * args)
340 : {
341 18 : srv6_as_localsid_t *ls_mem = va_arg (*args, void *);
342 :
343 18 : vnet_main_t *vnm = vnet_get_main ();
344 18 : srv6_as_main_t *sm = &srv6_as_main;
345 :
346 18 : if (ls_mem->inner_type == AS_TYPE_IP4)
347 : {
348 : s =
349 6 : format (s, "Next-hop:\t%U\n\t", format_ip4_address,
350 : &ls_mem->nh_addr.ip4);
351 : }
352 12 : else if (ls_mem->inner_type == AS_TYPE_IP6)
353 : {
354 : s =
355 6 : format (s, "Next-hop:\t%U\n\t", format_ip6_address,
356 : &ls_mem->nh_addr.ip6);
357 : }
358 :
359 18 : s = format (s, "Outgoing iface:\t%U\n", format_vnet_sw_if_index_name, vnm,
360 : ls_mem->sw_if_index_out);
361 18 : s = format (s, "\tIncoming iface:\t%U\n", format_vnet_sw_if_index_name, vnm,
362 : ls_mem->sw_if_index_in);
363 18 : s = format (s, "\tSource address:\t%U\n", format_ip6_address,
364 : &ls_mem->src_addr);
365 :
366 18 : s = format (s, "\tSegment list:\t< ");
367 : ip6_address_t *addr;
368 45 : vec_foreach (addr, ls_mem->sid_list)
369 : {
370 27 : s = format (s, "%U, ", format_ip6_address, addr);
371 : }
372 18 : s = format (s, "\b\b >\n");
373 :
374 : vlib_counter_t valid, invalid;
375 18 : vlib_get_combined_counter (&(sm->valid_counters), ls_mem->index, &valid);
376 18 : vlib_get_combined_counter (&(sm->invalid_counters), ls_mem->index,
377 : &invalid);
378 : s =
379 18 : format (s, "\tGood rewrite traffic: \t[%Ld packets : %Ld bytes]\n",
380 : valid.packets, valid.bytes);
381 : s =
382 18 : format (s, "\tBad rewrite traffic: \t[%Ld packets : %Ld bytes]\n",
383 : invalid.packets, invalid.bytes);
384 :
385 18 : return s;
386 : }
387 :
388 : /*
389 : * Process the parameters of a localsid
390 : * Example: process from:
391 : * sr localsid address cafe::1 behavior new_srv6_localsid 5
392 : * everything from behavior on... so in this case 'new_srv6_localsid 5'
393 : * Notice that it MUST match the keyword_str and params_str defined above.
394 : */
395 : uword
396 9 : unformat_srv6_as_localsid (unformat_input_t * input, va_list * args)
397 : {
398 9 : void **plugin_mem_p = va_arg (*args, void **);
399 : srv6_as_localsid_t *ls_mem;
400 :
401 9 : vnet_main_t *vnm = vnet_get_main ();
402 :
403 9 : u8 inner_type = AS_TYPE_L2;
404 : ip46_address_t nh_addr;
405 : u32 sw_if_index_out;
406 : u32 sw_if_index_in;
407 : ip6_address_t src_addr;
408 : ip6_address_t next_sid;
409 9 : ip6_address_t *sid_list = NULL;
410 :
411 9 : u8 params = 0;
412 : #define PARAM_AS_NH (1 << 0)
413 : #define PARAM_AS_OIF (1 << 1)
414 : #define PARAM_AS_IIF (1 << 2)
415 : #define PARAM_AS_SRC (1 << 3)
416 :
417 9 : if (!unformat (input, "end.as"))
418 3 : return 0;
419 :
420 35 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
421 : {
422 29 : if (!(params & PARAM_AS_NH) && unformat (input, "nh %U",
423 : unformat_ip4_address,
424 : &nh_addr.ip4))
425 : {
426 2 : inner_type = AS_TYPE_IP4;
427 2 : params |= PARAM_AS_NH;
428 : }
429 29 : if (!(params & PARAM_AS_NH) && unformat (input, "nh %U",
430 : unformat_ip6_address,
431 : &nh_addr.ip6))
432 : {
433 2 : inner_type = AS_TYPE_IP6;
434 2 : params |= PARAM_AS_NH;
435 : }
436 27 : else if (!(params & PARAM_AS_OIF) && unformat (input, "oif %U",
437 : unformat_vnet_sw_interface,
438 : vnm, &sw_if_index_out))
439 : {
440 6 : params |= PARAM_AS_OIF;
441 : }
442 21 : else if (!(params & PARAM_AS_IIF) && unformat (input, "iif %U",
443 : unformat_vnet_sw_interface,
444 : vnm, &sw_if_index_in))
445 : {
446 6 : params |= PARAM_AS_IIF;
447 : }
448 15 : else if (!(params & PARAM_AS_SRC) && unformat (input, "src %U",
449 : unformat_ip6_address,
450 : &src_addr))
451 : {
452 6 : params |= PARAM_AS_SRC;
453 : }
454 9 : else if (unformat (input, "next %U", unformat_ip6_address, &next_sid))
455 : {
456 9 : vec_add1 (sid_list, next_sid);
457 : }
458 : else
459 : {
460 0 : break;
461 : }
462 : }
463 :
464 : /* Make sure that all parameters are supplied */
465 6 : u8 params_chk = (PARAM_AS_OIF | PARAM_AS_IIF | PARAM_AS_SRC);
466 6 : if ((params & params_chk) != params_chk || sid_list == NULL)
467 : {
468 0 : vec_free (sid_list);
469 0 : return 0;
470 : }
471 :
472 : /* Allocate and initialize memory block for local SID parameters */
473 6 : ls_mem = clib_mem_alloc (sizeof *ls_mem);
474 6 : clib_memset (ls_mem, 0, sizeof *ls_mem);
475 6 : *plugin_mem_p = ls_mem;
476 :
477 : /* Set local SID parameters */
478 6 : ls_mem->inner_type = inner_type;
479 6 : if (inner_type == AS_TYPE_IP4)
480 2 : ls_mem->nh_addr.ip4 = nh_addr.ip4;
481 4 : else if (inner_type == AS_TYPE_IP6)
482 2 : ls_mem->nh_addr.ip6 = nh_addr.ip6;
483 6 : ls_mem->sw_if_index_out = sw_if_index_out;
484 6 : ls_mem->sw_if_index_in = sw_if_index_in;
485 6 : ls_mem->src_addr = src_addr;
486 6 : ls_mem->sid_list = sid_list;
487 :
488 6 : return 1;
489 : }
490 :
491 : /*************************/
492 : /* SRv6 LocalSID FIB DPO */
493 : static u8 *
494 0 : format_srv6_as_dpo (u8 * s, va_list * args)
495 : {
496 0 : index_t index = va_arg (*args, index_t);
497 0 : CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
498 :
499 0 : return (format (s, "SR: static_proxy_index:[%u]", index));
500 : }
501 :
502 : void
503 36 : srv6_as_dpo_lock (dpo_id_t * dpo)
504 : {
505 36 : }
506 :
507 : void
508 36 : srv6_as_dpo_unlock (dpo_id_t * dpo)
509 : {
510 36 : }
511 :
512 : const static dpo_vft_t srv6_as_vft = {
513 : .dv_lock = srv6_as_dpo_lock,
514 : .dv_unlock = srv6_as_dpo_unlock,
515 : .dv_format = format_srv6_as_dpo,
516 : };
517 :
518 : const static char *const srv6_as_ip6_nodes[] = {
519 : "srv6-as-localsid",
520 : NULL,
521 : };
522 :
523 : const static char *const *const srv6_as_nodes[DPO_PROTO_NUM] = {
524 : [DPO_PROTO_IP6] = srv6_as_ip6_nodes,
525 : };
526 :
527 : /**********************/
528 : static clib_error_t *
529 575 : srv6_as_init (vlib_main_t * vm)
530 : {
531 575 : srv6_as_main_t *sm = &srv6_as_main;
532 575 : int rv = 0;
533 :
534 575 : sm->vlib_main = vm;
535 575 : sm->vnet_main = vnet_get_main ();
536 :
537 : /* Create DPO */
538 575 : sm->srv6_as_dpo_type = dpo_register_new_type (&srv6_as_vft, srv6_as_nodes);
539 :
540 : /* Register SRv6 LocalSID */
541 575 : rv = sr_localsid_register_function (vm,
542 : function_name,
543 : keyword_str,
544 : def_str,
545 : params_str,
546 : 128,
547 : &sm->srv6_as_dpo_type,
548 : format_srv6_as_localsid,
549 : unformat_srv6_as_localsid,
550 : srv6_as_localsid_creation_fn,
551 : srv6_as_localsid_removal_fn);
552 575 : if (rv < 0)
553 0 : clib_error_return (0, "SRv6 LocalSID function could not be registered.");
554 : else
555 575 : sm->srv6_localsid_behavior_id = rv;
556 :
557 575 : return 0;
558 : }
559 :
560 : /* *INDENT-OFF* */
561 18431 : VNET_FEATURE_INIT (srv6_as2_rewrite, static) =
562 : {
563 : .arc_name = "device-input",
564 : .node_name = "srv6-as2-rewrite",
565 : .runs_before = VNET_FEATURES ("ethernet-input"),
566 : };
567 :
568 18431 : VNET_FEATURE_INIT (srv6_as4_rewrite, static) =
569 : {
570 : .arc_name = "ip4-unicast",
571 : .node_name = "srv6-as4-rewrite",
572 : .runs_before = 0,
573 : };
574 :
575 18431 : VNET_FEATURE_INIT (srv6_as6_rewrite, static) =
576 : {
577 : .arc_name = "ip6-unicast",
578 : .node_name = "srv6-as6-rewrite",
579 : .runs_before = 0,
580 : };
581 :
582 1151 : VLIB_INIT_FUNCTION (srv6_as_init);
583 :
584 : VLIB_PLUGIN_REGISTER () = {
585 : .version = VPP_BUILD_VER,
586 : .description = "Static Segment Routing for IPv6 (SRv6) Proxy",
587 : };
588 : /* *INDENT-ON* */
589 :
590 : /*
591 : * fd.io coding-style-patch-verification: ON
592 : *
593 : * Local Variables:
594 : * eval: (c-set-style "gnu")
595 : * End:
596 : */
|