diff options
-rw-r--r-- | src/vnet/tcp/tcp.c | 47 | ||||
-rw-r--r-- | src/vnet/tcp/tcp_output.c | 33 |
2 files changed, 56 insertions, 24 deletions
diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index 6de48b2bd3a..b3564004dd4 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -28,6 +28,47 @@ tcp_main_t tcp_main; +typedef struct +{ + fib_protocol_t nh_proto; + vnet_link_t link_type; + ip46_address_t ip; + u32 sw_if_index; + u8 is_add; +} tcp_add_del_adj_args_t; + +static void +tcp_add_del_adj_cb (tcp_add_del_adj_args_t * args) +{ + u32 ai; + if (args->is_add) + { + adj_nbr_add_or_lock (args->nh_proto, args->link_type, &args->ip, + args->sw_if_index); + } + else + { + ai = adj_nbr_find (FIB_PROTOCOL_IP6, VNET_LINK_IP6, &args->ip, + args->sw_if_index); + if (ai != ADJ_INDEX_INVALID) + adj_unlock (ai); + } +} + +static void +tcp_add_del_adjacency (tcp_connection_t * tc, u8 is_add) +{ + tcp_add_del_adj_args_t args = { + .nh_proto = FIB_PROTOCOL_IP6, + .link_type = VNET_LINK_IP6, + .ip = tc->c_rmt_ip, + .sw_if_index = tc->sw_if_index, + .is_add = is_add + }; + vlib_rpc_call_main_thread (tcp_add_del_adj_cb, (u8 *) & args, + sizeof (args)); +} + static u32 tcp_connection_bind (u32 session_index, transport_endpoint_t * lcl) { @@ -178,6 +219,9 @@ tcp_connection_cleanup (tcp_connection_t * tc) /* Make sure all timers are cleared */ tcp_connection_timers_reset (tc); + if (!tc->c_is_ip4 && ip6_address_is_link_local_unicast (&tc->c_rmt_ip6)) + tcp_add_del_adjacency (tc, 0); + /* Poison the entry */ if (CLIB_DEBUG > 0) memset (tc, 0xFA, sizeof (*tc)); @@ -494,6 +538,9 @@ tcp_connection_init_vars (tcp_connection_t * tc) if (tc->state == TCP_STATE_SYN_RCVD) tcp_init_snd_vars (tc); + if (!tc->c_is_ip4 && ip6_address_is_link_local_unicast (&tc->c_rmt_ip6)) + tcp_add_del_adjacency (tc, 1); + // tcp_connection_fib_attach (tc); } diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index 0d938cae372..5932ed406d9 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -1755,21 +1755,6 @@ tcp_session_has_ooo_data (tcp_connection_t * tc) return svm_fifo_has_ooo_data (s->server_rx_fifo); } -typedef struct -{ - fib_protocol_t nh_proto; - vnet_link_t link_type; - ip46_address_t ip; - u32 sw_if_index; -} tcp_adj_add_args_t; - -void -tcp_output_add_adj (tcp_adj_add_args_t * args) -{ - adj_nbr_add_or_lock (args->nh_proto, args->link_type, &args->ip, - args->sw_if_index); -} - static void tcp_output_handle_link_local (tcp_connection_t * tc0, vlib_buffer_t * b0, u32 * next0, u32 * error0) @@ -1777,18 +1762,12 @@ tcp_output_handle_link_local (tcp_connection_t * tc0, vlib_buffer_t * b0, ip_adjacency_t *adj; adj_index_t ai; + /* Not thread safe but as long as the connection exists the adj should + * not be removed */ ai = adj_nbr_find (FIB_PROTOCOL_IP6, VNET_LINK_IP6, &tc0->c_rmt_ip, tc0->sw_if_index); if (ai == ADJ_INDEX_INVALID) { - tcp_adj_add_args_t args = { - .nh_proto = FIB_PROTOCOL_IP6, - .link_type = VNET_LINK_IP6, - .ip = tc0->c_rmt_ip, - .sw_if_index = tc0->sw_if_index - }; - vlib_rpc_call_main_thread (tcp_output_add_adj, (u8 *) & args, - sizeof (args)); vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; *next0 = TCP_OUTPUT_NEXT_DROP; *error0 = TCP_ERROR_LINK_LOCAL_RW; @@ -1796,10 +1775,16 @@ tcp_output_handle_link_local (tcp_connection_t * tc0, vlib_buffer_t * b0, } adj = adj_get (ai); - if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE) + if (PREDICT_TRUE (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE)) *next0 = TCP_OUTPUT_NEXT_IP_REWRITE; else if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) *next0 = TCP_OUTPUT_NEXT_IP_ARP; + else + { + *next0 = TCP_OUTPUT_NEXT_DROP; + *error0 = TCP_ERROR_LINK_LOCAL_RW; + } + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ai; } always_inline uword |