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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include <vlib/vlib.h>
16 #include <vnet/vnet.h>
17 #include <vppinfra/error.h>
18 #include <srv6-un/un.h>
21 /******************************* Packet tracing *******************************/
25 } srv6_un_localsid_trace_t;
29 format_srv6_un_localsid_trace (u8 * s, va_list * args)
31 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
32 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
33 srv6_un_localsid_trace_t *t = va_arg (*args, srv6_un_localsid_trace_t *);
35 return format (s, "SRv6-uN-localsid: localsid_index %d", t->localsid_index);
38 /********************************* Next nodes *********************************/
41 SRV6_UN_LOCALSID_NEXT_ERROR,
42 SRV6_UN_LOCALSID_NEXT_IP6LOOKUP,
43 SRV6_UN_LOCALSID_N_NEXT,
44 } srv6_un_localsid_next_t;
46 /******************************* Local SID node *******************************/
49 * @brief Graph node for applying SRv6 uN.
52 srv6_un_localsid_fn (vlib_main_t * vm,
53 vlib_node_runtime_t * node, vlib_frame_t * frame)
55 ip6_sr_main_t *sm = &sr_main;
56 u32 n_left_from, next_index, *from, *to_next;
58 from = vlib_frame_vector_args (frame);
59 n_left_from = frame->n_vectors;
60 next_index = node->cached_next_index;
62 u32 thread_index = vm->thread_index;
64 while (n_left_from > 0)
67 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
70 while (n_left_from >= 8 && n_left_to_next >= 4)
72 u32 bi0, bi1, bi2, bi3;
73 vlib_buffer_t *b0, *b1, *b2, *b3;
74 ip6_header_t *ip0, *ip1, *ip2, *ip3;
75 u32 next0, next1, next2, next3;
76 next0 = next1 = next2 = next3 = SRV6_UN_LOCALSID_NEXT_IP6LOOKUP;
77 ip6_sr_localsid_t *ls0, *ls1, *ls2, *ls3;
79 /* Prefetch next iteration. */
81 vlib_buffer_t *p4, *p5, *p6, *p7;
83 p4 = vlib_get_buffer (vm, from[4]);
84 p5 = vlib_get_buffer (vm, from[5]);
85 p6 = vlib_get_buffer (vm, from[6]);
86 p7 = vlib_get_buffer (vm, from[7]);
88 /* Prefetch the buffer header and packet for the N+4 loop iteration */
89 vlib_prefetch_buffer_header (p4, LOAD);
90 vlib_prefetch_buffer_header (p5, LOAD);
91 vlib_prefetch_buffer_header (p6, LOAD);
92 vlib_prefetch_buffer_header (p7, LOAD);
94 CLIB_PREFETCH (p4->data, CLIB_CACHE_LINE_BYTES, STORE);
95 CLIB_PREFETCH (p5->data, CLIB_CACHE_LINE_BYTES, STORE);
96 CLIB_PREFETCH (p6->data, CLIB_CACHE_LINE_BYTES, STORE);
97 CLIB_PREFETCH (p7->data, CLIB_CACHE_LINE_BYTES, STORE);
100 to_next[0] = bi0 = from[0];
101 to_next[1] = bi1 = from[1];
102 to_next[2] = bi2 = from[2];
103 to_next[3] = bi3 = from[3];
109 b0 = vlib_get_buffer (vm, bi0);
110 b1 = vlib_get_buffer (vm, bi1);
111 b2 = vlib_get_buffer (vm, bi2);
112 b3 = vlib_get_buffer (vm, bi3);
115 pool_elt_at_index (sm->localsids,
116 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
118 pool_elt_at_index (sm->localsids,
119 vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
121 pool_elt_at_index (sm->localsids,
122 vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
124 pool_elt_at_index (sm->localsids,
125 vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
127 ip0 = vlib_buffer_get_current (b0);
128 ip1 = vlib_buffer_get_current (b1);
129 ip2 = vlib_buffer_get_current (b2);
130 ip3 = vlib_buffer_get_current (b3);
132 /* Set Destination Address to Last Segment (index 0) */
133 ip0->dst_address.as_u16[2] = ip0->dst_address.as_u16[3];
134 ip0->dst_address.as_u16[3] = ip0->dst_address.as_u16[4];
135 ip0->dst_address.as_u16[4] = ip0->dst_address.as_u16[5];
136 ip0->dst_address.as_u16[5] = ip0->dst_address.as_u16[6];
137 ip0->dst_address.as_u16[6] = ip0->dst_address.as_u16[7];
138 ip0->dst_address.as_u16[7] = 0x0000;
140 ip1->dst_address.as_u16[2] = ip1->dst_address.as_u16[3];
141 ip1->dst_address.as_u16[3] = ip1->dst_address.as_u16[4];
142 ip1->dst_address.as_u16[4] = ip1->dst_address.as_u16[5];
143 ip1->dst_address.as_u16[5] = ip1->dst_address.as_u16[6];
144 ip1->dst_address.as_u16[6] = ip1->dst_address.as_u16[7];
145 ip1->dst_address.as_u16[7] = 0x0000;
147 ip2->dst_address.as_u16[2] = ip2->dst_address.as_u16[3];
148 ip2->dst_address.as_u16[3] = ip2->dst_address.as_u16[4];
149 ip2->dst_address.as_u16[4] = ip2->dst_address.as_u16[5];
150 ip2->dst_address.as_u16[5] = ip2->dst_address.as_u16[6];
151 ip2->dst_address.as_u16[6] = ip2->dst_address.as_u16[7];
152 ip2->dst_address.as_u16[7] = 0x0000;
154 ip3->dst_address.as_u16[2] = ip3->dst_address.as_u16[3];
155 ip3->dst_address.as_u16[3] = ip3->dst_address.as_u16[4];
156 ip3->dst_address.as_u16[4] = ip3->dst_address.as_u16[5];
157 ip3->dst_address.as_u16[5] = ip3->dst_address.as_u16[6];
158 ip3->dst_address.as_u16[6] = ip3->dst_address.as_u16[7];
159 ip3->dst_address.as_u16[7] = 0x0000;
161 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
163 srv6_un_localsid_trace_t *tr =
164 vlib_add_trace (vm, node, b0, sizeof (*tr));
165 tr->localsid_index = ls0 - sm->localsids;
168 if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
170 srv6_un_localsid_trace_t *tr =
171 vlib_add_trace (vm, node, b1, sizeof (*tr));
172 tr->localsid_index = ls1 - sm->localsids;
175 if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
177 srv6_un_localsid_trace_t *tr =
178 vlib_add_trace (vm, node, b2, sizeof (*tr));
179 tr->localsid_index = ls2 - sm->localsids;
182 if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
184 srv6_un_localsid_trace_t *tr =
185 vlib_add_trace (vm, node, b3, sizeof (*tr));
186 tr->localsid_index = ls3 - sm->localsids;
189 vlib_increment_combined_counter
190 (&(sm->sr_ls_valid_counters),
191 thread_index, ls0 - sm->localsids,
192 1, vlib_buffer_length_in_chain (vm, b0));
194 vlib_increment_combined_counter
195 (&(sm->sr_ls_valid_counters),
196 thread_index, ls1 - sm->localsids,
197 1, vlib_buffer_length_in_chain (vm, b1));
199 vlib_increment_combined_counter
200 (&(sm->sr_ls_valid_counters),
201 thread_index, ls2 - sm->localsids,
202 1, vlib_buffer_length_in_chain (vm, b2));
204 vlib_increment_combined_counter
205 (&(sm->sr_ls_valid_counters),
206 thread_index, ls3 - sm->localsids,
207 1, vlib_buffer_length_in_chain (vm, b3));
209 vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
210 n_left_to_next, bi0, bi1, bi2, bi3,
211 next0, next1, next2, next3);
214 while (n_left_from > 0 && n_left_to_next > 0)
218 ip6_header_t *ip0 = 0;
219 u32 next0 = SRV6_UN_LOCALSID_NEXT_IP6LOOKUP;
220 ip6_sr_localsid_t *ls0;
228 b0 = vlib_get_buffer (vm, bi0);
229 ip0 = vlib_buffer_get_current (b0);
231 /* Lookup the SR End behavior based on IP DA (adj) */
233 pool_elt_at_index (sm->localsids,
234 vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
236 /* Set Destination Address to Last Segment (index 0) */
237 ip0->dst_address.as_u16[2] = ip0->dst_address.as_u16[3];
238 ip0->dst_address.as_u16[3] = ip0->dst_address.as_u16[4];
239 ip0->dst_address.as_u16[4] = ip0->dst_address.as_u16[5];
240 ip0->dst_address.as_u16[5] = ip0->dst_address.as_u16[6];
241 ip0->dst_address.as_u16[6] = ip0->dst_address.as_u16[7];
242 ip0->dst_address.as_u16[7] = 0x0000;
244 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
246 srv6_un_localsid_trace_t *tr =
247 vlib_add_trace (vm, node, b0, sizeof (*tr));
248 tr->localsid_index = ls0 - sm->localsids;
251 /* This increments the SRv6 per LocalSID counters. */
252 vlib_increment_combined_counter
253 (&(sm->sr_ls_valid_counters),
254 thread_index, ls0 - sm->localsids,
255 1, vlib_buffer_length_in_chain (vm, b0));
257 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
258 n_left_to_next, bi0, next0);
262 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
265 return frame->n_vectors;
269 VLIB_REGISTER_NODE (srv6_un_localsid_node) = {
270 .function = srv6_un_localsid_fn,
271 .name = "srv6-un-localsid",
272 .vector_size = sizeof (u32),
273 .format_trace = format_srv6_un_localsid_trace,
274 .type = VLIB_NODE_TYPE_INTERNAL,
275 .n_next_nodes = SRV6_UN_LOCALSID_N_NEXT,
277 [SRV6_UN_LOCALSID_NEXT_IP6LOOKUP] = "ip6-lookup",
278 [SRV6_UN_LOCALSID_NEXT_ERROR] = "error-drop",
284 * fd.io coding-style-patch-verification: ON
287 * eval: (c-set-style "gnu")