Browse Source

[NETDEV] Add notion of link state

Add ability for network devices to flag link up/down state to the
networking core.

Autobooting code will now wait for link-up before attempting DHCP.

IPoIB reflects the Infiniband link state as the network device link state
(which is not strictly correct; we also need a succesful IPoIB IPv4
broadcast group join), but is probably more informative.
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
1ba959c6b3

+ 3
- 0
src/arch/i386/drivers/net/undinet.c View File

@@ -708,6 +708,9 @@ int undinet_probe ( struct undi_device *undi ) {
708 708
 		undinic->hacks |= UNDI_HACK_EB54;
709 709
 	}
710 710
 
711
+	/* Mark as link up; we don't handle link state */
712
+	netdev_link_up ( netdev );
713
+
711 714
 	/* Register network device */
712 715
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
713 716
 		goto err_register;

+ 3
- 0
src/drivers/net/e1000/e1000.c View File

@@ -876,6 +876,9 @@ e1000_probe ( struct pci_device *pdev,
876 876
 	
877 877
 	e1000_get_hw_control ( adapter );
878 878
 
879
+	/* Mark as link up; we don't yet handle link state */
880
+	netdev_link_up ( netdev );
881
+
879 882
 	if ( ( err = register_netdev ( netdev ) ) != 0)
880 883
 		goto err_register;
881 884
 		

+ 19
- 1
src/drivers/net/ipoib.c View File

@@ -471,6 +471,12 @@ static int ipoib_transmit ( struct net_device *netdev,
471 471
 	}
472 472
 	iob_pull ( iobuf, ( sizeof ( *ipoib_pshdr ) ) );
473 473
 
474
+	/* Attempting transmission while link is down will put the
475
+	 * queue pair into an error state, so don't try it.
476
+	 */
477
+	if ( ! ibdev->link_up )
478
+		return -ENETUNREACH;
479
+
474 480
 	/* Construct address vector */
475 481
 	memset ( &av, 0, sizeof ( av ) );
476 482
 	av.qkey = IB_GLOBAL_QKEY;
@@ -790,6 +796,10 @@ static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
790 796
 		return rc;
791 797
 	}
792 798
 
799
+	/* We will set link up on the network device when we receive
800
+	 * the broadcast join response.
801
+	 */
802
+
793 803
 	return 0;
794 804
 }
795 805
 
@@ -907,16 +917,24 @@ static struct net_device_operations ipoib_operations = {
907 917
  */
908 918
 static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) {
909 919
 	struct ib_device *ibdev = ipoib->ibdev;
920
+	struct net_device *netdev = ipoib->netdev;
910 921
 	struct ipoib_mac *mac;
911 922
 
912 923
 	/* Calculate GID portion of MAC address based on port GID */
913
-	mac = ( ( struct ipoib_mac * ) ipoib->netdev->ll_addr );
924
+	mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
914 925
 	memcpy ( &mac->gid, &ibdev->port_gid, sizeof ( mac->gid ) );
915 926
 
916 927
 	/* Calculate broadcast GID based on partition key */
917 928
 	memcpy ( &ipoib->broadcast_gid, &ipv4_broadcast_gid,
918 929
 		 sizeof ( ipoib->broadcast_gid ) );
919 930
 	ipoib->broadcast_gid.u.words[2] = htons ( ibdev->pkey );
931
+
932
+	/* Set net device link state to reflect Infiniband link state */
933
+	if ( ibdev->link_up ) {
934
+		netdev_link_up ( netdev );
935
+	} else {
936
+		netdev_link_down ( netdev );
937
+	}
920 938
 }
921 939
 
922 940
 /**

+ 3
- 0
src/drivers/net/legacy.c View File

@@ -112,6 +112,9 @@ int legacy_probe ( void *hwdev,
112 112
 	 */
113 113
 	dev->desc.irq = nic.irqno;
114 114
 
