linux: adjust default policy rules
[project/netifd.git] / system-linux.c
index 4662bf8..e45fc69 100644 (file)
@@ -47,6 +47,7 @@
 #include <fcntl.h>
 #include <glob.h>
 #include <time.h>
+#include <unistd.h>
 
 #include <netlink/msg.h>
 #include <netlink/attr.h>
@@ -275,6 +276,26 @@ static void system_set_acceptlocal(struct device *dev, const char *val)
        system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/accept_local", dev->ifname, val);
 }
 
+static void system_set_igmpversion(struct device *dev, const char *val)
+{
+       system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version", dev->ifname, val);
+}
+
+static void system_set_mldversion(struct device *dev, const char *val)
+{
+       system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version", dev->ifname, val);
+}
+
+static void system_set_neigh4reachabletime(struct device *dev, const char *val)
+{
+       system_set_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", dev->ifname, val);
+}
+
+static void system_set_neigh6reachabletime(struct device *dev, const char *val)
+{
+       system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", dev->ifname, val);
+}
+
 static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
 {
        int fd = -1, ret = -1;
@@ -321,6 +342,30 @@ static int system_get_acceptlocal(struct device *dev, char *buf, const size_t bu
                        dev->ifname, buf, buf_sz);
 }
 
+static int system_get_igmpversion(struct device *dev, char *buf, const size_t buf_sz)
+{
+       return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/force_igmp_version",
+                       dev->ifname, buf, buf_sz);
+}
+
+static int system_get_mldversion(struct device *dev, char *buf, const size_t buf_sz)
+{
+       return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/force_mld_version",
+                       dev->ifname, buf, buf_sz);
+}
+
+static int system_get_neigh4reachabletime(struct device *dev, char *buf, const size_t buf_sz)
+{
+       return system_get_dev_sysctl("/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms",
+                       dev->ifname, buf, buf_sz);
+}
+
+static int system_get_neigh6reachabletime(struct device *dev, char *buf, const size_t buf_sz)
+{
+       return system_get_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms",
+                       dev->ifname, buf, buf_sz);
+}
+
 // Evaluate netlink messages
 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
 {
@@ -750,7 +795,7 @@ int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
                bridge->ifname, cfg->igmp_snoop ? "1" : "0");
 
        system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_querier",
-               bridge->ifname, cfg->igmp_snoop ? "1" : "0");
+               bridge->ifname, cfg->multicast_querier ? "1" : "0");
 
        args[0] = BRCTL_SET_BRIDGE_PRIORITY;
        args[1] = cfg->priority;
@@ -985,6 +1030,58 @@ system_if_get_settings(struct device *dev, struct device_settings *s)
                s->acceptlocal = strtoul(buf, NULL, 0);
                s->flags |= DEV_OPT_ACCEPTLOCAL;
        }
+
+       if (!system_get_igmpversion(dev, buf, sizeof(buf))) {
+               s->igmpversion = strtoul(buf, NULL, 0);
+               s->flags |= DEV_OPT_IGMPVERSION;
+       }
+
+       if (!system_get_mldversion(dev, buf, sizeof(buf))) {
+               s->mldversion = strtoul(buf, NULL, 0);
+               s->flags |= DEV_OPT_MLDVERSION;
+       }
+
+       if (!system_get_neigh4reachabletime(dev, buf, sizeof(buf))) {
+               s->neigh4reachabletime = strtoul(buf, NULL, 0);
+               s->flags |= DEV_OPT_NEIGHREACHABLETIME;
+       }
+
+       if (!system_get_neigh6reachabletime(dev, buf, sizeof(buf))) {
+               s->neigh6reachabletime = strtoul(buf, NULL, 0);
+               s->flags |= DEV_OPT_NEIGHREACHABLETIME;
+       }
+}
+
+static void
+system_if_set_rps_xps_val(const char *path, int val)
+{
+       char val_buf[8];
+       glob_t gl;
+       int i;
+
+       if (glob(path, 0, NULL, &gl))
+               return;
+
+       snprintf(val_buf, sizeof(val_buf), "%x", val);
+       for (i = 0; i < gl.gl_pathc; i++)
+               system_set_sysctl(gl.gl_pathv[i], val_buf);
+}
+
+static void
+system_if_apply_rps_xps(struct device *dev, struct device_settings *s)
+{
+       long n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+       int val;
+
+       if (n_cpus < 2)
+               return;
+
+       val = (1 << n_cpus) - 1;
+       snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/rps_cpus", dev->ifname);
+       system_if_set_rps_xps_val(dev_buf, s->rps ? val : 0);
+
+       snprintf(dev_buf, sizeof(dev_buf), "/sys/class/net/%s/queues/*/xps_cpus", dev->ifname);
+       system_if_set_rps_xps_val(dev_buf, s->xps ? val : 0);
 }
 
 void
@@ -992,9 +1089,6 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned
 {
        struct ifreq ifr;
 
-       if (!apply_mask)
-               return;
-
        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
        if (s->flags & DEV_OPT_MTU & apply_mask) {
@@ -1028,6 +1122,28 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned
        }
        if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
                system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
+       if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
+               char buf[2];
+
+               snprintf(buf, sizeof(buf), "%d", s->igmpversion);
+               system_set_igmpversion(dev, buf);
+       }
+       if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
+               char buf[2];
+
+               snprintf(buf, sizeof(buf), "%d", s->mldversion);
+               system_set_mldversion(dev, buf);
+       }
+       if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
+               char buf[12];
+
+               snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime);
+               system_set_neigh4reachabletime(dev, buf);
+               snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime);
+               system_set_neigh6reachabletime(dev, buf);
+       }
+
+       system_if_apply_rps_xps(dev, s);
 }
 
 int system_if_up(struct device *dev)
@@ -1682,7 +1798,7 @@ int system_flush_iprules(void)
 
        rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
 
-       rule.priority = 0;
+       rule.priority = 128;
        rule.lookup = RT_TABLE_LOCAL;
        rv |= system_iprule(&rule, RTM_NEWRULE);
 
@@ -1697,7 +1813,7 @@ int system_flush_iprules(void)
 
        rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
 
-       rule.priority = 0;
+       rule.priority = 128;
        rule.lookup = RT_TABLE_LOCAL;
        rv |= system_iprule(&rule, RTM_NEWRULE);