aboutsummaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
authorJuraj Sloboda <jsloboda@cisco.com>2016-08-07 23:46:45 -0700
committerDamjan Marion <dmarion.lists@gmail.com>2016-10-10 20:51:28 +0000
commit51ffa817d910ba058cd76f2b7dd9a4142944f2ee (patch)
tree826ab211ee1e1f330694bb1ce430d11044228e5b /vnet
parent506b24564d32c7aca58055a710eba64ed942c1c4 (diff)
ipfix: add l4 unformat support for mask and match (VPP-204)
Change-Id: Iff32c488af9b71acbc4e572c6741afae0a67333c Signed-off-by: Juraj Sloboda <jsloboda@cisco.com>
Diffstat (limited to 'vnet')
-rw-r--r--vnet/vnet/classify/vnet_classify.c199
-rw-r--r--vnet/vnet/ip/tcp_packet.h13
2 files changed, 201 insertions, 11 deletions
diff --git a/vnet/vnet/classify/vnet_classify.c b/vnet/vnet/classify/vnet_classify.c
index ff7945920b9..a9d60494ca3 100644
--- a/vnet/vnet/classify/vnet_classify.c
+++ b/vnet/vnet/classify/vnet_classify.c
@@ -678,6 +678,14 @@ int vnet_classify_add_del_table (vnet_classify_main_t * cm,
return 0;
}
+#define foreach_tcp_proto_field \
+_(src_port) \
+_(dst_port)
+
+#define foreach_udp_proto_field \
+_(src_port) \
+_(dst_port)
+
#define foreach_ip4_proto_field \
_(src_address) \
_(dst_address) \
@@ -688,6 +696,125 @@ _(ttl) \
_(protocol) \
_(checksum)
+uword unformat_tcp_mask (unformat_input_t * input, va_list * args)
+{
+ u8 ** maskp = va_arg (*args, u8 **);
+ u8 * mask = 0;
+ u8 found_something = 0;
+ tcp_header_t * tcp;
+
+#define _(a) u8 a=0;
+ foreach_tcp_proto_field;
+#undef _
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (0) ;
+#define _(a) else if (unformat (input, #a)) a=1;
+ foreach_tcp_proto_field
+#undef _
+ else
+ break;
+ }
+
+#define _(a) found_something += a;
+ foreach_tcp_proto_field;
+#undef _
+
+ if (found_something == 0)
+ return 0;
+
+ vec_validate (mask, sizeof (*tcp) - 1);
+
+ tcp = (tcp_header_t *) mask;
+
+#define _(a) if (a) memset (&tcp->a, 0xff, sizeof (tcp->a));
+ foreach_tcp_proto_field;
+#undef _
+
+ *maskp = mask;
+ return 1;
+}
+
+uword unformat_udp_mask (unformat_input_t * input, va_list * args)
+{
+ u8 ** maskp = va_arg (*args, u8 **);
+ u8 * mask = 0;
+ u8 found_something = 0;
+ udp_header_t * udp;
+
+#define _(a) u8 a=0;
+ foreach_udp_proto_field;
+#undef _
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (0) ;
+#define _(a) else if (unformat (input, #a)) a=1;
+ foreach_udp_proto_field
+#undef _
+ else
+ break;
+ }
+
+#define _(a) found_something += a;
+ foreach_udp_proto_field;
+#undef _
+
+ if (found_something == 0)
+ return 0;
+
+ vec_validate (mask, sizeof (*udp) - 1);
+
+ udp = (udp_header_t *) mask;
+
+#define _(a) if (a) memset (&udp->a, 0xff, sizeof (udp->a));
+ foreach_udp_proto_field;
+#undef _
+
+ *maskp = mask;
+ return 1;
+}
+
+typedef struct {
+ u16 src_port, dst_port;
+} tcpudp_header_t;
+
+uword unformat_l4_mask (unformat_input_t * input, va_list * args)
+{
+ u8 ** maskp = va_arg (*args, u8 **);
+ u16 src_port = 0, dst_port = 0;
+ tcpudp_header_t * tcpudp;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
+ return 1;
+ else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
+ return 1;
+ else if (unformat (input, "src_port"))
+ src_port = 0xFFFF;
+ else if (unformat (input, "dst_port"))
+ dst_port = 0xFFFF;
+ else
+ return 0;
+ }
+
+ if (!src_port && !dst_port)
+ return 0;
+
+ u8 * mask = 0;
+ vec_validate (mask, sizeof (tcpudp_header_t) - 1);
+
+ tcpudp = (tcpudp_header_t *) mask;
+ tcpudp->src_port = src_port;
+ tcpudp->dst_port = dst_port;
+
+ *maskp = mask;
+
+ return 1;
+}
+
uword unformat_ip4_mask (unformat_input_t * input, va_list * args)
{
u8 ** maskp = va_arg (*args, u8 **);
@@ -959,6 +1086,7 @@ uword unformat_classify_mask (unformat_input_t * input, va_list * args)
u8 * mask = 0;
u8 * l2 = 0;
u8 * l3 = 0;
+ u8 * l4 = 0;
int i;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
@@ -968,13 +1096,22 @@ uword unformat_classify_mask (unformat_input_t * input, va_list * args)
;
else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
;
+ else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
+ ;
else
break;
}
- if (mask || l2 || l3)
+ if (l4 && !l3) {
+ vec_free (mask);
+ vec_free (l2);
+ vec_free (l4);
+ return 0;
+ }
+
+ if (mask || l2 || l3 || l4)
{
- if (l2 || l3)
+ if (l2 || l3 || l4)
{
/* "With a free Ethernet header in every package" */
if (l2 == 0)
@@ -985,6 +1122,11 @@ uword unformat_classify_mask (unformat_input_t * input, va_list * args)
vec_append (mask, l3);
vec_free (l3);
}
+ if (l4)
+ {
+ vec_append (mask, l4);
+ vec_free (l4);
+ }
}
/* Scan forward looking for the first significant mask octet */
@@ -1396,6 +1538,36 @@ VLIB_CLI_COMMAND (show_classify_table_command, static) = {
.function = show_classify_tables_command_fn,
};
+uword unformat_l4_match (unformat_input_t * input, va_list * args)
+{
+ u8 ** matchp = va_arg (*args, u8 **);
+
+ u8 * proto_header = 0;
+ int src_port = 0;
+ int dst_port = 0;
+
+ tcpudp_header_t h;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "src_port %d", &src_port))
+ ;
+ else if (unformat (input, "dst_port %d", &dst_port))
+ ;
+ else
+ return 0;
+ }
+
+ h.src_port = clib_host_to_net_u16(src_port);
+ h.dst_port = clib_host_to_net_u16(dst_port);
+ vec_validate(proto_header, sizeof(h)-1);
+ memcpy(proto_header, &h, sizeof(h));
+
+ *matchp = proto_header;
+
+ return 1;
+}
+
uword unformat_ip4_match (unformat_input_t * input, va_list * args)
{
u8 ** matchp = va_arg (*args, u8 **);
@@ -1479,13 +1651,13 @@ uword unformat_ip4_match (unformat_input_t * input, va_list * args)
ip->tos = tos_val;
if (length)
- ip->length = length_val;
+ ip->length = clib_host_to_net_u16 (length_val);
if (ttl)
ip->ttl = ttl_val;
if (checksum)
- ip->checksum = checksum_val;
+ ip->checksum = clib_host_to_net_u16 (checksum_val);
*matchp = match;
return 1;
@@ -1733,6 +1905,7 @@ uword unformat_classify_match (unformat_input_t * input, va_list * args)
u8 * match = 0;
u8 * l2 = 0;
u8 * l3 = 0;
+ u8 * l4 = 0;
if (pool_is_free_index (cm->tables, table_index))
return 0;
@@ -1746,13 +1919,22 @@ uword unformat_classify_match (unformat_input_t * input, va_list * args)
;
else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
;
+ else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
+ ;
else
break;
}
- if (match || l2 || l3)
+ if (l4 && !l3) {
+ vec_free (match);
+ vec_free (l2);
+ vec_free (l4);
+ return 0;
+ }
+
+ if (match || l2 || l3 || l4)
{
- if (l2 || l3)
+ if (l2 || l3 || l4)
{
/* "Win a free Ethernet header in every packet" */
if (l2 == 0)
@@ -1763,6 +1945,11 @@ uword unformat_classify_match (unformat_input_t * input, va_list * args)
vec_append_aligned (match, l3, sizeof(u32x4));
vec_free (l3);
}
+ if (l4)
+ {
+ vec_append_aligned (match, l4, sizeof(u32x4));
+ vec_free (l4);
+ }
}
/* Make sure the vector is big enough even if key is all 0's */
diff --git a/vnet/vnet/ip/tcp_packet.h b/vnet/vnet/ip/tcp_packet.h
index ebb111572a0..5a9a420ebc5 100644
--- a/vnet/vnet/ip/tcp_packet.h
+++ b/vnet/vnet/ip/tcp_packet.h
@@ -65,11 +65,14 @@ enum {
typedef struct {
/* Source and destination port. */
union {
- struct {
- u16 src, dst;
- };
- u32 src_and_dst;
- } ports;
+ union {
+ struct {
+ u16 src, dst;
+ };
+ u32 src_and_dst;
+ } ports;
+ u16 src_port, dst_port;
+ };
/* Sequence and acknowledgment number. */
u32 seq_number, ack_number;