X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=support%2Fsdk%2Fc%2Fblip%2Fdriver%2Frouting.c;h=11059e14f597a4c55d34022d434a1cd2d9f2f5ec;hb=3d5c78e867d6fd52e44894e93e4bd0c172071522;hp=f883f32c7d28a7c1bcd7975ac85fec3b2db7f9cd;hpb=34dda4f22e2b435b6ddec072706809f158e60c7f;p=tinyos-2.x.git diff --git a/support/sdk/c/blip/driver/routing.c b/support/sdk/c/blip/driver/routing.c index f883f32c..11059e14 100644 --- a/support/sdk/c/blip/driver/routing.c +++ b/support/sdk/c/blip/driver/routing.c @@ -24,6 +24,11 @@ #include #include #include +#include +#include +#include +#include +#include #include <6lowpan.h> #include @@ -31,51 +36,213 @@ #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"; */ - -}