From: Michele Dionisio Date: Tue, 5 Nov 2024 10:53:30 +0000 (+0100) Subject: networkd: add possibility to specify MulticastIGMPVersion X-Git-Tag: v257-rc1~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d865abf9eb50bc484c1671c323e9e59e204b0a5b;p=thirdparty%2Fsystemd.git networkd: add possibility to specify MulticastIGMPVersion --- diff --git a/NEWS b/NEWS index 54d26249517..9ffc8ba23b3 100644 --- a/NEWS +++ b/NEWS @@ -2222,6 +2222,10 @@ CHANGES WITH 255: specific devices explicitly. NetworkManager will soon implement a similar logic. + * .network files gained a new MulticastIGMPVersion= setting in the + [Network] section, to control sysctl's + /proc/sys/net/ipv4/conf/INTERFACE/force_igmp_version setting. + systemctl: * systemctl is-failed now checks the system state if no unit is diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 6523c944ef3..5090d3fb636 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1004,6 +1004,27 @@ DuplicateAddressDetection=none + + MulticastIGMPVersion= + + Configures IPv4 Multicast IGMP Version to be used, and controls the value of + /proc/sys/net/ipv4/conf/INTERFACE/force_igmp_version. + Takes one of no, + v1, v2, or v3. + When no, no enforcement of an IGMP version will be applied, IGMPv1/v2 fallback are allowed, will back to + IGMPv3 mode again if all IGMPv1/v2 Querier Present timer expire. + When v1, use of IGMP version 1 will be enforced, and IGMPv1 report will be replied even if IGMPv2/v3 + queries are received. + When v2, use of IGMP version 2 will be enforced, and IGMPv2 report will be replied if an IGMPv2/v3 query + is received, but fallback to IGMPv1 if an IGMPv1 query is received. + When v3, use of IGMP version 3 will be enforced, and the same reaction will be done as no. + Defaults to unset, and the sysctl value will be unchanged. + + + + + + IPv4AcceptLocal= diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 50be74e55f4..ab7f2553ec0 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -150,6 +150,7 @@ Network.IPv4ProxyARPPrivateVLAN, config_parse_tristate, Network.ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp) Network.IPv6ProxyNDPAddress, config_parse_ipv6_proxy_ndp_address, 0, 0 Network.IPv4ReversePathFilter, config_parse_ip_reverse_path_filter, 0, offsetof(Network, ipv4_rp_filter) +Network.MulticastIGMPVersion, config_parse_ipv4_force_igmp_version, 0, offsetof(Network, ipv4_force_igmp_version) Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier) Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier) Network.IgnoreCarrierLoss, config_parse_ignore_carrier_loss, 0, 0 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 97bfe65394e..24885308292 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -481,6 +481,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .proxy_arp = -1, .proxy_arp_pvlan = -1, .ipv4_rp_filter = _IP_REVERSE_PATH_FILTER_INVALID, + .ipv4_force_igmp_version = _IPV4_FORCE_IGMP_VERSION_INVALID, .ndisc = -1, .ndisc_use_redirect = true, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 30ea9ac3526..3ea94e0e49d 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -340,6 +340,7 @@ struct Network { uint32_t ipv6_mtu; IPv6PrivacyExtensions ipv6_privacy_extensions; IPReversePathFilter ipv4_rp_filter; + IPv4ForceIgmpVersion ipv4_force_igmp_version; int ipv6_proxy_ndp; Set *ipv6_proxy_ndp_addresses; diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c index 17a2c6da38b..10a35bc44bc 100644 --- a/src/network/networkd-sysctl.c +++ b/src/network/networkd-sysctl.c @@ -408,6 +408,18 @@ static int link_set_ipv4_rp_filter(Link *link) { return sysctl_write_ip_property_int(AF_INET, link->ifname, "rp_filter", link->network->ipv4_rp_filter, manager_get_sysctl_shadow(link->manager)); } +static int link_set_ipv4_force_igmp_version(Link *link) { + assert(link); + + if (!link_is_configured_for_family(link, AF_INET)) + return 0; + + if (link->network->ipv4_force_igmp_version < 0) + return 0; + + return sysctl_write_ip_property_int(AF_INET, link->ifname, "force_igmp_version", link->network->ipv4_force_igmp_version, manager_get_sysctl_shadow(link->manager)); +} + static int link_set_ipv6_privacy_extensions(Link *link) { IPv6PrivacyExtensions val; @@ -723,6 +735,10 @@ int link_set_sysctl(Link *link) { if (r < 0) log_link_warning_errno(link, r, "Cannot set IPv4 reverse path filtering for interface, ignoring: %m"); + r = link_set_ipv4_force_igmp_version(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv4 force igmp version, ignoring: %m"); + r = link_set_ipv4_promote_secondaries(link); if (r < 0) log_link_warning_errno(link, r, "Cannot enable promote_secondaries for interface, ignoring: %m"); @@ -770,3 +786,13 @@ int config_parse_ip_forward_deprecated( "and the same settings in .network files for per-interface setting."); return 0; } + +static const char* const ipv4_force_igmp_version_table[_IPV4_FORCE_IGMP_VERSION_MAX] = { + [IPV4_FORCE_IGMP_VERSION_NO] = "no", + [IPV4_FORCE_IGMP_VERSION_1] = "v1", + [IPV4_FORCE_IGMP_VERSION_2] = "v2", + [IPV4_FORCE_IGMP_VERSION_3] = "v3", +}; + +DEFINE_STRING_TABLE_LOOKUP(ipv4_force_igmp_version, IPv4ForceIgmpVersion); +DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv4_force_igmp_version, ipv4_force_igmp_version, IPv4ForceIgmpVersion); diff --git a/src/network/networkd-sysctl.h b/src/network/networkd-sysctl.h index 1c19fbd2d6f..ea1d2bc897d 100644 --- a/src/network/networkd-sysctl.h +++ b/src/network/networkd-sysctl.h @@ -53,3 +53,18 @@ IPReversePathFilter ip_reverse_path_filter_from_string(const char *s) _pure_; CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions); CONFIG_PARSER_PROTOTYPE(config_parse_ip_reverse_path_filter); CONFIG_PARSER_PROTOTYPE(config_parse_ip_forward_deprecated); + +typedef enum IPv4ForceIgmpVersion { + /* These values map to the kernel's /proc/sys/net/ipv4/conf/INTERFACE/force_igmp_version values. Do not reorder! */ + IPV4_FORCE_IGMP_VERSION_NO = 0, + IPV4_FORCE_IGMP_VERSION_1 = 1, + IPV4_FORCE_IGMP_VERSION_2 = 2, + IPV4_FORCE_IGMP_VERSION_3 = 3, + _IPV4_FORCE_IGMP_VERSION_MAX, + _IPV4_FORCE_IGMP_VERSION_INVALID = -EINVAL, +} IPv4ForceIgmpVersion; + +const char* ipv4_force_igmp_version_to_string(IPv4ForceIgmpVersion i) _const_; +IPv4ForceIgmpVersion ipv4_force_igmp_version_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_ipv4_force_igmp_version); diff --git a/test/test-network/conf/25-sysctl.network b/test/test-network/conf/25-sysctl.network index 759fe65fe88..dcc4f0d293a 100644 --- a/test/test-network/conf/25-sysctl.network +++ b/test/test-network/conf/25-sysctl.network @@ -13,3 +13,4 @@ IPv6ProxyNDP=yes IPv6AcceptRA=no IPv4AcceptLocal=yes IPv4ReversePathFilter=no +MulticastIGMPVersion=v1 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index c7d75d8a670..8ee94a02946 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -4381,6 +4381,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp_pvlan', '1') self.check_ipv4_sysctl_attr('dummy98', 'accept_local', '1') self.check_ipv4_sysctl_attr('dummy98', 'rp_filter', '0') + self.check_ipv4_sysctl_attr('dummy98', 'force_igmp_version', '1') copy_network_unit('25-sysctl.network.d/25-ipv6-privacy-extensions.conf') networkctl_reload()