390 |
/* this is where we will send out queued packets! */ |
/* this is where we will send out queued packets! */ |
391 |
#if ARP_QUEUEING |
#if ARP_QUEUEING |
392 |
while (arp_table[i].p != NULL) { |
while (arp_table[i].p != NULL) { |
393 |
/* get the first packet on the queue (if any) */ |
/* get the first packet on the queue */ |
394 |
struct pbuf *p = arp_table[i].p; |
struct pbuf *p = arp_table[i].p; |
395 |
/* Ethernet header */ |
/* Ethernet header */ |
396 |
struct eth_hdr *ethhdr = p->payload;; |
struct eth_hdr *ethhdr = p->payload; |
397 |
/* remember (and reference) remainder of queue */ |
/* remember (and reference) remainder of queue */ |
398 |
/* note: this will also terminate the p pbuf chain */ |
/* note: this will also terminate the p pbuf chain */ |
399 |
arp_table[i].p = pbuf_dequeue(p); |
arp_table[i].p = pbuf_dequeue(p); |
571 |
/** |
/** |
572 |
* Resolve and fill-in Ethernet address header for outgoing packet. |
* Resolve and fill-in Ethernet address header for outgoing packet. |
573 |
* |
* |
574 |
* If ARP has the Ethernet address in cache, the given packet is |
* For IP multicast and broadcast, corresponding Ethernet addresses |
575 |
* returned, ready to be sent. |
* are selected and the packet is transmitted on the link. |
576 |
* |
* |
577 |
* If ARP does not have the Ethernet address in cache the packet is |
* For unicast addresses, the packet is submitted to etharp_query(). In |
578 |
* queued (if enabled and space available) and a ARP request is sent. |
* case the IP address is outside the local network, the IP address of |
579 |
* This ARP request is returned as a pbuf, which should be sent by |
* the gateway is used. |
|
* the caller. |
|
|
* |
|
|
* A returned non-NULL packet should be sent by the caller. |
|
|
* |
|
|
* If ARP failed to allocate resources, NULL is returned. |
|
580 |
* |
* |
581 |
* @param netif The lwIP network interface which the IP packet will be sent on. |
* @param netif The lwIP network interface which the IP packet will be sent on. |
582 |
* @param ipaddr The IP address of the packet destination. |
* @param ipaddr The IP address of the packet destination. |
583 |
* @param pbuf The pbuf(s) containing the IP packet to be sent. |
* @param pbuf The pbuf(s) containing the IP packet to be sent. |
584 |
* |
* |
|
* @return If non-NULL, a packet ready to be sent by caller. |
|
|
* |
|
585 |
* @return |
* @return |
586 |
* - ERR_BUF Could not make room for Ethernet header. |
* - ERR_RTE No route to destination (no gateway to external networks), |
587 |
* - ERR_MEM Hardware address unknown, and no more ARP entries available |
* or the return type of either etharp_query() or netif->linkoutput(). |
|
* to query for address or queue the packet. |
|
|
* - ERR_RTE No route to destination (no gateway to external networks). |
|
588 |
*/ |
*/ |
589 |
err_t |
err_t |
590 |
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) |
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) |
591 |
{ |
{ |
592 |
struct eth_addr *dest, *srcaddr, mcastaddr; |
struct eth_addr *dest, *srcaddr, mcastaddr; |
593 |
struct eth_hdr *ethhdr; |
struct eth_hdr *ethhdr; |
594 |
err_t result = ERR_OK; |
u8_t i; |
595 |
|
|
596 |
/* make room for Ethernet header - should not fail */ |
/* make room for Ethernet header - should not fail */ |
597 |
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { |
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { |
606 |
/* Determine on destination hardware address. Broadcasts and multicasts |
/* Determine on destination hardware address. Broadcasts and multicasts |
607 |
* are special, other IP addresses are looked up in the ARP table. */ |
* are special, other IP addresses are looked up in the ARP table. */ |
608 |
|
|
609 |
/* destination IP address is an IP broadcast address? */ |
/* broadcast destination IP address? */ |
610 |
if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif)) { |
if (ip_addr_isbroadcast(ipaddr, netif)) { |
611 |
/* broadcast on Ethernet also */ |
/* broadcast on Ethernet also */ |
612 |
dest = (struct eth_addr *)ðbroadcast; |
dest = (struct eth_addr *)ðbroadcast; |
613 |
/* destination IP address is an IP multicast address? */ |
/* multicast destination IP address? */ |
614 |
} else if (ip_addr_ismulticast(ipaddr)) { |
} else if (ip_addr_ismulticast(ipaddr)) { |
615 |
/* Hash IP multicast address to MAC address. */ |
/* Hash IP multicast address to MAC address.*/ |
616 |
mcastaddr.addr[0] = 0x01; |
mcastaddr.addr[0] = 0x01; |
617 |
mcastaddr.addr[1] = 0x00; |
mcastaddr.addr[1] = 0x00; |
618 |
mcastaddr.addr[2] = 0x5e; |
mcastaddr.addr[2] = 0x5e; |
621 |
mcastaddr.addr[5] = ip4_addr4(ipaddr); |
mcastaddr.addr[5] = ip4_addr4(ipaddr); |
622 |
/* destination Ethernet address is multicast */ |
/* destination Ethernet address is multicast */ |
623 |
dest = &mcastaddr; |
dest = &mcastaddr; |
624 |
/* destination IP address is an IP unicast address */ |
/* unicast destination IP address? */ |
625 |
} else { |
} else { |
626 |
/* outside local network? */ |
/* outside local network? */ |
627 |
if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { |
if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { |
631 |
ipaddr = &(netif->gw); |
ipaddr = &(netif->gw); |
632 |
/* no default gateway available */ |
/* no default gateway available */ |
633 |
} else { |
} else { |
634 |
/* no route to destination error */ |
/* no route to destination error (default gateway missing) */ |
635 |
return ERR_RTE; |
return ERR_RTE; |
636 |
} |
} |
637 |
} |
} |
639 |
return etharp_query(netif, ipaddr, q); |
return etharp_query(netif, ipaddr, q); |
640 |
} |
} |
641 |
|
|
642 |
/* destination Ethernet address known */ |
/* continuation for multicast/broadcast destinations */ |
643 |
if (dest != NULL) { |
/* obtain source Ethernet address of the given interface */ |
644 |
u8_t i; |
srcaddr = (struct eth_addr *)netif->hwaddr; |
645 |
/* obtain source Ethernet address of the given interface */ |
ethhdr = q->payload; |
646 |
srcaddr = (struct eth_addr *)netif->hwaddr; |
for (i = 0; i < netif->hwaddr_len; i++) { |
647 |
/* A valid IP->MAC address mapping was found, fill in the |
ethhdr->dest.addr[i] = dest->addr[i]; |
648 |
* Ethernet header for the outgoing packet */ |
ethhdr->src.addr[i] = srcaddr->addr[i]; |
649 |
ethhdr = q->payload; |
} |
650 |
for (i = 0; i < netif->hwaddr_len; i++) { |
ethhdr->type = htons(ETHTYPE_IP); |
651 |
ethhdr->dest.addr[i] = dest->addr[i]; |
/* send packet directly on the link */ |
652 |
ethhdr->src.addr[i] = srcaddr->addr[i]; |
return netif->linkoutput(netif, q); |
|
} |
|
|
ethhdr->type = htons(ETHTYPE_IP); |
|
|
/* send packet */ |
|
|
result = netif->linkoutput(netif, q); |
|
|
} |
|
|
return result; |
|
653 |
} |
} |
654 |
|
|
655 |
/** |
/** |
692 |
u8_t k; /* Ethernet address octet index */ |
u8_t k; /* Ethernet address octet index */ |
693 |
|
|
694 |
/* non-unicast address? */ |
/* non-unicast address? */ |
695 |
if (ip_addr_isany(ipaddr) || |
if (ip_addr_isbroadcast(ipaddr, netif) || |
696 |
ip_addr_isbroadcast(ipaddr, netif) || |
ip_addr_ismulticast(ipaddr) || |
697 |
ip_addr_ismulticast(ipaddr)) { |
ip_addr_isany(ipaddr)) { |
698 |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); |
699 |
return ERR_ARG; |
return ERR_ARG; |
700 |
} |
} |
703 |
i = find_entry(ipaddr, ETHARP_TRY_HARD); |
i = find_entry(ipaddr, ETHARP_TRY_HARD); |
704 |
|
|
705 |
/* could not find or create entry? */ |
/* could not find or create entry? */ |
706 |
if (i < 0) return (err_t)i; |
if (i < 0) |
707 |
|
{ |
708 |
|
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not create ARP entry\n")); |
709 |
|
if (q) LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: packet dropped\n")); |
710 |
|
return (err_t)i; |
711 |
|
} |
712 |
|
|
713 |
/* mark a fresh entry as pending (we just sent a request) */ |
/* mark a fresh entry as pending (we just sent a request) */ |
714 |
if (arp_table[i].state == ETHARP_STATE_EMPTY) { |
if (arp_table[i].state == ETHARP_STATE_EMPTY) { |
720 |
((arp_table[i].state == ETHARP_STATE_PENDING) || |
((arp_table[i].state == ETHARP_STATE_PENDING) || |
721 |
(arp_table[i].state == ETHARP_STATE_STABLE))); |
(arp_table[i].state == ETHARP_STATE_STABLE))); |
722 |
|
|
723 |
/* do we have a pending entry? */ |
/* do we have a pending entry? or an implicit query request? */ |
724 |
if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) { |
if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) { |
725 |
/* try to resolve it; send out ARP request */ |
/* try to resolve it; send out ARP request */ |
726 |
result = etharp_request(netif, ipaddr); |
result = etharp_request(netif, ipaddr); |
755 |
/* ... in the empty queue */ |
/* ... in the empty queue */ |
756 |
pbuf_ref(p); |
pbuf_ref(p); |
757 |
arp_table[i].p = p; |
arp_table[i].p = p; |
758 |
|
#if 0 /* multi-packet-queueing disabled, see bug #11400 */ |
759 |
} else { |
} else { |
760 |
/* ... at tail of non-empty queue */ |
/* ... at tail of non-empty queue */ |
761 |
pbuf_queue(arp_table[i].p, p); |
pbuf_queue(arp_table[i].p, p); |
762 |
|
#endif |
763 |
} |
} |
764 |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %d\n", (void *)q, i)); |
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %d\n", (void *)q, i)); |
765 |
result = ERR_OK; |
result = ERR_OK; |