Browse Source

Make TCP give up immediately when it receives -ENETUNREACH from

tcpip_tx().  This avoids the irritating wait when you accidentally type
"kernel pxelinux.0" before bringing up the network interface.

Add ENETUNREACH to strerror()'s list.
tags/v0.9.3
Michael Brown 17 years ago
parent
commit
76aa9ad07d
2 changed files with 65 additions and 46 deletions
  1. 10
    7
      src/hci/strerror.c
  2. 55
    39
      src/net/tcp.c

+ 10
- 7
src/hci/strerror.c View File

@@ -55,10 +55,13 @@ const char * strerror ( int errno ) {
55 55
 }
56 56
 
57 57
 /** The most common errors */
58
-struct errortab enoerr __errortab = { 0, "No error" };
59
-struct errortab enoem __errortab = { ENOMEM, "Out of memory" };
60
-struct errortab einval __errortab = { EINVAL, "Invalid argument" };
61
-struct errortab enospc __errortab = { ENOSPC, "No space left on device" };
62
-struct errortab eio __errortab = { EIO, "Input/output error" };
63
-struct errortab eacces __errortab = { EACCES, "Permission denied" };
64
-struct errortab enoent __errortab = { ENOENT, "File not found" };
58
+struct errortab common_errors[] __errortab = {
59
+	{ 0, "No error" },
60
+	{ ENOMEM, "Out of memory" },
61
+	{ EINVAL, "Invalid argument" },
62
+	{ ENOSPC, "No space left on device" },
63
+	{ EIO, "Input/output error" },
64
+	{ EACCES, "Permission denied" },
65
+	{ ENOENT, "File not found" },
66
+	{ ENETUNREACH, "Network unreachable" },
67
+};

+ 55
- 39
src/net/tcp.c View File

@@ -17,6 +17,7 @@
17 17
  */
18 18
 
19 19
 static void tcp_expired ( struct retry_timer *timer, int over );
20
+static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send );
20 21
 
21 22
 /**
22 23
  * A TCP connection
@@ -211,6 +212,35 @@ static void tcp_disassociate ( struct tcp_connection *conn ) {
211 212
 	}
212 213
 }
213 214
 
215
+/**
216
+ * Abort TCP connection
217
+ *
218
+ * @v conn		TCP connection
219
+ * @v send_rst		Send a RST after closing
220
+ * @v rc		Reason code
221
+ */
222
+static void tcp_abort ( struct tcp_connection *conn, int send_rst, int rc ) {
223
+	struct tcp_application *app = conn->app;
224
+
225
+	/* Transition to CLOSED */
226
+	conn->tcp_state = TCP_CLOSED;
227
+	tcp_dump_state ( conn );
228
+
229
+	/* Send RST if requested to do so */
230
+	if ( send_rst )
231
+		tcp_senddata_conn ( conn, 1 );
232
+
233
+	/* Break association between application and connection */
234
+	tcp_disassociate ( conn );
235
+
236
+	/* Free the connection */
237
+	free_tcp ( conn );
238
+
239
+	/* Notify application */
240
+	if ( app && app->tcp_op->closed )
241
+		app->tcp_op->closed ( app, rc );
242
+}
243
+
214 244
 /**
215 245
  * Transmit any outstanding data
216 246
  *
@@ -234,6 +264,7 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
234 264
 	unsigned int flags;
235 265
 	size_t len;
236 266
 	size_t seq_len;
267
+	int rc;
237 268
 
238 269
 	/* Allocate space to the TX buffer */
239 270
 	pkb = alloc_pkb ( MAX_PKB_LEN );
@@ -318,8 +349,23 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
318 349
 	DBGC ( conn, "\n" );
319 350
 
320 351
 	/* Transmit packet */
321
-	return tcpip_tx ( pkb, &tcp_protocol, &conn->peer,
322
-			  NULL, &tcphdr->csum );
352
+	rc = tcpip_tx ( pkb, &tcp_protocol, &conn->peer, NULL, &tcphdr->csum );
353
+
354
+	/* If we got -ENETUNREACH, kill the connection immediately
355
+	 * because there is no point retrying.  This isn't strictly
356
+	 * necessary (since we will eventually time out anyway), but
357
+	 * it avoids irritating needless delays.  Don't do this for
358
+	 * RST packets transmitted on connection abort, to avoid a
359
+	 * potential infinite loop.
360
+	 */
361
+	if ( ( ! ( conn->tcp_state & TCP_STATE_SENT ( TCP_RST ) ) ) &&
362
+	     ( rc == -ENETUNREACH ) ) {
363
+		DBGC ( conn, "TCP %p aborting after TX failed: %s\n",
364
+		       conn, strerror ( rc ) );
365
+		tcp_abort ( conn, 0, rc );
366
+	}
367
+
368
+	return rc;
323 369
 }
324 370
 
325 371
 /**
@@ -392,7 +438,6 @@ int tcp_send ( struct tcp_application *app, const void *data, size_t len ) {
392 438
 static void tcp_expired ( struct retry_timer *timer, int over ) {
393 439
 	struct tcp_connection *conn =
394 440
 		container_of ( timer, struct tcp_connection, timer );
395
-	struct tcp_application *app = conn->app;
396 441
 	int graceful_close = TCP_CLOSED_GRACEFULLY ( conn->tcp_state );
397 442
 
398 443
 	DBGC ( conn, "TCP %p timer %s in %s\n", conn,
@@ -406,29 +451,12 @@ static void tcp_expired ( struct retry_timer *timer, int over ) {
406 451
 		 ( conn->tcp_state == TCP_CLOSE_WAIT ) ||
407 452
 		 ( conn->tcp_state == TCP_CLOSING_OR_LAST_ACK ) );
408 453
 
409
-	/* If we have finally timed out and given up, or if this is
410
-	 * the result of a graceful close, terminate the connection
411
-	 */
412 454
 	if ( over || graceful_close ) {
413
-
414
-		/* Transition to CLOSED */
415
-		conn->tcp_state = TCP_CLOSED;
416
-		tcp_dump_state ( conn );
417
-
418
-		/* If we haven't closed gracefully, send a RST */
419
-		if ( ! graceful_close )
420
-			tcp_senddata_conn ( conn, 1 );
421
-
422
-		/* Break association between application and connection */
423
-		tcp_disassociate ( conn );
424
-
425
-		/* Free the connection */
426
-		free_tcp ( conn );
427
-
428
-		/* Notify application */
429
-		if ( app && app->tcp_op->closed )
430
-			app->tcp_op->closed ( app, -ETIMEDOUT );
431
-
455
+		/* If we have finally timed out and given up, or if
456
+		 * this is the result of a graceful close, terminate
457
+		 * the connection
458
+		 */
459
+		tcp_abort ( conn, 1, -ETIMEDOUT );
432 460
 	} else {
433 461
 		/* Otherwise, retransmit the packet */
434 462
 		tcp_senddata_conn ( conn, 0 );
@@ -658,7 +686,6 @@ static int tcp_rx_fin ( struct tcp_connection *conn, uint32_t seq ) {
658 686
  * @ret rc		Return status code
659 687
  */
660 688
 static int tcp_rx_rst ( struct tcp_connection *conn, uint32_t seq ) {
661
-	struct tcp_application *app = conn->app;
662 689
 
663 690
 	/* Accept RST only if it falls within the window.  If we have
664 691
 	 * not yet received a SYN, then we have no window to test
@@ -673,19 +700,8 @@ static int tcp_rx_rst ( struct tcp_connection *conn, uint32_t seq ) {
673 700
 			return 0;
674 701
 	}
675 702
 
676
-	/* Transition to CLOSED */
677
-	conn->tcp_state = TCP_CLOSED;
678
-	tcp_dump_state ( conn );
679
-
680
-	/* Break association between application and connection */
681
-	tcp_disassociate ( conn );
682
-	
683
-	/* Free the connection */
684
-	free_tcp ( conn );
685
-	
686
-	/* Notify application */
687
-	if ( app && app->tcp_op->closed )
688
-		app->tcp_op->closed ( app, -ECONNRESET );
703
+	/* Abort connection without sending a RST */
704
+	tcp_abort ( conn, 0, -ECONNRESET );
689 705
 
690 706
 	return -ECONNRESET;
691 707
 }

Loading…
Cancel
Save