Browse Source

[tcpip] Add IP statistics collection as per RFC 4293

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
11963c4f5f
7 changed files with 296 additions and 22 deletions
  1. 4
    0
      src/include/ipxe/fragment.h
  2. 187
    0
      src/include/ipxe/ipstat.h
  3. 3
    1
      src/include/ipxe/tcpip.h
  4. 8
    0
      src/net/fragment.c
  5. 45
    10
      src/net/ipv4.c
  6. 43
    9
      src/net/ipv6.c
  7. 6
    2
      src/net/tcpip.c

+ 4
- 0
src/include/ipxe/fragment.h View File

27
 	size_t hdrlen;
27
 	size_t hdrlen;
28
 	/** Reassembly timer */
28
 	/** Reassembly timer */
29
 	struct retry_timer timer;
29
 	struct retry_timer timer;
30
+	/** Fragment reassembler */
31
+	struct fragment_reassembler *fragments;
30
 };
32
 };
31
 
33
 
32
 /** A fragment reassembler */
34
 /** A fragment reassembler */
59
 	 * @ret more_frags	More fragments exist
61
 	 * @ret more_frags	More fragments exist
60
 	 */
62
 	 */
61
 	int ( * more_fragments ) ( struct io_buffer *iobuf, size_t hdrlen );
63
 	int ( * more_fragments ) ( struct io_buffer *iobuf, size_t hdrlen );
64
+	/** Associated IP statistics */
65
+	struct ip_statistics *stats;
62
 };
66
 };
63
 
67
 
64
 extern struct io_buffer *
68
 extern struct io_buffer *

+ 187
- 0
src/include/ipxe/ipstat.h View File

