网络子系统大杂烩

2023-10-11 20:33
文章标签 网络 子系统 大杂烩

本文主要是介绍网络子系统大杂烩,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

阅读《深入理解linux网络技术内幕》和Linux2.6.37.1源码记录

三个数据结构

1.net_device

2.softnet_data

3.sk_buff

softnet_data是一个cpu对应一个。

网卡接收数据的流程如下

网卡收到数据收首先会出发中断,导致执行中断处理函数dm9000_rx。


以太网驱动接收函数中的skb_reserve(skb, 2)

这是为了保证紧接Ethernet报头的ip报头可以从四节对齐的地址开始

因为Ethernet报头为14字节(目标mac+源mac+类型 = 6+6+2),所以需要额外填充

2字节。


值得一提的是,此中断处理函数在dm9000_open函数中注册,并非在driver_probe

函数中注册。中断处理函数的具体注册过程如下:
(net/core/dev.c)dev_open->__dev_open-> dm9000_open(ops->ndo_open)

最后在dm9000_open中通过request_irq注册网卡的中断处理函数dm9000_interrupt


在中断处理函数dm9000_interrupt中首先通过spin_lock_irqsave获取锁并将中断关闭,

然后判断中断的类型,是接收中断还是发送中断或者是其它,若是接收中断则调用

dm9000_rx函数进行帧接收。


linux2.6.37.1的dm9000驱动中 帧接收方式 采用的是中断期间处理多帧的策略(具体可见<网络技术内幕>)

在接收时,若网卡产生一次中断则会持续进行帧接收。多帧接收的具体实现是在dm9000_rx函数中实现的。

dm9000_rx函数的主体是一个do...while循环,若网卡一直有数据则会持续进行帧接收(中断期间处理多帧),

而此时的中断是关闭的(被spin_lock_irqsave关闭)。每次接受下来的帧则通过netif_rx->enqueue_to_backlog

函数将接收到的skb添加到softnet_data的input_pkt_queue队列中。


dm9000的数据接收方式为非napi方式,采用napi方式和非napi方式的重要区别在帧接收处理。

napi的接受过程如下:

网卡产生中断,调度napi_schedule执行

在napi_schedule中触发软中断

软中断处理函数轮训poll_list

调用napi_struct中的poll方法

在poll方法中执行帧接收等操作

而非napi的操作是方式是如dm9000所示:

网卡产生中断,通过dm9000rx、netif_rx在中断期间接受多帧

将接收到的帧存放到入口队列中,然后触发软中断

在软中断处理函数中轮询poll_list

调用的是非napi的系统默认poll方法process_backlog

在prcess_backlog中处理入口队列的帧


这两种方法的区别在于napi接收过程在中断下半部的poll中完成

非napi在中断处理函数中完成



内核中关于napi的问题

napi和非napi最大的区别在于 napi需要在网卡初始化的时候(网卡初始化分在probe和open两个函数中完成)

通过函数netif_napi_add初始化一个napi_struct数据中的poll方法,而非napi直接使用的是在net_dev_inti函数中

初始化的默认poll函数procee_backlog。最关键的区别在于这两种poll函数的工作方式。


封包类型设置

skb->protocol = eth_type_trans(skb, dev)

eth_type_trans函数其实需要完成两件事情,1.是设置包类型2.设置协议

设置包协议的是通过

skb->pkt_type = PACKET_BROADCAST;

skb->pkt_type = PACKET_MULTICAST;

skb->pkt_type = PACKET_OTHERHOST;

来实现的,具体需要根据mac_addr中ethernet的报头6+6+2)第一个6中的第一个byte的最高两位来普安段是

单播还是多播。如果未显式的设置skb->pkt_type则其实为0,表示PACKET_HOST,即MAC地址匹配。

封包类型设置完毕则进行协议设置。协议的类型可设置为:

1.ethernet帧

2.raw 802.3

3.802.3/LLC

4.802.3/SNAP

各协议之间的区别可参考 网络技术内幕 P289

主要区别是6+6+2中的2字节内数值表示的含义不同

2域中存放的的数值

>1536 表示这是一个ethernet帧

<1500的表示需要使用LLC报头的帧


802.3/LLC:   DSAP SSAP CTL

802.3/SNAP:DSAP SSAP CTL SNAP(其中DSAP SSAP CTL固定)


若不是多播帧则将帧中的mac地址与本机mac做比较,判断是否是传给本机的。若是传给本机的

则解包提取出报文头中的上层使用的协议类型。



出处:http://www.blogjava.net/shiliqiang/articles/304505.html
2.6.24.4内核网络接收数据包分析
瀚海书香
在2.6.24.4中所有的网卡,不管是否支持napi,都是通过struct napi_struct结构进行。所有我们先说一下这个结构。
struct napi_struct{
   struct list_head poll_list;
   unsigned long state;
   int weight;
   int (*poll)(struct napi_struct *,int);
}
对应支持napi的网卡,自己填充这个结构体;而非napi网卡,则使用per cpu的softnet_data>backlog,这个结构的初始化在net_dev_init()中完成。
我们先说一下非napi机制的网卡:
   网卡接收到数据包后dma到内核空间,然后调用netif_rx()将数据包挂接到softnet_data>input_pkt_queue中,如果backlog这个napi_struct没有被调度,则napi_schedule(&backlog).napi_schedule()会将backlog的poll_list挂接到softnet_data->poll_list上,同时出发软中断NET_RX_SOFTIRQ。NET_RX_SOFTIRQ软中断,调用相应的函数net_rx_action()。
对应napi机制的网卡:
    网卡初始化是会自己初始化一个自己的数据包接收队列,当有数据包到达时,将数据包dma到自己的数据包队列中,如果自己的napi没有调度,则napi_schedule(mynapi),这里的mynapi是网卡自己的napi_struct.napi_schedule()会将网卡自己的poll_list挂接到softnet_data->poll_list上,同时出发软中断NET_RX_SOFTIRQ。NET_RX_SOFTIRQ软中断,调用相应的函数net_rx_action()。
net_rx_action():
   首先获取softnet_data->poll_list,通过遍历poll_list,获取每个poll_list对应的napi_struct结构(container_of实现),然后根据napi_struct的weight调用poll函数,如果是非napi网卡,这里的napi_struct是backlog,所以poll函数就是process_backlog;如果是napi的网卡,则会使自己的poll函数。
napi网卡的poll函数就是从自己数据包队列中dequeue出一个skb,然后调用netif_receive_skb().
非napi的process_backlog会获取softnet_data->input_pkt_queue,然后对队列input_pkt_queue进行dequeue操作,获得一个skb,之后调用netif_receive_skb(skb)。
netif_receive_skb():
   对skb做一些准备工作,例如设置mac_len等,调用deliver_skb()给所有的注册ptype_all类型的协议处理handle,然后是网桥和VLAN的处理,之后会给注册的相应协议的ptype_base的handle。这里假设是ip协议,则会调用相应的ip协议handle的处理函数ip_rcv。
ip_rcv():
   对skb做一些检查工作,如果skb->users!=1,则clone一个skb,之后会转入netfilter的NF_IP_PRE_ROUTING的hook点,调用所有在该点注册的hook函数。比如说如果开启了conntrack,则会在这里进行数据包重组。之后调用ip_rcv_finish().
ip_rcv_finish():
    首先调用ip_route_input()决定数据包的路由,初始化skb->dst,调用dst_input(skb).
dst_input():
   实际上是调用skb->dst->input(skb),对应input的初始化在route.c中。如果是发往本地的数据包dst->input=ip_local_deliver;如果是转发的数据包dst->input=ip_forward;
本地流程:
ip_local_deliver():
    首先是对分片的数据包重组,会转入netfilter的NF_IP_LOCAL_IN的hook点,调用所有在该点注册的hook函数。之后会调用ip_local_deliver_finish(),之后就到第四层了。
转发流程:
ip_forward():
    做一些源路由等方面的检查后,会转入netfilter的NF_IP_FORWARD的hook点,调用所有在该点注册的hook函数。之后会调用ip_forward_finish().
ip_forward_finish():
    调用dst_output().
dst_output():
    skb->dst->output(skb).一般output=ip_output.
ip_output():
    设置skb的dev为发包的dev,同时设置skb->protocol,会转入netfilter的NF_IP_POST_ROUTING的hook点,调用所有在该点注册的hook函数。之后会调用ip_finish_output().
ip_finish_output():
    检查一下数据包是否需要分片,如果需要分片,则进行ip_fragement(),之后调用ip_finish_output2().
ip_finish_output2():
    根据neighbour,调用dst->neighbour->output.
到这为止,数据包会经过dev_queue_xmit放入dev的qdisc中。之后就是流控出队列。

这篇关于网络子系统大杂烩的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/190659

相关文章

Linux网络配置之网桥和虚拟网络的配置指南

《Linux网络配置之网桥和虚拟网络的配置指南》这篇文章主要为大家详细介绍了Linux中配置网桥和虚拟网络的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、网桥的配置在linux系统中配置一个新的网桥主要涉及以下几个步骤:1.为yum仓库做准备,安装组件epel-re

python如何下载网络文件到本地指定文件夹

《python如何下载网络文件到本地指定文件夹》这篇文章主要为大家详细介绍了python如何实现下载网络文件到本地指定文件夹,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...  在python中下载文件到本地指定文件夹可以通过以下步骤实现,使用requests库处理HTTP请求,并结合o

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为