[ovs-dev] [PATCH] datapath: compat: fix kernel module reference count.

William Tu u9012063 at gmail.com
Fri Nov 10 13:36:25 UTC 2017


Before we introduce dpif-netlink-rtnl, creating a tunnel device
depends on openvswitch/vport kernel module calling kernel's tunnel API.
Example call sequence:
 1) ovs_vport_add (openvswitch.ko)
 2) geneve_create (vport_geneve.ko)
 3) geneve_tnl_create (vport_geneve.ko)
 4) geneve_dev_create_fb (geneve.ko)
As a result, module dependency/refcnt is created: module openvswitch.ko
references vport_geneve.ko and vport_geneve.ko depends on geneve.ko.

After the dpif-netlink-rtnl, a tunnel device can be created by using
rtnetlink, so the creation of fb device comes from the ovs-vswitchd
instead of going through OVS kernel modules.  This breaks the module
dependency between 1) and 2).  As a result, when ovs-vswitchd is running,
the 'lsmod' shows:
  geneve                 27326  1 vport_geneve
  vport_geneve           12560  0
  openvswitch           172469  1 vport_geneve
Problems can be cerated by doing  `rmmod vport_geneve` then
`rmmod geneve`, when ovs-vswitchd expects geneve module should already
be loaded.

The patch introduces 1) load the upstream geneve.ko at init time
from openvswitch.ko and 2) grap the reference count of geneve.
This adds the dependency: openvswitch.ko needs geneve.ko, so that
geneve won't be unloaded accidentally.  As a result, `lsmod` shows
  geneve                 20254  2 vport_geneve
  vport_geneve            1744  0
  openvswitch           159846  1 vport_geneve

Note that when choosing to use upstream tunnel, we don't actually need
vport_geneve, so the patch increment refcnt of geneve instead of
vport_geneve.

Fixes: b6d6830d29e4 ("dpif-netlink-rtnl: Support GENEVE creation")
Signed-off-by: William Tu <u9012063 at gmail.com>
Cc: Eric Garver <e at erig.me>
---
Adding more testing details:
On OVS2.7 without dpif-netlink-rtnl, kernel 4.8
lsmod
  vport_geneve            1744  1 		(this is ref by openvswitch.ko)
  geneve                 20254  1 vport_geneve
  openvswitch           128504  3 vport_geneve

On OVS2.8 with dpif-netlink-rtnl, kernel 4.8, before the patch
lsmod
  geneve                 27326  1 vport_geneve
  vport_geneve           12560  0		(the ref is gone)
  openvswitch           172469  1 vport_geneve

On OVS2.8 with dpif-netlink-rtnl, kernel 4.8, after the patch
lsmod
  geneve                 27326  2 vport_geneve
  vport_geneve           12560  0
  openvswitch           172469  1 vport_geneve

---
 datapath/linux/compat/include/net/geneve.h | 32 ++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/datapath/linux/compat/include/net/geneve.h b/datapath/linux/compat/include/net/geneve.h
index d9c9f0bf7b38..02aaf4f83688 100644
--- a/datapath/linux/compat/include/net/geneve.h
+++ b/datapath/linux/compat/include/net/geneve.h
@@ -8,9 +8,41 @@
 
 #ifdef USE_UPSTREAM_TUNNEL
 #include_next <net/geneve.h>
+static struct module *geneve_mod;
 
 static inline int rpl_geneve_init_module(void)
 {
+	int ret;
+
+	/* When USE_UPSTREAM_TUNNEL, try loading and adding
+	 * module dependency on the upstream geneve module.
+	 */
+	geneve_mod = find_module("geneve");
+
+	if (!geneve_mod) {
+		ret = request_module("geneve");
+		if (ret) {
+			pr_warn("Failed loading geneve module\n");
+			return 0;
+		}
+	}
+
+	/* Geneve module already loaded, find
+	 * it and grap its reference count.
+	 */
+	mutex_lock(&module_mutex);
+
+	geneve_mod = find_module("geneve");
+	if (unlikely(!geneve_mod)) {
+		pr_warn("Failed loading geneve module\n");
+		return 0;
+	}
+
+	ret = ref_module(THIS_MODULE, geneve_mod);
+	if (ret)
+		pr_warn("Failed referencing geneve module\n");
+	mutex_unlock(&module_mutex);
+
 	return 0;
 }
 static inline void rpl_geneve_cleanup_module(void)
-- 
2.7.4



More information about the dev mailing list