Wednesday, October 21, 2009

Section 23.3.  IP Statistics










23.3. IP Statistics






























The Linux kernel keeps several sets of statistics about different events and conditions that can be useful for accounting, debugging, or confirming compatibility with standards. In this chapter, we will only briefly see what statistics are kept by the IP protocol layer (without touching on the SNMP infrastructure) and how they are updated. In previous chapters, especially when describing the various functions, we saw a few cases where macros such as IP_INC_STATS were used to update the value of some counters.


Let's start with the data structure that contains all of the counters associated with the IP protocol. It is called ip_statistics and is defined in net/ipv4/ip_input.c. It is a vector with two pointers, each one pointing to a vector of ipstats_mib[*] structures (defined in include/net/snmp.h), one per CPU. The allocation of such vectors is done in init_ipv4_mibs in net/ipv4/af_inet.c.

[*] MIB, as mentioned earlier, stands for Management Information Base, and is used to refer to a collection of objects (typically counters).



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



The ipstats_mib structure is simply declared as an array of unsigned long fields of size _ _IPSTATS_MIB_MAX, which happens to be the size of the IPSTATS_MIB_XXX enumeration list in include/linux/snmp.h.


Here is the meaning of the IPSTATS_MIB_XXX values, classified into four groups. For a more detailed description, you can refer to RFC 2011 for IPv4 and RFC 2465 for IPv6. The IPSTATS_MIX_XXX counters that are not used by IPv4 (with the exception of IPSTATS_MIB_INADDRERRORS) are not defined in RFC 2011.



Fields related to received packets




IPSTATS_MIB_INRECEIVES


Number of packets received. This field does not distinguish between complete IP packets and fragments. It also includes both the ones that will be accepted and the ones that will be discarded for any reason (with the exception of those dropped because an interface in promiscuous mode delivered frames to ip_rcv that were not addressed to the receiving interface). It is updated at the beginning of ip_rcv.


IPSTATS_MIB_INHDRERRORS


Number of packets (fragments as well as nonfragmented packets) that were discarded because of corrupted IP headers. This field can be updated both in ip_rcv and in ip_rcv_finish for different reasons.


IPSTATS_MIB_INTOOBIGERRORS


Not used by IPv4. IPv6 uses it to count those ingress IP packets that cannot be forwarded because they would need to be fragmented (which is not an allowed operation for a router in IPv6, unlike IPv4).


IPSTATS_MIB_INNOROUTES


Not used at the moment. It is supposed to count those ingress packets that could not be forwarded because the local host does not have a valid route.


IPSTATS_MIB_INADDRERRORS


Not used at the moment by IPv4. IPv6 uses it to count those packets received with a wrong address type.


IPSTATS_MIB_INUNKNOWNPROTOS


Number of packets received with an unknown L4 protocol (i.e., no handler for the protocol was registered). This field is updated in ip_local_deliver_finish.


IPSTATS_MIB_INTRUNCATEDPKTS


The packet is truncated (i.e., it does not include a full IP header). It is used by IPv6, but not by IPv4.


IPSTATS_MIB_INDISCARDS


Number of packets discarded. This counter does not include the packets dropped because of header errors; it mainly includes memory allocation problems. This field is updated in ip_rcv and ip_rcv_finish.


IPSTATS_MIB_INDELIVERS


Number of packets successfully delivered to L4 protocol handlers. This field is updated in ip_local_deliver_finish.


IPSTATS_MIB_INMCASTPKTS


Number of received multicast packets. It is used by IPv6, but not by IPv4.


Fields related to transmitted packets




IPSTATS_MIB_OUTFORWDATAGRAMS


Number of ingress packets that needed to be forwarded. This counter is actually incremented before the packets are transmitted and when they theoretically could still be discarded for some reason. Its value is updated in ip_forward_finish (and in ipmr_forward_finish for multicast).


IPSTATS_MIB_OUTREQUESTS


Number of packets that the system tried to transmit (successfully or not), not including forwarded packets. This field is updated in ip_ouput (and in ip_mc_output for multicast).


IPSTATS_MIB_OUTDISCARDS


Number of packets whose transmission failed. This field is updated in several places, including ip_append_data, ip_push_pending_frames, and raw_send_hdrinc.


IPSTATS_MIB_OUTNOROUTES


Number of locally generated packets discarded because there was no route to transmit them. Normally this field is updated after a failure of ip_route_output_flow. ip_queue_xmit is one of the functions that can update it.


IPSTATS_MIB_OUTMCASTPKTS


Number of transmitted multicast packets. Not used by IPv4 at the moment.


Fields related to defragmentation




IPSTATS_MIB_REASMTIMEOUT


Number of packets that failed defragmentation because some of the fragments were not received in time. The value reflects the number of complete packets, not the number of fragments. This field is updated in ip_expire, which is the timer function executed when an IP fragment list is dropped due to a timeout. Note that this counter is not used as defined in the two RFCs mentioned at the beginning of this section.


IPSTATS_MIB_REASMREQDS


Number of fragments received (and therefore the number of attempted reassemblies). This field is updated in ip_defrag.


IPSTATS_MIB_REASMFAILS


Number of packets that failed the defragmentation. This field is updated in several places (_ _ip_evictor, ip_expire, ip_frag_reasm, and ip_defrag) for different reasons.


IPSTATS_MIB_REASMOKS


Number of packets successfully defragmented. This field is updated in ip_frag_reasm.


Fields related to fragmentation




IPSTATS_MIB_FRAGFAILS


Number of failed fragmentation efforts. This field is updated in ip_fragment (and in ipmr_queue_xmit for multicast).


IPSTATS_MIB_FRAGOKS


Number of fragments transmitted. This field is updated in ip_fragment.


IPSTATS_MIB_FRAGCREATES


Number of fragments created. This field is updated in ip_fragment.


The values of these counters are exported in the /proc/net/snmp file.


Each CPU keeps its own accounting information about the packets it processes. Furthermore, it keeps two counters: one for events in interrupt context and the other for events outside interrupt context. Therefore, the ip_statistics array includes two elements per CPU, one for interrupt context and one for noninterrupt context. Not all of the events can happen in both contexts, but to make things easier and clearer, the vector has simply been defined of double in size; those elements that do not make sense in one of the two contexts are simply not to be used.


Because some pieces of code can be executed both in interrupt context and outside interrupt context, the kernel provides three different macros to add an event to the IP statistics vector:



#define IP_INC_STATS (field) SNMP_INC_STATS (ip_statistics, field)
#define IP_INC_STATS_BH (field) SNMP_INC_STATS_BH (ip_statistics, field)
#define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field)



The first can be used in either context, because it checks internally whether it was called in interrupt context and updates the right element accordingly. The second and the third macros are to be used for events that happened in and outside interrupt context, respectively. The macros IP_INC_STATS, IP_INC_STATS_BH, and IP_INC_STATS_USER are defined in include/net/ip.h, and the three associated SNMP_INC_XXX macros are defined in include/net/snmp.h.












No comments:

Post a Comment