Skip to content

Commit 96793b4

Browse files
David L StevensDavid S. Miller
authored andcommitted
[IPV4]: Add ICMPMsgStats MIB (RFC 4293)
Background: RFC 4293 deprecates existing individual, named ICMP type counters to be replaced with the ICMPMsgStatsTable. This table includes entries for both IPv4 and IPv6, and requires counting of all ICMP types, whether or not the machine implements the type. These patches "remove" (but not really) the existing counters, and replace them with the ICMPMsgStats tables for v4 and v6. It includes the named counters in the /proc places they were, but gets the values for them from the new tables. It also counts packets generated from raw socket output (e.g., OutEchoes, MLD queries, RA's from radvd, etc). Changes: 1) create icmpmsg_statistics mib 2) create icmpv6msg_statistics mib 3) modify existing counters to use these 4) modify /proc/net/snmp to add "IcmpMsg" with all ICMP types listed by number for easy SNMP parsing 5) modify /proc/net/snmp printing for "Icmp" to get the named data from new counters. Signed-off-by: David L Stevens <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 14878f7 commit 96793b4

File tree

8 files changed

+123
-78
lines changed

8 files changed

+123
-78
lines changed

include/linux/snmp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ enum
8282
__ICMP_MIB_MAX
8383
};
8484

85+
#define __ICMPMSG_MIB_MAX 512 /* Out+In for all 8-bit ICMP types */
86+
8587
/* icmp6 mib definitions */
8688
/*
8789
* RFC 2466: ICMPv6-MIB

include/net/icmp.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,16 @@ struct icmp_err {
3030

3131
extern struct icmp_err icmp_err_convert[];
3232
DECLARE_SNMP_STAT(struct icmp_mib, icmp_statistics);
33+
DECLARE_SNMP_STAT(struct icmpmsg_mib, icmpmsg_statistics);
3334
#define ICMP_INC_STATS(field) SNMP_INC_STATS(icmp_statistics, field)
3435
#define ICMP_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmp_statistics, field)
3536
#define ICMP_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmp_statistics, field)
37+
#define ICMPMSGOUT_INC_STATS(field) SNMP_INC_STATS(icmpmsg_statistics, field+256)
38+
#define ICMPMSGOUT_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmpmsg_statistics, field+256)
39+
#define ICMPMSGOUT_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmpmsg_statistics, field+256)
40+
#define ICMPMSGIN_INC_STATS(field) SNMP_INC_STATS(icmpmsg_statistics, field)
41+
#define ICMPMSGIN_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmpmsg_statistics, field)
42+
#define ICMPMSGIN_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmpmsg_statistics, field)
3643

3744
struct dst_entry;
3845
struct net_proto_family;
@@ -42,6 +49,7 @@ extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
4249
extern int icmp_rcv(struct sk_buff *skb);
4350
extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
4451
extern void icmp_init(struct net_proto_family *ops);
52+
extern void icmp_out_count(unsigned char type);
4553

4654
/* Move into dst.h ? */
4755
extern int xrlim_allow(struct dst_entry *dst, int timeout);

include/net/snmp.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ struct icmp_mib {
8282
unsigned long mibs[ICMP_MIB_MAX];
8383
} __SNMP_MIB_ALIGN__;
8484

85+
#define ICMPMSG_MIB_MAX __ICMPMSG_MIB_MAX
86+
struct icmpmsg_mib {
87+
unsigned long mibs[ICMPMSG_MIB_MAX];
88+
} __SNMP_MIB_ALIGN__;
89+
8590
/* ICMP6 (IPv6-ICMP) */
8691
#define ICMP6_MIB_MAX __ICMP6_MIB_MAX
8792
struct icmpv6_mib {

net/ipv4/af_inet.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,10 @@ static int __init init_ipv4_mibs(void)
13021302
sizeof(struct icmp_mib),
13031303
__alignof__(struct icmp_mib)) < 0)
13041304
goto err_icmp_mib;
1305+
if (snmp_mib_init((void **)icmpmsg_statistics,
1306+
sizeof(struct icmpmsg_mib),
1307+
__alignof__(struct icmpmsg_mib)) < 0)
1308+
goto err_icmpmsg_mib;
13051309
if (snmp_mib_init((void **)tcp_statistics,
13061310
sizeof(struct tcp_mib),
13071311
__alignof__(struct tcp_mib)) < 0)
@@ -1324,6 +1328,8 @@ static int __init init_ipv4_mibs(void)
13241328
err_udp_mib:
13251329
snmp_mib_free((void **)tcp_statistics);
13261330
err_tcp_mib:
1331+
snmp_mib_free((void **)icmpmsg_statistics);
1332+
err_icmpmsg_mib:
13271333
snmp_mib_free((void **)icmp_statistics);
13281334
err_icmp_mib:
13291335
snmp_mib_free((void **)ip_statistics);

