platform: use route mss when deleting IP route

The mss (advmss, RTA_METRICS.RTAX_ADVMSS) is in a way part of
the ID for IPv4 routes. That is, you can add multiple IPv4 routes, that
only differ by mss.

On the other hand, that is not the case for IPv6. Two IPv6 routes
that only differ by mss are considered the same.

Another issue is, that you cannot selectively delete an IPv4 route based
on the mss:

    ip netns del x
    ip netns add x
    IP() {
      ip netns exec x ip "$@"
    }

    IP link add type veth
    IP link set veth0 name v
    IP link set veth1 up
    IP link set v up

    IP route append 192.168.7.0/24 dev v advmss 6
    IP route append 192.168.7.0/24 dev v advmss 7

    IP -d route show dev v

    IP route delete 192.168.7.0/24 dev v advmss 7

    IP -d route show dev v

It seems for deleting routes, kernel ignores mss (which doesn't really
matter for IPv6, but does so for IPv4).
This commit is contained in:
Thomas Haller
2017-07-26 07:26:18 +02:00
parent 88da13f0b2
commit 8e4c5b173f
3 changed files with 16 additions and 7 deletions

View File

@@ -2419,7 +2419,6 @@ static struct nl_msg *
_nl_msg_new_route (int nlmsg_type,
int nlmsg_flags,
const NMPObject *obj,
guint32 mss,
gconstpointer pref_src,
gconstpointer src,
guint8 src_plen,
@@ -2476,15 +2475,16 @@ _nl_msg_new_route (int nlmsg_type,
if (pref_src)
NLA_PUT (msg, RTA_PREFSRC, addr_len, pref_src);
if (mss || window || cwnd || initcwnd || initrwnd || mtu || lock) {
if ( obj->ip_route.mss
|| window || cwnd || initcwnd || initrwnd || mtu || lock) {
struct nlattr *metrics;
metrics = nla_nest_start (msg, RTA_METRICS);
if (!metrics)
goto nla_put_failure;
if (mss)
NLA_PUT_U32 (msg, RTAX_ADVMSS, mss);
if (obj->ip_route.mss)
NLA_PUT_U32 (msg, RTAX_ADVMSS, obj->ip_route.mss);
if (window)
NLA_PUT_U32 (msg, RTAX_WINDOW, window);
if (cwnd)
@@ -5704,7 +5704,6 @@ ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route)
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
NLM_F_CREATE | NLM_F_REPLACE,
&obj,
route->mss,
route->pref_src ? &route->pref_src : NULL,
NULL,
0,
@@ -5732,7 +5731,6 @@ ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route)
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
NLM_F_CREATE | NLM_F_REPLACE,
&obj,
route->mss,
!IN6_IS_ADDR_UNSPECIFIED (&route->pref_src) ? &route->pref_src : NULL,
!IN6_IS_ADDR_UNSPECIFIED (&route->src) ? &route->src : NULL,
route->src_plen,
@@ -5792,7 +5790,6 @@ ip_route_delete (NMPlatform *platform,
nlmsg = _nl_msg_new_route (RTM_DELROUTE,
0,
obj,
0,
NULL,
NULL,
0,

View File

@@ -4754,6 +4754,7 @@ nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpT
h = NM_HASH_COMBINE (h, obj->rt_source);
h = NM_HASH_COMBINE (h, obj->scope_inv);
h = NM_HASH_COMBINE (h, obj->gateway);
h = NM_HASH_COMBINE (h, obj->mss);
}
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
@@ -4809,6 +4810,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
NM_CMP_FIELD (a, b, rt_source);
NM_CMP_FIELD (a, b, scope_inv);
NM_CMP_FIELD (a, b, gateway);
NM_CMP_FIELD (a, b, mss);
}
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:

View File

@@ -354,7 +354,17 @@ typedef union {
bool lock_mtu:1; \
\
guint32 metric; \
\
/* RTA_METRICS.RTAX_ADVMSS. For IPv4 routes, this is part of their
* ID (meaning: you can add otherwise idential IPv4 routes that
* only differ by mss). On the other hand, for IPv6 you cannot add two
* IPv6 routes that only differ by mss.
*
* When deleting a route, kernel seems to ignore RTA_METRICS.RTAX_ADVMSS.
* Which is a problem for IPv4 because you cannot explicitly select which
* route to delete. Kernel just picks the first. */ \
guint32 mss; \
\
guint32 tos; \
guint32 window; \
guint32 cwnd; \