From e2f7a1a610753465c2f9f47054ce9365cd131289 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 5 Oct 2013 13:16:18 -0600 Subject: netdev_findbyaddr() will not use a routing table if one is available. It will also make a better decision in the case there there is no routing table but only a single network interface. --- nuttx/ChangeLog | 6 +++ nuttx/net/net_close.c | 2 +- nuttx/net/net_internal.h | 8 +-- nuttx/net/net_route.h | 10 +++- nuttx/net/net_router.c | 14 +++-- nuttx/net/netdev_findbyaddr.c | 116 +++++++++++++++++++++++++++++++++--------- nuttx/net/netdev_txnotify.c | 15 +----- nuttx/net/send.c | 2 +- nuttx/net/sendto.c | 2 +- nuttx/net/uip/uip_icmpping.c | 2 +- 10 files changed, 126 insertions(+), 51 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index d410ca807..01b8965ee 100644 --- a/nuttx/ChangeLog +++ b/nuttx/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/nuttx/net/net_close.c b/nuttx/net/net_close.c index dce87ba47..10f7e199e 100644 --- a/nuttx/net/net_close.c +++ b/nuttx/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/nuttx/net/net_internal.h b/nuttx/net/net_internal.h index a9647f900..abea7ccfe 100644 --- a/nuttx/net/net_internal.h +++ b/nuttx/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/nuttx/net/net_route.h b/nuttx/net/net_route.h index 5c1fafa76..fec27698e 100644 --- a/nuttx/net/net_route.h +++ b/nuttx/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/nuttx/net/net_router.c b/nuttx/net/net_router.c index 3317f4006..71344f842 100644 --- a/nuttx/net/net_router.c +++ b/nuttx/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/nuttx/net/netdev_findbyaddr.c b/nuttx/net/netdev_findbyaddr.c index e8083e4d0..8ca1ae3b2 100644 --- a/nuttx/net/netdev_findbyaddr.c +++ b/nuttx/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 + + /* First, see if the address maps to the a local network */ + + dev = netdev_finddevice(addr); + if (dev) + { + return dev; + } - if (raddr) + /* 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) { - netdev_semtake(); - for (dev = g_netdevices; dev; dev = dev->flink) + /* Success... try to find the network device associated with the local + * router address + */ + + dev = netdev_finddevice(router); + if (dev) { - if (netdev_maskcmp(&dev->d_ipaddr, raddr, &dev->d_netmask)) - { - netdev_semgive(); - return dev; - } + return dev; } - netdev_semgive(); } - return NULL; +#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/nuttx/net/netdev_txnotify.c b/nuttx/net/netdev_txnotify.c index 41f97c401..18e4e1b70 100644 --- a/nuttx/net/netdev_txnotify.c +++ b/nuttx/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/nuttx/net/send.c b/nuttx/net/send.c index 3d18ecde5..d90b15b40 100644 --- a/nuttx/net/send.c +++ b/nuttx/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/nuttx/net/sendto.c b/nuttx/net/sendto.c index 232dd20f6..da3e5c860 100644 --- a/nuttx/net/sendto.c +++ b/nuttx/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/nuttx/net/uip/uip_icmpping.c b/nuttx/net/uip/uip_icmpping.c index 36f6e892a..8aa1f3e84 100644 --- a/nuttx/net/uip/uip_icmpping.c +++ b/nuttx/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 -- cgit v1.2.3