net_device 结构


一.动态分配net_device结构
alloc_netdev()
函数生成一个net_device结构体,对其成员赋值并返回该结构体的指针。第一个参数是设备私有成员的大小,第二个参数为设备名,第三个参数为net_device的setup()函数指针。setup()函数接收的参数为struct net_device指针,用于预置net_device成员的值。


linux-2.6.22/net/core/dev.c
----------------------------------------
struct net_device *alloc_netdev(int sizeof_priv, const char *name,
                void (*setup)(struct net_device *))
{
        void *p;
        struct net_device *dev;
        int alloc_size;

        BUG_ON(strlen(name) >= sizeof(dev->name));

        /* ensure 32-byte alignment of both the device and private area */
        alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
        alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;

        p = kzalloc(alloc_size, GFP_KERNEL);
        if (!p) {
                printk(KERN_ERR "alloc_netdev: Unable to allocate device.\n");
                return NULL;
        }

        dev = (struct net_device *)
                (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
        dev->padded = (char *)dev - (char *)p;

        if (sizeof_priv)
                dev->priv = netdev_priv(dev);

        dev->get_stats = internal_stats;
        setup(dev);
        strcpy(dev->name, name);
        return dev;
}
alloc_etherdev()是alloc_netdev()针对以太网的"快捷"函数

linux-2.6.22/net/ethernet/eth.c
----------------------------------------
struct net_device *alloc_etherdev(int sizeof_priv)
{
----returnalloc_netdev(sizeof_priv, "eth%d",ether_setup);
}


          net_device
+--------------+
|              |
|--------------|
|  base_addr   |
|--------------|
|              |
|              |
|--------------|
|  priv        |---+
|--------------|   |
|              |   |
|              |   |
+--------------+<--+
|              |
|              | sizeof_priv
|              |
+--------------+


net_device->base_addr  网络寄存器的基地址(物理地址)

二.net_device数据结构

在Linux系统中,网络设备都被抽象为struct net_device结构体。它是网络设备硬件与上层协议之间联系的接口。结构包括了虚拟网络设备和实际网络设备。该数据结构比较复杂,主要任务分为两部分:第一对上层协议屏蔽底层设备的区别,提供统一的操作接口。第二对下层设备,提供实际驱动方法。  结构在linux-2.6.38.8/include/linux/netdevice.h

struct net_device
{

 
 char   name[IFNAMSIZ];不必多说,就是ifconfig 后面的第一个参数
 
 structhlist_node name_hlist;

 
 unsignedlong  mem_end; 
 unsignedlong  mem_start; 
 unsignedlong  base_addr; 
 unsignedint  irq;  

 

 unsignedchar  if_port; 
 unsignedchar  dma;  

 unsignedlong  state;

 structlist_head dev_list; 做什么用呢?估计是内核维护
 
 
 int   (*init)(structnet_device *dev);

 

 
 unsignedlong  features;
#defineNETIF_F_SG  
#defineNETIF_F_IP_CSUM  
#defineNETIF_F_NO_CSUM  
#defineNETIF_F_HW_CSUM  
#defineNETIF_F_HIGHDMA  32 
#defineNETIF_F_FRAGLIST 64 
#defineNETIF_F_HW_VLAN_TX 128 
#defineNETIF_F_HW_VLAN_RX 256 
#defineNETIF_F_HW_VLAN_FILTER 512 
#defineNETIF_F_VLAN_CHALLENGED 1024 
#defineNETIF_F_GSO  2048 
#defineNETIF_F_LLTX  4096 

 
#define NETIF_F_GSO_SHIFT 16
#define NETIF_F_GSO_MASK 0xffff0000
#defineNETIF_F_TSO  (SKB_GSO_TCPV4<< NETIF_F_GSO_SHIFT)
#define NETIF_F_UFO  (SKB_GSO_UDP<< NETIF_F_GSO_SHIFT)
#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY<< NETIF_F_GSO_SHIFT)
#defineNETIF_F_TSO_ECN  (SKB_GSO_TCP_ECN<< NETIF_F_GSO_SHIFT)
#defineNETIF_F_TSO6  (SKB_GSO_TCPV6<< NETIF_F_GSO_SHIFT)

 
#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO |NETIF_F_TSO_ECN | NETIF_F_TSO6)

#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM |NETIF_F_HW_CSUM)
#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM |NETIF_F_GEN_CSUM)

 structnet_device *next_sched;

 
 int   ifindex;
 int   iflink;


 structnet_device_stats* (*get_stats)(struct net_device *dev);
 structnet_device_stats stats; 网卡发送包的个数等等,ifconfigeth0看到的东西就是啦

#ifdef CONFIG_WIRELESS_EXT
 
 const struct iw_handler_def* wireless_handlers;
 
 struct iw_public_data* wireless_data;
#endif
 const structethtool_ops *ethtool_ops;

 


 unsignedint  flags; 
 unsignedshort  gflags;
       unsignedshort         priv_flags;
 unsignedshort  padded; 

 unsignedchar  operstate;
 unsignedchar  link_mode;

 unsigned  mtu; 
 unsignedshort  type; 
 unsignedshort  hard_header_len; 

 structnet_device *master;

 
 unsignedchar  perm_addr[MAX_ADDR_LEN];
 unsignedchar  addr_len; 
 unsignedshort         dev_id;  

 structdev_mc_list *mc_list; 
 int   mc_count; 
 int   promiscuity;
 int   allmulti;


 
 
 void   *atalk_ptr; 
 void   *ip_ptr;  
 void                   *dn_ptr;       
 void                   *ip6_ptr;      
 void   *ec_ptr; 
 void   *ax25_ptr; 
 structwireless_dev *ieee80211_ptr; 


 struct list_head poll_list____cacheline_aligned_in_smp;
     

 int   (*poll)(struct net_device *dev, int *quota);
 int   quota;
 int   weight;
 unsignedlong  last_rx; 
 
 unsignedchar  dev_addr[MAX_ADDR_LEN]; 

 unsignedchar  broadcast[MAX_ADDR_LEN]; 


 
 spinlock_t  queue_lock____cacheline_aligned_in_smp;
 structQdisc  *qdisc;
 structQdisc  *qdisc_sleeping;
 structlist_head qdisc_list;
 unsignedlong  tx_queue_len; 

 
 structsk_buff  *gso_skb;

 
 spinlock_t  ingress_lock;
 structQdisc  *qdisc_ingress;


 
 spinlock_t  _xmit_lock____cacheline_aligned_in_smp;
 
 int   xmit_lock_owner;
 void   *priv; 
 int   (*hard_start_xmit)(struct sk_buff *skb,
         struct net_device*dev);
 
 unsignedlong  trans_start; 

 int   watchdog_timeo;
 structtimer_list watchdog_timer;


 
 atomic_t  refcnt____cacheline_aligned_in_smp;

 
 structlist_head todo_list;
 
 structhlist_node index_hlist;

 structnet_device *link_watch_next;

 
 enum { NETREG_UNINITIALIZED=0,
       NETREG_REGISTERED, 
       NETREG_UNREGISTERING, 
       NETREG_UNREGISTERED, 
       NETREG_RELEASED,  
 } reg_state;

 
 void   (*uninit)(structnet_device *dev);
 
 void   (*destructor)(structnet_device *dev);

 
 int   (*open)(structnet_device *dev);
 int   (*stop)(structnet_device *dev);
#defineHAVE_NETDEV_POLL
 int   (*hard_header)(struct sk_buff *skb,
      structnet_device *dev,
      unsignedshort type,
      void*daddr,
      void*saddr,
      unsignedlen);
 int   (*rebuild_header)(structsk_buff *skb);
#defineHAVE_MULTICAST   
 void   (*set_multicast_list)(structnet_device *dev);
#defineHAVE_SET_MAC_ADDR   
 int   (*set_mac_address)(structnet_device *dev,
        void *addr);
#define HAVE_PRIVATE_IOCTL
 int   (*do_ioctl)(structnet_device *dev,
        struct ifreq *ifr, int cmd);
#defineHAVE_SET_CONFIG
 int   (*set_config)(structnet_device *dev,
          struct ifmap *map);
#defineHAVE_HEADER_CACHE
 int   (*hard_header_cache)(structneighbour *neigh,
          struct hh_cache *hh);
 void   (*header_cache_update)(structhh_cache *hh,
            struct net_device *dev,
            unsigned char *  haddr);
#define HAVE_CHANGE_MTU
 int   (*change_mtu)(structnet_device *dev, int new_mtu);

#define HAVE_TX_TIMEOUT
 void   (*tx_timeout)(struct net_device *dev);

 void   (*vlan_rx_register)(structnet_device *dev,
         struct vlan_group *grp);
 void   (*vlan_rx_add_vid)(structnet_device *dev,
        unsigned short vid);
 void   (*vlan_rx_kill_vid)(structnet_device *dev,
         unsigned short vid);

 int   (*hard_header_parse)(structsk_buff *skb,
          unsigned char *haddr);
 int   (*neigh_setup)(structnet_device *dev, struct neigh_parms *);
#ifdef CONFIG_NETPOLL
 structnetpoll_info *npinfo;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
 void                   (*poll_controller)(struct net_device *dev);
#endif

 
 structnet_bridge_port *br_port;

 

  structdevice    dev;
 
  struct attribute_group  *sysfs_groups[3];
};

红色是基本字段
蓝色是fops相关
绿色是ethtool支持用

struct header_ops {
 int (*create) (struct sk_buff*skb, struct net_device *dev,
     unsigned short type, const void *daddr,
     const void *saddr, unsignedlen);  //创建一个新的硬件首部
 int (*parse)(const structsk_buff *skb, unsigned char *haddr);//分析一个给定的硬件首部
 int (*rebuild)(structsk_buff *skb);
#define HAVE_HEADER_CACHE
 int (*cache)(const structneighbour *neigh, struct hh_cache *hh);
 void (*cache_update)(structhh_cache *hh,
    conststruct net_device *dev,
    constunsigned char *haddr);
};
enum netdev_queue_state_t
{
 __QUEUE_STATE_XOFF, 
 __QUEUE_STATE_FROZEN,
};

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

struct netdev_queue{ //网络设备多队列相关东西,之前在“网卡多队列”的测试中碰到过,老的内核就一个接受队列和一个发生队列,新内核有多个发生队列和多个接受队列,这些dmesg和cat /proc/interrupts可以看到是否启用网卡多队列的,内核新特征

有篇写到

unsigned long state;
设备状态
__LINK_STATE_XOFF 0 Device queue turned off.
__LINK_STATE_START 1 Device queue turned on.
__LINK_STATE_PRESENT 2 Device ready to be scheduled.
__LINK_STATE_SCHED 3
__LINK_STATE_NOCARRIER 4
__LINK_STATE_RX_SCHED 5 Device placed on poll list.
__LINK_STATE_LINKWATCH_PENDING 6
这个在我这个内核差不多,只是少了几条对应的,不过多队列还是有的 



 struct net_device *dev;
 structQdisc  *qdisc;
 unsignedlong  state;
 structQdisc  *qdisc_sleeping;

 spinlock_t  _xmit_lock____cacheline_aligned_in_smp;
 int   xmit_lock_owner;
 
 unsignedlong  trans_start;
 unsignedlong  tx_bytes;
 unsignedlong  tx_packets;
 unsignedlong  tx_dropped;
} ____cacheline_aligned_in_smp;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值