session: extend connect api for internal apps

Change-Id: Ie4c5cfc4c97acb321a46b4df589dc44de1b616ba
Signed-off-by: Florin Coras <fcoras@cisco.com>
This commit is contained in:
Florin Coras
2018-10-25 18:03:45 -07:00
committed by Damjan Marion
parent 75b39f8711
commit 5665cedf57
18 changed files with 438 additions and 155 deletions

View File

@ -275,8 +275,7 @@ unformat_ip6_address (unformat_input_t * input, va_list * args)
uword
unformat_uri (unformat_input_t * input, va_list * args)
{
session_endpoint_extended_t *sep = va_arg (*args,
session_endpoint_extended_t *);
session_endpoint_cfg_t *sep = va_arg (*args, session_endpoint_cfg_t *);
u32 port;
char *tmp;
@ -606,7 +605,7 @@ session_connected_handler (session_connected_msg_t * mp)
{
udp_echo_main_t *utm = &udp_echo_main;
unformat_input_t _input, *input = &_input;
session_endpoint_extended_t _sep, *sep = &_sep;
session_endpoint_cfg_t _sep, *sep = &_sep;
app_session_t *session;
ASSERT (utm->i_am_server == 0);

View File

@ -451,7 +451,7 @@ sctp_half_open_connection_new (u8 thread_index)
}
static inline int
sctp_connection_open (transport_endpoint_t * rmt)
sctp_connection_open (transport_endpoint_cfg_t * rmt)
{
sctp_main_t *tm = vnet_get_sctp_main ();
sctp_connection_t *sctp_conn;
@ -485,9 +485,9 @@ sctp_connection_open (transport_endpoint_t * rmt)
clib_spinlock_lock_if_init (&tm->half_open_lock);
sctp_conn = sctp_half_open_connection_new (thread_id);
u32 mtu = rmt->is_ip4 ? vnet_sw_interface_get_mtu (vnet_get_main (),
rmt->sw_if_index,
rmt->peer.sw_if_index,
VNET_MTU_IP4) :
vnet_sw_interface_get_mtu (vnet_get_main (), rmt->sw_if_index,
vnet_sw_interface_get_mtu (vnet_get_main (), rmt->peer.sw_if_index,
VNET_MTU_IP6);
sctp_conn->sub_conn[idx].PMTU = mtu;
@ -542,7 +542,7 @@ sctp_connection_cleanup (sctp_connection_t * sctp_conn)
}
int
sctp_session_open (transport_endpoint_t * tep)
sctp_session_open (transport_endpoint_cfg_t * tep)
{
return sctp_connection_open (tep);
}

View File

@ -715,7 +715,7 @@ app_worker_stop_listen (app_worker_t * app_wrk, session_handle_t handle)
*/
int
application_start_listen (application_t * app,
session_endpoint_extended_t * sep_ext,
session_endpoint_cfg_t * sep_ext,
session_handle_t * res)
{
app_listener_t *app_listener;
@ -1055,7 +1055,7 @@ application_start_stop_proxy_fib_proto (application_t * app, u8 fib_proto,
{
app_namespace_t *app_ns = app_namespace_get (app->ns_index);
u8 is_ip4 = (fib_proto == FIB_PROTOCOL_IP4);
session_endpoint_extended_t sep = SESSION_ENDPOINT_EXT_NULL;
session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
transport_connection_t *tc;
app_worker_t *app_wrk;
stream_session_t *s;
@ -1408,7 +1408,7 @@ application_local_listen_session_free (application_t * app,
int
application_start_local_listen (application_t * app,
session_endpoint_extended_t * sep_ext,
session_endpoint_cfg_t * sep_ext,
session_handle_t * handle)
{
app_listener_t *app_listener;

View File

@ -243,7 +243,7 @@ int app_worker_lock_and_send_event (app_worker_t * app, stream_session_t * s,
clib_error_t *vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a);
int application_start_listen (application_t * app,
session_endpoint_extended_t * tep,
session_endpoint_cfg_t * tep,
session_handle_t * handle);
int application_stop_listen (u32 app_index, u32 app_or_wrk,
session_handle_t handle);
@ -295,7 +295,7 @@ local_session_t *application_get_local_session_from_handle (session_handle_t
local_session_t
* application_get_local_listen_session_from_handle (session_handle_t lh);
int application_start_local_listen (application_t * server,
session_endpoint_extended_t * sep,
session_endpoint_cfg_t * sep,
session_handle_t * handle);
int application_stop_local_listen (u32 app_index, u32 app_or_wrk,
session_handle_t lh);

View File

@ -137,11 +137,11 @@ api_parse_session_handle (u64 handle, u32 * session_index, u32 * thread_index)
}
static void
session_endpoint_update_for_app (session_endpoint_extended_t * sep,
application_t * app)
session_endpoint_update_for_app (session_endpoint_cfg_t * sep,
application_t * app, u8 is_connect)
{
app_namespace_t *app_ns;
u32 ns_index;
u32 ns_index, fib_index;
ns_index = app->ns_index;
@ -156,15 +156,29 @@ session_endpoint_update_for_app (session_endpoint_extended_t * sep,
ns_index = owner_app->ns_index;
}
app_ns = app_namespace_get (ns_index);
if (app_ns)
{
if (!app_ns)
return;
/* Ask transport and network to bind to/connect using local interface
* that "supports" app's namespace. This will fix our local connection
* endpoint.
*/
fib_index = sep->is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
sep->peer.fib_index = fib_index;
sep->fib_index = fib_index;
if (!is_connect)
{
sep->sw_if_index = app_ns->sw_if_index;
sep->fib_index =
sep->is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
}
else
{
if (app_ns->sw_if_index != APP_NAMESPACE_INVALID_INDEX
&& sep->peer.sw_if_index != ENDPOINT_INVALID_INDEX
&& sep->peer.sw_if_index != app_ns->sw_if_index)
clib_warning ("Local sw_if_index different from app ns sw_if_index");
sep->peer.sw_if_index = app_ns->sw_if_index;
}
}
@ -185,7 +199,7 @@ vnet_bind_inline (vnet_bind_args_t * a)
app_wrk = application_get_worker (app, a->wrk_map_index);
a->sep_ext.app_wrk_index = app_wrk->wrk_index;
session_endpoint_update_for_app (&a->sep_ext, app);
session_endpoint_update_for_app (&a->sep_ext, app, 0 /* is_connect */ );
if (!session_endpoint_in_ns (&a->sep))
return VNET_API_ERROR_INVALID_VALUE_2;
@ -278,7 +292,7 @@ application_connect (vnet_connect_args_t * a)
return VNET_API_ERROR_INVALID_VALUE;
client = application_get (a->app_index);
session_endpoint_update_for_app (&a->sep_ext, client);
session_endpoint_update_for_app (&a->sep_ext, client, 1 /* is_connect */ );
client_wrk = application_get_worker (client, a->wrk_map_index);
/*
@ -368,8 +382,7 @@ global_scope:
uword
unformat_vnet_uri (unformat_input_t * input, va_list * args)
{
session_endpoint_extended_t *sep = va_arg (*args,
session_endpoint_extended_t *);
session_endpoint_cfg_t *sep = va_arg (*args, session_endpoint_cfg_t *);
u32 transport_proto = 0, port;
if (unformat (input, "%U://%U/%d", unformat_transport_proto,
@ -411,10 +424,10 @@ unformat_vnet_uri (unformat_input_t * input, va_list * args)
}
static u8 *cache_uri;
static session_endpoint_extended_t *cache_sep;
static session_endpoint_cfg_t *cache_sep;
int
parse_uri (char *uri, session_endpoint_extended_t * sep)
parse_uri (char *uri, session_endpoint_cfg_t * sep)
{
unformat_input_t _input, *input = &_input;
@ -548,7 +561,7 @@ vnet_application_detach (vnet_app_detach_args_t * a)
int
vnet_bind_uri (vnet_bind_args_t * a)
{
session_endpoint_extended_t sep = SESSION_ENDPOINT_EXT_NULL;
session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
int rv;
rv = parse_uri (a->uri, &sep);
@ -562,7 +575,7 @@ vnet_bind_uri (vnet_bind_args_t * a)
int
vnet_unbind_uri (vnet_unbind_args_t * a)
{
session_endpoint_extended_t sep = SESSION_ENDPOINT_EXT_NULL;
session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
stream_session_t *listener;
u32 table_index;
int rv;
@ -585,7 +598,7 @@ vnet_unbind_uri (vnet_unbind_args_t * a)
clib_error_t *
vnet_connect_uri (vnet_connect_args_t * a)
{
session_endpoint_extended_t sep = SESSION_ENDPOINT_EXT_NULL;
session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
int rv;
/* Parse uri */

View File

@ -39,7 +39,7 @@ typedef struct _vnet_bind_args_t
{
union
{
session_endpoint_extended_t sep_ext;
session_endpoint_cfg_t sep_ext;
session_endpoint_t sep;
char *uri;
};
@ -71,7 +71,7 @@ typedef struct _vnet_connect_args
{
union
{
session_endpoint_extended_t sep_ext;
session_endpoint_cfg_t sep_ext;
session_endpoint_t sep;
char *uri;
};

View File

@ -886,14 +886,14 @@ int
session_open_cl (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
{
transport_connection_t *tc;
transport_endpoint_t *tep;
transport_endpoint_cfg_t *tep;
segment_manager_t *sm;
app_worker_t *app_wrk;
stream_session_t *s;
application_t *app;
int rv;
tep = session_endpoint_to_transport (rmt);
tep = session_endpoint_to_transport_cfg (rmt);
rv = tp_vfts[rmt->transport_proto].open (tep);
if (rv < 0)
{
@ -924,11 +924,11 @@ int
session_open_vc (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
{
transport_connection_t *tc;
transport_endpoint_t *tep;
transport_endpoint_cfg_t *tep;
u64 handle;
int rv;
tep = session_endpoint_to_transport (rmt);
tep = session_endpoint_to_transport_cfg (rmt);
rv = tp_vfts[rmt->transport_proto].open (tep);
if (rv < 0)
{
@ -958,11 +958,13 @@ session_open_vc (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
int
session_open_app (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
{
session_endpoint_extended_t *sep = (session_endpoint_extended_t *) rmt;
session_endpoint_cfg_t *sep = (session_endpoint_cfg_t *) rmt;
transport_endpoint_cfg_t *tep_cfg = session_endpoint_to_transport_cfg (sep);
sep->app_wrk_index = app_wrk_index;
sep->opaque = opaque;
return tp_vfts[rmt->transport_proto].open ((transport_endpoint_t *) sep);
return tp_vfts[rmt->transport_proto].open (tep_cfg);
}
typedef int (*session_open_service_fn) (u32, session_endpoint_t *, u32);
@ -1004,7 +1006,7 @@ session_open (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
* @param sep Local endpoint to be listened on.
*/
int
session_listen (stream_session_t * ls, session_endpoint_extended_t * sep)
session_listen (stream_session_t * ls, session_endpoint_cfg_t * sep)
{
transport_connection_t *tc;
transport_endpoint_t *tep;

View File

@ -570,7 +570,7 @@ void stream_session_reset_notify (transport_connection_t * tc);
int stream_session_accept (transport_connection_t * tc, u32 listener_index,
u8 notify);
int session_open (u32 app_index, session_endpoint_t * tep, u32 opaque);
int session_listen (stream_session_t * s, session_endpoint_extended_t * sep);
int session_listen (stream_session_t * s, session_endpoint_cfg_t * sep);
int session_stop_listen (stream_session_t * s);
void stream_session_disconnect (stream_session_t * s);
void stream_session_disconnect_transport (stream_session_t * s);

View File

@ -1290,8 +1290,8 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp)
a->sep.ip = *ip46;
a->sep.port = mp->port;
a->sep.transport_proto = mp->proto;
a->sep.fib_index = mp->vrf;
a->sep.sw_if_index = ENDPOINT_INVALID_INDEX;
a->sep.peer.fib_index = mp->vrf;
a->sep.peer.sw_if_index = ENDPOINT_INVALID_INDEX;
if (mp->hostname_len)
{
vec_validate (a->sep_ext.hostname, mp->hostname_len - 1);

View File

@ -45,12 +45,18 @@ dummy_session_reset_callback (stream_session_t * s)
clib_warning ("called...");
}
volatile u32 connected_session_index = ~0;
volatile u32 connected_session_thread = ~0;
int
dummy_session_connected_callback (u32 app_index, u32 api_context,
stream_session_t * s, u8 is_fail)
{
clib_warning ("called...");
return -1;
if (s)
{
connected_session_index = s->session_index;
connected_session_thread = s->thread_index;
}
return 0;
}
static u32 dummy_segment_count;
@ -76,11 +82,15 @@ dummy_session_disconnect_callback (stream_session_t * s)
}
static u32 dummy_accept;
volatile u32 accepted_session_index;
volatile u32 accepted_session_thread;
int
dummy_session_accept_callback (stream_session_t * s)
{
dummy_accept = 1;
accepted_session_index = s->session_index;
accepted_session_thread = s->thread_index;
s->session_state = SESSION_STATE_READY;
return 0;
}
@ -119,7 +129,10 @@ session_create_lookpback (u32 table_id, u32 * sw_if_index,
}
if (table_id != 0)
{
ip_table_create (FIB_PROTOCOL_IP4, table_id, 0, 0);
ip_table_bind (FIB_PROTOCOL_IP4, *sw_if_index, table_id, 0);
}
vnet_sw_interface_set_flags (vnet_get_main (), *sw_if_index,
VNET_SW_INTERFACE_FLAG_ADMIN_UP);
@ -207,6 +220,189 @@ session_test_basic (vlib_main_t * vm, unformat_input_t * input)
return 0;
}
static void
session_add_del_route_via_lookup_in_table (u32 in_table_id, u32 via_table_id,
ip4_address_t * ip, u8 mask,
u8 is_add)
{
fib_route_path_t *rpaths = 0, *rpath;
u32 in_fib_index, via_fib_index;
fib_prefix_t prefix = {
.fp_addr.ip4.as_u32 = ip->as_u32,
.fp_len = mask,
.fp_proto = FIB_PROTOCOL_IP4,
};
via_fib_index = fib_table_find (FIB_PROTOCOL_IP4, via_table_id);
if (via_fib_index == ~0)
{
clib_warning ("couldn't resolve via table id to index");
return;
}
in_fib_index = fib_table_find (FIB_PROTOCOL_IP4, in_table_id);
if (in_fib_index == ~0)
{
clib_warning ("couldn't resolve in table id to index");
return;
}
vec_add2 (rpaths, rpath, 1);
clib_memset (rpath, 0, sizeof (*rpath));
rpath->frp_weight = 1;
rpath->frp_fib_index = via_fib_index;
rpath->frp_proto = DPO_PROTO_IP4;
rpath->frp_sw_if_index = ~0;
rpath->frp_flags |= FIB_ROUTE_PATH_DEAG;
if (is_add)
fib_table_entry_path_add2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
FIB_ENTRY_FLAG_NONE, rpath);
else
fib_table_entry_path_remove2 (in_fib_index, &prefix, FIB_SOURCE_CLI,
rpath);
vec_free (rpaths);
}
static int
session_test_endpoint_cfg (vlib_main_t * vm, unformat_input_t * input)
{
session_endpoint_cfg_t client_sep = SESSION_ENDPOINT_CFG_NULL;
u64 options[APP_OPTIONS_N_OPTIONS], dummy_secret = 1234;
u16 dummy_server_port = 1234, dummy_client_port = 5678;
session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
u32 server_index, client_index, sw_if_index[2];
ip4_address_t intf_addr[3];
transport_connection_t *tc;
stream_session_t *s;
clib_error_t *error;
u8 *appns_id;
/*
* Create the loopbacks
*/
intf_addr[0].as_u32 = clib_host_to_net_u32 (0x01010101),
session_create_lookpback (0, &sw_if_index[0], &intf_addr[0]);
intf_addr[1].as_u32 = clib_host_to_net_u32 (0x02020202),
session_create_lookpback (1, &sw_if_index[1], &intf_addr[1]);
session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
1 /* is_add */ );
session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
1 /* is_add */ );
/*
* Insert namespace
*/
appns_id = format (0, "appns1");
vnet_app_namespace_add_del_args_t ns_args = {
.ns_id = appns_id,
.secret = dummy_secret,
.sw_if_index = sw_if_index[1],
.ip4_fib_id = 0,
.is_add = 1
};
error = vnet_app_namespace_add_del (&ns_args);
SESSION_TEST ((error == 0), "app ns insertion should succeed: %d",
clib_error_get_code (error));
/*
* Attach client/server
*/
clib_memset (options, 0, sizeof (options));
options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
vnet_app_attach_args_t attach_args = {
.api_client_index = ~0,
.options = options,
.namespace_id = 0,
.session_cb_vft = &dummy_session_cbs,
.name = format (0, "session_test_client"),
};
error = vnet_application_attach (&attach_args);
SESSION_TEST ((error == 0), "client app attached");
client_index = attach_args.app_index;
vec_free (attach_args.name);
attach_args.name = format (0, "session_test_server");
attach_args.namespace_id = appns_id;
attach_args.options[APP_OPTIONS_NAMESPACE_SECRET] = dummy_secret;
error = vnet_application_attach (&attach_args);
SESSION_TEST ((error == 0), "server app attached: %U", format_clib_error,
error);
vec_free (attach_args.name);
server_index = attach_args.app_index;
server_sep.is_ip4 = 1;
server_sep.port = dummy_server_port;
vnet_bind_args_t bind_args = {
.sep = server_sep,
.app_index = server_index,
};
error = vnet_bind (&bind_args);
SESSION_TEST ((error == 0), "server bind should work");
/*
* Connect and force lcl ip
*/
client_sep.is_ip4 = 1;
client_sep.ip.ip4.as_u32 = clib_host_to_net_u32 (0x02020202);
client_sep.port = dummy_server_port;
client_sep.peer.is_ip4 = 1;
client_sep.peer.ip.ip4.as_u32 = clib_host_to_net_u32 (0x01010101);
client_sep.peer.port = dummy_client_port;
client_sep.transport_proto = TRANSPORT_PROTO_TCP;
vnet_connect_args_t connect_args = {
.sep_ext = client_sep,
.app_index = client_index,
};
error = vnet_connect (&connect_args);
SESSION_TEST ((error == 0), "connect should work");
/* wait for stuff to happen */
vlib_process_suspend (vm, 10e-3);
SESSION_TEST ((connected_session_index != ~0), "session should exist");
s = session_get (connected_session_index, connected_session_thread);
tc = session_get_transport (s);
SESSION_TEST ((tc != 0), "transport should exist");
SESSION_TEST ((memcmp (&tc->lcl_ip, &client_sep.peer.ip,
sizeof (tc->lcl_ip)) == 0), "ips should be equal");
SESSION_TEST ((tc->lcl_port == dummy_client_port), "ports should be equal");
/* These sessions, because of the way they're established are pinned to
* main thread, even when we have workers and we avoid polling main thread,
* i.e., we can't cleanup pending disconnects, so force cleanup for both
*/
stream_session_cleanup (s);
s = session_get (accepted_session_index, accepted_session_thread);
stream_session_cleanup (s);
vnet_app_detach_args_t detach_args = {
.app_index = server_index,
};
vnet_application_detach (&detach_args);
detach_args.app_index = client_index;
vnet_application_detach (&detach_args);
/* Allow the disconnects to finish before removing the routes. */
vlib_process_suspend (vm, 10e-3);
session_add_del_route_via_lookup_in_table (0, 1, &intf_addr[1], 32,
0 /* is_add */ );
session_add_del_route_via_lookup_in_table (1, 0, &intf_addr[0], 32,
0 /* is_add */ );
session_delete_loopback (sw_if_index[0]);
session_delete_loopback (sw_if_index[1]);
return 0;
}
static int
session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
{
@ -1515,6 +1711,8 @@ session_test (vlib_main_t * vm,
res = session_test_rules (vm, input);
else if (unformat (input, "proxy"))
res = session_test_proxy (vm, input);
else if (unformat (input, "endpt-cfg"))
res = session_test_endpoint_cfg (vm, input);
else if (unformat (input, "all"))
{
if ((res = session_test_basic (vm, input)))
@ -1527,6 +1725,8 @@ session_test (vlib_main_t * vm,
goto done;
if ((res = session_test_proxy (vm, input)))
goto done;
if ((res = session_test_endpoint_cfg (vm, input)))
goto done;
}
else
break;

View File

@ -153,7 +153,7 @@ typedef struct local_session_
} local_session_t;
#define foreach_session_endpoint_fields \
foreach_transport_connection_fields \
foreach_transport_endpoint_cfg_fields \
_(u8, transport_proto) \
typedef struct _session_endpoint
@ -163,7 +163,7 @@ typedef struct _session_endpoint
#undef _
} session_endpoint_t;
typedef struct _session_endpoint_extended
typedef struct _session_endpoint_cfg
{
#define _(type, name) type name;
foreach_session_endpoint_fields
@ -171,7 +171,7 @@ typedef struct _session_endpoint_extended
u32 app_wrk_index;
u32 opaque;
u8 *hostname;
} session_endpoint_extended_t;
} session_endpoint_cfg_t;
#define SESSION_IP46_ZERO \
{ \
@ -179,6 +179,15 @@ typedef struct _session_endpoint_extended
{ 0, 0, }, \
}, \
}
#define TRANSPORT_ENDPOINT_NULL \
{ \
.sw_if_index = ENDPOINT_INVALID_INDEX, \
.ip = SESSION_IP46_ZERO, \
.fib_index = ENDPOINT_INVALID_INDEX, \
.is_ip4 = 0, \
.port = 0, \
}
#define SESSION_ENDPOINT_NULL \
{ \
.sw_if_index = ENDPOINT_INVALID_INDEX, \
@ -186,15 +195,17 @@ typedef struct _session_endpoint_extended
.fib_index = ENDPOINT_INVALID_INDEX, \
.is_ip4 = 0, \
.port = 0, \
.peer = TRANSPORT_ENDPOINT_NULL, \
.transport_proto = 0, \
}
#define SESSION_ENDPOINT_EXT_NULL \
#define SESSION_ENDPOINT_CFG_NULL \
{ \
.sw_if_index = ENDPOINT_INVALID_INDEX, \
.ip = SESSION_IP46_ZERO, \
.fib_index = ENDPOINT_INVALID_INDEX, \
.is_ip4 = 0, \
.port = 0, \
.peer = TRANSPORT_ENDPOINT_NULL, \
.transport_proto = 0, \
.app_wrk_index = ENDPOINT_INVALID_INDEX, \
.opaque = ENDPOINT_INVALID_INDEX, \
@ -202,6 +213,8 @@ typedef struct _session_endpoint_extended
}
#define session_endpoint_to_transport(_sep) ((transport_endpoint_t *)_sep)
#define session_endpoint_to_transport_cfg(_sep) \
((transport_endpoint_cfg_t *)_sep)
always_inline u8
session_endpoint_fib_proto (session_endpoint_t * sep)

View File

@ -291,7 +291,7 @@ always_inline transport_endpoint_t *
transport_endpoint_new (void)
{
transport_endpoint_t *tep;
pool_get (local_endpoints, tep);
pool_get_zero (local_endpoints, tep);
return tep;
}
@ -312,6 +312,19 @@ transport_endpoint_cleanup (u8 proto, ip46_address_t * lcl_ip, u16 port)
}
}
static void
transport_endpoint_mark_used (u8 proto, ip46_address_t * ip, u16 port)
{
transport_endpoint_t *tep;
clib_spinlock_lock_if_init (&local_endpoints_lock);
tep = transport_endpoint_new ();
clib_memcpy (&tep->ip, ip, sizeof (*ip));
tep->port = port;
transport_endpoint_table_add (&local_endpoints_table, proto, tep,
tep - local_endpoints);
clib_spinlock_unlock_if_init (&local_endpoints_lock);
}
/**
* Allocate local port and add if successful add entry to local endpoint
* table to mark the pair as used.
@ -319,10 +332,9 @@ transport_endpoint_cleanup (u8 proto, ip46_address_t * lcl_ip, u16 port)
int
transport_alloc_local_port (u8 proto, ip46_address_t * ip)
{
transport_endpoint_t *tep;
u32 tei;
u16 min = 1024, max = 65535; /* XXX configurable ? */
int tries, limit;
u32 tei;
limit = max - min;
@ -347,33 +359,49 @@ transport_alloc_local_port (u8 proto, ip46_address_t * ip)
port);
if (tei == ENDPOINT_INVALID_INDEX)
{
clib_spinlock_lock_if_init (&local_endpoints_lock);
tep = transport_endpoint_new ();
clib_memcpy (&tep->ip, ip, sizeof (*ip));
tep->port = port;
transport_endpoint_table_add (&local_endpoints_table, proto, tep,
tep - local_endpoints);
clib_spinlock_unlock_if_init (&local_endpoints_lock);
return tep->port;
transport_endpoint_mark_used (proto, ip, port);
return port;
}
}
return -1;
}
int
transport_alloc_local_endpoint (u8 proto, transport_endpoint_t * rmt,
ip46_address_t * lcl_addr, u16 * lcl_port)
static clib_error_t *
transport_get_interface_ip (u32 sw_if_index, u8 is_ip4, ip46_address_t * addr)
{
if (is_ip4)
{
ip4_address_t *ip4;
ip4 = ip_interface_get_first_ip (sw_if_index, 1);
if (!ip4)
return clib_error_return (0, "no routable ip4 address on %U",
format_vnet_sw_if_index_name,
vnet_get_main (), sw_if_index);
addr->ip4.as_u32 = ip4->as_u32;
}
else
{
ip6_address_t *ip6;
ip6 = ip_interface_get_first_ip (sw_if_index, 0);
if (ip6 == 0)
return clib_error_return (0, "no routable ip6 addresses on %U",
format_vnet_sw_if_index_name,
vnet_get_main (), sw_if_index);
clib_memcpy (&addr->ip6, ip6, sizeof (*ip6));
}
return 0;
}
static clib_error_t *
transport_find_local_ip_for_remote (u32 sw_if_index,
transport_endpoint_t * rmt,
ip46_address_t * lcl_addr)
{
fib_prefix_t prefix;
fib_node_index_t fei;
u32 sw_if_index;
int port;
/*
* Find the local address and allocate port
*/
fib_prefix_t prefix;
if (sw_if_index == ENDPOINT_INVALID_INDEX)
{
/* Find a FIB path to the destination */
clib_memcpy (&prefix.fp_addr, &rmt->ip, sizeof (rmt->ip));
prefix.fp_proto = rmt->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
@ -384,52 +412,50 @@ transport_alloc_local_endpoint (u8 proto, transport_endpoint_t * rmt,
/* Couldn't find route to destination. Bail out. */
if (fei == FIB_NODE_INDEX_INVALID)
{
clib_warning ("no route to destination");
return -1;
}
sw_if_index = rmt->sw_if_index;
if (sw_if_index == ENDPOINT_INVALID_INDEX)
sw_if_index = fib_entry_get_resolving_interface (fei);
if (sw_if_index == ENDPOINT_INVALID_INDEX)
{
clib_warning ("no resolving interface for %U", format_ip46_address,
return clib_error_return (0, "no route to %U", format_ip46_address,
&rmt->ip, (rmt->is_ip4 == 0) + 1);
return -1;
sw_if_index = fib_entry_get_resolving_interface (fei);
if (sw_if_index == ENDPOINT_INVALID_INDEX)
return clib_error_return (0, "no resolving interface for %U",
format_ip46_address, &rmt->ip,
(rmt->is_ip4 == 0) + 1);
}
clib_memset (lcl_addr, 0, sizeof (*lcl_addr));
if (rmt->is_ip4)
{
ip4_address_t *ip4;
ip4 = ip_interface_get_first_ip (sw_if_index, 1);
if (!ip4)
{
clib_warning ("no routable ip4 address on %U",
format_vnet_sw_if_index_name, vnet_get_main (),
sw_if_index);
return -1;
return transport_get_interface_ip (sw_if_index, rmt->is_ip4, lcl_addr);
}
lcl_addr->ip4.as_u32 = ip4->as_u32;
int
transport_alloc_local_endpoint (u8 proto, transport_endpoint_cfg_t * rmt_cfg,
ip46_address_t * lcl_addr, u16 * lcl_port)
{
transport_endpoint_t *rmt = (transport_endpoint_t *) rmt_cfg;
clib_error_t *error;
int port;
u32 tei;
/*
* Find the local address
*/
if (ip_is_zero (&rmt_cfg->peer.ip, rmt_cfg->peer.is_ip4))
{
error = transport_find_local_ip_for_remote (rmt_cfg->peer.sw_if_index,
rmt, lcl_addr);
if (error)
return -1;
}
else
{
ip6_address_t *ip6;
ip6 = ip_interface_get_first_ip (sw_if_index, 0);
if (ip6 == 0)
{
clib_warning ("no routable ip6 addresses on %U",
format_vnet_sw_if_index_name, vnet_get_main (),
sw_if_index);
return -1;
}
clib_memcpy (&lcl_addr->ip6, ip6, sizeof (*ip6));
/* Assume session layer vetted this address */
clib_memcpy (lcl_addr, &rmt_cfg->peer.ip, sizeof (rmt_cfg->peer.ip));
}
/* Allocate source port */
/*
* Allocate source port
*/
if (rmt_cfg->peer.port == 0)
{
port = transport_alloc_local_port (proto, lcl_addr);
if (port < 1)
{
@ -437,6 +463,19 @@ transport_alloc_local_endpoint (u8 proto, transport_endpoint_t * rmt,
return -1;
}
*lcl_port = port;
}
else
{
port = clib_net_to_host_u16 (rmt_cfg->peer.port);
tei = transport_endpoint_lookup (&local_endpoints_table, proto,
lcl_addr, port);
if (tei != ENDPOINT_INVALID_INDEX)
return -1;
transport_endpoint_mark_used (proto, lcl_addr, port);
*lcl_port = port;
}
return 0;
}

View File

@ -122,20 +122,31 @@ u8 *format_transport_half_open_connection (u8 * s, va_list * args);
uword unformat_transport_proto (unformat_input_t * input, va_list * args);
#define foreach_transport_connection_fields \
_(u32, sw_if_index) /**< interface endpoint is associated with */ \
_(ip46_address_t, ip) /**< ip address */ \
_(u32, fib_index) /**< fib table endpoint is associated with */ \
_(u8, is_ip4) /**< set if ip4 */ \
#define foreach_transport_endpoint_fields \
_(ip46_address_t, ip) /**< ip address in net order */ \
_(u16, port) /**< port in net order */ \
_(u8, is_ip4) /**< set if ip4 */ \
_(u32, sw_if_index) /**< interface endpoint is associated with */ \
_(u32, fib_index) /**< fib table endpoint is associated with */ \
typedef struct _transport_endpoint
typedef struct transport_endpoint_
{
#define _(type, name) type name;
foreach_transport_connection_fields
foreach_transport_endpoint_fields
#undef _
} transport_endpoint_t;
#define foreach_transport_endpoint_cfg_fields \
foreach_transport_endpoint_fields \
_(transport_endpoint_t, peer) \
typedef struct transport_endpoint_pair_
{
#define _(type, name) type name;
foreach_transport_endpoint_cfg_fields
#undef _
} transport_endpoint_cfg_t;
typedef clib_bihash_24_8_t transport_endpoint_table_t;
#define ENDPOINT_INVALID_INDEX ((u32)~0)
@ -153,7 +164,7 @@ transport_endpoint_fib_proto (transport_endpoint_t * tep)
}
int transport_alloc_local_port (u8 proto, ip46_address_t * ip);
int transport_alloc_local_endpoint (u8 proto, transport_endpoint_t * rmt,
int transport_alloc_local_endpoint (u8 proto, transport_endpoint_cfg_t * rmt,
ip46_address_t * lcl_addr,
u16 * lcl_port);
void transport_endpoint_cleanup (u8 proto, ip46_address_t * lcl_ip, u16 port);

View File

@ -47,7 +47,7 @@ typedef struct _transport_proto_vft
*/
u32 (*bind) (u32 session_index, transport_endpoint_t * lcl);
u32 (*unbind) (u32);
int (*open) (transport_endpoint_t * rmt);
int (*open) (transport_endpoint_cfg_t * rmt);
void (*close) (u32 conn_index, u32 thread_index);
void (*cleanup) (u32 conn_index, u32 thread_index);
clib_error_t *(*enable) (vlib_main_t * vm, u8 is_en);

View File

@ -620,7 +620,7 @@ tcp_alloc_custom_local_endpoint (tcp_main_t * tm, ip46_address_t * lcl_addr,
}
static int
tcp_connection_open (transport_endpoint_t * rmt)
tcp_session_open (transport_endpoint_cfg_t * rmt)
{
tcp_main_t *tm = vnet_get_tcp_main ();
tcp_connection_t *tc;
@ -666,12 +666,6 @@ tcp_connection_open (transport_endpoint_t * rmt)
return tc->c_c_index;
}
static int
tcp_session_open (transport_endpoint_t * tep)
{
return tcp_connection_open (tep);
}
const char *tcp_dbg_evt_str[] = {
#define _(sym, str) str,
foreach_tcp_dbg_evt

View File

@ -511,10 +511,10 @@ static session_cb_vft_t tls_app_cb_vft = {
/* *INDENT-ON* */
int
tls_connect (transport_endpoint_t * tep)
tls_connect (transport_endpoint_cfg_t * tep)
{
vnet_connect_args_t _cargs = { {}, }, *cargs = &_cargs;
session_endpoint_extended_t *sep;
session_endpoint_cfg_t *sep;
tls_engine_type_t engine_type;
tls_main_t *tm = &tls_main;
app_worker_t *app_wrk;
@ -523,7 +523,7 @@ tls_connect (transport_endpoint_t * tep)
tls_ctx_t *ctx;
u32 ctx_index;
sep = (session_endpoint_extended_t *) tep;
sep = (session_endpoint_cfg_t *) tep;
app_wrk = app_worker_get (sep->app_wrk_index);
app = application_get (app_wrk->app_index);
engine_type = tls_get_engine_type (app->tls_engine);
@ -579,7 +579,7 @@ tls_start_listen (u32 app_listener_index, transport_endpoint_t * tep)
app_worker_t *app_wrk;
tls_main_t *tm = &tls_main;
session_handle_t tls_handle;
session_endpoint_extended_t *sep;
session_endpoint_cfg_t *sep;
stream_session_t *tls_listener;
stream_session_t *app_listener;
tls_engine_type_t engine_type;
@ -587,7 +587,7 @@ tls_start_listen (u32 app_listener_index, transport_endpoint_t * tep)
tls_ctx_t *lctx;
u32 lctx_index;
sep = (session_endpoint_extended_t *) tep;
sep = (session_endpoint_cfg_t *) tep;
app_wrk = app_worker_get (sep->app_wrk_index);
app = application_get (app_wrk->app_index);
engine_type = tls_get_engine_type (app->tls_engine);

View File

@ -261,7 +261,7 @@ udp_send_space (transport_connection_t * t)
}
int
udp_open_connection (transport_endpoint_t * rmt)
udp_open_connection (transport_endpoint_cfg_t * rmt)
{
udp_main_t *um = vnet_get_udp_main ();
vlib_main_t *vm = vlib_get_main ();
@ -339,7 +339,7 @@ const static transport_proto_vft_t udp_proto = {
int
udpc_connection_open (transport_endpoint_t * rmt)
udpc_connection_open (transport_endpoint_cfg_t * rmt)
{
udp_connection_t *uc;
u32 uc_index;

View File

@ -47,14 +47,6 @@ class TestSession(VppTestCase):
super(TestSession, self).tearDown()
self.vapi.session_enable_disable(is_enabled=1)
def test_session(self):
""" Session Unit Tests """
error = self.vapi.cli("test session all")
if error:
self.logger.critical(error)
self.assertEqual(error.find("failed"), -1)
def test_segment_manager_alloc(self):
""" Session Segment Manager Multiple Segment Allocation """
@ -92,5 +84,25 @@ class TestSession(VppTestCase):
ip_t01.remove_vpp_config()
ip_t10.remove_vpp_config()
class TestSessionUnitTests(VppTestCase):
""" Session Unit Tests Case """
def setUp(self):
super(TestSessionUnitTests, self).setUp()
self.vapi.session_enable_disable(is_enabled=1)
def test_session(self):
""" Session Unit Tests """
error = self.vapi.cli("test session all")
if error:
self.logger.critical(error)
self.assertEqual(error.find("failed"), -1)
def tearDown(self):
super(TestSessionUnitTests, self).tearDown()
self.vapi.session_enable_disable(is_enabled=0)
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)