diff options
| author | David S. Miller <davem@davemloft.net> | 2017-03-25 00:47:32 +0300 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-03-25 00:47:32 +0300 |
| commit | f106d164720af76ef97c3d1e92901bf85f93aeb8 (patch) | |
| tree | 4e67bff13827d3aa72f90e7fb0f4dc70c16ef40d | |
| parent | 3b1af93cf193ca4a94df5f01f480a9d820a194bb (diff) | |
| parent | af4a2209b1344939eaac11f269c261d347cbc3ee (diff) | |
| download | linux-f106d164720af76ef97c3d1e92901bf85f93aeb8.tar.xz | |
Merge branch 'ipv6-sr-perf-improvements'
David Lebrun says:
====================
Performances improvement for IPv6 Segment Routing
This patch series improves the performances of IPv6 SR by optimizing skb head
reallocation and extending the use of dst_cache. The overall performances improve
by 35%.
Before patch series (SRH encap):
Result: OK: 7348320(c7347271+d1048) usec, 5000000 (1000byte,0frags)
680427pps 5443Mb/sec (5443416000bps) errors: 0
After patch series (SRH encap):
Result: OK: 4774543(c4774084+d459) usec, 5000000 (1000byte,0frags)
1047220pps 8377Mb/sec (8377760000bps) errors: 0
Baseline for plain IPv6 forwarding:
Result: OK: 4244144(c4243722+d422) usec, 5000000 (1000byte,0frags)
1178093pps 9424Mb/sec (9424744000bps) errors: 0
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/ipv6/seg6_iptunnel.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c index 85582257d3af..30ef1d1d182e 100644 --- a/net/ipv6/seg6_iptunnel.c +++ b/net/ipv6/seg6_iptunnel.c @@ -105,7 +105,7 @@ static int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh) hdrlen = (osrh->hdrlen + 1) << 3; tot_len = hdrlen + sizeof(*hdr); - err = pskb_expand_head(skb, tot_len, 0, GFP_ATOMIC); + err = skb_cow_head(skb, tot_len); if (unlikely(err)) return err; @@ -156,7 +156,7 @@ static int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh) hdrlen = (osrh->hdrlen + 1) << 3; - err = pskb_expand_head(skb, hdrlen, 0, GFP_ATOMIC); + err = skb_cow_head(skb, hdrlen); if (unlikely(err)) return err; @@ -237,6 +237,9 @@ static int seg6_do_srh(struct sk_buff *skb) static int seg6_input(struct sk_buff *skb) { + struct dst_entry *orig_dst = skb_dst(skb); + struct dst_entry *dst = NULL; + struct seg6_lwt *slwt; int err; err = seg6_do_srh(skb); @@ -245,8 +248,30 @@ static int seg6_input(struct sk_buff *skb) return err; } + slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); + +#ifdef CONFIG_DST_CACHE + preempt_disable(); + dst = dst_cache_get(&slwt->cache); + preempt_enable(); +#endif + skb_dst_drop(skb); - ip6_route_input(skb); + + if (!dst) { + ip6_route_input(skb); +#ifdef CONFIG_DST_CACHE + dst = skb_dst(skb); + if (!dst->error) { + preempt_disable(); + dst_cache_set_ip6(&slwt->cache, dst, + &ipv6_hdr(skb)->saddr); + preempt_enable(); + } +#endif + } else { + skb_dst_set(skb, dst); + } return dst_input(skb); } |
