]> git.proxmox.com Git - ovs.git/commitdiff
compat: Allow IPv6 GRE/ERSPAN Tx when ip6_gre is loaded
authorGreg Rose <gvrose8192@gmail.com>
Fri, 27 Jul 2018 18:20:08 +0000 (11:20 -0700)
committerBen Pfaff <blp@ovn.org>
Fri, 27 Jul 2018 19:29:16 +0000 (12:29 -0700)
When for some reason the built-in kernel ip6_gre module is loaded that
would prevent the openvswitch kernel driver from loading.  Even when
the built-in kernel ip6_gre module is loaded we can still perform
port mirroring via Tx.  Adjust the error handling and detect when
the ip6_gre kernel module is loaded and in that case still enable
IPv6 GRE/ERSPAN Tx.

Signed-off-by: Greg Rose <gvrose8192@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: William Tu <u9012063@gmail.com>
datapath/linux/compat/ip6_gre.c
datapath/vport.c

index 0c885472df5b208659676c48f14ec3d02879f1e6..54a76aba5169ae8c64f57ac38bcedb0a0fe5ab77 100644 (file)
@@ -65,6 +65,7 @@
 #define IP6_GRE_HASH_SIZE (1 << IP6_GRE_HASH_SIZE_SHIFT)
 
 static unsigned int ip6gre_net_id __read_mostly;
+static bool ip6_gre_loaded = false;
 struct ip6gre_net {
        struct ip6_tnl __rcu *tunnels[4][IP6_GRE_HASH_SIZE];
 
@@ -2792,32 +2793,52 @@ int rpl_ip6gre_init(void)
        int err;
 
        err = register_pernet_device(&ip6gre_net_ops);
-       if (err < 0)
-               return err;
+       if (err < 0) {
+               if (err == -EEXIST)
+                       goto ip6_gre_loaded;
+               else
+                       goto out;
+       }
 
        err = inet6_add_protocol(&ip6gre_protocol, IPPROTO_GRE);
        if (err < 0) {
                pr_info("%s: can't add protocol\n", __func__);
-               goto add_proto_failed;
+               unregister_pernet_device(&ip6gre_net_ops);
+               goto ip6_gre_loaded;
        }
 
        pr_info("GRE over IPv6 tunneling driver\n");
        ovs_vport_ops_register(&ovs_ip6gre_vport_ops);
        ovs_vport_ops_register(&ovs_erspan6_vport_ops);
-       return 0;
-out:
        return err;
 
-add_proto_failed:
-       unregister_pernet_device(&ip6gre_net_ops);
-       goto out;
+ip6_gre_loaded:
+       /* Since IPv6 GRE only allows single receiver to be registerd,
+        * we skip here so only transmit works, see:
+        *
+        * commit f9242b6b28d61295f2bf7e8adfb1060b382e5381
+        * Author: David S. Miller <davem@davemloft.net>
+        * Date:   Tue Jun 19 18:56:21 2012 -0700
+        *
+        *     inet: Sanitize inet{,6} protocol demux.
+        *
+        * OVS GRE receive part is disabled.
+        */
+       pr_info("GRE TX only over IPv6 tunneling driver\n");
+       ip6_gre_loaded = true;
+       ovs_vport_ops_register(&ovs_ip6gre_vport_ops);
+       ovs_vport_ops_register(&ovs_erspan6_vport_ops);
+out:
+       return err;
 }
 
 void rpl_ip6gre_fini(void)
 {
        ovs_vport_ops_unregister(&ovs_erspan6_vport_ops);
        ovs_vport_ops_unregister(&ovs_ip6gre_vport_ops);
-       inet6_del_protocol(&ip6gre_protocol, IPPROTO_GRE);
-       unregister_pernet_device(&ip6gre_net_ops);
+       if (!ip6_gre_loaded) {
+               inet6_del_protocol(&ip6gre_protocol, IPPROTO_GRE);
+               unregister_pernet_device(&ip6gre_net_ops);
+       }
 }
 #endif /* USE_UPSTREAM_TUNNEL */
index 28ddb865c3a25dfb73be4cfd6de1dd90add5fce3..e1b321fce15a33d99f75c1e451a7a4353075ca35 100644 (file)
@@ -43,6 +43,7 @@
 
 static LIST_HEAD(vport_ops_list);
 static bool compat_gre_loaded = false;
+static bool compat_ip6_tunnel_loaded = false;
 
 /* Protected by RCU read lock for reading, ovs_mutex for writing. */
 static struct hlist_head *dev_table;
@@ -81,11 +82,22 @@ int ovs_vport_init(void)
                compat_gre_loaded = true;
        }
        err = ip6gre_init();
-       if (err)
+       if (err && err != -EEXIST) {
                goto err_ip6gre;
+       } else {
+               if (err == -EEXIST) {
+                       pr_warn("IPv6 GRE/ERSPAN Rx mode is not supported\n");
+                       goto skip_ip6_tunnel_init;
+               }
+       }
+
        err = ip6_tunnel_init();
        if (err)
                goto err_ip6_tunnel;
+       else
+               compat_ip6_tunnel_loaded = true;
+
+skip_ip6_tunnel_init:
        err = geneve_init_module();
        if (err)
                goto err_geneve;
@@ -131,7 +143,8 @@ void ovs_vport_exit(void)
        ovs_stt_cleanup_module();
        vxlan_cleanup_module();
        geneve_cleanup_module();
-       ip6_tunnel_cleanup();
+       if (compat_ip6_tunnel_loaded)
+               ip6_tunnel_cleanup();
        ip6gre_fini();
        lisp_cleanup_module();
        kfree(dev_table);