aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vnet/ip/ip4.h1
-rw-r--r--src/vnet/ip/ip4_forward.c14
-rw-r--r--src/vnet/ip/ip6.h1
-rw-r--r--src/vnet/ip/ip6_forward.c10
-rw-r--r--src/vnet/ip/ip_types.api2
-rw-r--r--src/vnet/ip/ip_types_api.c25
-rw-r--r--src/vnet/ip/punt.api13
-rw-r--r--src/vnet/ip/punt.c132
-rw-r--r--src/vnet/ip/punt.h39
-rw-r--r--src/vnet/ip/punt_api.c26
-rw-r--r--src/vnet/ip/punt_node.c57
11 files changed, 282 insertions, 38 deletions
diff --git a/src/vnet/ip/ip4.h b/src/vnet/ip/ip4.h
index 5c9add4c796..9f25f43b98e 100644
--- a/src/vnet/ip/ip4.h
+++ b/src/vnet/ip/ip4.h
@@ -288,6 +288,7 @@ u16 ip4_tcp_udp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
ip4_header_t * ip0);
void ip4_register_protocol (u32 protocol, u32 node_index);
+void ip4_unregister_protocol (u32 protocolx);
serialize_function_t serialize_vnet_ip4_main, unserialize_vnet_ip4_main;
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index 9c5524f17a0..43213fe8ace 100644
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -1679,6 +1679,16 @@ ip4_register_protocol (u32 protocol, u32 node_index)
lm->local_next_by_ip_protocol[protocol] =
vlib_node_add_next (vm, ip4_local_node.index, node_index);
}
+
+void
+ip4_unregister_protocol (u32 protocol)
+{
+ ip4_main_t *im = &ip4_main;
+ ip_lookup_main_t *lm = &im->lookup_main;
+
+ ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol));
+ lm->local_next_by_ip_protocol[protocol] = IP_LOCAL_NEXT_PUNT;
+}
#endif
static clib_error_t *
@@ -1697,8 +1707,8 @@ show_ip_local_command_fn (vlib_main_t * vm,
u32 node_index = vlib_get_node (vm,
ip4_local_node.index)->
next_nodes[lm->local_next_by_ip_protocol[i]];
- vlib_cli_output (vm, "%d: %U", i, format_vlib_node_name, vm,
- node_index);
+ vlib_cli_output (vm, "%U: %U", format_ip_protocol, i,
+ format_vlib_node_name, vm, node_index);
}
}
return 0;
diff --git a/src/vnet/ip/ip6.h b/src/vnet/ip/ip6.h
index e66bbdd0827..b511cccbaa7 100644
--- a/src/vnet/ip/ip6.h
+++ b/src/vnet/ip/ip6.h
@@ -388,6 +388,7 @@ u16 ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
int *bogus_lengthp);
void ip6_register_protocol (u32 protocol, u32 node_index);
+void ip6_unregister_protocol (u32 protocol);
void ip6_local_hop_by_hop_register_protocol (u32 protocol, u32 node_index);
serialize_function_t serialize_vnet_ip6_main, unserialize_vnet_ip6_main;
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 74f51fa912f..b6eae6e3811 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -1433,6 +1433,16 @@ ip6_register_protocol (u32 protocol, u32 node_index)
vlib_node_add_next (vm, ip6_local_node.index, node_index);
}
+void
+ip6_unregister_protocol (u32 protocol)
+{
+ ip6_main_t *im = &ip6_main;
+ ip_lookup_main_t *lm = &im->lookup_main;
+
+ ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol));
+ lm->local_next_by_ip_protocol[protocol] = IP_LOCAL_NEXT_PUNT;
+}
+
clib_error_t *
ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index,
u8 refresh)
diff --git a/src/vnet/ip/ip_types.api b/src/vnet/ip/ip_types.api
index a9e66470665..4c685670d5e 100644
--- a/src/vnet/ip/ip_types.api
+++ b/src/vnet/ip/ip_types.api
@@ -25,6 +25,8 @@ enum address_family {
enum ip_proto {
IP_API_PROTO_TCP = 6,
IP_API_PROTO_UDP = 17,
+ IP_API_PROTO_EIGRP = 88,
+ IP_API_PROTO_OSPF = 89,
};
union address_union {
diff --git a/src/vnet/ip/ip_types_api.c b/src/vnet/ip/ip_types_api.c
index d84c1ff9126..fd8d24f36fe 100644
--- a/src/vnet/ip/ip_types_api.c
+++ b/src/vnet/ip/ip_types_api.c
@@ -65,16 +65,16 @@ ip_address_family_encode (ip_address_family_t af)
int
ip_proto_decode (int _ipp, ip_protocol_t * out)
{
- vl_api_ip_proto_t ipp = clib_host_to_net_u32 (_ipp);
+ ip_protocol_t ipp = clib_host_to_net_u32 (_ipp);
switch (ipp)
{
- case IP_API_PROTO_TCP:
- *out = IP_PROTOCOL_TCP;
- return (0);
- case IP_API_PROTO_UDP:
- *out = IP_PROTOCOL_UDP;
- return (0);
+#define ip_protocol(n,s) \
+ case IP_PROTOCOL_##s: \
+ *out = IP_PROTOCOL_##s; \
+ return (0);
+#include "protocols.def"
+#undef ip_protocol
}
return (-1);
}
@@ -84,12 +84,11 @@ ip_proto_encode (ip_protocol_t ipp)
{
switch (ipp)
{
- case IP_PROTOCOL_UDP:
- return (clib_host_to_net_u32 (IP_API_PROTO_UDP));
- case IP_PROTOCOL_TCP:
- return (clib_host_to_net_u32 (IP_API_PROTO_TCP));
- default:
- break;
+#define ip_protocol(n,s) \
+ case IP_PROTOCOL_##s: \
+ return (clib_host_to_net_u32 (IP_PROTOCOL_##s));
+#include "protocols.def"
+#undef ip_protocol
}
ASSERT (0);
diff --git a/src/vnet/ip/punt.api b/src/vnet/ip/punt.api
index cedddc5601d..6cb27311726 100644
--- a/src/vnet/ip/punt.api
+++ b/src/vnet/ip/punt.api
@@ -22,6 +22,8 @@ enum punt_type
{
/* L4 (UDP) packets */
PUNT_API_TYPE_L4,
+ /* IP proto (i.e. OSPF, RIP, etc) packets */
+ PUNT_API_TYPE_IP_PROTO,
/* Exception packets handled by the VLIB punt infra */
PUNT_API_TYPE_EXCEPTION,
};
@@ -38,6 +40,16 @@ typedef punt_l4
u16 port;
};
+/** \brief Punt IP protocol traffic definition
+ @param af - Address Family, IPv4 or IPV6
+ @param protocol - IP protocol to be punted
+*/
+typedef punt_ip_proto
+{
+ vl_api_address_family_t af;
+ vl_api_ip_proto_t protocol;
+};
+
/** \brief The ID of the punt exception reason
Dump all the reasons to obtain this
*/
@@ -52,6 +64,7 @@ union punt_union
{
vl_api_punt_exception_t exception;
vl_api_punt_l4_t l4;
+ vl_api_punt_ip_proto_t ip_proto;
};
/** \brief Full description of which packets are requested to be punted
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'",
diff --git a/src/vnet/ip/punt.h b/src/vnet/ip/punt.h
index a77e6330813..8835f3eb9d9 100644
--- a/src/vnet/ip/punt.h
+++ b/src/vnet/ip/punt.h
@@ -24,9 +24,10 @@
#include <stdbool.h>
#include <vnet/ip/ip.h>
-#define foreach_punt_type \
- _(L4, "l4") \
- _(EXCEPTION, "exception")
+#define foreach_punt_type \
+ _(L4, "l4") \
+ _(EXCEPTION, "exception") \
+ _(IP_PROTO, "ip-proto")
typedef enum punt_type_t_
{
@@ -42,6 +43,12 @@ typedef struct punt_l4_t_
u16 port;
} punt_l4_t;
+typedef struct punt_ip_proto_t_
+{
+ ip_address_family_t af;
+ ip_protocol_t protocol;
+} punt_ip_proto_t;
+
typedef struct punt_exception_t_
{
vlib_punt_reason_t reason;
@@ -51,6 +58,7 @@ typedef struct punt_union_t_
{
punt_exception_t exception;
punt_l4_t l4;
+ punt_ip_proto_t ip_proto;
} punt_union_t;
typedef struct punt_reg_t_
@@ -100,6 +108,7 @@ typedef struct punt_client_db_t_
{
void *clients_by_l4_port;
u32 *clients_by_exception;
+ void *clients_by_ip_proto;
} punt_client_db_t;
typedef struct
@@ -146,6 +155,28 @@ punt_client_l4_get (ip_address_family_t af, u16 port)
return (NULL);
}
+static_always_inline u32
+punt_client_ip_proto_mk_key (ip_address_family_t af, ip_protocol_t proto)
+{
+ return (af << 16 | proto);
+}
+
+static_always_inline punt_client_t *
+punt_client_ip_proto_get (ip_address_family_t af, ip_protocol_t proto)
+{
+ punt_main_t *pm = &punt_main;
+ uword *p;
+
+ p =
+ hash_get (pm->db.clients_by_ip_proto,
+ punt_client_ip_proto_mk_key (af, proto));
+
+ if (p)
+ return (pool_elt_at_index (pm->punt_client_pool, p[0]));
+
+ return (NULL);
+}
+
static_always_inline punt_client_t *
punt_client_exception_get (vlib_punt_reason_t reason)
{
@@ -167,6 +198,8 @@ extern vlib_node_registration_t udp4_punt_node;
extern vlib_node_registration_t udp6_punt_node;
extern vlib_node_registration_t udp4_punt_socket_node;
extern vlib_node_registration_t udp6_punt_socket_node;
+extern vlib_node_registration_t ip4_proto_punt_socket_node;
+extern vlib_node_registration_t ip6_proto_punt_socket_node;
extern vlib_node_registration_t punt_socket_rx_node;
#endif
diff --git a/src/vnet/ip/punt_api.c b/src/vnet/ip/punt_api.c
index 95fff714b46..b356886a56f 100644
--- a/src/vnet/ip/punt_api.c
+++ b/src/vnet/ip/punt_api.c
@@ -96,6 +96,18 @@ vl_api_punt_l4_decode (const vl_api_punt_l4_t * in, punt_l4_t * out)
}
static int
+vl_api_punt_ip_proto_decode (const vl_api_punt_ip_proto_t * in,
+ punt_ip_proto_t * out)
+{
+ int rv;
+
+ rv = ip_address_family_decode (in->af, &out->af);
+ rv += ip_proto_decode (in->protocol, &out->protocol);
+
+ return (rv);
+}
+
+static int
vl_api_punt_exception_decode (const vl_api_punt_exception_t * in,
punt_exception_t * out)
{
@@ -124,6 +136,9 @@ vl_api_punt_decode (const vl_api_punt_t * in, punt_reg_t * out)
case PUNT_TYPE_EXCEPTION:
return (vl_api_punt_exception_decode (&in->punt.exception,
&out->punt.exception));
+ case PUNT_TYPE_IP_PROTO:
+ return (vl_api_punt_ip_proto_decode (&in->punt.ip_proto,
+ &out->punt.ip_proto));
}
return (-1);
@@ -138,6 +153,14 @@ vl_api_punt_l4_encode (const punt_l4_t * in, vl_api_punt_l4_t * out)
}
static void
+vl_api_punt_ip_proto_encode (const punt_ip_proto_t * in,
+ vl_api_punt_ip_proto_t * out)
+{
+ out->af = ip_address_family_encode (in->af);
+ out->protocol = ip_proto_encode (in->protocol);
+}
+
+static void
vl_api_punt_exception_encode (const punt_exception_t * in,
vl_api_punt_exception_t * out)
{
@@ -154,6 +177,9 @@ vl_api_punt_encode (const punt_reg_t * in, vl_api_punt_t * out)
case PUNT_TYPE_L4:
vl_api_punt_l4_encode (&in->punt.l4, &out->punt.l4);
break;
+ case PUNT_TYPE_IP_PROTO:
+ vl_api_punt_ip_proto_encode (&in->punt.ip_proto, &out->punt.ip_proto);
+ break;
case PUNT_TYPE_EXCEPTION:
vl_api_punt_exception_encode (&in->punt.exception,
&out->punt.exception);
diff --git a/src/vnet/ip/punt_node.c b/src/vnet/ip/punt_node.c
index 53c8199342b..67f97431c19 100644
--- a/src/vnet/ip/punt_node.c
+++ b/src/vnet/ip/punt_node.c
@@ -286,13 +286,29 @@ punt_socket_inline (vlib_main_t * vm,
udp = (udp_header_t *) (ip + 1);
}
- u16 port = clib_net_to_host_u16 (udp->dst_port);
-
/*
* Find registerered client
* If no registered client, drop packet and count
*/
- c = punt_client_l4_get (af, port);
+ c = punt_client_l4_get (af, clib_net_to_host_u16 (udp->dst_port));
+ }
+ else if (PUNT_TYPE_IP_PROTO == pt)
+ {
+ /* Reverse UDP Punt advance */
+ ip_protocol_t proto;
+
+ if (AF_IP4 == af)
+ {
+ ip4_header_t *ip = vlib_buffer_get_current (b);
+ proto = ip->protocol;
+ }
+ else
+ {
+ ip6_header_t *ip = vlib_buffer_get_current (b);
+ proto = ip->protocol;
+ }
+
+ c = punt_client_ip_proto_get (af, proto);
}
else if (PUNT_TYPE_EXCEPTION == pt)
{
@@ -391,6 +407,22 @@ udp6_punt_socket (vlib_main_t * vm,
}
static uword
+ip4_proto_punt_socket (vlib_main_t * vm,
+ vlib_node_runtime_t * node, vlib_frame_t * from_frame)
+{
+ return punt_socket_inline (vm, node, from_frame,
+ PUNT_TYPE_IP_PROTO, AF_IP4);
+}
+
+static uword
+ip6_proto_punt_socket (vlib_main_t * vm,
+ vlib_node_runtime_t * node, vlib_frame_t * from_frame)
+{
+ return punt_socket_inline (vm, node, from_frame,
+ PUNT_TYPE_IP_PROTO, AF_IP6);
+}
+
+static uword
exception_punt_socket (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * from_frame)
{
@@ -419,6 +451,25 @@ VLIB_REGISTER_NODE (udp6_punt_socket_node) = {
.n_errors = PUNT_N_ERROR,
.error_strings = punt_error_strings,
};
+VLIB_REGISTER_NODE (ip4_proto_punt_socket_node) = {
+ .function = ip4_proto_punt_socket,
+ .name = "ip4-proto-punt-socket",
+ .format_trace = format_udp_punt_trace,
+ .flags = VLIB_NODE_FLAG_IS_DROP,
+ /* Takes a vector of packets. */
+ .vector_size = sizeof (u32),
+ .n_errors = PUNT_N_ERROR,
+ .error_strings = punt_error_strings,
+};
+VLIB_REGISTER_NODE (ip6_proto_punt_socket_node) = {
+ .function = ip6_proto_punt_socket,
+ .name = "ip6-proto-punt-socket",
+ .format_trace = format_udp_punt_trace,
+ .flags = VLIB_NODE_FLAG_IS_DROP,
+ .vector_size = sizeof (u32),
+ .n_errors = PUNT_N_ERROR,
+ .error_strings = punt_error_strings,
+};
VLIB_REGISTER_NODE (exception_punt_socket_node) = {
.function = exception_punt_socket,
.name = "exception-punt-socket",