115
+	/* Mark as link up; legacy devices don't handle link state */
116
+	netdev_link_up ( netdev );
117
+
115 118
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
116 119
 		goto err_register;
117 120
 

+ 3
- 0
src/drivers/net/mtnic.c View File

@@ -1731,6 +1731,9 @@ mtnic_probe(struct pci_device *pci,
1731 1731
                 mac = mac >> 8;
1732 1732
 	}
1733 1733
 
1734
+	/* Mark as link up; we don't yet handle link state */
1735
+	netdev_link_up ( dev );
1736
+
1734 1737
 	if (register_netdev(dev)) {
1735 1738
 		eprintf("Netdev registration failed\n");
1736 1739
 		return MTNIC_ERROR;

+ 3
- 0
src/drivers/net/natsemi.c View File

@@ -205,6 +205,9 @@ static int natsemi_probe (struct pci_device *pci,
205 205
 		last = last1;
206 206
 	}
207 207
 
208
+	/* Mark as link up; we don't yet handle link state */
209
+	netdev_link_up ( netdev );
210
+
208 211
 	if ((rc = register_netdev (netdev)) != 0)
209 212
 		goto err_register_netdev;
210 213
 

+ 3
- 0
src/drivers/net/pnic.c View File

@@ -250,6 +250,9 @@ static int pnic_probe ( struct pci_device *pci,
250 250
 	status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0,
251 251
 				netdev->ll_addr, ETH_ALEN, NULL );
252 252
 
253
+	/* Mark as link up; PNIC has no concept of link state */
254
+	netdev_link_up ( netdev );
255
+
253 256
 	/* Register network device */
254 257
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
255 258
 		goto err;

+ 3
- 0
src/drivers/net/rtl8139.c View File

@@ -518,6 +518,9 @@ static int rtl_probe ( struct pci_device *pci,
518 518
 	rtl_reset ( netdev );
519 519
 	rtl_init_eeprom ( netdev );
520 520
 	nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
521
+
522
+	/* Mark as link up; we don't yet handle link state */
523
+	netdev_link_up ( netdev );
521 524
 	
522 525
 	/* Register network device */
523 526
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )

+ 1
- 0
src/include/gpxe/errfile.h View File

@@ -151,6 +151,7 @@
151 151
 #define ERRFILE_uri_test	      ( ERRFILE_OTHER | 0x000b0000 )
152 152
 #define ERRFILE_ibft		      ( ERRFILE_OTHER | 0x000c0000 )
153 153
 #define ERRFILE_tls		      ( ERRFILE_OTHER | 0x000d0000 )
154
+#define ERRFILE_ifmgmt		      ( ERRFILE_OTHER | 0x000e0000 )
154 155
 
155 156
 /** @} */
156 157
 

+ 34
- 0
src/include/gpxe/netdevice.h View File

@@ -254,6 +254,9 @@ struct net_device {
254 254
 /** Network device is open */
255 255
 #define NETDEV_OPEN 0x0001
256 256
 
257
+/** Network device has link */
258
+#define NETDEV_LINK_UP 0x0002
259
+
257 260
 /** Declare a link-layer protocol */
258 261
 #define __ll_protocol  __table ( struct ll_protocol, ll_protocols, 01 )
259 262
 
@@ -352,6 +355,37 @@ netdev_settings ( struct net_device *netdev ) {
352 355
 	return &netdev->settings.settings;
353 356
 }
354 357
 
358
+/**
359
+ * Mark network device as having link up
360
+ *
361
+ * @v netdev		Network device
362
+ */
363
+static inline __attribute__ (( always_inline )) void
364
+netdev_link_up ( struct net_device *netdev ) {
365
+	netdev->state |= NETDEV_LINK_UP;
366
+}
367
+
368
+/**
369
+ * Mark network device as having link down
370
+ *
371
+ * @v netdev		Network device
372
+ */
373
+static inline __attribute__ (( always_inline )) void
374
+netdev_link_down ( struct net_device *netdev ) {
375
+	netdev->state &= ~NETDEV_LINK_UP;
376
+}
377
+
378
+/**
379
+ * Check link state of network device
380
+ *
381
+ * @v netdev		Network device
382
+ * @ret link_up		Link is up
383
+ */
384
+static inline __attribute__ (( always_inline )) int
385
+netdev_link_ok ( struct net_device *netdev ) {
386
+	return ( netdev->state & NETDEV_LINK_UP );
387
+}
388
+
355 389
 extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
356 390
 extern void netdev_tx_complete_err ( struct net_device *netdev,
357 391
 				 struct io_buffer *iobuf, int rc );

+ 1
- 0
src/include/usr/ifmgmt.h View File

@@ -12,5 +12,6 @@ struct net_device;
12 12
 extern int ifopen ( struct net_device *netdev );
13 13
 extern void ifclose ( struct net_device *netdev );
14 14
 extern void ifstat ( struct net_device *netdev );
15
+extern int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms );
15 16
 
16 17
 #endif /* _USR_IFMGMT_H */

+ 11
- 0
src/usr/autoboot.c View File

@@ -38,6 +38,9 @@
38 38
  *
39 39
  */
40 40
 
41
+/** Time to wait for link-up */
42
+#define LINK_WAIT_MS 15000
43
+
41 44
 /**
42 45
  * Identify the boot network device
43 46
  *
@@ -136,6 +139,14 @@ static int netboot ( struct net_device *netdev ) {
136 139
 		return rc;
137 140
 	ifstat ( netdev );
138 141
 
142
+	/* Wait for link-up */
143
+	printf ( "Waiting for link-up on %s...", netdev->name );
144
+	if ( ( rc = iflinkwait ( netdev, LINK_WAIT_MS ) ) != 0 ) {
145
+		printf ( " no link detected\n" );
146
+		return rc;
147
+	}
148
+	printf ( " ok\n" );
149
+
139 150
 	/* Configure device via DHCP */
140 151
 	if ( ( rc = dhcp ( netdev ) ) != 0 )
141 152
 		return rc;

+ 23
- 1
src/usr/ifmgmt.c View File

@@ -18,8 +18,11 @@
18 18
 
19 19
 #include <string.h>
20 20
 #include <stdio.h>
21
+#include <unistd.h>
22
+#include <errno.h>
21 23
 #include <gpxe/netdevice.h>
22 24
 #include <gpxe/device.h>
25
+#include <gpxe/process.h>
23 26
 #include <usr/ifmgmt.h>
24 27
 
25 28
 /** @file
@@ -61,9 +64,28 @@ void ifclose ( struct net_device *netdev ) {
61 64
  * @v netdev		Network device
62 65
  */
63 66
 void ifstat ( struct net_device *netdev ) {
64
-	printf ( "%s: %s on %s (%s) TX:%d TXE:%d RX:%d RXE:%d\n",
67
+	printf ( "%s: %s on %s (%s)\n"
68
+		 "  [Link:%s, TX:%d TXE:%d RX:%d RXE:%d]\n",
65 69
 		 netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name,
66 70
 		 ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ),
71
+		 ( netdev_link_ok ( netdev ) ? "up" : "down" ),
67 72
 		 netdev->stats.tx_ok, netdev->stats.tx_err,
68 73
 		 netdev->stats.rx_ok, netdev->stats.rx_err );
69 74
 }
75
+
76
+/**
77
+ * Wait for link-up
78
+ *
79
+ * @v netdev		Network device
80
+ * @v max_wait_ms	Maximum time to wait, in ms
81
+ */
82
+int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms ) {
83
+	while ( 1 ) {
84
+		if ( netdev_link_ok ( netdev ) )
85
+			return 0;
86
+		if ( max_wait_ms-- == 0 )
87
+			return -ETIMEDOUT;
88
+		step();
89
+		mdelay ( 1 );
90
+	}
91
+}

Loading…
Cancel
Save