0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于DWC_ether_qos的以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-LWIP的ICMP模塊介紹與PING收發(fā)測(cè)

嵌入式USB開(kāi)發(fā) ? 來(lái)源:嵌入式USB開(kāi)發(fā) ? 作者:嵌入式USB開(kāi)發(fā) ? 2023-09-18 17:51 ? 次閱讀

本文轉(zhuǎn)自公眾號(hào)歡迎關(guān)注
https://mp.weixin.qq.com/s/6MTNop3zBKdQ-gabbWo63Q

一. 前言

ICMP即Internet Control Message Protocol因特網(wǎng)控制消息協(xié)議。

ICMP是網(wǎng)絡(luò)層協(xié)議,IP不可分割的一部分。

ICMP用于報(bào)告數(shù)據(jù)報(bào)處理中的錯(cuò)誤,比如以下情況下時(shí)發(fā)送ICMP消息:當(dāng)數(shù)據(jù)報(bào)無(wú)法到達(dá)其目的地時(shí),當(dāng)網(wǎng)關(guān)沒(méi)有轉(zhuǎn)發(fā)數(shù)據(jù)報(bào)的緩沖能力時(shí),以及當(dāng)網(wǎng)關(guān)可以指示主機(jī)在較短的路由上發(fā)送數(shù)據(jù)時(shí)。

互聯(lián)網(wǎng)協(xié)議的設(shè)計(jì)并不是絕對(duì)可靠的。ICMP這些控制消息的目的是提供有關(guān)通信環(huán)境中問(wèn)題的反饋,而不是使IP可靠。不能確保數(shù)據(jù)報(bào)的傳遞或控制消息的返回,一些數(shù)據(jù)報(bào)可能無(wú)法送達(dá)時(shí)也沒(méi)有任何丟失報(bào)告。如果需要可靠的通信,則使用IP的更高級(jí)別協(xié)議必須實(shí)現(xiàn)其自己的可靠性程序。

ICMP消息通常報(bào)告數(shù)據(jù)報(bào)處理中的錯(cuò)誤,且不發(fā)送關(guān)于ICMP消息的ICMP消息,否則消息會(huì)無(wú)限遞歸。此外,ICMP消息只發(fā)送關(guān)于處理分段數(shù)據(jù)報(bào)的零分段時(shí)的錯(cuò)誤。(片段零的片段offeset等于零)。

參考

RFC 792

https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml

二. ICMP消息格式

ICMP消息格式

從 ICMP 的報(bào)文格式來(lái)說(shuō),ICMP 是 IP 的上層協(xié)議,他是在IP報(bào)的基礎(chǔ)上再添加ICMP報(bào)格式。但是 ICMP 是分擔(dān)了 IP 的一部分功能。所以,他也被認(rèn)為是與 IP 同層的協(xié)議。

圖片

我們這里只關(guān)注ICMP部分,ICMP由首部和數(shù)據(jù)兩部分組成,如下

區(qū)域類型Type代碼Code校驗(yàn)和Checksum
字節(jié)大小112
區(qū)域首部數(shù)據(jù),根據(jù)類型不一樣而不一樣,對(duì)于ping拆為了16位的ID和16位的序列號(hào)
字節(jié)大小4
區(qū)域ICMP數(shù)據(jù)部分
字節(jié)大小類型不同長(zhǎng)度不同

Type和Code如下表

