643 |
struct eth_addr *srcaddr; |
struct eth_addr *srcaddr; |
644 |
struct etharp_hdr *hdr; |
struct etharp_hdr *hdr; |
645 |
struct pbuf *p; |
struct pbuf *p; |
646 |
err_t result; |
err_t result = ERR_OK; |
647 |
u8_t i; |
u8_t i; |
648 |
|
u8_t perform_arp_request = 1; |
649 |
/* prevent warning if ARP_QUEUEING == 0 */ |
/* prevent warning if ARP_QUEUEING == 0 */ |
650 |
if (q); |
if (q); |
651 |
|
|
660 |
} |
} |
661 |
else if (arp_table[i].state == ETHARP_STATE_STABLE) { |
else if (arp_table[i].state == ETHARP_STATE_STABLE) { |
662 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already stable as entry %u\n", i)); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: requested IP already stable as entry %u\n", i)); |
663 |
/* TODO: user may wish to queue a packet on a stable entry. */ |
/* user may wish to queue a packet on a stable entry, so we proceed without ARP requesting */ |
664 |
return NULL; |
/* TODO: even if the ARP entry is stable, we might do an ARP request anyway in some cases? */ |
665 |
|
perform_arp_request = 0; |
666 |
|
break; |
667 |
} |
} |
668 |
} |
} |
669 |
} |
} |
675 |
/* bail out if no ARP entries are available */ |
/* bail out if no ARP entries are available */ |
676 |
if (i == ARP_TABLE_SIZE) { |
if (i == ARP_TABLE_SIZE) { |
677 |
DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n")); |
DEBUGF(ETHARP_DEBUG | 2, ("etharp_query: no more ARP entries available.\n")); |
678 |
return NULL; |
return ERR_MEM; |
679 |
} |
} |
680 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: created ARP table entry %u.\n", i)); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: created ARP table entry %u.\n", i)); |
681 |
/* i is available, create ARP entry */ |
/* i is available, create ARP entry */ |
683 |
arp_table[i].ctime = 0; |
arp_table[i].ctime = 0; |
684 |
arp_table[i].state = ETHARP_STATE_PENDING; |
arp_table[i].state = ETHARP_STATE_PENDING; |
685 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
686 |
arp_table[i].p = NULL; |
/* free queued packet, as entry is now invalidated */ |
687 |
|
if (arp_table[i].p != NULL) { |
688 |
|
pbuf_free(arp_table[i].p); |
689 |
|
arp_table[i].p = NULL; |
690 |
|
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); |
691 |
|
} |
692 |
#endif |
#endif |
693 |
} |
} |
694 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
695 |
/* any pbuf to queue and queue is empty? */ |
/* any pbuf to queue and queue is empty? */ |
696 |
if ((q != NULL) && (arp_table[i].p == NULL)) { |
if (q != NULL) { |
697 |
/* copy PBUF_REF referenced payloads to PBUF_RAM */ |
/* yield later packets over older packets? */ |
698 |
q = pbuf_take(q); |
#if ARP_QUEUE_FIRST == 0 |
699 |
/* remember pbuf to queue, if any */ |
/* earlier queued packet on this entry? */ |
700 |
arp_table[i].p = q; |
if (arp_table[i].p != NULL) { |
701 |
/* pbufs are queued, increase the reference count */ |
pbuf_free(arp_table[i].p); |
702 |
pbuf_ref(q); |
arp_table[i].p = NULL; |
703 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i)); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("etharp_query: dropped packet on ARP queue. Should not occur.\n")); |
704 |
} |
} |
705 |
#endif |
#endif |
706 |
/* allocate a pbuf for the outgoing ARP request packet */ |
/* packet can be queued? */ |
707 |
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM); |
if (arp_table[i].p == NULL) { |
708 |
/* could allocate pbuf? */ |
/* copy PBUF_REF referenced payloads to PBUF_RAM */ |
709 |
if (p != NULL) { |
q = pbuf_take(q); |
710 |
u8_t j; |
/* remember pbuf to queue, if any */ |
711 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n")); |
arp_table[i].p = q; |
712 |
hdr = p->payload; |
/* pbufs are queued, increase the reference count */ |
713 |
hdr->opcode = htons(ARP_REQUEST); |
pbuf_ref(q); |
714 |
for(j = 0; j < netif->hwaddr_len; ++j) |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | DBG_STATE, ("etharp_query: queued packet %p on ARP entry %u.\n", (void *)q, i)); |
|
{ |
|
|
hdr->dhwaddr.addr[j] = 0x00; |
|
|
hdr->shwaddr.addr[j] = srcaddr->addr[j]; |
|
715 |
} |
} |
716 |
ip_addr_set(&(hdr->dipaddr), ipaddr); |
} |
717 |
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); |
#endif |
718 |
|
/* ARP request? */ |
719 |
|
if (perform_arp_request) |
720 |
|
{ |
721 |
|
/* allocate a pbuf for the outgoing ARP request packet */ |
722 |
|
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM); |
723 |
|
/* could allocate pbuf? */ |
724 |
|
if (p != NULL) { |
725 |
|
u8_t j; |
726 |
|
DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n")); |
727 |
|
hdr = p->payload; |
728 |
|
hdr->opcode = htons(ARP_REQUEST); |
729 |
|
for(j = 0; j < netif->hwaddr_len; ++j) |
730 |
|
{ |
731 |
|
hdr->dhwaddr.addr[j] = 0x00; |
732 |
|
hdr->shwaddr.addr[j] = srcaddr->addr[j]; |
733 |
|
} |
734 |
|
ip_addr_set(&(hdr->dipaddr), ipaddr); |
735 |
|
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr)); |
736 |
|
|
737 |
hdr->hwtype = htons(HWTYPE_ETHERNET); |
hdr->hwtype = htons(HWTYPE_ETHERNET); |
738 |
ARPH_HWLEN_SET(hdr, netif->hwaddr_len); |
ARPH_HWLEN_SET(hdr, netif->hwaddr_len); |
739 |
|
|
740 |
hdr->proto = htons(ETHTYPE_IP); |
hdr->proto = htons(ETHTYPE_IP); |
741 |
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); |
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr)); |
742 |
for(j = 0; j < netif->hwaddr_len; ++j) |
for(j = 0; j < netif->hwaddr_len; ++j) |
743 |
{ |
{ |
744 |
hdr->ethhdr.dest.addr[j] = 0xff; |
hdr->ethhdr.dest.addr[j] = 0xff; |
745 |
hdr->ethhdr.src.addr[j] = srcaddr->addr[j]; |
hdr->ethhdr.src.addr[j] = srcaddr->addr[j]; |
746 |
} |
} |
747 |
hdr->ethhdr.type = htons(ETHTYPE_ARP); |
hdr->ethhdr.type = htons(ETHTYPE_ARP); |
748 |
/* send ARP query */ |
/* send ARP query */ |
749 |
result = netif->linkoutput(netif, p); |
result = netif->linkoutput(netif, p); |
750 |
/* free ARP query packet */ |
/* free ARP query packet */ |
751 |
pbuf_free(p); |
pbuf_free(p); |
752 |
p = NULL; |
p = NULL; |
753 |
} else { |
} else { |
754 |
result = ERR_MEM; |
result = ERR_MEM; |
755 |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n")); |
DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_query: could not allocate pbuf for ARP request.\n")); |
756 |
|
} |
757 |
} |
} |
758 |
return result; |
return result; |
759 |
} |
} |