Skip to content

Commit 14878f7

Browse files
David L StevensDavid S. Miller
authored andcommitted
[IPV6]: Add ICMPMsgStats MIB (RFC 4293) [rev 2]
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. [new to 2nd revision] 6) support per-interface ICMP stats 7) use common macro for per-device stat macros Signed-off-by: David L Stevens <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8b14a53 commit 14878f7

File tree

11 files changed

+135
-122
lines changed

11 files changed

+135
-122
lines changed

include/linux/snmp.h

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -91,35 +91,12 @@ enum
9191
ICMP6_MIB_NUM = 0,
9292
ICMP6_MIB_INMSGS, /* InMsgs */
9393
ICMP6_MIB_INERRORS, /* InErrors */
94-
ICMP6_MIB_INDESTUNREACHS, /* InDestUnreachs */
95-
ICMP6_MIB_INPKTTOOBIGS, /* InPktTooBigs */
96-
ICMP6_MIB_INTIMEEXCDS, /* InTimeExcds */
97-
ICMP6_MIB_INPARMPROBLEMS, /* InParmProblems */
98-
ICMP6_MIB_INECHOS, /* InEchos */
99-
ICMP6_MIB_INECHOREPLIES, /* InEchoReplies */
100-
ICMP6_MIB_INGROUPMEMBQUERIES, /* InGroupMembQueries */
101-
ICMP6_MIB_INGROUPMEMBRESPONSES, /* InGroupMembResponses */
102-
ICMP6_MIB_INGROUPMEMBREDUCTIONS, /* InGroupMembReductions */
103-
ICMP6_MIB_INROUTERSOLICITS, /* InRouterSolicits */
104-
ICMP6_MIB_INROUTERADVERTISEMENTS, /* InRouterAdvertisements */
105-
ICMP6_MIB_INNEIGHBORSOLICITS, /* InNeighborSolicits */
106-
ICMP6_MIB_INNEIGHBORADVERTISEMENTS, /* InNeighborAdvertisements */
107-
ICMP6_MIB_INREDIRECTS, /* InRedirects */
10894
ICMP6_MIB_OUTMSGS, /* OutMsgs */
109-
ICMP6_MIB_OUTDESTUNREACHS, /* OutDestUnreachs */
110-
ICMP6_MIB_OUTPKTTOOBIGS, /* OutPktTooBigs */
111-
ICMP6_MIB_OUTTIMEEXCDS, /* OutTimeExcds */
112-
ICMP6_MIB_OUTPARMPROBLEMS, /* OutParmProblems */
113-
ICMP6_MIB_OUTECHOREPLIES, /* OutEchoReplies */
114-
ICMP6_MIB_OUTROUTERSOLICITS, /* OutRouterSolicits */
115-
ICMP6_MIB_OUTNEIGHBORSOLICITS, /* OutNeighborSolicits */
116-
ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS, /* OutNeighborAdvertisements */
117-
ICMP6_MIB_OUTREDIRECTS, /* OutRedirects */
118-
ICMP6_MIB_OUTGROUPMEMBRESPONSES, /* OutGroupMembResponses */
119-
ICMP6_MIB_OUTGROUPMEMBREDUCTIONS, /* OutGroupMembReductions */
12095
__ICMP6_MIB_MAX
12196
};
12297

