精华内容
下载资源
问答
  • P2P常规流量检测一般通过常用的端口来进行识别,然而随着架构的演进,P2P流量识别也因此从简单的端口匹配到复杂的DPI深度数据包检测,其端口特性也由最初的固定端口发展到随机动态端口再到伪装端口,一步步地加大着...

    随着P2P技术不断地发展演进,P2P技术及架构的演进经历了集中式、全分布式、混合式三个阶段。P2P常规流量检测一般通过常用的端口来进行识别,然而随着架构的演进,P2P流量识别也因此从简单的端口匹配到复杂的DPI深度数据包检测,其端口特性也由最初的固定端口发展到随机动态端口再到伪装端口,一步步地加大着P2P流量检测的难度。同事,随着数据挖掘、模糊统计技术的不断发展,已经有很多研究人员开始将机器学习中的贝叶斯分类、雅各布算法等常用手段引入到流量识别的研究当中。

    通过对国际上各种P2P流量检测技术的调查研究,将各种流量检测技术归纳如下。

     

    (1) 基于IP地址的P2P识别

    (2) 基于端口的P2P识别

    (3) 基于会话的识别

    (4) 基于统一资源定位符(URL)的过滤方法

    (5) 基于流统计特性的识别

    (6) 基于传输层行为特征的识别

    (7) 基于深度数据包扫描的识别

    (8) 基于DNS查询日志的P2P节点检测

     

    (1) 基于IP地址的P2P识别

    IP地址识别可以分类出集中式P2P中的目录服务器以及混合式P2P中的Super-Peer,以及某些恶意的P2P用户。这种识别方法比较局限,应用范围比较狭窄。

     

    (2) 基于端口的P2P识别

    这里的端口指TCP/IP模型的传输层端口,即TCP或UDP端口。

    端口识别法的优点是:效率高、快速、易实现;采用端口检测方案不必对

    网络进行较大的改动,原理和控制逻辑都比较简单,实施方便,投资不大。然而P2P协议不使用固定端口,而是动态地使用端口,包括使用一些知名服务的端口。KaZaa使用了随机端口,而HTTP隧道、端口跳跃等技术的使用更是加大了识别、跟踪、控制的难度,导致了检测对象单一,造成识别误报和漏报率高等问题,同事对于一些VPN的应用或者通过NAT转换的应用无能为力。

     

         总体来看,使用端口法识别业务流量的方法缺点如下。

    Ø 不是所有的协议都在因特网编号分配机构IANA中注册了使用的端口

    Ø 在某些情况下,服务器的端口是动态分配的,例如FTP被动模式下的数据传输端口就是在控制流中协商的。

    Ø 由于防火墙等访问控制技术封堵了某些未授权的端口,很多协议使用

    常用端口以绕开防火墙的封堵,例如80端口被很多非Web应用程序使用,以绕开那些不过滤80端口流量的防火墙。

     

    (3) 基于会话的识别

    TCP/UDP端口可能存在于任何一个数据包中,高层协议的特征代码却只能

    存在于一个会话包的头几个数据报中。因此,当在一个会话包的第一个数据报中发现P2P特征代码时,该会话包的其余数据报也就可以判断为P2P数据报。有时P2P软件使用多个会话包,这就需要系统软件关联匹配这多个会话包进行P2P判定。

     

    (4) 基于统一资源定位符(URL)的过滤方法

    该方法多用于BT的识别控制,过滤URL中包含的.torrent,可以禁止扩展名为.torrent的文件的下载。这种方法具有很大的局限性,因为.torrent文件完全可以通过别的方式(如FTP)或者换一个扩展名以避免过滤。

     

    (5) 基于流统计特性的识别

    P2P应用作为一种充分利用客户端资源的应用,在传输层表现出来的流量

    特征相对于其他应用,如FTP、DNS等,有许多不同的地方。由于P2P流量数据量大,节点间数据交换频繁,P2P流量具有两个重要特点:一是不分时段性;二是持续性。对传统流量来说,一般访问一个网站的流量是突发的,持续时间短的,数据以下行为主;如果用传统方式下载文件,持续时间会相对较长,但数据还是以下行为主,上行量相对很小。对P2P流量来说,突出特点是持续时间长,流量也是非突发性的,并且上行和下行的流量是相当的。基于流统计特性的识别方法就是要对数据流量进行统计分析,从统计上来判断该流量是否数据P2P流量,而后对该流量进行控制。

         基于流统计特性的识别方法的优点有:

    Ø 由于P2P应用具有普遍适用的流量特征,新的应用也符合这一特征,所以这种技术有发现新的应用的能力;

    Ø 有检测加密应用的能力。

    基于流统计特性的识别方法缺点有:

    Ø 由于传输层的特征一般不能明确指示应用层协议类型,所以这种方法对应用分类的能力较

    弱,而应用分类对于服务质量的实施是非常重要的。

    Ø 由于对称路由和丢包、重传现象的存在,导致无法精确确定流量特征,从而有可能对流量

    检测的精确度造成影响;

    Ø 很多流量特征都不是流量唯一的,其他应用也有可能表现出这种流量特征,需要结合其他

    一些技术如端口检测来排除其他应用。

     

    (6) 基于传输层行为特征的识别

    该方法以P2P流量在传输层所表现出来的一般特性为依据并结合传统的端口检测技术对P2P流量进行识别。基于传输层的P2P识别与基于流的P2P识别有相似之处,都是通过宏观分析的方法进行识别,而不进行任何微观内容的检测。不同之处在于,基于流的P2P识别依据的是P2P流的字节数、平均速率以及持续时间等流的属性特征,而传输层的P2P识别则是根据P2P连接的IP地址和端口号的连接特征进行识别。

     

         这种方法主要使用一个数据流中两种不同类型的对。第一种是同时使用TCP和UDP进行数据传输{SourceIP,DestinationIP}对;第二种是两个P2P主机进行连接的{IP,Port}对。

     

    1)  同时使用TCP和UDP的{Source IP,Destination IP}对

    Ø 首先要识别出那些同时使用TCP和UDP传输协议的源-目的IP对。一般约有2/3的P2P协议同时使用TCP和UDP作为第四层的传输协议。这些协议包括eDonkey、Fasttrack、WinMx、Gnutella、MP2P以及DirectConnect。一般而言UDP用于流量控制请求和请求应答,而数据传输则用TCP。因此那些同时使用两种传输协议(TCP和UDP)的源、目的主机便极有可能是使用P2P应用的主机。

    2)  {IP,Port}对

    Ø 在P2P网络中,连接到一个主机节点上的不同的IP数与端口数是相等的。比如有20个不同主机连接到同一个主机时,一般需要20个不同端口。相比而言,一个主机如果连接到一个Web服务器上,为了并行下载,一般会使用不止一个端口。因此,IP数和端口数相对应的连接则极可能是P2P连接。

             利用这种方法识别P2P流量的步骤描述如下。

             首先找出在T时间内同时使用TCP和UDP的源-目的IP对。如果这样的IP对存在,认为是P2P连接。

             然后在T时间内,观察所有的源(IP,Port)对和目的(IP,Port)对,找出IP数和端口数相等的对,即为P2P对。相反如果连接到的IP数和Port数相差大到10个以上,则认为是非P2P流量。

             同基于流的识别方法一样,这种识别方法最大的问题也是不能区分出具体的P2P协议,虽然灵活性较好,即可以识别未知的P2P协议,但精确性不高。如果能提高检测精度,该方法将具有很好的扩展性。

     

    (7) 基于深度数据包扫描的识别

    由于P2P软件引入动态端口,只能通过扫描高层协议来探知P2P数据报。如对于Kazaa系统,只能深入内部获取Kazaa特征代码。对于其他P2P应用,有时甚至要通过几个特征代码才能判明其为P2P流。深度数据包检测技术DPI是通过对数据包应用层协议的检测解析发现P2P应用。DPI可以帮助实现对网络内部奥秘的透视和对网络资源的控制,可以分辨出具体用户具体应用的数据流,从而可以对用户的应用部署QoS、安全等其他策略。

          DPI技术使用一个载荷特征库存储载荷特征串,符合载荷特征串的数据包即被视为P2P数据包。几乎每种P2P应用都具有自己的应用层协议,通过数据报报文捕获,分析报文特征,则可以为每种P2P应用层协议定义唯一的载荷特征串。定义特征串的原则为:选择该协议特有的,交互过程中必须出现且实际环境中出现频率最高的字段作为协议的特征串。

     

    DPI的识别技术可以分为以下三类。

    Ø 基于“特征字”的识别技术

    不同的应用通常依赖于不同的协议,而不同的协议都有其特殊的指纹,这些指纹可能是特定的端口、特定的字符串或者特定的比特序列。基于“特征字”的识别技术通过对业务流中特定数据报文中的“指纹”信息的检测以确定业务流承载的应用。通过对“指纹”信息的升级,基于特征的识别技术可以很方便的进行功能扩展,实现对新协议的检测。

    如BitTorrent协议的识别,通过对其协议进行分析,发现BitTorrent协议由一个握手开始,后面是循环的消息流,每个消息的前面都有一个数字来表示消息的长度。在其握手过程中,首先发送19,然后是字符串“BitTorrent Protocol”。那么“19BitTorrent Portocol”就是BitTorrent的“特征字”。

    根据具体检测方式的不同,基于“特征字”的识别技术又可以分为固定位置特征字匹配、变动位置的特征匹配以及状态特征匹配三种技术。

     

    Ø 应用层网关识别技术

    某些业务的控制流和业务流是分离的,业务流没有任何特征。这种情

    况下需要采用应用层网关识别技术。应用层网关需要先识别出控制流,并根据控制流的协议通过特定的应用层网关对其进行解析,从协议内容中识别出相应的业务流。对于每一种协议,需要有不同的应用层网关对其进行分析。

            例如SIP、H.323协议。SIP/H.323通过信令交互过程,协商得到其数据通道,一般是RTP格式封装的语音流。也就是说,纯粹检测RTP流并不能得出这条RTP流是通过哪种协议建立的。只有通过检测SIP/H.323的协议交互,才能得到其完整的分析。

     

    Ø 行为模式识别技术

    行为模式识别技术基于对终端已经实施的行为的分析,判断出用户正

    在进行或者即将实施的动作。行为模式识别技术通常用于某些无法根据协议识别判断的业务。例如SPAM垃圾邮件业务流和普通的E-Mail业务流从E-Mail的内容上看是完全一致的,只有通过对用户行为的分析,才能够准确地识别出SPAM业务。

             DPI技术的主要用处包括以下几项。

    (一) 流量管理:控制P2P流量,防止这种“流量”占用了太多的带宽,

    而影响其他应用。

            (二)安全:识别出并能抑制DoS攻击和其他的恶意危害网络安全的行为。

            (三)网络资源使用的控制。

            (四)业务优化:例如个性业务和内容过滤。

            (五)全局业务控制策略应用。

    DPI技术的优点如下:

    (1) 精确度高:通过使用各种优化措施和发现更多的载荷特征,DPI技术可以达到非常高的检测精度和令人满意的性能。

    (2) 易于应用:目前主流的P2P协议都是非加密传输的,破解相对容易,使用DPI技术就能满足目前运营商限制P2P流量的需求。

    (3) 易于维护,升级简便:对于新出现的P2P协议,只需在破译后升级载荷特征库就可以实现对新出现的P2P协议的监控,后期维护简单。而且一种新P2P应用出现并大量占据互联网带宽需要比较长的时间,所以DPI技术检测新应用的滞后性对用户造成的影响有限。能够对已知协议的P2P流量惊醒精确的识别,误判概率很低。

    (4) 使用范围广:易于理解、升级方便、维护简单,是目前运用最普遍的方法。

     

    DPI技术的缺点如下。

    (1) 可扩展性差:由于该方法对新P2P应用的流量识别具有滞后性,即在未升级特征库钱无法检测新的P2P应用,必须找到新应用的载荷特征后,才能对该应用实施有效检测。这一点成为限制该方法的瓶颈。

    (2) 缺乏加密数据分析功能:某些P2P载荷采用了加密传输,隐藏了P2P应用的协议和数据特征,因此深度数据包检测技术对加密P2P应用的检测能力非常有限。

    (3) 代价较高:由于需要完成协议解析还原和特征匹配等操作,因此计算和存储开销大,流量检测算法性能低。载荷特征越复杂,检测代价越高,算法性能也越差。


    (8) 基于DNS查询日志的P2P节点检测

    除了截获数据包进行分析外,也有学者从识别P2P节点入手,获得其IP,从而发现P2P流量。山东大学的陈振祥等人通过研究发现,在中心化的、纯分布式的或者混合的P2P网络中,比如Skype、KaZaa、eMule、Shareazw、Gnucleus、Sancho、Bittorrent和eDonkey等应用,其对等节点不通过DNS查询来得到目标节点的IP地址信息,而是从中心服务器、超级节点或者DHT得到相邻节点的信息,因此DNS服务器的日志记录能作为识别P2P主机节点的一个凭据。根据陈振祥等人的试验,在5分钟的间隔内,对于一个固定IP主机节点,如果他发起的连接的主机数据超过5个,但是DNS关于该主机的查询日志为空,那么这可能就是一个P2P主机。通过主机IP地址的识别,可以分辨出集中式P2P中的目录服务器及混合式P2P中的超级节点,进而通过源地址IP对P2P流量进行识别检测。但是由于该方法是对P2P节点进行检测,导致检测范围大,可用性差。



    转自:Mpad.mobi P2P流量识别、控制技术

    展开全文
  • 在发动机工作时,空气经空气滤清器过滤后进人流量计推动叶片(测量片)旋转,使其开启。叶片开启角度由进气量产生的推力大小和叶片轴上卷簧(复位弹簧)弹力的平衡情况决定。当驾驶员操纵加速踏板来改变节气门开度时...
  • 洋葱网络流量识别方案

    千次阅读 2019-04-09 17:20:58
    Tor流量检测方案 1.Tor简介 Tor通过连接一系列虚拟隧道从而允许组织和个人通过公共网络共享信息而不会损害隐私。同样,Tor是一种有效的审查规避工具,允许其用户访问其他被阻止的目的地或内容。Tor的用户越多,...

    洋葱网络Tor流量检测方案
    1.Tor简介
    Tor通过连接一系列虚拟隧道从而允许组织和个人通过公共网络共享信息而不会损害隐私。同样,Tor是一种有效的审查规避工具,允许其用户访问其他被阻止的目的地或内容。Tor的用户越多,节点越多,匿名性就越受到保护。Tor网络上的数据包不是采用从源到目的地的直接路由,而是通过几个中继采用随机路径,因此任何单点的观察者都无法知道数据来自何处。客户端为电路中的每一跳协商一组单独的加密密钥,以确保每一跳在通过时不能跟踪这些连接。由于每个中继在电路中看到不超过一跳,因此窃听者和受损中继都不能使用流量分析来链接连接的源和目的地。为了提高效率,Tor软件使用相同的电路进行相同的十分钟左右的连接。后来的请求被赋予一个新的电路,以防止人们将您之前的行为与新的行动联系起来。
    2. Tor原理
    2.1获取节点列表
    步骤一:Tor客户端连接Tor网络,获取Tor网络节点列表,如图1:
    在这里插入图片描述
    图1
    2.2建立加密通道
    在这里插入图片描述
    图2
    步骤二:随机选择三个节点建立连接并生成密钥开始加密传输,如图2。
    2.3定期更新节点
    步骤三:连接会定期进行更新,减小被发现和破解的可能性,如图三。

    在这里插入图片描述
    图3
    2.4完整流程说明
    在这里插入图片描述
    图4
    如图4所示,Bob为了访问Alice,先访问Tor的目录服务器,获取一部分Tor节点的IP地址,并从中随机选择三个节点的IP地址A、B、C。
    a) Bob和节点C通过Curve25519椭圆曲线算法协商一个对称密钥keyC。之后,Bob和节点C之间就会用这把对称密钥keyC进行加密通信。
    b) Bob把B的IP地址和与B协商密钥所需的参数用对称密钥keyC加密后发送给C。C用keyC解密后,将Bob与B协商密钥所需的参数发送到B的IP地址。B收到参数后产生了对称密钥keyB,并将与Bob协商密钥所需的参数发还给C。C将参数通过keyC加密后发还给Bob。Bob通过算法计算出对称密钥keyB。
    c) Bob通过相同的方法和A协商出keyA。
    d) 至此,Bob有了三把钥匙keyA、keyB、keyC。Bob往Alice发送数据包时,先将数据Data用keyA加密,再用keyB加密,再用keyC加密,层层包裹,然后发往节点C。节点C解开一层加密,发往节点B。节点B解开一层加密,发往节点A。节点A解开一层加密,得到明文,最终发送给Alice。
    3.检测方案
    3.1方案1 基于TLS指纹的Tor流量识别

    在这里插入图片描述
    以上是TLS加密流量传输过程,我们通过全流量平台获取所有TLS访问数据,在此基础上过滤出所有“服务器发送Certificate”的数据包,之后查看所有的证书的授权商和授权时间。证书来源为******,地址为,证书的时间为15年到25年。
    在这里插入图片描述
    一般Tor流量的证书起效时间与当前时间接近,证书周期短,证书颁发机构和拥有者名称结构固定。具体的字段:validitty获取证书时间、Certificates获取证书相关内容,从证书的相关内容出发做出判断。
    3.2基于报文长度分布的Tor流量识别
    Tor流量可认为是少数典型长度报文大量出现,但由于上层应用的不同、Tor读写事件调度的不确定性和网络环境的实时变化,具体到每条Tor流量时其报文长度分布可能各不相同,因而难以建立统一的报文长度分布的线性模型。
    可以采用支持向量机分类算法判断待识别流的报文长度分布是否满足Tor流量的分布特征。由客户端发出的流量为上行流量,接收到的流量为下行流量。在特征选取阶段,针对数据集中所有Tor上行流量,将典型长度报文按出现的频率由高到低排序,并选取频率和值大于设定的门限值,如90%的前l位频率组成特别流量(Tor流量)的报文长度分布,统计每条Tor上行流量和其他类型流量中相同特征报文出现的频率,形成相应的区分标准,从而在其他场景中应用判断。

    展开全文
  • 在发动机工作时,空气经空气滤清器过滤后进人流量计推动叶片(测量片)旋转,使其开启。叶片开启角度由进气量产生的推力大小和叶片轴上卷簧(复位弹簧)弹力的平衡情况决定。当驾驶员操纵加速踏板来改变节气门开度时...
  • face++人脸识别接口实现原理(一)

    万次阅读 多人点赞 2017-07-19 21:33:34
    背景:市面上,能够提供人脸识别解决方案的公司主要有,百度,科大讯飞,旷世face++,还有已经被...需求:在安卓平台上,开发一app,这个app可以:(1)提取人脸特征,包括这个表情(微笑,惊讶,平静,生气),年

    背景:

    • 市面上,能够提供人脸识别解决方案的公司主要有,百度,科大讯飞,旷世face++,还有已经被facebook收购的face.com。这里涉及到的是旷世科技的人脸识别技术。旷世科技人脸识别技术,在国内得到了很广泛运用,其中最有名是,支付宝的刷脸验证登录技术,以及蚂蚁金服的刷脸验证技术。

    需求:

    在安卓平台上,开发一app,这个app可以:

    • 提取人脸特征,包括这个人表情(微笑,惊讶,平静,生气),年龄,是否戴眼镜,是否睁眼,肤色,性别,眼睛,鼻子,眉毛在脸部的位置(坐标)。

    • 实现登录验证

    • 将一张合影中的所有人的身份都识别出来。

    原理:

    • 实际上,原理并不是很难理解。首先,你将一张图片,上传到服务器,服务器会提取你的面部特征,写进一个文件中,这文件会有一个唯一标识吗,叫做face_token,代表你的身份,然后服务器会把这些特征以及标识通过json数据响应给你。响应给你的json数据里包含面部特征,以及你的face_token。

    • 登录验证就是对比或者说匹配的过程,你通过终端拍摄或者从相册选择一张照片,然后上传到服务器,服务器首先提取你的面部特征,然后和你注册账号时提取的面部特征进行对比,如果相识度达到一定高度,就会认为是同一个人,然后服务器响应验证通过,进入账号。

    • 将一张合影中的所有人的身份都识别出来,原理和登录验证是一样,只不过多了一个工序。首先,服务器会探测一张图片中有多人,并且把能探测到人的脸部特征以及标识码以json数组形式都反馈给你,我们可以通过遍历标识码的方式,一个一个匹配,最后把结果汇总,反馈个用户即可。可能你会有疑惑,为什么要遍历标识码来验证,因为标识码是代表一个人的身份,如果用其他参数,比如是否戴眼镜,那么你会分不清反馈的结果到底指向得是那个人,进而看不出图片中的某个人和服务器反馈的那个人是否是同一个人。

    准备

    • 注册face++ api_key Secret:

      登录官网,注册账号,进入开发者中心,注册免费体验版(正式版web api收费标准:一小时30元,一个月5000元,一年600000元,离线版sdk收费标准:每年300,000元起),然后创建应用程序,获取秘钥以及密码。

    • 通读官方文献,熟悉接口是怎么用的。

      进入官网api文档,了解相关接口,这里要注意的是需要下载java版的调用接口工具,这个工具不是必须,但是它可以省去你很长时间,里面把封装好了许多函数,方面我们调用。

    需要用到技术:

    • javaSE语法,android平台相关知识(页面布局,网络通信,调取摄像头),解析json,图像压缩技术(上传大小有限制),手机权限获取。

    实现:

    • 打开AS,创建新工程,将目录结构调整为project模式,lib文件夹添加java接口调用工具。如图(1)所示,右击工具包,点击add as lib…

    • 写页面布局(这不是重点,我直接给源码),初始化控件,绑定按钮,效果如图:

    • 注册人脸(此代码可以不断完善)

    1. 调取相机,拍照。
       private void take_photo() {
            // 设置相机拍照后照片保存路径
            mPictureFile = new File(Environment.getExternalStorageDirectory(),
                    "picture" + System.currentTimeMillis()/1000 + ".jpg");
            // 启动拍照,并保存到临时文件
            Intent mIntent = new Intent();
            mIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
            mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mPictureFile));
            mIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
            startActivityForResult(mIntent, REQUEST_CAMERA_IMAGE);
        }
    
    1. 将图片压缩,显示在ImageView中
    if (requestCode == REQUEST_CAMERA_IMAGE) {
                if (null == mPictureFile) {
                    showTip("拍照失败,请重试");
                    return;
                }
    
    
                fileSrc = mPictureFile.getAbsolutePath();
                updateGallery(fileSrc);
                // 跳转到图片裁剪页面
                FaceUtil.cropPicture(this,Uri.fromFile(new File(fileSrc)));
            } else if (requestCode == FaceUtil.REQUEST_CROP_IMAGE) {
                // 获取返回数据
                Bitmap bmp = data.getParcelableExtra("data");
                // 若返回数据不为null,保存至本地,防止裁剪时未能正常保存
                if(null != bmp){
                    FaceUtil.saveBitmapToFile(MainActivity.this, bmp);
                }
                // 获取图片保存路径
                fileSrc = FaceUtil.getImagePath(MainActivity.this);
                // 获取图片的宽和高
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                mImage = BitmapFactory.decodeFile(fileSrc, options);
    
                // 压缩图片
                options.inSampleSize = Math.max(1, (int) Math.ceil(Math.max(
                        (double) options.outWidth / 1024f,
                        (double) options.outHeight / 1024f)));
                options.inJustDecodeBounds = false;
                mImage = BitmapFactory.decodeFile(fileSrc, options);
    
    
                // 若mImageBitmap为空则图片信息不能正常获取
                if(null == mImage) {
                    showTip("图片信息无法正常获取!");
                    return;
                }
    
                // 部分手机会对图片做旋转,这里检测旋转角度
                int degree = FaceUtil.readPictureDegree(fileSrc);
                if (degree != 0) {
                    // 把图片旋转为正的方向
                    mImage = FaceUtil.rotateImage(degree, mImage);
                }
    
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
                //可根据流量及网络状况对图片进行压缩
                mImage.compress(Bitmap.CompressFormat.JPEG, 80, baos);
                mImageData = baos.toByteArray();
    
                imageView.setImageBitmap(mImage);
            }
    
    1. 将图片以二进制数组的形式传给服务器
       //图片转成二进制数组
        public  byte[] Bitmap2Bytes(Bitmap bm){
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
            return baos.toByteArray();
        }
    
    
      //控件事件调用
      CommonOperate commonOperate = new CommonOperate(key, secret, false);//创建连接
      Response response = commonOperate.detectByte(Bitmap2Bytes(mImage), 0, attributes);//以本地而形式探测
    
    1. 接收反馈数据,解析json
       if(response.getStatus() != 200){//连接不成功
                return new String(response.getContent());
            }
            String res = new String(response.getContent());//连接成功
            Log.e("response", res);//将返回的数据打印出来
            JSONObject json = new JSONObject(res);//将返回的数据转化为json数据格式
    
    1. 提取人脸face_token,将face_token加入脸集,用于后续匹配。
    String faceToken = json.optJSONArray("faces").optJSONObject(0).optString("face_token");//将face_token提取出来
           faceToken = getFaceToken(response);
    FaceSetOperate faceSetOperate=new FaceSetOperate(key, secret, false);
                        Response response1=faceSetOperate.addFaceByFaceToken(faceToken,"c0f50247c7d194f0998d555de208f0e6");```
    
    
    1. 一提示框的形式,反馈用户注册完成
    showtip("注册完成")
    private void showTip(final String str) {
            mToast.setText(str);
            mToast.show();
        } 
    
    1. 效果图
    1. 在Androidmanifest.xml中添加权限
     
    <!-- 读取网络信息状态 -->
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <!-- 如需使用人脸识别,还要添加: 摄相头权限,拍照需要用到 -->
        <uses-permission android:name="android.permission.CAMERA" />
    
    1. 总结:从结果上看,服务器把这个人的基本特性通过json数据反馈给我们,年龄22,女性,不戴眼镜,表情中立,并且这个人的face_token,和脸集的face_taken都反馈我们,这样我们可以利用这两个标识来完成我们想要的功能。
    展开全文
  • 【TCP/IP详解】【pause】以太网(PAUSE)流量控制原理

    千次阅读 多人点赞 2019-09-30 14:26:44
    以太网 数据链路层 PAUSE帧 流量控制。 摘 要: PAUSE操作实现了一种简单的停-等式流量控制机制,可以防止瞬时过载导致缓冲区溢出时不必要的帧丢失。 以太网流控的引入 硬件成本和数据帧处理速度的限制,缓冲...

    关键词:

    以太网  数据链路层  PAUSE帧  流量控制


    摘  要:

    PAUSE操作实现了一种简单的停-等式流量控制机制,可以防止瞬时过载导致缓冲区溢出时不必要的帧丢失。


    以太网流控的引入

    硬件成本和数据帧处理速度的限制,缓冲拥塞造成的丢帧率大于链路传输中位出错率,因此必须解决缓冲拥塞造成的丢帧问题。

    如何查看哪一层丢帧了?1000M网卡设备使用UDP发送数据给10M/100M网卡,会不会出现缓冲区溢出导致大量丢帧?)

    假如没有以太网流控功能,可能会造成哪些问题?

    对于以太网来说,Rx端口将会持续的接收到包,但是没有足够的空间临时存储这些包。Rx端口仅仅是简单的忽略这些输入数据包。Ethernet和TCP/IP协同合作重发这些包。然而,判决包已被丢弃,请求这些重新发送,最后发送包将耗费时间

     


    以太网流量控制技术

    IEEE802.3x标准定义了一种新方法,在全双工环境中去实现流量控制(PAUSE

    流量控制是作为一种减少接收包缓冲区溢出的可能性的方法来实现的,这种溢出会导致接收包的丢失,并允许对网络拥塞级别进行本地控制。这可以通过向发射站发送接收站中几乎满的接收缓冲区状态的指示来实现

    IEEE802.3z标准定义了非对称流量控制的具体操作(ASM_DIR)。

    非对称流控制的实现允许一个链路伙伴发送流控制数据包,同时允许忽略它们的接收。例如,不需要响应暂停帧。


    以太网流量控制-PAUSE帧

    在IEEE802.3协议中规定中,PAUSE帧是一种控制帧,用于控制数据流停止发送,在MAC 发送侧产生,在MAC接收侧解析并执行。当此端设备输入数据量过大,无法及时处理时会在此端发送侧MAC产生PAUSE帧,发给对端,要求对端在一定时间内停止发送数据。

    在全双工MAC控制框架下,流量控制机制是通过PAUSE功能实现的。如果某个端口要停止帧的接收,可以发送一个带有时间参数的PAUSE帧,参数指示全双工链路对方在开始发送数据前需要等待的时间,收到PAUSE帧的设备通过简单的解析,就可以确定停止发送的时长。当链路对方接收到PAUSE帧后,在参数指定的时间内停止发送数据。当指定时间超出,或原拥塞端口重新发出操作参数为0的PAUSE,链路对方从暂停的位置继续发送数据帧。


    • PAUSE帧功能

    PAUSE帧操作实现了一种简单的停-等式流量控制机制。可以防止瞬时过载导致缓冲区溢出时不必要的帧丢失。


    • PAUSE帧位于网络协议中的哪一层?

    PAUSE帧位于网络报文协议中的数据链路层(详细点讲应该是数据链路层中的MAC控制子层)。

    IEEE802.3 将数据链路层分为三层:LLCMAC控制子层(可选)和MAC介质访问控制子层

    MAC控制子层规定了通用的全双工流量控制结构。

    交换控制电路要防止缓冲区溢出,可以利用MAC控制子层来控制以太网介质访问控制子层的操作。当已用缓冲区容量达到一个预先设定的阈值时,端口向全双工链路对方发出停止发送数据的请求,这个请求通过MAC控制子层产生的控制帧实现。

    同样,端口可以接收由其他站点MAC控制子层产生的控制帧,控制帧夹在客户数据帧流中发送,接收方会根据帧的内容将控制帧分离出来,提交到MAC控制子层中的流量控制模块,流量控制模块解析控制帧的内容,提取帧中的控制参数,根据控制参数决定暂停发送的时间。


    • PAUSE帧格式

    PAUSE帧格式如下:

    目的地址(组播) 源地址    类型     操作码    操作参数    保留     …   校验序列
    
    (6字节)         (6字节)  (2字节)   (2字节)   (2字节)   (42字节)  …  (4字节)
    
    0180-C200-0001   xxxx     0x8808   0x0001     时间参数                   CRC

    MAC控制帧(PAUSE帧)是符合IEEE802.3协议的以太网帧,可以通过其唯一的类型域标识符(0x8808)识别。MAC控制帧在网络上的发送和接收与数据帧类似,除了前导码和帧开始符外,长度为以太网帧的最小帧长度(64字节)。MAC控制帧的数据域内,前两个字节标识了MAC控制的操作码,表示帧请求的控制功能。目前协议只定义了一种操作代码,即PAUSE操作,操作码为0x0001。操作码后是操作所需的参数,参数只用了数据字段的2个字节,数据字段中其余位将填充0。

    PAUSE帧各个字段的定义如下:

    目的地址:协议规定PAUSE的目的地址为保留的组播地址0x01-80-C2-00-00-01。

    源地址:发送PAUSE帧端口的48位MAC地址。

    类型:MAC控制帧(PAUSE帧)是符合IEEE802.3协议的以太网帧,可以通过其唯一的类型域标识符(0x8808)识别。

    操作码:恒为0x0001。其实,PAUSE帧是MAC控制帧的一种,其他类型的MAC控制帧使用不同的opcode值,此处不做详细说明。后面会谈到和PAUSE类似的PFC帧,PFC帧中该域的取值是0x0101。

    操作参数:2字节的暂停时间参数。它是PAUSE发送方请求对方停止发送数据帧的时间长度,通常为0xFFFF,时间度量单位是以当前传输速率传输512位数据所用的时间,接收方实际暂停的时间为操作参数字段内容与以当前传输速率传输512位数据所用时间的乘积。

    校验序列(FCS):4个字节的循环冗余校验序列(CRC)字段。CRC 是一种数学算法,MAC发送侧(MAC_TX)创建每个帧时都将运行它。MAC接收侧(MAC_RX)接收到帧时以preamble, SFD, DA, SA, Length/Type, DATA and Pading,作为输入数据进行 CRC 计算,计算结果与接收帧的FCS字段比较,结果相同表示帧有效,结果不同接收方认为发生了错误,进而将帧丢弃。

    使用wireshark软件分析PAUSE帧:


    • PAUSE帧处理流程

    如图所示,左侧为本端芯片,右侧为对端芯片。

    MAC0和MAC1都包含发送侧tx和接收侧rx。左侧芯片内部mac上游模块A与mac0发送侧有流控信号fc_rdy。信号高表示模块A无法及时处理输入数据,需要进行流控。为了方便突出重点,图中省略了PCS以及serdes等模块。

    具体流程处理如下:
    
    1~2步:对端mac1发送数据给mac0接收侧,进行发送到模块A
    
    3步:模块A无法即使处理输入的数据,需要减少数据输入,从而将fc_rdy拉高。
    
    4步:mac0发送侧tx发现流控信号fc_rdy为高,产生pause帧,发送给mac1接收侧。只要fc_rdy为高,mac0发送侧tx每隔一段时间发送一个pause帧,间隔时间由配置寄存器控制。间隔时长计算由计数器counting计算。Pause帧内停止发送数据的时间由另外一个配置寄存器控制。只要fc_rdy为高期间,mac0发送侧不发送正常数据。
    
    5步:mac1接收侧rx接受到pause报文后,提取pause帧内包含的暂停时间,控制发送侧tx停止发送数据
    
    6~7~8:mac1停止发送数据后,模块A处理完之前的数据后将fc_rdy拉低,表示mac1可以继续发送数据了。
    
    9:步:第9步分2种情况。
    
    情况1:fc_rdy拉低,并且counting在计数没有到一个间隔周期,此时发送pause帧,但是帧内暂停时间为0. Mac1接受到pause帧后,控制tx控制立即开始发送数据。
    
    情况2:fc_rdy拉低的同时,counting正好计数到一个间隔周期,此时不发送pause帧。等到上一个pause帧的暂停时间到达后,mac1发送侧tx继续发送数据。

    pause帧处理协议强制要求:

    pause的产生发送过程不能中断一个完整的数据报文。即在第4步中,fc_rdy拉高后,首先mac0 tx侧需要判断当前是否正常数据报文在传输。如果有,则需要在当前数据报文传输完成后才能发送pause帧。也就是说在发送过程中,只能在完整数据报文的间隙插入pause帧。

    新的pause报文暂停时间会覆盖上一个暂停时间。对mac1来说,当mac1接收到新的pause帧后,暂停时间以最新时间为准。

     


    流控功能分析

    在使用ethtool工具查看网卡信息中,有如下字段可以查看当前流控功能:

    (假如部分设备没有自带ethtool工具?ethtool源码可以通过Linux内核官网上下载:https://www.kernel.org/pub/software/network/ethtool/)

    [root@fe0fdb76-b761-11e9-b107-0014101e89e7 ~]# ethtool eth0
    Settings for eth0:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Full
        Supported pause frame use: Symmetric
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
                                1000baseT/Full
        Advertised pause frame use: Symmetric
        Advertised auto-negotiation: Yes
        Speed: 100Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 1
        Transceiver: internal
        Auto-negotiation: on
        MDI-X: off (auto)
        Supports Wake-on: pumbg
        Wake-on: g
        Current message level: 0x00000007 (7)
                       drv probe link
        Link detected: yes

        其中“Advertised pause frame use”表示当前流控的模式,直接通过ethtool源码找到什么情况下会打印“Symmetric”。

    fprintf(stdout, "       %s pause frame use: ", prefix);
    if (ethtool_link_mode_test_bit(
    ETHTOOL_LINK_MODE_Pause_BIT, mask)) {
    fprintf(stdout, "Symmetric");
    if (ethtool_link_mode_test_bit(
    ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask))
    fprintf(stdout, " Receive-only");
    fprintf(stdout, "\n");
    } else {
    if (ethtool_link_mode_test_bit(
    ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask))
    fprintf(stdout, "Transmit-only\n");
    else
    fprintf(stdout, "No\n");
    }

        根据源码,可以得出一个结论:

    ETHTOOL_LINK_MODE_Pause_BIT

    ETHTOOL_LINK_MODE_Asym_Pause_BIT

    输出结果

    0

    0

    No

    0

    1

    Symmetric Transmit-only

    1

    0

    Symmetric

    1

    1

    Symmetric Receive-only

        源码中涉及到两个宏定义如下:

        ETHTOOL_LINK_MODE_Pause_BIT         = 13,      /* IEEE802.3x标准定义流控 */
    
        ETHTOOL_LINK_MODE_Asym_Pause_BIT    = 14,      /* IEEE802.3z标准定义非对称流控 */

        可能会有人问两个宏定义具体是什么意思?在上文写流控技术的引入时,有提到:

    IEEE802.3x标准定义了在全双工环境中去实现流量控制。
    
    流量控制是作为一种减少接收包缓冲区溢出的可能性的方法来实现的,这种溢出会导致接收包的丢失,并允许对网络拥塞级别进行本地控制。这可以通过向发射站发送接收站中几乎满的接收缓冲区状态的指示来实现。
    
    IEEE802.3z标准定义了非对称流量控制的具体操作。
    
    非对称流控制的实现允许一个链路伙伴发送流控制数据包,同时允许忽略它们的接收。例如,不需要响应暂停帧。

    在802.3标准文档中,有相关的描述,如下图:

    https://img-blog.csdn.net/20150411183651243

    从描述上看到,802.3标准文档中的描述和ethtool源码是能对应上的。“PAUSE”是标准流控控制,“ASM_DIR”是非对称流控控制。关于本地设备(网卡)和对端设备(交换机)的详细关系如下:

    从图中可以明白,流控必须需要本地和对端都支持才行,否则只有一侧流控功能开启,是不生效的。其次,假如两端都开启了“PAUSE”功能,则都支持流控发送和接收。如果本地端没有开启“PAUSE”但开启了“ASM_DIR”功能,则需要判断对端是否都开启了“PAUSE”和“ASM_DIR”,若是,则本地端只能发送流控、对端只能接收流控。

    再来看I211网卡手册中的PHY芯片寄存器截图:

    表明当前网卡对应PHY的硬件上是支持标准流控和非对称流控功能的。也可以通过读PHY寄存器上的这两个位数据,确认当前的流控模式。

    再看I211网卡手册中的MAC寄存器截图:


    • 驱动中的流控支持

    同样的,驱动中也有对流控功能的相关描述,以I211网卡为例,网卡驱动对应“driver/net/Ethernet/inetl/igb/”目录下,流控功能相关描述如下:

           /* Two bits in the Auto Negotiation Advertisement Register
    
             * (Address 4) and two bits in the Auto Negotiation Base
    
             * Page Ability Register (Address 5) determine flow control
    
             * for both the PHY and the link partner.  The following
    
             * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
    
             * 1999, describes these PAUSE resolution bits and how flow
    
             * control is determined based upon these settings.
    
             * NOTE:  DC = Don't Care
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
            * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
    
            *-------|---------|-------|---------|--------------------
    
            *   0   |    0    |  DC   |   DC    | e1000_fc_none
    
            *   0   |    1    |   0   |   DC    | e1000_fc_none
    
            *   0   |    1    |   1   |    0    | e1000_fc_none
    
            *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
    
            *   1   |    0    |   0   |   DC    | e1000_fc_none
    
            *   1   |   DC    |   1   |   DC    | e1000_fc_full
    
            *   1   |    1    |   0   |    0    | e1000_fc_none
    
            *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
    
             *
    
             * Are both PAUSE bits set to 1?  If so, this implies
    
             * Symmetric Flow Control is enabled at both ends.  The
    
             * ASM_DIR bits are irrelevant per the spec.
    
             *
    
             * For Symmetric Flow Control:
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
    
             *-------|---------|-------|---------|--------------------
    
             *   1   |   DC    |   1   |   DC    | E1000_fc_full
    
             *
    
             */

    完整的流控初始化源码:

    /**
    
     *  igb_config_fc_after_link_up - 建立连接后的流控设置
    
     *  @hw: 指向HW结构的指针
    
     *  检查连接后的自动连接状态,确保全双工和传输速度不是被强制设置的
    
     *  如果链接必须被强制设置,那么流控也必须被强制设置
    
     *  如果自动协商是被开启的,并且没有失败,那么我们会根据链接伙伴状态进流控行配置
    
     **/
    
    s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
    
    {
    
        struct e1000_mac_info *mac = &hw->mac;
    
        s32 ret_val = 0;
    
        u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg;
    
        u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
    
        u16 speed, duplex;
    
    
        /* Check for the case where we have fiber media and auto-neg failed
    
         * so we had to force link.  In this case, we need to force the
    
         * configuration of the MAC to match the "fc" parameter.
    
         * 检查以下情况:当有光纤介质同时自适配失败,我们就不得不强制设置链接状态
    
         * 在这种情况下,我们也必须要强制配置MAC的“流控”参数
    
         */
    
        if (mac->autoneg_failed) {
    
            if (hw->phy.media_type == e1000_media_type_internal_serdes)
    
                ret_val = igb_force_mac_fc(hw);
    
        } else {
    
            if (hw->phy.media_type == e1000_media_type_copper)
    
                ret_val = igb_force_mac_fc(hw);
    
        }
    
    
        if (ret_val) {
    
            hw_dbg("Error forcing flow control settings\n");
    
            goto out;
    
        }
    
    
        /* Check for the case where we have copper media and auto-neg is
    
         * enabled.  In this case, we need to check and see if Auto-Neg
    
         * has completed, and if so, how the PHY and link partner has
    
         * flow control configured.
    
         * 检查以下情况:当有铜介质同时自适配使能,
    
         * 在这种情况下,我们需要检查自适配是否完成了,
    
         * 如果已经完成了,那么PHY和对端的流控需要配置
    
         */
    
        if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
    
            /* Read the MII Status Register and check to see if AutoNeg
    
             * has completed.  We read this twice because this reg has
    
             * some "sticky" (latched) bits.
    
             * 读取 MII 状态寄存器来检测自适配是否完成
    
             * 我们读取了两次寄存器,因为这个寄存器有一点“粘性”
    
             */
    
            ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
    
                               &mii_status_reg);
    
            if (ret_val)
    
                goto out;
    
            ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
    
                               &mii_status_reg);
    
            if (ret_val)
    
                goto out;
    
    
            if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
    
                hw_dbg("Copper PHY and Auto Neg has not completed.\n");
    
                goto out;
    
            }
    
    
            /* The AutoNeg process has completed, so we now need to
    
             * read both the Auto Negotiation Advertisement
    
             * Register (Address 4) and the Auto_Negotiation Base
    
             * Page Ability Register (Address 5) to determine how
    
             * flow control was negotiated.
    
             * 自适配过程已经完成,我们需要读PHY Register 4和PHY Register 5寄存器
    
             * 去决定如何配置流控
    
             */
    
            ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
    
                            &mii_nway_adv_reg);
    
            if (ret_val)
    
                goto out;
    
            ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
    
                            &mii_nway_lp_ability_reg);
    
            if (ret_val)
    
                goto out;
    
    
            /* Two bits in the Auto Negotiation Advertisement Register
    
             * (Address 4) and two bits in the Auto Negotiation Base
    
             * Page Ability Register (Address 5) determine flow control
    
             * for both the PHY and the link partner.  The following
    
             * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
    
             * 1999, describes these PAUSE resolution bits and how flow
    
             * control is determined based upon these settings.
    
             * NOTE:  DC = Don't Care
    
             * PHY Register 4和PHY Register 5寄存器中的
    
             * “PAUSE”,“ASM_DIR”两位决定了PHY和对端的流控控制模式
    
             * 下面的表摘自1999年3月25日的IEEE 802.3ab/D6.0
    
             * 描述了这些暂停分辨率位以及如何根据这些设置确定流量控制
    
             * (DC表示忽略,不用在意)
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
    
             *-------|---------|-------|---------|--------------------
    
             *   0   |    0    |  DC   |   DC    | e1000_fc_none
    
             *   0   |    1    |   0   |   DC    | e1000_fc_none
    
             *   0   |    1    |   1   |    0    | e1000_fc_none
    
             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
    
             *   1   |    0    |   0   |   DC    | e1000_fc_none
    
             *   1   |   DC    |   1   |   DC    | e1000_fc_full
    
             *   1   |    1    |   0   |    0    | e1000_fc_none
    
             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
    
             *
    
             * Are both PAUSE bits set to 1?  If so, this implies
    
             * Symmetric Flow Control is enabled at both ends.  The
    
             * ASM_DIR bits are irrelevant per the spec.
    
             * 如果PHY和对端的PAUSE位都为1?
    
             * 那么,“ASM_DIR”这一位(非对称流量控制)就没用了
    
             * 在两端都开启标准流量控制位的时候,“ASM_DIR”位可以忽略。
    
             *
    
             * For Symmetric Flow Control:
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
    
             *-------|---------|-------|---------|--------------------
    
             *   1   |   DC    |   1   |   DC    | E1000_fc_full
    
             *
    
             */
    
            if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
    
                (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
    
                /* Now we need to check if the user selected RX ONLY
    
                 * of pause frames.  In this case, we had to advertise
    
                 * FULL flow control because we could not advertise RX
    
                 * ONLY. Hence, we must now check to see if we need to
    
                 * turn OFF  the TRANSMISSION of PAUSE frames.
    
                 * 在PHY和对端都开启“PAUSE”位时,
    
                 * 我们需要判断用户是否希望设置为e1000_fc_rx_pause模式
    
                 * 但在这种情况下,我们不得不将流控设置为e1000_fc_full,
    
                 * 因此,我们必须检查暂停帧的传输是否被关闭了
    
                 */
    
                if (hw->fc.requested_mode == e1000_fc_full) {
    
                    hw->fc.current_mode = e1000_fc_full;
    
                    hw_dbg("Flow Control = FULL.\n");
    
                } else {
    
                    hw->fc.current_mode = e1000_fc_rx_pause;
    
                    hw_dbg("Flow Control = RX PAUSE frames only.\n");
    
                }
    
            }
    
            /* For receiving PAUSE frames ONLY.
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
    
             *-------|---------|-------|---------|--------------------
    
             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
    
             */
    
            else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
    
                  (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
    
                  (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
    
                  (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
    
                hw->fc.current_mode = e1000_fc_tx_pause;
    
                hw_dbg("Flow Control = TX PAUSE frames only.\n");
    
            }
    
            /* For transmitting PAUSE frames ONLY.
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
    
             *-------|---------|-------|---------|--------------------
    
             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
    
             */
    
            else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
    
                 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
    
                 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
    
                 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
    
                hw->fc.current_mode = e1000_fc_rx_pause;
    
                hw_dbg("Flow Control = RX PAUSE frames only.\n");
    
            }
    
            /* Per the IEEE spec, at this point flow control should be
    
             * disabled.  However, we want to consider that we could
    
             * be connected to a legacy switch that doesn't advertise
    
             * desired flow control, but can be forced on the link
    
             * partner.  So if we advertised no flow control, that is
    
             * what we will resolve to.  If we advertised some kind of
    
             * receive capability (Rx Pause Only or Full Flow Control)
    
             * and the link partner advertised none, we will configure
    
             * ourselves to enable Rx Flow Control only.  We can do
    
             * this safely for two reasons:  If the link partner really
    
             * didn't want flow control enabled, and we enable Rx, no
    
             * harm done since we won't be receiving any PAUSE frames
    
             * anyway.  If the intent on the link partner was to have
    
             * flow control enabled, then by us enabling RX only, we
    
             * can at least receive pause frames and process them.
    
             * This is a good idea because in most cases, since we are
    
             * predominantly a server NIC, more times than not we will
    
             * be asked to delay transmission of packets than asking
    
             * our link partner to pause transmission of frames.
    
             * 根据IEEE标准,此时应该禁用流控。
    
             * 但是我们希望可以遗留一个开关,与上述表格无关,可以强制的进行设置,
    
             * 这就是我们想要做的事情。
    
             * 如果当前PHY设置了“PAUSE”,“ASM_DIR”但是对端没有设置任何功能,
    
             * 那么我们也可以设置为只启用“RX”流控功能。
    
             * 这么做是非常安全的:
    
             * 1.对端连接伙伴没有设置流控,那么我们只启用RX,不会对对端造成任何伤害
    
             * 2.如果对端连接伙伴想要使能流控,那么我们至少可以接收暂停帧并处理它们,
    
             *   这是一个好主意。因为在大多数情况下,我们主要是一个服务器,
    
             *   我们会被要求延迟包的传输,而不是让对端暂停传输
    
             */
    
            else if ((hw->fc.requested_mode == e1000_fc_none) ||
    
                 (hw->fc.requested_mode == e1000_fc_tx_pause) ||
    
                 (hw->fc.strict_ieee)) {
    
                hw->fc.current_mode = e1000_fc_none;
    
                hw_dbg("Flow Control = NONE.\n");
    
            } else {
    
                hw->fc.current_mode = e1000_fc_rx_pause;
    
                hw_dbg("Flow Control = RX PAUSE frames only.\n");
    
            }
    
    
            /* Now we need to do one last check...  If we auto-
    
             * negotiated to HALF DUPLEX, flow control should not be
    
             * enabled per IEEE 802.3 spec.
    
             * 现在我们需要做最后一次检查,如果自协商到是半双工模式,
    
             * 那么根据IEEE标准,流控不能被开启
    
             */
    
            ret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex);
    
            if (ret_val) {
    
                hw_dbg("Error getting link speed and duplex\n");
    
                goto out;
    
            }
    
    
            if (duplex == HALF_DUPLEX)
    
                hw->fc.current_mode = e1000_fc_none;
    
    
            /* Now we call a subroutine to actually force the MAC
    
             * controller to use the correct flow control settings.
    
             * 现在我们可以调用函数来强制设置MAC的流控
    
             */
    
            ret_val = igb_force_mac_fc(hw);
    
            if (ret_val) {
    
                hw_dbg("Error forcing flow control settings\n");
    
                goto out;
    
            }
    
        }
    
        /* Check for the case where we have SerDes media and auto-neg is
    
         * enabled.  In this case, we need to check and see if Auto-Neg
    
         * has completed, and if so, how the PHY and link partner has
    
         * flow control configured.
    
         * 检查是否 SerDes 介质同时自协商是否使能,
    
         * 在这种情况下,我们需要检查自协商是否完成,
    
         * 如果已经完成,那么PHY和对端的流控需要配置
    
         */
    
        if ((hw->phy.media_type == e1000_media_type_internal_serdes)
    
            && mac->autoneg) {
    
            /* Read the PCS_LSTS and check to see if AutoNeg
    
             * has completed.
    
             * 读取PCS_LSTS位判断自协商是否完成
    
             */
    
            pcs_status_reg = rd32(E1000_PCS_LSTAT);
    
    
            if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) {
    
                hw_dbg("PCS Auto Neg has not completed.\n");
    
                return ret_val;
    
            }
    
    
            /* The AutoNeg process has completed, so we now need to
    
             * read both the Auto Negotiation Advertisement
    
             * Register (PCS_ANADV) and the Auto_Negotiation Base
    
             * Page Ability Register (PCS_LPAB) to determine how
    
             * flow control was negotiated.
    
             * 自协商已经完成,那么我们需要读取PCS_ANADV、PCS_LPAB位来协商如何设置流控模式
    
             */
    
            pcs_adv_reg = rd32(E1000_PCS_ANADV);
    
            pcs_lp_ability_reg = rd32(E1000_PCS_LPAB);
    
    
            /* Two bits in the Auto Negotiation Advertisement Register
    
             * (PCS_ANADV) and two bits in the Auto Negotiation Base
    
             * Page Ability Register (PCS_LPAB) determine flow control
    
             * for both the PHY and the link partner.  The following
    
             * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
    
             * 1999, describes these PAUSE resolution bits and how flow
    
             * control is determined based upon these settings.
    
             * NOTE:  DC = Don't Care
    
             * PHY Register 4和PHY Register 5寄存器中的
    
             * “PAUSE”,“ASM_DIR”两位决定了PHY和对端的流控控制模式
    
             * 下面的表摘自1999年3月25日的IEEE 802.3ab/D6.0
    
             * 描述了这些暂停分辨率位以及如何根据这些设置确定流量控制
    
             * (DC表示忽略,不用在意)
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
    
             *-------|---------|-------|---------|--------------------
    
             *   0   |    0    |  DC   |   DC    | e1000_fc_none
    
             *   0   |    1    |   0   |   DC    | e1000_fc_none
    
             *   0   |    1    |   1   |    0    | e1000_fc_none
    
             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
    
             *   1   |    0    |   0   |   DC    | e1000_fc_none
    
             *   1   |   DC    |   1   |   DC    | e1000_fc_full
    
             *   1   |    1    |   0   |    0    | e1000_fc_none
    
             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
    
             *
    
             * Are both PAUSE bits set to 1?  If so, this implies
    
             * Symmetric Flow Control is enabled at both ends.  The
    
             * ASM_DIR bits are irrelevant per the spec.
    
             * 如果PHY和对端的PAUSE位都为1?
    
             * 那么,“ASM_DIR”这一位(非对称流量控制)就没用了
    
             * 在两端都开启标准流量控制位的时候,“ASM_DIR”位可以忽略。
    
             *
    
             * For Symmetric Flow Control:
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
    
             *-------|---------|-------|---------|--------------------
    
             *   1   |   DC    |   1   |   DC    | e1000_fc_full
    
             *
    
             */
    
            if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
    
                (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) {
    
                /* Now we need to check if the user selected Rx ONLY
    
                 * of pause frames.  In this case, we had to advertise
    
                 * FULL flow control because we could not advertise Rx
    
                 * ONLY. Hence, we must now check to see if we need to
    
                 * turn OFF the TRANSMISSION of PAUSE frames.
    
                 * 在PHY和对端都开启“PAUSE”位时,
    
                 * 我们需要判断用户是否希望设置为e1000_fc_rx_pause模式
    
                 * 但在这种情况下,我们不得不将流控设置为e1000_fc_full,
    
                 * 因此,我们必须检查暂停帧的传输是否被关闭了
    
                 */
    
                if (hw->fc.requested_mode == e1000_fc_full) {
    
                    hw->fc.current_mode = e1000_fc_full;
    
                    hw_dbg("Flow Control = FULL.\n");
    
                } else {
    
                    hw->fc.current_mode = e1000_fc_rx_pause;
    
                    hw_dbg("Flow Control = Rx PAUSE frames only.\n");
    
                }
    
            }
    
            /* For receiving PAUSE frames ONLY.
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
    
             *-------|---------|-------|---------|--------------------
    
             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
    
             */
    
            else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) &&
    
                  (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
    
                  (pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
    
                  (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
    
                hw->fc.current_mode = e1000_fc_tx_pause;
    
                hw_dbg("Flow Control = Tx PAUSE frames only.\n");
    
            }
    
            /* For transmitting PAUSE frames ONLY.
    
             *
    
             *   LOCAL DEVICE  |   LINK PARTNER
    
             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
    
             *-------|---------|-------|---------|--------------------
    
             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
    
             */
    
            else if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
    
                 (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
    
                 !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
    
                 (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
    
                hw->fc.current_mode = e1000_fc_rx_pause;
    
                hw_dbg("Flow Control = Rx PAUSE frames only.\n");
    
            } else {
    
                /* Per the IEEE spec, at this point flow control
    
                 * should be disabled.
    
                 */
    
                hw->fc.current_mode = e1000_fc_none;
    
                hw_dbg("Flow Control = NONE.\n");
    
            }
    
    
            /* Now we call a subroutine to actually force the MAC
    
             * controller to use the correct flow control settings.
    
             * 现在我们可以调用函数来强制设置MAC的流控
    
             */
    
            pcs_ctrl_reg = rd32(E1000_PCS_LCTL);
    
            pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL;
    
            wr32(E1000_PCS_LCTL, pcs_ctrl_reg);
    
    
            ret_val = igb_force_mac_fc(hw);
    
            if (ret_val) {
    
                hw_dbg("Error forcing flow control settings\n");
    
                return ret_val;
    
            }
    
        }
    
    
    out:
    
        return ret_val;
    
    }

    • ethtool工具设置流控功能具体流程追踪

    ethtool是一个非常强大的网络工具,可以通过ethtool排查很多网卡的状态等信息,进而分析当前的网络问题。

    本文原本是主要分析流控相关驱动的,但是因为调试的时候发现,流控功能好像并没有被开启,即使用了ethtool工具查看并设置当前的流控,也没有效果,因此尝试追踪一下源码,找到流控对应的调用关系,并排查问题。

    首先,ethtool通过-a参数选择开启/关闭流控,源码如下(节段部分):

        { "-a|--show-pause", 1, do_gpause, "Show pause options" },
    
        { "-A|--pause", 1, do_spause, "Set pause options",
    
          "     [ autoneg on|off ]\n"
    
          "     [ rx on|off ]\n"
    
          "     [ tx on|off ]\n" },

    在ethtool源码中,调用do_gpause函数查看流控功能,调用do_spause函数设置流控功能。继续追踪do_spause函数,源码如下:

    static int do_spause(struct cmd_context *ctx)
    
    {
    
    …
    
        /* 获取pause参数 */
    
        parse_generic_cmdline(ctx, &gpause_changed,
    
                      cmdline_pause, ARRAY_SIZE(cmdline_pause));
    
    …
    
        /* 读取当前硬件pause设置 */
    
        epause.cmd = ETHTOOL_GPAUSEPARAM;
    
        err = send_ioctl(ctx, &epause);
    
    …
    
        /* 比较当前硬件pause设置是否与传入参数相同,相同则退出 */
    
        do_generic_set(cmdline_pause, ARRAY_SIZE(cmdline_pause), &changed);
    
        if (!changed) {
    
            fprintf(stderr, "no pause parameters changed, aborting\n");
    
            return 78;
    
        }
    
    …
    
        /* 硬件pause设置 */
    
        epause.cmd = ETHTOOL_SPAUSEPARAM;
    
        err = send_ioctl(ctx, &epause);
    
    …
    
    }

        其中send_ioctl函数会最终通过ioctl方式与驱动中的network device ioctl之间调用。Seng_ioctl函数源码如下:

    int send_ioctl(struct cmd_context *ctx, void *cmd)
    
    {
    
        ctx->ifr.ifr_data = cmd;
    
        return ioctl(ctx->fd, SIOCETHTOOL, &ctx->ifr);
    
    }

        send_ioctl函数中的ioctl最终会调用network device ioctl,在驱动中,network device ioctl对应dev_ioctl函数,源码如下(net/core/dev_ioctl.c):

    int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
    
    {
    
    …
    
        case SIOCETHTOOL:
    
            dev_load(net, ifr.ifr_name);
    
            rtnl_lock();
    
            ret = dev_ethtool(net, &ifr);
    
            rtnl_unlock();
    
    …
    
    }

        dev_ioctl函数会根据“SIOCETHTOOL”选择调用dev_ethtool函数,源码如下(net/core/ethtool.c):

    int dev_ethtool(struct net *net, struct ifreq *ifr)
    
    {
    
    …
    
        if (dev->ethtool_ops->begin) {            /* ethtool初始化 */
    
            rc = dev->ethtool_ops->begin(dev);
    
            if (rc  < 0)
    
                return rc;
    
        }
    
    …
    
        case ETHTOOL_SPAUSEPARAM:
    
            rc = ethtool_set_pauseparam(dev, useraddr);
    
            break;
    
    …
    
        if (dev->ethtool_ops->complete)          /* ethtool操作完成 */
    
            dev->ethtool_ops->complete(dev);
    
        if (old_features != dev->features)       /* 如果发生变化,设备更改特性*/
    
            netdev_features_change(dev);
    
    }

        继续追踪ethtool_set_pauseparam函数,源码如下(net/core/ethtool.c):

    static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr)
    
    {
    
        struct ethtool_pauseparam pauseparam;
    
    …
    
        if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam)))
    
            return -EFAULT;
    
        return dev->ethtool_ops->set_pauseparam(dev, &pauseparam);
    
    }

        ethtool_ops->set_pauseparam会在对应的网卡驱动中去配置,以I211驱动为例,对应源码如下(driver/net/Ethernet/intel/igb/igb_ethtool.c):

    static const struct ethtool_ops igb_ethtool_ops  = {
    
        .get_pauseparam     = igb_get_pauseparam,
    
        .set_pauseparam     = igb_set_pauseparam,
    
    }

        经过漫漫长路,终于从ethtool源码追踪到了I211网卡驱动中的设置流控函数。在igb_set_pauseparam函数中,会判断当前是否是自动适配模式,如果是自动匹配模式,直接重启网卡设备(不需要手动设置流控)。如果不是自动匹配模式,则判断ethtool传入的“rx_pause”、“tx_pause”等流控参数,最终调用igb_force_mac_fc设置对应的寄存器。

    static int igb_set_pauseparam(struct net_device *netdev,
    
                      struct ethtool_pauseparam *pause)
    
    {
    
    …
    
        if (adapter->fc_autoneg == AUTONEG_ENABLE) {
    
            hw->fc.requested_mode = e1000_fc_default;
    
            if (netif_running(adapter->netdev)) {
    
                igb_down(adapter);
    
                igb_up(adapter);
    
            } else {
    
                igb_reset(adapter);
    
            }
    
        } else {
    
            if (pause->rx_pause && pause->tx_pause)
    
                hw->fc.requested_mode = e1000_fc_full;
    
            else if (pause->rx_pause && !pause->tx_pause)
    
                hw->fc.requested_mode = e1000_fc_rx_pause;
    
            else if (!pause->rx_pause && pause->tx_pause)
    
                hw->fc.requested_mode = e1000_fc_tx_pause;
    
            else if (!pause->rx_pause && !pause->tx_pause)
    
                hw->fc.requested_mode = e1000_fc_none;
    
    
            hw->fc.current_mode = hw->fc.requested_mode;
    
            retval = ((hw->phy.media_type == e1000_media_type_copper) ?
    
                  igb_force_mac_fc(hw) : igb_setup_link(hw));
    
        }
    
    …
    
    }

        igb_force_mac_fc函数就不继续追踪了,实际就是在函数中读取和设置流控寄存器。

    /**
    
     *  igb_force_mac_fc - Force the MAC's flow control settings
    
     *  @hw: pointer to the HW structure
    
     *
    
     *  Force the MAC's flow control settings.  Sets the TFCE and RFCE bits in the
    
     *  device control register to reflect the adapter settings.  TFCE and RFCE
    
     *  need to be explicitly set by software when a copper PHY is used because
    
     *  autonegotiation is managed by the PHY rather than the MAC.  Software must
    
     *  also configure these bits when link is forced on a fiber connection.
    
     **/
    
    s32 igb_force_mac_fc(struct e1000_hw *hw)
    
    {
    
        u32 ctrl;
    
        s32 ret_val = 0;
    
     printk("%s(%d)\n", __func__, __LINE__);
    
        ctrl = rd32(E1000_CTRL);
    
    
        /* Because we didn't get link via the internal auto-negotiation
    
         * mechanism (we either forced link or we got link via PHY
    
         * auto-neg), we have to manually enable/disable transmit an
    
         * receive flow control.
    
         *
    
         * The "Case" statement below enables/disable flow control
    
         * according to the "hw->fc.current_mode" parameter.
    
         *
    
         * The possible values of the "fc" parameter are:
    
         *      0:  Flow control is completely disabled
    
         *      1:  Rx flow control is enabled (we can receive pause
    
         *          frames but not send pause frames).
    
         *      2:  Tx flow control is enabled (we can send pause frames
    
         *          frames but we do not receive pause frames).
    
         *      3:  Both Rx and TX flow control (symmetric) is enabled.
    
         *  other:  No other values should be possible at this point.
    
         */
    
        hw_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
    
    
        switch (hw->fc.current_mode) {
    
        case e1000_fc_none:
    
            ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
    
            break;
    
        case e1000_fc_rx_pause:
    
            ctrl &= (~E1000_CTRL_TFCE);
    
            ctrl |= E1000_CTRL_RFCE;
    
            break;
    
        case e1000_fc_tx_pause:
    
            ctrl &= (~E1000_CTRL_RFCE);
    
            ctrl |= E1000_CTRL_TFCE;
    
            break;
    
        case e1000_fc_full:
    
            ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
    
            break;
    
        default:
    
            hw_dbg("Flow control param set incorrectly\n");
    
            ret_val = -E1000_ERR_CONFIG;
    
            goto out;
    
        }
    
    
     printk("%s(%d) hw->fc.current_mode = %u, hw->fc.requested_mode=%u\n", __func__, __LINE__, hw->fc.current_mode, hw->fc.requested_mode);
    
        wr32(E1000_CTRL, ctrl);
    
    
    out:
    
        return ret_val;
    
    }


    查看流控状态

    • 查看/设置本地设备流控状态

    可以通过“ethtool –a”命令查看流控

    参数说明:
    
    ethtool -a|--show-pause DEVNAME     Show pause options
    
    功能使用:
    
    [root@fe0fdb76-b761-11e9-b107-0014101e89e7 ~]# ethtool -a eth0
    
    Pause parameters for eth0:
    
    Autonegotiate:       on          /* 自动协商状态(假如自动协商开启,流控模式由硬件自动协商) */
    
    RX:        on              /* 流控接收状态 */
    
    TX:         on              /* 流控发送状态 */

           通过“ethtool –A”命令设置流控

    参数说明:
    
    ethtool -A|--pause DEVNAME     Set pause options
    
                  [ autoneg on|off ]          /* 启动/关闭自协商模式 */
    
                  [ rx on|off ]               /* 启动/关闭流控接收 */
    
                  [ tx on|off ]               /* 启动/关闭流控发送 */
    
    功能使用:
    
    [root@fe0fdb76-b761-11e9-b107-0014101e89e7 ~]# ethtool -A eth0 autoneg off  /* 关闭自协商 */
    
    [root@fe0fdb76-b761-11e9-b107-0014101e89e7 ~]# ethtool -A eth0 rx off       /* 关闭流控接收 */
    
    [root@fe0fdb76-b761-11e9-b107-0014101e89e7 ~]# ethtool -A eth0 tx off       /* 关闭流控发送 */

           通过PHY寄存器也可以获取当前的流控状态,可以通过“mdio”工具查看PHY上的流控状态。(mdio工具是在用户层访问smi/mdio总线,读写phy芯片寄存器的通用代码。Linux内核2.6以上通用,自行编译,源码链接:https://blog.csdn.net/Ivan804638781/article/details/98882865)

    语法说明:
    
    mdio:
    
    read operation: mdio reg_addr
    
    write operation: mdio reg_addr value
    
    For example:
    
    mdio eth0 1
    
    mdio eth0 0 0x12
    
    功能使用:
    
    [root@fe0fdb76-b761-11e9-b107-0014101e89e7 ~]# ./mdio eth0 4  /* Auto-Neg寄存器 */
    
    read phy addr: 0x1  reg: 0x4   value : 0xde1


    • 查看远端设备流控状态

    通过“mdio”工具查看远端设备的流控状态

    [root@fe0fdb76-b761-11e9-b107-0014101e89e7 ~]# ./mdio eth0 5  /* Copper Link Partner寄存器 */
    
    read phy addr: 0x1  reg: 0x5   value : 0xcde1


    • 流控寄存器描述

    以I211网卡为例,在《i210-ethernet-controller-datasheet》数据手册上有如下流控寄存器描述:

    流控低地址。流量控制数据包由802.3X定义为一个唯一的组播地址,或者一个带有指示暂停的EtherType字段的站地址。完整的流控制组播地址为:0x01_80_C2_00_00_01;

    流控高地址。该寄存器包含48位流控制以太网地址的上位。这个寄存器只有下面的16位有意义。

    以太网帧类型(0x8808代表PAUSE帧)。此寄存器包含硬件匹配的类型字段,用于识别流控制包。只有寄存器的后16位才有意义。

    流控暂停时间参数。TTV字段中的16位值被插入到传输帧中(无论是XOFF帧还是其他任何暂停帧值)。它以64字节的插槽时间为单位计数。如果软件需要发送一个XON帧,它必须在启动PAUSE帧之前将TTV设置为0x0。

    流控低水位阀值。此寄存器包含用于确定何时发送XON包的接收阈值。完整的寄存器以字节为单位反映阈值。较低的四位必须被编程为0x0(16字节粒度)。软件必须设置XONE来支持传输XON帧。每次硬件通过接收高阈值(变得更满),然后通过接收低阈值并启用XONE (1b),硬件传输一个XON帧。XONE被设置时,RTL字段应该被编程为至少0x3(至少48字节)。流量控制接收/传输是通过自动协商过程协商的功能。当手动配置I210时,流控制操作由CTRL.RFCE和CTRL.TFCE位确定。

    流控高水位阀值。此寄存器包含用于确定何时发送XOFF包的接收阈值。完整的寄存器以字节为单位反映阈值。这个值必须小于分配给接收包缓冲区的最大字节数(RXPBSIZE.RXPbsize),并且较低的四位必须被编程为0x0(16字节粒度)。RTH的值也应该大于FCRTL0.RTL(流控低水位阀值)。每当接收FIFO达到RTH所指示的满度时,如果启用了流控制帧的传输,硬件就会传输一个暂停帧。流量控制接收/传输是通过自动协商过程协商的功能。当手动配置I210时,流控制操作由CTRL.RFCE和CTRL.TFCE位确定。

    流控刷新阀值。此寄存器指示启用传输流控制时流控制计数器的阈值(CTRL.TFCE = 1b)。当计数器达到这个值时,暂停状态的条件仍然有效(缓冲区满度高于低阈值),将向链接伙伴发送暂停(XOFF)帧。如果该字段包含零值,则禁用流控制刷新

    流控状态。该寄存器描述流量控制机的状态。


    分析驱动中的流控寄存器

    通过“ethtool -d”命令查看当前网卡寄存器。

    ethtool -d|--register-dump DEVNAME  Do a register dump
    
            [ raw on|off ]
    
            [ file FILENAME ]

        查看驱动中的流控寄存器:

    [root@fe0fdb76-b761-11e9-b107-0014101e89e7 ~]# ethtool -d eth0 | grep FC
    
    0x00028: FCAL        (Flow control address low)       0x00C28001
    
    0x0002C: FCAH        (Flow control address high)      0x00000100
    
    0x00170: FCTTV       (Flow control tx timer value)    0x0000FFFF
    
    0x02160: FCRTL       (Flow control rx threshold low)  0x80007A50
    
    0x02168: FCRTH       (Flow control rx threshold high) 0x00007A60
    
    0x02460: FCRTV       (Flow control refresh threshold) 0x00000000

    读取到的寄存器值为:0x00C28001

    流控低地址。完整的流控制组播地址为:0x01_80_C2_00_00_01。

    读取到的寄存器值为:0x00000100

    流控高地址。低16位有效,完整的流控制组播地址为:0x01_80_C2_00_00_01。

    读到的寄存器值为:0x00008808

    以太网帧类型。流控帧的Type类型为0x8808。

    读到的寄存器值为:0x0000FFFF

    流控暂停时间参数。当前流控时间参数65535,时间度量单位是以当前传输速率传输512位数据所用的时间。流控暂停时间为:65535*传输512位数据所用的时间。

    读到的寄存值为:0x80007A50

    流控低水位阀值。第31位为XON使能位,开启。第4~16位表示当前的流控低阀值,第0~3位必须被编程为0x0(16字节粒度)。即当前的低水位阀值为31312字节。(I210默认分配一个36kb的片上数据包缓冲区。缓冲区用于存储数据包,直到它们被转发到主机。实际芯片上分配的接收缓冲区可以控制RXPBSIZE寄存器。)

    当前I211读到的RXPBSIZE寄存值为:0x000000A2

    (网卡驱动中的rx_ring(接收描述符缓冲区)?rx_buffer(接收数据缓冲区)?之间的关系)

    读到的寄存器值为:0x00007A60

    流控高水位阀值。第4~17位表示当前流控高阀值,第0~3位必须被编程为0x0(16字节粒度)。即当前的高水位阀值为31328字节。

    流量控制设置:高水位线必须足够低,以适应一个完整的框架(或用于早期接收)以上的Rx先进先出。将其设置为:- 90%的Rx FIFO大小,以及完整的Rx FIFO大小减去早期接收大小(对于ERT支持的部件,假设ERT设置为E1000_ERT_2048),或完整的Rx FIFO大小减去一个完整帧

    文字读起来比较难懂,直接看代码。在I211对应的网卡驱动中,设置流控高水位阀值的代码如下:

    void igb_reset(struct igb_adapter *adapter)
    
    {
    
    …
    
        /* Repartition Pba for greater than 9k mtu
    
         * To take effect CTRL.RST is required.
    
         */
    
        switch (mac->type) {
    
        case e1000_i210:
    
        case e1000_i211:
    
        default:
    
            pba = E1000_PBA_34K;
    
            break;
    
        }
    
    …
    
        /* flow control settings */
    
        /* The high water mark must be low enough to fit one full frame
    
         * (or the size used for early receive) above it in the Rx FIFO.
    
         * Set it to the lower of:
    
         * - 90% of the Rx FIFO size, or
    
         * - the full Rx FIFO size minus one full frame
    
         */
    
        hwm = min(((pba << 10) * 9 / 10),
    
                ((pba << 10) - 2 * adapter->max_frame_size));
    
    
        fc->high_water = hwm & 0xFFFFFFF0; /* 16-byte granularity */
    
        fc->low_water = fc->high_water - 16;
    
        fc->pause_time = 0xFFFF;
    
        fc->send_xon = 1;
    
        fc->current_mode = fc->requested_mode;
    
    …
    
    }

    读到的寄存器值为:0x00000000

    流控刷新阀值。表示当前禁用流控制刷新

    读到的寄存器值为:0x00000004

        流控状态。第2位为1,表示当前流控低于低水位阀值。

    驱动中其他和流控相关的寄存器

    流控功能首先硬件需要支持,通常流控帧的发送是需要硬件做的。但是驱动这边可以控制开启/关闭硬件的流控功能。

    具体体现在驱动中会配置流控相关的寄存器。

    以JD4000设备为例,网卡型号为I211,对应的网卡驱动为igb。

    在I211数据手册中,定义了下列字段:

    •CTRL.RFCE字段用于启用接收流控包并对其进行响应 
    
    •CTRL.TFCE字段用于启用流控包的传输
    
    •流控制地址低/高(FCAL/H) - 6字节流控制多播地址
    
    •流量控制类型(FCT) 16位字段,表示流量控制类型
    
    •流量控制位在设备控制(CTRL)寄存器-启用流量控制模式
    
    •丢弃暂停帧(DPF),在RCTL中传递MAC控制帧(PMCF)——控制控制数据包转发到主机
    
    •流量控制接收阈值高(FCRTH0) -一个13位高字段,表示接收缓冲区已满。
    
    •DMA合并接收阈值高(FCRTC) -当DMA合并和Tx缓冲区为空时,表示一个13位高字段表示接收缓冲区已满。
    
    •流量控制接收阈值低(FCRTL0) -一个13位低字段,表示接收缓冲区的空值。
    
    •流量控制传输定时器值(FCTTV) -一组16位定时器值,包括在传输暂停帧。
    
    •流控制刷新阈值(FCRTV) - 16位暂停刷新阈值
    
    •RXPBSIZE。Rxpbsize字段用于控制接收包缓冲区的大小


    FAQ

    pause frame的目的地址决定了它不被bridge转发,意思就是它不能经过交换机吗?

    PAUSE帧的目的地址是0180c2000001,而不是发送到A和B的mac地址!交换机并不是不转发,而是延时转发,pause帧中有2个字节用来代表停止发送时间的,过了这个时间,交换机还是会继续转发的!

    Pause帧为什么会成对出现(PAUSE帧是不是一定是成对出现的)?因为在发送PAUSE_XOFF帧后,对端就不会再发送报文了,得等到对端的暂时时间结束(文中提到的0x1FFF,8191*传输512bit所需时间),或者收到PAUSE_XON帧后,才会继续发送。这应该就是PAUSE帧成对出现的原因。

    交换机在进入流控状态后会往对端发pause帧(假设工作在全双工),查了很多资料没找到发送pause帧的时间间隔是多少。是不停地发呢还是一秒固定发几个?哪位高人指点一下。


    总结

    合理设定发出流量控制请求时机。由于全双工链路存在传播延迟和响应延迟,发出PAUSE帧后,对方不能立即停止数据帧的发送。发送方必须考虑在发出PAUSE帧后能够接收的最大数据量,避免缓冲区溢出。以太网交换控制电路支持10M/100M链路传送,最坏情况下需要考虑的因素包括:

    (1)在发送PAUSE帧前正在发送一个最长数据帧(1 536字节);

    (2)发送PAUSE帧花费的时间为512位链路传输时间;

    (3)发送帧间隔为96位链路传输时间;

    (4)对方在解析PAUSE帧的同时,正开始发送一个最长数据帧 (1 536字节);

    (5)接收帧间隔为96位链路传输时间;

    (6)链路的往返传输延迟时间。

    根据上述因素,流量控制请求发出以后,还需要大约3.2K字节的数据等待接收与缓存,PAUSE帧才能终止链路对方数据帧的发送。在设计缓冲容量和选择流量控制阈值时,需要考虑这些延迟因素,有效地实现流量控制机制,防止帧丢失。+

    展开全文
  • 摘要:本文总结提出了一种主流的机器学习加密流量分析的方法 如何在不侵犯个人隐私的前提下,在加密流量中检测恶意攻击行为,为了找到一种切实可行的“在加密流量中检测恶意攻击行为”的方法,Infosec团队借鉴了...
  • 实时人流量检测

    万次阅读 2018-05-31 13:07:45
    由于头部到 Kinect 的距离总是比身体其他部位离得更近,人数计算的问题也就等价于寻找本地数据中 局部深度值最小的区域。根据深度图的特点,water-filling算法能鲁棒地标度不变地找到这些局部区域。 整体思路: ...
  • 基于OpenCV的简单人流量统计

    万次阅读 多人点赞 2018-12-30 13:14:40
    学习OpenCV快一年了,最近做了一个简单的人流量统计的项目,分享给大家。  本次人流量统计用的是纯OpenCV的技术,没有涉及深度学习的知识,如果大家深度学习做得好的话,效果会更好。  首先介绍我的环境Windows...
  • 使用百度AI实现视频的人流量统计(静态+动态) 百度AI提供了视频监测的诸多接口,下面以人体分析-人流量统计为例介绍。 目录使用百度AI实现视频的人流量统计(静态+动态)必备条件静态人流量统计输入输出及参数说明...
  • 描述基础知识内容:多目标跟踪,车流量统计中辅助功能,卡尔曼滤波器。 汇总了各个知识结果,便于理解和复习。 我的博客地址: https://blog.csdn.net/zzx188891020
  • 近日,人脸识别技术因多次在抓逃犯的过程中“立功”,再度走“红”。从20世纪60年代起,人脸识别研究开启,发展到今天有哪些进展?该产业里的竞争,是人工智能投资泡沫带来的浮躁,还是市场规模将持续突进? 何谓...
  • 人脸识别及数据流处理

    千次阅读 2020-08-20 20:17:45
    文章目录人脸识别及数据流处理1人脸识别1.1 基础简介1.1.1 人脸识别技术1.1.2 技术介绍1.2 原理1.3识别过程1.4 技术流程1.4.1 人脸图像采集及检测1.4.2 人脸图像预处理1.4.3 人脸图像特征提取1.4.4 人脸图像匹配与...
  •   来源:与非网   这两年,随着科技的迅速发展,人脸识别已经逐渐成为了新时期生物识别技术应用的重要领域,忘记密码了?没事儿,咱还可以“刷脸”!...传统的人脸识别技术主要是基于可见光图像...
  • python数据分析-杭州市地铁站人流量【数据源—阿里云天池新人赛】 前言 天池新人实战赛是针对数据新人开设的实战练习专场,以经典赛题作为学习场景,提供详尽入门教程,手把手教你学习数据挖掘。天池希望新人赛能...
  • 通俗易懂的AI算法原理

    万次阅读 2019-06-27 08:24:55
    我想尽量用直白的语言、较少的数学知识给各位产品经理讲清楚各个算法的原理是什么。 机器学习的过程 机器学习的过程从本质上来说就是通过一堆的训练数据找到一个与理想函数(f)相接近的函数。在理想情况下,对于...
  • Android即时通讯实现原理

    万次阅读 2016-07-19 20:58:38
    即时通讯实现原理即时通讯(Instant Messenger,简称IM)软件多是基于TCP/IP和UDP进行通讯的,TCP/IP和UDP都是建立在更低层的IP协议上的两种通讯传输协议。前者是以数据流的形式,将传输数据经分割、打包后,通过两...
  • 人脸识别系统概述

    千次阅读 2014-09-03 17:21:58
    一 人脸识别系统结构 图1显示了人脸识别系统...图像质量评估模块,用于从采集的同一个的多张人脸图像中,根据人脸姿态和光照条件选择最适合识别的一张或者几张人脸进行人脸识别/认证;人脸特征提取模块用于根据眼
  • 如何识别加密协议

    千次阅读 2015-11-21 21:07:08
    加密P2P视频流的识别 背景 观看在线视频时,可以发现游览器经常偷偷地上传流量,实际上目前很多在线视频网站采用了一种RTMFP的技术来传输视频流量。采用这种P2P技术可以大大节约服务器的带宽和资源。但是一般...
  • 车牌识别论文

    千次阅读 2019-06-25 09:42:03
    在现在这个社会发展中识别车牌的这个阶段中,其中最集中和有效的内容是车牌图像分割字符技术和车牌图像提取技术。在本论文中具体的说明了一种二值化分析识别车牌的算法介绍。在设计中是在内存为64M大小,其平台是...
  • 快速统计、识别及定位的研究 摘要:  本文着重分析了在室内、地下、机井、矿井等特殊环境下,人员的快速统计、识别及高精度定位的目前行业状况,并对相关案例进行了剖析研究,从而为项目有效性实施得出可行的解决...
  • 大气压力传感器的结构原理与进气歧管压力传感器相似。  图为三菱轿车大气压力传感器与ECU连接电路图,以该传感器为例,说明大气压力传感器的检测内容。  三菱车大气压力传感器安装在空气流量计内,由惠斯登电桥...
  • DDoS原理、分类与防御

    千次阅读 2020-12-28 11:16:14
    文章主要介绍了DDoS原理与防御方法。
  • TensorFlow on Android:物体识别

    千次阅读 2017-11-24 10:04:28
    用这个模型来识别视频每一帧中的物体(、汽车等); 将识别结果可视化(在物体周围画上边框和标签)。 我们要做的是这个功能的第一步,在 Android 上面选取一张图片,识别图片中有哪些物体,并将识别结果可视...
  • 指静脉识别技术特点及应用前景

    千次阅读 2019-02-15 15:22:35
    **指静脉识别技术特点及应用前景** 指静脉识别技术利用手指静脉血管的纹理进行身份验证,对人体无害,具有不易被盗取、伪造等特点。该识别技术可广泛应用于银行金融、政府国安、教育社保等领域的门禁系统,是比...
  • 汽车牌照自动识别系统

    千次阅读 2013-02-04 11:31:36
    汽车牌照自动识别系统是以汽车牌照为特定目标的专用计算机视觉系统,是计算机视觉和模式识别技术在智能交通领域应用的重要研究课题之一,它可广泛应用于交通流量检测,交通控制与诱导,机场、港口、小区的车辆管理,...
  • 搜索意图识别浅析

    千次阅读 2018-11-09 09:10:35
    本文主要谈论和解决的是令尴尬的问题。 为什么会搜索不到 1、不同的用户对同一种诉求的表达往往是有差别的,往往会存在一种比较常见的现象,用户输入的query并不能清晰准确的表达需求。 2、搜索系统对用户query的...
  • 这是一篇计算机视觉入门指南,从概念、原理、用例等角度介绍了计算机视觉。 「机器能够模拟人类视觉系统」的幻想已经过时了。自 1960 年代第一批学术论文出现以来,计算机视觉已经走了很远,现代系统已经出现...
  • 【推荐架构day5】今日头条算法的基本原理

    万次阅读 多人点赞 2020-02-22 16:03:37
    本文来自今日头条曹欢欢博士的分享。...今日头条委托资深算法架构师曹欢欢博士,公开今日头条的算法原理,以期推动整个行业问诊算法、建言算法;通过让算法透明,来消除各界对算法的误解,并逐步推动整个行业让算...
  • 本文通过分析web指纹的检测对象、检测方法、检测原理及常用工具,设计了一个简易的指纹搜集脚本来协助发现新指纹,并提取了多个开源指纹识别工具的规则库并进行了规则重组,开发了一个简单快捷的指纹识别小工具...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,777
精华内容 9,510
关键字:

人流量识别原理