首页 > 其他分享 >【IP层的校验和与UDP的校验和】+【FPGA实现】

【IP层的校验和与UDP的校验和】+【FPGA实现】

时间:2024-04-09 11:36:00浏览次数:19  
标签:UDP wire IP 校验 数据包 reg

MAC层的校验是CRC,而IP层也有其校验机制。

CRC保证数据包的传输正确;

 

IP头校验和

IP头校验和是一种错误检测机制,用于在互联网协议(IP)中保证IP头的数据完整性。

当一个IP数据包从源主机发送到目的主机时,它经过许多路由器和交换机,校验和可以帮助这些中间设备检查数据包在传输过程中是否出现错误。

IP头校验和的计算方式如下:

  1. 分割:将IP头部分为16位(2字节)的段。
  2. 求和:将所有16位的段相加(以二进制求和,也就是每个段直接按位相加)。
  3. 进位处理:如果求和的结果产生了溢出,则将溢出的部分(即进位)加到求和的结果的最低位上。这可能需要重复进行,直到不再有溢出发生。
  4. 取反:将求和结果取反(按位取反,1变0,0变1)得到校验和。

这个校验和随后被填充在IP头中专门为校验和预留的字段内。在接收端,同样的计算会被执行在收到的IP头上,包括校验和字段本身。如果数据包在传输过程中没有错误,所有段的总和加上接收到的校验和的结果应该是一个全1的二进制数(因为原始计算中结果取反了)。如果计算结果不是全1,那么就说明数据在传输过程中可能出现了错误。

重要的是,IP头校验和只检查头部的完整性,并不保护整个IP数据包的内容。传输层(如TCP或UDP)有自己的校验和,负责整个数据段(包括数据)的完整性检查。

在实际的网络设备中,这个计算通常是由硬件来执行,以提高数据包处理的效率。当数据包通过每个路由器传输时,因为TTL字段会改变,所以需要重新计算校验和。

FPGA实现:

