Linux网络设备管理

     网络设备管理是Linux上层协议栈的基础,所有上层的应用都是基于此层的处理。此处的网络设备管理指代的范围较广,通过对Linux对网络设备的管理的分析,涵盖Linux网络访问层的基本内容。

     网络访问层(TCP/IP参考模型中的主机到网络层,物理层,链路层)主要负责在计算机之间传输信息,与网卡的设备驱动程序直接协作。

Linux网络设备管理框架

Linux网络设备管理与其他类型设备的管理类似,都遵循统一的设备管理模型。

1.Linux网络命名空间(http://lwn.net/Articles/219597/)

   在Linux协议栈中引入网络命名空间,是为了支持网络协议栈的多个实例,而这些协议栈的隔离就是由命名空间来实现的(有点像进程的线性地址空间,协议栈不能访问其他协议栈的私有数据)。需要纳入命名空间的元素包括进程,套接字,网络设备。进程创建的套接字必须属于某个命名空间,套接字的操作也必须在命名空间内进行,网络设备也必须属于某个命名空间,但可能会改变,因为网络设备属于公共资源<~/include/net.h>。

   1:  struct net {
   2:      atomic_t        passive;    /* To decided when the network
   3:                           * namespace should be freed.
   4:                           */
   5:      atomic_t        count;        /* To decided when the network
   6:                           *  namespace should be shut down.
   7:                           */
   8:  #ifdef NETNS_REFCNT_DEBUG
   9:      atomic_t        use_count;    /* To track references we
  10:                           * destroy on demand
  11:                           */
  12:  #endif
  13:      spinlock_t        rules_mod_lock;
  14:   
  15:             /* list of network namespaces */
  16:      struct list_head    cleanup_list;    /* namespaces on death row */
  17:      struct list_head    exit_list;    /* Use only net_mutex */
  18:   
  19:      struct proc_dir_entry     *proc_net;
  20:      struct proc_dir_entry     *proc_net_stat;
  21:   
  22:  #ifdef CONFIG_SYSCTL
  23:      struct ctl_table_set    sysctls;
  24:  #endif
  25:   
  26:      struct sock         *rtnl;            /* rtnetlink socket */
  27:      struct sock        *genl_sock;
  28:   
  29:      
  30:      
  31:     
  32:      unsigned int        dev_base_seq;    /* protected by rtnl_mutex */
  33:   
  34:      /* core fib_rules */
  35:      struct list_head    rules_ops;
  36:   
  37:   
  38:                /* The loopback */
  39:      struct netns_core    core;
  40:      struct netns_mib    mib;
  41:      struct netns_packet    packet;
  42:      struct netns_unix    unx;
  43:      struct netns_ipv4    ipv4;
  44:  #if IS_ENABLED(CONFIG_IPV6)
  45:      struct netns_ipv6    ipv6;
  46:  #endif
  47:  #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
  48:      struct netns_dccp    dccp;
  49:  #endif
  50:  #ifdef CONFIG_NETFILTER
  51:      struct netns_xt        xt;
  52:  #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
  53:      struct netns_ct        ct;
  54:  #endif
  55:      struct sock        *nfnl;
  56:      struct sock        *nfnl_stash;
  57:  #endif
  58:  #ifdef CONFIG_WEXT_CORE
  59:      struct sk_buff_head    wext_nlevents;
  60:  #endif
  61:      struct net_generic __rcu    *gen;
  62:   
  63:      /* Note : following structs are cache line aligned */
  64:  #ifdef CONFIG_XFRM
  65:      struct netns_xfrm    xfrm;
  66:  #endif
  67:      struct netns_ipvs    *ipvs;
  68:  };
 
   1:  /* Init's network namespace */
   2:  

在内核中引入命名空间工作量非常大,现在还没有全部完成。为了保持与向后兼容,网络系统在初始化的时候只初始化了一个命名空间,即init_net命名空间。所有的命名空间通过list项组织起来。每个网络设备都对应有一个命名空间。命名空间下的所有网络设备通过dev_base_head组织在一起。

image

2. 网络设备

在内核中,每个网络设备都用一个net_device结构表示(~/include/linux/netdevice.h)。

   1:  struct net_device {
   2:   
   3:      /*
   4:       * This is the first field of the "visible" part of this structure
   5:       * (i.e. as seen by users in the "Space.c" file).  It is the name
   6:       * of the interface.
   7:       */
   8:      char            name[IFNAMSIZ];
   9:   
  10:      struct pm_qos_request    pm_qos_req;
  11:   
  12:      /* device name hash chain */
  13:      struct hlist_node    name_hlist;
  14:      /* snmp alias */
  15:      char             *ifalias;
  16:   
  17:      /*
  18:       *    I/O specific fields
  19:       *    FIXME: Merge these and struct ifmap into one
  20:       */
  21:      unsigned long        mem_end;    /* shared mem end    */
  22:      unsigned long        mem_start;    /* shared mem start    */
  23:      unsigned long        base_addr;    /* device I/O address    */
  24:      unsigned int        irq;        /* device IRQ number    */
  25:   
  26:      /*
  27:       *    Some hardware also needs these fields, but they are not
  28:       *    part of the usual set specified in Space.c.
  29:       */
  30:   
  31:      unsigned long        state; //和其队列规则有关的设备状态
  32:   
  33:      struct list_head    dev_list;
  34:      struct list_head    napi_list;
  35:      struct list_head    unreg_list;
  36:   
  37:      /* currently active device features */
  38:      netdev_features_t    features;
  39:      /* user-changeable features */
  40:      netdev_features_t    hw_features;
  41:      /* user-requested features */
  42:      netdev_features_t    wanted_features;
  43:      /* mask of features inheritable by VLAN devices */
  44:      netdev_features_t    vlan_features;
  45:   
  46:      /* Interface index. Unique device identifier    */
  47:      int            ifindex;
  48:      int            iflink;
  49:   
  50:      struct net_device_stats    stats;
  51:      atomic_long_t        rx_dropped; /* dropped packets by core network
  52:                           * Do not use this in drivers.
  53:                           */
  54:   
  55:  #ifdef CONFIG_WIRELESS_EXT
  56:      /* List of functions to handle Wireless Extensions (instead of ioctl).
  57:       * See <net/iw_handler.h> for details. Jean II */
  58:      const struct iw_handler_def *    wireless_handlers;
  59:      /* Instance data managed by the core of Wireless Extensions. */
  60:      struct iw_public_data *    wireless_data;
  61:  #endif
  62:      /* Management operations */
  63:      const struct net_device_ops *netdev_ops;
  64:      const struct ethtool_ops *ethtool_ops;
  65:   
  66:      /* Hardware header description */
  67:      const struct header_ops *header_ops;
  68:   
  69:      unsigned int        flags;    /* interface flags (a la BSD)    */用于存储各种标识的位域,多数标识都代表设备的能力
  70:      unsigned int        priv_flags; /* Like 'flags' but invisible to userspace. */
  71:      unsigned short        gflags;
  72:      unsigned short        padded;    /* How much padding added by alloc_netdev() */
  73:   
  74:      unsigned char        operstate; /* RFC2863 operstate */
  75:      unsigned char        link_mode; /* mapping policy to operstate */
  76:   
  77:      unsigned char        if_port;    /* Selectable AUI, TP,..*/
  78:      unsigned char        dma;        /* DMA channel        */
  79:   
  80:      unsigned int        mtu;    /* interface MTU value        */
  81:      unsigned short        type;    /* interface hardware type    */
  82:      unsigned short        hard_header_len;    /* hardware hdr length    */
  83:   
  84:      /* extra head- and tailroom the hardware may need, but not in all cases
  85:       * can this be guaranteed, especially tailroom. Some cases also use
  86:       * LL_MAX_HEADER instead to allocate the skb.
  87:       */
  88:      unsigned short        needed_headroom;
  89:      unsigned short        needed_tailroom;
  90:   
  91:      /* Interface address info. */
  92:      unsigned char        perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
  93:      unsigned char        addr_assign_type; /* hw address assignment type */
  94:      unsigned char        addr_len;    /* hardware address length    */
  95:      unsigned char        neigh_priv_len;
  96:      unsigned short          dev_id;        /* for shared network cards */
  97:   
  98:      spinlock_t        addr_list_lock;
  99:      struct netdev_hw_addr_list    uc;    /* Unicast mac addresses */
 100:      struct netdev_hw_addr_list    mc;    /* Multicast mac addresses */
 101:      bool            uc_promisc;
 102:      unsigned int        promiscuity;
 103:      unsigned int        allmulti;
 104:   
 105:   
 106:      /* Protocol specific pointers */
 107:   
 108:  #if IS_ENABLED(CONFIG_VLAN_8021Q)
 109:      struct vlan_info __rcu    *vlan_info;    /* VLAN info */
 110:  #endif
 111:  #if IS_ENABLED(CONFIG_NET_DSA)
 112:      struct dsa_switch_tree    *dsa_ptr;    /* dsa specific data */
 113:  #endif
 114:      void             *atalk_ptr;    /* AppleTalk link     */
 115:      struct in_device __rcu    *ip_ptr;    /* IPv4 specific data    */
 116:      struct dn_dev __rcu     *dn_ptr;        /* DECnet specific data */
 117:      struct inet6_dev __rcu    *ip6_ptr;       /* IPv6 specific data */
 118:      void            *ec_ptr;    /* Econet specific data    */
 119:      void            *ax25_ptr;    /* AX.25 specific data */
 120:      struct wireless_dev    *ieee80211_ptr;    /* IEEE 802.11 specific data,
 121:                             assign before registering */
 122:   
 123:  /*
 124:   * Cache lines mostly used on receive path (including eth_type_trans())
 125:   */
 126:      unsigned long        last_rx;    /* Time of last Rx
 127:                           * This should not be set in
 128:                           * drivers, unless really needed,
 129:                           * because network stack (bonding)
 130:                           * use it if/when necessary, to
 131:                           * avoid dirtying this cache line.
 132:                           */
 133:   
 134:      struct net_device    *master; /* Pointer to master device of a group,
 135:                        * which this device is member of.
 136:                        */
 137:   
 138:      /* Interface address info used in eth_type_trans() */
 139:      unsigned char        *dev_addr;    /* hw address, (before bcast
 140:                             because most packets are
 141:                             unicast) */
 142:   
 143:      struct netdev_hw_addr_list    dev_addrs; /* list of device
 144:                                hw addresses */
 145:   
 146:      unsigned char        broadcast[MAX_ADDR_LEN];    /* hw bcast add    */
 147:   
 148:  #ifdef CONFIG_SYSFS
 149:      struct kset        *queues_kset;
 150:  #endif
 151:   
 152:  #ifdef CONFIG_RPS
 153:      struct netdev_rx_queue    *_rx;
 154:   
 155:      /* Number of RX queues allocated at register_netdev() time */
 156:      unsigned int        num_rx_queues;
 157:   
 158:      /* Number of RX queues currently active in device */
 159:      unsigned int        real_num_rx_queues;
 160:   
 161:  #ifdef CONFIG_RFS_ACCEL
 162:      /* CPU reverse-mapping for RX completion interrupts, indexed
 163:       * by RX queue number.  Assigned by driver.  This must only be
 164:       * set if the ndo_rx_flow_steer operation is defined. */
 165:      struct cpu_rmap        *rx_cpu_rmap;
 166:  #endif
 167:  #endif
 168:   
 169:      rx_handler_func_t __rcu    *rx_handler;
 170:      void __rcu        *rx_handler_data;
 171:   
 172:      struct netdev_queue __rcu *ingress_queue;
 173:   
 174:  /*
 175:   * Cache lines mostly used on transmit path
 176:   */
 177:      struct netdev_queue    *_tx ____cacheline_aligned_in_smp;
 178:   
 179:      /* Number of TX queues allocated at alloc_netdev_mq() time  */
 180:      unsigned int        num_tx_queues;
 181:   
 182:      /* Number of TX queues currently active in device  */
 183:      unsigned int        real_num_tx_queues;
 184:   
 185:      /* root qdisc from userspace point of view */
 186:      struct Qdisc        *qdisc;
 187:   
 188:      unsigned long        tx_queue_len;    /* Max frames per queue allowed */
 189:      spinlock_t        tx_global_lock;
 190:   
 191:  #ifdef CONFIG_XPS
 192:      struct xps_dev_maps __rcu *xps_maps;
 193:  #endif
 194:   
 195:      /* These may be needed for future network-power-down code. */
 196:   
 197:      /*
 198:       * trans_start here is expensive for high speed devices on SMP,
 199:       * please use netdev_queue->trans_start instead.
 200:       */
 201:      unsigned long        trans_start;    /* Time (in jiffies) of last Tx    */
 202:   
 203:      int            watchdog_timeo; /* used by dev_watchdog() */
 204:      struct timer_list    watchdog_timer;
 205:   
 206:      /* Number of references to this device */
 207:      int __percpu        *pcpu_refcnt;
 208:   
 209:      /* delayed register/unregister */
 210:      struct list_head    todo_list;
 211:      /* device index hash chain */
 212:      struct hlist_node    index_hlist;
 213:   
 214:      struct list_head    link_watch_list;
 215:   
 216:      /* register/unregister state machine */
 217:      enum { NETREG_UNINITIALIZED=0,
 218:             NETREG_REGISTERED,    /* completed register_netdevice */
 219:             NETREG_UNREGISTERING,    /* called unregister_netdevice */
 220:             NETREG_UNREGISTERED,    /* completed unregister todo */
 221:             NETREG_RELEASED,        /* called free_netdev */
 222:             NETREG_DUMMY,        /* dummy device for NAPI poll */
 223:      } reg_state:8;
 224:   
 225:      bool dismantle; /* device is going do be freed */
 226:   
 227:      enum {
 228:          RTNL_LINK_INITIALIZED,
 229:          RTNL_LINK_INITIALIZING,
 230:      } rtnl_link_state:16;
 231:   
 232:      /* Called from unregister, can be used to call free_netdev */
 233:      void (*destructor)(struct net_device *dev);
 234:   
 235:  #ifdef CONFIG_NETPOLL
 236:      struct netpoll_info    *npinfo;
 237:  #endif
 238:   
 239:  #ifdef CONFIG_NET_NS
 240:      /* Network namespace this network device is inside */
 241:      struct net        *nd_net;
 242:  #endif
 243:   
 244:      /* mid-layer private */
 245:      union {
 246:          void                *ml_priv;
 247:          struct pcpu_lstats __percpu    *lstats; /* loopback stats */
 248:          struct pcpu_tstats __percpu    *tstats; /* tunnel stats */
 249:          struct pcpu_dstats __percpu    *dstats; /* dummy stats */
 250:      };
 251:      /* GARP */
 252:      struct garp_port __rcu    *garp_port;
 253:   
 254:      /* class/net/name entry */
 255:      struct device        dev;
 256:      /* space for optional device, statistics, and wireless sysfs groups */
 257:      const struct attribute_group *sysfs_groups[4];
 258:   
 259:      /* rtnetlink link ops */
 260:      const struct rtnl_link_ops *rtnl_link_ops;
 261:   
 262:      /* for setting kernel sock attribute on TCP connection setup */
 263:  #define GSO_MAX_SIZE        65536
 264:      unsigned int        gso_max_size;
 265:   
 266:  #ifdef CONFIG_DCB
 267:      /* Data Center Bridging netlink ops */
 268:      const struct dcbnl_rtnl_ops *dcbnl_ops;
 269:  #endif
 270:      u8 num_tc;
 271:      struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE];
 272:      u8 prio_tc_map[TC_BITMASK + 1];
 273:   
 274:  #if IS_ENABLED(CONFIG_FCOE)
 275:      /* max exchange id for FCoE LRO by ddp */
 276:      unsigned int        fcoe_ddp_xid;
 277:  #endif
 278:  #if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
 279:      struct netprio_map __rcu *priomap;
 280:  #endif
 281:      /* phy device may attach itself for hardware timestamping */
 282:      struct phy_device *phydev;
 283:   
 284:      /* group the device belongs to */
 285:      int group;
 286:  };
    

