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
 		undinic->hacks |= UNDI_HACK_EB54;
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
 	/* Register network device */
714
 	/* Register network device */
712
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
715
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
713
 		goto err_register;
716
 		goto err_register;

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

876
 	
876
 	
877
 	e1000_get_hw_control ( adapter );
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
 	if ( ( err = register_netdev ( netdev ) ) != 0)
882
 	if ( ( err = register_netdev ( netdev ) ) != 0)
880
 		goto err_register;
883
 		goto err_register;
881
 		
884
 		

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

471
 	}
471
 	}
472
 	iob_pull ( iobuf, ( sizeof ( *ipoib_pshdr ) ) );
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
 	/* Construct address vector */
480
 	/* Construct address vector */
475
 	memset ( &av, 0, sizeof ( av ) );
481
 	memset ( &av, 0, sizeof ( av ) );
476
 	av.qkey = IB_GLOBAL_QKEY;
482
 	av.qkey = IB_GLOBAL_QKEY;
790
 		return rc;
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
 	return 0;
803
 	return 0;
794
 }
804
 }
795
 
805
 
907
  */
917
  */
908
 static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) {
918
 static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) {
909
 	struct ib_device *ibdev = ipoib->ibdev;
919
 	struct ib_device *ibdev = ipoib->ibdev;
920
+	struct net_device *netdev = ipoib->netdev;
910
 	struct ipoib_mac *mac;
921
 	struct ipoib_mac *mac;
911
 
922
 
912
 	/* Calculate GID portion of MAC address based on port GID */
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
 	memcpy ( &mac->gid, &ibdev->port_gid, sizeof ( mac->gid ) );
925
 	memcpy ( &mac->gid, &ibdev->port_gid, sizeof ( mac->gid ) );
915
 
926
 
916
 	/* Calculate broadcast GID based on partition key */
927
 	/* Calculate broadcast GID based on partition key */
917
 	memcpy ( &ipoib->broadcast_gid, &ipv4_broadcast_gid,
928
 	memcpy ( &ipoib->broadcast_gid, &ipv4_broadcast_gid,
918
 		 sizeof ( ipoib->broadcast_gid ) );
929
 		 sizeof ( ipoib->broadcast_gid ) );
919
 	ipoib->broadcast_gid.u.words[2] = htons ( ibdev->pkey );
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
 	 */
112
 	 */
113
 	dev->desc.irq = nic.irqno;
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
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
118
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
116
 		goto err_register;
119
 		goto err_register;
117
 
120
 

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

1731
                 mac = mac >> 8;
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
 	if (register_netdev(dev)) {
1737
 	if (register_netdev(dev)) {
1735
 		eprintf("Netdev registration failed\n");
1738
 		eprintf("Netdev registration failed\n");
1736
 		return MTNIC_ERROR;
1739
 		return MTNIC_ERROR;

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

205
 		last = last1;
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
 	if ((rc = register_netdev (netdev)) != 0)
211
 	if ((rc = register_netdev (netdev)) != 0)
209
 		goto err_register_netdev;
212
 		goto err_register_netdev;
210
 
213
 

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

250
 	status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0,
250
 	status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0,
251
 				netdev->ll_addr, ETH_ALEN, NULL );
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
 	/* Register network device */
256
 	/* Register network device */
254
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
257
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
255
 		goto err;
258
 		goto err;

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

518
 	rtl_reset ( netdev );
518
 	rtl_reset ( netdev );
519
 	rtl_init_eeprom ( netdev );
519
 	rtl_init_eeprom ( netdev );
520
 	nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
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
 	/* Register network device */
525
 	/* Register network device */
523
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
526
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )

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

151
 #define ERRFILE_uri_test	      ( ERRFILE_OTHER | 0x000b0000 )
151
 #define ERRFILE_uri_test	      ( ERRFILE_OTHER | 0x000b0000 )
152
 #define ERRFILE_ibft		      ( ERRFILE_OTHER | 0x000c0000 )
152
 #define ERRFILE_ibft		      ( ERRFILE_OTHER | 0x000c0000 )
153
 #define ERRFILE_tls		      ( ERRFILE_OTHER | 0x000d0000 )
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
 /** Network device is open */
254
 /** Network device is open */
255
 #define NETDEV_OPEN 0x0001
255
 #define NETDEV_OPEN 0x0001
256
 
256
 
257
+/** Network device has link */
258
+#define NETDEV_LINK_UP 0x0002
259
+
257
 /** Declare a link-layer protocol */
260
 /** Declare a link-layer protocol */
258
 #define __ll_protocol  __table ( struct ll_protocol, ll_protocols, 01 )
261
 #define __ll_protocol  __table ( struct ll_protocol, ll_protocols, 01 )
259
 
262
 
352
 	return &netdev->settings.settings;
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
 extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
389
 extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
356
 extern void netdev_tx_complete_err ( struct net_device *netdev,
390
 extern void netdev_tx_complete_err ( struct net_device *netdev,
357
 				 struct io_buffer *iobuf, int rc );
391
 				 struct io_buffer *iobuf, int rc );

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

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

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

38
  *
38
  *
39
  */
39
  */
40
 
40
 
41
+/** Time to wait for link-up */
42
+#define LINK_WAIT_MS 15000
43
+
41
 /**
44
 /**
42
  * Identify the boot network device
45
  * Identify the boot network device
43
  *
46
  *
136
 		return rc;
139
 		return rc;
137
 	ifstat ( netdev );
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
 	/* Configure device via DHCP */
150
 	/* Configure device via DHCP */
140
 	if ( ( rc = dhcp ( netdev ) ) != 0 )
151
 	if ( ( rc = dhcp ( netdev ) ) != 0 )
141
 		return rc;
152
 		return rc;

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

18
 
18
 
19
 #include <string.h>
19
 #include <string.h>
20
 #include <stdio.h>
20
 #include <stdio.h>
21
+#include <unistd.h>
22
+#include <errno.h>
21
 #include <gpxe/netdevice.h>
23
 #include <gpxe/netdevice.h>
22
 #include <gpxe/device.h>
24
 #include <gpxe/device.h>
25
+#include <gpxe/process.h>
23
 #include <usr/ifmgmt.h>
26
 #include <usr/ifmgmt.h>
24
 
27
 
25
 /** @file
28
 /** @file
61
  * @v netdev		Network device
64
  * @v netdev		Network device
62
  */
65
  */
63
 void ifstat ( struct net_device *netdev ) {
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
 		 netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name,
69
 		 netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name,
66
 		 ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ),
70
 		 ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ),
71
+		 ( netdev_link_ok ( netdev ) ? "up" : "down" ),
67
 		 netdev->stats.tx_ok, netdev->stats.tx_err,
72
 		 netdev->stats.tx_ok, netdev->stats.tx_err,
68
 		 netdev->stats.rx_ok, netdev->stats.rx_err );
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