X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=system-linux.c;h=0ca525602d9ea63ac5b845b2be9c6c7bdec7c26c;hp=0ac4ae626c10307bc728a5019be9bd1b0b5d60db;hb=c06f84238952211b35c2940a82fcce3fcc3221c1;hpb=7573880ac042c6e5c8d48b1ad83d357b5e02743b diff --git a/system-linux.c b/system-linux.c index 0ac4ae6..0ca5256 100644 --- a/system-linux.c +++ b/system-linux.c @@ -346,6 +346,11 @@ static void system_bridge_set_hairpin_mode(struct device *dev, const char *val) system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val); } +static void system_bridge_set_isolate_mode(struct device *dev, const char *val) +{ + system_set_dev_sysctl("/sys/class/net/%s/brport/isolate_mode", dev->ifname, val); +} + static void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge) { system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" : @@ -543,16 +548,20 @@ out: static void handle_hotplug_msg(char *data, int size) { - const char *subsystem = NULL, *interface = NULL; + const char *subsystem = NULL, *interface = NULL, *interface_old = NULL; char *cur, *end, *sep; struct device *dev; int skip; - bool add; + bool add, move = false; if (!strncmp(data, "add@", 4)) add = true; else if (!strncmp(data, "remove@", 7)) add = false; + else if (!strncmp(data, "move@", 5)) { + add = true; + move = true; + } else return; @@ -573,12 +582,32 @@ handle_hotplug_msg(char *data, int size) subsystem = sep + 1; if (strcmp(subsystem, "net") != 0) return; + } else if (!strcmp(cur, "DEVPATH_OLD")) { + interface_old = strrchr(sep + 1, '/'); + if (interface_old) + interface_old++; } - if (subsystem && interface) + } + + if (subsystem && interface) { + if (move && interface_old) + goto move; + else goto found; } + return; +move: + dev = device_find(interface_old); + if (!dev) + goto found; + + if (dev->type != &simple_device_type) + goto found; + + device_set_present(dev, false); + found: dev = device_find(interface); if (!dev) @@ -708,7 +737,7 @@ int system_bridge_addif(struct device *bridge, struct device *dev) system_bridge_set_wireless(bridge, dev); if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) { - snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router); + snprintf(buf, sizeof(buf), "%u", dev->settings.multicast_router); system_bridge_set_multicast_router(dev, buf, false); } @@ -724,6 +753,10 @@ int system_bridge_addif(struct device *bridge, struct device *dev) !dev->settings.unicast_flood) system_bridge_set_unicast_flood(dev, "0"); + if (dev->settings.flags & DEV_OPT_ISOLATE && + dev->settings.isolate) + system_bridge_set_isolate_mode(dev, "1"); + return ret; } @@ -995,7 +1028,7 @@ static void system_bridge_conf_multicast(struct device *bridge, bridge->ifname, buf); if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) { - snprintf(buf, buf_len, "%i", bridge->settings.multicast_router); + snprintf(buf, buf_len, "%u", bridge->settings.multicast_router); system_bridge_set_multicast_router(bridge, buf, true); } @@ -1362,7 +1395,7 @@ system_if_get_settings(struct device *dev, struct device_settings *s) } if (!system_get_neigh4locktime(dev, buf, sizeof(buf))) { - s->neigh4locktime = strtoul(buf, NULL, 0); + s->neigh4locktime = strtol(buf, NULL, 0); s->flags |= DEV_OPT_NEIGHLOCKTIME; } @@ -1387,40 +1420,6 @@ system_if_get_settings(struct device *dev, struct device_settings *s) } } -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); - - globfree(&gl); -} - -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) { @@ -1456,23 +1455,23 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned s->flags &= ~DEV_OPT_PROMISC; } if (s->flags & DEV_OPT_RPFILTER & apply_mask) { - snprintf(buf, sizeof(buf), "%d", s->rpfilter); + snprintf(buf, sizeof(buf), "%u", s->rpfilter); system_set_rpfilter(dev, buf); } if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask) system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0"); if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) { - snprintf(buf, sizeof(buf), "%d", s->igmpversion); + snprintf(buf, sizeof(buf), "%u", s->igmpversion); system_set_igmpversion(dev, buf); } if (s->flags & DEV_OPT_MLDVERSION & apply_mask) { - snprintf(buf, sizeof(buf), "%d", s->mldversion); + snprintf(buf, sizeof(buf), "%u", s->mldversion); system_set_mldversion(dev, buf); } if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) { - snprintf(buf, sizeof(buf), "%d", s->neigh4reachabletime); + snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime); system_set_neigh4reachabletime(dev, buf); - snprintf(buf, sizeof(buf), "%d", s->neigh6reachabletime); + snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime); system_set_neigh6reachabletime(dev, buf); } if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) { @@ -1480,13 +1479,13 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned system_set_neigh4locktime(dev, buf); } if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) { - snprintf(buf, sizeof(buf), "%d", s->neigh4gcstaletime); + snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime); system_set_neigh4gcstaletime(dev, buf); - snprintf(buf, sizeof(buf), "%d", s->neigh6gcstaletime); + snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime); system_set_neigh6gcstaletime(dev, buf); } if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) { - snprintf(buf, sizeof(buf), "%d", s->dadtransmits); + snprintf(buf, sizeof(buf), "%u", s->dadtransmits); system_set_dadtransmits(dev, buf); } if (s->flags & DEV_OPT_MULTICAST & apply_mask) { @@ -1496,8 +1495,6 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned } if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask) system_set_sendredirects(dev, s->sendredirects ? "1" : "0"); - - system_if_apply_rps_xps(dev, s); } int system_if_up(struct device *dev) @@ -2171,6 +2168,9 @@ static int system_iprule(struct iprule *rule, int cmd) nla_put_u32(msg, FRA_TABLE, rule->lookup); } + if (rule->flags & IPRULE_SUP_PREFIXLEN) + nla_put_u32(msg, FRA_SUPPRESS_PREFIXLEN, rule->sup_prefixlen); + if (rule->flags & IPRULE_GOTO) nla_put_u32(msg, FRA_GOTO, rule->gotoid); @@ -2260,6 +2260,143 @@ static int tunnel_ioctl(const char *name, int cmd, void *p) } #ifdef IFLA_IPTUN_MAX +static int system_add_ip6_tunnel(const char *name, const unsigned int link, + struct blob_attr **tb) +{ + struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK, + NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE); + struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC }; + struct blob_attr *cur; + int ret = 0, ttl = 0; + + if (!nlm) + return -1; + + nlmsg_append(nlm, &ifi, sizeof(ifi), 0); + nla_put_string(nlm, IFLA_IFNAME, name); + + if (link) + nla_put_u32(nlm, IFLA_LINK, link); + + struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO); + if (!linkinfo) { + ret = -ENOMEM; + goto failure; + } + + nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl"); + struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA); + if (!infodata) { + ret = -ENOMEM; + goto failure; + } + + if (link) + nla_put_u32(nlm, IFLA_IPTUN_LINK, link); + + if ((cur = tb[TUNNEL_ATTR_TTL])) + ttl = blobmsg_get_u32(cur); + + nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP); + nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64); + nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4); + + struct in6_addr in6buf; + if ((cur = tb[TUNNEL_ATTR_LOCAL])) { + if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) { + ret = -EINVAL; + goto failure; + } + nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf); + } + + if ((cur = tb[TUNNEL_ATTR_REMOTE])) { + if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) { + ret = -EINVAL; + goto failure; + } + nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf); + } + +#ifdef IFLA_IPTUN_FMR_MAX + if ((cur = tb[TUNNEL_ATTR_DATA])) { + struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS); + struct blob_attr *dcur; + unsigned drem, fmrcnt = 0; + + blobmsg_for_each_attr(dcur, cur, drem) { + if (blobmsg_type(dcur) != BLOBMSG_TYPE_ARRAY || + strcmp(blobmsg_name(dcur), "fmrs") || + blobmsg_check_array(dcur, BLOBMSG_TYPE_UNSPEC) <= 0) + continue; + + struct blob_attr *rcur; + unsigned rrem; + blobmsg_for_each_attr(rcur, dcur, rrem) { + struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur; + struct in6_addr ip6prefix; + struct in_addr ip4prefix; + unsigned ip4len, ip6len, ealen, offset; + + blobmsg_parse(fmr_data_attr_list.params, __FMR_DATA_ATTR_MAX, tb_fmr, + blobmsg_data(rcur), blobmsg_len(rcur)); + + if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX6]) || + !parse_ip_and_netmask(AF_INET6, + blobmsg_data(tb_cur), &ip6prefix, + &ip6len)) { + ret = -EINVAL; + goto failure; + } + + if (!(tb_cur = tb_fmr[FMR_DATA_PREFIX4]) || + !parse_ip_and_netmask(AF_INET, + blobmsg_data(tb_cur), &ip4prefix, + &ip4len)) { + ret = -EINVAL; + goto failure; + } + + if (!(tb_cur = tb_fmr[FMR_DATA_EALEN])) { + ret = -EINVAL; + goto failure; + } + ealen = blobmsg_get_u32(tb_cur); + + if (!(tb_cur = tb_fmr[FMR_DATA_OFFSET])) { + ret = -EINVAL; + goto failure; + } + offset = blobmsg_get_u32(tb_cur); + + struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt); + + nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix); + nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix); + nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len); + nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len); + nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen); + nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset); + + nla_nest_end(nlm, rule); + } + } + nla_nest_end(nlm, fmrs); + } +#endif + + nla_nest_end(nlm, infodata); + nla_nest_end(nlm, linkinfo); + + return system_rtnl_call(nlm); + +failure: + nlmsg_free(nlm); + return ret; +} +#endif + +#ifdef IFLA_IPTUN_MAX #define IP6_FLOWINFO_TCLASS htonl(0x0FF00000) static int system_add_gre_tunnel(const char *name, const char *kind, const unsigned int link, struct blob_attr **tb, bool v6) @@ -2443,10 +2580,10 @@ static int system_add_gre_tunnel(const char *name, const char *kind, nla_put_u16(nlm, IFLA_GRE_IFLAGS, iflags); if (okey) - nla_put_u32(nlm, IFLA_GRE_OKEY, okey); + nla_put_u32(nlm, IFLA_GRE_OKEY, htonl(okey)); if (ikey) - nla_put_u32(nlm, IFLA_GRE_IKEY, ikey); + nla_put_u32(nlm, IFLA_GRE_IKEY, htonl(ikey)); nla_nest_end(nlm, infodata); nla_nest_end(nlm, linkinfo); @@ -2671,6 +2808,17 @@ static int system_add_vxlan(const char *name, const unsigned int link, struct bl } nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port)); + if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) { + bool rxcsum = blobmsg_get_bool(cur); + nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum); + } + + if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) { + bool txcsum = blobmsg_get_bool(cur); + nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum); + nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum); + } + if ((cur = tb[TUNNEL_ATTR_TOS])) { char *str = blobmsg_get_string(cur); unsigned tos = 1; @@ -2737,7 +2885,7 @@ static int system_add_sit_tunnel(const char *name, const unsigned int link, stru p6.prefixlen = mask; } - if ((cur = tb[SIXRD_DATA_RELAY_PREFIX])) { + if ((cur = tb_data[SIXRD_DATA_RELAY_PREFIX])) { if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur), &p6.relay_prefix, &mask) || mask > 32) { ret = -EINVAL; @@ -2913,107 +3061,7 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) return system_add_sit_tunnel(name, link, tb); #ifdef IFLA_IPTUN_MAX else if (!strcmp(str, "ipip6")) { - struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK, - NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE); - struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC }; - int ret = 0; - - if (!nlm) - return -1; - - nlmsg_append(nlm, &ifi, sizeof(ifi), 0); - nla_put_string(nlm, IFLA_IFNAME, name); - - if (link) - nla_put_u32(nlm, IFLA_LINK, link); - - struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO); - if (!linkinfo) { - ret = -ENOMEM; - goto failure; - } - nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl"); - struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA); - if (!infodata) { - ret = -ENOMEM; - goto failure; - } - - if (link) - nla_put_u32(nlm, IFLA_IPTUN_LINK, link); - - nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP); - nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64); - nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4); - - struct in6_addr in6buf; - if ((cur = tb[TUNNEL_ATTR_LOCAL])) { - if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) { - ret = -EINVAL; - goto failure; - } - nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf); - } - - if ((cur = tb[TUNNEL_ATTR_REMOTE])) { - if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) { - ret = -EINVAL; - goto failure; - } - nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf); - } - -#ifdef IFLA_IPTUN_FMR_MAX - if ((cur = tb[TUNNEL_ATTR_FMRS])) { - struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS); - - struct blob_attr *fmr; - unsigned rem, fmrcnt = 0; - blobmsg_for_each_attr(fmr, cur, rem) { - if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING) - continue; - - unsigned ip4len, ip6len, ealen, offset = 6; - char ip6buf[48]; - char ip4buf[16]; - - if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u", - ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) { - ret = -EINVAL; - goto failure; - } - - struct in6_addr ip6prefix; - struct in_addr ip4prefix; - if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 || - inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) { - ret = -EINVAL; - goto failure; - } - - struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt); - - nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix); - nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix); - nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len); - nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len); - nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen); - nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset); - - nla_nest_end(nlm, rule); - } - - nla_nest_end(nlm, fmrs); - } -#endif - - nla_nest_end(nlm, infodata); - nla_nest_end(nlm, linkinfo); - - return system_rtnl_call(nlm); -failure: - nlmsg_free(nlm); - return ret; + return system_add_ip6_tunnel(name, link, tb); } else if (!strcmp(str, "greip")) { return system_add_gre_tunnel(name, "gre", link, tb, false); } else if (!strcmp(str, "gretapip")) {