static int clr_flag(char *ifname, short flag) { struct ifreq ifr; int fd;
if (strchr(ifname, ':')) { /* This is a v4 alias interface. Downing it via a socket for another AF may have bad consequences. */ fd = get_socket_for_af(AF_INET); if (fd < 0) { fprintf(stderr, _("No support for INET on this system.\n")); return -1; } } else fd = skfd;
int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) { case SIOCSIFFLAGS: case SIOCSIFMETRIC: case SIOCSIFMTU: case SIOCSIFMAP: case SIOCSIFHWADDR: case SIOCSIFSLAVE: case SIOCADDMULTI: case SIOCDELMULTI: case SIOCSIFHWBROADCAST: case SIOCSIFTXQLEN: case SIOCSMIIREG: case SIOCBONDENSLAVE: case SIOCBONDRELEASE: case SIOCBONDSETHWADDR: case SIOCBONDCHANGEACTIVE: case SIOCBRADDIF: case SIOCBRDELIF: case SIOCSHWTSTAMP: if (!capable(CAP_NET_ADMIN)) return -EPERM; /* fall through */ case SIOCBONDSLAVEINFOQUERY: case SIOCBONDINFOQUERY: dev_load(net, ifr.ifr_name); rtnl_lock(); ret = dev_ifsioc(net, &ifr, cmd); rtnl_unlock(); return ret; }
SIOCSIFFLAGS会调用到dev_ifsioc函数:
1 2 3 4 5 6
static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) { switch (cmd) { case SIOCSIFFLAGS: /* Set interface flags */ return dev_change_flags(dev, ifr->ifr_flags); }
继续跟进dev_change_flags函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
int dev_change_flags(struct net_device *dev, unsigned flags) { int ret, changes; int old_flags = dev->flags;
ret = __dev_change_flags(dev, flags); // 打开设备 if (ret < 0) return ret;
int __dev_change_flags(struct net_device *dev, unsigned int flags) { if ((old_flags ^ flags) & IFF_UP) { /* Bit is different ? */ ret = ((old_flags & IFF_UP) ? __dev_close : __dev_open)(dev); }
/* * Tell people we are going down, so that they can * prepare to death, when device is still operating. */ call_netdevice_notifiers(NETDEV_GOING_DOWN, dev);
clear_bit(__LINK_STATE_START, &dev->state);
/* Synchronize to scheduled poll. We cannot touch poll list, * it can be even on different cpu. So just clear netif_running(). * * dev->stop() will invoke napi_disable() on all of it's * napi_struct instances on this device. */ smp_mb__after_clear_bit(); /* Commit netif_running(). */
dev_deactivate(dev);
/* * Call the device specific close. This cannot fail. * Only if device is UP * * We allow it to be called even after a DETACH hot-plug * event. */ if (ops->ndo_stop) ops->ndo_stop(dev);