diff --git a/ChangeLog b/ChangeLog index d410ca807fc..01b8965ee26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5702,4 +5702,10 @@ touschscreen drive is basically functional) (2013-10-3) * arch/arm/src/sama5/chip/sam_lcdc.h: Add SAMA5 LCD register definition header file (2013-10-4). + * net/netdev_findbyaddr.c: Now (1) uses the routing table + if available to look up the router to get to a remote network, + and (2) if there is only a single network device and no + route, then it will simply return that single device. The + ARP logic will use the default router address associated with + the interface in this case (2013-10-5). diff --git a/net/net_close.c b/net/net_close.c index dce87ba4757..10f7e199ef7 100644 --- a/net/net_close.c +++ b/net/net_close.c @@ -176,7 +176,7 @@ static inline void netclose_disconnect(FAR struct socket *psock) /* Notify the device driver of the availaibilty of TX data */ - netdev_txnotify(&conn->ripaddr); + netdev_txnotify(conn->ripaddr); /* Wait for the disconnect event */ diff --git a/net/net_internal.h b/net/net_internal.h index a9647f9003e..abea7ccfeee 100644 --- a/net/net_internal.h +++ b/net/net_internal.h @@ -202,21 +202,21 @@ FAR struct uip_driver_s *netdev_findbyname(FAR const char *ifname); /* net_findbyaddr.c **********************************************************/ #if CONFIG_NSOCKET_DESCRIPTORS > 0 -FAR struct uip_driver_s *netdev_findbyaddr(FAR const uip_ipaddr_t *raddr); +FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t addr); #endif /* net_txnotify.c ************************************************************/ #if CONFIG_NSOCKET_DESCRIPTORS > 0 -void netdev_txnotify(const uip_ipaddr_t *raddr); +void netdev_txnotify(const uip_ipaddr_t addr); #endif /* net_rxnotify.c ************************************************************/ #if CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET_RXAVAIL) -void netdev_rxnotify(const uip_ipaddr_t *raddr); +void netdev_rxnotify(const uip_ipaddr_t addr); #else -# define netdev_rxnotify(raddr) +# define netdev_rxnotify(addr) #endif /* net_count.c ***************************************************************/ diff --git a/net/net_route.h b/net/net_route.h index 5c1fafa764d..fec27698eb0 100644 --- a/net/net_route.h +++ b/net/net_route.h @@ -187,6 +187,12 @@ int net_delroute(uip_ipaddr_t target, uip_ipaddr_t netmask); * router on a local network that can forward to the external network. * * Parameters: + * target - An IP address on a remote network to use in the lookup. + * router - The address of router on a local network that can forward our + * packets to the target. + * + * NOTE: For IPv6, router will be an array, for IPv4 it will be a scalar + * value. Hence, the change in the function signature. * * Returned Value: * OK on success; Negated errno on failure. @@ -194,9 +200,9 @@ int net_delroute(uip_ipaddr_t target, uip_ipaddr_t netmask); ****************************************************************************/ #ifdef CONFIG_NET_IPv6 -int net_router(uip_ipaddr_t target, uip_ipaddr_t *router); -#else int net_router(uip_ipaddr_t target, uip_ipaddr_t router); +#else +int net_router(uip_ipaddr_t target, uip_ipaddr_t *router); #endif /**************************************************************************** diff --git a/net/net_router.c b/net/net_router.c index 3317f400627..71344f842a5 100644 --- a/net/net_router.c +++ b/net/net_router.c @@ -109,6 +109,12 @@ static int net_match(FAR struct net_route_s *route, FAR void *arg) * router on a local network that can forward to the external network. * * Parameters: + * target - An IP address on a remote network to use in the lookup. + * router - The address of router on a local network that can forward our + * packets to the target. + * + * NOTE: For IPv6, router will be an array, for IPv4 it will be a scalar + * value. Hence, the change in the function signature. * * Returned Value: * OK on success; Negated errno on failure. @@ -116,9 +122,9 @@ static int net_match(FAR struct net_route_s *route, FAR void *arg) ****************************************************************************/ #ifdef CONFIG_NET_IPv6 -int net_router(uip_ipaddr_t target, uip_ipaddr_t *router) -#else int net_router(uip_ipaddr_t target, uip_ipaddr_t router) +#else +int net_router(uip_ipaddr_t target, uip_ipaddr_t *router) #endif { struct route_match_s match; @@ -133,9 +139,9 @@ int net_router(uip_ipaddr_t target, uip_ipaddr_t router) ret = net_foreachroute(net_match, &match) ? OK : -ENOENT; #ifdef CONFIG_NET_IPv6 - uip_ipaddr_copy(*router, match.target); -#else uip_ipaddr_copy(router, match.target); +#else + uip_ipaddr_copy(*router, match.target); #endif return ret; diff --git a/net/netdev_findbyaddr.c b/net/netdev_findbyaddr.c index e8083e4d0c1..8ca1ae3b280 100644 --- a/net/netdev_findbyaddr.c +++ b/net/netdev_findbyaddr.c @@ -47,6 +47,7 @@ #include +#include "net_route.h" #include "net_internal.h" /**************************************************************************** @@ -73,16 +74,40 @@ * Function: netdev_maskcmp ****************************************************************************/ -static inline bool netdev_maskcmp(const uip_ipaddr_t *ipaddr, - const uip_ipaddr_t *raddr, - const uip_ipaddr_t *netmask) +/**************************************************************************** + * Function: netdev_finddevice + * + * Description: + * Find a previously registered network device by matching a local address + * with the subnet served by the device + * + * Parameters: + * addr - Pointer to the remote address of a connection + * + * Returned Value: + * Pointer to driver on success; null on failure + * + * Assumptions: + * Called from normal user mode + * + ****************************************************************************/ + +static FAR struct uip_driver_s *netdev_finddevice(const uip_ipaddr_t addr) { -#ifndef CONFIG_NET_IPv6 - return (*ipaddr & *netmask) == (*raddr & *netmask); -#else -# warning "Not implemented for IPv6" - return false; -#endif + struct uip_driver_s *dev; + + netdev_semtake(); + for (dev = g_netdevices; dev; dev = dev->flink) + { + if (uip_ipaddr_maskcmp(dev->d_ipaddr, addr, dev->d_netmask)) + { + netdev_semgive(); + return dev; + } + } + + netdev_semgive(); + return NULL; } /**************************************************************************** @@ -93,11 +118,11 @@ static inline bool netdev_maskcmp(const uip_ipaddr_t *ipaddr, * Function: netdev_findbyaddr * * Description: - * Find a previously registered network device by matching a remote address - * with the subnet served by the device + * Find a previously registered network device by matching an arbitrary + * IP address. * * Parameters: - * raddr - Pointer to the remote address of a connection + * addr - Pointer to the remote address of a connection * * Returned Value: * Pointer to driver on success; null on failure @@ -107,24 +132,69 @@ static inline bool netdev_maskcmp(const uip_ipaddr_t *ipaddr, * ****************************************************************************/ -FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t *raddr) +FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t addr) { struct uip_driver_s *dev; +#ifdef CONFIG_NET_ROUTE + uip_ipaddr_t router; + int ret; +#endif - if (raddr) + /* First, see if the address maps to the a local network */ + + dev = netdev_finddevice(addr); + if (dev) { - netdev_semtake(); - for (dev = g_netdevices; dev; dev = dev->flink) - { - if (netdev_maskcmp(&dev->d_ipaddr, raddr, &dev->d_netmask)) - { - netdev_semgive(); - return dev; - } - } - netdev_semgive(); + return dev; } - return NULL; + + /* No.. The address lies on an external network */ + +#ifdef CONFIG_NET_ROUTE + /* If we have a routing table, then perhaps we can find the the local + * address of a router that can forward packets to the external network. + */ + +#ifdef CONFIG_NET_IPv6 + ret = net_router(addr, router); +#else + ret = net_router(addr, &router); +#endif + if (ret >= 0) + { + /* Success... try to find the network device associated with the local + * router address + */ + + dev = netdev_finddevice(router); + if (dev) + { + return dev; + } + } +#endif /* CONFIG_NET_ROUTE */ + + /* The above lookup will fail if the packet is being sent out of our + * out subnet to a router and there is no routing information. + * + * However, if there is only a single, registered network interface, then + * the decision is pretty easy. Use that device and its default router + * address. + */ + + netdev_semtake(); + if (g_netdevices && !g_netdevices->flink) + { + dev = g_netdevices; + } + netdev_semgive(); + + /* If we will did not find the network device, then we might as well fail + * because we are not configured properly to determine the route to the + * target. + */ + + return dev; } #endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/net/netdev_txnotify.c b/net/netdev_txnotify.c index 41f97c4019c..18e4e1b702e 100644 --- a/net/netdev_txnotify.c +++ b/net/netdev_txnotify.c @@ -90,25 +90,12 @@ * ****************************************************************************/ -void netdev_txnotify(const uip_ipaddr_t *raddr) +void netdev_txnotify(const uip_ipaddr_t raddr) { /* Find the device driver that serves the subnet of the remote address */ struct uip_driver_s *dev = netdev_findbyaddr(raddr); - /* The above lookup will fail if the packet is being sent out of our - * out subnet to a router. REVISIT: For now, we fall back and try "eth0". - */ - - if (dev == NULL) - { - /* If the destination address is not in our subnet, assume eth0 as the - * default device. - */ - - dev = netdev_findbyname("eth0"); - } - if (dev && dev->d_txavail) { /* Notify the device driver that new TX data is available. */ diff --git a/net/send.c b/net/send.c index 3d18ecde582..d90b15b4041 100644 --- a/net/send.c +++ b/net/send.c @@ -576,7 +576,7 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len, /* Notify the device driver of the availaibilty of TX data */ - netdev_txnotify(&conn->ripaddr); + netdev_txnotify(conn->ripaddr); /* Wait for the send to complete or an error to occur: NOTES: (1) * uip_lockedwait will also terminate if a signal is received, (2) interrupts diff --git a/net/sendto.c b/net/sendto.c index 232dd20f6fe..da3e5c860e5 100644 --- a/net/sendto.c +++ b/net/sendto.c @@ -402,7 +402,7 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf, /* Notify the device driver of the availabilty of TX data */ - netdev_txnotify(&conn->ripaddr); + netdev_txnotify(conn->ripaddr); /* Wait for either the receive to complete or for an error/timeout to occur. * NOTES: (1) uip_lockedwait will also terminate if a signal is received, (2) diff --git a/net/uip/uip_icmpping.c b/net/uip/uip_icmpping.c index 36f6e892ade..8aa1f3e84d6 100644 --- a/net/uip/uip_icmpping.c +++ b/net/uip/uip_icmpping.c @@ -352,7 +352,7 @@ int uip_ping(uip_ipaddr_t addr, uint16_t id, uint16_t seqno, /* Notify the device driver of the availaibilty of TX data */ - netdev_txnotify(&state.png_addr); + netdev_txnotify(state.png_addr); /* Wait for either the full round trip transfer to complete or * for timeout to occur. (1) uip_lockedwait will also terminate if a