98+
#define __ICMP6MSG_MIB_MAX 512 /* Out+In for all 8-bit ICMPv6 types */
99+
123100
/* tcp mib definitions */
124101
/*
125102
* RFC 1213: MIB-II TCP group

include/net/if_inet6.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ struct ipv6_devstat {
154154
struct proc_dir_entry *proc_dir_entry;
155155
DEFINE_SNMP_STAT(struct ipstats_mib, ipv6);
156156
DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6);
157+
DEFINE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg);
157158
};
158159

159160
struct inet6_dev

include/net/ipv6.h

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -112,52 +112,49 @@ struct frag_hdr {
112112
extern int sysctl_ipv6_bindv6only;
113113
extern int sysctl_mld_max_msf;
114114

115-
/* MIBs */
116-
DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
117-
#define IP6_INC_STATS(idev,field) ({ \
115+
#define _DEVINC(statname, modifier, idev, field) \
116+
({ \
118117
struct inet6_dev *_idev = (idev); \
119118
if (likely(_idev != NULL)) \
120-
SNMP_INC_STATS(_idev->stats.ipv6, field); \
121-
SNMP_INC_STATS(ipv6_statistics, field); \
122-
})
123-
#define IP6_INC_STATS_BH(idev,field) ({ \
124-
struct inet6_dev *_idev = (idev); \
125-
if (likely(_idev != NULL)) \
126-
SNMP_INC_STATS_BH(_idev->stats.ipv6, field); \
127-
SNMP_INC_STATS_BH(ipv6_statistics, field); \
128-
})
129-
#define IP6_INC_STATS_USER(idev,field) ({ \
130-
struct inet6_dev *_idev = (idev); \
131-
if (likely(_idev != NULL)) \
132-
SNMP_INC_STATS_USER(_idev->stats.ipv6, field); \
133-
SNMP_INC_STATS_USER(ipv6_statistics, field); \
119+
SNMP_INC_STATS##modifier((_idev)->stats.statname, (field)); \
120+
SNMP_INC_STATS##modifier(statname##_statistics, (field)); \
134121
})
122+
123+
/* MIBs */
124+
DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
125+
126+
#define IP6_INC_STATS(idev,field) _DEVINC(ipv6, , idev, field)
127+
#define IP6_INC_STATS_BH(idev,field) _DEVINC(ipv6, _BH, idev, field)
128+
#define IP6_INC_STATS_USER(idev,field) _DEVINC(ipv6, _USER, idev, field)
129+
135130
DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
136-
#define ICMP6_INC_STATS(idev, field) ({ \
137-
struct inet6_dev *_idev = (idev); \
138-
if (likely(_idev != NULL)) \
139-
SNMP_INC_STATS(idev->stats.icmpv6, field); \
140-
SNMP_INC_STATS(icmpv6_statistics, field); \
141-
})
142-
#define ICMP6_INC_STATS_BH(idev, field) ({ \
143-
struct inet6_dev *_idev = (idev); \
144-
if (likely(_idev != NULL)) \
145-
SNMP_INC_STATS_BH((_idev)->stats.icmpv6, field); \
146-
SNMP_INC_STATS_BH(icmpv6_statistics, field); \
147-
})
148-
#define ICMP6_INC_STATS_USER(idev, field) ({ \
149-
struct inet6_dev *_idev = (idev); \
150-
if (likely(_idev != NULL)) \
151-
SNMP_INC_STATS_USER(_idev->stats.icmpv6, field); \
152-
SNMP_INC_STATS_USER(icmpv6_statistics, field); \
153-
})
131+
DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
132+
133+
#define ICMP6_INC_STATS(idev, field) _DEVINC(icmpv6, , idev, field)
134+
#define ICMP6_INC_STATS_BH(idev, field) _DEVINC(icmpv6, _BH, idev, field)
135+
#define ICMP6_INC_STATS_USER(idev, field) _DEVINC(icmpv6, _USER, idev, field)
136+
154137
#define ICMP6_INC_STATS_OFFSET_BH(idev, field, offset) ({ \
155138
struct inet6_dev *_idev = idev; \
156139
__typeof__(offset) _offset = (offset); \
157140
if (likely(_idev != NULL)) \
158141
SNMP_INC_STATS_OFFSET_BH(_idev->stats.icmpv6, field, _offset); \
159142
SNMP_INC_STATS_OFFSET_BH(icmpv6_statistics, field, _offset); \
160143
})
144+
145+
#define ICMP6MSGOUT_INC_STATS(idev, field) \
146+
_DEVINC(icmpv6msg, , idev, field +256)
147+
#define ICMP6MSGOUT_INC_STATS_BH(idev, field) \
148+
_DEVINC(icmpv6msg, _BH, idev, field +256)
149+
#define ICMP6MSGOUT_INC_STATS_USER(idev, field) \
150+
_DEVINC(icmpv6msg, _USER, idev, field +256)
151+
#define ICMP6MSGIN_INC_STATS(idev, field) \
152+
_DEVINC(icmpv6msg, , idev, field)
153+
#define ICMP6MSGIN_INC_STATS_BH(idev, field) \
154+
_DEVINC(icmpv6msg, _BH, idev, field)
155+
#define ICMP6MSGIN_INC_STATS_USER(idev, field) \
156+
_DEVINC(icmpv6msg, _USER, idev, field)
157+
161158
DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
162159
DECLARE_SNMP_STAT(struct udp_mib, udplite_stats_in6);
163160
#define UDP6_INC_STATS_BH(field, is_udplite) do { \