module emcode_checksum_ip (
    input   wire            sys_clk            ,
    input   wire            sys_rst_n          ,
    input   wire            i_vaild            ,
    input   wire  [7:0]     i_data             ,
    output  wire            o_vaild            ,
    output  wire  [7:0]     o_data                   
);
            reg   [15:0]    r_i_vaild          ;
            reg   [07:0]    r1_i_data  [15:0]  ;

            reg   [07:0]    checksum_cnt       ;
            reg   [01:0]    concat_cnt         ;
            wire  [15:0]    concat_data        ;
            reg   [31:0]    r1_sum             ;
            wire  [31:0]    r1_checksum_value  ;
            wire  [15:0]    r2_checksum_value  ;
            reg   [15:0]    r3_checksum_value  ;
            reg   [07:0]    vaild_cnt          ;
            reg   [07:0]    r_o_data           ;

    always @(posedge sys_clk) begin
        r_i_vaild <= {r_i_vaild[14:0],i_vaild};
    end

    reg [7:0] reg_i1;
    reg [7:0] reg_i2;
    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            for (reg_i1 = 0; reg_i1 < 'd15;  reg_i1 = reg_i1 + 1) begin
                r1_i_data[reg_i1] <= 'd0;
            end
        end else begin
            for (reg_i2 = 0; reg_i2 < 'd15;  reg_i2 = reg_i2 + 1) begin
                r1_i_data[reg_i2+1] <= r1_i_data[reg_i2];
            end
            r1_i_data[0] <= i_data;
        end
    end

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            checksum_cnt <= 8'h0;
        end else if(i_vaild == 1'b0 && r_i_vaild[0] == 1'b1) begin
            checksum_cnt <= 8'h0;
        end else if(i_vaild == 1'b1)begin
            checksum_cnt <= checksum_cnt + 1'b1;
        end
    end

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            vaild_cnt <= 8'h0;
        end else if(r_i_vaild[10] == 1'b0 && r_i_vaild[11] == 1'b1) begin
            vaild_cnt <= 8'h0;
        end else if(r_i_vaild[10] == 1'b1)begin
            vaild_cnt <= vaild_cnt + 1'b1;
        end
    end

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            concat_cnt <= 2'd0;
        end else if(i_vaild == 1'b0 && r_i_vaild[0] == 1'b1) begin
            concat_cnt <= 2'd0;
        end else if(i_vaild == 1'b1 && checksum_cnt >= 'd22 && checksum_cnt <= 41) begin
            if(concat_cnt == 1'b1) begin
                concat_cnt <= 2'd0;
            end else begin
                concat_cnt <= concat_cnt + 1'b1;
            end
        end else begin
            concat_cnt <= concat_cnt;
        end
    end

    assign  concat_data = {r1_i_data[0],i_data};

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            r1_sum <= 32'd0;
        end else if(i_vaild == 1'b0 && r_i_vaild[0] == 1'b1) begin
            r1_sum <= 32'd0;
        end else if(i_vaild == 1'b1 && checksum_cnt >= 'd22 && checksum_cnt <= 'd41 && concat_cnt == 1'b1) begin
            r1_sum <= r1_sum + concat_data;
        end else begin
            r1_sum <= r1_sum;
        end
    end    

    assign  r1_checksum_value =  r1_sum[15:0] + r1_sum[31:16];
    assign  r2_checksum_value = ~(r1_checksum_value[15:0]);

    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            r3_checksum_value <= 'd0;
        end else if(r_i_vaild[10] == 1'b0 && r_i_vaild[11] == 1'b1) begin
            r3_checksum_value <= 'd0;
        end else if(i_vaild == 1'b1 && checksum_cnt == 'd42) begin
            r3_checksum_value <= r2_checksum_value;
        end
    end

    assign  o_vaild = r_i_vaild[11];
    assign  o_data  = r_o_data     ;
    always @(posedge sys_clk) begin
        if(sys_rst_n == 1'b0) begin
            r_o_data <= 8'd0;
        end else if(r_i_vaild[10] == 1'b1 && vaild_cnt == 'd32) begin
            r_o_data <= r3_checksum_value[15:08];
        end else if(r_i_vaild[10] == 1'b1 && vaild_cnt == 'd33) begin
            r_o_data <= r3_checksum_value[07:00];
        end else begin
            r_o_data <= r1_i_data[10];
        end
    end
endmodule

 

UDP校验和

UDP校验和是一种错误检测机制,与IP校验和类似,但它覆盖了更多的数据:UDP校验和不仅检查UDP头部,还检查数据部分。这为UDP数据包提供了一个简单的形式的数据完整性验证。

计算UDP校验和的步骤如下:

  1. 伪头部:首先,创建一个所谓的“伪头部”,它包括源IP地址、目的IP地址、一个8位全零字段、协议字段(对于UDP,这个值是17,8‘h11)和UDP长度字段。这个伪头部不是UDP数据包的一部分,而是仅用于校验和计算过程。

  2. 合并:将伪头部、UDP头部和数据部分合并起来。如果数据的总字节长度不是偶数,会在最后添加一个零字节来填充。

  3. 分割:将合并后的数据分割成16位的段。

  4. 求和:以二进制求和这些16位的段,包括溢出。

  5. 进位处理:与IP校验和相同,如果求和的结果产生溢出,将溢出的部分加回到求和结果的最低位。

  6. 取反:将最终的求和结果取反。

 

得到的校验和随后放入UDP头部中的校验和字段。在接收端,同样的计算会被执行在整个数据包上(包括伪头部)。如果数据包传输正确,所有的16位段相加(包括校验和字段)应该结果为全1的二进制数(0xFFFF)。如果不是,那么就说明数据包在传输过程中出现了错误。

值得注意的是,UDP校验和是可选的,在IPv4中可以设置为零表示不计算校验和,但在IPv6中,UDP校验和是必需的。这是因为IPv6不包括一个独立的校验和,因此依赖于UDP校验和提供错误检测。

       

标签:UDP,wire,IP,校验,数据包,reg
From: https://www.cnblogs.com/VerweileDoch/p/18123556

相关文章

  • Javascript Promise用法详解
    1、约定本文的demo代码有些是伪代码,不可以直接执行。没有特殊说明,本文所有demo都是基于ES6规范。Object.method代表是静态方法,Object#method代表的是实例方法。如Promise#then代表的是Promise的实例方法,Promise.resolve代表的是Promise的静态方法.2、什么......
  • BNIP3作为识别实体瘤预后和诊断的潜在生物标志物
    介绍本文复现的是一篇单基因泛癌的文章,原文链接:BNIP3asapotentialbiomarkerfortheidentificationofprognosisanddiagnosisinsolidtumours视频链接:零代码复现1-BNIP3作为识别实体瘤预后和诊断的潜在生物标志物工具链接:http://www.sxdyc.com/zeroCodeTool本......
  • 剪映PC电脑版开心版5.5.0免VIP导出补丁下载_替换一次即可长期使用
    剪映5.5.0免VIP导出补丁来了,可以使用VIP特效,文字转语音声效,滤镜,等全部需要VIP的素材,都可以直接导出,不需要VIP并且是需要替换一次,每次启动软件都是可以直接导出的,只要不重新安装剪映,都是可以使用的补丁对应版本:5.5.0(不是5.5.0版本会出现闪退)补丁安全无毒无广告使用教程:打开......
  • Firefox火狐浏览器控制台,提示:已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1
    前言全局说明Firefox火狐浏览器控制台,提示:已拦截跨源请求一、火狐官方说明https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS/Errors/CORSMissingAllowOrigin?utm_source=devtools&utm_medium=firefox-cors-errors&utm_campaign=default二、修改浏览器方法[原文......
  • openGauss 用户口令强度校验机制
    用户口令强度校验机制可获得性本特性自openGauss1.1.0版本开始引入。特性简介对用户访问数据库所设置的口令强度进行校验。客户价值用户无法设置过低强度的口令,加固客户数据安全。特性描述初始化数据库、创建用户、修改用户时需要指定密码。密码必须满足强度校验,否则会提......
  • 「Java开发指南」如何利用MyEclipse启用Spring DSL?(一)
    本教程将引导您通过启用SpringDSL和使用ServiceSpringDSL抽象来引导Spring和Spring代码生成项目,本教程中学习的技能也可以很容易地应用于其他抽象。在本教程中,您将学习如何:为SpringDSL初始化一个项目创建一个模型包创建一个服务和操作实现一个服务方法启用JAX-WS和DWR......
  • 敌人——创建敌人Sniper
    目标创建一个继承自Enemy的敌人Sniper创建SniperAI1.创建一个继承自Enemy的敌人Sniper从子弹父类蓝图中创建一个子类蓝图(逻辑和玩家子弹一样,只是更改一下Tag为Player)敌人角色蓝图Sniper编写一个调用子弹蓝图的逻辑,作为发射子弹创建一个敌人列举将Sniper的列举配置好......
  • 网络基础三——IP协议补充
    3.网段划分3.1IP划分的前置知识​IP地址分为两个部分,网络号和主机号;网络号:保证两个相互连接的网段具有不同的标识;主机号:同一个网段内,主机之间具有相同的网段号,但是必须具有不同的主机号;​1.路由器也是特定一个子网的主机,所以路由器也要配置IP地址;​2.路由器可以跨网......
  • Datacom HCIP笔记-MPLS协议 之一
    MPLS标签放在二层头和IP头之间可以称之为2.5层的位置LSP(LabelSwitchedPath):标签交换路径,艮即到达同一目的地址的报文在MPLS网络中经过的路径。FEC(ForwardingEquivalentClass):一般指具有相同转发处理方式的报文。在MPLS网络中,到达同一目的地址的所有报文就是一个FEC。......
  • 校验ChatGPT 4真实性的三个经典问题:提供免费测试网站快速区分 GPT3.5 与 GPT4
    现在已经有很多ChatGPT的套壳网站,以下分享验明GPT-4真身的三个经典问题,帮助你快速区分套壳网站背后到底用的是GPT-3.5还是GPT-4。大家可以在这个网站测试:https://ai.hxkj.vip,免登录可以问三条,登录之后无限制。咱们使用免登录的额度测试就已经够用了测试问题1:Wha......