diff --git a/src/core/ipv6/ethip6.c b/src/core/ipv6/ethip6.c
index eedc1f9..9e7aedb 100644
--- a/src/core/ipv6/ethip6.c
+++ b/src/core/ipv6/ethip6.c
@@ -51,6 +51,9 @@
 #include "lwip/inet_chksum.h"
 #include "lwip/netif.h"
 #include "lwip/icmp6.h"
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+#include "lwip/ip6_route_table.h"
+#endif
 
 #include <string.h>
 
@@ -137,6 +140,9 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
 {
   struct eth_addr dest;
   s8_t i;
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+  ip6_addr_t *gateway = NULL;
+#endif
 
   /* make room for Ethernet header - should not fail */
   if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
@@ -162,6 +168,29 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
 
   /* We have a unicast destination IP address */
   /* TODO anycast? */
+
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+  /* See if a gateway is present for the destination address in the static route table */
+#ifdef LWIP_HOOK_ETHIP6_GET_GW
+  gateway = LWIP_HOOK_ETHIP6_GET_GW(netif, ip6addr);
+#endif
+  if (gateway != NULL) {
+    i = nd6_search_destination_cache_entry(ip6addr);
+    if (i < 0) {
+      /* Not found. Create a new destination entry. */
+      i = nd6_create_destination_cache_entry();
+      if (i < 0) {
+        /* Could not create a destination cache entry. */
+        return ERR_MEM;
+      }
+    }
+
+    /* Add gateway as next hop into destination cache */
+    destination_cache[i].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */
+    ip6_addr_copy(destination_cache[i].next_hop_addr, *gateway);
+  }
+#endif
+
   /* Get next hop record. */
   i = nd6_get_next_hop_entry(ip6addr, netif);
   if (i < 0) {
diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c
index f4bc4af..c525df4 100644
--- a/src/core/ipv6/ip6.c
+++ b/src/core/ipv6/ip6.c
@@ -59,6 +59,9 @@
 #include "lwip/mld6.h"
 #include "lwip/debug.h"
 #include "lwip/stats.h"
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+#include "lwip/ip6_route_table.h"
+#endif
 
 #if !LWIP_IPV4
 /** Global data for IPv6 only */
diff --git a/src/core/ipv6/ip6_route_table.c b/src/core/ipv6/ip6_route_table.c
new file mode 100644
index 0000000..83e9216
--- /dev/null
+++ b/src/core/ipv6/ip6_route_table.c
@@ -0,0 +1,272 @@
+/**
+ * @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 <pde@nestlabs.com>
+ *
+ *
+ * Please coordinate changes and requests with Pradip De
+ * <pde@nestlabs.com>
+ */
+
+#include "lwip/opt.h"
+
+#if LWIP_IPV6  /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/netif.h"
+#include "lwip/ip6.h"
+#include "lwip/ip6_route_table.h"
+#include "lwip/ip6_addr.h"
+#include "lwip/nd6.h"
+#include "lwip/debug.h"
+#include "lwip/stats.h"
+
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+
+struct ip6_route_entry static_route_table[LWIP_IPV6_NUM_ROUTE_ENTRIES];
+
+/**
+ * Compare two IPv6 addresses upto a given prefix length in bytes.
+ *
+ * @param addr1 First IPv6 address.
+ * @param addr2 Second IPv6 address.
+ * @param len_in_bytes prefix length in bytes.
+ * @return +1 if match, else -1.
+ */
+s8_t 
+ip6_addr_cmp_upto_bytenum(ip6_addr_t *addr1, ip6_addr_t *addr2, u8_t len_in_bytes)
+{
+  s8_t result = 1;
+  int i;
+  int four_byte_blocks = len_in_bytes / sizeof(u32_t);
+  int remainder_bytes = len_in_bytes % sizeof(u32_t);
+
+  /* Compare the 4 byte blocks directly */
+  for (i = 0; i < four_byte_blocks; i++) {
+    if (addr1->addr[i] == addr2->addr[i]) {
+      continue;
+    } else {
+      result = -1;
+      break;
+    }
+  }
+
+  /* Compare the remainder bytes from the ith word */
+  if (result) {
+    switch(remainder_bytes) {
+    case 1:
+      if ((htonl(addr1->addr[i]) >> 24 & 0x000000ff) !=
+          (htonl(addr2->addr[i]) >> 24 & 0x000000ff)) {
+        result = -1;
+      }
+      break;
+    case 2:
+      if ((htonl(addr1->addr[i]) >> 16 & 0x0000ffff) !=
+          (htonl(addr2->addr[i]) >> 16 & 0x0000ffff)) {
+        result = -1;
+      }
+      break;
+    case 3:
+      if ((htonl(addr1->addr[i]) >> 8 & 0x00ffffff) !=
+          (htonl(addr2->addr[i]) >> 8 & 0x00ffffff)) {
+        result = -1;
+      }
+      break;
+    }
+  }
+
+  return result;
+}
+
+/**
+ * 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.
+ * @return slot where new entry is entered.
+ */
+s8_t 
+ip6_add_route_entry(struct ip6_prefix *ip6_prefix, struct netif *netif, ip6_addr_t *gateway)
+{
+  int i = -1;
+
+  /* Prefix length cannot be greater than 128 bits */
+  if ((ip6_prefix->prefix_len > 128) || (netif == NULL)) {
+    return ERR_VAL;
+  }
+
+  /* Check if the table is full */
+  if (static_route_table[LWIP_IPV6_NUM_ROUTE_ENTRIES - 1].netif != NULL) {
+    return ERR_MEM;
+  }
+
+  /* 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 into the empty slot created */
+  SMEMCPY(&static_route_table[i].prefix, ip6_prefix, sizeof(struct ip6_prefix));
+  static_route_table[i].netif = netif;
+  
+  /* Add gateway to route table */
+  if (gateway && ip6_addr_islinklocal(gateway)) {
+    static_route_table[i].gateway = gateway;
+    /* Add gateway to default router list */
+    if (nd6_add_static_gateway(gateway, netif) < 0) {
+      return -1;
+    }
+  }
+  else {
+    static_route_table[i].gateway = NULL;
+  }
+
+  return i;
+}
+
+/**
+ * Removes the route entry from the static route table.
+ *
+ * @param ip6_prefix the route prefix entry to delete.
+ */
+void
+ip6_remove_route_entry(struct ip6_prefix *ip6_prefix)
+{
+  int i, pos = 0;
+  for (i = 0; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) {
+    /* compare prefix to find position to delete */
+    if (ip6_addr_cmp(&ip6_prefix->addr, &static_route_table[i].prefix.addr) &&
+        ip6_prefix->prefix_len == static_route_table[i].prefix.prefix_len) {
+      pos = i;
+      break;
+    }
+
+  }
+
+  /* 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;
+    }
+  }
+  /* Set the last entry shifted to NULL; Necessary if table was full */
+  if (i == LWIP_IPV6_NUM_ROUTE_ENTRIES - 1) {
+    static_route_table[LWIP_IPV6_NUM_ROUTE_ENTRIES - 1].netif == NULL;
+  }
+
+  return;
+}
+
+/**
+ * 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 index of the found route entry; -1 if not found.
+ */
+s8_t 
+ip6_find_route_entry(ip6_addr_t *ip6_dest_addr)
+{
+  int i, index = -1;
+
+  /* Search prefix in the sorted(decreasing order of prefix length) list */
+  for(i = 0; i < LWIP_IPV6_NUM_ROUTE_ENTRIES; i++) {
+    if (ip6_addr_cmp_upto_bytenum(ip6_dest_addr, &static_route_table[i].prefix.addr,
+        static_route_table[i].prefix.prefix_len / 8)) {
+      index = i;
+      break;
+    }
+  }
+
+  return index;
+}
+
+/**
+ * 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(ip6_addr_t *src, ip6_addr_t *dest)
+{
+  int i = -1;
+
+  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
+ */ 
+ip6_addr_t *ip6_get_gateway(struct netif *netif, ip6_addr_t *dest)
+{
+  int i = -1;
+  ip6_addr_t *ret_gw = NULL;
+  
+  i = ip6_find_route_entry(dest);
+  if (i >= 0) {
+    if (static_route_table[i].gateway != NULL) {
+      ret_gw = static_route_table[i].gateway;
+    }
+  }
+
+  return ret_gw;
+}
+
+#endif /* LWIP_IPV6_ROUTE_TABLE_SUPPORT */
+
+#endif /* LWIP_IPV6 */
diff --git a/src/core/ipv6/nd6.c b/src/core/ipv6/nd6.c
index c74e35a..27f7601 100644
--- a/src/core/ipv6/nd6.c
+++ b/src/core/ipv6/nd6.c
@@ -1272,6 +1272,56 @@ nd6_is_prefix_in_netif(const ip6_addr_t * ip6addr, struct netif * netif)
   return 0;
 }
 
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+/**
+ * Public method for creating a new destination cache entry. If no unused entry is found,
+ * will recycle oldest entry. 
+ *
+ * @return The destination cache entry index that was created, -1 if no
+ * entry was created
+ */
+s8_t
+nd6_create_destination_cache_entry(void)
+{
+    return nd6_new_destination_cache_entry();
+}
+
+/**
+ * Public method for searching for a destination cache entry
+ *
+ * @param ip6addr the IPv6 address of the destination
+ * @return The destination cache entry index that matched, -1 if no
+ * entry is found
+ */
+s8_t
+nd6_search_destination_cache_entry(ip6_addr_t * ip6addr)
+{
+    return nd6_find_destination_cache_entry(ip6addr);
+}
+
+/**
+ * Add a static gateway to the default router list.
+ *
+ * @param ip6addr the gateway address
+ * @param netif the netif to send the outgoing packet on
+ * @return the default router entry index, or -1 if no suitable
+ *         router is found
+ */
+s8_t
+nd6_add_static_gateway(ip6_addr_t *gateway, struct netif *netif)
+{
+    int i = -1;
+    /* Get the matching default router entry. */
+    i = nd6_get_router(gateway, netif);
+    if (i < 0) {
+      /* Create a new router entry. */
+      i = nd6_new_router(gateway, netif);
+    }
+
+    return i;
+}
+#endif
+
 /**
  * Select a default router for a destination.
  *
diff --git a/src/include/lwip/ip6_route_table.h b/src/include/lwip/ip6_route_table.h
new file mode 100644
index 0000000..9917d51
--- /dev/null
+++ b/src/include/lwip/ip6_route_table.h
@@ -0,0 +1,83 @@
+/**
+ * @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 <pde@nestlabs.com>
+ *
+ *
+ * Please coordinate changes and requests with Pradip De
+ * <pde@nestlabs.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/ip.h"
+#include "lwip/ip6_addr.h"
+#include "lwip/def.h"
+#include "lwip/netif.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+struct ip6_prefix {
+  ip6_addr_t addr;
+  s8_t prefix_len; /* prefix length is number of bytes */
+};
+
+struct ip6_route_entry {
+  struct ip6_prefix prefix;
+  struct netif *netif;
+  ip6_addr_t *gateway;
+};
+
+extern struct ip6_route_entry static_route_table[];
+
+s8_t ip6_add_route_entry(struct ip6_prefix *ip6_prefix, struct netif *netif, ip6_addr_t *gateway);
+void ip6_remove_route_entry(struct ip6_prefix *ip6_prefix);
+s8_t ip6_find_route_entry(ip6_addr_t *ip6_dest_addr);
+struct netif *ip6_static_route(ip6_addr_t *src, ip6_addr_t *dest);
+ip6_addr_t *ip6_get_gateway(struct netif *netif, ip6_addr_t *dest);
+#endif /* LWIP_IPV6_ROUTE_TABLE_SUPPORT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LWIP_IPV6 */
+
+#endif /* __LWIP_IP6_ROUTE_TABLE_H__ */
diff --git a/src/include/lwip/nd6.h b/src/include/lwip/nd6.h
index 5c01d2d..88439f9 100644
--- a/src/include/lwip/nd6.h
+++ b/src/include/lwip/nd6.h
@@ -352,6 +352,12 @@ err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf * p);
 #if LWIP_ND6_TCP_REACHABILITY_HINTS
 void nd6_reachability_hint(const ip6_addr_t * ip6addr);
 #endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+s8_t nd6_create_destination_cache_entry(void);
