Skip to content

Commit 40475b6

Browse files
IurmanJPaolo Abeni
authored andcommitted
net: ipv6: seg6_iptunnel: mitigate 2-realloc issue
This patch mitigates the two-reallocations issue with seg6_iptunnel by providing the dst_entry (in the cache) to the first call to skb_cow_head(). As a result, the very first iteration would still trigger two reallocations (i.e., empty cache), while next iterations would only trigger a single reallocation. Performance tests before/after applying this patch, which clearly shows the improvement: - before: https://ibb.co/3Cg4sNH - after: https://ibb.co/8rQ350r Signed-off-by: Justin Iurman <justin.iurman@uliege.be> Cc: David Lebrun <dlebrun@google.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent dce5251 commit 40475b6

File tree

1 file changed

+52
-33
lines changed

1 file changed

+52
-33
lines changed

net/ipv6/seg6_iptunnel.c

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ static __be32 seg6_make_flowlabel(struct net *net, struct sk_buff *skb,
124124
return flowlabel;
125125
}
126126

127-
/* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
128-
int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
127+
static int __seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
128+
int proto, struct dst_entry *cache_dst)
129129
{
130130
struct dst_entry *dst = skb_dst(skb);
131131
struct net *net = dev_net(dst->dev);
@@ -137,7 +137,7 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
137137
hdrlen = (osrh->hdrlen + 1) << 3;
138138
tot_len = hdrlen + sizeof(*hdr);
139139

140-
err = skb_cow_head(skb, tot_len + skb->mac_len);
140+
err = skb_cow_head(skb, tot_len + dst_dev_overhead(cache_dst, skb));
141141
if (unlikely(err))
142142
return err;
143143

@@ -197,11 +197,18 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
197197

198198
return 0;
199199
}
200+
201+
/* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
202+
int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
203+
{
204+
return __seg6_do_srh_encap(skb, osrh, proto, NULL);
205+
}
200206
EXPORT_SYMBOL_GPL(seg6_do_srh_encap);
201207

202208
/* encapsulate an IPv6 packet within an outer IPv6 header with reduced SRH */
203209
static int seg6_do_srh_encap_red(struct sk_buff *skb,
204-
struct ipv6_sr_hdr *osrh, int proto)
210+
struct ipv6_sr_hdr *osrh, int proto,
211+
struct dst_entry *cache_dst)
205212
{
206213
__u8 first_seg = osrh->first_segment;
207214
struct dst_entry *dst = skb_dst(skb);
@@ -230,7 +237,7 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
230237

231238
tot_len = red_hdrlen + sizeof(struct ipv6hdr);
232239

233-
err = skb_cow_head(skb, tot_len + skb->mac_len);
240+
err = skb_cow_head(skb, tot_len + dst_dev_overhead(cache_dst, skb));
234241
if (unlikely(err))
235242
return err;
236243

@@ -317,16 +324,16 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
317324
return 0;
318325
}
319326

320-
/* insert an SRH within an IPv6 packet, just after the IPv6 header */
321-
int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
327+
static int __seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
328+
struct dst_entry *cache_dst)
322329
{
323330
struct ipv6hdr *hdr, *oldhdr;
324331
struct ipv6_sr_hdr *isrh;
325332
int hdrlen, err;
326333

327334
hdrlen = (osrh->hdrlen + 1) << 3;
328335

329-
err = skb_cow_head(skb, hdrlen + skb->mac_len);
336+
err = skb_cow_head(skb, hdrlen + dst_dev_overhead(cache_dst, skb));
330337
if (unlikely(err))
331338
return err;
332339

@@ -369,9 +376,8 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
369376

370377
return 0;
371378
}
372-
EXPORT_SYMBOL_GPL(seg6_do_srh_inline);
373379

