科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Linux内核如何接收不同类型以太帧 (3)

Linux内核如何接收不同类型以太帧 (3)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

由于IP协议部分不能作为内核模块,所以是没有卸载函数的,没必要调用dev_remove_pack()函数。

作者:赛迪网技术社区 来源:赛迪网技术社区 2007年10月26日

关键字: 接收 内核 Linux

  • 评论
  • 分享微博
  • 分享邮件

由于IP协议部分不能作为内核模块,所以是没有卸载函数的,没必要调用dev_remove_pack()函数。

4.2 8021q vlan

/* net/8021q/vlan.c */
static struct packet_type vlan_packet_type = {
.type = __constant_htons(ETH_P_8021Q),
.func = vlan_skb_recv, /* VLAN receive method */
};
......
static int __init vlan_proto_init(void)
{
......
dev_add_pack(&vlan_packet_type);
......

static void __exit vlan_cleanup_module(void)
{
......
dev_remove_pack(&vlan_packet_type);
......

由于VLAN可为模块方式存在,所以在模块清除函数中要调用dev_remove_pack()。

5. 网络接收

网卡驱动收到数据包构造出skb后,通过接口函数netif_receive_skb()传递到上层进行协议处理分配。

/* net/core/dev.c */
int netif_receive_skb(struct sk_buff *skb)
{
......
// 先查处理所有以太类型的链表各节点
list_for_each_entry_rcu(ptype, &ptype_all, list) {
if (!ptype->dev || ptype->dev == skb->dev) {
if (pt_prev) 
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
}
......
// 再查指定协议的HASH链表
list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
if (ptype->type == type &&
(!ptype->dev || ptype->dev == skb->dev)) {
if (pt_prev) 
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
}
......

// 该函数就是调用个协议的接收函数处理该skb包,进入第三层网络层处理
static __inline__ int deliver_skb(struct sk_buff *skb,
struct packet_type *pt_prev,
struct net_device *orig_dev)
{
atomic_inc(&skb->users);
return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
}

6. 结论

通过链表挂接方式,Linux内核可以很容易的添加各种协议的接收处理函数。

数据流程:

网卡驱动--->netif_rx()--->netif_receive_skb()->deliver_skb()->packet_type.func

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章