icmp: Add counters for rate limits
There are multiple ICMP rate limiting mechanisms: * Global limits: net.ipv4.icmp_msgs_burst/icmp_msgs_per_sec * v4 per-host limits: net.ipv4.icmp_ratelimit/ratemask * v6 per-host limits: net.ipv6.icmp_ratelimit/ratemask However, when ICMP output is limited, there is no way to tell which limit has been hit or even if the limits are responsible for the lack of ICMP output. Add counters for each of the cases above. As we are within local_bh_disable(), use the __INC stats variant. Example output: # nstat -sz "*RateLimit*" IcmpOutRateLimitGlobal 134 0.0 IcmpOutRateLimitHost 770 0.0 Icmp6OutRateLimitHost 84 0.0 Signed-off-by: Jamie Bainbridge <jamie.bainbridge@gmail.com> Suggested-by: Abhishek Rawal <rawal.abhishek92@gmail.com> Link: https://lore.kernel.org/r/273b32241e6b7fdc5c609e6f5ebc68caf3994342.1674605770.git.jamie.bainbridge@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
9f92752788
commit
d0941130c9
|
@ -95,6 +95,8 @@ enum
|
||||||
ICMP_MIB_OUTADDRMASKS, /* OutAddrMasks */
|
ICMP_MIB_OUTADDRMASKS, /* OutAddrMasks */
|
||||||
ICMP_MIB_OUTADDRMASKREPS, /* OutAddrMaskReps */
|
ICMP_MIB_OUTADDRMASKREPS, /* OutAddrMaskReps */
|
||||||
ICMP_MIB_CSUMERRORS, /* InCsumErrors */
|
ICMP_MIB_CSUMERRORS, /* InCsumErrors */
|
||||||
|
ICMP_MIB_RATELIMITGLOBAL, /* OutRateLimitGlobal */
|
||||||
|
ICMP_MIB_RATELIMITHOST, /* OutRateLimitHost */
|
||||||
__ICMP_MIB_MAX
|
__ICMP_MIB_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -112,6 +114,7 @@ enum
|
||||||
ICMP6_MIB_OUTMSGS, /* OutMsgs */
|
ICMP6_MIB_OUTMSGS, /* OutMsgs */
|
||||||
ICMP6_MIB_OUTERRORS, /* OutErrors */
|
ICMP6_MIB_OUTERRORS, /* OutErrors */
|
||||||
ICMP6_MIB_CSUMERRORS, /* InCsumErrors */
|
ICMP6_MIB_CSUMERRORS, /* InCsumErrors */
|
||||||
|
ICMP6_MIB_RATELIMITHOST, /* OutRateLimitHost */
|
||||||
__ICMP6_MIB_MAX
|
__ICMP6_MIB_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -296,6 +296,7 @@ static bool icmpv4_global_allow(struct net *net, int type, int code)
|
||||||
if (icmp_global_allow())
|
if (icmp_global_allow())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
__ICMP_INC_STATS(net, ICMP_MIB_RATELIMITGLOBAL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,6 +326,8 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
|
||||||
if (peer)
|
if (peer)
|
||||||
inet_putpeer(peer);
|
inet_putpeer(peer);
|
||||||
out:
|
out:
|
||||||
|
if (!rc)
|
||||||
|
__ICMP_INC_STATS(net, ICMP_MIB_RATELIMITHOST);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -353,7 +353,7 @@ static void icmp_put(struct seq_file *seq)
|
||||||
seq_puts(seq, "\nIcmp: InMsgs InErrors InCsumErrors");
|
seq_puts(seq, "\nIcmp: InMsgs InErrors InCsumErrors");
|
||||||
for (i = 0; icmpmibmap[i].name; i++)
|
for (i = 0; icmpmibmap[i].name; i++)
|
||||||
seq_printf(seq, " In%s", icmpmibmap[i].name);
|
seq_printf(seq, " In%s", icmpmibmap[i].name);
|
||||||
seq_puts(seq, " OutMsgs OutErrors");
|
seq_puts(seq, " OutMsgs OutErrors OutRateLimitGlobal OutRateLimitHost");
|
||||||
for (i = 0; icmpmibmap[i].name; i++)
|
for (i = 0; icmpmibmap[i].name; i++)
|
||||||
seq_printf(seq, " Out%s", icmpmibmap[i].name);
|
seq_printf(seq, " Out%s", icmpmibmap[i].name);
|
||||||
seq_printf(seq, "\nIcmp: %lu %lu %lu",
|
seq_printf(seq, "\nIcmp: %lu %lu %lu",
|
||||||
|
@ -363,9 +363,11 @@ static void icmp_put(struct seq_file *seq)
|
||||||
for (i = 0; icmpmibmap[i].name; i++)
|
for (i = 0; icmpmibmap[i].name; i++)
|
||||||
seq_printf(seq, " %lu",
|
seq_printf(seq, " %lu",
|
||||||
atomic_long_read(ptr + icmpmibmap[i].index));
|
atomic_long_read(ptr + icmpmibmap[i].index));
|
||||||
seq_printf(seq, " %lu %lu",
|
seq_printf(seq, " %lu %lu %lu %lu",
|
||||||
snmp_fold_field(net->mib.icmp_statistics, ICMP_MIB_OUTMSGS),
|
snmp_fold_field(net->mib.icmp_statistics, ICMP_MIB_OUTMSGS),
|
||||||
snmp_fold_field(net->mib.icmp_statistics, ICMP_MIB_OUTERRORS));
|
snmp_fold_field(net->mib.icmp_statistics, ICMP_MIB_OUTERRORS),
|
||||||
|
snmp_fold_field(net->mib.icmp_statistics, ICMP_MIB_RATELIMITGLOBAL),
|
||||||
|
snmp_fold_field(net->mib.icmp_statistics, ICMP_MIB_RATELIMITHOST));
|
||||||
for (i = 0; icmpmibmap[i].name; i++)
|
for (i = 0; icmpmibmap[i].name; i++)
|
||||||
seq_printf(seq, " %lu",
|
seq_printf(seq, " %lu",
|
||||||
atomic_long_read(ptr + (icmpmibmap[i].index | 0x100)));
|
atomic_long_read(ptr + (icmpmibmap[i].index | 0x100)));
|
||||||
|
|
|
@ -183,6 +183,7 @@ static bool icmpv6_global_allow(struct net *net, int type)
|
||||||
if (icmp_global_allow())
|
if (icmp_global_allow())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
__ICMP_INC_STATS(net, ICMP_MIB_RATELIMITGLOBAL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +225,9 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
|
||||||
if (peer)
|
if (peer)
|
||||||
inet_putpeer(peer);
|
inet_putpeer(peer);
|
||||||
}
|
}
|
||||||
|
if (!res)
|
||||||
|
__ICMP6_INC_STATS(net, ip6_dst_idev(dst),
|
||||||
|
ICMP6_MIB_RATELIMITHOST);
|
||||||
dst_release(dst);
|
dst_release(dst);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,7 @@ static const struct snmp_mib snmp6_icmp6_list[] = {
|
||||||
SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS),
|
SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS),
|
||||||
SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS),
|
SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS),
|
||||||
SNMP_MIB_ITEM("Icmp6InCsumErrors", ICMP6_MIB_CSUMERRORS),
|
SNMP_MIB_ITEM("Icmp6InCsumErrors", ICMP6_MIB_CSUMERRORS),
|
||||||
|
SNMP_MIB_ITEM("Icmp6OutRateLimitHost", ICMP6_MIB_RATELIMITHOST),
|
||||||
SNMP_MIB_SENTINEL
|
SNMP_MIB_SENTINEL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue