Linux内核--网络栈实现分析(三)--驱动程序层+链路层(上)

发表于:2012-12-25 10:06

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:闫明    来源:51Testing软件测试网采编

  注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”(上)“表示分析是从底层向上分析、”(下)“表示分析是从上向下分析。

  经过前面两篇博文的分析,已经对Linux的内核网络栈的结构有了一个模糊的认识,这里我们开始从底层开始详细分析Linux内核网络栈的实现。由于这是早期版本,代码的层次隔离做的还不是很好,这里说是从底层分析,但是不免会牵扯上层或下层的函数,许多关键代码都在驱动的文件夹下。

  我们首先有第一篇博文中知道在网络栈初始化的时候在net/socket.c中的函数sock_init()函数中当proto_init()完成后会执行dev_init()来进行网络设备模块的初始化。

  首先说明一下,在drivers/net/space.c中定义了设备首节点地址dev_base,其实际上是回环设备的地址。

struct device loopback_dev = {
 "lo",   /* Software Loopback interface  */
 0x0,   /* recv memory end   */
 0x0,   /* recv memory start   */
 0x0,   /* memory end    */
 0x0,   /* memory start    */
 0,   /* base I/O address   */
 0,   /* IRQ     */
 0, 0, 0,  /* flags    */
 NEXT_DEV,  /* next device    */
 loopback_init  /* loopback_init should set up the rest */
};

struct device *dev_base = &loopback_dev;

  而NEXT_DEV宏定义即定义了下一个网络设备的地址,这样可以把设备串成链。

  附网络设备的定义(include/linux/netdevice.h)如下:

/*
 * The DEVICE structure.
 * Actually, this whole structure is a big mistake.  It mixes I/O
 * data with strictly "high-level" data, and it has to know about
 * almost every data structure used in the INET module. 
 */
struct device
{

  /*
   * This is the first field of the "visible" part of this structure
   * (i.e. as seen by users in the "Space.c" file).  It is the name
   * the interface.
   */
  char     *name;

  /* I/O specific fields - FIXME: Merge these and struct ifmap into one */
  unsigned long    rmem_end;  /* shmem "recv" end */
  unsigned long    rmem_start;  /* shmem "recv" start */
  unsigned long    mem_end;  /* sahared mem end */
  unsigned long    mem_start;  /* shared mem start */
  unsigned long    base_addr;  /* device I/O address */
  unsigned char    irq;   /* device IRQ number */

  /* Low-level status flags. */
  volatile unsigned char  start,  /* start an operation */
                          tbusy,  /* transmitter busy */
                          interrupt;  /* interrupt arrived */

  struct device    *next;

  /* The device initialization function. Called only once. */
  int     (*init)(struct device *dev);

  /* Some hardware also needs these fields, but they are not part of the
     usual set specified in Space.c. */
  unsigned char    if_port;  /* Selectable AUI, TP,..*/
  unsigned char    dma;   /* DMA channel  */

  struct enet_statistics* (*get_stats)(struct device *dev);

  /*
   * This marks the end of the "visible" part of the structure. All
   * fields hereafter are internal to the system, and may change at
   * will (read: may be cleaned up at will).
   */

  /* These may be needed for future network-power-down code. */
  unsigned long    trans_start; /* Time (in jiffies) of last Tx */
  unsigned long    last_rx; /* Time of last Rx  */

  unsigned short   flags; /* interface flags (a la BSD) */
  unsigned short   family; /* address family ID (AF_INET) */
  unsigned short   metric; /* routing metric (not used) */
  unsigned short   mtu;  /* interface MTU value  */
  unsigned short   type;  /* interface hardware type */
  unsigned short   hard_header_len; /* hardware hdr length */
  void     *priv; /* pointer to private data */

  /* Interface address info. */
  unsigned char    broadcast[MAX_ADDR_LEN]; /* hw bcast add */
  unsigned char    dev_addr[MAX_ADDR_LEN]; /* hw address */
  unsigned char    addr_len; /* hardware address length */
  unsigned long    pa_addr; /* protocol address  */
  unsigned long    pa_brdaddr; /* protocol broadcast addr */
  unsigned long    pa_dstaddr; /* protocol P-P other side addr */
  unsigned long    pa_mask; /* protocol netmask  */
  unsigned short   pa_alen; /* protocol address length */

  struct dev_mc_list  *mc_list; /* Multicast mac addresses */
  int    mc_count; /* Number of installed mcasts */
 
  struct ip_mc_list  *ip_mc_list; /* IP multicast filter chain    */
   
  /* For load balancing driver pair support */
 
  unsigned long     pkt_queue; /* Packets queued */
  struct device    *slave; /* Slave device */
 

  /* Pointer to the interface buffers. */
  struct sk_buff_head   buffs[DEV_NUMBUFFS];

  /* Pointers to interface service routines. */
  int     (*open)(struct device *dev);
  int     (*stop)(struct device *dev);
  int     (*hard_start_xmit) (struct sk_buff *skb,
           struct device *dev);
  int     (*hard_header) (unsigned char *buff,
       struct device *dev,
       unsigned short type,
       void *daddr,
       void *saddr,
       unsigned len,
       struct sk_buff *skb);
  int     (*rebuild_header)(void *eth, struct device *dev,
    unsigned long raddr, struct sk_buff *skb);
  unsigned short   (*type_trans) (struct sk_buff *skb,
      struct device *dev);
#define HAVE_MULTICAST   
  void     (*set_multicast_list)(struct device *dev,
        int num_addrs, void *addrs);
#define HAVE_SET_MAC_ADDR    
  int     (*set_mac_address)(struct device *dev, void *addr);
#define HAVE_PRIVATE_IOCTL
  int     (*do_ioctl)(struct device *dev, struct ifreq *ifr, int cmd);
#define HAVE_SET_CONFIG
  int     (*set_config)(struct device *dev, struct ifmap *map);
 
};

61/6123456>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号