数据包传输:应用层-内核-硬件

以下,整理出了 ping request 报文,从应用层,经内核,到达硬件,的 data path。

1. 应用层

// 应用层
busybox/ping.c
== ping_main()
	== common_ping_main()
		== ping()
			== create_icmp_socket()
				== socket(AF_INET, SOCK_RAW, 1);
			== ping4()
				== sendping4()
					== sendping_tail()
						== xsendto()
							== sendto()		// 系统调用

2. 内核

2.1 内核-网络

// (1)内核-网络
// net/socket.c
== __sys_sendto()		// sendto() 在内核的系统调用服务程序为 __sys_sendto()
	== sock_sendmsg()
		== sock_sendmsg_nosec()
			== raw_sendmsg()	// sock->ops->sendmsg,应用层使用 SOCK_RAW 创建 socket,故 sock->ops->sendmsg 指向 raw_sendmsg()
// net/ipv4/ip_output.c
				== ip_push_pending_frames()
					== ip_send_skb()
						== ip_local_out()
							== __ip_local_out()	// 经过 NF 的 LOCAL_OUT 钩子点
								== dst_output()
									== ip_output()	//	skb_dst(skb)->output
										== ip_finish_output()
											== __ip_finish_output()
												== ip_finish_output2()
// net/core/neighbour.c/h
													== neigh_output()
														== neigh_resolve_output()
// net/core/dev.c	
== dev_queue_xmit()
	== __dev_queue_xmit()
		== dev_hard_start_xmit()
			== xmit_one()
// include/linux/netdevice.h
				== netdev_start_xmit()
					== __netdev_start_xmit()
						== ops->ndo_start_xmit(skb, dev);	// 送入驱动
== dev_open(struct net_device *dev);
== __dev_open();
== ops->ndo_open(dev);
== eth_open(struct net_device *net);
	== eth_start(struct eth_dev *dev, gfp_t gfp_flags);
		== rx_fill(struct eth_dev *dev, gfp_t gfp_flags);
			== rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags);
				req->complete = rx_complete;
				== rx_complete(struct usb_ep *ep, struct usb_request *req);
					== dev->unwrap(dev->port_usb, skb, &dev->rx_frames);
						== eem_unwrap();

2.2 内核-驱动

// (2)内核-驱动
// drivers/net/usb/lan78xx.c																				
== lan78xx_start_xmit()		// .ndo_start_xmit		= lan78xx_start_xmit
	== skb_queue_tail()		// 插入队列
		== tasklet_schedule(&dev->bh);	// 触发任务调度 lan78xx_bh
			== lan78xx_bh()
				== lan78xx_tx_bh()
					== skb_dequeue()				// 取出数据
						== usb_fill_bulk_urb()		// 填充数据到 USB
// drivers/usb/core																										
							== usb_submit_urb()		// USB 发送数据

对于usb gadget 模式下,使用 function eem 的网卡驱动:

 // \drivers\usb\gadget\function\u_ether.c	 // .ndo_start_xmit		= eth_start_xmit,																			
== eth_start_xmit(struct sk_buff *skb, struct net_device *net)		
	== usb_ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags)		// 插入队列
		== ret = ep->ops->queue(ep, req, gfp_flags);
		==  dwc3_gadget_ep_queue();
			== __dwc3_gadget_ep_queue();
				== __dwc3_gadget_kick_transfer();
					== dwc3_prepare_trbs();
					== dwc3_send_gadget_ep_cmd();		trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
						== dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);

3. 硬件

// 硬件
== usb_submit_urb(cmdinfo->cmd_urb, GFP_ATOMIC);
	== usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags)
		hcd->driver->urb_enqueue(hcd, urb, mem_flags);
		== xhci_urb_enqueue();				trace_xhci_urb_enqueue(urb);
			== xhci_queue_bulk_tx();		//批量传输
				== prepare_transfer();
					== usb_hcd_link_urb_to_ep()		//add an URB to its endpoint queue
						== list_add_tail(&urb->urb_list, &urb->ep->urb_list);
				== queue_trb()						trace_xhci_queue_trb(ring, trb);	//queueing a TRB on a ring
					== inc_enq()					trace_xhci_inc_enq(ring);
				== giveback_first_trb()		//Pass all the TRBs to the hardware at once and make sure this write isn't reordered.
					== xhci_ring_ep_doorbell()		trace_xhci_ring_ep_doorbell(slot_id, DB_VALUE(ep_index, stream_id));
						== writel(DB_VALUE(ep_index, stream_id), db_addr);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值