類型TYPE代碼CODE**用途描述 Description**查詢類Query差錯(cuò)類Error
00Echo Reply——回顯應(yīng)答(Ping應(yīng)答)x
30Network Unreachable——網(wǎng)絡(luò)不可達(dá)x
31Host Unreachable——主機(jī)不可達(dá)x
32Protocol Unreachable——協(xié)議不可達(dá)x
33Port Unreachable——端口不可達(dá)x
34Fragmentation needed but no frag. bit set——需要進(jìn)行分片但設(shè)置不分片比特x
35Source routing failed——源站選路失敗x
36Destination network unknown——目的網(wǎng)絡(luò)未知x
37Destination host unknown——目的主機(jī)未知x
38Source host isolated (obsolete)——源主機(jī)被隔離(作廢不用)x
39Destination network administratively prohibited——目的網(wǎng)絡(luò)被強(qiáng)制禁止x
310Destination host administratively prohibited——目的主機(jī)被強(qiáng)制禁止x
311Network unreachable for TOS——由于服務(wù)類型TOS,網(wǎng)絡(luò)不可達(dá)x
312Host unreachable for TOS——由于服務(wù)類型TOS,主機(jī)不可達(dá)x
313Communication administratively prohibited by filtering——由于過(guò)濾,通信被強(qiáng)制禁止x
314Host precedence violation——主機(jī)越權(quán)x
315Precedence cutoff in effect——優(yōu)先中止生效x
40Source quench——源端被關(guān)閉(基本流控制)
50Redirect for network——對(duì)網(wǎng)絡(luò)重定向
51Redirect for host——對(duì)主機(jī)重定向
52Redirect for TOS and network——對(duì)服務(wù)類型和網(wǎng)絡(luò)重定向
53Redirect for TOS and host——對(duì)服務(wù)類型和主機(jī)重定向
80Echo request——回顯請(qǐng)求(Ping請(qǐng)求)x
90Router advertisement——路由器通告
100Route solicitation——路由器請(qǐng)求
110TTL equals 0 during transit——傳輸期間生存時(shí)間為0x
111TTL equals 0 during reassembly——在數(shù)據(jù)報(bào)組裝期間生存時(shí)間為0x
120IP header bad (catchall error)——壞的IP首部(包括各種差錯(cuò))x
121Required options missing——缺少必需的選項(xiàng)x
130Timestamp request (obsolete)——時(shí)間戳請(qǐng)求(作廢不用)x
14Timestamp reply (obsolete)——時(shí)間戳應(yīng)答(作廢不用)x
150Information request (obsolete)——信息請(qǐng)求(作廢不用)x
160Information reply (obsolete)——信息應(yīng)答(作廢不用)x
170Address mask request——地址掩碼請(qǐng)求x
180Address mask reply——地址掩碼應(yīng)答

使用wirshark協(xié)助解析

圖片

圖片

三. LWIP中ICMP相關(guān)代碼分析

這里只看IPV4相關(guān)的,IPV6下也有對(duì)應(yīng)的實(shí)現(xiàn)。

ipv4/icmp.c

icmp.h

3.1調(diào)試打印

可以配置宏ICMP_DEBUG,使能調(diào)試打印,一遍跟蹤對(duì)應(yīng)的程序處理過(guò)程。

lwipopts.h中配置

#define ICMP_DEBUG LWIP_DBG_ON

3.2數(shù)據(jù)結(jié)構(gòu)

實(shí)現(xiàn)了以下Type

#define ICMP_ER   0    /* echo reply */


#define ICMP_DUR  3    /* destination unreachable */


#define ICMP_SQ   4    /* source quench */


#define ICMP_RD   5    /* redirect */


#define ICMP_ECHO 8    /* echo */


#define ICMP_TE  11    /* time exceeded */


#define ICMP_PP  12    /* parameter problem */


#define ICMP_TS  13    /* timestamp */


#define ICMP_TSR 14    /* timestamp reply */


#define ICMP_IRQ 15    /* information request */


#define ICMP_IR  16    /* information reply */


#define ICMP_AM  17    /* address mask request */


#define ICMP_AMR 18    /* address mask reply */

定義了頭的數(shù)據(jù)結(jié)構(gòu)

struct icmp_hdr {


PACK_STRUCT_FLD_8(u8_t type);


PACK_STRUCT_FLD_8(u8_t code);


PACK_STRUCT_FIELD(u16_t chksum);


PACK_STRUCT_FIELD(u32_t data);


} PACK_STRUCT_STRUCT;

如果四echo則,ICMP首部后面4字節(jié)數(shù)據(jù)拆分成id和序列號(hào)