1
+#ifndef _IPXE_IPSTATS_H
2
+#define _IPXE_IPSTATS_H
3
+
4
+/** @file
5
+ *
6
+ * IP statistics
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <ipxe/tables.h>
13
+
14
+struct io_buffer;
15
+
16
+/** IP system statistics
17
+ *
18
+ * Definitions are taken from the RFC4293 section 5
19
+ * "ipSystemStatsEntry" table.
20
+ *
21
+ * To minimise code size, we use "unsigned long" as the counter
22
+ * variable type regardless of whether this type is 32-bit or 64-bit.
23
+ * On a 32-bit build (e.g. the standard BIOS build), this means that
24
+ * we omit the "high capacity" 64-bit counters (prefixed with "HC").
25
+ * This reduces the code size required to maintain the counter values,
26
+ * and avoids the need to support the "%lld" format in vsprintf.c
27
+ * (which would require dragging in the 64-bit division library on a
28
+ * standard 32-bit build).  Since total available memory in a 32-bit
29
+ * environment is limited to 4GB, it is unlikely that we will overflow
30
+ * even the 32-bit octet counters under normal operation.
31
+ *
32
+ * Counters relating to packet forwarding are omitted, since iPXE
33
+ * includes no functionality for acting as a router.
34
+ *
35
+ * Counters related to output fragmentation are omitted, since iPXE
36
+ * has no support for fragmenting transmitted packets.
37
+ *
38
+ * The ipSystemStatsInDiscards and ipSystemStatsOutDiscards counters
39
+ * are omitted, since they will always be zero.
40
+ *
41
+ * Separate octet counters for multicast packets are omitted to save
42
+ * code size.
43
+ */
44
+struct ip_statistics {
45
+	/** ipSystemStatsInReceives
46
+	 *
47
+	 * The total number of input IP datagrams received, including
48
+	 * those received in error.
49
+	 */
50
+	unsigned long in_receives;
51
+	/** ipSystemStatsInOctets
52
+	 *
53
+	 * The total number of octets received in input IP datagrams,
54
+	 * including those received in error.  Octets from datagrams
55
+	 * counted in ipSystemStatsInReceives MUST be counted here.
56
+	 */
57
+	unsigned long in_octets;
58
+	/** ipSystemStatsInHdrErrors
59
+	 *
60
+	 * The number of input IP datagrams discarded due to errors in
61
+	 * their IP headers, including version number mismatch, other
62
+	 * format errors, hop count exceeded, errors discovered in
63
+	 * processing their IP options, etc.
64
+	 */
65
+	unsigned long in_hdr_errors;
66
+	/** ipSystemStatsInAddrErrors
67
+	 *
68
+	 * The number of input IP datagrams discarded because the IP
69
+	 * address in their IP header's destination field was not a
70
+	 * valid address to be received at this entity.  This count
71
+	 * includes invalid addresses (e.g., ::0).  For entities that
72
+	 * are not IP routers and therefore do not forward datagrams,
73
+	 * this counter includes datagrams discarded because the
74
+	 * destination address was not a local address.
75
+	 */
76
+	unsigned long in_addr_errors;
77
+	/** ipSystemStatsInUnknownProtos
78
+	 *
79
+	 * The number of locally-addressed IP datagrams received
80
+	 * successfully but discarded because of an unknown or
81
+	 * unsupported protocol.
82
+	 */
83
+	unsigned long in_unknown_protos;
84
+	/** ipSystemStatsInTruncatedPkts
85
+	 *
86
+	 * The number of input IP datagrams discarded because the
87
+	 * datagram frame didn't carry enough data.
88
+	 */
89
+	unsigned long in_truncated_pkts;
90
+	/** ipSystemStatsReasmReqds
91
+	 *
92
+	 * The number of IP fragments received that needed to be
93
+	 * reassembled at this interface.
94
+	 */
95
+	unsigned long reasm_reqds;
96
+	/** ipSystemStatsReasmOks
97
+	 *
98
+	 * The number of IP datagrams successfully reassembled.
99
+	 */
100
+	unsigned long reasm_oks;
101
+	/** ipSystemStatsReasmFails
102
+	 *
103
+	 * The number of failures detected by the IP re-assembly
104
+	 * algorithm (for whatever reason: timed out, errors, etc.).
105
+	 * Note that this is not necessarily a count of discarded IP
106
+	 * fragments since some algorithms (notably the algorithm in
107
+	 * RFC 815) can lose track of the number of fragments by
108
+	 * combining them as they are received.
109
+	 */
110
+	unsigned long reasm_fails;
111
+	/** ipSystemStatsInDelivers
112
+	 *
113
+	 * The total number of datagrams successfully delivered to IP
114
+	 * user-protocols (including ICMP).
115
+	 */
116
+	unsigned long in_delivers;
117
+	/** ipSystemStatsOutRequests
118
+	 *
119
+	 * The total number of IP datagrams that local IP user-
120
+	 * protocols (including ICMP) supplied to IP in requests for
121
+	 * transmission.
122
+	 */
123
+	unsigned long out_requests;
124
+	/** ipSystemStatsOutNoRoutes
125
+	 *
126
+	 * The number of locally generated IP datagrams discarded
127
+	 * because no route could be found to transmit them to their
128
+	 * destination.
129
+	 */
130
+	unsigned long out_no_routes;
131
+	/** ipSystemStatsOutTransmits
132
+	 *
133
+	 * The total number of IP datagrams that this entity supplied
134
+	 * to the lower layers for transmission.  This includes
135
+	 * datagrams generated locally and those forwarded by this
136
+	 * entity.
137
+	 */
138
+	unsigned long out_transmits;
139
+	/** ipSystemStatsOutOctets
140
+	 *
141
+	 * The total number of octets in IP datagrams delivered to the
142
+	 * lower layers for transmission.  Octets from datagrams
143
+	 * counted in ipSystemStatsOutTransmits MUST be counted here.
144
+	 */
145
+	unsigned long out_octets;
146
+	/** ipSystemStatsInMcastPkts
147
+	 *
148
+	 * The number of IP multicast datagrams received.
149
+	 */
150
+	unsigned long in_mcast_pkts;
151
+	/** ipSystemStatsOutMcastPkts
152
+	 *
153
+	 * The number of IP multicast datagrams transmitted.
154
+	 */
155
+	unsigned long out_mcast_pkts;
156
+	/** ipSystemStatsInBcastPkts
157
+	 *
158
+	 * The number of IP broadcast datagrams received.
159
+	 */
160
+	unsigned long in_bcast_pkts;
161
+	/** ipSystemStatsOutBcastPkts
162
+	 *
163
+	 * The number of IP broadcast datagrams transmitted.
164
+	 */
165
+	unsigned long out_bcast_pkts;
166
+};
167
+
168
+/** An IP system statistics family */
169
+struct ip_statistics_family {
170
+	/** IP version */
171
+	unsigned int version;
172
+	/** Statistics */
173
+	struct ip_statistics *stats;
174
+};
175
+
176
+/** IP system statistics family table */
177
+#define IP_STATISTICS_FAMILIES \
178
+	__table ( struct ip_statistics_family, "ip_statistics_families" )
179
+
180
+/** Declare an IP system statistics family */
181
+#define __ip_statistics_family( order ) \
182
+	__table_entry ( IP_STATISTICS_FAMILIES, order )
183
+
184
+#define IP_STATISTICS_IPV4 01
185
+#define IP_STATISTICS_IPV6 02
186
+
187
+#endif /* _IPXE_IPSTATS_H */

+ 3
- 1
src/include/ipxe/tcpip.h View File

17
 
17
 
18
 struct io_buffer;
18
 struct io_buffer;
19
 struct net_device;
19
 struct net_device;
20
+struct ip_statistics;
20
 
21
 
