Browse Source

Allow recording of TX and RX errors to aid in end-user debugging.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
539ff45fd0
4 changed files with 92 additions and 28 deletions
  1. 37
    6
      src/include/gpxe/netdevice.h
  2. 4
    4
      src/interface/pxe/pxe_undi.c
  3. 48
    16
      src/net/netdevice.c
  4. 3
    2
      src/usr/ifmgmt.c

+ 37
- 6
src/include/gpxe/netdevice.h View File

134
  */
134
  */
135
 struct net_device_stats {
135
 struct net_device_stats {
136
 	/** Count of successfully completed transmissions */
136
 	/** Count of successfully completed transmissions */
137
-	unsigned int tx_count;
137
+	unsigned int tx_ok;
138
+	/** Count of transmission errors */
139
+	unsigned int tx_err;
138
 	/** Count of successfully received packets */
140
 	/** Count of successfully received packets */
139
-	unsigned int rx_count;
141
+	unsigned int rx_ok;
142
+	/** Count of reception errors */
143
+	unsigned int rx_err;
140
 };
144
 };
141
 
145
 
142
 /**
146
 /**
189
 	 * owned by the net device's TX queue, and the net device must
193
 	 * owned by the net device's TX queue, and the net device must
190
 	 * eventually call netdev_tx_complete() to free the buffer.
194
 	 * eventually call netdev_tx_complete() to free the buffer.
191
 	 * If this method returns failure, the I/O buffer is
195
 	 * If this method returns failure, the I/O buffer is
192
-	 * immediately released.
196
+	 * immediately released; the failure is interpreted as
197
+	 * "failure to enqueue buffer".
193
 	 *
198
 	 *
194
 	 * This method is guaranteed to be called only when the device
199
 	 * This method is guaranteed to be called only when the device
195
 	 * is open.
200
 	 * is open.
289
 }
294
 }
290
 
295
 
291
 extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
296
 extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
292
-extern void netdev_tx_complete ( struct net_device *netdev,
293
-				 struct io_buffer *iobuf );
294
-extern void netdev_tx_complete_next ( struct net_device *netdev );
297
+extern void netdev_tx_complete_err ( struct net_device *netdev,
298
+				 struct io_buffer *iobuf, int rc );
299
+extern void netdev_tx_complete_next_err ( struct net_device *netdev, int rc );
295
 extern void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf );
300
 extern void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf );
301
+extern void netdev_rx_err ( struct net_device *netdev,
302
+			    struct io_buffer *iobuf, int rc );
296
 extern int netdev_poll ( struct net_device *netdev, unsigned int rx_quota );
303
 extern int netdev_poll ( struct net_device *netdev, unsigned int rx_quota );
297
 extern struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev );
304
 extern struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev );
298
 extern struct net_device * alloc_netdev ( size_t priv_size );
305
 extern struct net_device * alloc_netdev ( size_t priv_size );
308
 extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
315
 extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
309
 		    uint16_t net_proto, const void *ll_source );
316
 		    uint16_t net_proto, const void *ll_source );
310
 
317
 
318
+/**
319
+ * Complete network transmission
320
+ *
321
+ * @v netdev		Network device
322
+ * @v iobuf		I/O buffer
323
+ *
324
+ * The packet must currently be in the network device's TX queue.
325
+ */
326
+static inline void netdev_tx_complete ( struct net_device *netdev,
327
+					struct io_buffer *iobuf ) {
328
+	netdev_tx_complete_err ( netdev, iobuf, 0 );
329
+}
330
+
331
+/**
332
+ * Complete network transmission
333
+ *
334
+ * @v netdev		Network device
335
+ *
336
+ * Completes the oldest outstanding packet in the TX queue.
337
+ */
338
+static inline void netdev_tx_complete_next ( struct net_device *netdev ) {
339
+	netdev_tx_complete_next_err ( netdev, 0 );
340
+}
341
+
311
 #endif /* _GPXE_NETDEVICE_H */
342
 #endif /* _GPXE_NETDEVICE_H */

+ 4
- 4
src/interface/pxe/pxe_undi.c View File