struct icmp_echo_hdr {


PACK_STRUCT_FLD_8(u8_t type);


PACK_STRUCT_FLD_8(u8_t code);


PACK_STRUCT_FIELD(u16_t chksum);


PACK_STRUCT_FIELD(u16_t id);


PACK_STRUCT_FIELD(u16_t seqno);


} PACK_STRUCT_STRUCT;

3.3輸入數(shù)據(jù)流

關(guān)鍵代碼是icmp_input

ethernet_input->Type=0x0800 ip4_input-> Protocol=0x01 icmp_input

通過(guò)switch處理各種類型

switch (type) {


  case ICMP_ER:

比如對(duì)于收到別人的ping請(qǐng)求就是進(jìn)入

case ICMP_ECHO:

如果是多播地址不響應(yīng)

然后檢查ICMP頭部至少要8字節(jié)。

然后檢查checksum

最后調(diào)用ip4_output_if發(fā)送響應(yīng)包。

3.4輸出數(shù)據(jù)流

icmp_dest_unreach

icmp_time_exceeded

都是調(diào)用

icmp_send_response

3.5發(fā)送PING

收到響應(yīng)進(jìn)入icmp_input的

case ICMP_ER:


    /* This is OK, echo reply might have been parsed by a raw PCB


       (as obviously, an echo request has been sent, too). */


    MIB2_STATS_INC(mib2.icmpinechoreps);


    break

發(fā)送ping可以裸機(jī)可以使用raw PCB,帶OS可以使用socket實(shí)現(xiàn)

詳見(jiàn)ping.c/h

#include "lwip/opt.h"


#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */


#include "ping.h"


#include "lwip/mem.h"
#include "lwip/raw.h"
#include "lwip/icmp.h"
#include "lwip/netif.h"
#include "lwip/sys.h"
#include "lwip/timeouts.h"
#include "lwip/inet_chksum.h"
#include "lwip/prot/ip4.h"


#if PING_USE_SOCKETS
#include "lwip/sockets.h"
#include "lwip/inet.h"
#include < string.h >
#endif /* PING_USE_SOCKETS */




/**
 * PING_DEBUG: Enable debugging for PING.
 */
#ifndef PING_DEBUG
#define PING_DEBUG     LWIP_DBG_ON
#endif


/** ping receive timeout - in milliseconds */
#ifndef PING_RCV_TIMEO
#define PING_RCV_TIMEO 1000
#endif


/** ping delay - in milliseconds */
#ifndef PING_DELAY
#define PING_DELAY     1000
#endif


/** ping identifier - must fit on a u16_t */
#ifndef PING_ID
#define PING_ID        0xAFAF
#endif


/** ping additional data size to include in the packet */
#ifndef PING_DATA_SIZE
#define PING_DATA_SIZE 32
#endif


/** ping result action - no default action */
#ifndef PING_RESULT
#define PING_RESULT(ping_ok)
#endif


/* ping variables */
static const ip_addr_t* ping_target;
static u16_t ping_seq_num;
#ifdef LWIP_DEBUG
static u32_t ping_time;
#endif /* LWIP_DEBUG */
#if !PING_USE_SOCKETS
static struct raw_pcb *ping_pcb;
#endif /* PING_USE_SOCKETS */


/** 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);
}


#if PING_USE_SOCKETS


/* Ping using the socket ip */
static err_t
ping_send(int s, const ip_addr_t *addr)
{
  int err;
  struct icmp_echo_hdr *iecho;
  struct sockaddr_storage to;
  size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
  LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);


#if LWIP_IPV6
  if(IP_IS_V6(addr) && !ip6_addr_isipv4mappedipv6(ip_2_ip6(addr))) {
    /* todo: support ICMP6 echo */
    return ERR_VAL;
  }
#endif /* LWIP_IPV6 */


  iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
  if (!iecho) {
    return ERR_MEM;
  }


  ping_prepare_echo(iecho, (u16_t)ping_size);


#if LWIP_IPV4
  if(IP_IS_V4(addr)) {
    struct sockaddr_in *to4 = (struct sockaddr_in*)&to;
    to4- >sin_len    = sizeof(*to4);
    to4- >sin_family = AF_INET;
    inet_addr_from_ip4addr(&to4- >sin_addr, ip_2_ip4(addr));
  }
#endif /* LWIP_IPV4 */


#if LWIP_IPV6
  if(IP_IS_V6(addr)) {
    struct sockaddr_in6 *to6 = (struct sockaddr_in6*)&to;
    to6- >sin6_len    = sizeof(*to6);
    to6- >sin6_family = AF_INET6;
    inet6_addr_from_ip6addr(&to6- >sin6_addr, ip_2_ip6(addr));
  }
#endif /* LWIP_IPV6 */


  err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));


  mem_free(iecho);


  return (err ? ERR_OK : ERR_VAL);
}