21
 /** Empty checksum value
22
 /** Empty checksum value
22
  *
23
  *
132
 
133
 
133
 extern int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
134
 extern int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
134
 		      uint8_t tcpip_proto, struct sockaddr_tcpip *st_src,
135
 		      uint8_t tcpip_proto, struct sockaddr_tcpip *st_src,
135
-		      struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum );
136
+		      struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum,
137
+		      struct ip_statistics *stats );
136
 extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
138
 extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
137
 		      struct sockaddr_tcpip *st_src,
139
 		      struct sockaddr_tcpip *st_src,
138
 		      struct sockaddr_tcpip *st_dest,
140
 		      struct sockaddr_tcpip *st_dest,

+ 8
- 0
src/net/fragment.c View File

24
 #include <string.h>
24
 #include <string.h>
25
 #include <ipxe/retry.h>
25
 #include <ipxe/retry.h>
26
 #include <ipxe/timer.h>
26
 #include <ipxe/timer.h>
27
+#include <ipxe/ipstat.h>
27
 #include <ipxe/fragment.h>
28
 #include <ipxe/fragment.h>
28
 
29
 
29
 /** @file
30
 /** @file
45
 	DBGC ( fragment, "FRAG %p expired\n", fragment );
46
 	DBGC ( fragment, "FRAG %p expired\n", fragment );
46
 	free_iob ( fragment->iobuf );
47
 	free_iob ( fragment->iobuf );
47
 	list_del ( &fragment->list );
48
 	list_del ( &fragment->list );
49
+	fragment->fragments->stats->reasm_fails++;
48
 	free ( fragment );
50
 	free ( fragment );
49
 }
51
 }
50
 
52
 
89
 	size_t expected_offset;
91
 	size_t expected_offset;
90
 	int more_frags;
92
 	int more_frags;
91
 
93
 
94
+	/* Update statistics */
95
+	fragments->stats->reasm_reqds++;
96
+
92
 	/* Find matching fragment reassembly buffer, if any */
97
 	/* Find matching fragment reassembly buffer, if any */
93
 	fragment = fragment_find ( fragments, iobuf, *hdrlen );
98
 	fragment = fragment_find ( fragments, iobuf, *hdrlen );
94
 
99
 
115
 		fragment->iobuf = iobuf;
120
 		fragment->iobuf = iobuf;
116
 		fragment->hdrlen = *hdrlen;
121
 		fragment->hdrlen = *hdrlen;
117
 		timer_init ( &fragment->timer, fragment_expired, NULL );
122
 		timer_init ( &fragment->timer, fragment_expired, NULL );
123
+		fragment->fragments = fragments;
118
 		DBGC ( fragment, "FRAG %p [0,%zd)\n", fragment,
124
 		DBGC ( fragment, "FRAG %p [0,%zd)\n", fragment,
119
 		       ( iob_len ( iobuf ) - *hdrlen ) );
125
 		       ( iob_len ( iobuf ) - *hdrlen ) );
120
 
126
 
157
 			*hdrlen = fragment->hdrlen;
163
 			*hdrlen = fragment->hdrlen;
158
 			list_del ( &fragment->list );
164
 			list_del ( &fragment->list );
159
 			free ( fragment );
165
 			free ( fragment );
166
+			fragments->stats->reasm_oks++;
160
 			return iobuf;
167
 			return iobuf;
161
 		}
168
 		}
162
 	}
169
 	}
167
 	return NULL;
174
 	return NULL;
168
 
175
 
169
  drop:
176
  drop:
177
+	fragments->stats->reasm_fails++;
170
 	free_iob ( iobuf );
178
 	free_iob ( iobuf );
171
 	return NULL;
179
 	return NULL;
172
 }
180
 }

+ 45
- 10
src/net/ipv4.c View File

15
 #include <ipxe/dhcp.h>
15
 #include <ipxe/dhcp.h>
16
 #include <ipxe/settings.h>
16
 #include <ipxe/settings.h>
17
 #include <ipxe/fragment.h>
17
 #include <ipxe/fragment.h>
18
+#include <ipxe/ipstat.h>
18
 
19
 
19
 /** @file
20
 /** @file
20
  *
21
  *
30
 /** List of IPv4 miniroutes */
31
 /** List of IPv4 miniroutes */
31
 struct list_head ipv4_miniroutes = LIST_HEAD_INIT ( ipv4_miniroutes );
32
 struct list_head ipv4_miniroutes = LIST_HEAD_INIT ( ipv4_miniroutes );
32
 
33
 
34
+/** IPv4 statistics */
35
+static struct ip_statistics ipv4_stats;
36
+
37
+/** IPv4 statistics family */
38
+struct ip_statistics_family
39
+ipv4_stats_family __ip_statistics_family ( IP_STATISTICS_IPV4 ) = {
40
+	.version = 4,
41
+	.stats = &ipv4_stats,
42
+};
43
+
33
 /**
44
 /**
34
  * Add IPv4 minirouting table entry
45
  * Add IPv4 minirouting table entry
35
  *
46
  *
178
 	.is_fragment = ipv4_is_fragment,
189
 	.is_fragment = ipv4_is_fragment,
179
 	.fragment_offset = ipv4_fragment_offset,
190
 	.fragment_offset = ipv4_fragment_offset,
180
 	.more_fragments = ipv4_more_fragments,
191
 	.more_fragments = ipv4_more_fragments,
192
+	.stats = &ipv4_stats,
181
 };
193
 };
182
 
194
 
183
 /**
195
 /**
232
 	const void *ll_dest;
244
 	const void *ll_dest;
233
 	int rc;
245
 	int rc;
234
 
246
 
247
+	/* Update statistics */
248
+	ipv4_stats.out_requests++;
249
+
235
 	/* Fill up the IP header, except source address */
