Skip to content

Commit

Permalink
net: route: Try to route IPv6 packet if we are not the recipient
Browse files Browse the repository at this point in the history
Instead of simply dropping the packet if the destination IPv6
address is not ours, try to figure out if there is a route
to real destination and then re-route the IPv6 packet there.

Change-Id: I6b2a0d7096b3d7877b82b04f38e3a6e588587c11
Signed-off-by: Jukka Rissanen <[email protected]>
  • Loading branch information
jukkar committed Mar 24, 2017
1 parent 1530178 commit 1061ce3
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 1 deletion.
21 changes: 21 additions & 0 deletions include/net/nbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ struct net_nbuf {
#if defined(CONFIG_NET_TCP)
bool buf_sent; /* Is this net_buf sent or not */
#endif

#if defined(CONFIG_NET_ROUTE)
bool forwarding; /* Are we forwarding this buf */
#endif
/* @endcond */
};

Expand Down Expand Up @@ -218,6 +222,23 @@ static inline void net_nbuf_set_buf_sent(struct net_buf *buf, bool sent)
}
#endif

#if defined(CONFIG_NET_ROUTE)
static inline bool net_nbuf_forwarding(struct net_buf *buf)
{
return ((struct net_nbuf *)net_buf_user_data(buf))->forwarding;
}

static inline void net_nbuf_set_forwarding(struct net_buf *buf, bool forward)
{
((struct net_nbuf *)net_buf_user_data(buf))->forwarding = forward;
}
#else
static inline bool net_nbuf_forwarding(struct net_buf *buf)
{
return false;
}
#endif

static inline uint16_t net_nbuf_get_len(struct net_buf *buf)
{
return buf->len;
Expand Down
8 changes: 8 additions & 0 deletions subsys/net/ip/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,14 @@ static struct net_buf *update_ll_reserve(struct net_buf *buf,
uint16_t reserve, room_len, copy_len, pos;
struct net_buf *orig_frag, *frag;

/* No need to do anything if we are forwarding the packet
* as we already know everything about the destination of
* the packet.
*/
if (net_nbuf_forwarding(buf)) {
return buf;
}

reserve = net_if_get_ll_reserve(net_nbuf_iface(buf), addr);
if (reserve == net_nbuf_ll_reserve(buf)) {
return buf;
Expand Down
24 changes: 23 additions & 1 deletion subsys/net/ip/net_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,29 @@ static inline enum net_verdict process_ipv6_pkt(struct net_buf *buf)
!net_is_my_ipv6_maddr(&hdr->dst) &&
!net_is_ipv6_addr_mcast(&hdr->dst) &&
!net_is_ipv6_addr_loopback(&hdr->dst)) {
NET_DBG("IPv6 packet in buf %p not for me", buf);
#if defined(CONFIG_NET_ROUTE)
struct net_route_entry *route;
struct in6_addr *nexthop;

/* Check if the packet can be routed */
if (net_route_get_info(&hdr->dst, &route, &nexthop)) {
int ret;

ret = net_route_packet(buf, route, nexthop);
if (ret < 0) {
NET_DBG("Cannot re-route buf %p via %s (%d)",
buf, net_sprint_ipv6_addr(nexthop),
ret);
} else {
return NET_OK;
}
} else
#endif /* CONFIG_NET_ROUTE */

{
NET_DBG("IPv6 packet in buf %p not for me", buf);
}

net_stats_update_ipv6_drop();
goto drop;
}
Expand Down
54 changes: 54 additions & 0 deletions subsys/net/ip/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,60 @@ net_route_mcast_lookup(struct in6_addr *group)
}
#endif /* CONFIG_NET_ROUTE_MCAST */

bool net_route_get_info(struct in6_addr *dst,
struct net_route_entry **route,
struct in6_addr **nexthop)
{
*route = net_route_lookup(NULL, dst);
if (*route) {
*nexthop = net_route_get_nexthop(*route);
if (!*nexthop) {
return false;
}

return true;
}

return false;
}

int net_route_packet(struct net_buf *buf, struct net_route_entry *route,
struct in6_addr *nexthop)
{
struct net_linkaddr_storage *lladdr;
struct net_nbr *nbr;

nbr = net_ipv6_nbr_lookup(route->iface, nexthop);
if (!nbr) {
NET_DBG("Cannot find %s neighbor.",
net_sprint_ipv6_addr(nexthop));
return -ENOENT;
}

lladdr = net_nbr_get_lladdr(nbr->idx);
if (!lladdr) {
NET_DBG("Cannot find %s neighbor link layer address.",
net_sprint_ipv6_addr(nexthop));
return -ESRCH;
}

net_nbuf_set_iface(buf, route->iface);
net_nbuf_set_forwarding(buf, true);

/* Set the destination and source ll address in the packet.
* We set the destination address to be the nexthop recipient.
*/
net_nbuf_ll_src(buf)->addr = net_nbuf_ll_if(buf)->addr;
net_nbuf_ll_src(buf)->type = net_nbuf_ll_if(buf)->type;
net_nbuf_ll_src(buf)->len = net_nbuf_ll_if(buf)->len;

net_nbuf_ll_dst(buf)->addr = lladdr->addr;
net_nbuf_ll_dst(buf)->type = lladdr->type;
net_nbuf_ll_dst(buf)->len = lladdr->len;

return net_send_data(buf);
}

void net_route_init(void)
{
NET_DBG("Allocated %d routing entries (%zu bytes)",
Expand Down
25 changes: 25 additions & 0 deletions subsys/net/ip/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,31 @@ net_route_mcast_lookup(struct in6_addr *group);

#endif /* CONFIG_NET_ROUTE_MCAST */

/**
* @brief Return a route to destination via some intermediate host.
*
* @param dst Destination IPv6 address
* @param route Route entry to destination is returned.
* @param nexthop Next hop neighbor IPv6 address is returned.
*
* @return True if there is a route to the destination, False otherwise
*/
bool net_route_get_info(struct in6_addr *dst,
struct net_route_entry **route,
struct in6_addr **nexthop);

/**
* @brief Send the network packet to network via some intermediate host.
*
* @param buf Network buffer to send.
* @param route Route entry to destination.
* @param nexthop Next hop neighbor IPv6 address.
*
* @return 0 if there was no error, <0 if the packet could not be sent.
*/
int net_route_packet(struct net_buf *buf, struct net_route_entry *route,
struct in6_addr *nexthop);

#else /* CONFIG_NET_ROUTE */
#define net_route_init(...)
#endif /* CONFIG_NET_ROUTE */
Expand Down

0 comments on commit 1061ce3

Please sign in to comment.