嵌入式培训专家Linux网络设备驱动主讲:宋宝华华清远见今天的内容vLinux网络设备驱动架构 vLinux网络设备驱动数据流程Ø NON-NAPI模式数据接收流程 Ø NAPI模式数据接收流程 Ø 数据发送流程vLinux网络协议栈的实现Ø TCP/UDP/IP/MAC各层数据传递 Ø 网络系统调用与socket华清远见Linux网络设备驱动架构华清远见net_devicestruct net_device_ops { int (*ndo_open)(struct net_device *dev); int (*ndo_start_xmit) (struct sk_buff *skb, struct net_device *dev); int (*ndo_set_mac_address)(struct net_device *dev, void *addr); int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); void (*ndo_tx_timeout) (struct net_device *dev); ... }struct net_device { struct net_device_stats stats; const struct net_device_ops *netdev_ops; const struct ethtool_ops *ethtool_ops; ... }struct ethtool_ops { int (*get_settings)(struct net_device *, struct ethtool_cmd *); int (*set_settings)(struct net_device *, struct ethtool_cmd *); void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); int (*get_regs_len)(struct net_device *); ... }华清远见n协议层包头1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20Linux网络设备驱动—sk_buffunion{ struct tcphdr *th; /* TCP头部 */ struct udphdr *uh; /* UDP头部*/ struct icmphdr *icmph; /* ICMP头部*/ struct igmphdr *igmph; /* IGMP头部*/ struct iphdr *ipiph; /* IP头部*/ struct ipv6hdr *ipv6h; /* IPv6头部*/ unsigned char *raw; /* 数据链路层头部*/ }h; union{ struct iphdr *iph; /* IP头部*/ struct ipv6hdr *ipv6h; /* IPv6头部*/ struct arphdr *arph; /*ARP头部*/ unsigned char *raw; /* 数据链路层头部*/ }nh; union{ unsigned char *raw; } mac;/* 数据链路层头部*/5华清远见n发送流程数据发送流程① 网络设备驱动程序从上层协议传递过来的sk_buff参数获得数据包的有效数据和长度,将有 效数据放入临时缓冲区。
② 对于以太网,如果有效数据的长度小于以太网冲突检测所要求数据帧的最小长度 ETH_ZLEN,则给临时缓冲区的末尾填充0。
③ 设置硬件的寄存器,驱使网络设备进行数据发送操作。
1 2 3 4 5 6 7 16 17 18 19 20 21 22 网络设备驱动程序数据包发送函数模板 int xxx_tx(struct sk_buff *skb, struct net_device *dev) { int len; char *data, shortpkt[ETH_ZLEN]; /* 获得有效数据指针和长度 */ data = skb->data; len = skb->len; … dev->trans_start = jiffies; /* 记录发送时间戳 */ /* 设置硬件寄存器让硬件把数据包发送出去 */ xxx_hw_tx(data, len, dev); ... }6华清远见传输超时n当发生传送超时, 驱动必须在接口统计量中标记这个错误, 并安排设备 被复位到一个干净的能发送新报文的状态. 当一个超时发生在 snull, 驱 动调用 snull_interrupt 来填充"丢失"的中断并用 netif_wake_queue 重启 队列.net_dev->watchdog_timeo = TX_TIMEOUT; static const struct net_device_ops netdev_ops = { ... .ndo_tx_timeout = xxx_tx_timeout, ... }; xxx_tx_timeout (struct net_device *dev) { ... netif_wake_queue(dev); }7华清远见n接收流程,NON-NAPI数据接收流程(1)网络设备接收数据的主要方法是由中断引发设备的中断处理函数,中断处理函数判 断中断类型,如果为接收中断,则读取接收到的数据,分配sk_buffer数据结构和数据缓 冲区,将接收到的数据拷入数据缓冲区,并调用netif_rx()将sk_buffer传递给上层协议。
网络设备驱动poll中断处理函数模板static irqreturn_t net_interrupt(int irq, void *dev_id) { switch(status & ISQ_EVENT_MASK) { case ISQ_RECEIVER_EVENT: /* Got a packet(s). */ net_rx(dev); break; ...}static void net_rx(struct net_device *dev) { skb = dev_alloc_skb(length + 2); skb_reserve(skb, 2); /* longword align L3 header */ skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); lp->stats.rx_packets++; lp->stats.rx_bytes += length; }8华清远见n接收流程,数据接收流程(2)NAPI方式 与数据包的中断接收方式不同的是,以poll方式接收数据包时,当第 一次中断发生后,中断处理程序要禁止设备的数据包接收中断:网络设备驱动poll中断处理函数模板1 2 3 4 5 6 7 8 9 10 11 12 static void xxx_poll_interrupt(int irq, void *dev_id, struct pt_regs *regs) { switch (status &ISQ_EVENT_MASK) { case ISQ_RECEIVER_EVENT: … /* 获取数据包 */ xxx_disable_rx_int(...); /* 禁止接收中断 */ netif_rx_schedule(dev); break; … /* 其他类型的中断 */ } }NAPI 在高负载的情况下可以产生更好的性能,它避免了为每 个传入的帧都产生中断。
9华清远见数据接收流程(3)nndo_poll_controller#ifdef CONFIG_NET_POLL_CONTROLLER static void net_poll_controller(struct net_device *dev) { disable_irq(dev->irq); net_interrupt(dev->irq, dev); enable_irq(dev->irq); } #endif static const struct net_device_ops net_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = net_poll_controller, #endif ... };10华清远见华清远见Linux驱动课程v 嵌入式Linux驱动初级班v 通过本课程的学习,学员可以掌握Linux下字符设备、块设备、网络设备的驱动程序开发,同时掌握嵌入式Linux的系统开发和分析方法。
v 嵌入式Linux驱动开发高级班v 本课程以案例教学为主,系统地介绍Linux下有关FrameBuffer、MMC卡、USB设备的驱动程序开发。
v 班级规模及环境v 为了保证培训效果,增加互动环节,我们坚持小班授课,每期报名人数限15人,多余人员安排到下一期进行。
人手一套开发板和开发用的PC主 机。
华清远见让我们一起讨论!The success's road谢谢!。