Linux内核网络发包过程函数调用分析(linux网络内核分析与开发)

网友投稿 613 2022-10-11


Linux内核网络发包过程函数调用分析(linux网络内核分析与开发)

Linux内核网络发包过程函数调用分析

应用通过socket将数据包送入协议中处理 在协议栈中从传输层发送到网络层,最后发送给邻居子系统 邻居子系统将数据包转化为arp或者调用网络设备层函数将数据包发到下层驱动 驱动完成数据最后的发送,并发送硬中断信号给cpu cpu简单处理后发出RX软中断完成数据包的释放

本文以Intel igb网卡驱动为例说明发包过程:

网卡驱动注册硬中断处理函数

网卡驱动注册中断处理函数igb_msix_ring()。

igb_open() - drivers/net/ethernet/intel/igb/igb_main.c igb_request_irq - drivers/net/ethernet/intel/igb/igb_main.c igb_request_msix - drivers/net/ethernet/intel/igb/igb_main.c igb_msix_ring() - drivers/net/ethernet/intel/igb/igb_main.c

系统启动时注册软中断处理函数

NET_TX_SOFTIRQ的软中断处理函数为net_tx_action()。

subsys_initcall(net_dev_init) - net/core/dev.c net_dev_init() - net/core/dev.c open_softirq(NET_TX_SOFTIRQ, net_tx_action) - net/core/dev.c

系统启动时注册协议栈处理函数

系统启动时,注册ipv4对应的发送函数inet_sendmsg(),注册各个传输层协议对应的发送函数udp_prot()、tcp_prot()、ping_prot()、raw_prot()等。同时注册arp output()函数。

fs_initcall(inet_init) - net/ipv4/af_inet.c inet_init() - net/ipv4/af_inet.c inet_register_protosw() - net/ipv4/af_inet.c arp_init() - net/ipv4/arp.c neigh_table_init() - net/ipv4/arp.c

socket sendto系统调用

应用程序通过socket调用sendto系统调用发送数据包,根据网络层协议调用inet_sendmsg或者inet6_sendmsg()函数,将数据包送入协议栈发送。

SYSCALL_DEFINE6(sendto...) - net/socket.c sock_sendmsg() - net/socket.c sock_sendmsg_nosec() - net/socket.c int ret = INDIRECT_CALL_INET(sock->ops->sendmsg, inet6_sendmsg, inet_sendmsg, sock, msg, msg_data_left(msg))

协议栈处理函数-L4

协议栈根据传输层协议调用对应的处理函数。这里以udp协议为例说明传输层发送过程。最后根据网络层协议,调用ip_output()、ip6_output()等将数据包发送到网络层处理。

inet_sendmsg() - net/ipv4/af_inet.c return INDIRECT_CALL_2(sk->sk_prot->sendmsg, tcp_sendmsg, udp_sendmsg, sk, msg, size) udp_sendmsg() - net/ipv4/udp.c udp_send_skb() - net/ipv4/udp.c ip_send_skb() - net/ipv4/ip_output.c ip_local_out() - net/ipv4/ip_output.c ip_local_out() - net/ipv4/ip_output.c dst_output() - net/dst.h return INDIRECT_CALL_INET(skb_dst(skb)->output, ip6_output, ip_output, net, sk, skb);

协议栈处理函数-L3

网络层处理后,调用neigh_output()函数将数据包送入邻居子系统发送或者转化为arp。

ip_output() - net/ipv4/ip_output.c ip_finish_output() - net/ipv4/ip_output.c __ip_finish_output() - net/ipv4/ip_output.c ip_finish_output_gso() - net/ipv4/ip_output.c ip_finish_output2() - net/ipv4/ip_output.c neigh_output() - net/neighbor.h

邻居子系统处理函数

neigh_output() - net/neighbor.h return n->output(n, skb) - net/neighbor.h neigh_hh_output() - net/neighbor.h dev_queue_xmit() - net/core/dev.c

网络设备层处理函数

网络设备层调用驱动注册的ndo_start_xmit()函数发送数据包到驱动。以igb驱动为例,ndo_start_xmit()即igb_xmit_frame()函数。

dev_queue_xmit() - net/core/dev.c __dev_queue_xmit() - net/core/dev.c dev_hard_start_xmit() - net/core/dev.c xmit_one() - net/core/dev.c netdev_start_xmit() - include/linux/netdevice.h __netdev_start_xmit() - include/linux/netdevice.h return ops->ndo_start_xmit(skb, dev)

驱动程序处理函数

网卡驱动完成最后的数据包发送过程。

igb_xmit_frame() - drivers/net/ethernet/intel/igb/igb_main.c igb_xmit_frame_ring() - drivers/net/ethernet/intel/igb/igb_main.c igb_tx_map() - drivers/net/ethernet/intel/igb/igb_main.c

数据包内存释放函数

网卡发送完数据包后,会给cpu发送一个硬中断通知cpu,cpu简单处理后,发出软中断NET_RX_SOFTIRQ。最后的中断处理函数net_rx_action()中完成数据包的释放。

硬中断处理函数:

igb_msix_ring() - drivers/net/ethernet/intel/igb/igb_main.c __napi_schedule() - net/core/dev.c ____napi_schedule() - net/core/dev.c __raise_softirq_irqoff(NET_RX_SOFTIRQ) - net/core/dev.c

软中断处理函数:

ksoftirqd为软中断处理进程,ksoftirqd收到NET_RX_SOFTIRQ软中断后,执行软中断处理函数net_rx_action(),调用网卡驱动poll()函数收包。在poll()函数中调用igb_clean_tx_irq()完成数据包的释放。

run_ksoftirqd() - kernel/softirqd.c __do_softirq() - kernel/softirqd.c h->action(h) - kernel/softirqd.c net_rx_action() - net/core/dev.c napi_poll() - net/core/dev.c __napi_poll - net/core/dev.c work = n->poll(n, weight) - net/core/dev.c igb_poll() - drivers/net/ethernet/intel/igb/igb_main.c igb_clean_tx_irq() - drivers/net/ethernet/intel/igb/igb_main.c


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:浅谈SpringBoot资源初始化加载的几种方式
下一篇:Linux内核网络收包过程函数调用分析(linux内核收发包流程)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~