wireguard: fix license headers
[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, 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 (wg_handshake_handoff) (vlib_main_t * vm,
133                                      vlib_node_runtime_t * node,
134                                      vlib_frame_t * from_frame)
135 {
136   wg_main_t *wmp = &wg_main;
137
138   return wg_handoff (vm, node, from_frame, wmp->in_fq_index,
139                      WG_HANDOFF_HANDSHAKE);
140 }
141
142 VLIB_NODE_FN (wg_input_data_handoff) (vlib_main_t * vm,
143                                       vlib_node_runtime_t * node,
144                                       vlib_frame_t * from_frame)
145 {
146   wg_main_t *wmp = &wg_main;
147
148   return wg_handoff (vm, node, from_frame, wmp->in_fq_index,
149                      WG_HANDOFF_INP_DATA);
150 }
151
152 VLIB_NODE_FN (wg_output_tun_handoff) (vlib_main_t * vm,
153                                       vlib_node_runtime_t * node,
154                                       vlib_frame_t * from_frame)
155 {
156   wg_main_t *wmp = &wg_main;
157
158   return wg_handoff (vm, node, from_frame, wmp->out_fq_index,
159                      WG_HANDOFF_OUT_TUN);
160 }
161
162 /* *INDENT-OFF* */
163 VLIB_REGISTER_NODE (wg_handshake_handoff) =
164 {
165   .name = "wg-handshake-handoff",
166   .vector_size = sizeof (u32),
167   .format_trace = format_wg_handoff_trace,
168   .type = VLIB_NODE_TYPE_INTERNAL,
169   .n_errors = ARRAY_LEN (wg_handoff_error_strings),
170   .error_strings = wg_handoff_error_strings,
171   .n_next_nodes = 1,
172   .next_nodes = {
173     [0] = "error-drop",
174   },
175 };
176
177 VLIB_REGISTER_NODE (wg_input_data_handoff) =
178 {
179   .name = "wg-input-data-handoff",
180   .vector_size = sizeof (u32),
181   .format_trace = format_wg_handoff_trace,
182   .type = VLIB_NODE_TYPE_INTERNAL,
183   .n_errors = ARRAY_LEN (wg_handoff_error_strings),
184   .error_strings = wg_handoff_error_strings,
185   .n_next_nodes = 1,
186   .next_nodes = {
187     [0] = "error-drop",
188   },
189 };
190
191 VLIB_REGISTER_NODE (wg_output_tun_handoff) =
192 {
193   .name = "wg-output-tun-handoff",
194   .vector_size = sizeof (u32),
195   .format_trace = format_wg_handoff_trace,
196   .type = VLIB_NODE_TYPE_INTERNAL,
197   .n_errors = ARRAY_LEN (wg_handoff_error_strings),
198   .error_strings = wg_handoff_error_strings,
199   .n_next_nodes = 1,
200   .next_nodes =  {
201     [0] = "error-drop",
202   },
203 };
204 /* *INDENT-ON* */
205
206 /*
207  * fd.io coding-style-patch-verification: ON
208  *
209  * Local Variables:
210  * eval: (c-set-style "gnu")
211  * End:
212  */