User Tools

Site Tools


ndo_change_carrier

This is an old revision of the document!


Overview

Setting/detecting carrier, and the subsequent implications of setting net_device_ops ndo_change_carrier field.

Normal behaviour

Net device state

From include/linux/netdevice.h:

Net device state:

struct net_device {
        ... snip ...
        unsigned long           state;
        ... snip ...

State flag bits for later testing:

enum netdev_state_t {
        __LINK_STATE_START,
        __LINK_STATE_PRESENT,
        __LINK_STATE_NOCARRIER,
        __LINK_STATE_LINKWATCH_PENDING,
        __LINK_STATE_DORMANT,
};

Checking for state of carrier

Again from netdevice.h:

/**
 *      netif_carrier_ok - test if carrier present
 *      @dev: network device
 *
 * Check if carrier is present on device
 */
static inline bool netif_carrier_ok(const struct net_device *dev)
{
        return !test_bit(__LINK_STATE_NOCARRIER, &dev->state);
}

void netif_carrier_on(struct net_device *dev);
void netif_carrier_off(struct net_device *dev);

Test for interface running

Still in netdevice.h:

/**
 *	netif_running - test if up
 *	@dev: network device
 *
 *	Test if the device has been brought up.
 */
static inline bool netif_running(const struct net_device *dev)
{
	return test_bit(__LINK_STATE_START, &dev->state);
}

Test if carrier on or off

From net/sched/sch_generic.c:

/**
 *      netif_carrier_on - set carrier
 *      @dev: network device
 *
 * Device has detected that carrier.
 */
void netif_carrier_on(struct net_device *dev)
{
        if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
                if (dev->reg_state == NETREG_UNINITIALIZED)
                        return;
                atomic_inc(&dev->carrier_up_count);
                linkwatch_fire_event(dev);
                if (netif_running(dev))
                        __netdev_watchdog_up(dev);
        }
}
EXPORT_SYMBOL(netif_carrier_on);

/**
 *      netif_carrier_off - clear carrier
 *      @dev: network device
 *
 * Device has detected loss of carrier.
 */
void netif_carrier_off(struct net_device *dev)
{
        if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
                if (dev->reg_state == NETREG_UNINITIALIZED)
                        return;
                atomic_inc(&dev->carrier_down_count);
                linkwatch_fire_event(dev);
        }
}
EXPORT_SYMBOL(netif_carrier_off);
ndo_change_carrier.1533400420.txt.gz · Last modified: 2018/08/04 16:33 by rpjday