Linux协议栈实现分析
Linux协议栈实现分析
功能模块、函数流程
Linux协议栈概括图
应用层 Socket操作函数集
inet_stream_ops INET层
inet_dgram_ops
Leabharlann Baidu
inet_sockraw_ops
tcp_prot
udp_prot
raw_prot
传输层
网络层
sk->sk_receive_queue sk->sk_write_queue
bind()
Socket()
recvfrom()
请求数据
sendto()
sendto()
应答数据
recvfrom()
close()
close()
面向无连接的 Socket工作流程
socket调用
socket()
bind调用
bind()
listen调用
listen()
accept调用
accept()
sys_socketcall()
sys_socketcall()
sys_socketcall()
sys_socketcall()
sys_socket()
sys_bind()
sys_listen()
sys_accept()
sock_create()
sockfd_lookup()
sockfd_lookup()
ip_route_input_slow() 单播
ip_route_input_mc() 多播 路由处理
ip_route_input() hh->hh_output() dst->neighbour->output()
ip_rcv_finish()
neigh_compat_output() dev_queue_xmit()
sockfd_lookup()
__sock_create()
security_socket_bind()
security_socket_listen()
sock_alloc()
sock_alloc()
security_ops->socket_bind()
sock->ops->listen()
security_socket_accept()
ESTABLISHE D
^-tcp_output.c:1332行,tcp_transmit_skb tcp_output.c:278行,ip_queue_xmit | |如果定义了NETFILTER,先进入LOCAL_OUT | ip_output.c:401行:ip_queue_xmit2 ip_output.c:317行;skb->dst->output(skb); (在route.c的ip_route_*put*函数中进 dst->output函数指针付值=ip_output或 ip_mc_output或ip_rt_bug) case TCP_SYN_RECV(收到ACK)(Server端) 如果ouput tcp_set_state 能会到 tcp_data_snd_check (tcp_input.c:4030) tcp_ack_snd_check (tcp_input.c:4031) LISTEN
sys_read()
sys_recv() sys_recvfrom()
sock_readv()
sock_readv_writev()
sock_recvmsg()
INET Sock层
sock->ops->recvmsg()
inet_stream_ops->recvmsg()
inet_dgram_ops->recvmsg()
ip_mc_output() 分片 ip_fragment() 分片
ip_output()
ip_forward() forward
ip_local_deliver() local_in skb->dst->input()
ip_finish_output()
dst_input()
NF_HOOK(PF_INET, NF_IP_POST_ROUTING) ip_finish_output2()
__skb_queue_tail
tcp_rcv_established
tcp_v4_do_rcv
将数据包放入队列的尾部 sk->receive_queue 并调用sk->data_ready通知上层数据 到达
在这之间做了tcp checksum校验等
tcp_v4_rcv
ipprot->protocol = TCP
sock_map_fd()
selinux_socket_bind()
inet_listen()
sock->ops->accept()
sock->ops->bind()
sockfd_put()
inet_accept()
inet_bind()
security_socket_post_accept()
type=SOCK_RAW
ip_output.c:367
lter
进行路由,并把skb->dst->input函数 指针指向ip_local_deliver或ip_error 或ip_forward或ip Route.c:1658-1675行,在路由时 会先在路由缓存中查找,没找到则 由ip_route_input_slow函数从路 由表中查,并加入到缓存中
t
tcp raw_v4_input ip_local_deliver
数据包发往本地 检查ip数据包的内容
Ip_forward
Tcp_output.c:278
如果定义了NETFILTER,则先进入 IP_FORWARD
Iq
ip_options_compile ip_forward_finish ip_route_input_slow 在缓存中找到
do_softirq
2751行,同时将queue->blog_dev.poll指向 s_backlog函数
ksoftirqd
内核线程,进程调度 将从网卡驱动接收到的 sk_buff放到内核接收队列中 通过__skb_queue_tail函数实 现
netif_rx
网络数据交互模型
服务器
Socket()
__skb_queue_tail() skb_queue_tail(&sk->sk_receive_queue, skb)
tcp_rcv_established()
sock_queue_rcv_skb()
tcp_v4_do_rcv() ip_queue_xmit() raw_send_hdrinc() ip_route_output_flow() ip_push_pending_frames() tcp_v4_rcv()
客户端
bind()
listen()
Socket()
accept()
建立连接
connet()
read() recv()
请求数据
write() send()
write() send()
应答数据
read() recv()
close()
close()
面向连接的 Socket工作流程
服务器
Socket()
客户端
物理层
OUTPUT
网络设备
INPUT
, 调用 sg
tcp_replace_ts_recent tcp_rcv_state_proces s
4, 函数中,将 i_fop指向 s结构。 d函数
tcp_sequence
tcp_paws_discard
!LISTEN && !ESTABLISHED
tcp_fast_parse_options
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING)
packet_type->func()(ip_rcv、arp_rcv) dev->hard_start_xmit() 驱动层 如驱动中的e1000_xmit_frame() handle_bridge() 桥模式 netif_receive_skb()
inet_sockraw_ops->recvmsg()
sock_common_recvmsg()
sk->sk_prot->recvmsg()
tcp_prot->recvmsg()
udp_prot->recvmsg()
raw_prot->recvmsg()
tcp_recvmsg()
udp_recvmsg()
raw_recvmsg()
sk->receive_quene NULL sk->sk_backlog_rcv() NOT NULL 读取
skb_recv_datagram()
skb_dequeue() 读取
sk->sk_receive_queue
填充 tcp_v4_do_rcv() tcp_rcv_established()
ip
ip_forward_options
ip_output.c:397
ip_
ip_route_input ip_send ip_rcv_finish
如果定义了NETF LOCAL_OUT
ip
如果定义了NETFILTER,则先进入 PRE_ROUTING
ip_fragment ip_rcv
如果产生了分片 即skb->len > rt->u.dst.pmtu 并将ip_output函数指针做为参数 给ip_fragment
Dev.c:1489行,调用ip_rcv函数 在ip_output.c:1001行初始化了 ip_packet_type,使它的成员func指向 ip_rcv函数 Dev.c:1553行,通过__skb_dequeue 函数取得sk_buff,
netif_receive_skb
Process_backlog
inet_bind()
sockfd_put()
close调用
close()
connect调用
connect()
sys_close()
sys_connect()
filp_close()
sk->sk_prot->connect()
fput()
tcp_v4_connect()
file->op->release()
c:1622行,调用dev->poll(dev, &budget)
Net_rx_action
如果定义 POST_
q.c:90行,产生软中断,通过全局变量 q_vec的函数指针调用net_rx_action
2847行,函数net_dev_init中,将 _action函数指针传给softirq_vec.action, oftirq中通过h->action调用net_rx_action
Protocol.c:56行开始,初始化全局数组 inet_protos, 在ip_input.c:262行查找到相应的接收函数 (tcp、udp、icmp、igmp)
udp_rcv
ipprot->protocol = UDP
ip_local_deliver_finish
如果定义了NETFILTER,则先进入LOCAL_IN 转发 数据 包
dst_output()
ip_forward_finish()
raw_rcv()
NF_HOOK(PF_INET, NF_IP_LOCAL_IN)
skb->dst->output()
NF_HOOK(PF_INET, NF_IP_FORWARD)
ip_call_ra_chain()
ip_defrag()
填充 sock_queue_rcv_skb() IP 层
tcp_v4_rcv()
udp_rcv()
raw_rcv()
write调用
write()
send调用
recv()
sendto调用
recvfrom() Sock层
sys_write()
sys_send() sys_sendfrom()
sock_writev()
udp_queue_rcv_skb()
icmp_pointers->handler()
raw_rcv_skb()
udp_rcv()
icmp_rcv()
raw_rcv()
ipprot->handler() NF_HOOK(PF_INET, NF_IP_LOCAL_OUT) tcp、udp
raw_v4_input() raw ip_local_deliver_finish()
ip_route_connect()
sock_close()
tcp_connect()
sock->ops->release()
tcp_transmit_skb()
tcp_close()、udp_close()
read调用
read()
recv调用
recv()
recvfrom调用
recvfrom() Sock层
sock_readv_writev()
sock_sendmsg()
INET Sock层
sock->ops->sendmsg()
inet_stream_ops->sendmsg()