250
 	/* Fill up the IP header, except source address */
236
 	memset ( iphdr, 0, sizeof ( *iphdr ) );
251
 	memset ( iphdr, 0, sizeof ( *iphdr ) );
237
 	iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
252
 	iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
255
 	if ( ! netdev ) {
270
 	if ( ! netdev ) {
256
 		DBGC ( sin_dest->sin_addr, "IPv4 has no route to %s\n",
271
 		DBGC ( sin_dest->sin_addr, "IPv4 has no route to %s\n",
257
 		       inet_ntoa ( iphdr->dest ) );
272
 		       inet_ntoa ( iphdr->dest ) );
273
+		ipv4_stats.out_no_routes++;
258
 		rc = -ENETUNREACH;
274
 		rc = -ENETUNREACH;
259
 		goto err;
275
 		goto err;
260
 	}
276
 	}
282
 	/* Calculate link-layer destination address, if possible */
298
 	/* Calculate link-layer destination address, if possible */
283
 	if ( ( ( next_hop.s_addr ^ INADDR_BROADCAST ) & ~netmask.s_addr ) == 0){
299
 	if ( ( ( next_hop.s_addr ^ INADDR_BROADCAST ) & ~netmask.s_addr ) == 0){
284
 		/* Broadcast address */
300
 		/* Broadcast address */
301
+		ipv4_stats.out_bcast_pkts++;
285
 		ll_dest = netdev->ll_broadcast;
302
 		ll_dest = netdev->ll_broadcast;
286
 	} else if ( IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) {
303
 	} else if ( IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) {
287
 		/* Multicast address */
304
 		/* Multicast address */
305
+		ipv4_stats.out_mcast_pkts++;
288
 		if ( ( rc = netdev->ll_protocol->mc_hash ( AF_INET, &next_hop,
306
 		if ( ( rc = netdev->ll_protocol->mc_hash ( AF_INET, &next_hop,
289
 							   ll_dest_buf ) ) !=0){
307
 							   ll_dest_buf ) ) !=0){
290
 			DBGC ( sin_dest->sin_addr, "IPv4 could not hash "
308
 			DBGC ( sin_dest->sin_addr, "IPv4 could not hash "
298
 		ll_dest = NULL;
316
 		ll_dest = NULL;
299
 	}
317
 	}
300
 
318
 
319
+	/* Update statistics */
320
+	ipv4_stats.out_transmits++;
321
+	ipv4_stats.out_octets += iob_len ( iobuf );
322
+
301
 	/* Hand off to link layer (via ARP if applicable) */
323
 	/* Hand off to link layer (via ARP if applicable) */
302
 	if ( ll_dest ) {
324
 	if ( ll_dest ) {
303
 		if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest,
325
 		if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest,
389
 	uint16_t pshdr_csum;
411
 	uint16_t pshdr_csum;
390
 	int rc;
412
 	int rc;
391
 
413
 
414
+	/* Update statistics */
415
+	ipv4_stats.in_receives++;
416
+	ipv4_stats.in_octets += iob_len ( iobuf );
417
+	if ( flags & LL_BROADCAST ) {
418
+		ipv4_stats.in_bcast_pkts++;
419
+	} else if ( flags & LL_MULTICAST ) {
420
+		ipv4_stats.in_mcast_pkts++;
421
+	}
422
+
392
 	/* Sanity check the IPv4 header */
423
 	/* Sanity check the IPv4 header */
393
 	if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
424
 	if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
394
 		DBGC ( iphdr->src, "IPv4 packet too short at %zd bytes (min "
425
 		DBGC ( iphdr->src, "IPv4 packet too short at %zd bytes (min "
395
 		       "%zd bytes)\n", iob_len ( iobuf ), sizeof ( *iphdr ) );
426
 		       "%zd bytes)\n", iob_len ( iobuf ), sizeof ( *iphdr ) );
396
-		goto err;
427
+		goto err_header;
397
 	}
428
 	}
398
 	if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
429
 	if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
399
 		DBGC ( iphdr->src, "IPv4 version %#02x not supported\n",
430
 		DBGC ( iphdr->src, "IPv4 version %#02x not supported\n",
400
 		       iphdr->verhdrlen );
431
 		       iphdr->verhdrlen );
401
-		goto err;
432
+		goto err_header;
402
 	}
433
 	}
403
 	hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
434
 	hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
404
 	if ( hdrlen < sizeof ( *iphdr ) ) {
435
 	if ( hdrlen < sizeof ( *iphdr ) ) {
405
 		DBGC ( iphdr->src, "IPv4 header too short at %zd bytes (min "
436
 		DBGC ( iphdr->src, "IPv4 header too short at %zd bytes (min "
406
 		       "%zd bytes)\n", hdrlen, sizeof ( *iphdr ) );
437
 		       "%zd bytes)\n", hdrlen, sizeof ( *iphdr ) );
407
-		goto err;
438
+		goto err_header;
408
 	}
439
 	}
409
 	if ( hdrlen > iob_len ( iobuf ) ) {
440
 	if ( hdrlen > iob_len ( iobuf ) ) {
410
 		DBGC ( iphdr->src, "IPv4 header too long at %zd bytes "
441
 		DBGC ( iphdr->src, "IPv4 header too long at %zd bytes "
411
 		       "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
442
 		       "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
412
-		goto err;
443
+		goto err_header;
413
 	}
444
 	}
414
 	if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
445
 	if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
415
 		DBGC ( iphdr->src, "IPv4 checksum incorrect (is %04x "
446
 		DBGC ( iphdr->src, "IPv4 checksum incorrect (is %04x "
416
 		       "including checksum field, should be 0000)\n", csum );
447
 		       "including checksum field, should be 0000)\n", csum );
417
-		goto err;
448
+		goto err_header;
418
 	}
449
 	}
419
 	len = ntohs ( iphdr->len );
450
 	len = ntohs ( iphdr->len );
420
 	if ( len < hdrlen ) {
451
 	if ( len < hdrlen ) {
421
 		DBGC ( iphdr->src, "IPv4 length too short at %zd bytes "
452
 		DBGC ( iphdr->src, "IPv4 length too short at %zd bytes "
422
 		       "(header is %zd bytes)\n", len, hdrlen );
453
 		       "(header is %zd bytes)\n", len, hdrlen );
423
-		goto err;
454
+		goto err_header;
424
 	}
455
 	}
425
 	if ( len > iob_len ( iobuf ) ) {
456
 	if ( len > iob_len ( iobuf ) ) {
426
 		DBGC ( iphdr->src, "IPv4 length too long at %zd bytes "
457
 		DBGC ( iphdr->src, "IPv4 length too long at %zd bytes "
427
 		       "(packet is %zd bytes)\n", len, iob_len ( iobuf ) );
458
 		       "(packet is %zd bytes)\n", len, iob_len ( iobuf ) );
428
-		goto err;
459
+		ipv4_stats.in_truncated_pkts++;
460
+		goto err_other;
429
 	}
461
 	}
430
 
462
 
431
 	/* Truncate packet to correct length */
463
 	/* Truncate packet to correct length */
443
 	     ( ! ipv4_has_addr ( netdev, iphdr->dest ) ) ) {
475
 	     ( ! ipv4_has_addr ( netdev, iphdr->dest ) ) ) {
444
 		DBGC ( iphdr->src, "IPv4 discarding non-local unicast packet "
476
 		DBGC ( iphdr->src, "IPv4 discarding non-local unicast packet "
445
 		       "for %s\n", inet_ntoa ( iphdr->dest ) );
477
 		       "for %s\n", inet_ntoa ( iphdr->dest ) );
446
-		goto err;
478
+		ipv4_stats.in_addr_errors++;
479
+		goto err_other;
447
 	}
480
 	}
