diff options
Diffstat (limited to 'contrib/addons/ipv6_static_routing')
-rw-r--r-- | contrib/addons/ipv6_static_routing/README | 43 | ||||
-rw-r--r-- | contrib/addons/ipv6_static_routing/ip6_route_table.c | 248 | ||||
-rw-r--r-- | contrib/addons/ipv6_static_routing/ip6_route_table.h | 94 |
3 files changed, 385 insertions, 0 deletions
diff --git a/contrib/addons/ipv6_static_routing/README b/contrib/addons/ipv6_static_routing/README new file mode 100644 index 00000000000..0c3b06cc08f --- /dev/null +++ b/contrib/addons/ipv6_static_routing/README @@ -0,0 +1,43 @@ +A simple routing table implementation for addition, deletion and lookup of IPv6 routes. + +APIs are: +1) s8_t ip6_add_route_entry(struct ip6_prefix *ip6_prefix, + struct netif *netif, + ip6_addr_t *gateway, + s8_t *index); + +2) err_t ip6_remove_route_entry(struct ip6_prefix *ip6_prefix); + +3) s8_t ip6_find_route_entry(ip6_addr_t *ip6_dest_addr); + +4) struct netif *ip6_static_route(ip6_addr_t *src, ip6_addr_t *dest); + +5) ip6_addr_t *ip6_get_gateway(struct netif *netif, ip6_addr_t *dest); + +6) struct ip6_route_entry *ip6_get_route_table(void); + +For route lookup from the table, The LWIP_HOOK_IP6_ROUTE hook in ip6_route(..) of ip6.c +could be assigned to the ip6_static_route() API of this implementation to return the +appropriate netif. + +-- The application can add routes using the API ip6_add_route_entry(..). + This API adds the ip6 prefix route into the static route table while + keeping all entries sorted in decreasing order of prefix length. + Subsequently, a linear search down the list can be performed to retrieve a + matching route entry for a Longest Prefix Match. + The prefix length is expected to be at an 8-bit boundary. While this is + a limitation, it would serve most practical purposes. + +-- The application can remove routes using the API ip6_remove_route_entry(..). + +-- The application can find a route entry for a specific address using the + ip6_find_route_entry() function which returns the index of the found entry. + This is used internally by the route lookup function ip6_static_route() API. + +-- To fetch the gateway IPv6 address for a specific destination IPv6 + address and target netif, the application can call ip6_get_gateway(..). + This API could be assigned to the LWIP_HOOK_ND6_GET_GW() if a gateway has + been added as part of the ip6_add_route_entry(). + +-- To fetch a pointer to the head of the table, the application can call + ip6_get_route_table(). diff --git a/contrib/addons/ipv6_static_routing/ip6_route_table.c b/contrib/addons/ipv6_static_routing/ip6_route_table.c new file mode 100644 index 00000000000..a92dd33706d --- /dev/null +++ b/contrib/addons/ipv6_static_routing/ip6_route_table.c @@ -0,0 +1,248 @@ +/** + * @file + * IPv6 static route table. + */ + +/* + * Copyright (c) 2015 Nest Labs, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Pradip De <pradipd@google.com> + * + * + * Please coordinate changes and requests with Pradip De + * <pradipd@google.com> + */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "ip6_route_table.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/nd6.h" +#include "lwip/debug.h" +#include "lwip/stats.h" + +#include "string.h" + +static struct ip6_route_entry static_route_table[LWIP_IPV6_NUM_ROUTE_ENTRIES]; + +/** + * Add the ip6 prefix route and target netif into the static route table while + * keeping all entries sorted in decreasing order of prefix length. + * 1. Search from the last entry up to find the correct slot to insert while + * moving entries one position down to create room. + * 2. Insert into empty slot created. + * + * Subsequently, a linear search down the list can be performed to retrieve a + * matching route entry for a Longest Prefix Match. + * + * @param ip6_prefix the route prefix entry to add. + * @param netif pointer to target netif. + * @param gateway the gateway address to use to send through. Has to be link local. + * @param idx return value argument of index where route entry was added in table. + * @return ERR_OK if addition was successful. + * ERR_MEM if table is already full. + * ERR_ARG if passed argument is bad or route already exists in table. + */ +err_t +ip6_add_route_entry(const struct ip6_prefix *ip6_prefix, struct netif *netif, const ip6_addr_t *gateway, s8_t *idx) +{ + s8_t i = -1; + err_t retval = ERR_OK; + + if (!ip6_prefix_valid(ip6_prefix->prefix_len) || (netif == NULL)) { + retval = ERR_ARG; + goto exit; + } + + /* Check if an entry already exists with matching prefix; If so, replace it. */ + for (i = 0; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) { + if ((ip6_prefix->prefix_len == static_route_table[i].prefix.prefix_len) && + memcmp(&ip6_prefix->addr, &static_route_table[i].prefix.addr, + ip6_prefix->prefix_len / 8) == 0) { + /* Prefix matches; replace the netif with the one being added. */ + goto insert; + } + } + + /* Check if the table is full */ + if (static_route_table[LWIP_IPV6_NUM_ROUTE_ENTRIES - 1].netif != NULL) { + retval = ERR_MEM; + goto exit; + } + + /* Shift all entries down the table until slot is found */ + for (i = LWIP_IPV6_NUM_ROUTE_ENTRIES - 1; + i > 0 && (ip6_prefix->prefix_len > static_route_table[i - 1].prefix.prefix_len); i--) { + SMEMCPY(&static_route_table[i], &static_route_table[i - 1], sizeof(struct ip6_route_entry)); + } + +insert: + /* Insert into the slot selected */ + SMEMCPY(&static_route_table[i].prefix, ip6_prefix, sizeof(struct ip6_prefix)); + static_route_table[i].netif = netif; + + /* Add gateway to route table */ + static_route_table[i].gateway = gateway; + + if (idx != NULL) { + *idx = i; + } + +exit: + return retval; +} + +/** + * Removes the route entry from the static route table. + * + * @param ip6_prefix the route prefix entry to delete. + */ +void +ip6_remove_route_entry(const struct ip6_prefix *ip6_prefix) +{ + int i, pos = -1; + + for (i = 0; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) { + /* compare prefix to find position to delete */ + if (ip6_prefix->prefix_len == static_route_table[i].prefix.prefix_len && + memcmp(&ip6_prefix->addr, &static_route_table[i].prefix.addr, + ip6_prefix->prefix_len / 8) == 0) { + pos = i; + break; + } + } + + if (pos >= 0) { + /* Shift everything beyond pos one slot up */ + for (i = pos; i < LWIP_IPV6_NUM_ROUTE_ENTRIES - 1; i++) { + SMEMCPY(&static_route_table[i], &static_route_table[i+1], sizeof(struct ip6_route_entry)); + if (static_route_table[i].netif == NULL) { + break; + } + } + /* Zero the remaining entries */ + for (; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) { + ip6_addr_set_zero((&static_route_table[i].prefix.addr)); + static_route_table[i].netif = NULL; + } + } +} + +/** + * Finds the appropriate route entry in the static route table corresponding to the given + * destination IPv6 address. Since the entries in the route table are kept sorted in decreasing + * order of prefix length, a linear search down the list is performed to retrieve a matching + * index. + * + * @param ip6_dest_addr the destination address to match + * @return the idx of the found route entry; -1 if not found. + */ +s8_t +ip6_find_route_entry(const ip6_addr_t *ip6_dest_addr) +{ + s8_t i, idx = -1; + + /* Search prefix in the sorted(decreasing order of prefix length) list */ + for(i = 0; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) { + if (memcmp(ip6_dest_addr, &static_route_table[i].prefix.addr, + static_route_table[i].prefix.prefix_len / 8) == 0) { + idx = i; + break; + } + } + + return idx; +} + +/** + * Finds the appropriate network interface for a given IPv6 address from a routing table with + * static IPv6 routes. + * + * @param src the source IPv6 address, if known + * @param dest the destination IPv6 address for which to find the route + * @return the netif on which to send to reach dest + */ +struct netif * +ip6_static_route(const ip6_addr_t *src, const ip6_addr_t *dest) +{ + int i; + + LWIP_UNUSED_ARG(src); + + /* Perform table lookup */ + i = ip6_find_route_entry(dest); + + if (i >= 0) { + return static_route_table[i].netif; + } else { + return NULL; + } +} + +/** + * Finds the gateway IP6 address for a given destination IPv6 address and target netif + * from a routing table with static IPv6 routes. + * + * @param netif the netif used for sending + * @param dest the destination IPv6 address + * @return the ip6 address of the gateway to forward packet to + */ +const ip6_addr_t * +ip6_get_gateway(struct netif *netif, const ip6_addr_t *dest) +{ + const ip6_addr_t *ret_gw = NULL; + const int i = ip6_find_route_entry(dest); + + LWIP_UNUSED_ARG(netif); + + if (i >= 0) { + if (static_route_table[i].gateway != NULL) { + ret_gw = static_route_table[i].gateway; + } + } + + return ret_gw; +} + +/** + * Returns the top of the route table. + * This should be used for debug printing only. + * + * @return the top of the route table. + */ +const struct ip6_route_entry * +ip6_get_route_table(void) +{ + return static_route_table; +} + +#endif /* LWIP_IPV6 */ diff --git a/contrib/addons/ipv6_static_routing/ip6_route_table.h b/contrib/addons/ipv6_static_routing/ip6_route_table.h new file mode 100644 index 00000000000..478328e47d7 --- /dev/null +++ b/contrib/addons/ipv6_static_routing/ip6_route_table.h @@ -0,0 +1,94 @@ +/** + * @file + * + * IPv6 static route table. + */ + +/* + * Copyright (c) 2015 Nest Labs, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Pradip De <pradipd@google.com> + * + * + * Please coordinate changes and requests with Pradip De + * <pradipd@google.com> + */ + +#ifndef __LWIP_IP6_ROUTE_TABLE_H__ +#define __LWIP_IP6_ROUTE_TABLE_H__ + +#include "lwip/opt.h" + +#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/ip6_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct netif; + +/** + * LWIP_IPV6_NUM_ROUTES: Number of IPV6 routes that can be kept in the static route table. + */ +#ifndef LWIP_IPV6_NUM_ROUTE_ENTRIES +#define LWIP_IPV6_NUM_ROUTE_ENTRIES (8) +#endif + +#define IP6_MAX_PREFIX_LEN (128) +#define IP6_PREFIX_ALLOWED_GRANULARITY (8) +/* Prefix length cannot be greater than 128 bits and needs to be at a byte boundary */ +#define ip6_prefix_valid(prefix_len) (((prefix_len) <= IP6_MAX_PREFIX_LEN) && \ + (((prefix_len) % IP6_PREFIX_ALLOWED_GRANULARITY) == 0)) + +struct ip6_prefix { + ip6_addr_t addr; + u8_t prefix_len; /* prefix length in bits at byte boundaries */ +}; + +struct ip6_route_entry { + struct ip6_prefix prefix; + struct netif *netif; + const ip6_addr_t *gateway; +}; + +err_t ip6_add_route_entry(const struct ip6_prefix *ip6_prefix, struct netif *netif, + const ip6_addr_t *gateway, s8_t *idx); +void ip6_remove_route_entry(const struct ip6_prefix *ip6_prefix); +s8_t ip6_find_route_entry(const ip6_addr_t *ip6_dest_addr); +struct netif *ip6_static_route(const ip6_addr_t *src, const ip6_addr_t *dest); +const ip6_addr_t *ip6_get_gateway(struct netif *netif, const ip6_addr_t *dest); +const struct ip6_route_entry *ip6_get_route_table(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IPV6 */ + +#endif /* __LWIP_IP6_ROUTE_TABLE_H__ */ |