diff --git a/net/sixlowpan/sixlowpan_icmpv6send.c b/net/sixlowpan/sixlowpan_icmpv6send.c index 1e707c80dc6..e62c617ed1e 100644 --- a/net/sixlowpan/sixlowpan_icmpv6send.c +++ b/net/sixlowpan/sixlowpan_icmpv6send.c @@ -114,15 +114,13 @@ void sixlowpan_icmpv6_send(FAR struct net_driver_s *dev, uint16_t buflen; int ret; - /* Get the IEEE 802.15.4 MAC address of the destination. This - * assumes an encoding of the MAC address in the IPv6 address. - */ + /* Get the IEEE 802.15.4 MAC address of the next hop. */ - ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)fwddev, - ipv6icmpv6->ipv6.destipaddr, &destmac); + ret = sixlowpan_nexthopaddr((FAR struct radio_driver_s *)fwddev, + ipv6icmpv6->ipv6.destipaddr, &destmac); if (ret < 0) { - nerr("ERROR: Failed to dest MAC address: %d\n", ret); + nerr("ERROR: Failed to get dest MAC address: %d\n", ret); goto drop; } diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index 614ba468435..e64becd9c1b 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -782,11 +782,11 @@ int sixlowpan_input(FAR struct radio_driver_s *radio, * address. */ - ret = sixlowpan_destaddrfromip(radio, ipv6hdr->destipaddr, - &destmac); + ret = sixlowpan_nexthopaddr(radio, ipv6hdr->destipaddr, + &destmac); if (ret < 0) { - nerr("ERROR: Failed to dest MAC address: %d\n", ret); + nerr("ERROR: Failed to get dest MAC address: %d\n", ret); goto drop; } diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index 1681d8b2720..7e527dae0df 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -564,6 +564,22 @@ int sixlowpan_uncompresshdr_hc1(FAR struct radio_driver_s *radio, FAR uint8_t *bptr); #endif +/**************************************************************************** + * Name: sixlowpan_nexthopaddr + * + * Description: + * sixlowpan_nexthopaddr(): If the destination is on-link, extract the + * IEEE 802.15.14 destination address from the destination IP address. If the + * destination is not reachable directly, use the routing table (if available) + * or fall back to the default router IP address and use the router IP address + * to derive the IEEE 802.15.4 MAC address. + * + ****************************************************************************/ + +int sixlowpan_nexthopaddr(FAR struct radio_driver_s *radio, + FAR const net_ipv6addr_t ipaddr, + FAR struct netdev_varaddr_s *destaddr); + /**************************************************************************** * Name: sixlowpan_islinklocal, sixlowpan_destaddrfromip, and * sixlowpan_ismacbased diff --git a/net/sixlowpan/sixlowpan_tcpsend.c b/net/sixlowpan/sixlowpan_tcpsend.c index d1ee784cc0d..df7eab7971c 100644 --- a/net/sixlowpan/sixlowpan_tcpsend.c +++ b/net/sixlowpan/sixlowpan_tcpsend.c @@ -838,12 +838,10 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, } #endif - /* Get the IEEE 802.15.4 MAC address of the destination. This assumes - * an encoding of the MAC address in the IPv6 address. - */ + /* Get the IEEE 802.15.4 MAC address of the next hop. */ - ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)dev, - conn->u.ipv6.raddr, &destmac); + ret = sixlowpan_nexthopaddr((FAR struct radio_driver_s *)dev, + conn->u.ipv6.raddr, &destmac); if (ret < 0) { nerr("ERROR: Failed to get dest MAC address: %d\n", ret); @@ -957,12 +955,10 @@ void sixlowpan_tcp_send(FAR struct net_driver_s *dev, uint16_t buflen; int ret; - /* Get the IEEE 802.15.4 MAC address of the destination. This - * assumes an encoding of the MAC address in the IPv6 address. - */ + /* Get the IEEE 802.15.4 MAC address of the next hop. */ - ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)fwddev, - ipv6hdr->ipv6.destipaddr, &destmac); + ret = sixlowpan_nexthopaddr((FAR struct radio_driver_s *)fwddev, + ipv6hdr->ipv6.destipaddr, &destmac); if (ret < 0) { nerr("ERROR: Failed to get dest MAC address: %d\n", ret); diff --git a/net/sixlowpan/sixlowpan_udpsend.c b/net/sixlowpan/sixlowpan_udpsend.c index c9ca4c6161a..e2f115eb090 100644 --- a/net/sixlowpan/sixlowpan_udpsend.c +++ b/net/sixlowpan/sixlowpan_udpsend.c @@ -292,12 +292,10 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock, g_netstats.udp.sent++; #endif - /* Get the IEEE 802.15.4 MAC address of the destination This assumes an - * encoding of the MAC address in the IPv6 address. - */ + /* Get the IEEE 802.15.4 MAC address of the next hop. */ - ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)dev, - to6->sin6_addr.in6_u.u6_addr16, &destmac); + ret = sixlowpan_nexthopaddr((FAR struct radio_driver_s *)dev, + to6->sin6_addr.in6_u.u6_addr16, &destmac); if (ret < 0) { nerr("ERROR: Failed to get dest MAC address: %d\n", ret); @@ -468,12 +466,10 @@ void sixlowpan_udp_send(FAR struct net_driver_s *dev, uint16_t buflen; int ret; - /* Get the IEEE 802.15.4 MAC address of the destination. This - * assumes an encoding of the MAC address in the IPv6 address. - */ + /* Get the IEEE 802.15.4 MAC address of the next hop. */ - ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)fwddev, - ipv6udp->ipv6.destipaddr, &destmac); + ret = sixlowpan_nexthopaddr((FAR struct radio_driver_s *)fwddev, + ipv6udp->ipv6.destipaddr, &destmac); if (ret < 0) { nerr("ERROR: Failed to get dest MAC address: %d\n", ret); diff --git a/net/sixlowpan/sixlowpan_utils.c b/net/sixlowpan/sixlowpan_utils.c index a020e5c9ca6..c15bd2d9dca 100644 --- a/net/sixlowpan/sixlowpan_utils.c +++ b/net/sixlowpan/sixlowpan_utils.c @@ -166,6 +166,63 @@ static void sixlowpan_eaddrfromip(const net_ipv6addr_t ipaddr, FAR uint8_t *eadd * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: sixlowpan_nexthopaddr + * + * Description: + * sixlowpan_nexthopaddr(): If the destination is on-link, extract the + * IEEE 802.15.14 destination address from the destination IP address. If the + * destination is not reachable directly, use the routing table (if available) + * or fall back to the default router IP address and use the router IP address + * to derive the IEEE 802.15.4 MAC address. + * + ****************************************************************************/ + +int sixlowpan_nexthopaddr(FAR struct radio_driver_s *radio, + FAR const net_ipv6addr_t ipaddr, + FAR struct netdev_varaddr_s *destaddr) +{ + FAR net_ipv6addr_t router; + int ret; + + /* Try to get the IEEE 802.15.4 MAC address of the destination. This + * assumes an encoding of the MAC address in the IPv6 address. + */ + + ret = sixlowpan_destaddrfromip(radio, ipaddr, destaddr); + if (ret < 0) + { + /* Destination address is not on the local network */ + +#ifdef CONFIG_NET_ROUTE + /* We have a routing table.. find the correct router to use in + * this case (or, as a fall-back, use the device's default router + * address). We will use the router IPv6 address instead of the + * destination address when determining the MAC address. + */ + + netdev_ipv6_router(radio->r_dev, ipaddr, router); +#else + /* Use the device's default router IPv6 address instead of the + * destination address when determining the MAC address. + */ + + net_ipv6addr_copy(router, radio->r_dev.d_ipv6draddr); +#endif + /* Get the IEEE 802.15.4 MAC address of the router. This + * assumes an encoding of the MAC address in the IPv6 address. + */ + + ret = sixlowpan_destaddrfromip(radio, router, destaddr); + if (ret < 0) + { + return ret; + } + } + + return OK; +} + /**************************************************************************** * Name: sixlowpan_destaddrfromip *