+s8_t nd6_search_destination_cache_entry(ip6_addr_t * ip6addr);
+s8_t nd6_add_static_gateway(ip6_addr_t *gateway, struct netif *netif);
+#endif /* LWIP_IPV6_ROUTE_TABLE_SUPPORT */
+
 
 #ifdef __cplusplus
 }
diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h
index d0976e4..3bc984d 100644
--- a/src/include/lwip/opt.h
+++ b/src/include/lwip/opt.h
@@ -1263,6 +1263,19 @@
 #define TCP_RCV_SCALE                   0
 #endif
 
+/**
+ * LWIP_IPV6_ROUTE_TABLE_SUPPORT==1: Enable support for adding static routes and refering these during forwarding.
+ */
+#ifndef LWIP_IPV6_ROUTE_TABLE_SUPPORT
+#define LWIP_IPV6_ROUTE_TABLE_SUPPORT   0
+#endif
+
+/**
+ * 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
 
 /*
    ----------------------------------
@@ -2786,6 +2799,22 @@
  * Returns the destination netif or NULL if no destination netif is found. In
  * that case, ip6_route() continues as normal.
  */
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+#define LWIP_HOOK_IP6_ROUTE(src, dest)               ip6_static_route(src, dest)
+#endif
+
+/**
+* LWIP_HOOK_ETHIP6_GET_GW(netif, dest):
+* - called from ethip6_output() (IPv6)
+* - netif: the netif used for sending
+* - dest: the destination IPv6 address
+* Returns the IPv6 address of the gateway to handle the specified destination
+* IPv6 address. If NULL is returned, the netif's default gateway is used.
+* The returned address MUST be reachable on the specified netif!
+*/
+#if LWIP_IPV6_ROUTE_TABLE_SUPPORT
+#define LWIP_HOOK_ETHIP6_GET_GW(netif, dest)         ip6_get_gateway(netif, dest)
+#endif
 
 /**
  * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr):
