专栏首页相遇LinuxLinux网络收包流程

Linux网络收包流程

关于linux网络包的收发流程,网上随便一搜都可以搜一桶,但自己不动手永远都搞不原理。最近在家比较闲,对网络这一块也不太了解,老婆在看《三生三世枕上书》,我只能看下代码打发下时间。

小编习惯熟悉内核子系统原理从低版本内核开始.

Linux(2.6.11.12)网络收包流程图:

  device driver interrupt handler
       netif_rx()
              cpu_raise_softirq()
                     do_softirq()
net_rx_atcion()
      dev->poll(dev, &budget)( process_backlog)(注0)

      process_backlog()
   netif_receive_skb()
       skb_bond(skb); 如果网卡绑定,则取netdev 的master设备
       pt_prev->func() (注1)
       type = skb->protocol(L3层 ipv4 or ipv6 ..)
          ip_rcv()
             NF_HOOK(PF_INET,NF_IP_PRE_ROUTING,skb, dev, NULL,ip_rcv_finish);
               ip_rcv_finish()
                   dst_input()
                     skb->dst->input();(注2)
                        (ip_local_deliver或ip_forward)
                           ip_local_deliver()
                              NF_HOOK(PF_INET,NF_IP_LOCAL_IN, skb, skb->dev, NULL,
                                ip_local_deliver_finish);
                                    ip_local_deliver_finish()
                                        ipprot->handler(skb);
                                        (L4层 udp_rcv/tcp_v4_rcv..)
                                         udp_rcv()
                                           udp_queue_rcv_skb()
                                              sock_queue_rcv_skb
                                               sk->sk_data_ready()                   (sock_def_readable)

                                                             
static void sock_def_readable(structsock *sk, int len)

{

       read_lock(&sk->sk_callback_lock);
       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
               wake_up_interruptible(sk->sk_sleep);
       sk_wake_async(sk,1,POLL_IN);
       read_unlock(&sk->sk_callback_lock);
}

                                                                     
sys_recvfrom()
       sock_recvmsg()
              sock->ops->recvmsg()(sock_common_recvmsg)
              sock_common_recvmsg()
                     sk->sk_prot->recvmsg()(udp_recvmsg)
                     udp_recvmsg()
                            skb_recv_datagram()
                                   wait_for_packet()
   
static int wait_for_packet(structsock *sk, int *err, long *timeo_p)
{
…
  DEFINE_WAIT(wait);
  prepare_to_wait_exclusive(sk->sk_sleep,&wait,TASK_INTERRUPTIBLE);
…
}
注0:
net_dev_init()
{
  …
  queue->backlog_dev.poll = process_backlog;
  …
}
注1:
void __init ip_init(void)
{
  dev_add_pack(&ip_packet_type);
}
static struct packet_type ip_packet_type = {
        .type = __constant_htons(ETH_P_IP),
        .func = ip_rcv,
};
void __init ipv6_packet_init(void)
{
        dev_add_pack(&ipv6_packet_type);
}

static struct packet_type ipv6_packet_type = {
        .type = __constant_htons(ETH_P_IPV6),
        .func = ipv6_rcv,
};

void dev_add_pack(struct packet_type *pt)
{
  …
  list_add_rcu(&pt->list, &ptype_base[hash]);
 …
}

注2:
ip_rcv_finish
  ip_route_input
    ip_route_input_slow
ip_route_input_slow()
{
  …
  rth->u.dst.input = ip_forward;
  …
  rth->u.dst.input= ip_local_deliver;
}

参考:

1.《understanding the linux kernel》

2. 谢宝友Linux kernel 2.6.11.12源码注释

本文分享自微信公众号 - 相遇Linux(LinuxJeff),作者:JeffXie

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-02-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux网络发包流程

    首先网卡驱动申请一个著名的数据结构sk_buffer,根据数据包中的网络类型 type = skb->protocol(L3层 ipv4 or ipv6 .....

    jeff xie
  • qemu联网解决方案

    bridge和tap设备在linux中都属于网络虚拟设备,因为数据包经过网络协议栈通过物理网卡发送和接收同样也能也能从软件层面上代替物理网卡,经过网络协议栈进行...

    jeff xie
  • qemu联网解决方案

    bridge和tap设备在linux中都属于网络虚拟设备,因为数据包经过网络协议栈通过物理网卡发送和接收同样也能也能从软件层面上代替物理网卡,经过网络协议栈进行...

    jeff xie
  • 烽火2640路由器命令行手册-06-组播协议配置命令

    如果希望对组播报文的处理流程进行跟踪,可使用debug ip mpacket命令。使用此命令的no形式关掉debug信息。

    landv
  • 聊聊nacos的HealthCheckCommon

    nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/HealthChec...

    codecraft
  • 聊聊nacos的HealthCheckCommon

    nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/healthcheck/HealthChec...

    codecraft
  • Python CIDR地址块算法

    最近写扫描器有个模块需要把CIDR地址块(类似与192.168.1.1/24)之类的地址解析成IP地址。

    V站CEO-西顾
  • SpringBoot自定义拦截器实现IP白名单功能

    上帝
  • 用Python爬虫抓取免费代理IP

    -- Illustrations by Ash Thorp & Maciej Kuciara --

    Python中文社区
  • SpringBoot自定义拦截器实现IP白名单功能

    转载请注明源地址:http://www.cnblogs.com/funnyzpc/p/8993331.html

    上帝

扫码关注云+社区

领取腾讯云代金券