Saturday, October 24, 2009

Section 25.9.  ICMP Statistics










25.9. ICMP Statistics












The ICMP protocol keeps the statistics defined in RFC 2011, storing them in icmp_mib data structures. The kernel maintains statistics on a per-CPU basis, and for each CPU it distinguishes between statistics updated in software interrupt context and those updated outside that context. In other words, for each counter there are two instances per CPU: one of those two instances is used by code running in software interrupt context and the other is used by code not running in software interrupt context. All of those icmp_mib instances are allocated by init_ipv4_mibs in net/ipv4/af_inet.c. icmp_statistics is a two-element array, whose first element represents the per-CPU array of icmp_mib instances used by code that runs in software interrupt context, and whose second element represents the other per-CPU array.



static int _ _init init_ipv4_mibs(void)
{
...
icmp_statistics[0] = alloc_percpu(struct icmp_mib);
icmp_statistics[1] = alloc_percpu(struct icmp_mib);
...
}



The icmp_mib structure consists of an array of unsigned long members, one for each counter defined in RFC 2011 for the ICMP protocol:



#define SNMP_MIB_DUMMY _ _ICMP_MIB_MAX
#define ICMP_MIB_MAX (ICMP_MIB_MAX + 1)
struct icmp_mib {
unsigned long mibs[ICMP_MIB_MAX];
} _ _SNMP_MIB_ALIGN_ _;



The counters are identified via the enumeration list ICMP_MIB_XXX, defined in include/linux/snmp.h:



enum
{
ICMP_MIB_NUM = 0,
ICMP_MIB_INMSG,
...
ICMP_MIB_OUTADDRMASKREPS,
_ _ICMP_MIB_MAX
}



Note that the size of the icmp_mib array is one unit bigger than the size of the ICMP_MIB_XXX enumeration list. The extra element is used to account for ICMP message types not recognized by the kernel.


At any time, when the kernel needs to update a given counter, it selects the right element of icmp_statistics based on the interrupt context, and then the right icmp_mib instance based on the current CPU. The kernel provides a set of macros in include/net/icmp.h that need only the counter identifier in input (i.e., ICMP_MIB_XXX) and transparently take care of the two selections just described:



ICMP_INC_STATS


This macro can be used both in and outside of software interrupt context.


ICMP_INC_STATS_BH


This macro can be used when the code that needs to update a counter always runs in software interrupt context.


ICMP_INC_STATS_USER


This macro can be used when the code that needs to update a counter never runs in software interrupt context.


The three macros are defined as wrappers around generic macros provided by the SNMP subsystem:



#define ICMP_INC_STATS(field) SNMP_INC_STATS(icmp_statistics, field)
#define ICMP_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmp_statistics, field)
#define ICMP_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmp_statistics, field)



Here is the meaning of the ICMP_MIB_XXX values. For a more detailed description, you can refer to RFC 2011.


Fields related to received ICMP messages



ICMP_MIB_INMSG


Number of received ICMP messages. It includes those messages that are accounted by ICMP_MIB_INERRORS.


ICMP_MIB_INERRORS


Number of ICMP messages dropped because of some problem. icmp_rcv and the handlers in Table 25-9 drop ingress messages when they have a truncated ICMP header. The L4 layer err_handler function described in the section "Passing Error Notifications to the Transport Layer" drops ingress messages when they have a truncated ICMP payload.


ICMP_MIB_IN XXX


Besides the two general-purpose counters just listed, there is one per-ICMP message type. ICMP_MIB_INXXX counts the number of ICMP messages of type XXX received.


ICMP_MIB_INXXX counterpart for each ICMP_MIB_OUTXXX counter:



ICMP_MIB_OUTMSG


Number of transmitted ICMP messages.


ICMP_MIB_OUTERRORS


Number of faulty ICMP transmissions. Not used.


ICMP_MIB_OUTXXX


Besides the two general-purpose counters just listed, there is one per-ICMP message type. ICMP_MIB_OUTXXX counts the number of ICMP messages of type XXX TRansmitted.


ICMP_MIB_INXXX counters are updated in icmp_rcv.


ICMP_MIB_OUTXXX counters are updated within icmp_reply and icmp_send by invoking icmp_out_count:



static void icmp_out_count(int type)
{
if (type <= NR_ICMP_TYPES) {
ICMP_INC_STATS(icmp_pointers[type].output_entry);
ICMP_INC_STATS(ICMP_MIB_OUTMSGS);
}
}



In both cases, for any ICMP type t, the right counter to increment is identified by means of the input_entry and output_entry fields of the icmp_control data structure associated with t. The values of these counters are exported in the /proc/net/snmp file. You can also read them with netstat -s (and with SNMP agents, of course).












No comments:

Post a Comment