/** 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;
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,
/* 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().
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 );
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;
}
/**
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" );