371
 					 *undi_get_statistics ) {
371
 					 *undi_get_statistics ) {
372
 	DBG ( "PXENV_UNDI_GET_STATISTICS" );
372
 	DBG ( "PXENV_UNDI_GET_STATISTICS" );
373
 
373
 
374
-	undi_get_statistics->XmtGoodFrames = pxe_netdev->stats.tx_count;
375
-	undi_get_statistics->RcvGoodFrames = pxe_netdev->stats.rx_count;
376
-	undi_get_statistics->RcvCRCErrors = 0;
377
-	undi_get_statistics->RcvResourceErrors = 0;
374
+	undi_get_statistics->XmtGoodFrames = pxe_netdev->stats.tx_ok;
375
+	undi_get_statistics->RcvGoodFrames = pxe_netdev->stats.rx_ok;
376
+	undi_get_statistics->RcvCRCErrors = pxe_netdev->stats.rx_err;
377
+	undi_get_statistics->RcvResourceErrors = pxe_netdev->stats.rx_err;
378
 
378
 
379
 	undi_get_statistics->Status = PXENV_STATUS_SUCCESS;
379
 	undi_get_statistics->Status = PXENV_STATUS_SUCCESS;
380
 	return PXENV_EXIT_SUCCESS;
380
 	return PXENV_EXIT_SUCCESS;

+ 48
- 16
src/net/netdevice.c View File

74
 	return 0;
74
 	return 0;
75
 
75
 
76
  err:
76
  err:
77
-	DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
78
-	       netdev, iobuf, strerror ( rc ) );
79
-	netdev_tx_complete ( netdev, iobuf );
77
+	netdev_tx_complete_err ( netdev, iobuf, rc );
80
 	return rc;
78
 	return rc;
81
 }
79
 }
82
 
80
 
85
  *
83
  *
86
  * @v netdev		Network device
84
  * @v netdev		Network device
87
  * @v iobuf		I/O buffer
85
  * @v iobuf		I/O buffer
86
+ * @v rc		Packet status code
88
  *
87
  *
89
  * The packet must currently be in the network device's TX queue.
88
  * The packet must currently be in the network device's TX queue.
90
  */
89
  */
91
-void netdev_tx_complete ( struct net_device *netdev, struct io_buffer *iobuf ) {
92
-	DBGC ( netdev, "NETDEV %p transmission %p complete\n", netdev, iobuf );
90
+void netdev_tx_complete_err ( struct net_device *netdev,
91
+			      struct io_buffer *iobuf, int rc ) {
92
+
93
+	/* Update statistics counter */
94
+	if ( rc == 0 ) {
95
+		netdev->stats.tx_ok++;
96
+		DBGC ( netdev, "NETDEV %p transmission %p complete\n",
97
+		       netdev, iobuf );
98
+	} else {
99
+		netdev->stats.tx_err++;
100
+		DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
101
+		       netdev, iobuf, strerror ( rc ) );
102
+	}
93
 
103
 
94
 	/* Catch data corruption as early as possible */
104
 	/* Catch data corruption as early as possible */
95
 	assert ( iobuf->list.next != NULL );
105
 	assert ( iobuf->list.next != NULL );
98
 	/* Dequeue and free I/O buffer */
108
 	/* Dequeue and free I/O buffer */
99
 	list_del ( &iobuf->list );
109
 	list_del ( &iobuf->list );
100
 	free_iob ( iobuf );
110
 	free_iob ( iobuf );
101
-
102
-	/* Update statistics counter */
103
-	netdev->stats.tx_count++;
104
 }
111
 }
105
 
112
 
106
 /**
113
 /**
107
  * Complete network transmission
114
  * Complete network transmission
108
  *
115
  *
109
  * @v netdev		Network device
116
  * @v netdev		Network device
117
+ * @v rc		Packet status code
110
  *
118
  *
111
  * Completes the oldest outstanding packet in the TX queue.
119
  * Completes the oldest outstanding packet in the TX queue.
112
  */
120
  */
113
-void netdev_tx_complete_next ( struct net_device *netdev ) {
121
+void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
114
 	struct io_buffer *iobuf;
122
 	struct io_buffer *iobuf;
115
 
123
 
116
 	list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
124
 	list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
117
-		netdev_tx_complete ( netdev, iobuf );
125
+		netdev_tx_complete_err ( netdev, iobuf, rc );
118
 		return;
126
 		return;
119
 	}
127
 	}
120
 }
128
 }
128
 
136
 
129
 	/* Discard any packets in the TX queue */
137
 	/* Discard any packets in the TX queue */
130
 	while ( ! list_empty ( &netdev->tx_queue ) ) {
138
 	while ( ! list_empty ( &netdev->tx_queue ) ) {
131
-		netdev_tx_complete_next ( netdev );
139
+		netdev_tx_complete_next_err ( netdev, -ECANCELED );
132
 	}
140
 	}
133
 }
141
 }
134
 
142
 
136
  * Add packet to receive queue
144
  * Add packet to receive queue
137
  *
145
  *
138
  * @v netdev		Network device
146
  * @v netdev		Network device
139
- * @v iobuf		I/O buffer
147
+ * @v iobuf		I/O buffer, or NULL
140
  *
148
  *
141
  * The packet is added to the network device's RX queue.  This
149
  * The packet is added to the network device's RX queue.  This
142
  * function takes ownership of the I/O buffer.
150
  * function takes ownership of the I/O buffer.
143
  */
151
  */
144
 void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
152
 void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
153
+
145
 	DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
154
 	DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
146
 	       netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
155
 	       netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
147
 
156
 
149
 	list_add_tail ( &iobuf->list, &netdev->rx_queue );
158
 	list_add_tail ( &iobuf->list, &netdev->rx_queue );
150
 
159
 
151
 	/* Update statistics counter */
160
 	/* Update statistics counter */
152
-	netdev->stats.rx_count++;
161
+	netdev->stats.rx_ok++;
162
+}
163
+
164
+/**
165
+ * Discard received packet
166
+ *
167
+ * @v netdev		Network device
168
+ * @v iobuf		I/O buffer, or NULL
169
+ * @v rc		Packet status code
170
+ *
171
+ * The packet is discarded and an RX error is recorded.  This function
172
+ * takes ownership of the I/O buffer.  @c iobuf may be NULL if, for
173
+ * example, the net device wishes to report an error due to being
174
+ * unable to allocate an I/O buffer.
175
+ */
176
+void netdev_rx_err ( struct net_device *netdev,
177
+		     struct io_buffer *iobuf, int rc ) {
178
+
179
+	DBGC ( netdev, "NETDEV %p failed to receive %p: %s\n",
180
+	       netdev, iobuf, strerror ( rc ) );
181
+
182
+	/* Discard packet */
183
+	free_iob ( iobuf );
184
+
185
+	/* Update statistics counter */
186
+	netdev->stats.rx_err++;
153
 }
187
 }
154
 
188
 
155
 /**
189
 /**
200
 
234
 
201
 	/* Discard any packets in the RX queue */
235
 	/* Discard any packets in the RX queue */
202
 	while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
236
 	while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
203
-		DBGC ( netdev, "NETDEV %p discarding received %p\n",
204
-		       netdev, iobuf );
205
-		free_iob ( iobuf );
237
+		netdev_rx_err ( netdev, iobuf, -ECANCELED );
206
 	}
238
 	}
207
 }
239
 }
208
 
240
 

+ 3
- 2
src/usr/ifmgmt.c View File

61
  * @v netdev		Network device
61
  * @v netdev		Network device
62
  */
62
  */
63
 void ifstat ( struct net_device *netdev ) {
63
 void ifstat ( struct net_device *netdev ) {
64
-	printf ( "%s: %s on %s (%s) TX:%d RX:%d\n",
64
+	printf ( "%s: %s on %s (%s) TX:%d TXE:%d RX:%d RXE:%d\n",
65
 		 netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name,
65
 		 netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name,
66
 		 ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ),
66
 		 ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ),
67
-		 netdev->stats.tx_count, netdev->stats.rx_count );
67
+		 netdev->stats.tx_ok, netdev->stats.tx_err,
68
+		 netdev->stats.rx_ok, netdev->stats.rx_err );
68
 }
69
 }

Loading…
Cancel
Save