LwIP的ARP协议实现(3)

LwIP的ARP协议实现系列文章

LwIP中的ARP实现(1)之 ARP缓存表的数据结构
LwIP中的ARP实现(2)之 ARP缓存表的超时处理
LwIP中的ARP实现(3)之 发送ARP请求包
LwIP中的ARP实现(4)之 ARP数据包接收
LwIP中的ARP实现(5)之 ARP数据包发送

发送ARP请求包

发送ARP请求包的时候,需要填充已知的目标IP地址、源MAC地址、源IP地址等,并且需要该ARP包进行广播出去,所以以太网首部的目标MAC地址为FF-FF-FF-FF-FF-FF
LwIP先调用etharp_request()函数进行发送ARP请求包,在etharp_request()函数中会调用etharp_request_dst()函数进行发送,此时指定的目标MAC地址是ethbroadcast,而在etharp_request_dst()函数中会调用etharp_raw()进行发送ARP请求包,层层调用,并且每层的参数都是越来越多的,这样子封装对于上层程序来说更加好处理,在etharp_raw()函数中,会对ARP数据包进行封装,然后再封装到以太网数据帧中,最终调用以太网底层发送函数进行将以太网数据帧发送出去。
LwIP的实现函数是etharp_raw()

/* --------------------------------------------------------------------------------------------- */
err_t
etharp_request(struct netif *netif, const ip4_addr_t *ipaddr)
{
  return etharp_request_dst(netif, ipaddr, &ethbroadcast);
}
/* --------------------------------------------------------------------------------------------- */

const struct eth_addr ethbroadcast = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};	//FF-FF-FF-FF-FF-FF
const struct eth_addr ethzero = {{0, 0, 0, 0, 0, 0}};	//00-00-00-00-00-00

static err_t
etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr *hw_dst_addr)
{
  return etharp_raw(netif, 
					(struct eth_addr *)netif->hwaddr,
					hw_dst_addr,
					(struct eth_addr *)netif->hwaddr,
					netif_ip4_addr(netif),
					&ethzero,
					ipaddr, 
					ARP_REQUEST);
}
/* --------------------------------------------------------------------------------------------- */

* @param netif				用于发送ARP数据包的lwip网络接口
* @param ethsrc_addr		以太网头的源MAC地址
* @param ethdst_addr		以太网头的目标MAC地址
* @param hwsrc_addr 		ARP协议头的源MAC地址
* @param ipsrc_addr 		ARP协议头的源IP地址
* @param hwdst_addr 		ARP协议头的目标MAC地址
* @param ipdst_addr 		ARP协议头的目标IP地址
* @param opcode				ARP数据包的类型
* @return ERR_OK			如果已发送ARP数据包
* 如果无法分配ARP数据包,则为ERR_MEM
static err_t
etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
           const struct eth_addr *ethdst_addr,
           const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr,
           const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr,
           const u16_t opcode)
{
  struct pbuf *p;
  err_t result = ERR_OK;
  struct etharp_hdr *hdr;

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

  /* 申请ARP报文的内存空间 */
  p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_HDR, PBUF_RAM);
  
  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_HDR));

  hdr = (struct etharp_hdr *)p->payload;
  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
  hdr->opcode = lwip_htons(opcode);

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

  /* 填写源MAC地址与目标MAC地址 */
  SMEMCPY(&hdr->shwaddr, hwsrc_addr, ETH_HWADDR_LEN);
  SMEMCPY(&hdr->dhwaddr, hwdst_addr, ETH_HWADDR_LEN);
  
  /* 以太网首部源ip地址与目标ip地址 */
  IPADDR_WORDALIGNED_COPY_FROM_IP4_ADDR_T(&hdr->sipaddr, ipsrc_addr);
  IPADDR_WORDALIGNED_COPY_FROM_IP4_ADDR_T(&hdr->dipaddr, ipdst_addr);

  //填写ARP首部硬件类型与协议类型
  hdr->hwtype = PP_HTONS(LWIP_IANA_HWTYPE_ETHERNET);
  hdr->proto = PP_HTONS(ETHTYPE_IP);
  
  /* 填写ARP数据包硬件地址长度与协议地址长度 */
  hdr->hwlen = ETH_HWADDR_LEN;
  hdr->protolen = sizeof(ip4_addr_t);

  /* 发送请求包 */
#if LWIP_AUTOIP
  if (ip4_addr_islinklocal(ipsrc_addr)) 
  {
    ethernet_output(netif, p, ethsrc_addr, &ethbroadcast, ETHTYPE_ARP);
  }
  else
#endif /* LWIP_AUTOIP */
  {
    ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP);
  }

  ETHARP_STATS_INC(etharp.xmit);
  /* 释放内存 */
  pbuf_free(p);
  p = NULL;

  return result;
}

欢迎关注杰杰个人公众号,更多干货等着你!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值