include/net/snmp.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ struct icmpv6_mib {
8888
unsigned long mibs[ICMP6_MIB_MAX];
8989
} __SNMP_MIB_ALIGN__;
9090

91+
#define ICMP6MSG_MIB_MAX __ICMP6MSG_MIB_MAX
92+
struct icmpv6msg_mib {
93+
unsigned long mibs[ICMP6MSG_MIB_MAX];
94+
} __SNMP_MIB_ALIGN__;
95+
96+
9197
/* TCP */
9298
#define TCP_MIB_MAX __TCP_MIB_MAX
9399
struct tcp_mib {

net/ipv6/addrconf.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,15 @@ static int snmp6_alloc_dev(struct inet6_dev *idev)
261261
sizeof(struct icmpv6_mib),
262262
__alignof__(struct icmpv6_mib)) < 0)
263263
goto err_icmp;
264+
if (snmp_mib_init((void **)idev->stats.icmpv6msg,
265+
sizeof(struct icmpv6msg_mib),
266+
__alignof__(struct icmpv6msg_mib)) < 0)
267+
goto err_icmpmsg;
264268

265269
return 0;
266270

271+
err_icmpmsg:
272+
snmp_mib_free((void **)idev->stats.icmpv6);
267273
err_icmp:
268274
snmp_mib_free((void **)idev->stats.ipv6);
269275
err_ip:
@@ -272,6 +278,7 @@ static int snmp6_alloc_dev(struct inet6_dev *idev)
272278

273279
static int snmp6_free_dev(struct inet6_dev *idev)
274280
{
281+
snmp_mib_free((void **)idev->stats.icmpv6msg);
275282
snmp_mib_free((void **)idev->stats.icmpv6);
276283
snmp_mib_free((void **)idev->stats.ipv6);
277284
return 0;

net/ipv6/af_inet6.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,9 @@ static int __init init_ipv6_mibs(void)
719719
if (snmp_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib),
720720
__alignof__(struct icmpv6_mib)) < 0)
721721
goto err_icmp_mib;
722+
if (snmp_mib_init((void **)icmpv6msg_statistics,
723+
sizeof (struct icmpv6msg_mib), __alignof__(struct icmpv6_mib)) < 0)
724+
goto err_icmpmsg_mib;
722725
if (snmp_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib),
723726
__alignof__(struct udp_mib)) < 0)
724727
goto err_udp_mib;
@@ -730,6 +733,8 @@ static int __init init_ipv6_mibs(void)
730733
err_udplite_mib:
731734
snmp_mib_free((void **)udp_stats_in6);
732735
err_udp_mib:
736+
snmp_mib_free((void **)icmpv6msg_statistics);
737+
err_icmpmsg_mib:
733738
snmp_mib_free((void **)icmpv6_statistics);
734739
err_icmp_mib:
735740
snmp_mib_free((void **)ipv6_statistics);

net/ipv6/icmp.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@
6969

7070
DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly;
7171
EXPORT_SYMBOL(icmpv6_statistics);
72+
DEFINE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics) __read_mostly;
73+
EXPORT_SYMBOL(icmpv6msg_statistics);
7274

