session: add ip4-fib-id and ip6-fib-id to app ns CLI
Problem The API app_namespace_add_del allows specifying ip4_fib_id and ip6_fib_id. But the CLI does not. It only allows interface. Interface binding may change after the application namespace is created and there is no registration for the callback when the interface binding changes. Fix Add ip4-fib-id and ip6-fib-id to app ns CLI. When both interface and fib-id's are specified, interface takes precedence. When interface is not specified, either ip4-fib-id or ip6-fib-id or both ip4 and ip6 fib-id's may be specified. If only ip4-fib-id is specified, ip6 is disable for this particular app namespace. If only ip6-fib-id is specified, ip4 is disable for this namespace. When the interface binding changes to different vrf and the application namespace was created via interface option, we delete the application namespace and recreate the application namespace with the new interface binding. Notice when the application namespace is removed, all session rules and sdl rules previously created for the deleted application namespace will be deleted. However, if the fib table/session table was shared by another namespace, the other namespace will still contain the session rules and sdl rules. Type: improvement Change-Id: I76eb30da1ed8a39d06694c1e66d0675bf03516bf Signed-off-by: Steven Luong <sluong@cisco.com>
This commit is contained in:
parent
fd896fc9fa
commit
2e67a3f377
@ -191,6 +191,22 @@ static __clib_unused void * __clib_unused_##f = f;
|
||||
#define VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION_PRIO(f,p) \
|
||||
_VNET_INTERFACE_FUNCTION_DECL_PRIO(f,sw_interface_admin_up_down, p)
|
||||
|
||||
#define VNET_SW_INTERFACE_TABLE_BIND_V4_CB(f) \
|
||||
{ \
|
||||
ip4_table_bind_callback_t cb = { \
|
||||
.function = f, \
|
||||
}; \
|
||||
vec_add1 (ip4_main.table_bind_callbacks, cb); \
|
||||
}
|
||||
|
||||
#define VNET_SW_INTERFACE_TABLE_BIND_V6_CB(f) \
|
||||
{ \
|
||||
ip6_table_bind_callback_t cb = { \
|
||||
.function = f, \
|
||||
}; \
|
||||
vec_add1 (ip6_main.table_bind_callbacks, cb); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Tunnel description parameters
|
||||
*/
|
||||
|
@ -107,6 +107,7 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t *a)
|
||||
session_table_t *st;
|
||||
u32 ns_index;
|
||||
session_error_t rv;
|
||||
u32 ip4_fib_index, ip6_fib_index;
|
||||
|
||||
if (a->is_add)
|
||||
{
|
||||
@ -115,6 +116,10 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t *a)
|
||||
a->sw_if_index))
|
||||
return SESSION_E_INVALID;
|
||||
|
||||
/*
|
||||
* sw_if_index takes precedence over fib_id's.
|
||||
* When sw_if_index is provided, overwrite what's in fib_id's
|
||||
*/
|
||||
if (a->sw_if_index != APP_NAMESPACE_INVALID_INDEX)
|
||||
{
|
||||
a->ip4_fib_id =
|
||||
@ -124,8 +129,23 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t *a)
|
||||
fib_table_get_table_id_for_sw_if_index (FIB_PROTOCOL_IP6,
|
||||
a->sw_if_index);
|
||||
}
|
||||
if (a->sw_if_index == APP_NAMESPACE_INVALID_INDEX
|
||||
&& a->ip4_fib_id == APP_NAMESPACE_INVALID_INDEX)
|
||||
/* Either sw_if_index or one of 2 fib_id's must be provided */
|
||||
if (a->sw_if_index == APP_NAMESPACE_INVALID_INDEX &&
|
||||
a->ip4_fib_id == APP_NAMESPACE_INVALID_INDEX &&
|
||||
a->ip6_fib_id == APP_NAMESPACE_INVALID_INDEX)
|
||||
return SESSION_E_INVALID;
|
||||
|
||||
/* Validate the fib_id's */
|
||||
ip4_fib_index = fib_table_find (FIB_PROTOCOL_IP4, a->ip4_fib_id);
|
||||
ip6_fib_index = fib_table_find (FIB_PROTOCOL_IP6, a->ip6_fib_id);
|
||||
if ((ip4_fib_index == ~0) && (ip6_fib_index == ~0))
|
||||
return SESSION_E_INVALID;
|
||||
|
||||
/* if fib_id entered, check fib_id exist */
|
||||
if (((a->ip4_fib_id != APP_NAMESPACE_INVALID_INDEX) &&
|
||||
(ip4_fib_index == ~0)) ||
|
||||
((a->ip6_fib_id != APP_NAMESPACE_INVALID_INDEX) &&
|
||||
(ip6_fib_index == ~0)))
|
||||
return SESSION_E_INVALID;
|
||||
|
||||
app_ns = app_namespace_get_from_id (a->ns_id);
|
||||
@ -169,8 +189,8 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t *a)
|
||||
app_ns->ns_secret = a->secret;
|
||||
app_ns->sw_if_index = a->sw_if_index;
|
||||
|
||||
app_ns->ip4_fib_index = fib_table_find (FIB_PROTOCOL_IP4, a->ip4_fib_id);
|
||||
app_ns->ip6_fib_index = fib_table_find (FIB_PROTOCOL_IP6, a->ip6_fib_id);
|
||||
app_ns->ip4_fib_index = ip4_fib_index;
|
||||
app_ns->ip6_fib_index = ip6_fib_index;
|
||||
session_lookup_set_tables_appns (app_ns);
|
||||
}
|
||||
else
|
||||
@ -266,11 +286,98 @@ appns_sapi_enabled (void)
|
||||
return app_sapi_enabled;
|
||||
}
|
||||
|
||||
static void
|
||||
app_namespace_table_bind_v4 (ip4_main_t *im, uword opaque, u32 sw_if_index,
|
||||
u32 new_fib_index, u32 old_fib_index)
|
||||
{
|
||||
app_namespace_t *app_ns;
|
||||
|
||||
pool_foreach (app_ns, app_namespace_pool)
|
||||
{
|
||||
if (app_ns->sw_if_index == sw_if_index)
|
||||
{
|
||||
/*
|
||||
* For add, call vnet_app_namespace_add_del without sw_if_index and
|
||||
* keep the existing ip6_fib_index.
|
||||
*/
|
||||
vnet_app_namespace_add_del_args_t add = {
|
||||
.ns_id = vec_dup (app_ns->ns_id),
|
||||
.secret = app_ns->ns_secret,
|
||||
.sw_if_index = APP_NAMESPACE_INVALID_INDEX,
|
||||
.sock_name = vec_dup (app_ns->sock_name),
|
||||
.ip4_fib_id =
|
||||
fib_table_get_table_id (new_fib_index, FIB_PROTOCOL_IP4),
|
||||
.ip6_fib_id =
|
||||
fib_table_get_table_id (app_ns->ip6_fib_index, FIB_PROTOCOL_IP6),
|
||||
.is_add = 1,
|
||||
};
|
||||
vnet_app_namespace_add_del_args_t del = {
|
||||
.ns_id = app_ns->ns_id,
|
||||
.is_add = 0,
|
||||
};
|
||||
vnet_app_namespace_add_del (&del);
|
||||
|
||||
vnet_app_namespace_add_del (&add);
|
||||
|
||||
/* keep the sw_if_index */
|
||||
app_ns->sw_if_index = sw_if_index;
|
||||
|
||||
vec_free (add.ns_id);
|
||||
vec_free (add.sock_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
app_namespace_table_bind_v6 (ip6_main_t *im, uword opaque, u32 sw_if_index,
|
||||
u32 new_fib_index, u32 old_fib_index)
|
||||
{
|
||||
app_namespace_t *app_ns;
|
||||
|
||||
pool_foreach (app_ns, app_namespace_pool)
|
||||
{
|
||||
if (app_ns->sw_if_index == sw_if_index)
|
||||
{
|
||||
/*
|
||||
* For add, call vnet_app_namespace_add_del without sw_if_index and
|
||||
* keep the existing ip4_fib_index.
|
||||
*/
|
||||
vnet_app_namespace_add_del_args_t add = {
|
||||
.ns_id = vec_dup (app_ns->ns_id),
|
||||
.secret = app_ns->ns_secret,
|
||||
.sw_if_index = APP_NAMESPACE_INVALID_INDEX,
|
||||
.sock_name = vec_dup (app_ns->sock_name),
|
||||
.ip4_fib_id =
|
||||
fib_table_get_table_id (app_ns->ip4_fib_index, FIB_PROTOCOL_IP4),
|
||||
.ip6_fib_id =
|
||||
fib_table_get_table_id (new_fib_index, FIB_PROTOCOL_IP6),
|
||||
.is_add = 1,
|
||||
};
|
||||
vnet_app_namespace_add_del_args_t del = {
|
||||
.ns_id = app_ns->ns_id,
|
||||
.is_add = 0,
|
||||
};
|
||||
vnet_app_namespace_add_del (&del);
|
||||
|
||||
vnet_app_namespace_add_del (&add);
|
||||
|
||||
/* keep the sw_if_index */
|
||||
app_ns->sw_if_index = sw_if_index;
|
||||
|
||||
vec_free (add.ns_id);
|
||||
vec_free (add.sock_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
app_namespaces_init (void)
|
||||
{
|
||||
u8 *ns_id = format (0, "default");
|
||||
|
||||
VNET_SW_INTERFACE_TABLE_BIND_V4_CB (app_namespace_table_bind_v4);
|
||||
VNET_SW_INTERFACE_TABLE_BIND_V6_CB (app_namespace_table_bind_v6);
|
||||
|
||||
if (!app_namespace_lookup_table)
|
||||
app_namespace_lookup_table =
|
||||
hash_create_vec (0, sizeof (u8), sizeof (uword));
|
||||
@ -298,9 +405,11 @@ app_ns_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
vlib_cli_command_t * cmd)
|
||||
{
|
||||
u8 is_add = 0, *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
|
||||
u8 fib6_id_set = 0, fib4_id_set = 0;
|
||||
u8 *sock_name = 0;
|
||||
unformat_input_t _line_input, *line_input = &_line_input;
|
||||
u32 sw_if_index, fib_id = APP_NAMESPACE_INVALID_INDEX;
|
||||
u32 sw_if_index = APP_NAMESPACE_INVALID_INDEX;
|
||||
u32 fib4_id = ~0, fib6_id = ~0;
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
u64 secret;
|
||||
clib_error_t *error = 0;
|
||||
@ -326,8 +435,10 @@ app_ns_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
else if (unformat (line_input, "if %U", unformat_vnet_sw_interface, vnm,
|
||||
&sw_if_index))
|
||||
sw_if_index_set = 1;
|
||||
else if (unformat (line_input, "fib_id", &fib_id))
|
||||
;
|
||||
else if (unformat (line_input, "ip4-fib-id %u", &fib4_id))
|
||||
fib4_id_set = 1;
|
||||
else if (unformat (line_input, "ip6-fib-id %u", &fib6_id))
|
||||
fib6_id_set = 1;
|
||||
else if (unformat (line_input, "sock-name %_%v%_", &sock_name))
|
||||
;
|
||||
else
|
||||
@ -344,9 +455,23 @@ app_ns_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (is_add && (!secret_set || !sw_if_index_set))
|
||||
if (is_add &&
|
||||
(!secret_set || (!sw_if_index_set && !fib4_id_set && !fib6_id_set)))
|
||||
{
|
||||
vlib_cli_output (vm, "secret and interface must be provided");
|
||||
vlib_cli_output (vm, "secret and interface or fib-id must be provided");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Validate the fib-id is valid */
|
||||
if (fib4_id_set && (fib_table_find (FIB_PROTOCOL_IP4, fib4_id) == ~0))
|
||||
{
|
||||
vlib_cli_output (vm, "ip4-fib-id %u does not exist", fib4_id);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (fib6_id_set && (fib_table_find (FIB_PROTOCOL_IP6, fib6_id) == ~0))
|
||||
{
|
||||
vlib_cli_output (vm, "ip6-fib-id %u does not exist", fib6_id);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -356,7 +481,8 @@ app_ns_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
.secret = secret,
|
||||
.sw_if_index = sw_if_index,
|
||||
.sock_name = sock_name,
|
||||
.ip4_fib_id = fib_id,
|
||||
.ip4_fib_id = fib4_id,
|
||||
.ip6_fib_id = fib6_id,
|
||||
.is_add = is_add,
|
||||
};
|
||||
/* clang-format on */
|
||||
@ -376,7 +502,8 @@ done:
|
||||
VLIB_CLI_COMMAND (app_ns_command, static) = {
|
||||
.path = "app ns",
|
||||
.short_help = "app ns [add|del] id <namespace-id> secret <secret> "
|
||||
"sw_if_index <sw_if_index> if <interface>",
|
||||
"sw_if_index <sw_if_index> "
|
||||
"{ip4-fib-id <id> ip6-fib-id <id> | if <interface>}",
|
||||
.function = app_ns_fn,
|
||||
};
|
||||
|
||||
|
@ -1454,6 +1454,8 @@ session_lookup_set_tables_appns (app_namespace_t * app_ns)
|
||||
for (fp = 0; fp < ARRAY_LEN (fib_index_to_table_index); fp++)
|
||||
{
|
||||
fib_index = app_namespace_get_fib_index (app_ns, fp);
|
||||
if (fib_index == ~0)
|
||||
continue;
|
||||
st = session_table_get_or_alloc (fp, fib_index);
|
||||
if (st)
|
||||
{
|
||||
@ -1953,6 +1955,8 @@ session_lookup_table_cleanup (u32 fib_proto, u32 fib_index, u32 ns_index)
|
||||
u32 table_index, appns_index;
|
||||
int i;
|
||||
|
||||
if (fib_index == ~0)
|
||||
return;
|
||||
session_lookup_fib_table_unlock (fib_index, fib_proto);
|
||||
table_index = session_lookup_get_index_for_fib (fib_proto, fib_index);
|
||||
st = session_table_get (table_index);
|
||||
|
@ -122,7 +122,6 @@ class TestSession(VppAsfTestCase):
|
||||
ip_t10.remove_vpp_config()
|
||||
|
||||
|
||||
@tag_fixme_vpp_workers
|
||||
class TestApplicationNamespace(VppAsfTestCase):
|
||||
"""Application Namespacee"""
|
||||
|
||||
@ -219,6 +218,160 @@ class TestApplicationNamespace(VppAsfTestCase):
|
||||
)
|
||||
self.assertEqual(rv.retval, -1)
|
||||
|
||||
def test_application_namespace_binding(self):
|
||||
"""Application Namespace Interface Binding"""
|
||||
|
||||
self.vapi.session_enable_disable_v2(
|
||||
rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_RULE_TABLE
|
||||
)
|
||||
|
||||
table_id = 99
|
||||
|
||||
# Bad ip4_fib_id
|
||||
with self.vapi.assert_negative_api_retval():
|
||||
rv = self.vapi.app_namespace_add_del_v4(
|
||||
is_add=1, namespace_id="2", ip4_fib_id=table_id, ip6_fib_id=0
|
||||
)
|
||||
self.assertEqual(rv.retval, -19)
|
||||
|
||||
# Bad ip6_fib_id
|
||||
with self.vapi.assert_negative_api_retval():
|
||||
rv = self.vapi.app_namespace_add_del_v4(
|
||||
is_add=1, namespace_id="2", ip4_fib_id=0, ip6_fib_id=table_id
|
||||
)
|
||||
self.assertEqual(rv.retval, -19)
|
||||
|
||||
tbl = VppIpTable(self, table_id)
|
||||
tbl.add_vpp_config()
|
||||
|
||||
tbl6 = VppIpTable(self, table_id, is_ip6=1)
|
||||
tbl6.add_vpp_config()
|
||||
|
||||
# Not expecting an error with valid table_id's
|
||||
self.vapi.app_namespace_add_del_v4(
|
||||
is_add=1, namespace_id="2", ip4_fib_id=table_id, ip6_fib_id=table_id
|
||||
)
|
||||
# delete
|
||||
self.vapi.app_namespace_add_del_v4(
|
||||
is_add=0, namespace_id="2", ip4_fib_id=table_id, ip6_fib_id=table_id
|
||||
)
|
||||
|
||||
# ip4 only
|
||||
self.vapi.app_namespace_add_del_v4(
|
||||
is_add=1, namespace_id="2", ip4_fib_id=table_id, ip6_fib_id=0xFFFFFFFF
|
||||
)
|
||||
# delete
|
||||
self.vapi.app_namespace_add_del_v4(
|
||||
is_add=0, namespace_id="2", ip4_fib_id=table_id, ip6_fib_id=0xFFFFFFFF
|
||||
)
|
||||
|
||||
# ip6 only
|
||||
self.vapi.app_namespace_add_del_v4(
|
||||
is_add=1, namespace_id="2", ip4_fib_id=0xFFFFFFFF, ip6_fib_id=table_id
|
||||
)
|
||||
# delete
|
||||
self.vapi.app_namespace_add_del_v4(
|
||||
is_add=0, namespace_id="2", ip4_fib_id=0xFFFFFFFF, ip6_fib_id=table_id
|
||||
)
|
||||
|
||||
app0 = self.vapi.app_namespace_add_del_v4(
|
||||
namespace_id="0", sw_if_index=self.loop0.sw_if_index, is_add=1
|
||||
)
|
||||
self.vapi.session_rule_add_del(
|
||||
transport_proto=VppEnum.vl_api_transport_proto_t.TRANSPORT_PROTO_API_TCP,
|
||||
lcl="172.100.1.1/32",
|
||||
rmt="172.100.1.2/32",
|
||||
lcl_port=5000,
|
||||
rmt_port=5000,
|
||||
action_index=1,
|
||||
appns_index=app0.appns_index,
|
||||
scope=VppEnum.vl_api_session_rule_scope_t.SESSION_RULE_SCOPE_API_GLOBAL,
|
||||
is_add=1,
|
||||
)
|
||||
dump = self.vapi.session_rules_v2_dump()
|
||||
self.assertEqual(len(dump[1].appns_index), 2)
|
||||
self.assertEqual(dump[1].count, 2)
|
||||
|
||||
# move the interface to vrf 99
|
||||
self.vapi.sw_interface_set_table(
|
||||
sw_if_index=self.loop0.sw_if_index,
|
||||
is_ipv6=0,
|
||||
vrf_id=table_id,
|
||||
)
|
||||
dump = self.vapi.session_rules_v2_dump()
|
||||
self.assertEqual(len(dump[1].appns_index), 1)
|
||||
self.assertEqual(dump[1].count, 1)
|
||||
|
||||
self.vapi.session_rule_add_del(
|
||||
transport_proto=VppEnum.vl_api_transport_proto_t.TRANSPORT_PROTO_API_TCP,
|
||||
lcl="172.100.1.1/32",
|
||||
rmt="172.100.1.2/32",
|
||||
lcl_port=5000,
|
||||
rmt_port=5000,
|
||||
action_index=1,
|
||||
appns_index=0,
|
||||
scope=VppEnum.vl_api_session_rule_scope_t.SESSION_RULE_SCOPE_API_GLOBAL,
|
||||
is_add=0,
|
||||
)
|
||||
|
||||
# move the interface to vrf 0
|
||||
self.vapi.sw_interface_set_table(
|
||||
sw_if_index=self.loop0.sw_if_index,
|
||||
is_ipv6=0,
|
||||
vrf_id=0,
|
||||
)
|
||||
|
||||
# try it with ip6
|
||||
self.vapi.session_rule_add_del(
|
||||
transport_proto=VppEnum.vl_api_transport_proto_t.TRANSPORT_PROTO_API_TCP,
|
||||
lcl="2001::1/128",
|
||||
rmt="2002::1/128",
|
||||
lcl_port=5000,
|
||||
rmt_port=5000,
|
||||
action_index=1,
|
||||
appns_index=app0.appns_index,
|
||||
scope=VppEnum.vl_api_session_rule_scope_t.SESSION_RULE_SCOPE_API_GLOBAL,
|
||||
is_add=1,
|
||||
)
|
||||
dump = self.vapi.session_rules_v2_dump()
|
||||
self.assertEqual(len(dump[1].appns_index), 2)
|
||||
self.assertEqual(dump[1].count, 2)
|
||||
|
||||
self.vapi.sw_interface_set_table(
|
||||
sw_if_index=self.loop0.sw_if_index,
|
||||
is_ipv6=1,
|
||||
vrf_id=table_id,
|
||||
)
|
||||
dump = self.vapi.session_rules_v2_dump()
|
||||
self.assertEqual(len(dump[1].appns_index), 2)
|
||||
self.assertEqual(dump[1].count, 2)
|
||||
|
||||
# move back to 0
|
||||
self.vapi.sw_interface_set_table(
|
||||
sw_if_index=self.loop0.sw_if_index,
|
||||
is_ipv6=1,
|
||||
vrf_id=0,
|
||||
)
|
||||
|
||||
self.vapi.session_rule_add_del(
|
||||
transport_proto=VppEnum.vl_api_transport_proto_t.TRANSPORT_PROTO_API_TCP,
|
||||
lcl="2001::1/128",
|
||||
rmt="2002::1/128",
|
||||
lcl_port=5000,
|
||||
rmt_port=5000,
|
||||
action_index=1,
|
||||
appns_index=0,
|
||||
scope=VppEnum.vl_api_session_rule_scope_t.SESSION_RULE_SCOPE_API_GLOBAL,
|
||||
is_add=0,
|
||||
)
|
||||
|
||||
self.vapi.app_namespace_add_del_v4(
|
||||
namespace_id="0", sw_if_index=self.loop0.sw_if_index, is_add=0
|
||||
)
|
||||
|
||||
tbl.remove_vpp_config()
|
||||
tbl6.remove_vpp_config()
|
||||
|
||||
|
||||
@tag_fixme_vpp_workers
|
||||
class TestSessionUnitTests(VppAsfTestCase):
|
||||
|
Loading…
x
Reference in New Issue
Block a user