448
 
481
 
449
 	/* Perform fragment reassembly if applicable */
482
 	/* Perform fragment reassembly if applicable */
470
 	pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
503
 	pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
471
 	iob_pull ( iobuf, hdrlen );
504
 	iob_pull ( iobuf, hdrlen );
472
 	if ( ( rc = tcpip_rx ( iobuf, netdev, iphdr->protocol, &src.st,
505
 	if ( ( rc = tcpip_rx ( iobuf, netdev, iphdr->protocol, &src.st,
473
-			       &dest.st, pshdr_csum ) ) != 0 ) {
506
+			       &dest.st, pshdr_csum, &ipv4_stats ) ) != 0 ) {
474
 		DBGC ( src.sin.sin_addr, "IPv4 received packet rejected by "
507
 		DBGC ( src.sin.sin_addr, "IPv4 received packet rejected by "
475
 		       "stack: %s\n", strerror ( rc ) );
508
 		       "stack: %s\n", strerror ( rc ) );
476
 		return rc;
509
 		return rc;
478
 
511
 
479
 	return 0;
512
 	return 0;
480
 
513
 
481
- err:
514
+ err_header:
515
+	ipv4_stats.in_hdr_errors++;
516
+ err_other:
482
 	free_iob ( iobuf );
517
 	free_iob ( iobuf );
483
 	return -EINVAL;
518
 	return -EINVAL;
484
 }
519
 }

+ 43
- 9
src/net/ipv6.c View File

31
 #include <ipxe/if_ether.h>
31
 #include <ipxe/if_ether.h>
32
 #include <ipxe/crc32.h>
32
 #include <ipxe/crc32.h>
33
 #include <ipxe/fragment.h>