static void
ping_recv(int s)
{
  char buf[64];
  int len;
  struct sockaddr_storage from;
  int fromlen = sizeof(from);


  while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) {
    if (len >= (int)(sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) {
      ip_addr_t fromaddr;
      memset(&fromaddr, 0, sizeof(fromaddr));


#if LWIP_IPV4
      if(from.ss_family == AF_INET) {
        struct sockaddr_in *from4 = (struct sockaddr_in*)&from;
        inet_addr_to_ip4addr(ip_2_ip4(&fromaddr), &from4- >sin_addr);
        IP_SET_TYPE_VAL(fromaddr, IPADDR_TYPE_V4);
      }
#endif /* LWIP_IPV4 */


#if LWIP_IPV6
      if(from.ss_family == AF_INET6) {
        struct sockaddr_in6 *from6 = (struct sockaddr_in6*)&from;
        inet6_addr_to_ip6addr(ip_2_ip6(&fromaddr), &from6- >sin6_addr);
        IP_SET_TYPE_VAL(fromaddr, IPADDR_TYPE_V6);
      }
#endif /* LWIP_IPV6 */


      LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
      ip_addr_debug_print_val(PING_DEBUG, fromaddr);
      LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" msn", (sys_now() - ping_time)));


      /* todo: support ICMP6 echo */
#if LWIP_IPV4
      if (IP_IS_V4_VAL(fromaddr)) {
        struct ip_hdr *iphdr;
        struct icmp_echo_hdr *iecho;


        iphdr = (struct ip_hdr *)buf;
        iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
        if ((iecho- >id == PING_ID) && (iecho- >seqno == lwip_htons(ping_seq_num))) {
          /* do some ping result processing */
          PING_RESULT((ICMPH_TYPE(iecho) == ICMP_ER));
          return;
        } else {
          LWIP_DEBUGF( PING_DEBUG, ("ping: dropn"));
        }
      }
#endif /* LWIP_IPV4 */
    }
    fromlen = sizeof(from);
  }


  if (len == 0) {
    LWIP_DEBUGF( PING_DEBUG, ("ping: recv - %"U32_F" ms - timeoutn", (sys_now()-ping_time)));
  }


  /* do some ping result processing */
  PING_RESULT(0);
}


static void
ping_thread(void *arg)
{
  int s;
  int ret;


#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
  int timeout = PING_RCV_TIMEO;
#else
  struct timeval timeout;
  timeout.tv_sec = PING_RCV_TIMEO/1000;
  timeout.tv_usec = (PING_RCV_TIMEO%1000)*1000;
#endif
  LWIP_UNUSED_ARG(arg);


#if LWIP_IPV6
  if(IP_IS_V4(ping_target) || ip6_addr_isipv4mappedipv6(ip_2_ip6(ping_target))) {
    s = lwip_socket(AF_INET6, SOCK_RAW, IP_PROTO_ICMP);
  } else {
    s = lwip_socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6);
  }
#else
  s = lwip_socket(AF_INET,  SOCK_RAW, IP_PROTO_ICMP);
