From 458b1a7e9473c150a40cae5d8be174f4bb03bd39 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Sat, 12 Dec 2020 21:50:53 +0100 Subject: netifd: add segment routing support seg6_enabled - Bool Accept or drop SR-enabled IPv6 packets on this interface. More Information: https://www.kernel.org/doc/html/latest/networking/seg6-sysctl.html Now you can set as interface option option ip6segmentrouting '1' It is not enough to turn on "seg6_enabled" on the interface. Further, we have to enable "/all/seg6_enabled". This means that a working config is "interface + all". Signed-off-by: Nick Hainke Signed-off-by: Hans Dedecker [style fixes] --- device.c | 21 +++++++++++++++++++++ device.h | 5 +++++ system-linux.c | 25 +++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/device.c b/device.c index 73cc4bf..4243c18 100644 --- a/device.c +++ b/device.c @@ -36,6 +36,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_TXQUEUELEN] = { .name = "txqueuelen", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_ENABLED] = { .name = "enabled", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_IPV6] = { .name = "ipv6", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_IP6SEGMENTROUTING] = { .name = "ip6segmentrouting", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_PROMISC] = { .name = "promisc", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_RPFILTER] = { .name = "rpfilter", .type = BLOBMSG_TYPE_STRING }, [DEV_ATTR_ACCEPTLOCAL] = { .name = "acceptlocal", .type = BLOBMSG_TYPE_BOOL }, @@ -230,6 +231,7 @@ device_merge_settings(struct device *dev, struct device_settings *n) (s->flags & (DEV_OPT_MACADDR|DEV_OPT_DEFAULT_MACADDR) ? s->macaddr : os->macaddr), sizeof(n->macaddr)); n->ipv6 = s->flags & DEV_OPT_IPV6 ? s->ipv6 : os->ipv6; + n->ip6segmentrouting = s->flags & DEV_OPT_IP6SEGMENTROUTING ? s->ip6segmentrouting : os->ip6segmentrouting; n->promisc = s->flags & DEV_OPT_PROMISC ? s->promisc : os->promisc; n->rpfilter = s->flags & DEV_OPT_RPFILTER ? s->rpfilter : os->rpfilter; n->acceptlocal = s->flags & DEV_OPT_ACCEPTLOCAL ? s->acceptlocal : os->acceptlocal; @@ -299,6 +301,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb) s->flags |= DEV_OPT_IPV6; } + if ((cur = tb[DEV_ATTR_IP6SEGMENTROUTING])) { + s->ip6segmentrouting = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_IP6SEGMENTROUTING; + } + if ((cur = tb[DEV_ATTR_PROMISC])) { s->promisc = blobmsg_get_bool(cur); s->flags |= DEV_OPT_PROMISC; @@ -844,6 +851,18 @@ device_init_pending(void) } } +bool +device_check_ip6segmentrouting(void) +{ + struct device *dev; + bool ip6segmentrouting = false; + + avl_for_each_element(&devices, dev, avl) + ip6segmentrouting |= dev->settings.ip6segmentrouting; + + return ip6segmentrouting; +} + static enum dev_change_type device_set_config(struct device *dev, struct device_type *type, struct blob_attr *attr) @@ -1053,6 +1072,8 @@ device_dump_status(struct blob_buf *b, struct device *dev) blobmsg_add_u32(b, "txqueuelen", st.txqueuelen); if (st.flags & DEV_OPT_IPV6) blobmsg_add_u8(b, "ipv6", st.ipv6); + if (st.flags & DEV_OPT_IP6SEGMENTROUTING) + blobmsg_add_u8(b, "ip6segmentrouting", st.ip6segmentrouting); if (st.flags & DEV_OPT_PROMISC) blobmsg_add_u8(b, "promisc", st.promisc); if (st.flags & DEV_OPT_RPFILTER) diff --git a/device.h b/device.h index ab5a162..dc410b4 100644 --- a/device.h +++ b/device.h @@ -53,6 +53,7 @@ enum { DEV_ATTR_SENDREDIRECTS, DEV_ATTR_NEIGHLOCKTIME, DEV_ATTR_ISOLATE, + DEV_ATTR_IP6SEGMENTROUTING, __DEV_ATTR_MAX, }; @@ -107,6 +108,7 @@ enum { DEV_OPT_SENDREDIRECTS = (1 << 21), DEV_OPT_NEIGHLOCKTIME = (1 << 22), DEV_OPT_ISOLATE = (1 << 23), + DEV_OPT_IP6SEGMENTROUTING = (1 << 24), }; /* events broadcasted to all users of a device */ @@ -173,6 +175,7 @@ struct device_settings { bool learning; bool unicast_flood; bool sendredirects; + bool ip6segmentrouting; bool isolate; }; @@ -320,4 +323,6 @@ device_set_disabled(struct device *dev, bool value) device_refresh_present(dev); } +bool device_check_ip6segmentrouting(void); + #endif diff --git a/system-linux.c b/system-linux.c index bf746f9..c57ecab 100644 --- a/system-linux.c +++ b/system-linux.c @@ -304,6 +304,11 @@ static void system_set_disable_ipv6(struct device *dev, const char *val) system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val); } +static void system_set_ip6segmentrouting(struct device *dev, const char *val) +{ + system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/seg6_enabled", dev->ifname, val); +} + static void system_set_rpfilter(struct device *dev, const char *val) { system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val); @@ -509,6 +514,12 @@ static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t b dev->ifname, buf, buf_sz); } +static int system_get_ip6segmentrouting(struct device *dev, char *buf, const size_t buf_sz) +{ + return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/seg6_enabled", + dev->ifname, buf, buf_sz); +} + static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz) { return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", @@ -1572,6 +1583,11 @@ system_if_get_settings(struct device *dev, struct device_settings *s) s->flags |= DEV_OPT_IPV6; } + if (!system_get_ip6segmentrouting(dev, buf, sizeof(buf))) { + s->ip6segmentrouting = strtoul(buf, NULL, 0); + s->flags |= DEV_OPT_IP6SEGMENTROUTING; + } + if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) { s->promisc = ifr.ifr_flags & IFF_PROMISC; s->flags |= DEV_OPT_PROMISC; @@ -1667,6 +1683,15 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned } if (apply_mask & DEV_OPT_IPV6) system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1"); + if (s->flags & DEV_OPT_IP6SEGMENTROUTING & apply_mask) { + struct device dummy = { + .ifname = "all", + }; + bool ip6segmentrouting = device_check_ip6segmentrouting(); + + system_set_ip6segmentrouting(dev, s->ip6segmentrouting ? "1" : "0"); + system_set_ip6segmentrouting(&dummy, ip6segmentrouting ? "1" : "0"); + } if (apply_mask & DEV_OPT_PROMISC) { if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0, !s->promisc ? IFF_PROMISC : 0) < 0) -- cgit v1.2.1