about summary refs log tree commit diff
path: root/src/libnm-platform
diff options
context:
space:
mode:
authorSebastien Bacher <seb128@ubuntu.com>2021-09-27 13:36:59 +0200
committerSebastien Bacher <seb128@ubuntu.com>2021-09-27 13:38:47 +0200
commit77097921e09de99e0b66b43a541ec35004e64630 (patch)
treec36633d782404ea31955254a2133cf9cf036d81e /src/libnm-platform
parent0e7561c087918ef6b0e8a64155109d3b005e700c (diff)
parent2bfcbfb13b1672c072e4f902260d2122b3e3c122 (diff)
Update upstream source from tag 'upstream/1.32.12'
Update to upstream version '1.32.12'
with Debian dir 8a9c3ca7f117acef29e7880aa507a1c3ab742155
Diffstat (limited to 'src/libnm-platform')
-rw-r--r--src/libnm-platform/nm-platform-utils.c198
-rw-r--r--src/libnm-platform/nm-platform-utils.h3
-rw-r--r--src/libnm-platform/nm-platform.c39
-rw-r--r--src/libnm-platform/tests/test-nm-platform.c41
-rw-r--r--src/libnm-platform/wpan/nm-wpan-utils.c3
5 files changed, 238 insertions, 46 deletions
diff --git a/src/libnm-platform/nm-platform-utils.c b/src/libnm-platform/nm-platform-utils.c
index 2470704a..ce847451 100644
--- a/src/libnm-platform/nm-platform-utils.c
+++ b/src/libnm-platform/nm-platform-utils.c
@@ -7,9 +7,10 @@
 
 #include "nm-platform-utils.h"
 
+#include "libnm-std-aux/nm-linux-compat.h"
+
 #include <unistd.h>
 #include <sys/ioctl.h>
-#include <linux/ethtool.h>
 #include <linux/sockios.h>
 #include <linux/mii.h>
 #include <linux/if.h>
@@ -1331,10 +1332,6 @@ nmp_utils_ethtool_get_link_settings(int                       ifindex,
 }
 
 #define ADVERTISED_INVALID 0
-#define BASET_ALL_MODES                                                                 \
-    (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half       \
-     | ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full \
-     | ADVERTISED_10000baseT_Full)
 
 static guint32
 get_baset_mode(guint32 speed, NMPlatformLinkDuplexType duplex)
@@ -1386,6 +1383,96 @@ platform_link_duplex_type_to_native(NMPlatformLinkDuplexType duplex_type, guint8
     }
 }
 