#endif
  if (s < 0) {
    return;
  }


  ret = lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  LWIP_ASSERT("setting receive timeout failed", ret == 0);
  LWIP_UNUSED_ARG(ret);


  while (1) {
    if (ping_send(s, ping_target) == ERR_OK) {
      LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
      ip_addr_debug_print(PING_DEBUG, ping_target);
      LWIP_DEBUGF( PING_DEBUG, ("n"));


#ifdef LWIP_DEBUG
      ping_time = sys_now();
#endif /* LWIP_DEBUG */
      ping_recv(s);
    } else {
      LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
      ip_addr_debug_print(PING_DEBUG, ping_target);
      LWIP_DEBUGF( PING_DEBUG, (" - errorn"));
    }
    sys_msleep(PING_DELAY);
  }
}


#else /* PING_USE_SOCKETS */


/* Ping using the raw ip */
static u8_t
ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr)
{
  struct icmp_echo_hdr *iecho;
  LWIP_UNUSED_ARG(arg);
  LWIP_UNUSED_ARG(pcb);
  LWIP_UNUSED_ARG(addr);
  LWIP_ASSERT("p != NULL", p != NULL);


  if ((p- >tot_len >= (PBUF_IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
      pbuf_remove_header(p, PBUF_IP_HLEN) == 0) {
    iecho = (struct icmp_echo_hdr *)p- >payload;


    if ((iecho- >id == PING_ID) && (iecho- >seqno == lwip_htons(ping_seq_num))) {
      LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
      ip_addr_debug_print(PING_DEBUG, addr);
      LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" msn", (sys_now()-ping_time)));


      /* do some ping result processing */
      PING_RESULT(1);
      pbuf_free(p);
      return 1; /* eat the packet */
    }
    /* not eaten, restore original packet */
    pbuf_add_header(p, PBUF_IP_HLEN);
  }


  return 0; /* don't eat the packet */
}


static void
ping_send(struct raw_pcb *raw, const ip_addr_t *addr)
{
  struct pbuf *p;
  struct icmp_echo_hdr *iecho;
  size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;


  LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
  ip_addr_debug_print(PING_DEBUG, addr);
  LWIP_DEBUGF( PING_DEBUG, ("n"));
  LWIP_ASSERT("ping_size <= 0xffff", ping_size <= 0xffff);


  p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
  if (!p) {
    return;
  }
  if ((p- >len == p- >tot_len) && (p- >next == NULL)) {
    iecho = (struct icmp_echo_hdr *)p- >payload;


    ping_prepare_echo(iecho, (u16_t)ping_size);


    raw_sendto(raw, p, addr);
#ifdef LWIP_DEBUG
    ping_time = sys_now();
#endif /* LWIP_DEBUG */
  }
  pbuf_free(p);
}


static void
ping_timeout(void *arg)
{
  struct raw_pcb *pcb = (struct raw_pcb*)arg;


  LWIP_ASSERT("ping_timeout: no pcb given!", pcb != NULL);


  ping_send(pcb, ping_target);


  sys_timeout(PING_DELAY, ping_timeout, pcb);
}


static void
ping_raw_init(void)
{
  ping_pcb = raw_new(IP_PROTO_ICMP);
  LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL);


  raw_recv(ping_pcb, ping_recv, NULL);
  raw_bind(ping_pcb, IP_ADDR_ANY);
  sys_timeout(PING_DELAY, ping_timeout, ping_pcb);
}


void
ping_send_now(void)
{
  LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL);
  ping_send(ping_pcb, ping_target);
}


#endif /* PING_USE_SOCKETS */


