
From: Orange9887 <3488547067@qq.com> hulk inclusion category: feature bugzilla: NA CVE: NA ------------------------------------ By using sysctl_run_estimation_target, you can adjust the CPU on which the estimation is performed to prevent interference with business operations. Signed-off-by: Xiangwei Li <liwei728@huawei.com> --- Documentation/networking/ipvs-sysctl.txt | 9 +++++++ include/net/ip_vs.h | 11 +++++++++ net/netfilter/ipvs/ip_vs_ctl.c | 30 ++++++++++++++++++++++++ net/netfilter/ipvs/ip_vs_est.c | 11 ++++++++- 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/ipvs-sysctl.txt b/Documentation/networking/ipvs-sysctl.txt index ec0b260fb409..ff7389172569 100644 --- a/Documentation/networking/ipvs-sysctl.txt +++ b/Documentation/networking/ipvs-sysctl.txt @@ -303,3 +303,12 @@ run_estimation - BOOLEAN You can always re-enable estimation by setting this value to 1. But be careful, the first estimation after re-enable is not accurate. + +run_estimation_target - int + -1 - default + not -1 - run_estimation on target cpu + + If not -1, the estimation running on the target CPU. + + You can adjust the CPU where estimation is located to prevent + interference with business operations. diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 4ffc08670234..048172e0c80c 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -927,6 +927,7 @@ struct netns_ipvs { int sysctl_schedule_icmp; int sysctl_ignore_tunneled; int sysctl_run_estimation; + int sysctl_run_estimation_target; /* ip_vs_lblc */ int sysctl_lblc_expiration; @@ -1066,6 +1067,11 @@ static inline int sysctl_run_estimation(struct netns_ipvs *ipvs) return ipvs->sysctl_run_estimation; } +static inline int sysctl_run_estimation_target(struct netns_ipvs *ipvs) +{ + return ipvs->sysctl_run_estimation_target; +} + #else static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs) @@ -1158,6 +1164,11 @@ static inline int sysctl_run_estimation(struct netns_ipvs *ipvs) return 1; } +static inline int sysctl_run_estimation_target(struct netns_ipvs *ipvs) +{ + return -1; +} + #endif /* IPVS core functions diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index f3a745b0ef48..624fd6beb092 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1735,6 +1735,28 @@ proc_do_sync_ports(struct ctl_table *table, int write, return rc; } +static int +proc_dointvec_target(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int rc, t; + int *target = table->data; + struct netns_ipvs *ipvs = + container_of(target, struct netns_ipvs, sysctl_run_estimation_target); + + t = *target; + + rc = proc_dointvec(table, write, buffer, lenp, ppos); + if (write && (*target >= nr_cpu_ids || *target < 0)) + *target = t; + else if (*target != t && cpu_online(*target)) { + del_timer_sync(&ipvs->est_timer); + add_timer_on(&ipvs->est_timer, *target); + } + + return rc; +} + /* * IPVS sysctl table (under the /proc/sys/net/ipv4/vs/) * Do not change order or insert new entries without @@ -1909,6 +1931,12 @@ static struct ctl_table vs_vars[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "run_estimation_target", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_target, + }, #ifdef CONFIG_IP_VS_DEBUG { .procname = "debug_level", @@ -3963,6 +3991,8 @@ static int __net_init ip_vs_control_net_init_sysctl(struct netns_ipvs *ipvs) tbl[idx++].data = &ipvs->sysctl_ignore_tunneled; ipvs->sysctl_run_estimation = 1; tbl[idx++].data = &ipvs->sysctl_run_estimation; + ipvs->sysctl_run_estimation_target = -1; + tbl[idx++].data = &ipvs->sysctl_run_estimation_target; ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); if (ipvs->sysctl_hdr == NULL) { diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c index 338e04fa6fbe..ef1743f69edc 100644 --- a/net/netfilter/ipvs/ip_vs_est.c +++ b/net/netfilter/ipvs/ip_vs_est.c @@ -195,10 +195,19 @@ void ip_vs_read_estimator(struct ip_vs_kstats *dst, struct ip_vs_stats *stats) int __net_init ip_vs_estimator_net_init(struct netns_ipvs *ipvs) { + int target; + INIT_LIST_HEAD(&ipvs->est_list); spin_lock_init(&ipvs->est_lock); + + target = sysctl_run_estimation_target(ipvs); timer_setup(&ipvs->est_timer, estimation_timer, 0); - mod_timer(&ipvs->est_timer, jiffies + 2 * HZ); + if (target > -1 && target < nr_cpu_ids && cpu_online(target)) { + ipvs->est_timer.expires = jiffies + 2 * HZ; + add_timer_on(&ipvs->est_timer, target); + } else + mod_timer(&ipvs->est_timer, jiffies + 2 * HZ); + return 0; } -- 2.25.1