[OpenWrt-Devel] [PATCH 3/3] netifd: Read current link state when processing netlink event

Hans Dedecker dedeckeh at gmail.com
Wed Oct 22 08:14:22 EDT 2014


Netifd commit b2dcb02570939d98b92c7c55db1c328693a5d52a introduces
a race condition resulting into infinite toggling interfaces
(eg static interfaces with linksensing enabled, vlan interfaces
with proto none (#18106)) when linksensing is enabled resulting into
a crash.
As netlink event messages will be queued on the netlink event socket
the included lower up interface flag will not always represent the
current link state when netifd processes the netlink messages;
by reading the current link state when a netlink event message is
parsed the correct info is passed to the device layer.
This will avoid continuous interface toggling (down/up) triggered
by link state changes based on outdated netlink interface info.
This solution replaces the patch which was introduced to solve
issue (#1806) for vlan devices as other protocol handlers suffered
from the same problem.

Signed-off-by: Hans Dedecker <dedeckeh at gmail.com>
---
 device.h       |  2 --
 macvlan.c      |  1 -
 system-linux.c | 16 ++++++++++------
 vlan.c         |  1 -
 vlandev.c      |  1 -
 5 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/device.h b/device.h
index adf72c5..73b2656 100644
--- a/device.h
+++ b/device.h
@@ -47,8 +47,6 @@ struct device_type {
 	struct list_head list;
 	const char *name;
 
-	bool keep_link_status;
-
 	const struct uci_blob_param_list *config_params;
 
 	struct device *(*create)(const char *name, struct blob_attr *attr);
diff --git a/macvlan.c b/macvlan.c
index 019a7ff..e5a4891 100644
--- a/macvlan.c
+++ b/macvlan.c
@@ -258,7 +258,6 @@ macvlan_create(const char *name, struct blob_attr *attr)
 const struct device_type macvlan_device_type = {
 	.name = "MAC VLAN",
 	.config_params = &macvlan_attr_list,
-	.keep_link_status = true,
 
 	.create = macvlan_create,
 	.config_init = macvlan_config_init,
diff --git a/system-linux.c b/system-linux.c
index 7ae9e27..8e0564c 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -299,16 +299,14 @@ static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t b
 			dev->ifname, buf, buf_sz);
 }
 
-#ifndef IFF_LOWER_UP
-#define IFF_LOWER_UP	0x10000
-#endif
-
 // Evaluate netlink messages
 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
 {
 	struct nlmsghdr *nh = nlmsg_hdr(msg);
 	struct ifinfomsg *ifi = NLMSG_DATA(nh);
 	struct nlattr *nla[__IFLA_MAX];
+	int link_state = 0;
+	char buf[10];
 
 	if (nh->nlmsg_type != RTM_NEWLINK)
 		goto out;
@@ -322,8 +320,10 @@ static int cb_rtnl_event(struct nl_msg *msg, void *arg)
 		goto out;
 
 	device_set_ifindex(dev, ifi->ifi_index);
-	if (!dev->type->keep_link_status)
-		device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
+	if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
+		link_state = strtoul(buf, NULL, 0);
+
+	device_set_link(dev, link_state ? true : false);
 
 out:
 	return 0;
@@ -1020,6 +1020,10 @@ struct if_check_data {
 	int ret;
 };
 
+#ifndef IFF_LOWER_UP
+#define IFF_LOWER_UP	0x10000
+#endif
+
 static int cb_if_check_valid(struct nl_msg *msg, void *arg)
 {
 	struct nlmsghdr *nh = nlmsg_hdr(msg);
diff --git a/vlan.c b/vlan.c
index 354e12f..28b1441 100644
--- a/vlan.c
+++ b/vlan.c
@@ -102,7 +102,6 @@ static struct device *get_vlan_device(struct device *dev, int id, bool create)
 	static const struct device_type vlan_type = {
 		.name = "VLAN",
 		.config_params = &device_attr_list,
-		.keep_link_status = true,
 		.free = free_vlan_if,
 	};
 	struct vlan_device *vldev;
diff --git a/vlandev.c b/vlandev.c
index 7b2038e..36a5c63 100644
--- a/vlandev.c
+++ b/vlandev.c
@@ -246,7 +246,6 @@ vlandev_create(const char *name, struct blob_attr *attr)
 const struct device_type vlandev_device_type = {
 	.name = "VLANDEV",
 	.config_params = &vlandev_attr_list,
-	.keep_link_status = true,
 
 	.create = vlandev_create,
 	.config_init = vlandev_config_init,
-- 
1.9.1
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list