Skip to content

Commit cb891fa

Browse files
Paolo Abenidavem330
authored andcommitted
udp6: fix jumbogram reception
Since commit 67a5178 ("ipv6: udp: leverage scratch area helpers") udp6_recvmsg() read the skb len from the scratch area, to avoid a cache miss. But the UDP6 rx path support RFC 2675 UDPv6 jumbograms, and their length exceeds the 16 bits available in the scratch area. As a side effect the length returned by recvmsg() is: <ingress datagram len> % (1<<16) This commit addresses the issue allocating one more bit in the IP6CB flags field and setting it for incoming jumbograms. Such field is still in the first cacheline, so at recvmsg() time we can check it and fallback to access skb->len if required, without a measurable overhead. Fixes: 67a5178 ("ipv6: udp: leverage scratch area helpers") Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ddab828 commit cb891fa

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

include/linux/ipv6.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ struct inet6_skb_parm {
128128
#define IP6SKB_FRAGMENTED 16
129129
#define IP6SKB_HOPBYHOP 32
130130
#define IP6SKB_L3SLAVE 64
131+
#define IP6SKB_JUMBOGRAM 128
131132
};
132133

133134
#if defined(CONFIG_NET_L3_MASTER_DEV)
@@ -152,6 +153,11 @@ static inline int inet6_iif(const struct sk_buff *skb)
152153
return l3_slave ? skb->skb_iif : IP6CB(skb)->iif;
153154
}
154155

156+
static inline bool inet6_is_jumbogram(const struct sk_buff *skb)
157+
{
158+
return !!(IP6CB(skb)->flags & IP6SKB_JUMBOGRAM);
159+
}
160+
155161
/* can not be used in TCP layer after tcp_v6_fill_cb */
156162
static inline bool inet6_exact_dif_match(struct net *net, struct sk_buff *skb)
157163
{

net/ipv6/exthdrs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,7 @@ static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
756756
if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
757757
goto drop;
758758

759+
IP6CB(skb)->flags |= IP6SKB_JUMBOGRAM;
759760
return true;
760761

761762
drop:

net/ipv6/udp.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,15 @@ struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be
328328
EXPORT_SYMBOL_GPL(udp6_lib_lookup);
329329
#endif
330330

331+
/* do not use the scratch area len for jumbogram: their length execeeds the
332+
* scratch area space; note that the IP6CB flags is still in the first
333+
* cacheline, so checking for jumbograms is cheap
334+
*/
335+
static int udp6_skb_len(struct sk_buff *skb)
336+
{
337+
return unlikely(inet6_is_jumbogram(skb)) ? skb->len : udp_skb_len(skb);
338+
}
339+
331340
/*
332341
* This should be easy, if there is something there we
333342
* return it, otherwise we block.
@@ -358,7 +367,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
358367
if (!skb)
359368
return err;
360369

361-
ulen = udp_skb_len(skb);
370+
ulen = udp6_skb_len(skb);
362371
copied = len;
363372
if (copied > ulen - off)
364373
copied = ulen - off;

0 commit comments

Comments
 (0)