瀏覽代碼

[tcpip] Add IP statistics collection as per RFC 4293

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 年之前
父節點
當前提交
11963c4f5f
共有 7 個檔案被更改,包括 296 行新增22 行删除
  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 查看文件

@@ -27,6 +27,8 @@ struct fragment {
27 27
 	size_t hdrlen;
28 28
 	/** Reassembly timer */
29 29
 	struct retry_timer timer;
30
+	/** Fragment reassembler */
31
+	struct fragment_reassembler *fragments;
30 32
 };
31 33
 
32 34
 /** A fragment reassembler */
@@ -59,6 +61,8 @@ struct fragment_reassembler {
59 61
 	 * @ret more_frags	More fragments exist
60 62
 	 */
61 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 68
 extern struct io_buffer *

+ 187
- 0
src/include/ipxe/ipstat.h 查看文件

@@ -0,0 +1,187 @@
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 查看文件

@@ -17,6 +17,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
17 17
 
18 18
 struct io_buffer;
19 19
 struct net_device;
20
+struct ip_statistics;
20 21
 
21 22
 /** Empty checksum value
22 23
  *
@@ -132,7 +133,8 @@ struct tcpip_net_protocol {
132 133
 
133 134
 extern int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
134 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 138
 extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip,
137 139
 		      struct sockaddr_tcpip *st_src,
138 140
 		      struct sockaddr_tcpip *st_dest,

+ 8
- 0
src/net/fragment.c 查看文件

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

+ 45
- 10
src/net/ipv4.c 查看文件

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

+ 43
- 9
src/net/ipv6.c 查看文件

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

+ 6
- 2
src/net/tcpip.c 查看文件

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

Loading…
取消
儲存