Punt: specify packets by IP protocol Type
Change-Id: I0c2d6fccd95146e52bb88ca4a6e84554d5d6b2ed Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -74,6 +74,36 @@ punt_client_l4_db_remove (ip_address_family_t af, u16 port)
|
||||
return (index);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
@ -159,6 +183,36 @@ punt_socket_register_l4 (vlib_main_t * vm,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
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,
|
||||
@ -202,6 +256,24 @@ punt_socket_unregister_l4 (ip_address_family_t af,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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'",
|
||||
|
@ -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
|
||||
|
@ -95,6 +95,18 @@ vl_api_punt_l4_decode (const vl_api_punt_l4_t * in, punt_l4_t * out)
|
||||
return (rv);
|
||||
}
|
||||
|
||||
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);
|
||||
@ -137,6 +152,14 @@ vl_api_punt_l4_encode (const punt_l4_t * in, vl_api_punt_l4_t * out)
|
||||
out->port = clib_net_to_host_u16 (in->port);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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)
|
||||
{
|
||||
@ -390,6 +406,22 @@ udp6_punt_socket (vlib_main_t * vm,
|
||||
return punt_socket_inline (vm, node, from_frame, PUNT_TYPE_L4, AF_IP6);
|
||||
}
|
||||
|
||||
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",
|
||||
|
@ -22,6 +22,7 @@ from scapy.layers.inet import IP, UDP, ICMP
|
||||
from scapy.layers.ipsec import ESP
|
||||
import scapy.layers.inet6 as inet6
|
||||
from scapy.layers.inet6 import IPv6, ICMPv6DestUnreach
|
||||
from scapy.contrib.ospf import OSPF_Hdr, OSPFv3_Hello
|
||||
import six
|
||||
from framework import VppTestCase, VppTestRunner
|
||||
|
||||
@ -130,6 +131,13 @@ class TestPuntSocket(VppTestCase):
|
||||
self.assertEqual(vpr.punt.punt.exception.id,
|
||||
pr['punt']['exception']['id'])
|
||||
|
||||
def verify_ip_proto(self, pr, vpr):
|
||||
self.assertEqual(vpr.punt.type, pr['type'])
|
||||
self.assertEqual(vpr.punt.punt.ip_proto.af,
|
||||
pr['punt']['ip_proto']['af'])
|
||||
self.assertEqual(vpr.punt.punt.ip_proto.protocol,
|
||||
pr['punt']['ip_proto']['protocol'])
|
||||
|
||||
def verify_udp_pkts(self, rxs, n_rx, port):
|
||||
n_match = 0
|
||||
for rx in rxs:
|
||||
@ -182,7 +190,7 @@ def mk_vpp_cfg6():
|
||||
|
||||
|
||||
class TestIP4PuntSocket(TestPuntSocket):
|
||||
""" Punt Socket for IPv4 """
|
||||
""" Punt Socket for IPv4 UDP """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@ -409,7 +417,7 @@ class TestIP4PuntSocket(TestPuntSocket):
|
||||
|
||||
|
||||
class TestIP6PuntSocket(TestPuntSocket):
|
||||
""" Punt Socket for IPv6"""
|
||||
""" Punt Socket for IPv6 UDP """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@ -850,8 +858,157 @@ class TestExceptionPuntSocket(TestPuntSocket):
|
||||
self.vapi.punt_socket_deregister(cfg['vpp'])
|
||||
|
||||
|
||||
class TestIpProtoPuntSocket(TestPuntSocket):
|
||||
""" Punt Socket for IP packets """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestIpProtoPuntSocket, cls).setUpClass()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(TestIpProtoPuntSocket, cls).tearDownClass()
|
||||
|
||||
def setUp(self):
|
||||
super(TestIpProtoPuntSocket, self).setUp()
|
||||
|
||||
for i in self.pg_interfaces:
|
||||
i.config_ip4()
|
||||
i.resolve_arp()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestIpProtoPuntSocket, self).tearDown()
|
||||
for i in self.pg_interfaces:
|
||||
i.unconfig_ip4()
|
||||
i.admin_down()
|
||||
|
||||
def test_registration(self):
|
||||
""" Punt socket registration/deregistration"""
|
||||
|
||||
af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
|
||||
pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
|
||||
proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
|
||||
proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
|
||||
|
||||
punts = self.vapi.punt_socket_dump(type=pt_ip)
|
||||
self.assertEqual(len(punts), 0)
|
||||
|
||||
#
|
||||
# configure a punt socket
|
||||
#
|
||||
punt_ospf = {
|
||||
'type': pt_ip,
|
||||
'punt': {
|
||||
'ip_proto': {
|
||||
'af': af_ip4,
|
||||
'protocol': proto_ospf
|
||||
}
|
||||
}
|
||||
}
|
||||
punt_eigrp = {
|
||||
'type': pt_ip,
|
||||
'punt': {
|
||||
'ip_proto': {
|
||||
'af': af_ip4,
|
||||
'protocol': proto_eigrp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.vapi.punt_socket_register(punt_ospf,
|
||||
b"%s/socket_punt_1" %
|
||||
six.ensure_binary(self.tempdir))
|
||||
self.vapi.punt_socket_register(punt_eigrp,
|
||||
b"%s/socket_punt_2" %
|
||||
six.ensure_binary(self.tempdir))
|
||||
self.logger.info(self.vapi.cli("sh punt sock reg ip"))
|
||||
punts = self.vapi.punt_socket_dump(type=pt_ip)
|
||||
self.assertEqual(len(punts), 2)
|
||||
self.verify_ip_proto(punt_ospf, punts[0])
|
||||
self.verify_ip_proto(punt_eigrp, punts[1])
|
||||
|
||||
#
|
||||
# deregister a punt socket
|
||||
#
|
||||
self.vapi.punt_socket_deregister(punt_ospf)
|
||||
punts = self.vapi.punt_socket_dump(type=pt_ip)
|
||||
self.assertEqual(len(punts), 1)
|
||||
|
||||
#
|
||||
# configure a punt socket again
|
||||
#
|
||||
self.vapi.punt_socket_register(punt_ospf,
|
||||
b"%s/socket_punt_3" %
|
||||
six.ensure_binary(self.tempdir))
|
||||
punts = self.vapi.punt_socket_dump(type=pt_ip)
|
||||
self.assertEqual(len(punts), 2)
|
||||
|
||||
self.logger.info(self.vapi.cli("sh punt sock reg exception"))
|
||||
|
||||
#
|
||||
# deregister all punt socket
|
||||
#
|
||||
self.vapi.punt_socket_deregister(punt_eigrp)
|
||||
self.vapi.punt_socket_deregister(punt_ospf)
|
||||
punts = self.vapi.punt_socket_dump(type=pt_ip)
|
||||
self.assertEqual(len(punts), 0)
|
||||
|
||||
def verify_ospf_pkts(self, rxs, n_sent):
|
||||
self.assertEqual(len(rxs), n_sent)
|
||||
for rx in rxs:
|
||||
self.assertTrue(rx.haslayer(OSPF_Hdr))
|
||||
|
||||
def test_traffic(self):
|
||||
""" Punt socket traffic """
|
||||
|
||||
af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
|
||||
pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
|
||||
proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
|
||||
|
||||
#
|
||||
# configure a punt socket to capture OSPF packets
|
||||
#
|
||||
punt_ospf = {
|
||||
'type': pt_ip,
|
||||
'punt': {
|
||||
'ip_proto': {
|
||||
'af': af_ip4,
|
||||
'protocol': proto_ospf
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# create packet streams and configure a punt sockets
|
||||
#
|
||||
pkt = (Ether(src=self.pg0.remote_mac,
|
||||
dst=self.pg0.local_mac) /
|
||||
IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
|
||||
OSPF_Hdr() /
|
||||
OSPFv3_Hello())
|
||||
pkts = pkt * 7
|
||||
|
||||
sock = self.socket_client_create(b"%s/socket_1" % (
|
||||
six.ensure_binary(self.tempdir)))
|
||||
self.vapi.punt_socket_register(
|
||||
punt_ospf,
|
||||
b"%s/socket_1" % (six.ensure_binary(self.tempdir)))
|
||||
|
||||
#
|
||||
# send packets for each SPI we expect to be punted
|
||||
#
|
||||
self.send_and_assert_no_replies(self.pg0, pkts)
|
||||
|
||||
#
|
||||
# verify the punted packets arrived on the associated socket
|
||||
#
|
||||
rx = sock.close()
|
||||
self.verify_ospf_pkts(rx, len(pkts))
|
||||
self.vapi.punt_socket_deregister(punt_ospf)
|
||||
|
||||
|
||||
class TestPunt(VppTestCase):
|
||||
""" Punt Test Case """
|
||||
""" Exception Punt Test Case """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
Reference in New Issue
Block a user