lwip发送ethernet ii包

有时候系统很简单时,可能想通过网口直接发送数据包给网张中的设备,这里可以发送ethernet ii包。

ethernet ii包的格式如下所示,其中FCS由硬件填充:

lwip发送ethernet ii包_第1张图片

在etharp.h中定义了ethernet ii包的数据结构:

lwip发送ethernet ii包_第2张图片

我们组一个pbuf包通过netif->linkoutput发送出支去,代码如下:

//ethernet_ii.c

#include "lwip/opt.h"
#include "lwip/ip_addr.h"
#include "lwip/def.h"
#include "lwip/ip.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/dhcp.h"
#include "lwip/autoip.h"
#include "netif/etharp.h"

#include 
#include "ethernet_ii.h"

err_t ethernet_ii_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
           const struct eth_addr *ethdst_addr, unsigned char *buff, int len)
{
  struct pbuf *p;
  err_t result = ERR_OK;
  struct eth_hdr *ethhdr;
    unsigned char *hdr;

#if LWIP_AUTOIP
    const u8_t * ethdst_hwaddr;
#endif /* LWIP_AUTOIP */


  LWIP_ASSERT("netif != NULL", netif != NULL);

  /* allocate a pbuf for the outgoing ARP request packet */
  p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHERNET_II_PACKET, PBUF_RAM);
  /* could allocate a pbuf for an ARP request? */
  if (p == NULL) {
    LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
      ("etharp_raw: could not allocate pbuf for ARP request.\n"));
    ETHARP_STATS_INC(etharp.memerr);
    return ERR_MEM;
  }
  LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
              (p->len >= SIZEOF_ETHARP_PACKET));

  ethhdr = (struct eth_hdr *)p->payload;
  hdr = ((u8_t*)ethhdr + ETHERNET_II_HEAD);
  memcpy(hdr, buff, len);

  LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
              (netif->hwaddr_len == ETHARP_HWADDR_LEN));

#if LWIP_AUTOIP
    /* If we are using Link-Local, all ARP packets that contain a Link-Local
     * 'sender IP address' MUST be sent using link-layer broadcast instead of
     * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
    ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
#endif /* LWIP_AUTOIP */

#if LWIP_AUTOIP
  ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr);
#else  /* LWIP_AUTOIP */
  ETHADDR16_COPY(ðhdr->dest, ethdst_addr);
#endif /* LWIP_AUTOIP */
  ETHADDR16_COPY(ðhdr->src, ethsrc_addr);


  ethhdr->type = PP_HTONS(ETHTYPE_ETHERNET_II);
  /* send ARP query */
  result = netif->linkoutput(netif, p);
  ETHARP_STATS_INC(etharp.xmit);
  /* free ARP query packet */
  pbuf_free(p);
  p = NULL;
  /* could not allocate pbuf for ARP request */

  return result;
}

//ethernet_ii.h

#ifndef __ETHERNET_II_H__
#define __ETHERNET_II_H__

#define ETHERNET_II_HEAD            (14)
#define ETHERNET_II_DATA_LEN        (50)
#define SIZEOF_ETHERNET_II_PACKET   (ETHERNET_II_HEAD+ETHERNET_II_DATA_LEN)
#define ETHTYPE_ETHERNET_II         (0x7002U)

err_t ethernet_ii_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
           const struct eth_addr *ethdst_addr, unsigned char *buff, int len);


#endif

在主程序中,调用ethernet_ii_raw函数即可发送ethernet ii包:

ret = ethernet_ii_raw(&enc28j60_netif, (struct eth_addr *)src_mac.addr, 
                (struct eth_addr *)des_mac.addr, sendbuff, ETHERNET_II_DATA_LEN);

参数分别为网络接口,源mac,目标mac,要发送的数据,数据长度。

你可能感兴趣的:(TCP/IP)