Chinaunix首页 | 论坛 | 博客
  • 博客访问: 972024
  • 博文数量: 58
  • 博客积分: 10192
  • 博客等级: 上将
  • 技术积分: 1845
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-22 21:24
文章分类

全部博文(58)

文章存档

2011年(11)

2010年(12)

2009年(20)

2008年(15)

分类: LINUX

2010-08-11 11:51:53

Kernel version : Kernel-2.6.11

 

  每种网络协议都有一个初始化函数。静态包含在内核中的协议而言,初始化函数会在引导期间执行;就编译成模块的协议而言,当模块被加载时,初始化函数就会执行。初始化函数有一个重要的任务就是在内核里注册一个处理函数,以处理该协议的流量。

 

  看一下IP协议的初始化函数ip_init():

  static struct packet_type ip_packet_type = {

    .type = __constant_htons(ETH_P_IP),

    .func = ip_rcv,

  };

 

  void __int ip_init(void)

  {

    dev_add_pack(&ip_packet_type);

    ...

  }

 

  ip_init函数会在引导期间执行,并通过调用dev_add_pack函数把IP协议的ip_packet_type放入全局变量ptype_base所指的数组里。ip_packet_type是一个packet_type类型,type代表协议代码,func代表当type=ETH_P_IP时,就调用ip_rcv这个处理函数。 

  ptype_base是一个由16个列表组成的数组。当ip_init调用dev_add_pack函数注册时,它就会对协议类型进行hash函数,然后把packet_type结构放入16列表的其中一个。 

 

  看一下dev_add_pack函数:

void dev_add_pack(struct packet_type *pt)

{

    int hash;

 

    spin_lock_bh(&ptype_lock);

    if (pt->type == htons(ETH_P_ALL)) {

        netdev_nit++;

        list_add_rcu(&pt->list, &ptype_all);

    } else {

        hash = ntohs(pt->type) & 15;

        list_add_rcu(&pt->list, &ptype_base[hash]);

    }

    spin_unlock_bh(&ptype_lock);

}

 

如果pt->typeETH_P_ALL,新增的处理函数为协议嗅探器,并添加到全局变量ptype_all里。pt->type不是ETH_P_ALL,得到一个hash值,并添加到全局变量ptype_base[hash]里。

 

当设备驱动程序接受到数据帧时,就会保存在一个skb_buff缓冲区数据结构里,然后对其成员protocol进行初始化。然后系统调用netif_receive_skb函数根据protocol值进行查询,确定把入口帧分派给正确的协议处理函数。当协议没有处理函数时,该帧就会被丢弃。

 

 

参考:LINUX网络技术内幕第十三章

 

阅读(1240) | 评论(0) | 转发(0) |
0

上一篇:IP选项

下一篇:what's pdflush process?

给主人留下些什么吧!~~