]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: add possibility to specify MulticastIGMPVersion
authorMichele Dionisio <michele.dionisio@powersoft.com>
Tue, 5 Nov 2024 10:53:30 +0000 (11:53 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Wed, 6 Nov 2024 15:50:27 +0000 (15:50 +0000)
NEWS
man/systemd.network.xml
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-sysctl.c
src/network/networkd-sysctl.h
test/test-network/conf/25-sysctl.network
test/test-network/systemd-networkd-tests.py

diff --git a/NEWS b/NEWS
index 54d26249517078ef1d9a5281176fddf303c68722..9ffc8ba23b3ef94ffcb28e739eb05c960720aef9 100644 (file)
--- 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
index 6523c944ef31dc229f944acf152f02e3d9dc90c0..5090d3fb6366d6fa09e6f08cd211c145175954c2 100644 (file)
@@ -1004,6 +1004,27 @@ DuplicateAddressDetection=none</programlisting></para>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>MulticastIGMPVersion=</varname></term>
+        <listitem>
+          <para>Configures IPv4 Multicast IGMP Version to be used, and controls the value of
+          <filename>/proc/sys/net/ipv4/conf/<replaceable>INTERFACE</replaceable>/force_igmp_version</filename>.
+          Takes one of <literal>no</literal>,
+          <literal>v1</literal>, <literal>v2</literal>, or <literal>v3</literal>.
+          When <literal>no</literal>, 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 <literal>v1</literal>, use of IGMP version 1 will be enforced, and IGMPv1 report will be replied even if IGMPv2/v3
+          queries are received.
+          When <literal>v2</literal>, 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 <literal>v3</literal>, use of IGMP version 3 will be enforced, and the same reaction will be done as <literal>no</literal>.
+          Defaults to unset, and the sysctl value will be unchanged.
+          </para>
+
+          <xi:include href="version-info.xml" xpointer="v257"/>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>IPv4AcceptLocal=</varname></term>
         <listitem>
index 50be74e55f43e610d6fd605c10de24ce60464815..ab7f2553ec044b5ba5330c9cf949671adba9b49d 100644 (file)
@@ -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
index 97bfe65394e4a9777f251e413719ee3830587125..248853082928135920bbc0fe7f9adf40033234d1 100644 (file)
@@ -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,
index 30ea9ac3526d4cfeb98439466077819ba488a474..3ea94e0e49deac4ad21f189b695bec658c81554a 100644 (file)
@@ -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;
 
index 17a2c6da38b978e3c00b7f3548d5d1acd17169ef..10a35bc44bc886f405c9505fb9ed14ad5884061c 100644 (file)
@@ -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);
index 1c19fbd2d6f2b2a1d8c7fc667a0524dda26ef027..ea1d2bc897d72af6d041689cfd6e8d3537e46752 100644 (file)
@@ -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);
index 759fe65fe88d994c5f3bc7ee89ea67e2975eb36c..dcc4f0d293a3cd3cff5bd5ba1a25045c51603dd7 100644 (file)
@@ -13,3 +13,4 @@ IPv6ProxyNDP=yes
 IPv6AcceptRA=no
 IPv4AcceptLocal=yes
 IPv4ReversePathFilter=no
+MulticastIGMPVersion=v1
index c7d75d8a6709fdb1f4aca63b392aedb0446c077f..8ee94a02946c9d282f0701d7d0ba2fd9d33be1a6 100755 (executable)
@@ -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()