前面文章讲了Linux系统的ethtool框架的一些东西,是从用户空间可以直观认识到的地方入手。同样,本文从Linux系统绝大部分人都熟悉的“ifconfig eth0 up”命令来跟踪一下此命令在内核中的发生了什么事情。由于ifconfig启动(up)和禁止(down)网络设备很相似,就放到一起讲了。
首先从ifconfig的源码入手,我下载的源码地址是http://www.tazenda.demon.co.uk/phil/net-tools/。这个网站上还有大量很有用的工具的源码,源码分布符合Linux的系统目录,有兴趣的可以去看看。
在我们输入up或down时,对应的代码如下:
- main()
- {
- if (!strcmp(*spp, "up")) {
- goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
- spp++;
- continue;
- }
- if (!strcmp(*spp, "down")) {
- goterr |= clr_flag(ifr.ifr_name, IFF_UP);
- spp++;
- continue;
- }
- }
很简单,就是根据用户的输入来标志IFF_UP参考。当up时,使用set_flag置位IFF_UP和IFF_RUNNING,当down时,使用clr_flag清除IFF_UP。Linux的这种思想值得学习,其实对于内核来讲,真的就是通过IFF_UP标志来判断网卡的使能和禁止的。
来看设置标志的set_flag函数:
- static int set_flag(char *ifname, short flag)
- {
- struct ifreq ifr;
- safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
- if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
- fprintf(stderr, _("%s: unknown interface: %s\n"),
- ifname, strerror(errno));
- return (-1);
- }
- safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
- ifr.ifr_flags |= flag;
- if (ioctl(skfd, SIOCSIFFLAGS, &ifr) < 0) {
- perror("SIOCSIFFLAGS");
- return -1;
- }
- return (0);
- }
以及清除标志的clr_flag函数:
- 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;