不得不说,这个结构实在是有些过于庞大了,内核中的注释中也说这是一个big mistake。网络协议栈中经常会出现的缩写RX和TX分别是Receive和Transmit的缩写。

网络设备的名称存储在name中。它是一个字符串,末尾的数字用于区分同一类型的多个适配器。常见的设备类别:

名称设备类别
ethX以太网适配器,无论电缆类型和传输速度如何
pppX通过调制解调器建立的PPP连接
isdnXISDN卡
atmXatm高速网卡的接口
lo换回设备

在内核中,每个网卡都有唯一索引号,在注册时动态分配保存在ifindex成员中。内核提供了dev_get_by_name和dev_get_by_index函数,用于根据网卡的名称和索引号来查找其net_device实例。

mtu指定一个传输帧的最大长度。网络层的协议也必须遵守该值的限制,可能需要将分组拆分为更小的单位(IP分组)。

type保存设备的类型,它使用的是<if_arp.h>中定义的常数。ARPHRD_ETHER和ARPHDR_IEEE802分别表示10兆以太网和802.2以太网,APRHRD_APPLETLK表示AppleTalk。

dev_addr存储设备的硬件地址,broadcast是用于向附接的所有站点发送消息的广播地址。

ip_ptr,ip6_ptr,atalk_ptr等指针指向特定协议的数据,通用代码不会操作这些数据。

