Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'ipv6-snmp-avoid-performance-issue-with-ratelimithost'

Eric Dumazet says:

====================
ipv6: snmp: avoid performance issue with RATELIMITHOST

Addition of ICMP6_MIB_RATELIMITHOST in commit d0941130c9351
("icmp: Add counters for rate limits") introduced a performance drop
in case of DOS (like receiving UDP packets to closed ports).

Per netns ICMP6_MIB_RATELIMITHOST tracking uses per-cpu storage and
is enough, we do not need per-device and slow tracking for this metric.

In v2 of this series, I completed the removal of SNMP_MIB_SENTINEL
in all the kernel for consistency.

v1: https://lore.kernel.org/20250904092432.113c4940@kernel.org
====================

Link: https://patch.msgid.link/20250905165813.1470708-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+113 -106
+5 -4
include/net/ip.h
··· 326 326 } 327 327 #endif 328 328 329 - #define snmp_get_cpu_field64_batch(buff64, stats_list, mib_statistic, offset) \ 329 + #define snmp_get_cpu_field64_batch_cnt(buff64, stats_list, cnt, \ 330 + mib_statistic, offset) \ 330 331 { \ 331 332 int i, c; \ 332 333 for_each_possible_cpu(c) { \ 333 - for (i = 0; stats_list[i].name; i++) \ 334 + for (i = 0; i < cnt; i++) \ 334 335 buff64[i] += snmp_get_cpu_field64( \ 335 336 mib_statistic, \ 336 337 c, stats_list[i].entry, \ ··· 339 338 } \ 340 339 } 341 340 342 - #define snmp_get_cpu_field_batch(buff, stats_list, mib_statistic) \ 341 + #define snmp_get_cpu_field_batch_cnt(buff, stats_list, cnt, mib_statistic) \ 343 342 { \ 344 343 int i, c; \ 345 344 for_each_possible_cpu(c) { \ 346 - for (i = 0; stats_list[i].name; i++) \ 345 + for (i = 0; i < cnt; i++) \ 347 346 buff[i] += snmp_get_cpu_field( \ 348 347 mib_statistic, \ 349 348 c, stats_list[i].entry); \
-5
include/net/snmp.h
··· 36 36 .entry = _entry, \ 37 37 } 38 38 39 - #define SNMP_MIB_SENTINEL { \ 40 - .name = NULL, \ 41 - .entry = 0, \ 42 - } 43 - 44 39 /* 45 40 * We use unsigned longs for most mibs but u64 for ipstats. 46 41 */
+33 -32
net/ipv4/proc.c
··· 95 95 SNMP_MIB_ITEM("FragFails", IPSTATS_MIB_FRAGFAILS), 96 96 SNMP_MIB_ITEM("FragCreates", IPSTATS_MIB_FRAGCREATES), 97 97 SNMP_MIB_ITEM("OutTransmits", IPSTATS_MIB_OUTPKTS), 98 - SNMP_MIB_SENTINEL 99 98 }; 100 99 101 100 /* Following items are displayed in /proc/net/netstat */ ··· 118 119 SNMP_MIB_ITEM("InECT0Pkts", IPSTATS_MIB_ECT0PKTS), 119 120 SNMP_MIB_ITEM("InCEPkts", IPSTATS_MIB_CEPKTS), 120 121 SNMP_MIB_ITEM("ReasmOverlaps", IPSTATS_MIB_REASM_OVERLAPS), 121 - SNMP_MIB_SENTINEL 122 122 }; 123 123 124 124 static const struct { ··· 155 157 SNMP_MIB_ITEM("InErrs", TCP_MIB_INERRS), 156 158 SNMP_MIB_ITEM("OutRsts", TCP_MIB_OUTRSTS), 157 159 SNMP_MIB_ITEM("InCsumErrors", TCP_MIB_CSUMERRORS), 158 - SNMP_MIB_SENTINEL 159 160 }; 160 161 161 162 static const struct snmp_mib snmp4_udp_list[] = { ··· 167 170 SNMP_MIB_ITEM("InCsumErrors", UDP_MIB_CSUMERRORS), 168 171 SNMP_MIB_ITEM("IgnoredMulti", UDP_MIB_IGNOREDMULTI), 169 172 SNMP_MIB_ITEM("MemErrors", UDP_MIB_MEMERRORS), 170 - SNMP_MIB_SENTINEL 171 173 }; 172 174 173 175 static const struct snmp_mib snmp4_net_list[] = { ··· 305 309 SNMP_MIB_ITEM("TCPAOKeyNotFound", LINUX_MIB_TCPAOKEYNOTFOUND), 306 310 SNMP_MIB_ITEM("TCPAOGood", LINUX_MIB_TCPAOGOOD), 307 311 SNMP_MIB_ITEM("TCPAODroppedIcmps", LINUX_MIB_TCPAODROPPEDICMPS), 308 - SNMP_MIB_SENTINEL 309 312 }; 310 313 311 314 static void icmpmsg_put_line(struct seq_file *seq, unsigned long *vals, ··· 384 389 */ 385 390 static int snmp_seq_show_ipstats(struct seq_file *seq, void *v) 386 391 { 392 + const int cnt = ARRAY_SIZE(snmp4_ipstats_list); 393 + u64 buff64[ARRAY_SIZE(snmp4_ipstats_list)]; 387 394 struct net *net = seq->private; 388 - u64 buff64[IPSTATS_MIB_MAX]; 389 395 int i; 390 396 391 - memset(buff64, 0, IPSTATS_MIB_MAX * sizeof(u64)); 397 + memset(buff64, 0, sizeof(buff64)); 392 398 393 399 seq_puts(seq, "Ip: Forwarding DefaultTTL"); 394 - for (i = 0; snmp4_ipstats_list[i].name; i++) 400 + for (i = 0; i < cnt; i++) 395 401 seq_printf(seq, " %s", snmp4_ipstats_list[i].name); 396 402 397 403 seq_printf(seq, "\nIp: %d %d", ··· 400 404 READ_ONCE(net->ipv4.sysctl_ip_default_ttl)); 401 405 402 406 BUILD_BUG_ON(offsetof(struct ipstats_mib, mibs) != 0); 403 - snmp_get_cpu_field64_batch(buff64, snmp4_ipstats_list, 404 - net->mib.ip_statistics, 405 - offsetof(struct ipstats_mib, syncp)); 406 - for (i = 0; snmp4_ipstats_list[i].name; i++) 407 + snmp_get_cpu_field64_batch_cnt(buff64, snmp4_ipstats_list, cnt, 408 + net->mib.ip_statistics, 409 + offsetof(struct ipstats_mib, syncp)); 410 + for (i = 0; i < cnt; i++) 407 411 seq_printf(seq, " %llu", buff64[i]); 408 412 409 413 return 0; ··· 411 415 412 416 static int snmp_seq_show_tcp_udp(struct seq_file *seq, void *v) 413 417 { 418 + const int udp_cnt = ARRAY_SIZE(snmp4_udp_list); 419 + const int tcp_cnt = ARRAY_SIZE(snmp4_tcp_list); 414 420 unsigned long buff[TCPUDP_MIB_MAX]; 415 421 struct net *net = seq->private; 416 422 int i; 417 423 418 - memset(buff, 0, TCPUDP_MIB_MAX * sizeof(unsigned long)); 424 + memset(buff, 0, tcp_cnt * sizeof(unsigned long)); 419 425 420 426 seq_puts(seq, "\nTcp:"); 421 - for (i = 0; snmp4_tcp_list[i].name; i++) 427 + for (i = 0; i < tcp_cnt; i++) 422 428 seq_printf(seq, " %s", snmp4_tcp_list[i].name); 423 429 424 430 seq_puts(seq, "\nTcp:"); 425 - snmp_get_cpu_field_batch(buff, snmp4_tcp_list, 426 - net->mib.tcp_statistics); 427 - for (i = 0; snmp4_tcp_list[i].name; i++) { 431 + snmp_get_cpu_field_batch_cnt(buff, snmp4_tcp_list, 432 + tcp_cnt, 433 + net->mib.tcp_statistics); 434 + for (i = 0; i < tcp_cnt; i++) { 428 435 /* MaxConn field is signed, RFC 2012 */ 429 436 if (snmp4_tcp_list[i].entry == TCP_MIB_MAXCONN) 430 437 seq_printf(seq, " %ld", buff[i]); ··· 435 436 seq_printf(seq, " %lu", buff[i]); 436 437 } 437 438 438 - memset(buff, 0, TCPUDP_MIB_MAX * sizeof(unsigned long)); 439 + memset(buff, 0, udp_cnt * sizeof(unsigned long)); 439 440 440 - snmp_get_cpu_field_batch(buff, snmp4_udp_list, 441 - net->mib.udp_statistics); 441 + snmp_get_cpu_field_batch_cnt(buff, snmp4_udp_list, 442 + udp_cnt, 443 + net->mib.udp_statistics); 442 444 seq_puts(seq, "\nUdp:"); 443 - for (i = 0; snmp4_udp_list[i].name; i++) 445 + for (i = 0; i < udp_cnt; i++) 444 446 seq_printf(seq, " %s", snmp4_udp_list[i].name); 445 447 seq_puts(seq, "\nUdp:"); 446 - for (i = 0; snmp4_udp_list[i].name; i++) 448 + for (i = 0; i < udp_cnt; i++) 447 449 seq_printf(seq, " %lu", buff[i]); 448 450 449 - memset(buff, 0, TCPUDP_MIB_MAX * sizeof(unsigned long)); 451 + memset(buff, 0, udp_cnt * sizeof(unsigned long)); 450 452 451 453 /* the UDP and UDP-Lite MIBs are the same */ 452 454 seq_puts(seq, "\nUdpLite:"); 453 - snmp_get_cpu_field_batch(buff, snmp4_udp_list, 454 - net->mib.udplite_statistics); 455 - for (i = 0; snmp4_udp_list[i].name; i++) 455 + snmp_get_cpu_field_batch_cnt(buff, snmp4_udp_list, 456 + udp_cnt, 457 + net->mib.udplite_statistics); 458 + for (i = 0; i < udp_cnt; i++) 456 459 seq_printf(seq, " %s", snmp4_udp_list[i].name); 457 460 seq_puts(seq, "\nUdpLite:"); 458 - for (i = 0; snmp4_udp_list[i].name; i++) 461 + for (i = 0; i < udp_cnt; i++) 459 462 seq_printf(seq, " %lu", buff[i]); 460 463 461 464 seq_putc(seq, '\n'); ··· 481 480 */ 482 481 static int netstat_seq_show(struct seq_file *seq, void *v) 483 482 { 484 - const int ip_cnt = ARRAY_SIZE(snmp4_ipextstats_list) - 1; 485 - const int tcp_cnt = ARRAY_SIZE(snmp4_net_list) - 1; 483 + const int ip_cnt = ARRAY_SIZE(snmp4_ipextstats_list); 484 + const int tcp_cnt = ARRAY_SIZE(snmp4_net_list); 486 485 struct net *net = seq->private; 487 486 unsigned long *buff; 488 487 int i; ··· 495 494 buff = kzalloc(max(tcp_cnt * sizeof(long), ip_cnt * sizeof(u64)), 496 495 GFP_KERNEL); 497 496 if (buff) { 498 - snmp_get_cpu_field_batch(buff, snmp4_net_list, 499 - net->mib.net_statistics); 497 + snmp_get_cpu_field_batch_cnt(buff, snmp4_net_list, tcp_cnt, 498 + net->mib.net_statistics); 500 499 for (i = 0; i < tcp_cnt; i++) 501 500 seq_printf(seq, " %lu", buff[i]); 502 501 } else { ··· 514 513 u64 *buff64 = (u64 *)buff; 515 514 516 515 memset(buff64, 0, ip_cnt * sizeof(u64)); 517 - snmp_get_cpu_field64_batch(buff64, snmp4_ipextstats_list, 516 + snmp_get_cpu_field64_batch_cnt(buff64, snmp4_ipextstats_list, ip_cnt, 518 517 net->mib.ip_statistics, 519 518 offsetof(struct ipstats_mib, syncp)); 520 519 for (i = 0; i < ip_cnt; i++)
+1 -2
net/ipv6/icmp.c
··· 230 230 } 231 231 rcu_read_unlock(); 232 232 if (!res) 233 - __ICMP6_INC_STATS(net, ip6_dst_idev(dst), 234 - ICMP6_MIB_RATELIMITHOST); 233 + __ICMP6_INC_STATS(net, NULL, ICMP6_MIB_RATELIMITHOST); 235 234 else 236 235 icmp_global_consume(net); 237 236 dst_release(dst);
+50 -41
net/ipv6/proc.c
··· 85 85 SNMP_MIB_ITEM("Ip6InECT0Pkts", IPSTATS_MIB_ECT0PKTS), 86 86 SNMP_MIB_ITEM("Ip6InCEPkts", IPSTATS_MIB_CEPKTS), 87 87 SNMP_MIB_ITEM("Ip6OutTransmits", IPSTATS_MIB_OUTPKTS), 88 - SNMP_MIB_SENTINEL 89 88 }; 90 89 91 90 static const struct snmp_mib snmp6_icmp6_list[] = { ··· 94 95 SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS), 95 96 SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS), 96 97 SNMP_MIB_ITEM("Icmp6InCsumErrors", ICMP6_MIB_CSUMERRORS), 98 + /* ICMP6_MIB_RATELIMITHOST needs to be last, see snmp6_dev_seq_show(). */ 97 99 SNMP_MIB_ITEM("Icmp6OutRateLimitHost", ICMP6_MIB_RATELIMITHOST), 98 - SNMP_MIB_SENTINEL 99 100 }; 100 - 101 - /* RFC 4293 v6 ICMPMsgStatsTable; named items for RFC 2466 compatibility */ 102 - static const char *const icmp6type2name[256] = { 103 - [ICMPV6_DEST_UNREACH] = "DestUnreachs", 104 - [ICMPV6_PKT_TOOBIG] = "PktTooBigs", 105 - [ICMPV6_TIME_EXCEED] = "TimeExcds", 106 - [ICMPV6_PARAMPROB] = "ParmProblems", 107 - [ICMPV6_ECHO_REQUEST] = "Echos", 108 - [ICMPV6_ECHO_REPLY] = "EchoReplies", 109 - [ICMPV6_MGM_QUERY] = "GroupMembQueries", 110 - [ICMPV6_MGM_REPORT] = "GroupMembResponses", 111 - [ICMPV6_MGM_REDUCTION] = "GroupMembReductions", 112 - [ICMPV6_MLD2_REPORT] = "MLDv2Reports", 113 - [NDISC_ROUTER_ADVERTISEMENT] = "RouterAdvertisements", 114 - [NDISC_ROUTER_SOLICITATION] = "RouterSolicits", 115 - [NDISC_NEIGHBOUR_ADVERTISEMENT] = "NeighborAdvertisements", 116 - [NDISC_NEIGHBOUR_SOLICITATION] = "NeighborSolicits", 117 - [NDISC_REDIRECT] = "Redirects", 118 - }; 119 - 120 101 121 102 static const struct snmp_mib snmp6_udp6_list[] = { 122 103 SNMP_MIB_ITEM("Udp6InDatagrams", UDP_MIB_INDATAGRAMS), ··· 108 129 SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS), 109 130 SNMP_MIB_ITEM("Udp6IgnoredMulti", UDP_MIB_IGNOREDMULTI), 110 131 SNMP_MIB_ITEM("Udp6MemErrors", UDP_MIB_MEMERRORS), 111 - SNMP_MIB_SENTINEL 112 132 }; 113 133 114 134 static const struct snmp_mib snmp6_udplite6_list[] = { ··· 119 141 SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS), 120 142 SNMP_MIB_ITEM("UdpLite6InCsumErrors", UDP_MIB_CSUMERRORS), 121 143 SNMP_MIB_ITEM("UdpLite6MemErrors", UDP_MIB_MEMERRORS), 122 - SNMP_MIB_SENTINEL 123 144 }; 124 145 125 146 static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, atomic_long_t *smib) ··· 128 151 129 152 /* print by name -- deprecated items */ 130 153 for (i = 0; i < ICMP6MSG_MIB_MAX; i++) { 154 + const char *p = NULL; 131 155 int icmptype; 132 - const char *p; 156 + 157 + #define CASE(TYP, STR) case TYP: p = STR; break; 133 158 134 159 icmptype = i & 0xff; 135 - p = icmp6type2name[icmptype]; 160 + switch (icmptype) { 161 + /* RFC 4293 v6 ICMPMsgStatsTable; named items for RFC 2466 compatibility */ 162 + CASE(ICMPV6_DEST_UNREACH, "DestUnreachs") 163 + CASE(ICMPV6_PKT_TOOBIG, "PktTooBigs") 164 + CASE(ICMPV6_TIME_EXCEED, "TimeExcds") 165 + CASE(ICMPV6_PARAMPROB, "ParmProblems") 166 + CASE(ICMPV6_ECHO_REQUEST, "Echos") 167 + CASE(ICMPV6_ECHO_REPLY, "EchoReplies") 168 + CASE(ICMPV6_MGM_QUERY, "GroupMembQueries") 169 + CASE(ICMPV6_MGM_REPORT, "GroupMembResponses") 170 + CASE(ICMPV6_MGM_REDUCTION, "GroupMembReductions") 171 + CASE(ICMPV6_MLD2_REPORT, "MLDv2Reports") 172 + CASE(NDISC_ROUTER_ADVERTISEMENT, "RouterAdvertisements") 173 + CASE(NDISC_ROUTER_SOLICITATION, "RouterSolicits") 174 + CASE(NDISC_NEIGHBOUR_ADVERTISEMENT, "NeighborAdvertisements") 175 + CASE(NDISC_NEIGHBOUR_SOLICITATION, "NeighborSolicits") 176 + CASE(NDISC_REDIRECT, "Redirects") 177 + } 178 + #undef CASE 136 179 if (!p) /* don't print un-named types here */ 137 180 continue; 138 181 snprintf(name, sizeof(name), "Icmp6%s%s", ··· 179 182 */ 180 183 static void snmp6_seq_show_item(struct seq_file *seq, void __percpu *pcpumib, 181 184 atomic_long_t *smib, 182 - const struct snmp_mib *itemlist) 185 + const struct snmp_mib *itemlist, 186 + int cnt) 183 187 { 184 188 unsigned long buff[SNMP_MIB_MAX]; 185 189 int i; 186 190 187 191 if (pcpumib) { 188 - memset(buff, 0, sizeof(unsigned long) * SNMP_MIB_MAX); 192 + memset(buff, 0, sizeof(unsigned long) * cnt); 189 193 190 - snmp_get_cpu_field_batch(buff, itemlist, pcpumib); 191 - for (i = 0; itemlist[i].name; i++) 194 + snmp_get_cpu_field_batch_cnt(buff, itemlist, cnt, pcpumib); 195 + for (i = 0; i < cnt; i++) 192 196 seq_printf(seq, "%-32s\t%lu\n", 193 197 itemlist[i].name, buff[i]); 194 198 } else { 195 - for (i = 0; itemlist[i].name; i++) 199 + for (i = 0; i < cnt; i++) 196 200 seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, 197 201 atomic_long_read(smib + itemlist[i].entry)); 198 202 } 199 203 } 200 204 201 205 static void snmp6_seq_show_item64(struct seq_file *seq, void __percpu *mib, 202 - const struct snmp_mib *itemlist, size_t syncpoff) 206 + const struct snmp_mib *itemlist, 207 + int cnt, size_t syncpoff) 203 208 { 204 209 u64 buff64[SNMP_MIB_MAX]; 205 210 int i; 206 211 207 - memset(buff64, 0, sizeof(u64) * SNMP_MIB_MAX); 212 + memset(buff64, 0, sizeof(u64) * cnt); 208 213 209 - snmp_get_cpu_field64_batch(buff64, itemlist, mib, syncpoff); 210 - for (i = 0; itemlist[i].name; i++) 214 + snmp_get_cpu_field64_batch_cnt(buff64, itemlist, cnt, mib, syncpoff); 215 + for (i = 0; i < cnt; i++) 211 216 seq_printf(seq, "%-32s\t%llu\n", itemlist[i].name, buff64[i]); 212 217 } 213 218 ··· 218 219 struct net *net = (struct net *)seq->private; 219 220 220 221 snmp6_seq_show_item64(seq, net->mib.ipv6_statistics, 221 - snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp)); 222 + snmp6_ipstats_list, 223 + ARRAY_SIZE(snmp6_ipstats_list), 224 + offsetof(struct ipstats_mib, syncp)); 222 225 snmp6_seq_show_item(seq, net->mib.icmpv6_statistics, 223 - NULL, snmp6_icmp6_list); 226 + NULL, snmp6_icmp6_list, 227 + ARRAY_SIZE(snmp6_icmp6_list)); 224 228 snmp6_seq_show_icmpv6msg(seq, net->mib.icmpv6msg_statistics->mibs); 225 229 snmp6_seq_show_item(seq, net->mib.udp_stats_in6, 226 - NULL, snmp6_udp6_list); 230 + NULL, snmp6_udp6_list, 231 + ARRAY_SIZE(snmp6_udp6_list)); 227 232 snmp6_seq_show_item(seq, net->mib.udplite_stats_in6, 228 - NULL, snmp6_udplite6_list); 233 + NULL, snmp6_udplite6_list, 234 + ARRAY_SIZE(snmp6_udplite6_list)); 229 235 return 0; 230 236 } 231 237 ··· 240 236 241 237 seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); 242 238 snmp6_seq_show_item64(seq, idev->stats.ipv6, 243 - snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp)); 239 + snmp6_ipstats_list, 240 + ARRAY_SIZE(snmp6_ipstats_list), 241 + offsetof(struct ipstats_mib, syncp)); 242 + 243 + /* Per idev icmp stats do not have ICMP6_MIB_RATELIMITHOST */ 244 244 snmp6_seq_show_item(seq, NULL, idev->stats.icmpv6dev->mibs, 245 - snmp6_icmp6_list); 245 + snmp6_icmp6_list, ARRAY_SIZE(snmp6_icmp6_list) - 1); 246 + 246 247 snmp6_seq_show_icmpv6msg(seq, idev->stats.icmpv6msgdev->mibs); 247 248 return 0; 248 249 }
+6 -6
net/mptcp/mib.c
··· 85 85 SNMP_MIB_ITEM("DssFallback", MPTCP_MIB_DSSFALLBACK), 86 86 SNMP_MIB_ITEM("SimultConnectFallback", MPTCP_MIB_SIMULTCONNFALLBACK), 87 87 SNMP_MIB_ITEM("FallbackFailed", MPTCP_MIB_FALLBACKFAILED), 88 - SNMP_MIB_SENTINEL 89 88 }; 90 89 91 90 /* mptcp_mib_alloc - allocate percpu mib counters ··· 107 108 108 109 void mptcp_seq_show(struct seq_file *seq) 109 110 { 110 - unsigned long sum[ARRAY_SIZE(mptcp_snmp_list) - 1]; 111 + unsigned long sum[ARRAY_SIZE(mptcp_snmp_list)]; 112 + const int cnt = ARRAY_SIZE(mptcp_snmp_list); 111 113 struct net *net = seq->private; 112 114 int i; 113 115 114 116 seq_puts(seq, "MPTcpExt:"); 115 - for (i = 0; mptcp_snmp_list[i].name; i++) 117 + for (i = 0; i < cnt; i++) 116 118 seq_printf(seq, " %s", mptcp_snmp_list[i].name); 117 119 118 120 seq_puts(seq, "\nMPTcpExt:"); 119 121 120 122 memset(sum, 0, sizeof(sum)); 121 123 if (net->mib.mptcp_statistics) 122 - snmp_get_cpu_field_batch(sum, mptcp_snmp_list, 123 - net->mib.mptcp_statistics); 124 + snmp_get_cpu_field_batch_cnt(sum, mptcp_snmp_list, cnt, 125 + net->mib.mptcp_statistics); 124 126 125 - for (i = 0; mptcp_snmp_list[i].name; i++) 127 + for (i = 0; i < cnt; i++) 126 128 seq_printf(seq, " %lu", sum[i]); 127 129 128 130 seq_putc(seq, '\n');
+6 -6
net/sctp/proc.c
··· 52 52 SNMP_MIB_ITEM("SctpInPktBacklog", SCTP_MIB_IN_PKT_BACKLOG), 53 53 SNMP_MIB_ITEM("SctpInPktDiscards", SCTP_MIB_IN_PKT_DISCARDS), 54 54 SNMP_MIB_ITEM("SctpInDataChunkDiscards", SCTP_MIB_IN_DATA_CHUNK_DISCARDS), 55 - SNMP_MIB_SENTINEL 56 55 }; 57 56 58 57 /* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */ 59 58 static int sctp_snmp_seq_show(struct seq_file *seq, void *v) 60 59 { 61 - unsigned long buff[SCTP_MIB_MAX]; 60 + unsigned long buff[ARRAY_SIZE(sctp_snmp_list)]; 61 + const int cnt = ARRAY_SIZE(sctp_snmp_list); 62 62 struct net *net = seq->private; 63 63 int i; 64 64 65 - memset(buff, 0, sizeof(unsigned long) * SCTP_MIB_MAX); 65 + memset(buff, 0, sizeof(buff)); 66 66 67 - snmp_get_cpu_field_batch(buff, sctp_snmp_list, 68 - net->sctp.sctp_statistics); 69 - for (i = 0; sctp_snmp_list[i].name; i++) 67 + snmp_get_cpu_field_batch_cnt(buff, sctp_snmp_list, cnt, 68 + net->sctp.sctp_statistics); 69 + for (i = 0; i < cnt; i++) 70 70 seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name, 71 71 buff[i]); 72 72
+6 -4
net/tls/tls_proc.c
··· 27 27 SNMP_MIB_ITEM("TlsTxRekeyOk", LINUX_MIB_TLSTXREKEYOK), 28 28 SNMP_MIB_ITEM("TlsTxRekeyError", LINUX_MIB_TLSTXREKEYERROR), 29 29 SNMP_MIB_ITEM("TlsRxRekeyReceived", LINUX_MIB_TLSRXREKEYRECEIVED), 30 - SNMP_MIB_SENTINEL 31 30 }; 32 31 33 32 static int tls_statistics_seq_show(struct seq_file *seq, void *v) 34 33 { 35 - unsigned long buf[LINUX_MIB_TLSMAX] = {}; 34 + unsigned long buf[ARRAY_SIZE(tls_mib_list)]; 35 + const int cnt = ARRAY_SIZE(tls_mib_list); 36 36 struct net *net = seq->private; 37 37 int i; 38 38 39 - snmp_get_cpu_field_batch(buf, tls_mib_list, net->mib.tls_statistics); 40 - for (i = 0; tls_mib_list[i].name; i++) 39 + memset(buf, 0, sizeof(buf)); 40 + snmp_get_cpu_field_batch_cnt(buf, tls_mib_list, cnt, 41 + net->mib.tls_statistics); 42 + for (i = 0; i < cnt; i++) 41 43 seq_printf(seq, "%-32s\t%lu\n", tls_mib_list[i].name, buf[i]); 42 44 43 45 return 0;
+6 -6
net/xfrm/xfrm_proc.c
··· 45 45 SNMP_MIB_ITEM("XfrmInStateDirError", LINUX_MIB_XFRMINSTATEDIRERROR), 46 46 SNMP_MIB_ITEM("XfrmInIptfsError", LINUX_MIB_XFRMINIPTFSERROR), 47 47 SNMP_MIB_ITEM("XfrmOutNoQueueSpace", LINUX_MIB_XFRMOUTNOQSPACE), 48 - SNMP_MIB_SENTINEL 49 48 }; 50 49 51 50 static int xfrm_statistics_seq_show(struct seq_file *seq, void *v) 52 51 { 53 - unsigned long buff[LINUX_MIB_XFRMMAX]; 52 + unsigned long buff[ARRAY_SIZE(xfrm_mib_list)]; 53 + const int cnt = ARRAY_SIZE(xfrm_mib_list); 54 54 struct net *net = seq->private; 55 55 int i; 56 56 57 - memset(buff, 0, sizeof(unsigned long) * LINUX_MIB_XFRMMAX); 57 + memset(buff, 0, sizeof(buff)); 58 58 59 59 xfrm_state_update_stats(net); 60 - snmp_get_cpu_field_batch(buff, xfrm_mib_list, 61 - net->mib.xfrm_statistics); 62 - for (i = 0; xfrm_mib_list[i].name; i++) 60 + snmp_get_cpu_field_batch_cnt(buff, xfrm_mib_list, cnt, 61 + net->mib.xfrm_statistics); 62 + for (i = 0; i < cnt; i++) 63 63 seq_printf(seq, "%-24s\t%lu\n", xfrm_mib_list[i].name, 64 64 buff[i]); 65 65