33
 #include <ipxe/fragment.h>
34
+#include <ipxe/ipstat.h>
34
 #include <ipxe/ndp.h>
35
 #include <ipxe/ndp.h>
35
 #include <ipxe/ipv6.h>
36
 #include <ipxe/ipv6.h>
36
 
37
 
57
 /** List of IPv6 miniroutes */
58
 /** List of IPv6 miniroutes */
58
 struct list_head ipv6_miniroutes = LIST_HEAD_INIT ( ipv6_miniroutes );
59
 struct list_head ipv6_miniroutes = LIST_HEAD_INIT ( ipv6_miniroutes );
59
 
60
 
61
+/** IPv6 statistics */
62
+static struct ip_statistics ipv6_stats;
63
+
64
+/** IPv6 statistics family */
65
+struct ip_statistics_family
66
+ipv6_statistics_family __ip_statistics_family ( IP_STATISTICS_IPV6 ) = {
67
+	.version = 6,
68
+	.stats = &ipv6_stats,
69
+};
70
+
60
 /**
71
 /**
61
  * Determine debugging colour for IPv6 debug messages
72
  * Determine debugging colour for IPv6 debug messages
62
  *
73
  *
398
 	.is_fragment = ipv6_is_fragment,
409
 	.is_fragment = ipv6_is_fragment,
399
 	.fragment_offset = ipv6_fragment_offset,
410
 	.fragment_offset = ipv6_fragment_offset,
400
 	.more_fragments = ipv6_more_fragments,
411
 	.more_fragments = ipv6_more_fragments,
412
+	.stats = &ipv6_stats,
401
 };
413
 };
402
 
414
 
403
 /**
415
 /**
455
 	size_t len;
467
 	size_t len;
456
 	int rc;
468
 	int rc;
457
 
469
 
470
+	/* Update statistics */
471
+	ipv6_stats.out_requests++;
472
+
458
 	/* Fill up the IPv6 header, except source address */
473
 	/* Fill up the IPv6 header, except source address */
459
 	len = iob_len ( iobuf );
474
 	len = iob_len ( iobuf );
460
 	iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
475
 	iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
475
 	if ( ! netdev ) {
490
 	if ( ! netdev ) {
476
 		DBGC ( ipv6col ( &iphdr->dest ), "IPv6 has no route to %s\n",
491
 		DBGC ( ipv6col ( &iphdr->dest ), "IPv6 has no route to %s\n",
477
 		       inet6_ntoa ( &iphdr->dest ) );
492
 		       inet6_ntoa ( &iphdr->dest ) );
493
+		ipv6_stats.out_no_routes++;
478
 		rc = -ENETUNREACH;
494
 		rc = -ENETUNREACH;
479
 		goto err;
495
 		goto err;
480
 	}
496
 	}
498
 	/* Calculate link-layer destination address, if possible */
514
 	/* Calculate link-layer destination address, if possible */
