Skip to content

Commit ad40585

Browse files
wdebruijdavem330
authored andcommitted
udp: better wmem accounting on gso
skb_segment by default transfers allocated wmem from the gso skb to the tail of the segment list. This underreports real truesize of the list, especially if the tail might be dropped. Similar to tcp_gso_segment, update wmem_alloc with the aggregate list truesize and make each segment responsible for its own share by setting skb->destructor. Clear gso_skb->destructor prior to calling skb_segment to skip the default assignment to tail. Signed-off-by: Willem de Bruijn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bec1f6f commit ad40585

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

net/ipv4/udp_offload.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
191191
netdev_features_t features,
192192
unsigned int mss, __sum16 check)
193193
{
194+
struct sock *sk = gso_skb->sk;
195+
unsigned int sum_truesize = 0;
194196
struct sk_buff *segs, *seg;
195197
unsigned int hdrlen;
196198
struct udphdr *uh;
@@ -201,9 +203,15 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
201203
hdrlen = gso_skb->data - skb_mac_header(gso_skb);
202204
skb_pull(gso_skb, sizeof(*uh));
203205

206+
/* clear destructor to avoid skb_segment assigning it to tail */
207+
WARN_ON_ONCE(gso_skb->destructor != sock_wfree);
208+
gso_skb->destructor = NULL;
209+
204210
segs = skb_segment(gso_skb, features);
205-
if (unlikely(IS_ERR_OR_NULL(segs)))
211+
if (unlikely(IS_ERR_OR_NULL(segs))) {
212+
gso_skb->destructor = sock_wfree;
206213
return segs;
214+
}
207215

208216
for (seg = segs; seg; seg = seg->next) {
209217
uh = udp_hdr(seg);
@@ -214,8 +222,14 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
214222
if (!seg->next)
215223
csum_replace2(&uh->check, htons(mss),
216224
htons(seg->len - hdrlen - sizeof(*uh)));
225+
226+
seg->destructor = sock_wfree;
227+
seg->sk = sk;
228+
sum_truesize += seg->truesize;
217229
}
218230

231+
refcount_add(sum_truesize - gso_skb->truesize, &sk->sk_wmem_alloc);
232+
219233
return segs;
220234
}
221235
EXPORT_SYMBOL_GPL(__udp_gso_segment);

0 commit comments

Comments
 (0)