netdev_ops指针指向struct net_device_ops,该结构中定义了与网卡相关的典型任务。尽管不同的网卡的实现各有不同,但调用的语法(和执行的任务)总是相同的。因而这些成员表示了与下一层协议层次的抽象接口。这些接口使得内核能够用同一组接口函数来访问所有的网卡,而网卡的驱动程序负责实现细节。

header_ops指向的结构定义了操作底层数据帧的操作,最重要的是create和parse函数。前者创建一个硬件首部,后者分析一个给定的硬件首部。

nd_net,该网络设备所属的命名空间

rmem_end,rmem_start,mem_end,mem_start,设备内存信息,保存了设备使用的共享内存之起始和终止地址。如果该设备具有不同的接受和传输内存,则mem成员用于传输内存,而rmem成员用于接收内存。

irq,被赋予的中断号。这个值通常在引导或装载阶段设置,其后可用ifconfig修改

特定于网络设备的信息,以前的文献中都说有priv指针,但是现在的代码中似乎没有该指针了。私有数据的设置和提取都是特定的函数在遵守一定的规则下隐含存在的。

3.IP 网络设备

在内核中,IP层网络设备使用struct in_device表示,struct net_device中ip_ptr指针即指向的该结构(~/include/linux/inetdevice.h)。

   1:  struct in_device {
   2:      struct net_device    *dev;
   3:      atomic_t        refcnt;
   4:      int            dead;
   5:      struct in_ifaddr    *ifa_list;    /* IP ifaddr chain        */
   6:      struct ip_mc_list __rcu    *mc_list;    /* IP multicast filter chain    */
   7:      int            mc_count;    /* Number of installed mcasts    */
   8:      spinlock_t        mc_tomb_lock;
   9:      struct ip_mc_list    *mc_tomb;
  10:      unsigned long        mr_v1_seen;
  11:      unsigned long        mr_v2_seen;
  12:      unsigned long        mr_maxdelay;
  13:      unsigned char        mr_qrv;
  14:      unsigned char        mr_gq_running;
  15:      unsigned char        mr_ifc_count;
  16:      struct timer_list    mr_gq_timer;    /* general query timer */
  17:      struct timer_list    mr_ifc_timer;    /* interface change timer */
  18:   
  19:      struct neigh_parms    *arp_parms;
  20:      struct ipv4_devconf    cnf;
  21:      struct rcu_head        rcu_head;
  22:  };