7375
/*
7476
* The ICMP socket(s). This is the most convenient way to flow control
@@ -456,8 +458,6 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
456458
}
457459
err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr));
458460

459-
if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
460-
ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_OUTDESTUNREACHS, type - ICMPV6_DEST_UNREACH);
461461
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
462462

463463
out_put:
@@ -547,9 +547,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
547547
}
548548
err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
549549

550-
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTECHOREPLIES);
551-
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
552-
553550
out_put:
554551
if (likely(idev != NULL))
555552
in6_dev_put(idev);
@@ -656,10 +653,7 @@ static int icmpv6_rcv(struct sk_buff **pskb)
656653

657654
type = hdr->icmp6_type;
658655

659-
if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
660-
ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_INDESTUNREACHS, type - ICMPV6_DEST_UNREACH);
661-
else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
662-
ICMP6_INC_STATS_OFFSET_BH(idev, ICMP6_MIB_INECHOS, type - ICMPV6_ECHO_REQUEST);
656+
ICMP6MSGIN_INC_STATS_BH(idev, type);
663657

664658
switch (type) {
665659
case ICMPV6_ECHO_REQUEST:

net/ipv6/ip6_output.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,13 @@ int ip6_push_pending_frames(struct sock *sk)
13991399

14001400
skb->dst = dst_clone(&rt->u.dst);
14011401
IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
1402+
if (proto == IPPROTO_ICMPV6) {
1403+
struct inet6_dev *idev = ip6_dst_idev(skb->dst);
1404+
1405+
ICMP6MSGOUT_INC_STATS_BH(idev, icmp6_hdr(skb)->icmp6_type);
1406+
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
1407+
}
1408+
14021409
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
14031410
if (err) {
14041411
if (err > 0)

net/ipv6/mcast.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,10 +1479,11 @@ static void mld_sendpack(struct sk_buff *skb)
14791479
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
14801480
mld_dev_queue_xmit);
14811481
if (!err) {
1482-
ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS);
1483-
IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
1482+
ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT);
1483+
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
1484+
IP6_INC_STATS_BH(idev, IPSTATS_MIB_OUTMCASTPKTS);
14841485
} else
1485-
IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
1486+
IP6_INC_STATS_BH(idev, IPSTATS_MIB_OUTDISCARDS);
14861487

14871488
if (likely(idev != NULL))
14881489
in6_dev_put(idev);
@@ -1822,10 +1823,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
18221823
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
18231824
mld_dev_queue_xmit);
18241825
if (!err) {
1825-
if (type == ICMPV6_MGM_REDUCTION)
1826-
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBREDUCTIONS);
1827-
else
1828-
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBRESPONSES);
1826+
ICMP6MSGOUT_INC_STATS(idev, type);
18291827
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
18301828
IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
18311829
} else

net/ipv6/ndisc.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ static void __ndisc_send(struct net_device *dev,
431431
struct neighbour *neigh,
432432
struct in6_addr *daddr, struct in6_addr *saddr,
433433
struct icmp6hdr *icmp6h, struct in6_addr *target,
434-
int llinfo, int icmp6_mib_outnd)
434+
int llinfo)
435435
{
436436
struct flowi fl;
437437
struct dst_entry *dst;
@@ -441,9 +441,11 @@ static void __ndisc_send(struct net_device *dev,
441441
struct inet6_dev *idev;
442442
int len;
443443
int err;
444-
u8 *opt;
444+
u8 *opt, type;
445+
446+
type = icmp6h->icmp6_type;
445447

446-
ndisc_flow_init(&fl, icmp6h->icmp6_type, saddr, daddr,
448+
ndisc_flow_init(&fl, type, saddr, daddr,
447449
dev->ifindex);
448450

449451
dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
@@ -504,7 +506,7 @@ static void __ndisc_send(struct net_device *dev,
504506

505507
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
506508
if (!err) {
507-
ICMP6_INC_STATS(idev, icmp6_mib_outnd);
509+
ICMP6MSGOUT_INC_STATS(idev, type);
508510
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
509511
}
510512

@@ -542,8 +544,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
542544

543545
__ndisc_send(dev, neigh, daddr, src_addr,
544546
&icmp6h, solicited_addr,
545-
inc_opt ? ND_OPT_TARGET_LL_ADDR : 0,
546-
ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS);
547+
inc_opt ? ND_OPT_TARGET_LL_ADDR : 0);
547548
}
548549

549550
void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
@@ -564,8 +565,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
564565

565566
__ndisc_send(dev, neigh, daddr, saddr,
566567
&icmp6h, solicit,
567-
!ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0,
568-
ICMP6_MIB_OUTNEIGHBORSOLICITS);
568+
!ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0);
569569
}
570570

571571
void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
@@ -599,8 +599,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
599599
#endif
600600
__ndisc_send(dev, NULL, daddr, saddr,
601601
&icmp6h, NULL,
602-
send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0,
603-
ICMP6_MIB_OUTROUTERSOLICITS);
602+
send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0);
604603
}
605604

606605

@@ -1455,7 +1454,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
14551454
IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
14561455
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
14571456
if (!err) {
1458-
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS);
1457+
ICMP6MSGOUT_INC_STATS(idev, NDISC_REDIRECT);
14591458
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
14601459
}
14611460

0 commit comments

Comments
 (0)