Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
operstate [2018/08/26 16:36] – [net/core/net-sysfs.c] rpjdayoperstate [2018/08/27 11:07] (current) – [Testing under sysfs] rpjday
Line 66: Line 66:
  
 ==== include/uapi/linux/if.h ==== ==== include/uapi/linux/if.h ====
 +
 +Possible values for ''netdev%%->%%operstate'':
  
 <code> <code>
Line 116: Line 118:
 ===== Testing under sysfs ===== ===== Testing under sysfs =====
  
-Unplugging and plugging:+Unplugging and plugging (administratively, the interface remains UP the whole time):
  
 <code> <code>
Line 150: Line 152:
 </code> </code>
  
-This should be set by ''dev_open()'', so it should be up regardless.+This should be set by ''dev_open()'', so it should be up regardless. See usage [[https://elixir.bootlin.com/linux/latest/ident/__LINK_STATE_START|here]].
 ==== netif_oper_up() ==== ==== netif_oper_up() ====
  
-This is the important one related to plugging and unplugging:+This is the important one related to plugging and unplugging (ignore the possibility of ''IF_OPER_UNKNOWN'' for now):
  
 <code> <code>
Line 169: Line 171:
 </code> </code>
 ==== netif_carrier_ok() ==== ==== netif_carrier_ok() ====
 +
 +This routine becomes important shortly:
  
 <code> <code>
Line 199: Line 203:
         struct net_device *netdev = to_net_dev(dev);         struct net_device *netdev = to_net_dev(dev);
  
-        if (netif_running(netdev))  // if IFF_UP, which should be true+        if (netif_running(netdev))  // if __LINK_STATE_START, which should be true
                 return sprintf(buf, fmt_dec, !!netif_carrier_ok(netdev));                 return sprintf(buf, fmt_dec, !!netif_carrier_ok(netdev));
  
Line 215: Line 219:
 } }
 </code> </code>
 +
 +==== Where is IF_OPER_DOWN set? ====
 +
 +From ''net/core/link_watch.c'', it all comes back to ''netif_carrier_ok()'':
 +
 +<code>
 +static unsigned char default_operstate(const struct net_device *dev)
 +{
 + if (!netif_carrier_ok(dev))
 + return (dev->ifindex != dev_get_iflink(dev) ?
 + IF_OPER_LOWERLAYERDOWN : IF_OPER_DOWN);
 +
 + if (netif_dormant(dev))
 + return IF_OPER_DORMANT;
 +
 + return IF_OPER_UP;
 +}
 +</code>
 +
 +which brings us back to who sets ''%%__%%LINK_STATE_NOCARRIER''.
 +
 +==== Setting/detecting carrier ====
 +
 +From ''net/sched/sch_generic.c'':
 +
 +<code>
 +/**
 + * 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);
 +</code>
 +
 +So who calls ''netif_carrier_off()''? Apparently, lots of people.
  • operstate.1535301401.txt.gz
  • Last modified: 2018/08/26 16:36
  • by rpjday