flow dissector: ICMP support
authorSimon Horman <simon.horman@netronome.com>
Wed, 7 Dec 2016 12:48:27 +0000 (13:48 +0100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 8 Dec 2016 16:45:21 +0000 (11:45 -0500)
Allow dissection of ICMP(V6) type and code. This should only occur
if a packet is ICMP(V6) and the dissector has FLOW_DISSECTOR_KEY_ICMP set.

There are currently no users of FLOW_DISSECTOR_KEY_ICMP.
A follow-up patch will allow FLOW_DISSECTOR_KEY_ICMP to be used by
the flower classifier.

Signed-off-by: Simon Horman <simon.horman@netronome.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/flow_dissector.h
net/core/flow_dissector.c

index c4f31666afd24695b9d83688f0800ebcc017114b..d896a33e00d4d1b5a81b85dd5766b78d09647d78 100644 (file)
@@ -104,6 +104,22 @@ struct flow_dissector_key_ports {
        };
 };
 
+/**
+ * flow_dissector_key_icmp:
+ *     @ports: type and code of ICMP header
+ *             icmp: ICMP type (high) and code (low)
+ *             type: ICMP type
+ *             code: ICMP code
+ */
+struct flow_dissector_key_icmp {
+       union {
+               __be16 icmp;
+               struct {
+                       u8 type;
+                       u8 code;
+               };
+       };
+};
 
 /**
  * struct flow_dissector_key_eth_addrs:
@@ -122,6 +138,7 @@ enum flow_dissector_key_id {
        FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_ipv4_addrs */
        FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
        FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
+       FLOW_DISSECTOR_KEY_ICMP, /* struct flow_dissector_key_icmp */
        FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */
        FLOW_DISSECTOR_KEY_TIPC_ADDRS, /* struct flow_dissector_key_tipc_addrs */
        FLOW_DISSECTOR_KEY_VLAN, /* struct flow_dissector_key_flow_vlan */
index 1eb6f949e5b2f8d55263fff361bcd758a3a12afb..d6447dc1037151495d88064938dfb4e255377416 100644 (file)
@@ -57,6 +57,28 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
 }
 EXPORT_SYMBOL(skb_flow_dissector_init);
 
+/**
+ * skb_flow_get_be16 - extract be16 entity
+ * @skb: sk_buff to extract from
+ * @poff: offset to extract at
+ * @data: raw buffer pointer to the packet
+ * @hlen: packet header length
+ *
+ * The function will try to retrieve a be32 entity at
+ * offset poff
+ */
+__be16 skb_flow_get_be16(const struct sk_buff *skb, int poff, void *data,
+                        int hlen)
+{
+       __be16 *u, _u;
+
+       u = __skb_header_pointer(skb, poff, sizeof(_u), data, hlen, &_u);
+       if (u)
+               return *u;
+
+       return 0;
+}
+
 /**
  * __skb_flow_get_ports - extract the upper layer ports and return them
  * @skb: sk_buff to extract the ports from
@@ -117,6 +139,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
        struct flow_dissector_key_basic *key_basic;
        struct flow_dissector_key_addrs *key_addrs;
        struct flow_dissector_key_ports *key_ports;
+       struct flow_dissector_key_icmp *key_icmp;
        struct flow_dissector_key_tags *key_tags;
        struct flow_dissector_key_vlan *key_vlan;
        struct flow_dissector_key_keyid *key_keyid;
@@ -546,6 +569,14 @@ ip_proto_again:
                                                        data, hlen);
        }
 
+       if (dissector_uses_key(flow_dissector,
+                              FLOW_DISSECTOR_KEY_ICMP)) {
+               key_icmp = skb_flow_dissector_target(flow_dissector,
+                                                    FLOW_DISSECTOR_KEY_ICMP,
+                                                    target_container);
+               key_icmp->icmp = skb_flow_get_be16(skb, nhoff, data, hlen);
+       }
+
 out_good:
        ret = true;