#define RTN_FAILED_POLICY 12
#endif
+#ifndef RT_TABLE_PRELOCAL
+#define RT_TABLE_PRELOCAL 128
+#endif
+
+#ifndef IFA_F_NOPREFIXROUTE
+#define IFA_F_NOPREFIXROUTE 0x200
+#endif
+
#include <string.h>
#include <fcntl.h>
#include <glob.h>
#include <time.h>
+#include <unistd.h>
#include <netlink/msg.h>
#include <netlink/attr.h>
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;
- nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
+ nlmsg_parse(nh, sizeof(struct ifinfomsg), nla, __IFLA_MAX - 1, NULL);
if (!nla[IFLA_IFNAME])
goto out;
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;
}
}
+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
system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned int apply_mask)
{
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) {
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)
.ifa_family = (alen == 4) ? AF_INET : AF_INET6,
.ifa_prefixlen = addr->mask,
.ifa_index = dev->ifindex,
+ .ifa_flags = (addr->flags & DEVADDR_OFFLINK) ? IFA_F_NOPREFIXROUTE : 0,
};
struct nl_msg *msg;
table = RT_TABLE_MAIN;
else if (!strcmp(name, "local"))
table = RT_TABLE_LOCAL;
+ else if (!strcmp(name, "prelocal"))
+ table = RT_TABLE_PRELOCAL;
/* try to look up name in /etc/iproute2/rt_tables */
else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
rule.priority = 0;
+ rule.lookup = RT_TABLE_PRELOCAL;
+ rv |= system_iprule(&rule, RTM_NEWRULE);
+
+ rule.priority = 1;
rule.lookup = RT_TABLE_LOCAL;
rv |= system_iprule(&rule, RTM_NEWRULE);
rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
rule.priority = 0;
+ rule.lookup = RT_TABLE_PRELOCAL;
+ rv |= system_iprule(&rule, RTM_NEWRULE);
+
+ rule.priority = 1;
rule.lookup = RT_TABLE_LOCAL;
rv |= system_iprule(&rule, RTM_NEWRULE);