hs-test: more debug output in http3 test
[vpp.git] / src / plugins / wireguard / wireguard_handoff.c
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 format_wg_handoff_trace (u8 * s, va_list * args)
52 {
53   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
54   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
55   wg_handoff_trace_t *t = va_arg (*args, wg_handoff_trace_t *);
56
57   s = format (s, "next-worker %d peer %d", t->next_worker_index, t->peer);
58
59   return s;
60 }
61
62 static_always_inline uword
63 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   wmp = &wg_main;
73   from = vlib_frame_vector_args (frame);
74   n_left_from = frame->n_vectors;
75   vlib_get_buffers (vm, from, bufs, n_left_from);
76
77   b = bufs;
78   ti = thread_indices;
79
80   while (n_left_from > 0)
81     {
82       const wg_peer_t *peer;
83       index_t peeri = INDEX_INVALID;
84
85       if (PREDICT_FALSE (mode == WG_HANDOFF_HANDSHAKE))
86         {
87           ti[0] = 0;
88         }
89       else if (mode == WG_HANDOFF_INP_DATA)
90         {
91           message_data_t *data = vlib_buffer_get_current (b[0]);
92           u32 *entry =
93             wg_index_table_lookup (&wmp->index_table, data->receiver_index);
94           peeri = *entry;
95           peer = wg_peer_get (peeri);
96
97           ti[0] = peer->input_thread_index;
98         }
99       else
100         {
101           peeri =
102             wg_peer_get_by_adj_index (vnet_buffer (b[0])->
103                                       ip.adj_index[VLIB_TX]);
104           peer = wg_peer_get (peeri);
105           ti[0] = peer->output_thread_index;
106         }
107
108       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
109         {
110           wg_handoff_trace_t *t =
111             vlib_add_trace (vm, node, b[0], sizeof (*t));
112           t->next_worker_index = ti[0];
113           t->peer = peeri;
114         }
115
116       n_left_from -= 1;
117       ti += 1;
118       b += 1;
119     }
120
121   n_enq = vlib_buffer_enqueue_to_thread (vm, node, fq_index, from,
122                                          thread_indices, frame->n_vectors, 1);
123
124   if (n_enq < frame->n_vectors)
125     vlib_node_increment_counter (vm, node->node_index,
126                                  WG_HANDOFF_ERROR_CONGESTION_DROP,
127                                  frame->n_vectors - n_enq);
128
129   return n_enq;
130 }
131
132 VLIB_NODE_FN (wg4_handshake_handoff)
133 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
134 {
135   wg_main_t *wmp = &wg_main;
136
137   return wg_handoff (vm, node, from_frame, wmp->in4_fq_index,
138                      WG_HANDOFF_HANDSHAKE);
139 }
140
141 VLIB_NODE_FN (wg6_handshake_handoff)
142 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
143 {
144   wg_main_t *wmp = &wg_main;
145
146   return wg_handoff (vm, node, from_frame, wmp->in6_fq_index,
147                      WG_HANDOFF_HANDSHAKE);
148 }
149
150 VLIB_NODE_FN (wg4_input_data_handoff)
151 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
152 {
153   wg_main_t *wmp = &wg_main;
154
155   return wg_handoff (vm, node, from_frame, wmp->in4_fq_index,
156                      WG_HANDOFF_INP_DATA);
157 }
158
159 VLIB_NODE_FN (wg6_input_data_handoff)
160 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
161 {
162   wg_main_t *wmp = &wg_main;
163
164   return wg_handoff (vm, node, from_frame, wmp->in6_fq_index,
165                      WG_HANDOFF_INP_DATA);
166 }
167
168 VLIB_NODE_FN (wg4_output_tun_handoff)
169 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
170 {
171   wg_main_t *wmp = &wg_main;
172
173   return wg_handoff (vm, node, from_frame, wmp->out4_fq_index,
174                      WG_HANDOFF_OUT_TUN);
175 }
176
177 VLIB_NODE_FN (wg6_output_tun_handoff)
178 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
179 {
180   wg_main_t *wmp = &wg_main;
181
182   return wg_handoff (vm, node, from_frame, wmp->out6_fq_index,
183                      WG_HANDOFF_OUT_TUN);
184 }
185
186 VLIB_REGISTER_NODE (wg4_handshake_handoff) =
187 {
188   .name = "wg4-handshake-handoff",
189   .vector_size = sizeof (u32),
190   .format_trace = format_wg_handoff_trace,
191   .type = VLIB_NODE_TYPE_INTERNAL,
192   .n_errors = ARRAY_LEN (wg_handoff_error_strings),
193   .error_strings = wg_handoff_error_strings,
194   .n_next_nodes = 1,
195   .next_nodes = {
196     [0] = "error-drop",
197   },
198 };
199
200 VLIB_REGISTER_NODE (wg6_handshake_handoff) =
201 {
202   .name = "wg6-handshake-handoff",
203   .vector_size = sizeof (u32),
204   .format_trace = format_wg_handoff_trace,
205   .type = VLIB_NODE_TYPE_INTERNAL,
206   .n_errors = ARRAY_LEN (wg_handoff_error_strings),
207   .error_strings = wg_handoff_error_strings,
208   .n_next_nodes = 1,
209   .next_nodes = {
210     [0] = "error-drop",
211   },
212 };
213
214 VLIB_REGISTER_NODE (wg4_input_data_handoff) =
215 {
216   .name = "wg4-input-data-handoff",
217   .vector_size = sizeof (u32),
218   .format_trace = format_wg_handoff_trace,
219   .type = VLIB_NODE_TYPE_INTERNAL,
220   .n_errors = ARRAY_LEN (wg_handoff_error_strings),
221   .error_strings = wg_handoff_error_strings,
222   .n_next_nodes = 1,
223   .next_nodes = {
224     [0] = "error-drop",
225   },
226 };
227
228 VLIB_REGISTER_NODE (wg6_input_data_handoff) =
229 {
230   .name = "wg6-input-data-handoff",
231   .vector_size = sizeof (u32),
232   .format_trace = format_wg_handoff_trace,
233   .type = VLIB_NODE_TYPE_INTERNAL,
234   .n_errors = ARRAY_LEN (wg_handoff_error_strings),
235   .error_strings = wg_handoff_error_strings,
236   .n_next_nodes = 1,
237   .next_nodes = {
238     [0] = "error-drop",
239   },
240 };
241
242 VLIB_REGISTER_NODE (wg4_output_tun_handoff) =
243 {
244   .name = "wg4-output-tun-handoff",
245   .vector_size = sizeof (u32),
246   .format_trace = format_wg_handoff_trace,
247   .type = VLIB_NODE_TYPE_INTERNAL,
248   .n_errors = ARRAY_LEN (wg_handoff_error_strings),
249   .error_strings = wg_handoff_error_strings,
250   .n_next_nodes = 1,
251   .next_nodes =  {
252     [0] = "error-drop",
253   },
254 };
255
256 VLIB_REGISTER_NODE (wg6_output_tun_handoff) =
257 {
258   .name = "wg6-output-tun-handoff",
259   .vector_size = sizeof (u32),
260   .format_trace = format_wg_handoff_trace,
261   .type = VLIB_NODE_TYPE_INTERNAL,
262   .n_errors = ARRAY_LEN (wg_handoff_error_strings),
263   .error_strings = wg_handoff_error_strings,
264   .n_next_nodes = 1,
265   .next_nodes =  {
266     [0] = "error-drop",
267   },
268 };
269
270 /*
271  * fd.io coding-style-patch-verification: ON
272  *
273  * Local Variables:
274  * eval: (c-set-style "gnu")
275  * End:
276  */