platform: preserve IPv6 multicast route added by kernel

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. Ensure it's not
removed it when we do a route sync in mode ALL.

In kernel 5.11 there were commits:

  https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ceed9038b2783d14e0422bdc6fd04f70580efb4c
  https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a826b04303a40d52439aa141035fca5654ccaccd

After those the route looks like

  multicast ff00::/8 dev $IFACE proto kernel metric 256 pref medium

As NM ignores routes with rtm_type multicast, the code in this commit
is not needed on newer kernels.

https://bugzilla.redhat.com/show_bug.cgi?id=2004212
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/984
This commit is contained in:
Beniamino Galvani 2021-09-17 13:53:18 +02:00
parent 0d4840c484
commit 8003ca68f7

View file

@ -4288,6 +4288,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;
@ -4312,6 +4313,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);
@ -4404,6 +4406,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;