flow_dissector: allow dissection of tunnel options from metadata
authorSimon Horman <simon.horman@netronome.com>
Tue, 7 Aug 2018 15:36:00 +0000 (17:36 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 7 Aug 2018 19:22:14 +0000 (12:22 -0700)
Allow the existing 'dissection' of tunnel metadata to 'dissect'
options already present in tunnel metadata. This dissection is
controlled by a new dissector key, FLOW_DISSECTOR_KEY_ENC_OPTS.

This dissection only occurs when skb_flow_dissect_tunnel_info()
is called, currently only the Flower classifier makes that call.
So there should be no impact on other users of the flow dissector.

This is in preparation for allowing the flower classifier to
match on Geneve options.

Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/flow_dissector.h
net/core/flow_dissector.c

index 2a17f041f7a1742e069e7c6d49658251e45519e3..6a4586dcdeded9b6cfe7d299d368b6a6ea6801cc 100644 (file)
@@ -57,6 +57,21 @@ struct flow_dissector_key_mpls {
                mpls_label:20;
 };
 
+#define FLOW_DIS_TUN_OPTS_MAX 255
+/**
+ * struct flow_dissector_key_enc_opts:
+ * @data: tunnel option data
+ * @len: length of tunnel option data
+ * @dst_opt_type: tunnel option type
+ */
+struct flow_dissector_key_enc_opts {
+       u8 data[FLOW_DIS_TUN_OPTS_MAX]; /* Using IP_TUNNEL_OPTS_MAX is desired
+                                        * here but seems difficult to #include
+                                        */
+       u8 len;
+       __be16 dst_opt_type;
+};
+
 struct flow_dissector_key_keyid {
        __be32  keyid;
 };
@@ -208,6 +223,8 @@ enum flow_dissector_key_id {
        FLOW_DISSECTOR_KEY_IP, /* struct flow_dissector_key_ip */
        FLOW_DISSECTOR_KEY_CVLAN, /* struct flow_dissector_key_flow_vlan */
        FLOW_DISSECTOR_KEY_ENC_IP, /* struct flow_dissector_key_ip */
+       FLOW_DISSECTOR_KEY_ENC_OPTS, /* struct flow_dissector_key_enc_opts */
+
        FLOW_DISSECTOR_KEY_MAX,
 };
 
index 08a5184f4b344281ed1c458aa62a3033e63a81e5..ce9eeeb7c024c8ab98ca77a03317105c73b8e108 100644 (file)
@@ -154,7 +154,9 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
            !dissector_uses_key(flow_dissector,
                                FLOW_DISSECTOR_KEY_ENC_PORTS) &&
            !dissector_uses_key(flow_dissector,
-                               FLOW_DISSECTOR_KEY_ENC_IP))
+                               FLOW_DISSECTOR_KEY_ENC_IP) &&
+           !dissector_uses_key(flow_dissector,
+                               FLOW_DISSECTOR_KEY_ENC_OPTS))
                return;
 
        info = skb_tunnel_info(skb);
@@ -224,6 +226,21 @@ skb_flow_dissect_tunnel_info(const struct sk_buff *skb,
                ip->tos = key->tos;
                ip->ttl = key->ttl;
        }
+
+       if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_ENC_OPTS)) {
+               struct flow_dissector_key_enc_opts *enc_opt;
+
+               enc_opt = skb_flow_dissector_target(flow_dissector,
+                                                   FLOW_DISSECTOR_KEY_ENC_OPTS,
+                                                   target_container);
+
+               if (info->options_len) {
+                       enc_opt->len = info->options_len;
+                       ip_tunnel_info_opts_get(enc_opt->data, info);
+                       enc_opt->dst_opt_type = info->key.tun_flags &
+                                               TUNNEL_OPTIONS_PRESENT;
+               }
+       }
 }
 EXPORT_SYMBOL(skb_flow_dissect_tunnel_info);