Line data Source code
1 : /*
2 : * Copyright (c) 2020 Cisco and/or its affiliates.
3 : * Copyright (c) 2020 Doc.ai and/or its affiliates.
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at:
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : */
16 :
17 : #include <wireguard/wireguard.h>
18 : #include <wireguard/wireguard_peer.h>
19 :
20 : #define foreach_wg_handoff_error \
21 : _(CONGESTION_DROP, "congestion drop")
22 :
23 : typedef enum
24 : {
25 : #define _(sym,str) WG_HANDOFF_ERROR_##sym,
26 : foreach_wg_handoff_error
27 : #undef _
28 : HANDOFF_N_ERROR,
29 : } ipsec_handoff_error_t;
30 :
31 : static char *wg_handoff_error_strings[] = {
32 : #define _(sym,string) string,
33 : foreach_wg_handoff_error
34 : #undef _
35 : };
36 :
37 : typedef enum
38 : {
39 : WG_HANDOFF_HANDSHAKE,
40 : WG_HANDOFF_INP_DATA,
41 : WG_HANDOFF_OUT_TUN,
42 : } wg_handoff_mode_t;
43 :
44 : typedef struct wg_handoff_trace_t_
45 : {
46 : u32 next_worker_index;
47 : index_t peer;
48 : } wg_handoff_trace_t;
49 :
50 : static u8 *
51 880 : format_wg_handoff_trace (u8 * s, va_list * args)
52 : {
53 880 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
54 880 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
55 880 : wg_handoff_trace_t *t = va_arg (*args, wg_handoff_trace_t *);
56 :
57 880 : s = format (s, "next-worker %d peer %d", t->next_worker_index, t->peer);
58 :
59 880 : return s;
60 : }
61 :
62 : static_always_inline uword
63 69 : wg_handoff (vlib_main_t * vm,
64 : vlib_node_runtime_t * node,
65 : vlib_frame_t * frame, u32 fq_index, wg_handoff_mode_t mode)
66 : {
67 : vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
68 : u16 thread_indices[VLIB_FRAME_SIZE], *ti;
69 : u32 n_enq, n_left_from, *from;
70 : wg_main_t *wmp;
71 :
72 69 : wmp = &wg_main;
73 69 : from = vlib_frame_vector_args (frame);
74 69 : n_left_from = frame->n_vectors;
75 69 : vlib_get_buffers (vm, from, bufs, n_left_from);
76 :
77 69 : b = bufs;
78 69 : ti = thread_indices;
79 :
80 1041 : while (n_left_from > 0)
81 : {
82 : const wg_peer_t *peer;
83 972 : index_t peeri = INDEX_INVALID;
84 :
85 972 : if (PREDICT_FALSE (mode == WG_HANDOFF_HANDSHAKE))
86 : {
87 462 : ti[0] = 0;
88 : }
89 510 : else if (mode == WG_HANDOFF_INP_DATA)
90 : {
91 255 : message_data_t *data = vlib_buffer_get_current (b[0]);
92 : u32 *entry =
93 255 : wg_index_table_lookup (&wmp->index_table, data->receiver_index);
94 255 : peeri = *entry;
95 255 : peer = wg_peer_get (peeri);
96 :
97 255 : ti[0] = peer->input_thread_index;
98 : }
99 : else
100 : {
101 : peeri =
102 255 : wg_peer_get_by_adj_index (vnet_buffer (b[0])->
103 : ip.adj_index[VLIB_TX]);
104 255 : peer = wg_peer_get (peeri);
105 255 : ti[0] = peer->output_thread_index;
106 : }
107 :
108 972 : if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
109 : {
110 : wg_handoff_trace_t *t =
111 972 : vlib_add_trace (vm, node, b[0], sizeof (*t));
112 972 : t->next_worker_index = ti[0];
113 972 : t->peer = peeri;
114 : }
115 :
116 972 : n_left_from -= 1;
117 972 : ti += 1;
118 972 : b += 1;
119 : }
120 :
121 69 : n_enq = vlib_buffer_enqueue_to_thread (vm, node, fq_index, from,
122 69 : thread_indices, frame->n_vectors, 1);
123 :
124 69 : if (n_enq < frame->n_vectors)
125 0 : vlib_node_increment_counter (vm, node->node_index,
126 : WG_HANDOFF_ERROR_CONGESTION_DROP,
127 0 : frame->n_vectors - n_enq);
128 :
129 69 : return n_enq;
130 : }
131 :
132 615 : VLIB_NODE_FN (wg4_handshake_handoff)
133 : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
134 : {
135 40 : wg_main_t *wmp = &wg_main;
136 :
137 40 : return wg_handoff (vm, node, from_frame, wmp->in4_fq_index,
138 : WG_HANDOFF_HANDSHAKE);
139 : }
140 :
141 602 : VLIB_NODE_FN (wg6_handshake_handoff)
142 : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
143 : {
144 27 : wg_main_t *wmp = &wg_main;
145 :
146 27 : return wg_handoff (vm, node, from_frame, wmp->in6_fq_index,
147 : WG_HANDOFF_HANDSHAKE);
148 : }
149 :
150 576 : VLIB_NODE_FN (wg4_input_data_handoff)
151 : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
152 : {
153 1 : wg_main_t *wmp = &wg_main;
154 :
155 1 : return wg_handoff (vm, node, from_frame, wmp->in4_fq_index,
156 : WG_HANDOFF_INP_DATA);
157 : }
158 :
159 575 : VLIB_NODE_FN (wg6_input_data_handoff)
160 : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
161 : {
162 0 : wg_main_t *wmp = &wg_main;
163 :
164 0 : return wg_handoff (vm, node, from_frame, wmp->in6_fq_index,
165 : WG_HANDOFF_INP_DATA);
166 : }
167 :
168 576 : VLIB_NODE_FN (wg4_output_tun_handoff)
169 : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
170 : {
171 1 : wg_main_t *wmp = &wg_main;
172 :
173 1 : return wg_handoff (vm, node, from_frame, wmp->out4_fq_index,
174 : WG_HANDOFF_OUT_TUN);
175 : }
176 :
177 575 : VLIB_NODE_FN (wg6_output_tun_handoff)
178 : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
179 : {
180 0 : wg_main_t *wmp = &wg_main;
181 :
182 0 : return wg_handoff (vm, node, from_frame, wmp->out6_fq_index,
183 : WG_HANDOFF_OUT_TUN);
184 : }
185 :
186 : /* *INDENT-OFF* */
187 1151 : VLIB_REGISTER_NODE (wg4_handshake_handoff) =
188 : {
189 : .name = "wg4-handshake-handoff",
190 : .vector_size = sizeof (u32),
191 : .format_trace = format_wg_handoff_trace,
192 : .type = VLIB_NODE_TYPE_INTERNAL,
193 : .n_errors = ARRAY_LEN (wg_handoff_error_strings),
194 : .error_strings = wg_handoff_error_strings,
195 : .n_next_nodes = 1,
196 : .next_nodes = {
197 : [0] = "error-drop",
198 : },
199 : };
200 :
201 1151 : VLIB_REGISTER_NODE (wg6_handshake_handoff) =
202 : {
203 : .name = "wg6-handshake-handoff",
204 : .vector_size = sizeof (u32),
205 : .format_trace = format_wg_handoff_trace,
206 : .type = VLIB_NODE_TYPE_INTERNAL,
207 : .n_errors = ARRAY_LEN (wg_handoff_error_strings),
208 : .error_strings = wg_handoff_error_strings,
209 : .n_next_nodes = 1,
210 : .next_nodes = {
211 : [0] = "error-drop",
212 : },
213 : };
214 :
215 1151 : VLIB_REGISTER_NODE (wg4_input_data_handoff) =
216 : {
217 : .name = "wg4-input-data-handoff",
218 : .vector_size = sizeof (u32),
219 : .format_trace = format_wg_handoff_trace,
220 : .type = VLIB_NODE_TYPE_INTERNAL,
221 : .n_errors = ARRAY_LEN (wg_handoff_error_strings),
222 : .error_strings = wg_handoff_error_strings,
223 : .n_next_nodes = 1,
224 : .next_nodes = {
225 : [0] = "error-drop",
226 : },
227 : };
228 :
229 1151 : VLIB_REGISTER_NODE (wg6_input_data_handoff) =
230 : {
231 : .name = "wg6-input-data-handoff",
232 : .vector_size = sizeof (u32),
233 : .format_trace = format_wg_handoff_trace,
234 : .type = VLIB_NODE_TYPE_INTERNAL,
235 : .n_errors = ARRAY_LEN (wg_handoff_error_strings),
236 : .error_strings = wg_handoff_error_strings,
237 : .n_next_nodes = 1,
238 : .next_nodes = {
239 : [0] = "error-drop",
240 : },
241 : };
242 :
243 1151 : VLIB_REGISTER_NODE (wg4_output_tun_handoff) =
244 : {
245 : .name = "wg4-output-tun-handoff",
246 : .vector_size = sizeof (u32),
247 : .format_trace = format_wg_handoff_trace,
248 : .type = VLIB_NODE_TYPE_INTERNAL,
249 : .n_errors = ARRAY_LEN (wg_handoff_error_strings),
250 : .error_strings = wg_handoff_error_strings,
251 : .n_next_nodes = 1,
252 : .next_nodes = {
253 : [0] = "error-drop",
254 : },
255 : };
256 :
257 1151 : VLIB_REGISTER_NODE (wg6_output_tun_handoff) =
258 : {
259 : .name = "wg6-output-tun-handoff",
260 : .vector_size = sizeof (u32),
261 : .format_trace = format_wg_handoff_trace,
262 : .type = VLIB_NODE_TYPE_INTERNAL,
263 : .n_errors = ARRAY_LEN (wg_handoff_error_strings),
264 : .error_strings = wg_handoff_error_strings,
265 : .n_next_nodes = 1,
266 : .next_nodes = {
267 : [0] = "error-drop",
268 : },
269 : };
270 : /* *INDENT-ON* */
271 :
272 : /*
273 : * fd.io coding-style-patch-verification: ON
274 : *
275 : * Local Variables:
276 : * eval: (c-set-style "gnu")
277 : * End:
278 : */
|