@@ -71,6 +71,7 @@ static void erspan_build_header(struct sk_buff *skb,
bool truncate, bool is_ipv4);
static struct rtnl_link_ops ipgre_link_ops __read_mostly;
+static bool ip_gre_loaded = false;
#define ip_gre_calc_hlen rpl_ip_gre_calc_hlen
static int ip_gre_calc_hlen(__be16 o_flags)
@@ -1640,25 +1641,57 @@ int rpl_ipgre_init(void)
int err;
err = register_pernet_device(&ipgre_tap_net_ops);
- if (err < 0)
- goto pnet_tap_failed;
+ if (err < 0) {
+ if (err == -EEXIST)
+ goto ip_gre_loaded;
+ else
+ goto pnet_tap_failed;
+ }
err = register_pernet_device(&erspan_net_ops);
- if (err < 0)
- goto pnet_erspan_failed;
+ if (err < 0) {
+ if (err == -EEXIST)
+ goto ip_gre_loaded;
+ else
+ goto pnet_erspan_failed;
+ }
err = register_pernet_device(&ipgre_net_ops);
- if (err < 0)
- goto pnet_ipgre_failed;
+ if (err < 0) {
+ if (err == -EEXIST)
+ goto ip_gre_loaded;
+ else
+ goto pnet_ipgre_failed;
+ }
err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
if (err < 0) {
pr_info("%s: can't add protocol\n", __func__);
- goto add_proto_failed;
+ if (err == -EBUSY) {
+ goto ip_gre_loaded;
+ } else {
+ goto add_proto_failed;
+ }
}
pr_info("GRE over IPv4 tunneling driver\n");
-
+ ovs_vport_ops_register(&ovs_ipgre_vport_ops);
+ ovs_vport_ops_register(&ovs_erspan_vport_ops);
+ return 0;
+
+ip_gre_loaded:
+ /* Since GRE only allows single receiver to be registerd,
+ * we skip here so only gre transmit works, see:
+ *
+ * commit 9f57c67c379d88a10e8ad676426fee5ae7341b14
+ * Author: Pravin B Shelar <pshelar@nicira.com>
+ * Date: Fri Aug 7 23:51:52 2015 -0700
+ * gre: Remove support for sharing GRE protocol hook
+ *
+ * OVS GRE receive part is disabled.
+ */
+ pr_info("GRE TX only over IPv4 tunneling driver\n");
+ ip_gre_loaded = true;
ovs_vport_ops_register(&ovs_ipgre_vport_ops);
ovs_vport_ops_register(&ovs_erspan_vport_ops);
return 0;
@@ -1678,10 +1711,13 @@ void rpl_ipgre_fini(void)
{
ovs_vport_ops_unregister(&ovs_erspan_vport_ops);
ovs_vport_ops_unregister(&ovs_ipgre_vport_ops);
- gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
- unregister_pernet_device(&ipgre_net_ops);
- unregister_pernet_device(&erspan_net_ops);
- unregister_pernet_device(&ipgre_tap_net_ops);
+
+ if (!ip_gre_loaded) {
+ gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
+ unregister_pernet_device(&ipgre_net_ops);
+ unregister_pernet_device(&erspan_net_ops);
+ unregister_pernet_device(&ipgre_tap_net_ops);
+ }
}
#endif
@@ -66,11 +66,15 @@ int ovs_vport_init(void)
if (err)
goto err_lisp;
err = gre_init();
- if (err && err != -EEXIST)
+ if (err && err != -EEXIST) {
goto err_gre;
- else if (err == -EEXIST)
- pr_warn("Cannot take GRE protocol entry - The ERSPAN feature may not be supported\n");
- else {
+ } else {
+ if (err == -EEXIST) {
+ pr_warn("Cannot take GRE protocol rx entry"\
+ "- The GRE/ERSPAN rx feature not supported\n");
+ /* continue GRE tx */
+ }
+
err = ipgre_init();
if (err && err != -EEXIST)
goto err_ipgre;