X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fwireguard%2Fwireguard_peer.c;h=32a92da102bb266b46e4f8d34c5a85b19ac12a23;hb=56b8abc07fcf9b339d54d659797715df7f0328f1;hp=922ca8cdae5f114baaa7e1d5f5c48720b860f8f2;hpb=fee9853a4f5d9a180ef6309cc37bd4060d27a51e;p=vpp.git diff --git a/src/plugins/wireguard/wireguard_peer.c b/src/plugins/wireguard/wireguard_peer.c index 922ca8cdae5..32a92da102b 100644 --- a/src/plugins/wireguard/wireguard_peer.c +++ b/src/plugins/wireguard/wireguard_peer.c @@ -16,7 +16,6 @@ #include #include -#include #include #include #include @@ -64,14 +63,13 @@ wg_peer_clear (vlib_main_t * vm, wg_peer_t * peer) wg_peer_endpoint_reset (&peer->src); wg_peer_endpoint_reset (&peer->dst); - wg_peer_adj_t *peer_adj; - vec_foreach (peer_adj, peer->adjs) + adj_index_t *adj_index; + vec_foreach (adj_index, peer->adj_indices) { - wg_peer_by_adj_index[peer_adj->adj_index] = INDEX_INVALID; - if (FIB_NODE_INDEX_INVALID != peer_adj->fib_entry_index) - fib_entry_untrack (peer_adj->fib_entry_index, peer_adj->sibling_index); - if (adj_is_valid (peer_adj->adj_index)) - adj_nbr_midchain_unstack (peer_adj->adj_index); + wg_peer_by_adj_index[*adj_index] = INDEX_INVALID; + + if (adj_is_valid (*adj_index)) + adj_midchain_delegate_unstack (*adj_index); } peer->input_thread_index = ~0; peer->output_thread_index = ~0; @@ -85,9 +83,10 @@ wg_peer_clear (vlib_main_t * vm, wg_peer_t * peer) peer->new_handshake_interval_tick = 0; peer->rehandshake_interval_tick = 0; peer->timer_need_another_keepalive = false; + peer->handshake_is_sent = false; vec_free (peer->rewrite); vec_free (peer->allowed_ips); - vec_free (peer->adjs); + vec_free (peer->adj_indices); } static void @@ -99,17 +98,17 @@ wg_peer_init (vlib_main_t * vm, wg_peer_t * peer) } static void -wg_peer_adj_stack (wg_peer_t *peer, wg_peer_adj_t *peer_adj) +wg_peer_adj_stack (wg_peer_t *peer, adj_index_t ai) { ip_adjacency_t *adj; u32 sw_if_index; wg_if_t *wgi; fib_protocol_t fib_proto; - if (!adj_is_valid (peer_adj->adj_index)) + if (!adj_is_valid (ai)) return; - adj = adj_get (peer_adj->adj_index); + adj = adj_get (ai); sw_if_index = adj->rewrite_header.sw_if_index; u8 is_ip4 = ip46_address_is_ip4 (&peer->src.addr); fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; @@ -122,7 +121,7 @@ wg_peer_adj_stack (wg_peer_t *peer, wg_peer_adj_t *peer_adj) if (!vnet_sw_interface_is_admin_up (vnet_get_main (), wgi->sw_if_index) || !wg_peer_can_send (peer)) { - adj_nbr_midchain_unstack (peer_adj->adj_index); + adj_midchain_delegate_unstack (ai); } else { @@ -136,16 +135,17 @@ wg_peer_adj_stack (wg_peer_t *peer, wg_peer_adj_t *peer_adj) u32 fib_index; fib_index = fib_table_find (fib_proto, peer->table_id); - peer_adj->fib_entry_index = - fib_entry_track (fib_index, &dst, FIB_NODE_TYPE_ADJ, - peer_adj->adj_index, &peer_adj->sibling_index); - adj_nbr_midchain_stack_on_fib_entry ( - peer_adj->adj_index, peer_adj->fib_entry_index, - fib_forw_chain_type_from_fib_proto (dst.fp_proto)); + adj_midchain_delegate_stack (ai, fib_index, &dst); } } +static void +wg_peer_adj_reset_stacking (adj_index_t ai) +{ + adj_midchain_delegate_remove (ai); +} + static void wg_peer_66_fixup (vlib_main_t *vm, const ip_adjacency_t *adj, vlib_buffer_t *b, const void *data) @@ -203,16 +203,72 @@ wg_peer_get_fixup (wg_peer_t *peer, vnet_link_t lt) return (NULL); } +static void +wg_peer_disable (vlib_main_t *vm, wg_peer_t *peer) +{ + index_t peeri = peer - wg_peer_pool; + + wg_timers_stop (peer); + wg_peer_update_flags (peeri, WG_PEER_ESTABLISHED, false); + + for (int i = 0; i < WG_N_TIMERS; i++) + { + peer->timers[i] = ~0; + peer->timers_dispatched[i] = 0; + } + peer->timer_handshake_attempts = 0; + + peer->last_sent_handshake = vlib_time_now (vm) - (REKEY_TIMEOUT + 1); + peer->last_sent_packet = 0; + peer->last_received_packet = 0; + peer->session_derived = 0; + peer->rehandshake_started = 0; + + peer->new_handshake_interval_tick = 0; + peer->rehandshake_interval_tick = 0; + + peer->timer_need_another_keepalive = false; + + noise_remote_clear (vm, &peer->remote); +} + +static void +wg_peer_enable (vlib_main_t *vm, wg_peer_t *peer) +{ + index_t peeri = peer - wg_peer_pool; + wg_if_t *wg_if; + u8 public_key[NOISE_PUBLIC_KEY_LEN]; + + wg_if = wg_if_get (wg_if_find_by_sw_if_index (peer->wg_sw_if_index)); + clib_memcpy (public_key, peer->remote.r_public, NOISE_PUBLIC_KEY_LEN); + + noise_remote_init (vm, &peer->remote, peeri, public_key, wg_if->local_idx); + + wg_timers_send_first_handshake (peer); +} + walk_rc_t wg_peer_if_admin_state_change (index_t peeri, void *data) { wg_peer_t *peer; - wg_peer_adj_t *peer_adj; + adj_index_t *adj_index; + vlib_main_t *vm = vlib_get_main (); + peer = wg_peer_get (peeri); - vec_foreach (peer_adj, peer->adjs) + vec_foreach (adj_index, peer->adj_indices) + { + wg_peer_adj_stack (peer, *adj_index); + } + + if (vnet_sw_interface_is_admin_up (vnet_get_main (), peer->wg_sw_if_index)) + { + wg_peer_enable (vm, peer); + } + else { - wg_peer_adj_stack (peer, peer_adj); + wg_peer_disable (vm, peer); } + return (WALK_CONTINUE); } @@ -224,7 +280,6 @@ wg_peer_if_adj_change (index_t peeri, void *data) ip_adjacency_t *adj; wg_peer_t *peer; fib_prefix_t *allowed_ip; - wg_peer_adj_t *peer_adj; adj = adj_get (*adj_index); @@ -234,10 +289,7 @@ wg_peer_if_adj_change (index_t peeri, void *data) if (fib_prefix_is_cover_addr_46 (allowed_ip, &adj->sub_type.nbr.next_hop)) { - vec_add2 (peer->adjs, peer_adj, 1); - peer_adj->adj_index = *adj_index; - peer_adj->fib_entry_index = FIB_NODE_INDEX_INVALID; - peer_adj->sibling_index = ~0; + vec_add1 (peer->adj_indices, *adj_index); vec_validate_init_empty (wg_peer_by_adj_index, *adj_index, INDEX_INVALID); @@ -248,7 +300,7 @@ wg_peer_if_adj_change (index_t peeri, void *data) ADJ_FLAG_MIDCHAIN_IP_STACK, vec_dup (peer->rewrite)); - wg_peer_adj_stack (peer, peer_adj); + wg_peer_adj_stack (peer, *adj_index); return (WALK_STOP); } } @@ -342,25 +394,19 @@ wg_peer_update_endpoint (index_t peeri, const ip46_address_t *addr, u16 port) peer->rewrite = wg_build_rewrite (&peer->src.addr, peer->src.port, &peer->dst.addr, peer->dst.port, is_ip4); - wg_peer_adj_t *peer_adj; - vec_foreach (peer_adj, peer->adjs) + adj_index_t *adj_index; + vec_foreach (adj_index, peer->adj_indices) { - if (FIB_NODE_INDEX_INVALID != peer_adj->fib_entry_index) - { - fib_entry_untrack (peer_adj->fib_entry_index, - peer_adj->sibling_index); - peer_adj->fib_entry_index = FIB_NODE_INDEX_INVALID; - peer_adj->sibling_index = ~0; - } - - if (adj_is_valid (peer_adj->adj_index)) + if (adj_is_valid (*adj_index)) { adj_midchain_fixup_t fixup = - wg_peer_get_fixup (peer, adj_get_link_type (peer_adj->adj_index)); - adj_nbr_midchain_update_rewrite (peer_adj->adj_index, fixup, NULL, + wg_peer_get_fixup (peer, adj_get_link_type (*adj_index)); + adj_nbr_midchain_update_rewrite (*adj_index, fixup, NULL, ADJ_FLAG_MIDCHAIN_IP_STACK, vec_dup (peer->rewrite)); - wg_peer_adj_stack (peer, peer_adj); + + wg_peer_adj_reset_stacking (*adj_index); + wg_peer_adj_stack (peer, *adj_index); } } } @@ -438,14 +484,13 @@ wg_peer_add (u32 tun_sw_if_index, const u8 public_key[NOISE_PUBLIC_KEY_LEN], return (rv); } - noise_remote_init (&peer->remote, peer - wg_peer_pool, public_key, + noise_remote_init (vm, &peer->remote, peer - wg_peer_pool, public_key, wg_if->local_idx); cookie_maker_init (&peer->cookie_maker, public_key); - wg_send_handshake (vm, peer, false); - if (peer->persistent_keepalive_interval != 0) + if (vnet_sw_interface_is_admin_up (vnet_get_main (), tun_sw_if_index)) { - wg_send_keepalive (vm, peer); + wg_timers_send_first_handshake (peer); } *peer_index = peer - wg_peer_pool; @@ -507,9 +552,9 @@ format_wg_peer (u8 * s, va_list * va) { index_t peeri = va_arg (*va, index_t); fib_prefix_t *allowed_ip; + adj_index_t *adj_index; u8 key[NOISE_KEY_LEN_BASE64]; wg_peer_t *peer; - wg_peer_adj_t *peer_adj; peer = wg_peer_get (peeri); key_to_base64 (peer->remote.r_public, NOISE_PUBLIC_KEY_LEN, key); @@ -522,9 +567,9 @@ format_wg_peer (u8 * s, va_list * va) peer->wg_sw_if_index, peer->persistent_keepalive_interval, peer->flags, pool_elts (peer->api_clients)); s = format (s, "\n adj:"); - vec_foreach (peer_adj, peer->adjs) + vec_foreach (adj_index, peer->adj_indices) { - s = format (s, " %d", peer_adj->adj_index); + s = format (s, " %d", *adj_index); } s = format (s, "\n key:%=s %U", key, format_hex_bytes, peer->remote.r_public, NOISE_PUBLIC_KEY_LEN);