net/ipv4/icmp.c

Lines changed: 6 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ struct icmp_bxm {
115115
* Statistics
116116
*/
117117
DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics) __read_mostly;
118+
DEFINE_SNMP_STAT(struct icmpmsg_mib, icmpmsg_statistics) __read_mostly;
118119

119120
/* An array of errno for error messages from dest unreach. */
120121
/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */
@@ -214,8 +215,6 @@ int sysctl_icmp_errors_use_inbound_ifaddr __read_mostly;
214215
*/
215216

216217
struct icmp_control {
217-
int output_entry; /* Field for increment on output */
218-
int input_entry; /* Field for increment on input */
219218
void (*handler)(struct sk_buff *skb);
220219
short error; /* This ICMP is classed as an error message */
221220
};
@@ -316,12 +315,10 @@ static inline int icmpv4_xrlim_allow(struct rtable *rt, int type, int code)
316315
/*
317316
* Maintain the counters used in the SNMP statistics for outgoing ICMP
318317
*/
319-
static void icmp_out_count(int type)
318+
void icmp_out_count(unsigned char type)
320319
{
321-
if (type <= NR_ICMP_TYPES) {
322-
ICMP_INC_STATS(icmp_pointers[type].output_entry);
323-
ICMP_INC_STATS(ICMP_MIB_OUTMSGS);
324-
}
320+
ICMPMSGOUT_INC_STATS(type);
321+
ICMP_INC_STATS(ICMP_MIB_OUTMSGS);
325322
}
326323