其中,ifa_list维护设备的地址列表,一个设备可能有多个地址。

由于网络命名空间的工作还远未结束,在此暂不讨论。in_device,net_device,特定设备的特化数据的关系如下图所示,具体的指针指向可能有些许不同,但意思大体如此:

QQ截图20120510123620

  • 设备无关层采用in_device()数结构保存IP地址和邻居信息
  • 网络抽象层采用net_device()数据机构保存设备的名字、编号、地址等共性
  • 设备特定层的数据则由设备驱动开发人员自己定义,一般有硬件发送、接收缓冲区、芯片寄存器的信息等等。这片内存区是紧跟在net_device{}后面,由驱动程序在创建net_device{}的时候顺带把这块内存也创建了。

网络设备的注册

每个网络设备都按照如下的过程注册。

1)alloc_netdev()分配一个新的struct net_device实例,一个特定于协议的函数用典型值填充该结构。对于以太网设备,该函数是ether_setup。其他协议会使用形如XXX_setup()的函数,其中XXX可以使fddi,tr,ltalk,hippi,fc。内核中的一些伪设备在不绑定到硬件的情况下实现了特定的接口,他们也使用了net_device框架。例如,ppp_setup根据PPP协议初始化设备。

2)在struct net_device填充完毕后,需要用register_netdev或register_netdevice注册。这两个函数的区别在于,register_netdev可以处理用作接口名称的格式串。在net_device中给出的名字可以包含格式说明符%d。在设备注册时,内核会选择一个唯一的数字来代替%d。便捷函数alloc_etherdev(sizeof_priv)分配一个struct net_device实例,外加sizeof_priv字节私有数据区。

