aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/wireguard
diff options
context:
space:
mode:
authorArtem Glazychev <artem.glazychev@xored.com>2021-05-25 12:06:42 +0700
committerEd Warnicke <hagbard@gmail.com>2021-10-04 16:21:34 +0000
commit9e24f7eb911fc5ab7558109286fe8e1d2774ea93 (patch)
treef7aa375e88ee3d2325fb430bc4012b1ff012d734 /src/plugins/wireguard
parent039f289e516b073f6db67f7b35aa3aa64fdc9c82 (diff)
wireguard: use the same udp-port for multi-tunnel
now we can reuse udp-port for many wireguard interfaces Type: improvement Change-Id: I14b5a9dbe917d83300ccb4d6907743d88355e5c5 Signed-off-by: Artem Glazychev <artem.glazychev@xored.com>
Diffstat (limited to 'src/plugins/wireguard')
-rw-r--r--src/plugins/wireguard/wireguard_if.c37
-rw-r--r--src/plugins/wireguard/wireguard_if.h12
-rw-r--r--src/plugins/wireguard/wireguard_input.c34
-rw-r--r--src/plugins/wireguard/wireguard_peer.c7
-rw-r--r--src/plugins/wireguard/wireguard_peer.h1
5 files changed, 62 insertions, 29 deletions
diff --git a/src/plugins/wireguard/wireguard_if.c b/src/plugins/wireguard/wireguard_if.c
index b1c5cb20638..0866d24e775 100644
--- a/src/plugins/wireguard/wireguard_if.c
+++ b/src/plugins/wireguard/wireguard_if.c
@@ -32,7 +32,7 @@ static uword *wg_if_instances;
static index_t *wg_if_index_by_sw_if_index;
/* vector of interfaces key'd on their UDP port (in network order) */
-index_t *wg_if_index_by_port;
+index_t **wg_if_indexes_by_port;
static u8 *
format_wg_if_name (u8 * s, va_list * args)
@@ -254,13 +254,6 @@ wg_if_create (u32 user_instance,
*sw_if_indexp = (u32) ~ 0;
/*
- * Check if the required port is already in use
- */
- udp_dst_port_info_t *pi = udp_get_dst_port_info (&udp_main, port, UDP_IP4);
- if (pi)
- return VNET_API_ERROR_UDP_PORT_TAKEN;
-
- /*
* Allocate a wg_if instance. Either select on dynamically
* or try to use the desired user_instance number.
*/
@@ -295,10 +288,11 @@ wg_if_create (u32 user_instance,
if (~0 == wg_if->user_instance)
wg_if->user_instance = t_idx;
- udp_register_dst_port (vlib_get_main (), port, wg_input_node.index, 1);
+ vec_validate_init_empty (wg_if_indexes_by_port, port, NULL);
+ if (vec_len (wg_if_indexes_by_port[port]) == 0)
+ udp_register_dst_port (vlib_get_main (), port, wg_input_node.index, 1);
- vec_validate_init_empty (wg_if_index_by_port, port, INDEX_INVALID);
- wg_if_index_by_port[port] = wg_if - wg_if_pool;
+ vec_add1 (wg_if_indexes_by_port[port], t_idx);
wg_if->port = port;
wg_if->local_idx = local - noise_local_pool;
@@ -334,15 +328,30 @@ wg_if_delete (u32 sw_if_index)
return VNET_API_ERROR_INVALID_VALUE;
wg_if_t *wg_if;
- wg_if = wg_if_get (wg_if_find_by_sw_if_index (sw_if_index));
+ index_t wgii = wg_if_find_by_sw_if_index (sw_if_index);
+ wg_if = wg_if_get (wgii);
if (NULL == wg_if)
return VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
if (wg_if_instance_free (wg_if->user_instance) < 0)
return VNET_API_ERROR_INVALID_VALUE_2;
- udp_unregister_dst_port (vlib_get_main (), wg_if->port, 1);
- wg_if_index_by_port[wg_if->port] = INDEX_INVALID;
+ // Remove peers before interface deletion
+ wg_if_peer_walk (wg_if, wg_peer_if_delete, NULL);
+
+ index_t *ii;
+ index_t *ifs = wg_if_indexes_get_by_port (wg_if->port);
+ vec_foreach (ii, ifs)
+ {
+ if (*ii == wgii)
+ {
+ vec_del1 (ifs, ifs - ii);
+ break;
+ }
+ }
+ if (vec_len (ifs) == 0)
+ udp_unregister_dst_port (vlib_get_main (), wg_if->port, 1);
+
vnet_delete_hw_interface (vnm, hw->hw_if_index);
pool_put_index (noise_local_pool, wg_if->local_idx);
pool_put (wg_if_pool, wg_if);
diff --git a/src/plugins/wireguard/wireguard_if.h b/src/plugins/wireguard/wireguard_if.h
index e43557b56fe..3153a380066 100644
--- a/src/plugins/wireguard/wireguard_if.h
+++ b/src/plugins/wireguard/wireguard_if.h
@@ -71,16 +71,16 @@ wg_if_get (index_t wgii)
return (pool_elt_at_index (wg_if_pool, wgii));
}
-extern index_t *wg_if_index_by_port;
+extern index_t **wg_if_indexes_by_port;
-static_always_inline wg_if_t *
-wg_if_get_by_port (u16 port)
+static_always_inline index_t *
+wg_if_indexes_get_by_port (u16 port)
{
- if (vec_len (wg_if_index_by_port) < port)
+ if (vec_len (wg_if_indexes_by_port) == 0)
return (NULL);
- if (INDEX_INVALID == wg_if_index_by_port[port])
+ if (vec_len (wg_if_indexes_by_port[port]) == 0)
return (NULL);
- return (wg_if_get (wg_if_index_by_port[port]));
+ return (wg_if_indexes_by_port[port]);
}
diff --git a/src/plugins/wireguard/wireguard_input.c b/src/plugins/wireguard/wireguard_input.c
index 8dfba7615ef..ad002dcb3c2 100644
--- a/src/plugins/wireguard/wireguard_input.c
+++ b/src/plugins/wireguard/wireguard_input.c
@@ -116,6 +116,7 @@ wg_handshake_process (vlib_main_t * vm, wg_main_t * wmp, vlib_buffer_t * b)
enum cookie_mac_state mac_state;
bool packet_needs_cookie;
bool under_load;
+ index_t *wg_ifs;
wg_if_t *wg_if;
wg_peer_t *peer = NULL;
@@ -131,11 +132,6 @@ wg_handshake_process (vlib_main_t * vm, wg_main_t * wmp, vlib_buffer_t * b)
message_header_t *header = current_b_data;
under_load = false;
- wg_if = wg_if_get_by_port (udp_dst_port);
-
- if (NULL == wg_if)
- return WG_INPUT_ERROR_INTERFACE;
-
if (PREDICT_FALSE (header->type == MESSAGE_HANDSHAKE_COOKIE))
{
message_handshake_cookie_t *packet =
@@ -159,10 +155,30 @@ wg_handshake_process (vlib_main_t * vm, wg_main_t * wmp, vlib_buffer_t * b)
message_macs_t *macs = (message_macs_t *)
((u8 *) current_b_data + len - sizeof (*macs));
- mac_state =
- cookie_checker_validate_macs (vm, &wg_if->cookie_checker, macs,
- current_b_data, len, under_load, ip4_src,
- udp_src_port);
+ index_t *ii;
+ wg_ifs = wg_if_indexes_get_by_port (udp_dst_port);
+ if (NULL == wg_ifs)
+ return WG_INPUT_ERROR_INTERFACE;
+
+ vec_foreach (ii, wg_ifs)
+ {
+ wg_if = wg_if_get (*ii);
+ if (NULL == wg_if)
+ continue;
+
+ mac_state = cookie_checker_validate_macs (
+ vm, &wg_if->cookie_checker, macs, current_b_data, len, under_load,
+ ip4_src, udp_src_port);
+ if (mac_state == INVALID_MAC)
+ {
+ wg_if = NULL;
+ continue;
+ }
+ break;
+ }
+
+ if (NULL == wg_if)
+ return WG_INPUT_ERROR_HANDSHAKE_MAC;
if ((under_load && mac_state == VALID_MAC_WITH_COOKIE)
|| (!under_load && mac_state == VALID_MAC_BUT_NO_COOKIE))
diff --git a/src/plugins/wireguard/wireguard_peer.c b/src/plugins/wireguard/wireguard_peer.c
index 5e2011b401e..d4a85a20cf6 100644
--- a/src/plugins/wireguard/wireguard_peer.c
+++ b/src/plugins/wireguard/wireguard_peer.c
@@ -207,6 +207,13 @@ wg_peer_adj_walk (adj_index_t ai, void *data)
ADJ_WALK_RC_STOP;
}
+walk_rc_t
+wg_peer_if_delete (index_t peeri, void *data)
+{
+ wg_peer_remove (peeri);
+ return (WALK_CONTINUE);
+}
+
static int
wg_peer_fill (vlib_main_t *vm, wg_peer_t *peer, u32 table_id,
const ip46_address_t *dst, u16 port,
diff --git a/src/plugins/wireguard/wireguard_peer.h b/src/plugins/wireguard/wireguard_peer.h
index cf859f32b1f..e23feb7866f 100644
--- a/src/plugins/wireguard/wireguard_peer.h
+++ b/src/plugins/wireguard/wireguard_peer.h
@@ -106,6 +106,7 @@ index_t wg_peer_walk (wg_peer_walk_cb_t fn, void *data);
u8 *format_wg_peer (u8 * s, va_list * va);
walk_rc_t wg_peer_if_admin_state_change (index_t peeri, void *data);
+walk_rc_t wg_peer_if_delete (index_t peeri, void *data);
walk_rc_t wg_peer_if_adj_change (index_t peeri, void *data);
adj_walk_rc_t wg_peer_adj_walk (adj_index_t ai, void *data);