327324
/*
@@ -390,7 +387,6 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
390387
return;
391388

392389
icmp_param->data.icmph.checksum = 0;
393-
icmp_out_count(icmp_param->data.icmph.type);
394390

395391
inet->tos = ip_hdr(skb)->tos;
396392
daddr = ipc.addr = rt->rt_src;
@@ -952,6 +948,7 @@ int icmp_rcv(struct sk_buff *skb)
952948

953949
icmph = icmp_hdr(skb);
954950

951+
ICMPMSGIN_INC_STATS_BH(icmph->type);
955952
/*
956953
* 18 is the highest 'known' ICMP type. Anything else is a mystery
957954
*
@@ -986,7 +983,6 @@ int icmp_rcv(struct sk_buff *skb)
986983
}
987984
}
988985

989-
ICMP_INC_STATS_BH(icmp_pointers[icmph->type].input_entry);
990986
icmp_pointers[icmph->type].handler(skb);
991987

992988
drop:
@@ -1002,109 +998,71 @@ int icmp_rcv(struct sk_buff *skb)
1002998
*/
1003999
static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
10041000
[ICMP_ECHOREPLY] = {
1005-
.output_entry = ICMP_MIB_OUTECHOREPS,
1006-
.input_entry = ICMP_MIB_INECHOREPS,
10071001
.handler = icmp_discard,
10081002
},
10091003
[1] = {
1010-
.output_entry = ICMP_MIB_DUMMY,
1011-
.input_entry = ICMP_MIB_INERRORS,
10121004
.handler = icmp_discard,
10131005
.error = 1,
10141006
},
10151007
[2] = {
1016-
.output_entry = ICMP_MIB_DUMMY,
1017-
.input_entry = ICMP_MIB_INERRORS,
10181008
.handler = icmp_discard,
10191009
.error = 1,
10201010
},
10211011
[ICMP_DEST_UNREACH] = {
1022-
.output_entry = ICMP_MIB_OUTDESTUNREACHS,
1023-
.input_entry = ICMP_MIB_INDESTUNREACHS,
10241012
.handler = icmp_unreach,
10251013
.error = 1,
10261014
},
10271015
[ICMP_SOURCE_QUENCH] = {
1028-
.output_entry = ICMP_MIB_OUTSRCQUENCHS,
1029-
.input_entry = ICMP_MIB_INSRCQUENCHS,
10301016
.handler = icmp_unreach,
10311017
.error = 1,
10321018
},
10331019
[ICMP_REDIRECT] = {
1034-
.output_entry = ICMP_MIB_OUTREDIRECTS,
1035-
.input_entry = ICMP_MIB_INREDIRECTS,
10361020
.handler = icmp_redirect,
10371021
.error = 1,
10381022
},
10391023
[6] = {
1040-
.output_entry = ICMP_MIB_DUMMY,
1041-
.input_entry = ICMP_MIB_INERRORS,
10421024
.handler = icmp_discard,
10431025
.error = 1,
10441026
},
10451027
[7] = {
1046-
.output_entry = ICMP_MIB_DUMMY,
1047-
.input_entry = ICMP_MIB_INERRORS,
10481028
.handler = icmp_discard,
10491029
.error = 1,
10501030
},
10511031
[ICMP_ECHO] = {
1052-
.output_entry = ICMP_MIB_OUTECHOS,
1053-
.input_entry = ICMP_MIB_INECHOS,
10541032
.handler = icmp_echo,
10551033
},
10561034
[9] = {
1057-
.output_entry = ICMP_MIB_DUMMY,
1058-
.input_entry = ICMP_MIB_INERRORS,
10591035
.handler = icmp_discard,
10601036
.error = 1,
10611037
},
10621038
[10] = {
1063-
.output_entry = ICMP_MIB_DUMMY,
1064-
.input_entry = ICMP_MIB_INERRORS,
10651039
.handler = icmp_discard,
10661040
.error = 1,
10671041
},
10681042
[ICMP_TIME_EXCEEDED] = {
1069-
.output_entry = ICMP_MIB_OUTTIMEEXCDS,
1070-
.input_entry = ICMP_MIB_INTIMEEXCDS,
10711043
.handler = icmp_unreach,
10721044
.error = 1,
10731045
},
10741046
[ICMP_PARAMETERPROB] = {
1075-
.output_entry = ICMP_MIB_OUTPARMPROBS,
1076-
.input_entry = ICMP_MIB_INPARMPROBS,
10771047
.handler = icmp_unreach,
10781048
.error = 1,
10791049
},
10801050
[ICMP_TIMESTAMP] = {
1081-
.output_entry = ICMP_MIB_OUTTIMESTAMPS,
1082-
.input_entry = ICMP_MIB_INTIMESTAMPS,
10831051
.handler = icmp_timestamp,
10841052
},
10851053
[ICMP_TIMESTAMPREPLY] = {
1086-
.output_entry = ICMP_MIB_OUTTIMESTAMPREPS,
1087-
.input_entry = ICMP_MIB_INTIMESTAMPREPS,
10881054
.handler = icmp_discard,
10891055
},
10901056
[ICMP_INFO_REQUEST] = {
1091-
.output_entry = ICMP_MIB_DUMMY,
1092-
.input_entry = ICMP_MIB_DUMMY,
10931057
.handler = icmp_discard,
10941058
},
10951059
[ICMP_INFO_REPLY] = {
1096-
.output_entry = ICMP_MIB_DUMMY,
1097-
.input_entry = ICMP_MIB_DUMMY,
10981060
.handler = icmp_discard,
10991061
},
11001062
[ICMP_ADDRESS] = {
1101-
.output_entry = ICMP_MIB_OUTADDRMASKS,
1102-
.input_entry = ICMP_MIB_INADDRMASKS,
11031063
.handler = icmp_address,
11041064
},
11051065
[ICMP_ADDRESSREPLY] = {
1106-
.output_entry = ICMP_MIB_OUTADDRMASKREPS,
1107-
.input_entry = ICMP_MIB_INADDRMASKREPS,
11081066
.handler = icmp_address_reply,
11091067
},
11101068
};
@@ -1146,4 +1104,5 @@ void __init icmp_init(struct net_proto_family *ops)
11461104
EXPORT_SYMBOL(icmp_err_convert);
11471105
EXPORT_SYMBOL(icmp_send);
11481106
EXPORT_SYMBOL(icmp_statistics);
1107+
EXPORT_SYMBOL(icmpmsg_statistics);
11491108
EXPORT_SYMBOL(xrlim_allow);

net/ipv4/ip_output.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,10 @@ int ip_push_pending_frames(struct sock *sk)
12611261
skb->priority = sk->sk_priority;
12621262
skb->dst = dst_clone(&rt->u.dst);
12631263

1264+
if (iph->protocol == IPPROTO_ICMP)
1265+
icmp_out_count(((struct icmphdr *)
1266+
skb_transport_header(skb))->type);
1267+
12641268
/* Netfilter gets whole the not fragmented skb. */
12651269
err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
12661270
skb->dst->dev, dst_output);

0 commit comments

Comments
 (0)