网络设备注册实例

1.loopback(~/drivers/net/loopback.c)

   1:  /* Setup and register the loopback device. */
   2:  static __net_init int loopback_net_init(struct net *net)
   3:  {
   4:      struct net_device *dev;
   5:      int err;
   6:      long_print_int(long_count++);
   7:      //panic("long");
   8:      err = -ENOMEM;
   9:      
  10:      if (!dev)
  11:          goto out;
  12:   
  13:      
  14:      
  15:      if (err)
  16:          goto out_free_netdev;
  17:   
  18:      ;
  19:      return 0;
  20:   
  21:   
  22:  out_free_netdev:
  23:      free_netdev(dev);
  24:  out:
  25:      if (net_eq(net, &init_net))
  26:          panic("loopback: Failed to register netdevice: %d\n", err);
  27:      return err;
  28:  }
 
 
   1:  struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
   2:          void (*setup)(struct net_device *),
   3:          unsigned int txqs, unsigned int rxqs)
   4:  {
   5:      struct net_device *dev;
   6:      size_t alloc_size;
   7:      struct net_device *p;
   8:   
   9:      BUG_ON(strlen(name) >= sizeof(dev->name));
  10:   
  11:      if (txqs < 1) {
  12:          pr_err("alloc_netdev: Unable to allocate device "
  13:                 "with zero queues.\n");
  14:          return NULL;
  15:      }
  16:   
  17:  #ifdef CONFIG_RPS
  18:      if (rxqs < 1) {
  19:          pr_err("alloc_netdev: Unable to allocate device "
  20:                 "with zero RX queues.\n");
  21:          return NULL;
  22:      }
  23:  #endif
  24:   
  25:      alloc_size = sizeof(struct net_device);
  26:     
  31:      /* ensure 32-byte alignment of whole construct */
  32:      alloc_size += NETDEV_ALIGN - 1;
  33:   
  34:      p = kzalloc(alloc_size, GFP_KERNEL);
  35:      if (!p) {
  36:          printk(KERN_ERR "alloc_netdev: Unable to allocate device.\n");
  37:          return NULL;
  38:      }
  39:   
  40:      dev = PTR_ALIGN(p, NETDEV_ALIGN);
  41:      dev->padded = (char *)dev - (char *)p;
  42:   
  43:      dev->pcpu_refcnt = alloc_percpu(int);
  44:      if (!dev->pcpu_refcnt)
  45:          goto free_p;
  46:   
  47:      if (dev_addr_init(dev))
  48:          goto free_pcpu;
  49:   
  50:      dev_mc_init(dev);
  51:      dev_uc_init(dev);
  52:   
  53:      
  54:   
  55:      dev->gso_max_size = GSO_MAX_SIZE;
  56:   
  57:      INIT_LIST_HEAD(&dev->napi_list);
  58:      INIT_LIST_HEAD(&dev->unreg_list);
  59:      INIT_LIST_HEAD(&dev->link_watch_list);
  60:      dev->priv_flags = IFF_XMIT_DST_RELEASE;
  61:      setup(dev);
  62:   
  63:      dev->num_tx_queues = txqs;
  64:      dev->real_num_tx_queues = txqs;
  65:      if (netif_alloc_netdev_queues(dev))
  66:          goto free_all;
  67:   
  68:  #ifdef CONFIG_RPS
  69:      dev->num_rx_queues = rxqs;
  70:      dev->real_num_rx_queues = rxqs;
  71:      if (netif_alloc_rx_queues(dev))
  72:          goto free_all;
  73:  #endif
  74:   
  75:      strcpy(dev->name, name);
  76:      dev->group = INIT_NETDEV_GROUP;
  77:      return dev;
  78:   
  79:  free_all:
  80:      free_netdev(dev);
  81:      return NULL;
  82:   
  83:  free_pcpu:
  84:      free_percpu(dev->pcpu_refcnt);
  85:      kfree(dev->_tx);
  86:  #ifdef CONFIG_RPS
  87:      kfree(dev->_rx);
  88:  #endif
  89:   
  90:  free_p:
  91:      kfree(p);
  92:      return NULL;

93: }

 

 

   1:  int register_netdevice(struct net_device *dev)
   2:  {
   3:      int ret;
   4:      struct net *net = dev_net(dev);
   5:   
   6:      BUG_ON(dev_boot_phase);
   7:      ASSERT_RTNL();
   8:   
   9:      might_sleep();
  10:   
  11:      /* When net_device's are persistent, this will be fatal. */
  12:      BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
  13:      BUG_ON(!net);
  14:   
  15:      spin_lock_init(&dev->addr_list_lock);
  16:      netdev_set_addr_lockdep_class(dev);
  17:   
  18:      dev->iflink = -1;
  19:   
  20:      ret = dev_get_valid_name(dev, dev->name);
  21:      if (ret < 0)
  22:          goto out;
  23:   
  24:      /* Init, if this function is available */
  25:      if () {
  26:          ret = dev->netdev_ops->ndo_init(dev);
  27:          if (ret) {
  28:              if (ret > 0)
  29:                  ret = -EIO;
  30:              goto out;
  31:          }
  32:      }
  33:   
  34:     
  35:      if (dev->iflink == -1)
  36:          dev->iflink = dev->ifindex;
  37:   
  38:      /* Transfer changeable features to wanted_features and enable
  39:       * software offloads (GSO and GRO).
  40:       */
  41:      dev->hw_features |= NETIF_F_SOFT_FEATURES;
  42:      dev->features |= NETIF_F_SOFT_FEATURES;
  43:      dev->wanted_features = dev->features & dev->hw_features;
  44:   
  45:      /* Turn on no cache copy if HW is doing checksum */
  46:      if (!(dev->flags & IFF_LOOPBACK)) {
  47:          dev->hw_features |= NETIF_F_NOCACHE_COPY;
  48:          if (dev->features & NETIF_F_ALL_CSUM) {
  49:              dev->wanted_features |= NETIF_F_NOCACHE_COPY;
  50:              dev->features |= NETIF_F_NOCACHE_COPY;
  51:          }
  52:      }
  53:   
  54:      /* Make NETIF_F_HIGHDMA inheritable to VLAN devices.
  55:       */
  56:      dev->vlan_features |= NETIF_F_HIGHDMA;
  57:   
  58:      
  60:      if (ret)
  61:          goto err_uninit;
  62:   
  63:      ret = netdev_register_kobject(dev);
  64:      if (ret)
  65:          goto err_uninit;
  66:      dev->reg_state = NETREG_REGISTERED;
  67:   
  68:      __netdev_update_features(dev);
  69:   
  70:      /*
  71:       *    Default initial state at registry is that the
  72:       *    device is present.
  73:       */
  74:   
  75:      set_bit(__LINK_STATE_PRESENT, &dev->state);
  76:   
  77:      dev_init_scheduler(dev);
  78:      dev_hold(dev);
  79:      list_netdevice(dev);
  80:   
  81:      /* Notify protocols, that a new device appeared. */
  82:      ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
  83:      ret = notifier_to_errno(ret);
  84:      if (ret) {
  85:          rollback_registered(dev);
  86:          dev->reg_state = NETREG_UNREGISTERED;
  87:      }
  88:      /*
  89:       *    Prevent userspace races by waiting until the network
  90:       *    device is fully setup before sending notifications.
  91:       */
  92:      if (!dev->rtnl_link_ops ||
  93:          dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
  94:          rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
  95:   
  96:  out:
  97:      return ret;
  98:   
  99:  err_uninit:
 100:      if (dev->netdev_ops->ndo_uninit)
 101:          dev->netdev_ops->ndo_uninit(dev);
 102:      goto out;
 103:  }

转载于:https://my.oschina.net/longscu/blog/56940

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值