Thread (4 messages) 4 messages, 2 authors, 2020-02-03

RE: Freeing 'temporary' IPv4 route table entries.

flat view

From: David Laight <hidden>
Date: 2020-02-03 12:12:11

From: Eric Dumazet
Sent: 31 January 2020 15:54
On 1/31/20 2:26 AM, David Laight wrote:
quoted
If I call sendmsg() on a raw socket (or probably
an unconnected UDP one) rt_dst_alloc() is called
in the bowels of ip_route_output_flow() to hold
the remote address.

Much later __dev_queue_xmit() calls dst_release()
to delete the 'dst' referenced from the skb.

Prior to f8864972 it did just that.
Afterwards the actual delete is 'laundered' through the
rcu callbacks.
This is probably ok for dst that are actually attached
to sockets or tunnels (which aren't freed very often).
But it leads to horrid long rcu callback sequences
when a lot of messages are sent.
(A sample of 1 gave nearly 100 deletes in one go.)
There is also the additional cost of deferring the free
(and the extra retpoline etc).

ISTM that the dst_alloc() done during a send should
set a flag so that the 'dst' can be immediately
freed since it is known that no one can be picking up
a reference as it is being freed.

Thoughts?
I thought these routes were cached in per-cpu caches.

At least for UDP I do not see rcu callbacks being queueed.
I've done a bit more investigation.

For raw_ip sockets with inet->hdrincl set (ie the application
builds the IPv4 header) flowi4_flags has FLOWI_FLAG_KNOWN_NH set.

This is detected inside __mkroute_output() (in ipv4/route.c)
and forces rt_dst_alloc() be called instead of using the
'dst' from (I think) fib_select_path().
(Is this basically the arp table entry?)

rt_set_nexthop() then calls rt_add_uncached_list().

I suspect that dst_release() is called after every
transmit - but normally just decrements the ref count.
However for raw sends it frees the uncached route.

I think the 'fault' is down to c27c9322d which fixed
an issue where the code was using the IP address from the
pre-built packet instead of the one from the destination
address.

I think there are two issues:
1) if __mkroute_output() creates an 'uncached' route
   it can be freed without waiting for rcu grace.
2) if a raw packets destination address matches then
   the cached route can be used.

Oh - nothing seems to check DST_HOST any more

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help