【朝花夕拾】RT1060 ICMP硬件checksum插入方法

一, 文章简介

ICMP(Internet Control Message Protocol,英特网控制报文协议),常用于网络的调试与维护. ICMP通常被认为是IP层协议的一部分,但从体系结构上,它是位于IP层之上。
在这里插入图片描述

图1
Ping命令使用的就是ICMP的查询报文,如果能ping成功,说明网卡、IP层、ICMP层是能正常通信的。
对于RT1060,可以支持ICMP的硬件checksum插入,所涉及的控制寄存器相关位为:
在这里插入图片描述

图2
那么,如何在现有的RT1060 LWIP SDK ping工程中加入ICMP的硬件checksum呢?SDK ping工程默认是使用软件checksum。如果要测试ICMP硬件checksum的插入,首先需要关闭软件checksum,然后才能通过配置RT1060 ENET IP的TACC寄存器中的IPCHK, PROCHK 位去使能硬件checksum。IPCHK控制的是IP头checksum,PROCHK控制的是message protocol checksum。
小编在测试的时候,遇到了一些坑,开始只是简单的使能了lwipopts.h中的CHECKSUM_BY_HARDWARE宏,认为该宏是直接控制所有的软硬件checksum选择,但是测试发现该宏只能去掉软件ICMP报文中的IP checksum,但是报文中的message protocol的checksum还是存在,这种情况只能测试IP硬件checksum的插入,无法测试message protocol 硬件checksum的插入,就像下图一样:
在这里插入图片描述

图 3
可以发现,报文中IP checksum已经关闭,但是message protocol的checksum依旧存在。所以本篇文章旨在如何在官方SDK lwip ping工程中实现ICMP硬件checksum的插入。

二, 功能实现代码修改

2.1 测试平台

代码:

\SDK_2_14_0_EVK-MIMXRT1060\boards\evkmimxrt1060\lwip_examples\lwip_ping\freertos

开发板:

MIMXRT1060-EVK

2.2 代码修改点

1)lwipopts.h

#define CHECKSUM_BY_HARDWARE 

#ifdef CHECKSUM_BY_HARDWARE
/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 0
/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 0
/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 0
/* CHECKSUM_GEN_ICMP==0: Generate checksums in hardware for outgoing ICMP packets.*/
#define CHECKSUM_GEN_ICMP 0
/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 0
/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 0
/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 0
/* CHECKSUM_GEN_ICMP==0: Generate checksums in hardware for incoming ICMP packets.*/
#define CHECKSUM_CHECK_ICMP 0
#else
/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
#define CHECKSUM_GEN_IP    1
/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP   1
/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP   1
/* CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets.*/
#define CHECKSUM_GEN_ICMP 1
/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
#define CHECKSUM_CHECK_IP  1
/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 1
/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 1
/* CHECKSUM_CHECK_ICMP==1: Check checksums in software for incoming ICMP packets.*/
#define CHECKSUM_CHECK_ICMP 1

#endif

图 4
2)enet_ethernetif_kinetis.c, ethernetif_plat_init函数

void ethernetif_plat_init(struct netif *netif,
                          struct ethernetif *ethernetif,
                          const ethernetif_config_t *ethernetifConfig)
{
    enet_config_t config;
    enet_buffer_config_t buffCfg[ETHERNETIF_RING_NUM];
    int i;

....
    ENET_GetDefaultConfig(&config);
    config.ringNum     = ETHERNETIF_RING_NUM;
    config.rxBuffAlloc = ethernetif_rx_alloc;
    config.rxBuffFree  = ethernetif_rx_free;
    config.userData    = netif;

#ifdef CHECKSUM_BY_HARDWARE
//config.txAccelerConfig = (uint32_t)kENET_TxAccelIpCheckEnabled | (uint32_t)kENET_TxAccelProtoCheckEnabled;
#endif
    /* Used for detection of change.
       Initilize to value different than any possible enum value. */
    ethernetif->last_speed   = (phy_speed_t)0xa5a5;
    ethernetif->last_duplex  = (phy_duplex_t)0x5a5a;
    ethernetif->last_link_up = false;

图 5
这里主要是为了配置寄存器使能硬件IP和protocol checksum,如图2所示。
3)ping.c,ping_prepare_echo函数

/** Prepare a echo ICMP request */
static void
ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
{
  size_t i;
  size_t data_len = len - sizeof(struct icmp_echo_hdr);

  ICMPH_TYPE_SET(iecho, ICMP_ECHO);
  ICMPH_CODE_SET(iecho, 0);
  iecho->chksum = 0;
  iecho->id     = PING_ID;
  iecho->seqno  = lwip_htons(++ping_seq_num);

  /* fill the additional data buffer with some data */
  for(i = 0; i < data_len; i++) {
    ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
  }

 // iecho->chksum = inet_chksum(iecho, len);
#ifndef CHECKSUM_BY_HARDWARE //kerry add
  iecho->chksum = inet_chksum(iecho, len);
#endif
}

图 6
对于iecho->chksum = inet_chksum(iecho, len);添加硬件checksum的宏判断,如果是硬件checksum,则不需要运行软件的checksum计算,否则会导致ICMP 报文中依旧会有protocol checksum的值。
至此,修改点已经全部完毕。

三, 测试结果

3.1 去除软件checksum的测试报文情况

首先测试去除软件checksum,并且不添加硬件ICMP checksum使能的情况,也就是在上面修改代码的基础上屏蔽代码:
config.txAccelerConfig = (uint32_t)kENET_TxAccelIpCheckEnabled | (uint32_t)kENET_TxAccelProtoCheckEnabled;
测试结果如下:
在这里插入图片描述

图 7
可以看到,当关闭软件checksum,但是还没有使能硬件checksum的寄存器的时候,抓到的ICMP 报文的IP checksum和message protocol checksum没有被添加,是错误的状态。

3.2 添加硬件checksum使能的测试报文情况

下面在enet_ethernetif_kinetis.c文件中, ethernetif_plat_init函数加回:
config.txAccelerConfig = (uint32_t)kENET_TxAccelIpCheckEnabled | (uint32_t)kENET_TxAccelProtoCheckEnabled;
测试结果如下:
在这里插入图片描述

图 8
可以看到,这个时候,在软件ICMP checksum关闭的情况下,硬件的IPCHK,PROCHK位使能,已经能够在ICMP 报文中插入硬件的checksum,包括IP header checksum和message protocol checksum。
综上,经过SDK代码的修改,能够实现RT1060 ICMP IP 和message protocol 硬件checksum的添加。
希望小小经验对大家有所帮助.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值