374-
static int seg6_do_srh(struct sk_buff *skb)
380+
static int seg6_do_srh(struct sk_buff *skb, struct dst_entry *cache_dst)
375381
{
376382
struct dst_entry *dst = skb_dst(skb);
377383
struct seg6_iptunnel_encap *tinfo;
@@ -384,7 +390,7 @@ static int seg6_do_srh(struct sk_buff *skb)
384390
if (skb->protocol != htons(ETH_P_IPV6))
385391
return -EINVAL;
386392

387-
err = seg6_do_srh_inline(skb, tinfo->srh);
393+
err = __seg6_do_srh_inline(skb, tinfo->srh, cache_dst);
388394
if (err)
389395
return err;
390396
break;
@@ -402,9 +408,11 @@ static int seg6_do_srh(struct sk_buff *skb)
402408
return -EINVAL;
403409

404410
if (tinfo->mode == SEG6_IPTUN_MODE_ENCAP)
405-
err = seg6_do_srh_encap(skb, tinfo->srh, proto);
411+
err = __seg6_do_srh_encap(skb, tinfo->srh,
412+
proto, cache_dst);
406413
else
407-
err = seg6_do_srh_encap_red(skb, tinfo->srh, proto);
414+
err = seg6_do_srh_encap_red(skb, tinfo->srh,
415+
proto, cache_dst);
408416

409417
if (err)
410418
return err;
@@ -425,11 +433,13 @@ static int seg6_do_srh(struct sk_buff *skb)
425433
skb_push(skb, skb->mac_len);
426434

427435
if (tinfo->mode == SEG6_IPTUN_MODE_L2ENCAP)
428-
err = seg6_do_srh_encap(skb, tinfo->srh,
429-
IPPROTO_ETHERNET);
436+
err = __seg6_do_srh_encap(skb, tinfo->srh,
437+
IPPROTO_ETHERNET,
438+
cache_dst);
430439
else
431440
err = seg6_do_srh_encap_red(skb, tinfo->srh,
432-
IPPROTO_ETHERNET);
441+
IPPROTO_ETHERNET,
442+
cache_dst);
433443

434444
if (err)
435445
return err;
@@ -444,6 +454,13 @@ static int seg6_do_srh(struct sk_buff *skb)
444454
return 0;
445455
}
446456

457+
/* insert an SRH within an IPv6 packet, just after the IPv6 header */
458+
int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
459+
{
460+
return __seg6_do_srh_inline(skb, osrh, NULL);
461+
}
462+
EXPORT_SYMBOL_GPL(seg6_do_srh_inline);
463+
447464
static int seg6_input_finish(struct net *net, struct sock *sk,
448465
struct sk_buff *skb)
449466
{
@@ -458,31 +475,33 @@ static int seg6_input_core(struct net *net, struct sock *sk,
458475
struct seg6_lwt *slwt;
459476
int err;
460477

461-
err = seg6_do_srh(skb);
462-
if (unlikely(err))
463-
goto drop;
464-
465478
slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
466479

467480
local_bh_disable();
468481
dst = dst_cache_get(&slwt->cache);
482+
local_bh_enable();
483+
484+
err = seg6_do_srh(skb, dst);
485+
if (unlikely(err))
486+
goto drop;
469487

470488
if (!dst) {
471489
ip6_route_input(skb);
472490
dst = skb_dst(skb);
473491
if (!dst->error) {
492+
local_bh_disable();
474493
dst_cache_set_ip6(&slwt->cache, dst,
475494
&ipv6_hdr(skb)->saddr);
495+
local_bh_enable();
476496
}
497+
498+
err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
499+
if (unlikely(err))
500+
goto drop;
477501
} else {
478502
skb_dst_drop(skb);
479503
skb_dst_set(skb, dst);
480504
}
481-
local_bh_enable();
482-
483-
err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
484-
if (unlikely(err))
485-
goto drop;
486505

487506
if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
488507
return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
@@ -528,16 +547,16 @@ static int seg6_output_core(struct net *net, struct sock *sk,
528547
struct seg6_lwt *slwt;
529548
int err;
530549

531-
err = seg6_do_srh(skb);
532-
if (unlikely(err))
533-
goto drop;
534-
535550
slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
536551

537552
local_bh_disable();
538553
dst = dst_cache_get(&slwt->cache);
539554
local_bh_enable();
540555

556+
err = seg6_do_srh(skb, dst);
557+
if (unlikely(err))
558+
goto drop;
559+
541560
if (unlikely(!dst)) {
542561
struct ipv6hdr *hdr = ipv6_hdr(skb);
543562
struct flowi6 fl6;
@@ -559,15 +578,15 @@ static int seg6_output_core(struct net *net, struct sock *sk,
559578
local_bh_disable();
560579
dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
561580
local_bh_enable();
581+
582+
err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
583+
if (unlikely(err))
584+
goto drop;
562585
}
563586

564587
skb_dst_drop(skb);
565588
skb_dst_set(skb, dst);
566589

567-
err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
568-
if (unlikely(err))
569-
goto drop;
570-
571590
if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
572591
return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb,
573592
NULL, skb_dst(skb)->dev, dst_output);

0 commit comments

Comments
 (0)