]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - support/sdk/c/blip/driver/routing.c
commit svn HEAD of blip into core to start merge testing
[tinyos-2.x.git] / support / sdk / c / blip / driver / routing.c
index f883f32c7d28a7c1bcd7975ac85fec3b2db7f9cd..11059e14f597a4c55d34022d434a1cd2d9f2f5ec 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/select.h>
+#include <net/route.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
 
 #include <6lowpan.h>
 #include <lib6lowpan.h>
 #include "nwstate.h"
 #include "logging.h"
 #include "config.h"
+#include "mcast.h"
+#include "netlink.h"
 
-static hw_addr_t my_short_addr;
+static ieee154_saddr_t my_short_addr;
 extern struct in6_addr  __my_address;
 
 char proxy_dev[IFNAMSIZ], tun_dev[IFNAMSIZ];
+int mcast_sock;
+
+char report_buf[ROUTMSGSIZ];
 
 /*
  * Call to setup routing tables.
  *
  */
-uint8_t routing_init(struct config *c, char *tun_name) {
-  nw_init();
+int routing_init(struct config *c, char *tun_name) {
+  FILE *fd;
+  char buf[256];
   my_short_addr = ntohs(__my_address.s6_addr16[7]);
   strncpy(proxy_dev, c->proxy_dev, IFNAMSIZ);
   strncpy(tun_dev, tun_name, IFNAMSIZ);
-/*   nl_fd = socket(AF_NETLINK, SOCK_RAW, protocol); */
-/*   if (nl_fd < 0)  */
-/*     return -1; */
 
+  // set up the network state data structures
+  nw_init();
+
+  // start a netlink session to the kernel
+  nl_init();
+
+  mcast_sock = mcast_start(proxy_dev);;
+
+  if ((fd = fopen("/proc/sys/net/ipv6/conf/all/forwarding", "w")) == NULL) {
+    log_fatal_perror("enable forwarding");
+    return -1;
+  }
+  fprintf(fd, "1");
+  fclose(fd);
+
+  snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/proxy_ndp", proxy_dev);
+  if ((fd = fopen(buf, "w")) == NULL) {
+    warn("unable to enable IPv6 ND proxy on %s\n", proxy_dev);
+  } else {
+    fprintf(fd, "1");
+    fclose(fd);
+  }
+
+  return (mcast_sock >= 0) ? 0 : -1;
+}
+
+int routing_add_fds(fd_set *fds) {
+  if (mcast_sock >=0) {
+    FD_SET(mcast_sock, fds);
+  }
+  return mcast_sock;
+}
+
+int route_cmd(int cmd, struct in6_addr *dest, char *dev) {
+  struct in6_rtmsg rt;
+  memset((char *) &rt, 0, sizeof(struct in6_rtmsg));
+  memcpy(&rt.rtmsg_dst, dest, sizeof(struct in6_addr));
+
+  rt.rtmsg_flags = RTF_UP | RTF_HOST;
+  rt.rtmsg_metric = 1;
+  rt.rtmsg_dst_len = 128;
+  rt.rtmsg_ifindex = if_nametoindex(dev);
+
+  return ioctl(mcast_sock, cmd, &rt);
+}        
+
+
+int routing_process(fd_set *fds) {
+  struct sockaddr_in6 from;
+  char buf[ROUTMSGSIZ], *cur, printbuf[100];
+  struct routing_message *rmsg;
+  struct topology_header_package *th;
+  int len;
+  struct in6_addr addr;
+
+  if (mcast_sock < 0 || !FD_ISSET(mcast_sock, fds)) return 0;
+
+  len = mcast_recvfrom(&from, buf, sizeof(buf));
+  rmsg = (struct routing_message *)buf;
+
+  inet_ntop(AF_INET6, &from.sin6_addr, printbuf, sizeof(printbuf));
+  debug("processing routing message from %s type %i\n", printbuf, rmsg->type);
+
+  memset(&addr, 0, sizeof(struct in6_addr));
+  memcpy(addr.s6_addr, __my_address.s6_addr, 8);
+
+  switch (rmsg->type) {
+  case RMSG_TOPOLOGY:
+    cur = rmsg->data;
+    len -= sizeof(struct routing_message);
+    while (len > 0) {
+      router_t *router;
+      int header_len, i;
+      node_id_t reporter;
+
+      th = (struct topology_header_package *)cur;
+      header_len = ntohs(th->len);
+      reporter = ntohs(th->reporter);
+
+      nw_unmark_links(reporter);
+      for (i = 0; i < (header_len - sizeof(struct topology_header_package))/sizeof(struct topology_entry); i++) {
+
+        nw_add_incr_edge(reporter, &th->topo[i]);
+
+        router = nw_get_router(reporter);
+        gettimeofday(&router->lastReport, NULL);
+        
+        if (router == NULL) continue;
+        addr.s6_addr16[7] = htons(reporter);
+
+        if (rmsg->source == __my_address.s6_addr16[7] && !router->isProxying) {
+          // if I sent this report, make sure we are proxying for him
+          info("Starting to proxy for 0x%x\n", reporter);
+
+          if (route_cmd(SIOCADDRT, &addr, tun_dev) < 0) {
+            log_fatal_perror("route_add");
+          }
+
+          nl_nd_add_proxy(&addr, proxy_dev);
+          router->isProxying = TRUE;
+        }
+        if (rmsg->source != __my_address.s6_addr16[7] && router->isProxying) {
+          info("Was proxying 0x%x, but he has moved\n", reporter);
+          if (route_cmd(SIOCDELRT, &addr, tun_dev) < 0) {
+            log_fatal_perror("route_del");
+          }
+
+          nl_nd_del_neigh(&addr, proxy_dev);
+          router->isProxying = FALSE;
+        }
+      }
+      nw_clear_unmarked(reporter);
+
+      router = nw_get_router(ntohs(rmsg->source));
+      if (router != NULL && !router->isController) {
+        nw_add_controller(ntohs(rmsg->source));
+      }
+      
+      cur += header_len;
+      len -= header_len;
+    }
+    break;
+  }
   return 0;
 }
 
+int routing_add_report(node_id_t reporter, struct tlv_hdr *tlv) {
+  struct topology_header *th = (struct topology_header *)(tlv + 1);
+  struct routing_message *rmsg;
+  struct topology_header_package *pack;
+
+  rmsg = (struct routing_message *)report_buf;
+  pack = (struct topology_header_package *)&rmsg->data[0];
+
+  memset(report_buf, 0, sizeof(report_buf));
+
+  debug("routing_add_report: report from 0x%x seq: %i\n", reporter, th->seqno);
+
+  rmsg->type = RMSG_TOPOLOGY;
+  rmsg->source = __my_address.s6_addr16[7];
+  pack->reporter = htons(reporter);
+  pack->seqno = th->seqno;
+  pack->len      = htons(tlv->len - 
+                         sizeof(struct tlv_hdr) -
+                         sizeof(struct topology_header) + 
+                         sizeof(struct topology_header_package));
+
+  memcpy(pack->topo, th->topo, tlv->len - sizeof(struct tlv_hdr) -
+         sizeof(struct topology_header));
+  
+  mcast_send(report_buf, ntohs(pack->len) + sizeof(struct routing_message));
+
+  return 0;
+}
+
+
 /*
  * @returns: truth value indicating if the destination of the packet
  * is a single hop, and requires no source route.
  */
-uint8_t routing_is_onehop(struct split_ip_msg *msg) {
+int routing_is_onehop(struct split_ip_msg *msg) {
   path_t *path;
-  uint8_t ret = ROUTE_NO_ROUTE;
+  int ret = ROUTE_NO_ROUTE;
 
   if (cmpPfx(msg->hdr.ip6_dst.s6_addr, multicast_prefix))
     return ROUTE_ONEHOP;
 
+
+#if 0
   if (msg->hdr.nxt_hdr == NXTHDR_SOURCE) {
     debug("routing_is_onehop: Source header\n");
     return ROUTE_SOURCE;
   }
+#endif
 
   path = nw_get_route(my_short_addr, ntohs(msg->hdr.ip6_dst.s6_addr16[7]));
   
   if (path != NULL) {
-    if (path->length == 1)
+    if (path->isController) {
+      ret = ROUTE_WORMHOLE;
+    } else if (path->length == 1) {
       ret = ROUTE_ONEHOP;
-    else
+    } else {
       ret = ROUTE_MHOP;
+    }
   }
   debug("routing_is_onehop: 0x%x\n", ret);
   nw_free_path(path);
@@ -137,31 +304,32 @@ uint8_t routing_is_onehop(struct split_ip_msg *msg) {
 */
 
 /*
- * Copys the IP message at orig to the empty one at ret, inserting
- * necessary routing information.
  */
 uint8_t routing_insert_route(struct split_ip_msg *orig) {
   int offset = 0;
   path_t *path = nw_get_route(my_short_addr, ntohs(orig->hdr.ip6_dst.s6_addr16[7]));
   path_t *i;
   struct generic_header *g_hdr = (struct generic_header *)malloc(sizeof(struct generic_header));
-  struct source_header *sh;
+  struct ip6_route *sh;
 
   if (g_hdr == NULL || path == NULL) {
     if (g_hdr) free(g_hdr);
     if (path) nw_free_path(path);
     return 1;
   }
+#if 0
   if (path->length == 1) {
     free(g_hdr);
     nw_free_path(path);
     return 1;
   }
+#endif
+
   debug("routing_insert_route len: 0x%x\n", path->length);
 
   // if the packet with the source route is longer then the buffer
   // we're putting it into, drop it.
-  if (ntoh16(orig->hdr.plen) + sizeof(struct source_header) + 
+  if (ntoh16(orig->hdr.plen) + sizeof(struct ip6_route) + 
       (path->length * sizeof(uint16_t)) + sizeof(struct ip6_hdr) > INET_MTU) {
     warn("packet plus source header too long\n");
     free(g_hdr);
@@ -169,7 +337,7 @@ uint8_t routing_insert_route(struct split_ip_msg *orig) {
     return 1;
   }
   
-  sh = (struct source_header *)malloc(sizeof(struct source_header) + path->length * sizeof(uint16_t));
+  sh = (struct ip6_route *)malloc(sizeof(struct ip6_route) + path->length * sizeof(uint16_t));
   if (sh == NULL) {
     free (g_hdr);
     nw_free_path(path);
@@ -177,11 +345,11 @@ uint8_t routing_insert_route(struct split_ip_msg *orig) {
   }
 
   sh->nxt_hdr = orig->hdr.nxt_hdr;
-  sh->len = sizeof(struct source_header) + (path->length * sizeof(uint16_t));
-  sh->dispatch = IP_EXT_SOURCE_DISPATCH | IP_EXT_SOURCE_CONTROLLER;
-  sh->current = 0;
+  sh->len = sizeof(struct ip6_route) + (path->length * sizeof(uint16_t));
+  sh->type = IP6ROUTE_FLAG_CONTROLLER | IP6ROUTE_TYPE_SOURCE;
+  sh->segs_remain = path->length;
   
-  orig->hdr.nxt_hdr = NXTHDR_SOURCE;
+  orig->hdr.nxt_hdr = IPV6_ROUTING;
 
   log_clear(LOGLVL_DEBUG, "to 0x%x [%i]: ", ntohs(orig->hdr.ip6_dst.s6_addr16[7]), path->length);
   for (i = path; i != NULL; i = i->next) {
@@ -207,17 +375,19 @@ uint8_t routing_insert_route(struct split_ip_msg *orig) {
 /*
  * Returns the address of the next router this packet should be send to.
  */
-hw_addr_t routing_get_nexthop(struct split_ip_msg *msg) {
-  hw_addr_t ret = 0xffff;;
+ieee154_saddr_t routing_get_nexthop(struct split_ip_msg *msg) {
+  ieee154_saddr_t ret = 0xffff;;
   path_t * path;
   if (cmpPfx(msg->hdr.ip6_dst.s6_addr, multicast_prefix))
     return ret;
 
   // If it's source routed, just grab the next hop out of the header 
+#if 0
   if (msg->hdr.nxt_hdr == NXTHDR_SOURCE) {
     debug("routing_get_nexthop: src header\n"); 
     return ntoh16((msg->headers->hdr.sh->hops[msg->headers->hdr.sh->current]));
   }
+#endif
 
   path = nw_get_route(my_short_addr, ntohs(msg->hdr.ip6_dst.s6_addr16[7]));
 
@@ -228,45 +398,3 @@ hw_addr_t routing_get_nexthop(struct split_ip_msg *msg) {
 
   return ret;
 }
-
-void routing_proc_msg(struct split_ip_msg *msg) {
-  struct generic_header *g_hdr, **prev_hdr;
-  uint8_t *prev_next, nxt_hdr = msg->hdr.nxt_hdr;
-  int i;
-  node_id_t reporter = ntohs(msg->hdr.ip6_src.s6_addr16[7]);
-
-  prev_next = &msg->hdr.nxt_hdr;
-  prev_hdr = &msg->headers;
-
-  nw_report_node(reporter);
-  for (g_hdr = msg->headers; g_hdr != NULL; g_hdr = g_hdr->next) {
-    if (nxt_hdr == NXTHDR_TOPO) {
-      // add the topology reports to the database 
-      nw_unmark_links(reporter);
-      for (i = 0; i < (g_hdr->len - sizeof(struct topology_header))/sizeof(struct topology_entry); i++) {
-        //debug("topo neigh: 0x%x hop: %i qual: 0x%x\n", g_hdr->hdr.th->topo[i].hwaddr,
-             // g_hdr->hdr.th->topo[i].hops, g_hdr->hdr.th->topo[i].link);
-        nw_add_incr_edge(reporter, &g_hdr->hdr.th->topo[i]);
-      }
-      nw_clear_unmarked(reporter);
-      // remove the topology header
-      *prev_next = g_hdr->hdr.ext->nxt_hdr;
-      *prev_hdr = g_hdr->next;
-      if (g_hdr->payload_malloced) free(g_hdr->hdr.data);
-      msg->hdr.plen = hton16(ntoh16(msg->hdr.plen) - g_hdr->len);
-      free(g_hdr);
-      return;
-    } else {
-      nxt_hdr = g_hdr->hdr.ext->nxt_hdr;
-      prev_next = &g_hdr->hdr.ext->nxt_hdr;
-      prev_hdr = &g_hdr->next;
-    }
-  }
-}
-
-
-void routing_add_table_entry(node_id_t id) {
-  /* static const char* route_add_fmt = "ip -6 route add %x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x/128 dev %s"; */
-  /* static const char* route_proxy_fmt = "ip -6 neigh add proxy %x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x:%x%02x dev %s"; */
-}