mirror of https://github.com/ipxe/ipxe.git
[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.pull/1/head
parent
d72bf13b78
commit
1ba959c6b3
|
@ -708,6 +708,9 @@ int undinet_probe ( struct undi_device *undi ) {
|
||||||
undinic->hacks |= UNDI_HACK_EB54;
|
undinic->hacks |= UNDI_HACK_EB54;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark as link up; we don't handle link state */
|
||||||
|
netdev_link_up ( netdev );
|
||||||
|
|
||||||
/* Register network device */
|
/* Register network device */
|
||||||
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
||||||
goto err_register;
|
goto err_register;
|
||||||
|
|
|
@ -876,6 +876,9 @@ e1000_probe ( struct pci_device *pdev,
|
||||||
|
|
||||||
e1000_get_hw_control ( adapter );
|
e1000_get_hw_control ( adapter );
|
||||||
|
|
||||||
|
/* Mark as link up; we don't yet handle link state */
|
||||||
|
netdev_link_up ( netdev );
|
||||||
|
|
||||||
if ( ( err = register_netdev ( netdev ) ) != 0)
|
if ( ( err = register_netdev ( netdev ) ) != 0)
|
||||||
goto err_register;
|
goto err_register;
|
||||||
|
|
||||||
|
|
|
@ -471,6 +471,12 @@ static int ipoib_transmit ( struct net_device *netdev,
|
||||||
}
|
}
|
||||||
iob_pull ( iobuf, ( sizeof ( *ipoib_pshdr ) ) );
|
iob_pull ( iobuf, ( sizeof ( *ipoib_pshdr ) ) );
|
||||||
|
|
||||||
|
/* Attempting transmission while link is down will put the
|
||||||
|
* queue pair into an error state, so don't try it.
|
||||||
|
*/
|
||||||
|
if ( ! ibdev->link_up )
|
||||||
|
return -ENETUNREACH;
|
||||||
|
|
||||||
/* Construct address vector */
|
/* Construct address vector */
|
||||||
memset ( &av, 0, sizeof ( av ) );
|
memset ( &av, 0, sizeof ( av ) );
|
||||||
av.qkey = IB_GLOBAL_QKEY;
|
av.qkey = IB_GLOBAL_QKEY;
|
||||||
|
@ -790,6 +796,10 @@ static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We will set link up on the network device when we receive
|
||||||
|
* the broadcast join response.
|
||||||
|
*/
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -907,16 +917,24 @@ static struct net_device_operations ipoib_operations = {
|
||||||
*/
|
*/
|
||||||
static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) {
|
static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) {
|
||||||
struct ib_device *ibdev = ipoib->ibdev;
|
struct ib_device *ibdev = ipoib->ibdev;
|
||||||
|
struct net_device *netdev = ipoib->netdev;
|
||||||
struct ipoib_mac *mac;
|
struct ipoib_mac *mac;
|
||||||
|
|
||||||
/* Calculate GID portion of MAC address based on port GID */
|
/* Calculate GID portion of MAC address based on port GID */
|
||||||
mac = ( ( struct ipoib_mac * ) ipoib->netdev->ll_addr );
|
mac = ( ( struct ipoib_mac * ) netdev->ll_addr );
|
||||||
memcpy ( &mac->gid, &ibdev->port_gid, sizeof ( mac->gid ) );
|
memcpy ( &mac->gid, &ibdev->port_gid, sizeof ( mac->gid ) );
|
||||||
|
|
||||||
/* Calculate broadcast GID based on partition key */
|
/* Calculate broadcast GID based on partition key */
|
||||||
memcpy ( &ipoib->broadcast_gid, &ipv4_broadcast_gid,
|
memcpy ( &ipoib->broadcast_gid, &ipv4_broadcast_gid,
|
||||||
sizeof ( ipoib->broadcast_gid ) );
|
sizeof ( ipoib->broadcast_gid ) );
|
||||||
ipoib->broadcast_gid.u.words[2] = htons ( ibdev->pkey );
|
ipoib->broadcast_gid.u.words[2] = htons ( ibdev->pkey );
|
||||||
|
|
||||||
|
/* Set net device link state to reflect Infiniband link state */
|
||||||
|
if ( ibdev->link_up ) {
|
||||||
|
netdev_link_up ( netdev );
|
||||||
|
} else {
|
||||||
|
netdev_link_down ( netdev );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -112,6 +112,9 @@ int legacy_probe ( void *hwdev,
|
||||||
*/
|
*/
|
||||||
dev->desc.irq = nic.irqno;
|
dev->desc.irq = nic.irqno;
|
||||||
|
|
||||||
|
/* Mark as link up; legacy devices don't handle link state */
|
||||||
|
netdev_link_up ( netdev );
|
||||||
|
|
||||||
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
||||||
goto err_register;
|
goto err_register;
|
||||||
|
|
||||||
|
|
|
@ -1731,6 +1731,9 @@ mtnic_probe(struct pci_device *pci,
|
||||||
mac = mac >> 8;
|
mac = mac >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark as link up; we don't yet handle link state */
|
||||||
|
netdev_link_up ( dev );
|
||||||
|
|
||||||
if (register_netdev(dev)) {
|
if (register_netdev(dev)) {
|
||||||
eprintf("Netdev registration failed\n");
|
eprintf("Netdev registration failed\n");
|
||||||
return MTNIC_ERROR;
|
return MTNIC_ERROR;
|
||||||
|
|
|
@ -205,6 +205,9 @@ static int natsemi_probe (struct pci_device *pci,
|
||||||
last = last1;
|
last = last1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark as link up; we don't yet handle link state */
|
||||||
|
netdev_link_up ( netdev );
|
||||||
|
|
||||||
if ((rc = register_netdev (netdev)) != 0)
|
if ((rc = register_netdev (netdev)) != 0)
|
||||||
goto err_register_netdev;
|
goto err_register_netdev;
|
||||||
|
|
||||||
|
|
|
@ -250,6 +250,9 @@ static int pnic_probe ( struct pci_device *pci,
|
||||||
status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0,
|
status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0,
|
||||||
netdev->ll_addr, ETH_ALEN, NULL );
|
netdev->ll_addr, ETH_ALEN, NULL );
|
||||||
|
|
||||||
|
/* Mark as link up; PNIC has no concept of link state */
|
||||||
|
netdev_link_up ( netdev );
|
||||||
|
|
||||||
/* Register network device */
|
/* Register network device */
|
||||||
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -519,6 +519,9 @@ static int rtl_probe ( struct pci_device *pci,
|
||||||
rtl_init_eeprom ( netdev );
|
rtl_init_eeprom ( netdev );
|
||||||
nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
|
nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
|
||||||
|
|
||||||
|
/* Mark as link up; we don't yet handle link state */
|
||||||
|
netdev_link_up ( netdev );
|
||||||
|
|
||||||
/* Register network device */
|
/* Register network device */
|
||||||
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
||||||
goto err_register_netdev;
|
goto err_register_netdev;
|
||||||
|
|
|
@ -151,6 +151,7 @@
|
||||||
#define ERRFILE_uri_test ( ERRFILE_OTHER | 0x000b0000 )
|
#define ERRFILE_uri_test ( ERRFILE_OTHER | 0x000b0000 )
|
||||||
#define ERRFILE_ibft ( ERRFILE_OTHER | 0x000c0000 )
|
#define ERRFILE_ibft ( ERRFILE_OTHER | 0x000c0000 )
|
||||||
#define ERRFILE_tls ( ERRFILE_OTHER | 0x000d0000 )
|
#define ERRFILE_tls ( ERRFILE_OTHER | 0x000d0000 )
|
||||||
|
#define ERRFILE_ifmgmt ( ERRFILE_OTHER | 0x000e0000 )
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|
|
@ -254,6 +254,9 @@ struct net_device {
|
||||||
/** Network device is open */
|
/** Network device is open */
|
||||||
#define NETDEV_OPEN 0x0001
|
#define NETDEV_OPEN 0x0001
|
||||||
|
|
||||||
|
/** Network device has link */
|
||||||
|
#define NETDEV_LINK_UP 0x0002
|
||||||
|
|
||||||
/** Declare a link-layer protocol */
|
/** Declare a link-layer protocol */
|
||||||
#define __ll_protocol __table ( struct ll_protocol, ll_protocols, 01 )
|
#define __ll_protocol __table ( struct ll_protocol, ll_protocols, 01 )
|
||||||
|
|
||||||
|
@ -352,6 +355,37 @@ netdev_settings ( struct net_device *netdev ) {
|
||||||
return &netdev->settings.settings;
|
return &netdev->settings.settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark network device as having link up
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
netdev_link_up ( struct net_device *netdev ) {
|
||||||
|
netdev->state |= NETDEV_LINK_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark network device as having link down
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) void
|
||||||
|
netdev_link_down ( struct net_device *netdev ) {
|
||||||
|
netdev->state &= ~NETDEV_LINK_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check link state of network device
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
* @ret link_up Link is up
|
||||||
|
*/
|
||||||
|
static inline __attribute__ (( always_inline )) int
|
||||||
|
netdev_link_ok ( struct net_device *netdev ) {
|
||||||
|
return ( netdev->state & NETDEV_LINK_UP );
|
||||||
|
}
|
||||||
|
|
||||||
extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
|
extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
|
||||||
extern void netdev_tx_complete_err ( struct net_device *netdev,
|
extern void netdev_tx_complete_err ( struct net_device *netdev,
|
||||||
struct io_buffer *iobuf, int rc );
|
struct io_buffer *iobuf, int rc );
|
||||||
|
|
|
@ -12,5 +12,6 @@ struct net_device;
|
||||||
extern int ifopen ( struct net_device *netdev );
|
extern int ifopen ( struct net_device *netdev );
|
||||||
extern void ifclose ( struct net_device *netdev );
|
extern void ifclose ( struct net_device *netdev );
|
||||||
extern void ifstat ( struct net_device *netdev );
|
extern void ifstat ( struct net_device *netdev );
|
||||||
|
extern int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms );
|
||||||
|
|
||||||
#endif /* _USR_IFMGMT_H */
|
#endif /* _USR_IFMGMT_H */
|
||||||
|
|
|
@ -38,6 +38,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** Time to wait for link-up */
|
||||||
|
#define LINK_WAIT_MS 15000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identify the boot network device
|
* Identify the boot network device
|
||||||
*
|
*
|
||||||
|
@ -136,6 +139,14 @@ static int netboot ( struct net_device *netdev ) {
|
||||||
return rc;
|
return rc;
|
||||||
ifstat ( netdev );
|
ifstat ( netdev );
|
||||||
|
|
||||||
|
/* Wait for link-up */
|
||||||
|
printf ( "Waiting for link-up on %s...", netdev->name );
|
||||||
|
if ( ( rc = iflinkwait ( netdev, LINK_WAIT_MS ) ) != 0 ) {
|
||||||
|
printf ( " no link detected\n" );
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
printf ( " ok\n" );
|
||||||
|
|
||||||
/* Configure device via DHCP */
|
/* Configure device via DHCP */
|
||||||
if ( ( rc = dhcp ( netdev ) ) != 0 )
|
if ( ( rc = dhcp ( netdev ) ) != 0 )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -18,8 +18,11 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <gpxe/netdevice.h>
|
#include <gpxe/netdevice.h>
|
||||||
#include <gpxe/device.h>
|
#include <gpxe/device.h>
|
||||||
|
#include <gpxe/process.h>
|
||||||
#include <usr/ifmgmt.h>
|
#include <usr/ifmgmt.h>
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
@ -61,9 +64,28 @@ void ifclose ( struct net_device *netdev ) {
|
||||||
* @v netdev Network device
|
* @v netdev Network device
|
||||||
*/
|
*/
|
||||||
void ifstat ( struct net_device *netdev ) {
|
void ifstat ( struct net_device *netdev ) {
|
||||||
printf ( "%s: %s on %s (%s) TX:%d TXE:%d RX:%d RXE:%d\n",
|
printf ( "%s: %s on %s (%s)\n"
|
||||||
|
" [Link:%s, TX:%d TXE:%d RX:%d RXE:%d]\n",
|
||||||
netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name,
|
netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name,
|
||||||
( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ),
|
( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ),
|
||||||
|
( netdev_link_ok ( netdev ) ? "up" : "down" ),
|
||||||
netdev->stats.tx_ok, netdev->stats.tx_err,
|
netdev->stats.tx_ok, netdev->stats.tx_err,
|
||||||
netdev->stats.rx_ok, netdev->stats.rx_err );
|
netdev->stats.rx_ok, netdev->stats.rx_err );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for link-up
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
* @v max_wait_ms Maximum time to wait, in ms
|
||||||
|
*/
|
||||||
|
int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms ) {
|
||||||
|
while ( 1 ) {
|
||||||
|
if ( netdev_link_ok ( netdev ) )
|
||||||
|
return 0;
|
||||||
|
if ( max_wait_ms-- == 0 )
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
step();
|
||||||
|
mdelay ( 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue