net: flow_dissector: add support for dissection of tcp flags
authorJiri Pirko <jiri@mellanox.com>
Tue, 23 May 2017 16:40:44 +0000 (18:40 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 24 May 2017 20:22:11 +0000 (16:22 -0400)
Add support for dissection of tcp flags. Uses similar function call to
tcp dissection function as arp, mpls and others.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/flow_dissector.h
net/core/flow_dissector.c

index 8d21d448daa9d19ad58a753e373035f2a1be59bb..efe34eec61dccc125fe59741e45de2c2e61cd250 100644 (file)
@@ -157,6 +157,14 @@ struct flow_dissector_key_eth_addrs {
        unsigned char src[ETH_ALEN];
 };
 
+/**
+ * struct flow_dissector_key_tcp:
+ * @flags: flags
+ */
+struct flow_dissector_key_tcp {
+       __be16 flags;
+};
+
 enum flow_dissector_key_id {
        FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
        FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
@@ -177,6 +185,7 @@ enum flow_dissector_key_id {
        FLOW_DISSECTOR_KEY_ENC_CONTROL, /* struct flow_dissector_key_control */
        FLOW_DISSECTOR_KEY_ENC_PORTS, /* struct flow_dissector_key_ports */
        FLOW_DISSECTOR_KEY_MPLS, /* struct flow_dissector_key_mpls */
+       FLOW_DISSECTOR_KEY_TCP, /* struct flow_dissector_key_tcp */
 
        FLOW_DISSECTOR_KEY_MAX,
 };
index 28d94bce4df8eb046dd6a03103c9249b29e74cd8..5a45943081f5ff7723389bee3c7f80786add6c00 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/stddef.h>
 #include <linux/if_ether.h>
 #include <linux/mpls.h>
+#include <linux/tcp.h>
 #include <net/flow_dissector.h>
 #include <scsi/fc/fc_fcoe.h>
 
@@ -342,6 +343,30 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
        return FLOW_DISSECT_RET_OUT_PROTO_AGAIN;
 }
 
+static void
+__skb_flow_dissect_tcp(const struct sk_buff *skb,
+                      struct flow_dissector *flow_dissector,
+                      void *target_container, void *data, int thoff, int hlen)
+{
+       struct flow_dissector_key_tcp *key_tcp;
+       struct tcphdr *th, _th;
+
+       if (!dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_TCP))
+               return;
+
+       th = __skb_header_pointer(skb, thoff, sizeof(_th), data, hlen, &_th);
+       if (!th)
+               return;
+
+       if (unlikely(__tcp_hdrlen(th) < sizeof(_th)))
+               return;
+
+       key_tcp = skb_flow_dissector_target(flow_dissector,
+                                           FLOW_DISSECTOR_KEY_TCP,
+                                           target_container);
+       key_tcp->flags = (*(__be16 *) &tcp_flag_word(th) & htons(0x0FFF));
+}
+
 /**
  * __skb_flow_dissect - extract the flow_keys struct and return it
  * @skb: sk_buff to extract the flow from, can be NULL if the rest are specified
@@ -683,6 +708,10 @@ ip_proto_again:
        case IPPROTO_MPLS:
                proto = htons(ETH_P_MPLS_UC);
                goto mpls;
+       case IPPROTO_TCP:
+               __skb_flow_dissect_tcp(skb, flow_dissector, target_container,
+                                      data, nhoff, hlen);
+               break;
        default:
                break;
        }