Skip to content

Commit

Permalink
[tcpip] Add IP statistics collection as per RFC 4293
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Mar 2, 2014
1 parent c165e8d commit 11963c4
Show file tree
Hide file tree
Showing 7 changed files with 296 additions and 22 deletions.
4 changes: 4 additions & 0 deletions src/include/ipxe/fragment.h
Expand Up @@ -27,6 +27,8 @@ struct fragment {
size_t hdrlen;
/** Reassembly timer */
struct retry_timer timer;
/** Fragment reassembler */
struct fragment_reassembler *fragments;
};

/** A fragment reassembler */
Expand Down Expand Up @@ -59,6 +61,8 @@ struct fragment_reassembler {
* @ret more_frags More fragments exist
*/
int ( * more_fragments ) ( struct io_buffer *iobuf, size_t hdrlen );
/** Associated IP statistics */
struct ip_statistics *stats;
};

extern struct io_buffer *
Expand Down
187 changes: 187 additions & 0 deletions src/include/ipxe/ipstat.h
@@ -0,0 +1,187 @@
#ifndef _IPXE_IPSTATS_H
#define _IPXE_IPSTATS_H

/** @file
*
* IP statistics
*
*/

FILE_LICENCE ( GPL2_OR_LATER );

#include <ipxe/tables.h>

struct io_buffer;

/** IP system statistics
*
* Definitions are taken from the RFC4293 section 5
* "ipSystemStatsEntry" table.
*
* To minimise code size, we use "unsigned long" as the counter
* variable type regardless of whether this type is 32-bit or 64-bit.
* On a 32-bit build (e.g. the standard BIOS build), this means that
* we omit the "high capacity" 64-bit counters (prefixed with "HC").
* This reduces the code size required to maintain the counter values,
* and avoids the need to support the "%lld" format in vsprintf.c
* (which would require dragging in the 64-bit division library on a
* standard 32-bit build). Since total available memory in a 32-bit
* environment is limited to 4GB, it is unlikely that we will overflow
* even the 32-bit octet counters under normal operation.
*
* Counters relating to packet forwarding are omitted, since iPXE
* includes no functionality for acting as a router.
*
* Counters related to output fragmentation are omitted, since iPXE
* has no support for fragmenting transmitted packets.
*
* The ipSystemStatsInDiscards and ipSystemStatsOutDiscards counters
* are omitted, since they will always be zero.
*
* Separate octet counters for multicast packets are omitted to save
* code size.
*/
struct ip_statistics {
/** ipSystemStatsInReceives
*
* The total number of input IP datagrams received, including
* those received in error.
*/
unsigned long in_receives;
/** ipSystemStatsInOctets
*
* The total number of octets received in input IP datagrams,
* including those received in error. Octets from datagrams
* counted in ipSystemStatsInReceives MUST be counted here.
*/
unsigned long in_octets;
/** ipSystemStatsInHdrErrors
*
* The number of input IP datagrams discarded due to errors in
* their IP headers, including version number mismatch, other
* format errors, hop count exceeded, errors discovered in
* processing their IP options, etc.
*/
unsigned long in_hdr_errors;
/** ipSystemStatsInAddrErrors
*
* The number of input IP datagrams discarded because the IP
* address in their IP header's destination field was not a
* valid address to be received at this entity. This count
* includes invalid addresses (e.g., ::0). For entities that
* are not IP routers and therefore do not forward datagrams,
* this counter includes datagrams discarded because the
* destination address was not a local address.
*/
unsigned long in_addr_errors;
/** ipSystemStatsInUnknownProtos
*
* The number of locally-addressed IP datagrams received
* successfully but discarded because of an unknown or
* unsupported protocol.
*/
unsigned long in_unknown_protos;
/** ipSystemStatsInTruncatedPkts
*
* The number of input IP datagrams discarded because the
* datagram frame didn't carry enough data.
*/
unsigned long in_truncated_pkts;
/** ipSystemStatsReasmReqds
*
* The number of IP fragments received that needed to be
* reassembled at this interface.
*/
unsigned long reasm_reqds;
/** ipSystemStatsReasmOks
*
* The number of IP datagrams successfully reassembled.
*/
unsigned long reasm_oks;
/** ipSystemStatsReasmFails
*
* The number of failures detected by the IP re-assembly
* algorithm (for whatever reason: timed out, errors, etc.).
* Note that this is not necessarily a count of discarded IP
* fragments since some algorithms (notably the algorithm in
* RFC 815) can lose track of the number of fragments by
* combining them as they are received.
*/
unsigned long reasm_fails;
/** ipSystemStatsInDelivers
*
* The total number of datagrams successfully delivered to IP
* user-protocols (including ICMP).
*/
unsigned long in_delivers;
/** ipSystemStatsOutRequests
*
* The total number of IP datagrams that local IP user-
* protocols (including ICMP) supplied to IP in requests for
* transmission.
*/
unsigned long out_requests;
/** ipSystemStatsOutNoRoutes
*
* The number of locally generated IP datagrams discarded
* because no route could be found to transmit them to their
* destination.
*/
unsigned long out_no_routes;
/** ipSystemStatsOutTransmits
*
* The total number of IP datagrams that this entity supplied
* to the lower layers for transmission. This includes
* datagrams generated locally and those forwarded by this
* entity.
*/
unsigned long out_transmits;
/** ipSystemStatsOutOctets
*
* The total number of octets in IP datagrams delivered to the
* lower layers for transmission. Octets from datagrams
* counted in ipSystemStatsOutTransmits MUST be counted here.
*/
unsigned long out_octets;
/** ipSystemStatsInMcastPkts
*
* The number of IP multicast datagrams received.
*/
unsigned long in_mcast_pkts;
/** ipSystemStatsOutMcastPkts
*
* The number of IP multicast datagrams transmitted.
*/
unsigned long out_mcast_pkts;
/** ipSystemStatsInBcastPkts
*
* The number of IP broadcast datagrams received.
*/
unsigned long in_bcast_pkts;
/** ipSystemStatsOutBcastPkts
*
* The number of IP broadcast datagrams transmitted.
*/
unsigned long out_bcast_pkts;
};

