diff options
Diffstat (limited to 'src/vnet')
-rw-r--r-- | src/vnet/session/transport.c | 17 | ||||
-rw-r--r-- | src/vnet/session/transport.h | 8 | ||||
-rw-r--r-- | src/vnet/tcp/tcp.c | 29 | ||||
-rw-r--r-- | src/vnet/udp/udp.c | 34 |
4 files changed, 36 insertions, 52 deletions
diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c index 8554c730bda..0020d743d9b 100644 --- a/src/vnet/session/transport.c +++ b/src/vnet/session/transport.c @@ -566,7 +566,8 @@ transport_share_local_endpoint (u8 proto, ip46_address_t * lcl_ip, u16 port) * table to mark the pair as used. */ int -transport_alloc_local_port (u8 proto, ip46_address_t * ip) +transport_alloc_local_port (u8 proto, ip46_address_t *lcl_addr, + transport_endpoint_cfg_t *rmt) { u16 min = 1024, max = 65535; /* XXX configurable ? */ transport_main_t *tm = &tp_main; @@ -594,8 +595,18 @@ transport_alloc_local_port (u8 proto, ip46_address_t * ip) break; } - if (!transport_endpoint_mark_used (proto, ip, port)) + if (!transport_endpoint_mark_used (proto, lcl_addr, port)) return port; + + /* IP:port pair already in use, check if 6-tuple available */ + if (session_lookup_connection (rmt->fib_index, lcl_addr, &rmt->ip, port, + rmt->port, proto, rmt->is_ip4)) + continue; + + /* 6-tuple is available so increment lcl endpoint refcount */ + transport_share_local_endpoint (proto, lcl_addr, port); + + return port; } return -1; } @@ -683,7 +694,7 @@ transport_alloc_local_endpoint (u8 proto, transport_endpoint_cfg_t * rmt_cfg, */ if (rmt_cfg->peer.port == 0) { - port = transport_alloc_local_port (proto, lcl_addr); + port = transport_alloc_local_port (proto, lcl_addr, rmt_cfg); if (port < 1) return SESSION_E_NOPORT; *lcl_port = port; diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h index 6e8b22a8cac..3cd64c90995 100644 --- a/src/vnet/session/transport.h +++ b/src/vnet/session/transport.h @@ -246,10 +246,10 @@ transport_register_new_protocol (const transport_proto_vft_t * vft, transport_proto_vft_t *transport_protocol_get_vft (transport_proto_t tp); void transport_update_time (clib_time_type_t time_now, u8 thread_index); -int transport_alloc_local_port (u8 proto, ip46_address_t * ip); -int transport_alloc_local_endpoint (u8 proto, transport_endpoint_cfg_t * rmt, - ip46_address_t * lcl_addr, - u16 * lcl_port); +int transport_alloc_local_port (u8 proto, ip46_address_t *ip, + transport_endpoint_cfg_t *rmt); +int transport_alloc_local_endpoint (u8 proto, transport_endpoint_cfg_t *rmt, + ip46_address_t *lcl_addr, u16 *lcl_port); void transport_share_local_endpoint (u8 proto, ip46_address_t * lcl_ip, u16 port); int transport_release_local_endpoint (u8 proto, ip46_address_t *lcl_ip, diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index c0445b9048b..6e0c1474dd5 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -764,11 +764,13 @@ tcp_connection_init_vars (tcp_connection_t * tc) } static int -tcp_alloc_custom_local_endpoint (tcp_main_t * tm, ip46_address_t * lcl_addr, - u16 * lcl_port, u8 is_ip4) +tcp_alloc_custom_local_endpoint (ip46_address_t *lcl_addr, u16 *lcl_port, + transport_endpoint_cfg_t *rmt) { + tcp_main_t *tm = vnet_get_tcp_main (); int index, port; - if (is_ip4) + + if (rmt->is_ip4) { index = tm->last_v4_addr_rotor++; if (tm->last_v4_addr_rotor >= vec_len (tcp_cfg.ip4_src_addrs)) @@ -784,7 +786,7 @@ tcp_alloc_custom_local_endpoint (tcp_main_t * tm, ip46_address_t * lcl_addr, clib_memcpy_fast (&lcl_addr->ip6, &tcp_cfg.ip6_src_addrs[index], sizeof (ip6_address_t)); } - port = transport_alloc_local_port (TRANSPORT_PROTO_TCP, lcl_addr); + port = transport_alloc_local_port (TRANSPORT_PROTO_TCP, lcl_addr, rmt); if (port < 1) return SESSION_E_NOPORT; *lcl_port = port; @@ -794,7 +796,6 @@ tcp_alloc_custom_local_endpoint (tcp_main_t * tm, ip46_address_t * lcl_addr, static int tcp_session_open (transport_endpoint_cfg_t * rmt) { - tcp_main_t *tm = vnet_get_tcp_main (); tcp_connection_t *tc; ip46_address_t lcl_addr; u16 lcl_port; @@ -805,27 +806,13 @@ tcp_session_open (transport_endpoint_cfg_t * rmt) */ if ((rmt->is_ip4 && vec_len (tcp_cfg.ip4_src_addrs)) || (!rmt->is_ip4 && vec_len (tcp_cfg.ip6_src_addrs))) - rv = tcp_alloc_custom_local_endpoint (tm, &lcl_addr, &lcl_port, - rmt->is_ip4); + rv = tcp_alloc_custom_local_endpoint (&lcl_addr, &lcl_port, rmt); else rv = transport_alloc_local_endpoint (TRANSPORT_PROTO_TCP, rmt, &lcl_addr, &lcl_port); if (rv) - { - if (rv != SESSION_E_PORTINUSE) - return rv; - - if (session_lookup_connection (rmt->fib_index, &lcl_addr, &rmt->ip, - lcl_port, rmt->port, TRANSPORT_PROTO_TCP, - rmt->is_ip4)) - return SESSION_E_PORTINUSE; - - /* 5-tuple is available so increase lcl endpoint refcount and proceed - * with connection allocation */ - transport_share_local_endpoint (TRANSPORT_PROTO_TCP, &lcl_addr, - lcl_port); - } + return rv; /* * Create connection and send SYN diff --git a/src/vnet/udp/udp.c b/src/vnet/udp/udp.c index 4553701dced..7147fa32657 100644 --- a/src/vnet/udp/udp.c +++ b/src/vnet/udp/udp.c @@ -362,44 +362,30 @@ udp_open_connection (transport_endpoint_cfg_t * rmt) rv = transport_alloc_local_endpoint (TRANSPORT_PROTO_UDP, rmt, &lcl_addr, &lcl_port); if (rv) - { - if (rv != SESSION_E_PORTINUSE) - return rv; - - if (udp_connection_port_used_extern (lcl_port, rmt->is_ip4)) - return SESSION_E_PORTINUSE; - - /* If port in use, check if 5-tuple is also in use */ - if (session_lookup_connection (rmt->fib_index, &lcl_addr, &rmt->ip, - lcl_port, rmt->port, TRANSPORT_PROTO_UDP, - rmt->is_ip4)) - return SESSION_E_PORTINUSE; - - /* 5-tuple is available so increase lcl endpoint refcount and proceed - * with connection allocation */ - transport_share_local_endpoint (TRANSPORT_PROTO_UDP, &lcl_addr, - lcl_port); - goto conn_alloc; - } + return rv; if (udp_is_valid_dst_port (lcl_port, rmt->is_ip4)) { /* If specific source port was requested abort */ if (rmt->peer.port) - return SESSION_E_PORTINUSE; + { + transport_release_local_endpoint (TRANSPORT_PROTO_UDP, &lcl_addr, + lcl_port); + return SESSION_E_PORTINUSE; + } /* Try to find a port that's not used */ while (udp_is_valid_dst_port (lcl_port, rmt->is_ip4)) { - lcl_port = transport_alloc_local_port (TRANSPORT_PROTO_UDP, - &lcl_addr); + transport_release_local_endpoint (TRANSPORT_PROTO_UDP, &lcl_addr, + lcl_port); + lcl_port = + transport_alloc_local_port (TRANSPORT_PROTO_UDP, &lcl_addr, rmt); if (lcl_port < 1) return SESSION_E_PORTINUSE; } } -conn_alloc: - /* We don't poll main thread if we have workers */ thread_index = transport_cl_thread (); |