aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/wireguard/wireguard_output_tun.c
diff options
context:
space:
mode:
authorArtem Glazychev <artem.glazychev@xored.com>2020-09-14 11:36:01 +0700
committerNeale Ranns <nranns@cisco.com>2020-09-23 10:11:13 +0000
commit8eb69407c8075e101b773d5a27ea21bd3fc906d7 (patch)
treefe6dffcf1865882a1c32a86d083a68e6c4f7e0af /src/plugins/wireguard/wireguard_output_tun.c
parent6a3d4cc9a11efbe73a1cda35a64c619eebde0b24 (diff)
wireguard: add handoff node
All timer and control plane functions happen from main thread Type: fix Change-Id: I4fc333c644485cd17e6f426493feef91688d9b24 Signed-off-by: Artem Glazychev <artem.glazychev@xored.com>
Diffstat (limited to 'src/plugins/wireguard/wireguard_output_tun.c')
-rwxr-xr-xsrc/plugins/wireguard/wireguard_output_tun.c94
1 files changed, 38 insertions, 56 deletions
diff --git a/src/plugins/wireguard/wireguard_output_tun.c b/src/plugins/wireguard/wireguard_output_tun.c
index cdfd9d730f6..9a8710b77db 100755
--- a/src/plugins/wireguard/wireguard_output_tun.c
+++ b/src/plugins/wireguard/wireguard_output_tun.c
@@ -15,10 +15,6 @@
#include <vlib/vlib.h>
#include <vnet/vnet.h>
-#include <vnet/pg/pg.h>
-#include <vnet/fib/ip6_fib.h>
-#include <vnet/fib/ip4_fib.h>
-#include <vnet/fib/fib_entry.h>
#include <vppinfra/error.h>
#include <wireguard/wireguard.h>
@@ -28,19 +24,8 @@
_(NONE, "No error") \
_(PEER, "Peer error") \
_(KEYPAIR, "Keypair error") \
- _(HANDSHAKE_SEND, "Handshake sending failed") \
_(TOO_BIG, "packet too big") \
-#define WG_OUTPUT_SCRATCH_SIZE 2048
-
-typedef struct wg_output_scratch_t_
-{
- u8 scratch[WG_OUTPUT_SCRATCH_SIZE];
-} wg_output_scratch_t;
-
-/* Cache line aligned per-thread scratch space */
-static wg_output_scratch_t *wg_output_scratchs;
-
typedef enum
{
#define _(sym,str) WG_OUTPUT_ERROR_##sym,
@@ -58,6 +43,7 @@ static char *wg_output_error_strings[] = {
typedef enum
{
WG_OUTPUT_NEXT_ERROR,
+ WG_OUTPUT_NEXT_HANDOFF,
WG_OUTPUT_NEXT_INTERFACE_OUTPUT,
WG_OUTPUT_N_NEXT,
} wg_output_next_t;
@@ -65,6 +51,7 @@ typedef enum
typedef struct
{
ip4_udp_header_t hdr;
+ index_t peer;
} wg_output_tun_trace_t;
u8 *
@@ -87,7 +74,8 @@ format_wg_output_tun_trace (u8 * s, va_list * args)
wg_output_tun_trace_t *t = va_arg (*args, wg_output_tun_trace_t *);
- s = format (s, "Encrypted packet: %U\n", format_ip4_udp_header, &t->hdr);
+ s = format (s, "peer: %d\n", t->peer);
+ s = format (s, " Encrypted packet: %U", format_ip4_udp_header, &t->hdr);
return s;
}
@@ -109,7 +97,6 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
vlib_get_buffers (vm, from, bufs, n_left_from);
wg_main_t *wmp = &wg_main;
- u32 handsh_fails = 0;
wg_peer_t *peer = NULL;
while (n_left_from > 0)
@@ -119,11 +106,12 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
sizeof (ip4_udp_header_t));
u16 plain_data_len =
clib_net_to_host_u16 (((ip4_header_t *) plain_data)->length);
+ index_t peeri;
next[0] = WG_OUTPUT_NEXT_ERROR;
-
- peer =
+ peeri =
wg_peer_get_by_adj_index (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]);
+ peer = wg_peer_get (peeri);
if (!peer || peer->is_dead)
{
@@ -131,21 +119,34 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
goto out;
}
+ if (PREDICT_FALSE (~0 == peer->output_thread_index))
+ {
+ /* this is the first packet to use this peer, claim the peer
+ * for this thread.
+ */
+ clib_atomic_cmp_and_swap (&peer->output_thread_index, ~0,
+ wg_peer_assign_thread (thread_index));
+ }
+
+ if (PREDICT_TRUE (thread_index != peer->output_thread_index))
+ {
+ next[0] = WG_OUTPUT_NEXT_HANDOFF;
+ goto next;
+ }
+
if (PREDICT_FALSE (!peer->remote.r_current))
{
- if (PREDICT_FALSE (!wg_send_handshake (vm, peer, false)))
- handsh_fails++;
+ wg_send_handshake_from_mt (peeri, false);
b[0]->error = node->errors[WG_OUTPUT_ERROR_KEYPAIR];
goto out;
}
-
size_t encrypted_packet_len = message_data_len (plain_data_len);
/*
* Ensure there is enough space to write the encrypted data
* into the packet
*/
- if (PREDICT_FALSE (encrypted_packet_len >= WG_OUTPUT_SCRATCH_SIZE) ||
+ if (PREDICT_FALSE (encrypted_packet_len >= WG_DEFAULT_DATA_SIZE) ||
PREDICT_FALSE ((b[0]->current_data + encrypted_packet_len) >=
vlib_buffer_get_default_data_size (vm)))
{
@@ -154,35 +155,29 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
}
message_data_t *encrypted_packet =
- (message_data_t *) wg_output_scratchs[thread_index].scratch;
+ (message_data_t *) wmp->per_thread_data[thread_index].data;
enum noise_state_crypt state;
state =
- noise_remote_encrypt (wmp->vlib_main,
+ noise_remote_encrypt (vm,
&peer->remote,
&encrypted_packet->receiver_index,
&encrypted_packet->counter, plain_data,
plain_data_len,
encrypted_packet->encrypted_data);
- switch (state)
+
+ if (PREDICT_FALSE (state == SC_KEEP_KEY_FRESH))
+ {
+ wg_send_handshake_from_mt (peeri, false);
+ }
+ else if (PREDICT_FALSE (state == SC_FAILED))
{
- case SC_OK:
- break;
- case SC_KEEP_KEY_FRESH:
- if (PREDICT_FALSE (!wg_send_handshake (vm, peer, false)))
- handsh_fails++;
- break;
- case SC_FAILED:
//TODO: Maybe wrong
- if (PREDICT_FALSE (!wg_send_handshake (vm, peer, false)))
- handsh_fails++;
- clib_mem_free (encrypted_packet);
+ wg_send_handshake_from_mt (peeri, false);
goto out;
- default:
- break;
}
- // Here we are sure that can send packet to next node.
+ /* Here we are sure that can send packet to next node */
next[0] = WG_OUTPUT_NEXT_INTERFACE_OUTPUT;
encrypted_packet->header.type = MESSAGE_DATA;
@@ -195,9 +190,9 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
ip4_header_set_len_w_chksum
(&hdr->ip4, clib_host_to_net_u16 (b[0]->current_length));
- wg_timers_any_authenticated_packet_traversal (peer);
wg_timers_any_authenticated_packet_sent (peer);
wg_timers_data_sent (peer);
+ wg_timers_any_authenticated_packet_traversal (peer);
out:
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
@@ -206,17 +201,15 @@ VLIB_NODE_FN (wg_output_tun_node) (vlib_main_t * vm,
wg_output_tun_trace_t *t =
vlib_add_trace (vm, node, b[0], sizeof (*t));
t->hdr = *hdr;
+ t->peer = peeri;
}
+ next:
n_left_from -= 1;
next += 1;
b += 1;
}
vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
-
- vlib_node_increment_counter (vm, node->node_index,
- WG_OUTPUT_ERROR_HANDSHAKE_SEND, handsh_fails);
-
return frame->n_vectors;
}
@@ -231,24 +224,13 @@ VLIB_REGISTER_NODE (wg_output_tun_node) =
.error_strings = wg_output_error_strings,
.n_next_nodes = WG_OUTPUT_N_NEXT,
.next_nodes = {
+ [WG_OUTPUT_NEXT_HANDOFF] = "wg-output-tun-handoff",
[WG_OUTPUT_NEXT_INTERFACE_OUTPUT] = "adj-midchain-tx",
[WG_OUTPUT_NEXT_ERROR] = "error-drop",
},
};
/* *INDENT-ON* */
-static clib_error_t *
-wireguard_output_module_init (vlib_main_t * vm)
-{
- vlib_thread_main_t *tm = vlib_get_thread_main ();
-
- vec_validate_aligned (wg_output_scratchs, tm->n_vlib_mains,
- CLIB_CACHE_LINE_BYTES);
- return (NULL);
-}
-
-VLIB_INIT_FUNCTION (wireguard_output_module_init);
-
/*
* fd.io coding-style-patch-verification: ON
*