499
 	if ( IN6_IS_ADDR_MULTICAST ( next_hop ) ) {
515
 	if ( IN6_IS_ADDR_MULTICAST ( next_hop ) ) {
500
 		/* Multicast address */
516
 		/* Multicast address */
517
+		ipv6_stats.out_mcast_pkts++;
501
 		if ( ( rc = netdev->ll_protocol->mc_hash ( AF_INET6, next_hop,
518
 		if ( ( rc = netdev->ll_protocol->mc_hash ( AF_INET6, next_hop,
502
 							   ll_dest_buf ) ) !=0){
519
 							   ll_dest_buf ) ) !=0){
503
 			DBGC ( ipv6col ( &iphdr->dest ), "IPv6 could not hash "
520
 			DBGC ( ipv6col ( &iphdr->dest ), "IPv6 could not hash "
511
 		ll_dest = NULL;
528
 		ll_dest = NULL;
512
 	}
529
 	}
513
 
530
 
531
+	/* Update statistics */
532
+	ipv6_stats.out_transmits++;
533
+	ipv6_stats.out_octets += iob_len ( iobuf );
534
+
514
 	/* Hand off to link layer (via NDP if applicable) */
535
 	/* Hand off to link layer (via NDP if applicable) */
515
 	if ( ll_dest ) {
536
 	if ( ll_dest ) {
516
 		if ( ( rc = net_tx ( iobuf, netdev, &ipv6_protocol, ll_dest,
537
 		if ( ( rc = net_tx ( iobuf, netdev, &ipv6_protocol, ll_dest,
568
 	int next_header;
589
 	int next_header;
569
 	int rc;
590
 	int rc;
570
 
591
 
592
+	/* Update statistics */
593
+	ipv6_stats.in_receives++;
594
+	ipv6_stats.in_octets += iob_len ( iobuf );
595
+	if ( flags & LL_BROADCAST ) {
596
+		ipv6_stats.in_bcast_pkts++;
597
+	} else if ( flags & LL_MULTICAST ) {
598
+		ipv6_stats.in_mcast_pkts++;
599
+	}
600
+
571
 	/* Sanity check the IPv6 header */
601
 	/* Sanity check the IPv6 header */
572
 	if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
602
 	if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
573
 		DBGC ( ipv6col ( &iphdr->src ), "IPv6 packet too short at %zd "
603
 		DBGC ( ipv6col ( &iphdr->src ), "IPv6 packet too short at %zd "
574
 		       "bytes (min %zd bytes)\n", iob_len ( iobuf ),
604
 		       "bytes (min %zd bytes)\n", iob_len ( iobuf ),
575
 		       sizeof ( *iphdr ) );
605
 		       sizeof ( *iphdr ) );
576
 		rc = -EINVAL_LEN;
606
 		rc = -EINVAL_LEN;
577
-		goto err;
607
+		goto err_header;
578
 	}
608
 	}
579
 	if ( ( iphdr->ver_tc_label & htonl ( IPV6_MASK_VER ) ) !=
609
 	if ( ( iphdr->ver_tc_label & htonl ( IPV6_MASK_VER ) ) !=
580
 	     htonl ( IPV6_VER ) ) {
610
 	     htonl ( IPV6_VER ) ) {
581
 		DBGC ( ipv6col ( &iphdr->src ), "IPv6 version %#08x not "
611
 		DBGC ( ipv6col ( &iphdr->src ), "IPv6 version %#08x not "
582
 		       "supported\n", ntohl ( iphdr->ver_tc_label ) );
612
 		       "supported\n", ntohl ( iphdr->ver_tc_label ) );
583
 		rc = -ENOTSUP_VER;
613
 		rc = -ENOTSUP_VER;
584
-		goto err;
614
+		goto err_header;
585
 	}
615
 	}
586
 
616
 
587
 	/* Truncate packet to specified length */
617
 	/* Truncate packet to specified length */
589
 	if ( len > iob_len ( iobuf ) ) {
619
 	if ( len > iob_len ( iobuf ) ) {
590
 		DBGC ( ipv6col ( &iphdr->src ), "IPv6 length too long at %zd "
620
 		DBGC ( ipv6col ( &iphdr->src ), "IPv6 length too long at %zd "
591
 		       "bytes (packet is %zd bytes)\n", len, iob_len ( iobuf ));
621
 		       "bytes (packet is %zd bytes)\n", len, iob_len ( iobuf ));
622
+		ipv6_stats.in_truncated_pkts++;
592
 		rc = -EINVAL_LEN;
623
 		rc = -EINVAL_LEN;
593
-		goto err;
624
+		goto err_other;
594
 	}
625
 	}
595
 	iob_unput ( iobuf, ( iob_len ( iobuf ) - len - sizeof ( *iphdr ) ) );
626
 	iob_unput ( iobuf, ( iob_len ( iobuf ) - len - sizeof ( *iphdr ) ) );
596
 	hdrlen = sizeof ( *iphdr );
627
 	hdrlen = sizeof ( *iphdr );
606
 	     ( ! ipv6_has_addr ( netdev, &iphdr->dest ) ) ) {
637
 	     ( ! ipv6_has_addr ( netdev, &iphdr->dest ) ) ) {
607
 		DBGC ( ipv6col ( &iphdr->src ), "IPv6 discarding non-local "
638
 		DBGC ( ipv6col ( &iphdr->src ), "IPv6 discarding non-local "
608
 		       "unicast packet for %s\n", inet6_ntoa ( &iphdr->dest ) );
639
 		       "unicast packet for %s\n", inet6_ntoa ( &iphdr->dest ) );
640
+		ipv6_stats.in_addr_errors++;
609
 		rc = -EPIPE;
641
 		rc = -EPIPE;
610
-		goto err;
642
+		goto err_other;
611
 	}
643
 	}
612
 
644
 
613
 	/* Process any extension headers */
645
 	/* Process any extension headers */
624
 			       "%zd bytes)\n", this_header,
656
 			       "%zd bytes)\n", this_header,
625
 			       ( iob_len ( iobuf ) - hdrlen ), extlen );
657
 			       ( iob_len ( iobuf ) - hdrlen ), extlen );
626
 			rc = -EINVAL_LEN;
658
 			rc = -EINVAL_LEN;
627
-			goto err;
659
+			goto err_header;
628
 		}
660
 		}
629
 
661
 
630
 		/* Determine size of extension header (if applicable) */
662
 		/* Determine size of extension header (if applicable) */
645
 			       "%zd bytes)\n", this_header,
677
 			       "%zd bytes)\n", this_header,
646
 			       ( iob_len ( iobuf ) - hdrlen ), extlen );
678
 			       ( iob_len ( iobuf ) - hdrlen ), extlen );
647
 			rc = -EINVAL_LEN;
679
 			rc = -EINVAL_LEN;
648
-			goto err;
680
+			goto err_header;
649
 		}
681
 		}
650
 		hdrlen += extlen;
682
 		hdrlen += extlen;
