mirror of https://github.com/ipxe/ipxe.git
[netdevice] Add mechanism for reporting detailed link status codes
Expand the NETDEV_LINK_UP bit into a link_rc status code field, allowing specific reasons for link failure to be reported via "ifstat". Originally-authored-by: Joshua Oreman <oremanj@rwcr.net>pull/1/head
parent
cb9700ef6f
commit
a310d00d37
|
@ -115,6 +115,7 @@ struct errortab common_errors[] __errortab = {
|
||||||
{ ENOEXEC, "Not an executable image" },
|
{ ENOEXEC, "Not an executable image" },
|
||||||
{ ENOMEM, "Out of memory" },
|
{ ENOMEM, "Out of memory" },
|
||||||
{ ENOSPC, "No space left on device" },
|
{ ENOSPC, "No space left on device" },
|
||||||
|
{ ENOTCONN, "Not connected" },
|
||||||
{ ENOTSUP, "Not supported" },
|
{ ENOTSUP, "Not supported" },
|
||||||
{ EPERM, "Operation not permitted" },
|
{ EPERM, "Operation not permitted" },
|
||||||
{ ERANGE, "Out of range" },
|
{ ERANGE, "Out of range" },
|
||||||
|
|
|
@ -267,6 +267,12 @@ struct net_device {
|
||||||
* This is the bitwise-OR of zero or more NETDEV_XXX constants.
|
* This is the bitwise-OR of zero or more NETDEV_XXX constants.
|
||||||
*/
|
*/
|
||||||
unsigned int state;
|
unsigned int state;
|
||||||
|
/** Link status code
|
||||||
|
*
|
||||||
|
* Zero indicates that the link is up; any other value
|
||||||
|
* indicates the error preventing link-up.
|
||||||
|
*/
|
||||||
|
int link_rc;
|
||||||
/** Maximum packet length
|
/** Maximum packet length
|
||||||
*
|
*
|
||||||
* This length includes any link-layer headers.
|
* This length includes any link-layer headers.
|
||||||
|
@ -291,9 +297,6 @@ 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
|
|
||||||
|
|
||||||
/** Link-layer protocol table */
|
/** Link-layer protocol table */
|
||||||
#define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" )
|
#define LL_PROTOCOLS __table ( struct ll_protocol, "ll_protocols" )
|
||||||
|
|
||||||
|
@ -420,17 +423,18 @@ netdev_settings_init ( struct net_device *netdev ) {
|
||||||
*/
|
*/
|
||||||
static inline __attribute__ (( always_inline )) void
|
static inline __attribute__ (( always_inline )) void
|
||||||
netdev_link_up ( struct net_device *netdev ) {
|
netdev_link_up ( struct net_device *netdev ) {
|
||||||
netdev->state |= NETDEV_LINK_UP;
|
netdev->link_rc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark network device as having link down
|
* Mark network device as having link down due to a specific error
|
||||||
*
|
*
|
||||||
* @v netdev Network device
|
* @v netdev Network device
|
||||||
|
* @v rc Link status code
|
||||||
*/
|
*/
|
||||||
static inline __attribute__ (( always_inline )) void
|
static inline __attribute__ (( always_inline )) void
|
||||||
netdev_link_down ( struct net_device *netdev ) {
|
netdev_link_err ( struct net_device *netdev, int rc ) {
|
||||||
netdev->state &= ~NETDEV_LINK_UP;
|
netdev->link_rc = rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -441,9 +445,10 @@ netdev_link_down ( struct net_device *netdev ) {
|
||||||
*/
|
*/
|
||||||
static inline __attribute__ (( always_inline )) int
|
static inline __attribute__ (( always_inline )) int
|
||||||
netdev_link_ok ( struct net_device *netdev ) {
|
netdev_link_ok ( struct net_device *netdev ) {
|
||||||
return ( netdev->state & NETDEV_LINK_UP );
|
return ( netdev->link_rc == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void netdev_link_down ( struct net_device *netdev );
|
||||||
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 );
|
||||||
|
|
|
@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||||
#include <gpxe/process.h>
|
#include <gpxe/process.h>
|
||||||
#include <gpxe/init.h>
|
#include <gpxe/init.h>
|
||||||
#include <gpxe/device.h>
|
#include <gpxe/device.h>
|
||||||
|
#include <gpxe/errortab.h>
|
||||||
#include <gpxe/netdevice.h>
|
#include <gpxe/netdevice.h>
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
@ -44,6 +45,34 @@ struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
|
||||||
/** List of open network devices, in reverse order of opening */
|
/** List of open network devices, in reverse order of opening */
|
||||||
struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
|
struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
|
||||||
|
|
||||||
|
/** Default link status code */
|
||||||
|
#define EUNKNOWN_LINK_STATUS EINPROGRESS
|
||||||
|
|
||||||
|
/** Human-readable message for the default link status */
|
||||||
|
struct errortab netdev_errors[] __errortab = {
|
||||||
|
{ EUNKNOWN_LINK_STATUS, "Unknown" },
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark network device as having link down
|
||||||
|
*
|
||||||
|
* @v netdev Network device
|
||||||
|
*/
|
||||||
|
void netdev_link_down ( struct net_device *netdev ) {
|
||||||
|
|
||||||
|
switch ( netdev->link_rc ) {
|
||||||
|
case 0:
|
||||||
|
case -EUNKNOWN_LINK_STATUS:
|
||||||
|
netdev->link_rc = -ENOTCONN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Avoid clobbering a more detailed link status code,
|
||||||
|
* if one is already set.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record network device statistic
|
* Record network device statistic
|
||||||
*
|
*
|
||||||
|
@ -302,6 +331,7 @@ struct net_device * alloc_netdev ( size_t priv_size ) {
|
||||||
netdev = zalloc ( total_len );
|
netdev = zalloc ( total_len );
|
||||||
if ( netdev ) {
|
if ( netdev ) {
|
||||||
netdev->refcnt.free = free_netdev;
|
netdev->refcnt.free = free_netdev;
|
||||||
|
netdev->link_rc = -EUNKNOWN_LINK_STATUS;
|
||||||
INIT_LIST_HEAD ( &netdev->tx_queue );
|
INIT_LIST_HEAD ( &netdev->tx_queue );
|
||||||
INIT_LIST_HEAD ( &netdev->rx_queue );
|
INIT_LIST_HEAD ( &netdev->rx_queue );
|
||||||
netdev_settings_init ( netdev );
|
netdev_settings_init ( netdev );
|
||||||
|
|
|
@ -94,6 +94,10 @@ void ifstat ( struct net_device *netdev ) {
|
||||||
( netdev_link_ok ( netdev ) ? "up" : "down" ),
|
( netdev_link_ok ( netdev ) ? "up" : "down" ),
|
||||||
netdev->tx_stats.good, netdev->tx_stats.bad,
|
netdev->tx_stats.good, netdev->tx_stats.bad,
|
||||||
netdev->rx_stats.good, netdev->rx_stats.bad );
|
netdev->rx_stats.good, netdev->rx_stats.bad );
|
||||||
|
if ( ! netdev_link_ok ( netdev ) ) {
|
||||||
|
printf ( " [Link status: %s]\n",
|
||||||
|
strerror ( netdev->link_rc ) );
|
||||||
|
}
|
||||||
ifstat_errors ( &netdev->tx_stats, "TXE" );
|
ifstat_errors ( &netdev->tx_stats, "TXE" );
|
||||||
ifstat_errors ( &netdev->rx_stats, "RXE" );
|
ifstat_errors ( &netdev->rx_stats, "RXE" );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue