diff --git a/src/include/ipxe/neighbour.h b/src/include/ipxe/neighbour.h index 1ca0ee333..7e7fac277 100644 --- a/src/include/ipxe/neighbour.h +++ b/src/include/ipxe/neighbour.h @@ -49,9 +49,9 @@ struct neighbour { /** Link-layer destination address */ uint8_t ll_dest[MAX_LL_ADDR_LEN]; - /** Neighbour discovery protocol (if any) */ + /** Neighbour discovery protocol (if discovery is ongoing) */ struct neighbour_discovery *discovery; - /** Network-layer source address (if any) */ + /** Network-layer source address (for discovery requests) */ uint8_t net_source[MAX_NET_ADDR_LEN]; /** Retransmission timer */ struct retry_timer timer; @@ -60,17 +60,6 @@ struct neighbour { struct list_head tx_queue; }; -/** - * Test if neighbour cache entry has a valid link-layer address - * - * @v neighbour Neighbour cache entry - * @ret has_ll_dest Neighbour cache entry has a valid link-layer address - */ -static inline __attribute__ (( always_inline )) int -neighbour_has_ll_dest ( struct neighbour *neighbour ) { - return ( ! timer_running ( &neighbour->timer ) ); -} - extern struct list_head neighbours; extern int neighbour_tx ( struct io_buffer *iobuf, struct net_device *netdev, diff --git a/src/net/neighbour.c b/src/net/neighbour.c index 253cdc0e6..908f8e4b2 100644 --- a/src/net/neighbour.c +++ b/src/net/neighbour.c @@ -186,6 +186,9 @@ static void neighbour_discovered ( struct neighbour *neighbour, /* Stop retransmission timer */ stop_timer ( &neighbour->timer ); + /* Mark discovery as complete */ + neighbour->discovery = NULL; + /* Transmit any packets in queue. Take out a temporary * reference on the entry to prevent it from going out of * scope during the call to net_tx(). @@ -300,6 +303,7 @@ int neighbour_tx ( struct io_buffer *iobuf, struct net_device *netdev, struct neighbour_discovery *discovery, const void *net_source ) { struct neighbour *neighbour; + int rc; /* Find or create neighbour cache entry */ neighbour = neighbour_find ( netdev, net_protocol, net_dest ); @@ -310,19 +314,24 @@ int neighbour_tx ( struct io_buffer *iobuf, struct net_device *netdev, neighbour_discover ( neighbour, discovery, net_source ); } - /* If a link-layer address is available then transmit - * immediately, otherwise queue for later transmission. + /* If discovery is still in progress then queue for later + * transmission. */ - if ( neighbour_has_ll_dest ( neighbour ) ) { - return net_tx ( iobuf, netdev, net_protocol, neighbour->ll_dest, - netdev->ll_addr ); - } else { + if ( neighbour->discovery ) { DBGC2 ( neighbour, "NEIGHBOUR %s %s %s deferring packet\n", netdev->name, net_protocol->name, net_protocol->ntoa ( net_dest ) ); list_add_tail ( &iobuf->list, &neighbour->tx_queue ); return 0; } + + /* Otherwise, transmit immediately */ + if ( ( rc = net_tx ( iobuf, netdev, net_protocol, neighbour->ll_dest, + netdev->ll_addr ) ) != 0 ) { + return rc; + } + + return 0; } /** diff --git a/src/usr/neighmgmt.c b/src/usr/neighmgmt.c index 9fd88f82b..fcdcbbfbb 100644 --- a/src/usr/neighmgmt.c +++ b/src/usr/neighmgmt.c @@ -50,9 +50,8 @@ void nstat ( void ) { printf ( "%s %s %s is %s %s", netdev->name, net_protocol->name, net_protocol->ntoa ( neighbour->net_dest ), ll_protocol->name, - ( neighbour_has_ll_dest ( neighbour ) ? - ll_protocol->ntoa ( neighbour->ll_dest ) : - "(incomplete)" ) ); + ( neighbour->discovery ? "(incomplete)" : + ll_protocol->ntoa ( neighbour->ll_dest ) ) ); if ( neighbour->discovery ) printf ( " (%s)", neighbour->discovery->name ); printf ( "\n" );