void
ping_init(const ip_addr_t* ping_addr)
{
  ping_target = ping_addr;


#if PING_USE_SOCKETS
  sys_thread_new("ping_thread", ping_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
#else /* PING_USE_SOCKETS */
  ping_raw_init();
#endif /* PING_USE_SOCKETS */
}


#endif /* LWIP_RAW */
#ifndef LWIP_PING_H
#define LWIP_PING_H


#include "lwip/ip_addr.h"


/**
 * PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is used
 */
#ifndef PING_USE_SOCKETS
#define PING_USE_SOCKETS    LWIP_SOCKET
#endif


void ping_init(const ip_addr_t* ping_addr);


#if !PING_USE_SOCKETS
void ping_send_now(void);
#endif /* !PING_USE_SOCKETS */


#endif /* LWIP_PING_H */

如下是帶OS的測(cè)試

ip_addr_t ping_addr;


  IP4_ADDR(&ping_addr, 192, 168, 1, 9);


  ping_init(&ping_addr);

打印如下,(這里printf不支持某些格式所以IP地址打印顯示不對(duì))

圖片

四. 總結(jié)

了解ICMP包的格式,了解LWIP發(fā)送ping和對(duì)堆ping請(qǐng)求響應(yīng)的過(guò)程。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 以太網(wǎng)
    +關(guān)注

    關(guān)注

    40

    文章

    5317

    瀏覽量

    170461
  • ICMP
    +關(guān)注

    關(guān)注

    0

    文章

    51

    瀏覽量

    14893
  • Ping
    +關(guān)注

    關(guān)注

    0

    文章

    68

    瀏覽量

    15911
  • LwIP
    +關(guān)注

    關(guān)注

    2

    文章

    85

    瀏覽量

    27018
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-MAC幀格式介紹

    本文轉(zhuǎn)自公眾號(hào),歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-MAC幀格式介紹 (qq.com) 一.前言 ? 在
    的頭像 發(fā)表于 08-30 09:23 ?2070次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-MAC幀格式<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-MDIO驅(qū)動(dòng)編寫與測(cè)試

    本文轉(zhuǎn)自公眾號(hào)歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-MDIO驅(qū)動(dòng)編寫與測(cè)試 一.前言
    的頭像 發(fā)表于 08-30 09:37 ?3440次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-MDIO<b class='flag-5'>驅(qū)動(dòng)</b>編寫與測(cè)試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-描述符鏈表介紹

    本文轉(zhuǎn)自公眾號(hào)歡迎關(guān)注 一.描述符概述 1.0 前言 對(duì)于DWC Ethernet QoS驅(qū)動(dòng)的編寫來(lái)說(shuō),初始化完成之后,核心操作就是DMA的描述符鏈表配置(linked list
    的頭像 發(fā)表于 08-30 09:39 ?4149次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-描述符鏈表<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-數(shù)據(jù)流驗(yàn)證過(guò)程

    轉(zhuǎn)自公眾號(hào)歡迎關(guān)注 https://mp.weixin.qq.com/s/klrHhaLMM_0W3FGVwHXFkA 基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-數(shù)據(jù)流驗(yàn)證過(guò)程
    的頭像 發(fā)表于 08-31 08:41 ?1776次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-數(shù)據(jù)流驗(yàn)證過(guò)程

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-收發(fā)驅(qū)動(dòng)編寫與調(diào)試

    本文轉(zhuǎn)自公眾號(hào),歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-收發(fā)驅(qū)動(dòng)編寫與調(diào)試 (
    的頭像 發(fā)表于 09-05 08:47 ?2059次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-<b class='flag-5'>收發(fā)</b><b class='flag-5'>驅(qū)動(dòng)</b>編寫與調(diào)試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-無(wú)OS環(huán)境移植LWIP

    本文轉(zhuǎn)自公眾號(hào)歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-無(wú)OS環(huán)境移植LWIP (qq.com) https://mp.we
    的頭像 發(fā)表于 09-06 08:40 ?1417次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-無(wú)OS環(huán)境移植<b class='flag-5'>LWIP</b>

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-LWIP的內(nèi)存池介紹

    本文轉(zhuǎn)自公眾號(hào),歡迎關(guān)注 https://mp.weixin.qq.com/s/mBoGSf_u9edFF01U_OZT9g 一.前言 lwIP為基礎(chǔ)結(jié)構(gòu)提供了專用的內(nèi)存池管理,比如netconn
    的頭像 發(fā)表于 09-07 08:45 ?1491次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-<b class='flag-5'>LWIP</b>的內(nèi)存池<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-LWIP的堆管理介紹

    本文轉(zhuǎn)自公眾號(hào)歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-LWIP的堆管理介紹 (
    的頭像 發(fā)表于 09-08 08:40 ?1135次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-<b class='flag-5'>LWIP</b>的堆管理<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-LWIP的堆(內(nèi)存池)未對(duì)齊導(dǎo)致問(wèn)題的案例分享

    本文轉(zhuǎn)自公眾號(hào)歡迎關(guān)注 https://mp.weixin.qq.com/s/ErIa2ss2YZLGYbSwoJEzog 一.?前言 內(nèi)存未對(duì)齊訪問(wèn)問(wèn)題這個(gè)已經(jīng)是老生常談的問(wèn)題了, 由于LWIP
    的頭像 發(fā)表于 09-09 08:44 ?1595次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-<b class='flag-5'>LWIP</b>的堆(內(nèi)存池)未對(duì)齊導(dǎo)致問(wèn)題的案例分享

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-RTOS環(huán)境移植LWIP與性能測(cè)試

    本文轉(zhuǎn)自公眾號(hào),歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-RTOS環(huán)境移植LWIP與性能測(cè)試 (qq.com) https:
    的頭像 發(fā)表于 09-11 11:20 ?1785次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-RTOS環(huán)境移植<b class='flag-5'>LWIP</b>與性能測(cè)試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-LWIP在PC上進(jìn)行開(kāi)發(fā)調(diào)試

    本文轉(zhuǎn)自公眾號(hào)歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-LWIP在PC上進(jìn)行開(kāi)發(fā)
    的頭像 發(fā)表于 09-11 08:40 ?1798次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-<b class='flag-5'>LWIP</b>在PC上進(jìn)行<b class='flag-5'>開(kāi)發(fā)</b>調(diào)試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-LWIP的定時(shí)器模塊詳解

    一. 前言 LWIP的定時(shí)器模塊,實(shí)現(xiàn)了通用的軟件定時(shí)器,用于內(nèi)部的周期事件處理,比如arp,tcp的超時(shí)等,用戶也可以使用。這一篇來(lái)分析該模塊的實(shí)現(xiàn)。 二.代碼分析 2.1源碼 源碼
    的頭像 發(fā)表于 09-18 09:33 ?1440次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-<b class='flag-5'>LWIP</b>的定時(shí)器<b class='flag-5'>模塊</b>詳解

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-LWIP的ARP模塊介紹

    TCP/IP通訊第一步需要先調(diào)通ARP,否則TCP/IP包都不知道MAC地址要發(fā)給誰(shuí)。這一篇來(lái)基于LWIP的ARP實(shí)現(xiàn)進(jìn)行相關(guān)的分析。
    的頭像 發(fā)表于 09-18 09:34 ?1629次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-<b class='flag-5'>LWIP</b>的ARP<b class='flag-5'>模塊</b><b class='flag-5'>介紹</b>

    設(shè)計(jì)軟件核心以太網(wǎng)服務(wù)質(zhì)量數(shù)據(jù)手冊(cè)免費(fèi)下載

    本文描述Synopsys設(shè)計(jì)軟件核心以太網(wǎng)服務(wù)質(zhì)量DWC以太網(wǎng)QoS核心5.10A。DWC以太網(wǎng)
    發(fā)表于 10-23 08:00 ?16次下載
    設(shè)計(jì)軟件核心<b class='flag-5'>以太網(wǎng)</b>服務(wù)質(zhì)量數(shù)據(jù)手冊(cè)免費(fèi)下載

    基于DWC_ether_qos以太網(wǎng)驅(qū)動(dòng)開(kāi)發(fā)-包過(guò)濾

    以太網(wǎng)上數(shù)據(jù)非常多,如果所有數(shù)據(jù)都接收交給軟件去處理軟件負(fù)載會(huì)非常重,所以一般只需要接收發(fā)給自己的數(shù)據(jù)即可
    的頭像 發(fā)表于 09-02 09:19 ?1427次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開(kāi)發(fā)</b>-包過(guò)濾