651
 		next_header = ext->common.next_header;
683
 		next_header = ext->common.next_header;
662
 			/* Check that all options can be ignored */
694
 			/* Check that all options can be ignored */
663
 			if ( ( rc = ipv6_check_options ( iphdr, &ext->options,
695
 			if ( ( rc = ipv6_check_options ( iphdr, &ext->options,
664
 							 extlen ) ) != 0 )
696
 							 extlen ) ) != 0 )
665
-				goto err;
697
+				goto err_header;
666
 
698
 
667
 		} else if ( this_header == IPV6_FRAGMENT ) {
699
 		} else if ( this_header == IPV6_FRAGMENT ) {
668
 
700
 
692
 	pshdr_csum = ipv6_pshdr_chksum ( iphdr, iob_len ( iobuf ),
724
 	pshdr_csum = ipv6_pshdr_chksum ( iphdr, iob_len ( iobuf ),
693
 					 next_header, TCPIP_EMPTY_CSUM );
725
 					 next_header, TCPIP_EMPTY_CSUM );
694
 	if ( ( rc = tcpip_rx ( iobuf, netdev, next_header, &src.st, &dest.st,
726
 	if ( ( rc = tcpip_rx ( iobuf, netdev, next_header, &src.st, &dest.st,
695
-			       pshdr_csum ) ) != 0 ) {
727
+			       pshdr_csum, &ipv6_stats ) ) != 0 ) {
696
 		DBGC ( ipv6col ( &src.sin6.sin6_addr ), "IPv6 received packet "
728
 		DBGC ( ipv6col ( &src.sin6.sin6_addr ), "IPv6 received packet "
697
 				"rejected by stack: %s\n", strerror ( rc ) );
729
 				"rejected by stack: %s\n", strerror ( rc ) );
698
 		return rc;
730
 		return rc;
700
 
732
 
701
 	return 0;
733
 	return 0;
702
 
734
 
703
- err:
735
+ err_header:
736
+	ipv6_stats.in_hdr_errors++;
737
+ err_other:
704
 	free_iob ( iobuf );
738
 	free_iob ( iobuf );
705
 	return rc;
739
 	return rc;
706
 }
740
 }

+ 6
- 2
src/net/tcpip.c View File

5
 #include <byteswap.h>
5
 #include <byteswap.h>
6
 #include <ipxe/iobuf.h>
6
 #include <ipxe/iobuf.h>
7
 #include <ipxe/tables.h>
7
 #include <ipxe/tables.h>
8
+#include <ipxe/ipstat.h>
8
 #include <ipxe/tcpip.h>
9
 #include <ipxe/tcpip.h>
9
 
10
 
10
 /** @file
11
 /** @file
25
  * @v st_src		Partially-filled source address
26
  * @v st_src		Partially-filled source address
26
  * @v st_dest		Partially-filled destination address
27
  * @v st_dest		Partially-filled destination address
27
  * @v pshdr_csum	Pseudo-header checksum
28
  * @v pshdr_csum	Pseudo-header checksum
29
+ * @v stats		IP statistics
28
  * @ret rc		Return status code
30
  * @ret rc		Return status code
29
  *
31
  *
30
  * This function expects a transport-layer segment from the network
32
  * This function expects a transport-layer segment from the network
35
  */
37
  */
36
 int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
38
 int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
37
 	       uint8_t tcpip_proto, struct sockaddr_tcpip *st_src,
39
 	       uint8_t tcpip_proto, struct sockaddr_tcpip *st_src,
38
-	       struct sockaddr_tcpip *st_dest,
39
-	       uint16_t pshdr_csum ) {
40
+	       struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum,
41
+	       struct ip_statistics *stats ) {
40
 	struct tcpip_protocol *tcpip;
42
 	struct tcpip_protocol *tcpip;
41
 
43
 
42
 	/* Hand off packet to the appropriate transport-layer protocol */
44
 	/* Hand off packet to the appropriate transport-layer protocol */
43
 	for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
45
 	for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
44
 		if ( tcpip->tcpip_proto == tcpip_proto ) {
46
 		if ( tcpip->tcpip_proto == tcpip_proto ) {
45
 			DBG ( "TCP/IP received %s packet\n", tcpip->name );
47
 			DBG ( "TCP/IP received %s packet\n", tcpip->name );
48
+			stats->in_delivers++;
46
 			return tcpip->rx ( iobuf, netdev, st_src, st_dest,
49
 			return tcpip->rx ( iobuf, netdev, st_src, st_dest,
47
 					   pshdr_csum );
50
 					   pshdr_csum );
48
 		}
51
 		}
49
 	}
52
 	}
50
 
53
 
51
 	DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
54
 	DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
55
+	stats->in_unknown_protos++;
52
 	free_iob ( iobuf );
56
 	free_iob ( iobuf );
53
 	return -EPROTONOSUPPORT;
57
 	return -EPROTONOSUPPORT;
54
 }
58
 }

Loading…
Cancel
Save