+const guint8 _nmp_link_mode_all_advertised_modes_bits[] = {
+    ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+    ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+    ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+    ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+    ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+    ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+    ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+    ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
+    ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+    ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+    ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+    ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+    ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT,
+    ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
+    ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
+    ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
+    ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
+    ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
+    ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
+    ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
+    ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
+    ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
+    ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
+    /* 32 bit flags start here. */
+    ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
+    ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
+    ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
+    ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
+    ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
+    ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
+    ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
+    ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+    ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
+    ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
+    ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
+    ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+    ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+    ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
+    ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
+    ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
+    ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
+    ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT,
+    ETHTOOL_LINK_MODE_100baseT1_Full_BIT,
+    ETHTOOL_LINK_MODE_1000baseT1_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseKR_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseSR_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseCR_Full_BIT,
+    ETHTOOL_LINK_MODE_100000baseDR_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT,
+    ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT,
+    ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT,
+    ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
+    ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
+};
+
+/* these are the bits from _nmp_link_mode_all_advertised_modes_bits set. */
+const guint32 _nmp_link_mode_all_advertised_modes[] = {
+    0xfffe903fu,
+    0xfff1ffffu,
+    0x0ffffbffu,
+};
+
 static NMOptionBool
 set_link_settings_new(SocketHandle *           shandle,
                       gboolean                 autoneg,
@@ -1396,6 +1483,7 @@ set_link_settings_new(SocketHandle *           shandle,
     gs_free struct ethtool_link_settings *edata = NULL;
     gsize                                 edata_size;
     guint                                 nwords;
+    guint                                 i;
 
     edata0 = (struct ethtool_link_settings){
         .cmd                    = ETHTOOL_GLINKSETTINGS,
@@ -1421,16 +1509,14 @@ set_link_settings_new(SocketHandle *           shandle,
 
     /* then change the needed ones */
     edata->cmd = ETHTOOL_SLINKSETTINGS;
-    if (autoneg) {
-        edata->autoneg = AUTONEG_ENABLE;
 
-        /* copy @map_supported to @map_advertising and @map_lp_advertising */
-        memcpy(&edata->link_mode_masks[nwords],
-               &edata->link_mode_masks[0],
-               sizeof(guint32) * nwords);
-        memcpy(&edata->link_mode_masks[nwords * 2],
-               &edata->link_mode_masks[0],
-               sizeof(guint32) * nwords);
+    {
+        const guint32 *v_map_supported      = &edata->link_mode_masks[0];
+        guint32 *      v_map_advertising    = &edata->link_mode_masks[nwords];
+        guint32 *      v_map_lp_advertising = &edata->link_mode_masks[2 * nwords];
+
+        memcpy(v_map_advertising, v_map_supported, sizeof(guint32) * nwords);
+        (void) v_map_lp_advertising;
 
         if (speed != 0) {
             guint32 mode;
@@ -1438,6 +1524,8 @@ set_link_settings_new(SocketHandle *           shandle,
             mode = get_baset_mode(speed, duplex);
 
             if (mode == ADVERTISED_INVALID) {
+                if (!autoneg)
+                    goto set_autoneg;
                 nm_log_trace(LOGD_PLATFORM,
                              "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised",
                              shandle->ifindex,
@@ -1446,8 +1534,9 @@ set_link_settings_new(SocketHandle *           shandle,
                 return FALSE;
             }
 
-            /* We only support BASE-T modes in the first word */
-            if (!(edata->link_mode_masks[0] & mode)) {
+            if (!(v_map_supported[0] & mode)) {
+                if (!autoneg)
+                    goto set_autoneg;
                 nm_log_trace(LOGD_PLATFORM,
                              "ethtool[%d]: device does not support %uBASE-T %s duplex mode",
                              shandle->ifindex,
@@ -1456,11 +1545,16 @@ set_link_settings_new(SocketHandle *           shandle,
                 return FALSE;
             }
 
-            edata->link_mode_masks[nwords] =
-                (edata->link_mode_masks[nwords] & ~BASET_ALL_MODES) | mode;
-            edata->link_mode_masks[nwords * 2] = edata->link_mode_masks[nwords];
+            for (i = 0; i < (guint) G_N_ELEMENTS(_nmp_link_mode_all_advertised_modes); i++)
+                v_map_advertising[i] &= ~_nmp_link_mode_all_advertised_modes[i];
+            v_map_advertising[0] |= mode;
         }
-    } else {
+    }
+
+set_autoneg:
+    if (autoneg)
+        edata->autoneg = AUTONEG_ENABLE;
+    else {
         edata->autoneg = AUTONEG_DISABLE;
 
         if (speed)
@@ -1489,6 +1583,13 @@ nmp_utils_ethtool_set_link_settings(int                      ifindex,
                              || (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN),
                          FALSE);
 
+    nm_log_trace(LOGD_PLATFORM,
+                 "ethtool[%d]: set link: autoneg=%d, speed=%d, duplex=%s",
+                 ifindex,
+                 autoneg,
+                 speed,
+                 nm_platform_link_duplex_type_to_string(duplex));
+
     ret = set_link_settings_new(&shandle, autoneg, speed, duplex);
     if (ret != NM_OPTION_BOOL_DEFAULT)
         return ret;
@@ -1501,34 +1602,41 @@ nmp_utils_ethtool_set_link_settings(int                      ifindex,
 
     /* then change the needed ones */
     edata.cmd = ETHTOOL_SSET;
-    if (autoneg) {
-        edata.autoneg = AUTONEG_ENABLE;
-        if (speed == 0)
-            edata.advertising = edata.supported;
-        else {
-            guint32 mode;
 
-            mode = get_baset_mode(speed, duplex);
+    edata.advertising = edata.supported;
+    if (speed != 0) {
+        guint32 mode;
 
-            if (mode == ADVERTISED_INVALID) {
-                nm_log_trace(LOGD_PLATFORM,
-                             "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised",
-                             ifindex,
-                             speed,
-                             nm_platform_link_duplex_type_to_string(duplex));
-                return FALSE;
-            }
-            if (!(edata.supported & mode)) {
-                nm_log_trace(LOGD_PLATFORM,
-                             "ethtool[%d]: device does not support %uBASE-T %s duplex mode",
-                             ifindex,
-                             speed,
-                             nm_platform_link_duplex_type_to_string(duplex));
-                return FALSE;
-            }
-            edata.advertising = (edata.supported & ~BASET_ALL_MODES) | mode;
+        mode = get_baset_mode(speed, duplex);
+
+        if (mode == ADVERTISED_INVALID) {
+            if (!autoneg)
+                goto set_autoneg;
+            nm_log_trace(LOGD_PLATFORM,
+                         "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised",
+                         ifindex,
+                         speed,
+                         nm_platform_link_duplex_type_to_string(duplex));
+            return FALSE;
         }
-    } else {
+        if (!(edata.supported & mode)) {
+            if (!autoneg)
+                goto set_autoneg;
+            nm_log_trace(LOGD_PLATFORM,
+                         "ethtool[%d]: device does not support %uBASE-T %s duplex mode",
+                         ifindex,
+                         speed,
+                         nm_platform_link_duplex_type_to_string(duplex));
+            return FALSE;
+        }
+        edata.advertising &= ~_nmp_link_mode_all_advertised_modes[0];
+        edata.advertising |= mode;
+    }
+
+set_autoneg:
+    if (autoneg)
+        edata.autoneg = AUTONEG_ENABLE;
+    else {
         edata.autoneg = AUTONEG_DISABLE;
 
         if (speed)
diff --git a/src/libnm-platform/nm-platform-utils.h b/src/libnm-platform/nm-platform-utils.h
index d70f4385..5511e8af 100644
--- a/src/libnm-platform/nm-platform-utils.h
+++ b/src/libnm-platform/nm-platform-utils.h
@@ -22,6 +22,9 @@ gboolean    nmp_utils_ethtool_set_wake_on_lan(int                      ifindex,
 
 const char *nm_platform_link_duplex_type_to_string(NMPlatformLinkDuplexType duplex);
 
+extern const guint8  _nmp_link_mode_all_advertised_modes_bits[79];
+extern const guint32 _nmp_link_mode_all_advertised_modes[3];
+
 gboolean nmp_utils_ethtool_get_link_settings(int                       ifindex,
                                              gboolean *                out_autoneg,
                                              guint32 *                 out_speed,
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 6c0d0015..b7a65df5 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -4304,6 +4304,7 @@ nm_platform_ip_route_get_prune_list(NMPlatform *           self,
     CList *                      iter;
     NMPlatformIP4Route           rt_local4;
     NMPlatformIP6Route           rt_local6;
+    NMPlatformIP6Route           rt_mcast6;
     const NMPlatformLink *       pllink;
     const NMPlatformLnkVrf *     lnk_vrf;
     guint32                      local_table;
@@ -4328,6 +4329,7 @@ nm_platform_ip_route_get_prune_list(NMPlatform *           self,
 
     rt_local4.plen = 0;
     rt_local6.plen = 0;
+    rt_mcast6.plen = 0;
 
     routes_prune = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nm_dedup_multi_obj_unref);
 
@@ -4420,6 +4422,43 @@ nm_platform_ip_route_get_prune_list(NMPlatform *           self,
                         == 0)
                         continue;
                 }
+
+                /* Kernels < 5.11 add a route like:
+                 *
+                 * unicast ff00::/8 dev $IFACE proto boot scope global metric 256 pref medium
+                 *
+                 * to allow sending and receiving IPv6 multicast traffic. Don't remove it.
+                 * Since kernel 5.11 the route looks like:
+                 *
+                 * multicast ff00::/8 dev $IFACE proto kernel metric 256 pref medium
+                 *
+                 * As NM ignores routes with rtm_type multicast, there is no need for the code
+                 * below on newer kernels.
+                 */
+                if (nm_platform_ip_route_get_effective_table(&rt->rx) == local_table
+                    && rt->rx.plen == 8 && rt->rx.rt_source == NM_IP_CONFIG_SOURCE_RTPROT_BOOT
+                    && rt->rx.metric == 256 && rt->r6.rt_pref == NM_ICMPV6_ROUTER_PREF_MEDIUM
+                    && IN6_IS_ADDR_UNSPECIFIED(&rt->r6.gateway)) {
+                    if (rt_mcast6.plen == 0) {
+                        rt_mcast6 = (NMPlatformIP6Route){
+                            .ifindex       = ifindex,
+                            .type_coerced  = nm_platform_route_type_coerce(RTN_UNICAST),
+                            .plen          = 8,
+                            .rt_source     = NM_IP_CONFIG_SOURCE_RTPROT_BOOT,
+                            .metric        = 256,
+                            .table_coerced = nm_platform_route_table_coerce(local_table),
+                            .rt_pref       = NM_ICMPV6_ROUTER_PREF_MEDIUM,
+                            .gateway       = IN6ADDR_ANY_INIT,
+                            .network = {{{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}},
+                        };
+                    }
+
+                    if (nm_platform_ip6_route_cmp(&rt->r6,
+                                                  &rt_mcast6,
+                                                  NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
+                        == 0)
+                        continue;
+                }
             }
             break;
 
diff --git a/src/libnm-platform/tests/test-nm-platform.c b/src/libnm-platform/tests/test-nm-platform.c
index 5b1b8e87..d4de0dd5 100644
--- a/src/libnm-platform/tests/test-nm-platform.c
+++ b/src/libnm-platform/tests/test-nm-platform.c
@@ -5,6 +5,7 @@
 #include "libnm-log-core/nm-logging.h"
 #include "libnm-platform/nm-netlink.h"
 #include "libnm-platform/nmp-netns.h"
+#include "libnm-platform/nm-platform-utils.h"
 
 #include "libnm-glib-aux/nm-test-utils.h"
 
@@ -103,6 +104,44 @@ test_use_symbols(void)
 
 /*****************************************************************************/
 
+static void
+test_nmp_link_mode_all_advertised_modes_bits(void)
+{
+    guint32 flags[(SCHAR_MAX + 1) / 32];
+    guint   max_bit;
+    int     i;
+
+    memset(flags, 0, sizeof(flags));
+
+    max_bit = 0;
+    for (i = 0; i < (int) G_N_ELEMENTS(_nmp_link_mode_all_advertised_modes_bits); i++) {
+        if (i > 0) {
+            g_assert_cmpint(_nmp_link_mode_all_advertised_modes_bits[i - 1],
+                            <,
+                            _nmp_link_mode_all_advertised_modes_bits[i]);
+        }
+        g_assert_cmpint(_nmp_link_mode_all_advertised_modes_bits[i], <, SCHAR_MAX);
+        g_assert_cmpint(_nmp_link_mode_all_advertised_modes_bits[i] / 32, <, G_N_ELEMENTS(flags));
+        flags[_nmp_link_mode_all_advertised_modes_bits[i] / 32] |=
+            (1u << (_nmp_link_mode_all_advertised_modes_bits[i] % 32u));
+        max_bit = NM_MAX(max_bit, _nmp_link_mode_all_advertised_modes_bits[i]);
+    }
+
+    g_assert_cmpint((max_bit + 31u) / 32u, ==, G_N_ELEMENTS(_nmp_link_mode_all_advertised_modes));
+
+    for (i = 0; i < (int) G_N_ELEMENTS(_nmp_link_mode_all_advertised_modes); i++) {
+        if (flags[i] != _nmp_link_mode_all_advertised_modes[i]) {
+            g_error("_nmp_link_mode_all_advertised_modes[%d] should be 0x%0x but is 0x%0x "
+                    "(according to the bits in _nmp_link_mode_all_advertised_modes_bits)",
+                    i,
+                    flags[i],
+                    _nmp_link_mode_all_advertised_modes[i]);
+        }
+    }
+}
+
+/*****************************************************************************/
+
 NMTST_DEFINE();
 
 int
@@ -111,6 +150,8 @@ main(int argc, char **argv)
     nmtst_init(&argc, &argv, TRUE);
 
     g_test_add_func("/nm-platform/test_use_symbols", test_use_symbols);
+    g_test_add_func("/nm-platform/test_nmp_link_mode_all_advertised_modes_bits",
+                    test_nmp_link_mode_all_advertised_modes_bits);
 
     return g_test_run();
 }
diff --git a/src/libnm-platform/wpan/nm-wpan-utils.c b/src/libnm-platform/wpan/nm-wpan-utils.c
index 5c2917b4..082cc3e7 100644
--- a/src/libnm-platform/wpan/nm-wpan-utils.c
+++ b/src/libnm-platform/wpan/nm-wpan-utils.c
@@ -7,11 +7,12 @@
 
 #include "nm-wpan-utils.h"
 
+#include "libnm-std-aux/nm-linux-compat.h"
+
 #include <linux/if.h>
 
 #include "libnm-log-core/nm-logging.h"
 #include "libnm-platform/nm-netlink.h"
-#include "linux-headers/nl802154.h"
 #include "libnm-platform/nm-platform-utils.h"
 
 #define _NMLOG_PREFIX_NAME "wpan-nl802154"