From 84444eeb89ae1671337f0f3148e147ed67199763 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Jan 2024 11:01:06 +0100 Subject: [PATCH] 5.15-stable patches added patches: ipv6-remove-max_size-check-inline-with-ipv4.patch --- ...move-max_size-check-inline-with-ipv4.patch | 202 ++++++++++++++++++ queue-5.15/series | 1 + 2 files changed, 203 insertions(+) create mode 100644 queue-5.15/ipv6-remove-max_size-check-inline-with-ipv4.patch diff --git a/queue-5.15/ipv6-remove-max_size-check-inline-with-ipv4.patch b/queue-5.15/ipv6-remove-max_size-check-inline-with-ipv4.patch new file mode 100644 index 00000000000..2987b7561ae --- /dev/null +++ b/queue-5.15/ipv6-remove-max_size-check-inline-with-ipv4.patch @@ -0,0 +1,202 @@ +From af6d10345ca76670c1b7c37799f0d5576ccef277 Mon Sep 17 00:00:00 2001 +From: Jon Maxwell +Date: Thu, 12 Jan 2023 12:25:32 +1100 +Subject: ipv6: remove max_size check inline with ipv4 + +From: Jon Maxwell + +commit af6d10345ca76670c1b7c37799f0d5576ccef277 upstream. + +In ip6_dst_gc() replace: + + if (entries > gc_thresh) + +With: + + if (entries > ops->gc_thresh) + +Sending Ipv6 packets in a loop via a raw socket triggers an issue where a +route is cloned by ip6_rt_cache_alloc() for each packet sent. This quickly +consumes the Ipv6 max_size threshold which defaults to 4096 resulting in +these warnings: + +[1] 99.187805] dst_alloc: 7728 callbacks suppressed +[2] Route cache is full: consider increasing sysctl net.ipv6.route.max_size. +. +. +[300] Route cache is full: consider increasing sysctl net.ipv6.route.max_size. + +When this happens the packet is dropped and sendto() gets a network is +unreachable error: + +remaining pkt 200557 errno 101 +remaining pkt 196462 errno 101 +. +. +remaining pkt 126821 errno 101 + +Implement David Aherns suggestion to remove max_size check seeing that Ipv6 +has a GC to manage memory usage. Ipv4 already does not check max_size. + +Here are some memory comparisons for Ipv4 vs Ipv6 with the patch: + +Test by running 5 instances of a program that sends UDP packets to a raw +socket 5000000 times. Compare Ipv4 and Ipv6 performance with a similar +program. + +Ipv4: + +Before test: + +MemFree: 29427108 kB +Slab: 237612 kB + +ip6_dst_cache 1912 2528 256 32 2 : tunables 0 0 0 +xfrm_dst_cache 0 0 320 25 2 : tunables 0 0 0 +ip_dst_cache 2881 3990 192 42 2 : tunables 0 0 0 + +During test: + +MemFree: 29417608 kB +Slab: 247712 kB + +ip6_dst_cache 1912 2528 256 32 2 : tunables 0 0 0 +xfrm_dst_cache 0 0 320 25 2 : tunables 0 0 0 +ip_dst_cache 44394 44394 192 42 2 : tunables 0 0 0 + +After test: + +MemFree: 29422308 kB +Slab: 238104 kB + +ip6_dst_cache 1912 2528 256 32 2 : tunables 0 0 0 +xfrm_dst_cache 0 0 320 25 2 : tunables 0 0 0 +ip_dst_cache 3048 4116 192 42 2 : tunables 0 0 0 + +Ipv6 with patch: + +Errno 101 errors are not observed anymore with the patch. + +Before test: + +MemFree: 29422308 kB +Slab: 238104 kB + +ip6_dst_cache 1912 2528 256 32 2 : tunables 0 0 0 +xfrm_dst_cache 0 0 320 25 2 : tunables 0 0 0 +ip_dst_cache 3048 4116 192 42 2 : tunables 0 0 0 + +During Test: + +MemFree: 29431516 kB +Slab: 240940 kB + +ip6_dst_cache 11980 12064 256 32 2 : tunables 0 0 0 +xfrm_dst_cache 0 0 320 25 2 : tunables 0 0 0 +ip_dst_cache 3048 4116 192 42 2 : tunables 0 0 0 + +After Test: + +MemFree: 29441816 kB +Slab: 238132 kB + +ip6_dst_cache 1902 2432 256 32 2 : tunables 0 0 0 +xfrm_dst_cache 0 0 320 25 2 : tunables 0 0 0 +ip_dst_cache 3048 4116 192 42 2 : tunables 0 0 0 + +Tested-by: Andrea Mayer +Signed-off-by: Jon Maxwell +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20230112012532.311021-1-jmaxwell37@gmail.com +Signed-off-by: Jakub Kicinski +Cc: "Jitindar Singh, Suraj" +Signed-off-by: Greg Kroah-Hartman +--- + include/net/dst_ops.h | 2 +- + net/core/dst.c | 8 ++------ + net/ipv6/route.c | 13 +++++-------- + 3 files changed, 8 insertions(+), 15 deletions(-) + +--- a/include/net/dst_ops.h ++++ b/include/net/dst_ops.h +@@ -16,7 +16,7 @@ struct dst_ops { + unsigned short family; + unsigned int gc_thresh; + +- int (*gc)(struct dst_ops *ops); ++ void (*gc)(struct dst_ops *ops); + struct dst_entry * (*check)(struct dst_entry *, __u32 cookie); + unsigned int (*default_advmss)(const struct dst_entry *); + unsigned int (*mtu)(const struct dst_entry *); +--- a/net/core/dst.c ++++ b/net/core/dst.c +@@ -82,12 +82,8 @@ void *dst_alloc(struct dst_ops *ops, str + + if (ops->gc && + !(flags & DST_NOCOUNT) && +- dst_entries_get_fast(ops) > ops->gc_thresh) { +- if (ops->gc(ops)) { +- pr_notice_ratelimited("Route cache is full: consider increasing sysctl net.ipv6.route.max_size.\n"); +- return NULL; +- } +- } ++ dst_entries_get_fast(ops) > ops->gc_thresh) ++ ops->gc(ops); + + dst = kmem_cache_alloc(ops->kmem_cachep, GFP_ATOMIC); + if (!dst) +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -91,7 +91,7 @@ static struct dst_entry *ip6_negative_ad + static void ip6_dst_destroy(struct dst_entry *); + static void ip6_dst_ifdown(struct dst_entry *, + struct net_device *dev, int how); +-static int ip6_dst_gc(struct dst_ops *ops); ++static void ip6_dst_gc(struct dst_ops *ops); + + static int ip6_pkt_discard(struct sk_buff *skb); + static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); +@@ -3295,11 +3295,10 @@ out: + return dst; + } + +-static int ip6_dst_gc(struct dst_ops *ops) ++static void ip6_dst_gc(struct dst_ops *ops) + { + struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops); + int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval; +- int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size; + int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity; + int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout; + unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc; +@@ -3307,11 +3306,10 @@ static int ip6_dst_gc(struct dst_ops *op + int entries; + + entries = dst_entries_get_fast(ops); +- if (entries > rt_max_size) ++ if (entries > ops->gc_thresh) + entries = dst_entries_get_slow(ops); + +- if (time_after(rt_last_gc + rt_min_interval, jiffies) && +- entries <= rt_max_size) ++ if (time_after(rt_last_gc + rt_min_interval, jiffies)) + goto out; + + fib6_run_gc(atomic_inc_return(&net->ipv6.ip6_rt_gc_expire), net, true); +@@ -3321,7 +3319,6 @@ static int ip6_dst_gc(struct dst_ops *op + out: + val = atomic_read(&net->ipv6.ip6_rt_gc_expire); + atomic_set(&net->ipv6.ip6_rt_gc_expire, val - (val >> rt_elasticity)); +- return entries > rt_max_size; + } + + static int ip6_nh_lookup_table(struct net *net, struct fib6_config *cfg, +@@ -6528,7 +6525,7 @@ static int __net_init ip6_route_net_init + #endif + + net->ipv6.sysctl.flush_delay = 0; +- net->ipv6.sysctl.ip6_rt_max_size = 4096; ++ net->ipv6.sysctl.ip6_rt_max_size = INT_MAX; + net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2; + net->ipv6.sysctl.ip6_rt_gc_timeout = 60*HZ; + net->ipv6.sysctl.ip6_rt_gc_interval = 30*HZ; diff --git a/queue-5.15/series b/queue-5.15/series index 40c912a58f1..1139786f023 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -50,3 +50,4 @@ mmc-rpmb-fixes-pause-retune-on-all-rpmb-partitions.patch mmc-core-cancel-delayed-work-before-releasing-host.patch mmc-sdhci-sprd-fix-emmc-init-failure-after-hw-reset.patch net-tls-update-curr-on-splice-as-well.patch +ipv6-remove-max_size-check-inline-with-ipv4.patch -- 2.47.3