summaryrefslogtreecommitdiffstats
path: root/src/vnet/ipsec
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2020-02-20 09:45:16 +0000
committerNeale Ranns <nranns@cisco.com>2020-02-25 10:48:52 +0000
commit8d6d74cdf43d7560eab3cf609cab27e5deb816e0 (patch)
treefe3d7328edbb9b8e6d7d8e3b0cea7fd7307d78e5 /src/vnet/ipsec
parent719ef39d988182d1297dc9c3f06b7bbda3043d47 (diff)
vlib: Punt reason allocation listener enable/disable callback
Type: improvement allow clients that allocate punt reasons to pass a callback function that is invoked when the first/last client registers to use/listen on that punt reason. This allows the client to perform some necessary configs that might not otherwise be enabled. IPSec uses this callback to register the ESP proto and UDP handling nodes, that would not otherwise be enabled unless a tunnel was present. Change-Id: I9759349903f21ffeeb253d4271e619e6bf46054b Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/ipsec')
-rw-r--r--src/vnet/ipsec/ipsec_punt.c18
-rw-r--r--src/vnet/ipsec/ipsec_tun.c77
-rw-r--r--src/vnet/ipsec/ipsec_tun.h3
3 files changed, 75 insertions, 23 deletions
diff --git a/src/vnet/ipsec/ipsec_punt.c b/src/vnet/ipsec/ipsec_punt.c
index 357e9596cfc..a08231ab299 100644
--- a/src/vnet/ipsec/ipsec_punt.c
+++ b/src/vnet/ipsec/ipsec_punt.c
@@ -17,11 +17,27 @@
#include <vnet/ipsec/ipsec.h>
#include <vnet/ipsec/ipsec_punt.h>
+#include <vnet/ipsec/ipsec_tun.h>
static vlib_punt_hdl_t punt_hdl;
vlib_punt_reason_t ipsec_punt_reason[IPSEC_PUNT_N_REASONS];
+static void
+ipsec_punt_interested_listener (vlib_enable_or_disable_t action, void *data)
+{
+ if (action == VLIB_ENABLE)
+ {
+ ipsec_tun_register_nodes (AF_IP4);
+ ipsec_tun_register_nodes (AF_IP6);
+ }
+ else
+ {
+ ipsec_tun_unregister_nodes (AF_IP4);
+ ipsec_tun_unregister_nodes (AF_IP6);
+ }
+}
+
static clib_error_t *
ipsec_punt_init (vlib_main_t * vm)
{
@@ -33,6 +49,8 @@ ipsec_punt_init (vlib_main_t * vm)
punt_hdl = vlib_punt_client_register ("ipsec");
#define _(s,v) vlib_punt_reason_alloc (punt_hdl, v, \
+ ipsec_punt_interested_listener, \
+ NULL, \
&ipsec_punt_reason[IPSEC_PUNT_##s]);
foreach_ipsec_punt_reason
#undef _
diff --git a/src/vnet/ipsec/ipsec_tun.c b/src/vnet/ipsec/ipsec_tun.c
index 769229721f6..07dd9ea409b 100644
--- a/src/vnet/ipsec/ipsec_tun.c
+++ b/src/vnet/ipsec/ipsec_tun.c
@@ -81,6 +81,43 @@ const static ipsec_tun_protect_itf_db_t IPSEC_TUN_PROTECT_DEFAULT_DB_ENTRY = {
_fmt, ##_args); \
}
+static u32 ipsec_tun_node_regs[N_AF];
+
+void
+ipsec_tun_register_nodes (ip_address_family_t af)
+{
+ if (0 == ipsec_tun_node_regs[af]++)
+ {
+ if (AF_IP4 == af)
+ {
+ udp_register_dst_port (vlib_get_main (),
+ UDP_DST_PORT_ipsec,
+ ipsec4_tun_input_node.index, 1);
+ ip4_register_protocol (IP_PROTOCOL_IPSEC_ESP,
+ ipsec4_tun_input_node.index);
+ }
+ else
+ ip6_register_protocol (IP_PROTOCOL_IPSEC_ESP,
+ ipsec6_tun_input_node.index);
+ }
+}
+
+void
+ipsec_tun_unregister_nodes (ip_address_family_t af)
+{
+ ASSERT (0 != ipsec_tun_node_regs[af]);
+ if (0 == --ipsec_tun_node_regs[af])
+ {
+ if (AF_IP4 == af)
+ {
+ udp_unregister_dst_port (vlib_get_main (), UDP_DST_PORT_ipsec, 1);
+ ip4_unregister_protocol (IP_PROTOCOL_IPSEC_ESP);
+ }
+ else
+ ip6_unregister_protocol (IP_PROTOCOL_IPSEC_ESP);
+ }
+}
+
static void
ipsec_tun_protect_add_adj (adj_index_t ai, index_t sai)
{
@@ -208,14 +245,7 @@ ipsec_tun_protect_rx_db_add (ipsec_main_t * im,
.spi = clib_host_to_net_u32 (sa->spi),
};
hash_set (im->tun4_protect_by_key, key.as_u64, res.as_u64);
- if (1 == hash_elts(im->tun4_protect_by_key))
- {
- udp_register_dst_port (vlib_get_main(),
- UDP_DST_PORT_ipsec,
- ipsec4_tun_input_node.index, 1);
- ip4_register_protocol (IP_PROTOCOL_IPSEC_ESP,
- ipsec4_tun_input_node.index);
- }
+ ipsec_tun_register_nodes(AF_IP4);
}
else
{
@@ -224,10 +254,7 @@ ipsec_tun_protect_rx_db_add (ipsec_main_t * im,
.spi = clib_host_to_net_u32 (sa->spi),
};
hash_set_mem_alloc (&im->tun6_protect_by_key, &key, res.as_u64);
-
- if (1 == hash_elts (im->tun6_protect_by_key))
- ip6_register_protocol (IP_PROTOCOL_IPSEC_ESP,
- ipsec6_tun_input_node.index);
+ ipsec_tun_register_nodes(AF_IP6);
}
}))
/* *INDENT-ON* */
@@ -295,6 +322,9 @@ ipsec_tun_protect_tx_db_add (ipsec_tun_protect_t * itp)
adj_nbr_walk_nh (itp->itp_sw_if_index,
nh_proto, &nh, ipsec_tun_protect_adj_add, itp);
+
+ ipsec_tun_register_nodes (FIB_PROTOCOL_IP6 == nh_proto ?
+ AF_IP6 : AF_IP4);
}
}
@@ -313,11 +343,11 @@ ipsec_tun_protect_rx_db_remove (ipsec_main_t * im,
.remote_ip = itp->itp_crypto.dst.ip4,
.spi = clib_host_to_net_u32 (sa->spi),
};
- hash_unset (im->tun4_protect_by_key, key.as_u64);
- if (0 == hash_elts(im->tun4_protect_by_key))
- udp_unregister_dst_port (vlib_get_main(),
- UDP_DST_PORT_ipsec,
- 1);
+ if (hash_get(im->tun4_protect_by_key, key.as_u64))
+ {
+ hash_unset (im->tun4_protect_by_key, key.as_u64);
+ ipsec_tun_unregister_nodes(AF_IP4);
+ }
}
else
{
@@ -325,7 +355,11 @@ ipsec_tun_protect_rx_db_remove (ipsec_main_t * im,
.remote_ip = itp->itp_crypto.dst.ip6,
.spi = clib_host_to_net_u32 (sa->spi),
};
- hash_unset_mem_free (&im->tun6_protect_by_key, &key);
+ if (hash_get_mem(im->tun6_protect_by_key, &key))
+ {
+ hash_unset_mem_free (&im->tun6_protect_by_key, &key);
+ ipsec_tun_unregister_nodes(AF_IP6);
+ }
}
}))
/* *INDENT-ON* */
@@ -372,6 +406,8 @@ ipsec_tun_protect_tx_db_remove (ipsec_tun_protect_t * itp)
hash_free (idi->id_hash);
idi->id_hash = NULL;
}
+ ipsec_tun_unregister_nodes (FIB_PROTOCOL_IP6 == nh_proto ?
+ AF_IP6 : AF_IP4);
}
}
@@ -732,11 +768,6 @@ ipsec_tun_protect_del (u32 sw_if_index, const ip_address_t * nh)
clib_mem_free (itp->itp_key);
pool_put (ipsec_tun_protect_pool, itp);
- if (0 == hash_elts (im->tun4_protect_by_key))
- ip4_unregister_protocol (IP_PROTOCOL_IPSEC_ESP);
- if (0 == hash_elts (im->tun6_protect_by_key))
- ip6_unregister_protocol (IP_PROTOCOL_IPSEC_ESP);
-
return (0);
}
diff --git a/src/vnet/ipsec/ipsec_tun.h b/src/vnet/ipsec/ipsec_tun.h
index 56d3de14704..863afdbba5a 100644
--- a/src/vnet/ipsec/ipsec_tun.h
+++ b/src/vnet/ipsec/ipsec_tun.h
@@ -121,6 +121,9 @@ extern void ipsec_tun_protect_walk_itf (u32 sw_if_index,
extern u8 *format_ipsec_tun_protect (u8 * s, va_list * args);
extern u8 *format_ipsec_tun_protect_index (u8 * s, va_list * args);
+extern void ipsec_tun_register_nodes (ip_address_family_t af);
+extern void ipsec_tun_unregister_nodes (ip_address_family_t af);
+
// FIXME
extern vlib_node_registration_t ipsec4_tun_input_node;
extern vlib_node_registration_t ipsec6_tun_input_node;