summaryrefslogtreecommitdiffstats
path: root/src/vnet/ip/punt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ip/punt.c')
-rw-r--r--src/vnet/ip/punt.c132
1 files changed, 115 insertions, 17 deletions
diff --git a/src/vnet/ip/punt.c b/src/vnet/ip/punt.c
index d4d502887d7..296df59b615 100644
--- a/src/vnet/ip/punt.c
+++ b/src/vnet/ip/punt.c
@@ -75,6 +75,36 @@ punt_client_l4_db_remove (ip_address_family_t af, u16 port)
}
static void
+punt_client_ip_proto_db_add (ip_address_family_t af,
+ ip_protocol_t proto, u32 index)
+{
+ punt_main_t *pm = &punt_main;
+
+ pm->db.clients_by_ip_proto = hash_set (pm->db.clients_by_ip_proto,
+ punt_client_ip_proto_mk_key (af,
+ proto),
+ index);
+}
+
+static u32
+punt_client_ip_proto_db_remove (ip_address_family_t af, ip_protocol_t proto)
+{
+ punt_main_t *pm = &punt_main;
+ u32 key, index = ~0;
+ uword *p;
+
+ key = punt_client_ip_proto_mk_key (af, proto);
+ p = hash_get (pm->db.clients_by_ip_proto, key);
+
+ if (p)
+ index = p[0];
+
+ hash_unset (pm->db.clients_by_ip_proto, key);
+
+ return (index);
+}
+
+static void
punt_client_exception_db_add (vlib_punt_reason_t reason, u32 pci)
{
punt_main_t *pm = &punt_main;
@@ -129,12 +159,6 @@ punt_socket_register_l4 (vlib_main_t * vm,
if (port == (u16) ~ 0)
return clib_error_return (0, "UDP port number required");
- if (strncmp (client_pathname, vnet_punt_get_server_pathname (),
- UNIX_PATH_MAX) == 0)
- return clib_error_return (0,
- "Punt socket: Invalid client path: %s",
- client_pathname);
-
c = punt_client_l4_get (af, port);
if (NULL == c)
@@ -160,6 +184,36 @@ punt_socket_register_l4 (vlib_main_t * vm,
}
static clib_error_t *
+punt_socket_register_ip_proto (vlib_main_t * vm,
+ ip_address_family_t af,
+ ip_protocol_t proto, char *client_pathname)
+{
+ punt_main_t *pm = &punt_main;
+ punt_client_t *c;
+
+ c = punt_client_ip_proto_get (af, proto);
+
+ if (NULL == c)
+ {
+ pool_get_zero (pm->punt_client_pool, c);
+ punt_client_ip_proto_db_add (af, proto, c - pm->punt_client_pool);
+ }
+
+ memcpy (c->caddr.sun_path, client_pathname, sizeof (c->caddr.sun_path));
+ c->caddr.sun_family = AF_UNIX;
+ c->reg.type = PUNT_TYPE_IP_PROTO;
+ c->reg.punt.ip_proto.protocol = proto;
+ c->reg.punt.ip_proto.af = af;
+
+ if (af == AF_IP4)
+ ip4_register_protocol (proto, ip4_proto_punt_socket_node.index);
+ else
+ ip6_register_protocol (proto, ip6_proto_punt_socket_node.index);
+
+ return (NULL);
+}
+
+static clib_error_t *
punt_socket_register_exception (vlib_main_t * vm,
vlib_punt_reason_t reason,
char *client_pathname)
@@ -203,6 +257,24 @@ punt_socket_unregister_l4 (ip_address_family_t af,
}
static clib_error_t *
+punt_socket_unregister_ip_proto (ip_address_family_t af, ip_protocol_t proto)
+{
+ u32 pci;
+
+ if (af == AF_IP4)
+ ip4_unregister_protocol (proto);
+ else
+ ip6_unregister_protocol (proto);
+
+ pci = punt_client_ip_proto_db_remove (af, proto);
+
+ if (~0 != pci)
+ pool_put_index (punt_main.punt_client_pool, pci);
+
+ return (NULL);
+}
+
+static clib_error_t *
punt_socket_unregister_exception (vlib_punt_reason_t reason)
{
u32 pci;
@@ -227,6 +299,12 @@ vnet_punt_socket_add (vlib_main_t * vm, u32 header_version,
if (header_version != PUNT_PACKETDESC_VERSION)
return clib_error_return (0, "Invalid packet descriptor version");
+ if (strncmp (client_pathname, vnet_punt_get_server_pathname (),
+ UNIX_PATH_MAX) == 0)
+ return clib_error_return (0,
+ "Punt socket: Invalid client path: %s",
+ client_pathname);
+
/* Register client */
switch (pr->type)
{
@@ -235,6 +313,11 @@ vnet_punt_socket_add (vlib_main_t * vm, u32 header_version,
pr->punt.l4.af,
pr->punt.l4.protocol,
pr->punt.l4.port, client_pathname));
+ case PUNT_TYPE_IP_PROTO:
+ return (punt_socket_register_ip_proto (vm,
+ pr->punt.ip_proto.af,
+ pr->punt.ip_proto.protocol,
+ client_pathname));
case PUNT_TYPE_EXCEPTION:
return (punt_socket_register_exception (vm,
pr->punt.exception.reason,
@@ -258,6 +341,9 @@ vnet_punt_socket_del (vlib_main_t * vm, const punt_reg_t * pr)
return (punt_socket_unregister_l4 (pr->punt.l4.af,
pr->punt.l4.protocol,
pr->punt.l4.port));
+ case PUNT_TYPE_IP_PROTO:
+ return (punt_socket_unregister_ip_proto (pr->punt.ip_proto.af,
+ pr->punt.ip_proto.protocol));
case PUNT_TYPE_EXCEPTION:
return (punt_socket_unregister_exception (pr->punt.exception.reason));
}
@@ -330,13 +416,6 @@ punt_l4_add_del (vlib_main_t * vm,
}
}
-static clib_error_t *
-punt_exception_add_del (vlib_main_t * vm,
- vlib_punt_reason_t reason, bool is_add)
-{
- return (NULL);
-}
-
clib_error_t *
vnet_punt_add_del (vlib_main_t * vm, const punt_reg_t * pr, bool is_add)
{
@@ -346,7 +425,8 @@ vnet_punt_add_del (vlib_main_t * vm, const punt_reg_t * pr, bool is_add)
return (punt_l4_add_del (vm, pr->punt.l4.af, pr->punt.l4.protocol,
pr->punt.l4.port, is_add));
case PUNT_TYPE_EXCEPTION:
- return (punt_exception_add_del (vm, pr->punt.exception.reason, is_add));
+ case PUNT_TYPE_IP_PROTO:
+ break;
}
return (clib_error_return (0, "Unsupported punt type: %d", pr->type));
@@ -560,11 +640,22 @@ punt_client_walk (punt_type_t pt, punt_client_walk_cb_t cb, void *ctx)
{
case PUNT_TYPE_L4:
{
- u32 pci;
- u16 port;
+ u32 pci, key;
/* *INDENT-OFF* */
- hash_foreach(port, pci, pm->db.clients_by_l4_port,
+ hash_foreach(key, pci, pm->db.clients_by_l4_port,
+ ({
+ cb (pool_elt_at_index(pm->punt_client_pool, pci), ctx);
+ }));
+ /* *INDENT-ON* */
+ break;
+ }
+ case PUNT_TYPE_IP_PROTO:
+ {
+ u32 pci, key;
+
+ /* *INDENT-OFF* */
+ hash_foreach(key, pci, pm->db.clients_by_ip_proto,
({
cb (pool_elt_at_index(pm->punt_client_pool, pci), ctx);
}));
@@ -601,6 +692,11 @@ format_punt_client (u8 * s, va_list * args)
format_ip_protocol, pc->reg.punt.l4.protocol,
pc->reg.punt.l4.port);
break;
+ case PUNT_TYPE_IP_PROTO:
+ s = format (s, "%U %U",
+ format_ip_address_family, pc->reg.punt.ip_proto.af,
+ format_ip_protocol, pc->reg.punt.ip_proto.protocol);
+ break;
case PUNT_TYPE_EXCEPTION:
s = format (s, " %U", format_vlib_punt_reason,
pc->reg.punt.exception.reason);
@@ -635,6 +731,8 @@ punt_socket_show_cmd (vlib_main_t * vm,
pt = PUNT_TYPE_EXCEPTION;
else if (unformat (input, "l4"))
pt = PUNT_TYPE_L4;
+ else if (unformat (input, "ip"))
+ pt = PUNT_TYPE_IP_PROTO;
else
{
error = clib_error_return (0, "parse error: '%U'",