/** An IP system statistics family */
struct ip_statistics_family {
/** IP version */
unsigned int version;
/** Statistics */
struct ip_statistics *stats;
};

/** IP system statistics family table */
#define IP_STATISTICS_FAMILIES \
__table ( struct ip_statistics_family, "ip_statistics_families" )

/** Declare an IP system statistics family */
#define __ip_statistics_family( order ) \
__table_entry ( IP_STATISTICS_FAMILIES, order )

#define IP_STATISTICS_IPV4 01
#define IP_STATISTICS_IPV6 02

#endif /* _IPXE_IPSTATS_H */
4 changes: 3 additions & 1 deletion src/include/ipxe/tcpip.h
Expand Up @@ -17,6 +17,7 @@ FILE_LICENCE ( GPL2_OR_LATER );

struct io_buffer;
struct net_device;
struct ip_statistics;

/** Empty checksum value
*
Expand Down Expand Up @@ -132,7 +133,8 @@ struct tcpip_net_protocol {

extern int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
uint8_t tcpip_proto, struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum,
struct ip_statistics *stats );
extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
struct sockaddr_tcpip *st_src,
struct sockaddr_tcpip *st_dest,
Expand Down
8 changes: 8 additions & 0 deletions src/net/fragment.c
Expand Up @@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <string.h>
#include <ipxe/retry.h>
#include <ipxe/timer.h>
#include <ipxe/ipstat.h>
#include <ipxe/fragment.h>

/** @file
Expand All @@ -45,6 +46,7 @@ static void fragment_expired ( struct retry_timer *timer, int fail __unused ) {
DBGC ( fragment, "FRAG %p expired\n", fragment );
free_iob ( fragment->iobuf );
list_del ( &fragment->list );
fragment->fragments->stats->reasm_fails++;
free ( fragment );
}

Expand Down Expand Up @@ -89,6 +91,9 @@ struct io_buffer * fragment_reassemble ( struct fragment_reassembler *fragments,
size_t expected_offset;
int more_frags;

/* Update statistics */
fragments->stats->reasm_reqds++;

/* Find matching fragment reassembly buffer, if any */
fragment = fragment_find ( fragments, iobuf, *hdrlen );

Expand All @@ -115,6 +120,7 @@ struct io_buffer * fragment_reassemble ( struct fragment_reassembler *fragments,
fragment->iobuf = iobuf;
fragment->hdrlen = *hdrlen;
timer_init ( &fragment->timer, fragment_expired, NULL );
fragment->fragments = fragments;
DBGC ( fragment, "FRAG %p [0,%zd)\n", fragment,
( iob_len ( iobuf ) - *hdrlen ) );

Expand Down Expand Up @@ -157,6 +163,7 @@ struct io_buffer * fragment_reassemble ( struct fragment_reassembler *fragments,
*hdrlen = fragment->hdrlen;
list_del ( &fragment->list );
free ( fragment );
fragments->stats->reasm_oks++;
return iobuf;
}
}
Expand All @@ -167,6 +174,7 @@ struct io_buffer * fragment_reassemble ( struct fragment_reassembler *fragments,
return NULL;

drop:
fragments->stats->reasm_fails++;
free_iob ( iobuf );
return NULL;
}

0 comments on commit 11963c4

Please sign in to comment.