netifd: Add sendredirects config support
authorDaniel Golle <daniel@makrotopia.org>
Fri, 12 Feb 2016 20:04:00 +0000 (22:04 +0200)
committerDaniel Golle <daniel@makrotopia.org>
Tue, 10 Jan 2017 11:48:39 +0000 (12:48 +0100)
Setting /proc/sys/net/ipv4/conf/*/send_redirects is useful if a single
layer-2 domain is shared among routed subnets.
Sending redirects will prevents traffic from taking unnessesary detours
through a gateway in cases where direct connectivity on layer 2 exists.
This is commonly the case if an existing LAN infratructure with dump
switches is used to additionally carry routing protocols like OLSR
which are supported only by some nodes on the network.
It's important to note that the default value for send_redirects
differs for interface types (it's enabled on physical ethernet
interfaces, but disabled e.g. on VLANs) due to olsrd changing
/proc/sys/net/ipv4/conf/default/send_redirects during boot, thus the
default differs also depending e.g. on the way an on-board switch is
integrated on specific boards (as eth0 exists before olsrd is started,
eth0.1 gets created by netifd later on...)
Having a way to explicitely enable or disable send_redirects is
thus desireable also to unify the default behaviour among different,
but seemingly similar devices supported.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
device.c
device.h
system-linux.c

index 3c57a02..43881e5 100644 (file)
--- a/device.c
+++ b/device.c
@@ -58,6 +58,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
        [DEV_ATTR_MULTICAST] = { .name ="multicast", .type = BLOBMSG_TYPE_BOOL },
        [DEV_ATTR_LEARNING] = { .name ="learning", .type = BLOBMSG_TYPE_BOOL },
        [DEV_ATTR_UNICAST_FLOOD] = { .name ="unicast_flood", .type = BLOBMSG_TYPE_BOOL },
+       [DEV_ATTR_SENDREDIRECTS] = { .name = "sendredirects", .type = BLOBMSG_TYPE_BOOL },
 };
 
 const struct uci_blob_param_list device_attr_list = {
@@ -225,6 +226,8 @@ device_merge_settings(struct device *dev, struct device_settings *n)
        n->multicast_fast_leave = s->multicast_fast_leave;
        n->learning = s->learning;
        n->unicast_flood = s->unicast_flood;
+       n->sendredirects = s->flags & DEV_OPT_SENDREDIRECTS ?
+               s->sendredirects : os->sendredirects;
        n->flags = s->flags | os->flags | os->valid_flags;
 }
 
@@ -363,6 +366,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
                s->flags |= DEV_OPT_UNICAST_FLOOD;
        }
 
+       if ((cur = tb[DEV_ATTR_SENDREDIRECTS])) {
+               s->sendredirects = blobmsg_get_bool(cur);
+               s->flags |= DEV_OPT_SENDREDIRECTS;
+       }
+
        device_set_disabled(dev, disabled);
 }
 
@@ -1050,6 +1058,8 @@ device_dump_status(struct blob_buf *b, struct device *dev)
                        blobmsg_add_u8(b, "learning", st.learning);
                if (st.flags & DEV_OPT_UNICAST_FLOOD)
                        blobmsg_add_u8(b, "unicast_flood", st.unicast_flood);
+               if (st.flags & DEV_OPT_SENDREDIRECTS)
+                       blobmsg_add_u8(b, "sendredirects", st.sendredirects);
        }
 
        s = blobmsg_open_table(b, "statistics");
index 2af93bb..3c172ce 100644 (file)
--- a/device.h
+++ b/device.h
@@ -50,6 +50,7 @@ enum {
        DEV_ATTR_LEARNING,
        DEV_ATTR_UNICAST_FLOOD,
        DEV_ATTR_NEIGHGCSTALETIME,
+       DEV_ATTR_SENDREDIRECTS,
        __DEV_ATTR_MAX,
 };
 
@@ -101,6 +102,7 @@ enum {
        DEV_OPT_UNICAST_FLOOD           = (1 << 18),
        DEV_OPT_NEIGHGCSTALETIME        = (1 << 19),
        DEV_OPT_MULTICAST_FAST_LEAVE    = (1 << 20),
+       DEV_OPT_SENDREDIRECTS           = (1 << 17),
 };
 
 /* events broadcasted to all users of a device */
@@ -167,6 +169,7 @@ struct device_settings {
        bool multicast;
        bool learning;
        bool unicast_flood;
+       bool sendredirects;
 };
 
 /*
index 52a1c17..2f15bf1 100644 (file)
@@ -397,6 +397,11 @@ static void system_bridge_set_unicast_flood(struct device *dev, const char *val)
        system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
 }
 
+static void system_set_sendredirects(struct device *dev, const char *val)
+{
+       system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
+}
+
 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
 {
        int fd = -1, ret = -1;
@@ -485,6 +490,12 @@ static int system_get_dadtransmits(struct device *dev, char *buf, const size_t b
                        dev->ifname, buf, buf_sz);
 }
 
+static int system_get_sendredirects(struct device *dev, char *buf, const size_t buf_sz)
+{
+       return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects",
+                       dev->ifname, buf, buf_sz);
+}
+
 // Evaluate netlink messages
 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
 {
@@ -1288,6 +1299,11 @@ system_if_get_settings(struct device *dev, struct device_settings *s)
                s->dadtransmits = strtoul(buf, NULL, 0);
                s->flags |= DEV_OPT_DADTRANSMITS;
        }
+
+       if (!system_get_sendredirects(dev, buf, sizeof(buf))) {
+               s->sendredirects = strtoul(buf, NULL, 0);
+               s->flags |= DEV_OPT_SENDREDIRECTS;
+       }
 }
 
 static void
@@ -1393,6 +1409,8 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned
                                    !s->multicast ? IFF_MULTICAST : 0) < 0)
                        s->flags &= ~DEV_OPT_MULTICAST;
        }
+       if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
+               system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
 
        system_if_apply_rps_xps(dev, s);
 }