Revision: 539
          http://vde.svn.sourceforge.net/vde/?rev=539&view=rev
Author:   danielel
Date:     2012-01-29 02:59:45 +0000 (Sun, 29 Jan 2012)
Log Message:
-----------
Olsr: refactoring of messages. still TODO: timing implementation, message 
forwarding, evaluate link quality

Modified Paths:
--------------
    branches/vde-router/vde-2/src/vde_router/vder_olsr.c
    branches/vde-router/vde-2/src/vde_router/vder_olsr.h

Modified: branches/vde-router/vde-2/src/vde_router/vder_olsr.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_olsr.c        2012-01-23 
12:41:31 UTC (rev 538)
+++ branches/vde-router/vde-2/src/vde_router/vder_olsr.c        2012-01-29 
02:59:45 UTC (rev 539)
@@ -9,202 +9,316 @@
 
 #define OLSR_MSG_INTERVAL 2000
 #define HOST_NETMASK (htonl(0xFFFFFFFF))
-#define MAX_HOPS 256
+#ifndef MIN
+# define MIN(a,b) (a<b?a:b)
+#endif
 
+static struct vder_udp_socket *udpsock;
+static struct olsr_setup *settings;
+uint16_t my_ansn = 0;
+
 struct olsr_route_entry
 {
        struct olsr_route_entry *next;
-       unsigned long           time_left;
+       long            time_left;
        uint32_t                        destination;
-       uint32_t                        gateway;
+       struct olsr_route_entry *gateway;
        struct vder_iface       *iface;
        uint16_t                        metric;
        uint8_t                         link_type;
+       struct olsr_route_entry *children;
+       uint16_t ansn;
+       uint8_t lq, nlq;
+       uint8_t *advertised_tc;
 };
 
-static struct olsr_route_entry *Routes[MAX_HOPS] = {};
-static struct vder_udp_socket *udpsock;
-static struct olsr_setup *settings;
+static struct olsr_route_entry *Local_interfaces;
 
-static struct olsr_route_entry *get_route_by_address(uint32_t ip)
+struct olsr_route_entry *olsr_get_ethentry(struct vder_iface *vif)
 {
-       struct olsr_route_entry *cur;
-       int i;
+       struct olsr_route_entry *cur = Local_interfaces;
+       while(cur) {
+               if (cur->iface == vif)
+                       return cur;
+               cur = cur->next;
+       }
+       return NULL;
+}
 
-       for (i = 0; i < MAX_HOPS; i++) {
-               cur = Routes[i];
-               while(cur) {
-                       if (cur->destination == ip)
-                               return cur;
-                       cur = cur->next;
-               }
+static struct olsr_route_entry *get_next_hop(struct olsr_route_entry *dst)
+{
+       struct olsr_route_entry *hop = dst;
+       while(hop) {
+               if(hop->metric <= 1)
+                       return hop;
+               hop = hop->gateway;
        }
        return NULL;
 }
 
-static void route_change_metric(struct olsr_route_entry *r, int new_metric, 
uint32_t new_gateway)
+static inline void olsr_route_add(struct olsr_route_entry *el)
 {
-       struct olsr_route_entry *cur, *prev;
-       cur = Routes[r->metric], prev = NULL;
+       struct olsr_route_entry *nexthop;
+       if (el->gateway) {
+               /* 2-hops route or more */
+               el->next = el->gateway->children;
+               el->gateway->children = el;
+               nexthop = get_next_hop(el);
+               vder_route_add(el->destination, HOST_NETMASK, 
nexthop->destination, el->metric, NULL);
+               el->link_type = OLSRLINK_MPR;
+       } else if (el->iface) {
+               /* neighbor */
+               struct olsr_route_entry *ei = olsr_get_ethentry(el->iface);
+               el->link_type = OLSRLINK_SYMMETRIC;
+               if (ei) {
+                       el->next = ei->children;
+                       ei->children = el;
+               }
+       }
+}
+
+static inline void olsr_route_del(struct olsr_route_entry *r)
+{
+       struct olsr_route_entry *cur, *prev = NULL, *lst;
+       if (r->gateway) {
+               lst = r->gateway->children;
+       } else if (r->iface) {
+               lst = olsr_get_ethentry(r->iface);
+       } else {
+               lst = Local_interfaces;
+       }
+       cur = lst, prev = NULL;
        while(cur) {
                if (cur == r) {
                        /* found */
-                       if (!prev)
-                               Routes[r->metric] = cur->next;
-                       else
-                               prev->next = cur->next;
+                       if (r->gateway) {
+                               vder_route_del(r->destination, HOST_NETMASK, 
r->metric);
 
-                       if (r->metric > 1)
-                               vder_route_del(cur->destination, HOST_NETMASK, 
r->metric);
+                               if (!prev)
+                                       r->gateway->children = r->next;
+                               else
+                                       prev->next = r->next;
+                       }
 
-                       r->metric = new_metric;
-                       r->gateway = new_gateway;
-
-                       if (r->metric > 1) {
-                               vder_route_add(cur->destination, HOST_NETMASK, 
new_gateway, new_metric, NULL);
-                               r->next = Routes[r->metric];
-                               Routes[r->metric] = r;
+                       while (r->children) {
+                               olsr_route_del(r->children);
+                               /* Orphans must die. */
+                               free(r->children);
                        }
                        return;
                }
-
                prev = cur;
                cur = cur->next;
        }
 }
 
+static struct olsr_route_entry *get_route_by_address(struct olsr_route_entry 
*lst, uint32_t ip)
+{
+       struct olsr_route_entry *found;
+       if(lst) {
+               if (lst->destination == ip) {
+                       return lst;
+               }
+               found = get_route_by_address(lst->children, ip);
+               if (found)
+                       return found;
+               found = get_route_by_address(lst->next, ip);
+               if (found)
+                       return found;
+       }
+       return NULL;
+}
 
 static void refresh_neighbors(struct vder_iface *iface)
 {
-       struct olsr_route_entry *cur;
        uint32_t neighbors[256];
        int i;
-       unsigned char found = 0;
+       struct olsr_route_entry *found = NULL, *ancestor = NULL;
        int n_vec_size = vder_arp_get_neighbors(iface, neighbors, 256);
+
+       ancestor = olsr_get_ethentry(iface);
+       if (!ancestor)
+               return;
+
        for (i = 0; i < n_vec_size; i++) {
-               cur = Routes[1];
-               while(cur) {
-                       if (cur->destination == neighbors[i]) {
-                               cur->time_left = (OLSR_MSG_INTERVAL << 2);
-                               found = 1;
-                               break;
+               found = get_route_by_address(Local_interfaces, neighbors[i]);
+               if (found) {
+                       if (found->metric > 1) { /* Reposition among neighbors 
*/
+                               olsr_route_del(found);
+                               found->gateway = olsr_get_ethentry(iface);
+                               found->iface = iface;
+                               found->metric = 1;
+                               found->lq = 0xFF;
+                               found->nlq = 0xFF;
+                               olsr_route_add(found);
                        }
-                       cur = cur->next;
-               }
-               if (!found) {
-                       /* look on bigger metrics */
-                       struct olsr_route_entry *e = 
get_route_by_address(neighbors[i]);
-                       if (e) {
-                               route_change_metric(e, 0U, 1);
-                       } else {
-                               e = malloc(sizeof (struct olsr_route_entry));
-                               if (!e) {
-                                       perror("olsr: adding local route 
entry");
-                                       return;
-                               }
+                       found->link_type = OLSRLINK_SYMMETRIC;
+                       found->time_left = (OLSR_MSG_INTERVAL << 2);
+               } else {
+                       struct olsr_route_entry *e = malloc(sizeof (struct 
olsr_route_entry));
+                       if (!e) {
+                               perror("olsr: adding local route entry");
+                               return;
                        }
+                       memset(e, 0, sizeof(struct olsr_route_entry));
                        e->destination = neighbors[i];
                        e->link_type = OLSRLINK_SYMMETRIC;
                        e->time_left = (OLSR_MSG_INTERVAL << 2);
-                       e->gateway = 0U;
+                       e->gateway = olsr_get_ethentry(iface);
                        e->iface = iface;
                        e->metric = 1;
-                       e->next = Routes[1];
-                       Routes[1] = e;
+                       e->lq = 0xFF;
+                       e->nlq = 0xFF;
+                       olsr_route_add(e);
                }
        }
 }
 
+static void olsr_garbage_collector(struct olsr_route_entry *sublist)
+{
+       if(!sublist)
+               return;
+       if ((sublist->time_left--) <= 0) {
+               olsr_route_del(sublist);
+               free(sublist);
+               return;
+       }
+       olsr_garbage_collector(sublist->children);
+       olsr_garbage_collector(sublist->next);
+}
 
+
 static void refresh_routes(void)
 {
        int i;
-       struct olsr_route_entry *cur, *prev = NULL;
+       struct olsr_route_entry *local, *neighbor = NULL;
 
        /* Refresh local entries */
 
        /* Step 1: set zero expire time for local addresses and neighbors*/
-       for (i = 0; i < 2; i++) {
-               cur = Routes[i];
-               while(cur) {
-                       cur->time_left = (OLSR_MSG_INTERVAL << 2);
-                       cur = cur->next;
+       local = Local_interfaces;
+       while(local) {
+               local->time_left = 0;
+               neighbor = local->children;
+               while (neighbor && (neighbor->metric < 2)) {
+                       //printf("Setting to zero. Neigh: %08x metric %d\n", 
neighbor->destination, neighbor->metric);
+                       neighbor->time_left = 0;
+                       neighbor = neighbor->next;
                }
+               local = local->next;
        }
 
-
        /* Step 2: refresh timer for entries that are still valid. 
         * Add new entries.
         */
        for (i = 0; i < settings->n_ifaces; i++) {
                struct vder_iface *icur = settings->ifaces[i];
-               struct vder_ip4address *addr = icur->address_list;
-               while (addr) {
-                       unsigned char found = 0;
-                       cur = Routes[0];
-                       while(cur) {
-                               if (cur->destination == addr->address) {
-                                       cur->time_left = (OLSR_MSG_INTERVAL << 
2);
-                                       found = 1;
-                                       break;
-                               }
-                               cur = cur->next;
+               local = olsr_get_ethentry(icur);
+               if (local) {
+                       local->time_left = (OLSR_MSG_INTERVAL << 2);
+               } else if (icur->address_list) {
+                       struct olsr_route_entry *e = malloc(sizeof (struct 
olsr_route_entry));
+                       if (!e) {
+                               perror("olsr: adding local route entry");
+                               return;
                        }
-                       if (!found) {
-                               struct olsr_route_entry *e = malloc(sizeof 
(struct olsr_route_entry));
-                               if (!e) {
-                                       perror("olsr: adding local route 
entry");
-                                       return;
-                               }
-                               e->destination = addr->address;
-                               e->time_left = (OLSR_MSG_INTERVAL << 2);
-                               e->gateway = 0U;
-                               e->iface = icur;
-                               e->metric = 0;
-                               e->next = Routes[0];
-                               Routes[0] = e;
-                       }
-                       refresh_neighbors(icur);
-                       addr = addr->next;
+                       memset(e, 0, sizeof(struct olsr_route_entry));
+                       e->destination = icur->address_list->address; /* Always 
pick the first address */
+                       e->time_left = (OLSR_MSG_INTERVAL << 2);
+                       e->iface = icur;
+                       e->metric = 0;
+                       e->lq = 0xFF;
+                       e->nlq = 0xFF;
+                       e->next = Local_interfaces;
+                       Local_interfaces = e;
                }
+               refresh_neighbors(icur);
        }
 
-       /* Remove expired entries */
+}
 
-       for (i = 0; i < MAX_HOPS; i++) {
-               cur = Routes[i], prev = NULL; 
-               while(cur) {
-                       if (cur->time_left < OLSR_MSG_INTERVAL) {
-                               if (!prev)
-                                       Routes[i] = cur->next;
-                               else
-                                       prev->next = cur->next;
-                               printf("Route expired!\n");
-                               if (i > 1)
-                                       vder_route_del(cur->destination, 
HOST_NETMASK, i);
-                               free(cur);
-                       } else {
-                               prev = cur;
-                       }
-                       cur = cur->next;
+static int olsr_build_hello_neighbors(uint8_t *buf, int size)
+{
+       int ret = 0;
+       struct olsr_route_entry *local, *neighbor;
+       struct olsr_neighbor *dst = (struct olsr_neighbor *) buf;
+       local = Local_interfaces;
+       while (local) {
+               neighbor = local->children;
+               while (neighbor) {
+                       struct olsr_link *li = (struct olsr_link *) (buf + ret);
+                       li->link_code = neighbor->link_type;
+                       li->reserved = 0;
+                       li->link_msg_size = htons(sizeof(struct olsr_neighbor) 
+ sizeof(struct olsr_link));
+                       ret += sizeof(struct olsr_link);
+                       dst = (struct olsr_neighbor *) (buf+ret);
+                       dst->addr = neighbor->destination;
+                       dst->nlq = neighbor->nlq;
+                       dst->lq = neighbor->lq;
+                       dst->reserved = 0;
+                       ret += sizeof(struct olsr_neighbor);
+                       if (ret >= size)
+                               return ret - sizeof(struct olsr_neighbor) - 
sizeof(struct olsr_link);
+                       neighbor = neighbor->next;
                }
+               local = local->next;
        }
+       return ret;
 }
 
+static int olsr_build_tc_neighbors(uint8_t *buf, int size)
+{
+       int ret = 0;
+       struct olsr_route_entry *local, *neighbor;
+       struct olsr_neighbor *dst = (struct olsr_neighbor *) buf;
+       local = Local_interfaces;
+       while (local) {
+               neighbor = local->children;
+               while (neighbor) {
+                       dst->addr = neighbor->destination;
+                       dst->nlq = neighbor->nlq;
+                       dst->lq = neighbor->lq;
+                       dst->reserved = 0;
+                       ret += sizeof(struct olsr_neighbor);
+                       dst = (struct olsr_neighbor *) (buf + ret);
+                       if (ret >= size)
+                               return ret - sizeof(struct olsr_neighbor);
+                       neighbor = neighbor->next;
+               }
+               local = local->next;
+       }
+       return ret;
+}
+
+static int olsr_build_mid(uint8_t *buf, int size, struct vder_iface *excluded)
+{
+       int ret = 0;
+       struct olsr_route_entry *local;
+       uint32_t *dst = (uint32_t *) buf;
+       local = Local_interfaces;
+       while (local) {
+               if (local->iface != excluded) {
+                       *dst = local->destination;
+                       ret += sizeof(uint32_t);
+                       dst = (uint32_t *) (buf + ret);
+                       if (ret >= size)
+                               return ret - sizeof(uint32_t);
+               }
+               local = local->next;
+       }
+       return ret;
+}
+
 static void olsr_make_dgram(struct vder_iface *vif)
 {
        uint8_t dgram[2000];
-       int size = 0;
+       int size = 0, r;
        struct vder_ip4address *ep;
        struct olsrhdr *ohdr;
        uint32_t netmask, bcast;
-       struct olsrmsg *msg_hello, *msg_mid;
+       struct olsrmsg *msg_hello, *msg_mid, *msg_tc;
        struct olsr_hmsg_hello *hello;
-
-       struct olsr_link *hlink;
-       struct olsr_route_entry *entry;
-       int n_vec_size, i, mid_count = 0;
-
+       struct olsr_hmsg_tc *tc;
        static uint8_t hello_counter = 0, mid_counter = 0, tc_counter = 0;
        static uint16_t pkt_counter = 0;
 
@@ -224,44 +338,26 @@
        msg_hello = (struct olsrmsg *) (dgram + size);
        size += sizeof(struct olsrmsg);
        msg_hello->type = OLSRMSG_HELLO;
-       msg_hello->vtime = 60; /* one hot minute */
+       msg_hello->vtime = 0x2c;
        msg_hello->orig = ep->address;
        msg_hello->ttl = 1;
        msg_hello->hop = 0;
        msg_hello->seq = htons(hello_counter++);
-
        hello = (struct olsr_hmsg_hello *)(dgram + size);
        size += sizeof(struct olsr_hmsg_hello);
        hello->reserved = 0;
        hello->htime = 0x05; /* Todo: find and define values */
        hello->willingness = 0x07;
-
-
-       entry = Routes[1];
-       n_vec_size = 0;
-       while(entry) {
-               struct olsr_neighbor *neigh;
-               hlink = (struct olsr_link *) (dgram + size);
-               size += (sizeof(struct olsr_link));
-               hlink->reserved = 0;
-               hlink->link_code = entry->link_type;
-               hlink->link_msg_size = htons(sizeof(struct olsr_link) + 
sizeof(struct olsr_neighbor));
-               neigh = (struct olsr_neighbor *) (dgram + size);
-               size += (sizeof(struct olsr_neighbor));
-               neigh->addr = entry->destination;
-               neigh->lq = 0xFF;
-               neigh->nlq = 0xFF;
-               n_vec_size++;
-               entry = entry->next;
+       r = olsr_build_hello_neighbors(dgram + size, 2000 - size);
+       if (r < 0) {
+               perror("Building hello message");
+               return;
        }
-       msg_hello->size = htons(sizeof(struct olsrmsg) +
-               sizeof(struct olsr_hmsg_hello) +  n_vec_size * ((sizeof(struct 
olsr_link) + sizeof(struct olsr_neighbor))));
+       size += r;
+       msg_hello->size = htons(sizeof(struct olsrmsg) + sizeof(struct 
olsr_hmsg_hello) + r);
 
-
-
        /* MID Message */
 
-       entry = Routes[0];
        msg_mid = (struct olsrmsg *)(dgram + size);
        size += sizeof(struct olsrmsg);
        msg_mid->type = OLSRMSG_MID;
@@ -269,28 +365,38 @@
        msg_mid->orig = ep->address;
        msg_mid->ttl = 0xFF;
        msg_mid->hop = 0;
-
-       while(entry) {
-               uint32_t mid_address;
-               if (entry->iface != vif) {
-                       mid_address = entry->destination;
-                       memcpy(dgram + size, &mid_address, sizeof(uint32_t));
-                       size += sizeof(uint32_t);
-                       mid_count++;
-               }
-               entry = entry->next;
+       msg_mid->seq = htons(mid_counter++);
+       r = olsr_build_mid(dgram + size, 2000 - size, vif);
+       if (r < 0) {
+               perror("Building mid message");
+               return;
        }
-       if (mid_count == 0) {
-               size -= (sizeof(struct olsrmsg));
+       if (r == 0) {
+               size -= sizeof(struct olsrmsg);
        } else {
-               msg_mid->seq = htons(mid_counter++);
-               msg_mid->size = htons(sizeof(struct olsrmsg) + sizeof(uint32_t) 
* mid_count);
+               size += r;
+               msg_mid->size = htons(sizeof(struct olsrmsg) + r);
        }
 
-       /* TODO: Add TC msg */
-       
+       msg_tc = (struct olsrmsg *) (dgram + size);
+       size += sizeof(struct olsrmsg);
+       msg_tc->type = OLSRMSG_TC;
+       msg_tc->vtime = 0x2c; 
+       msg_tc->orig = ep->address;
+       msg_tc->ttl = 0xFF;
+       msg_tc->hop = 0;
+       msg_tc->seq = htons(tc_counter++);
+       tc = (struct olsr_hmsg_tc *)(dgram + size);
+       size += sizeof(struct olsr_hmsg_tc);
+       tc->ansn = htons(my_ansn);
+       r = olsr_build_tc_neighbors(dgram + size, 2000 - size);
+       if (r < 0) {
+               perror("Building tc message");
+               return;
+       }
+       size += r;
+       msg_tc->size = htons(sizeof(struct olsrmsg) + sizeof(struct 
olsr_hmsg_tc) + r);
 
-
        /* Finalize olsr packet */
        ohdr->len = htons(size);
        ohdr->seq = htons(pkt_counter++);
@@ -309,71 +415,190 @@
        }
 }
 
-static void recv_hello(uint8_t *buffer, int len, uint32_t origin)
+static void recv_mid(uint8_t *buffer, int len, struct olsr_route_entry 
*origin) 
 {
-       struct olsr_link *li;
+       int parsed = 0;
        uint32_t *address;
        struct olsr_route_entry *e;
+
+       if (len % sizeof(uint32_t)) /*drop*/
+               return;
+
+       while (len > parsed) {
+               address = (uint32_t *)(buffer + parsed);
+               e = get_route_by_address(Local_interfaces, *address);
+               if (!e) {
+                       e = malloc(sizeof(struct olsr_route_entry));
+                       if (!e) {
+                               perror("olsr allocating route");
+                               return;
+                       }
+                       memset(e, 0, sizeof(struct olsr_route_entry));
+                       e->time_left = (OLSR_MSG_INTERVAL << 2);
+                       e->destination = *address;
+                       e->gateway = origin;
+                       e->iface = origin->iface;
+                       e->metric = origin->metric + 1;
+                       e->lq = origin->lq;
+                       e->nlq = origin->nlq;
+                       olsr_route_add(e);
+                       arp_storm(e->destination);
+               } else if (e->metric > (origin->metric + 1)) {
+                       olsr_route_del(e);
+                       e->metric = origin->metric;
+                       e->gateway = origin;
+                       olsr_route_add(e);
+               }
+               parsed += sizeof(uint32_t);
+       }
+}
+
+static void recv_hello(uint8_t *buffer, int len, struct olsr_route_entry 
*origin)
+{
+       struct olsr_link *li;
+       struct olsr_route_entry *e;
        int parsed = 0;
+       struct olsr_neighbor *neigh;
 
+       if (!origin)
+               return;
+
        while (len > parsed) {
                li = (struct olsr_link *) buffer;
-               address = (uint32_t *)(buffer + parsed + sizeof(struct 
olsr_link));
+               neigh = (struct olsr_neighbor *)(buffer + parsed + 
sizeof(struct olsr_link));
                parsed += ntohs(li->link_msg_size);
-               e = get_route_by_address(*address);
+               e = get_route_by_address(Local_interfaces, neigh->addr);
                if (!e) {
                        e = malloc(sizeof(struct olsr_route_entry));
                        if (!e) {
                                perror("olsr allocating route");
                                return;
                        }
+                       memset(e, 0, sizeof(struct olsr_route_entry));
                        e->time_left = (OLSR_MSG_INTERVAL << 2);
-                       e->destination = *address;
+                       e->destination = neigh->addr;
                        e->gateway = origin;
-                       e->iface = NULL;
-                       e->metric = 2;
-                       e->next = Routes[2];
-                       Routes[2] = e;
+                       e->iface = origin->iface;
+                       e->metric = origin->metric + 1;
+                       e->link_type = OLSRLINK_UNKNOWN;
+                       e->lq = MIN(origin->lq, neigh->lq);
+                       e->nlq = MIN(origin->nlq, neigh->nlq);
+                       olsr_route_add(e);
                        arp_storm(e->destination);
-                       vder_route_add(*address, HOST_NETMASK, origin, 2, NULL);
-               } else if (e->metric > 2) {
-                       route_change_metric(e, origin, 2);
+               } else if ((e->gateway != origin) && (e->metric > 
(origin->metric + 1))) {
+                       olsr_route_del(e);
+                       e->metric = origin->metric + 1;
+                       e->gateway = origin;
+                       olsr_route_add(e);
                }
        }
 }
 
+static int reconsider_topology(uint8_t *buf, int size, struct olsr_route_entry 
*e)
+{
+       struct olsr_hmsg_tc *tc = (struct olsr_hmsg_tc *) buf;
+       uint16_t new_ansn = ntohs(tc->ansn);
+       int parsed = sizeof(struct olsr_hmsg_tc);
+       struct olsr_route_entry *rt;
+       struct olsr_neighbor *n;
+
+       if (e->advertised_tc && ((new_ansn > e->ansn) || ((e->ansn - new_ansn) 
> 32768)))
+       {
+               free(e->advertised_tc);
+               e->advertised_tc = NULL;
+       }
+
+       if (!e->advertised_tc) {
+               e->advertised_tc = malloc(size);
+               if (!e) {
+                       perror("Allocating forward packet");
+                       return -1;
+               }
+               memcpy(e->advertised_tc, buf, size);
+               e->ansn = new_ansn;
+               while (parsed < size) {
+                       n = (struct olsr_neighbor *) (buf + parsed);
+                       parsed += sizeof(struct olsr_neighbor);
+                       rt = get_route_by_address(Local_interfaces, n->addr);
+                       if (rt && (rt->gateway == e)) {
+                               /* Refresh existing node */
+                               rt->time_left = e->time_left;
+                       } else if (!rt || (rt->metric > (e->metric + 1)) || 
(rt->nlq < n->nlq)) {
+                               if (!rt) {
+                                       rt = malloc(sizeof (struct 
olsr_route_entry));
+                                       memset(rt, 0, sizeof(struct 
olsr_route_entry));
+                                       rt->destination = n->addr;
+                               } else {
+                                       olsr_route_del(rt);
+                               }
+                               rt->link_type = OLSRLINK_UNKNOWN;
+                               rt->iface = e->iface;
+                               rt->gateway = e;
+                               rt->metric = e->metric + 1;
+                               rt->lq = n->lq;
+                               rt->nlq = n->nlq;
+                               //rt->time_left = e->time_left;
+                               rt->time_left = 289;
+                               olsr_route_add(rt);
+                       }
+               }
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
 static void olsr_recv(uint8_t *buffer, int len)
 {
+       struct olsrmsg *msg;
+       struct olsr_hmsg_tc *msg_tc;
        struct olsrhdr *oh = (struct olsrhdr *) buffer;
+       struct olsr_route_entry *ancestor;
        int parsed = 0;
        if (len != ntohs(oh->len)) {
                return;
        }
        parsed += sizeof(struct olsrhdr);
 
-       struct olsrmsg *msg;
        while (len > parsed) {
                struct olsr_route_entry *origin;
                msg = (struct olsrmsg *) (buffer + parsed);
-               origin = get_route_by_address(msg->orig);
+               origin = get_route_by_address(Local_interfaces, msg->orig);
                if (!origin) {
+                       /* Discard this msg while it is not from known host */
                        arp_storm(msg->orig);
-               } else {
-                       origin->link_type = OLSRLINK_MPR;
+                       parsed += ntohs(msg->size);
+                       continue;
                }
+               /* We know this is a Master host and a neighbor */
+               origin->link_type = OLSRLINK_MPR;
+               origin->time_left = 288; /* TODO: get from msg->vtime */
                switch(msg->type) {
                        case OLSRMSG_HELLO:
+                               ancestor = olsr_get_ethentry(origin->iface);
+                               if ((origin->metric > 1) && ancestor) {
+                                       olsr_route_del(origin);
+                                       origin->gateway = ancestor;
+                                       origin->metric = 1;
+                                       olsr_route_add(origin);
+                               }
                                recv_hello(buffer + parsed + sizeof(struct 
olsrmsg) + sizeof(struct olsr_hmsg_hello),
                                        ntohs(msg->size) - (sizeof(struct 
olsrmsg)) - sizeof(struct olsr_hmsg_hello),
-                                       msg->orig);
+                                       origin);
                                break;
                        case OLSRMSG_MID:
+                               recv_mid(buffer + parsed + sizeof(struct 
olsrmsg), ntohs(msg->size) - (sizeof(struct olsrmsg)), origin);
                                break;
                        case OLSRMSG_TC:
+                               msg_tc = (struct olsr_hmsg_tc *) (buffer + 
parsed);
+                               reconsider_topology(buffer + parsed + 
sizeof(struct olsrmsg), ntohs(msg->size) - (sizeof(struct olsrmsg)), origin);
                                break;
                        default:
                                return;
                }
+               if ((--msg->ttl) > 0) {
+                       /*TODO: Fwd */
+               }
                parsed += ntohs(msg->size);
        }
 }
@@ -396,6 +621,28 @@
        if (!udpsock)
                return NULL;
 
+       for (i = 0; i < settings->n_ifaces; i++) {
+               struct vder_ip4address *a = settings->ifaces[i]->address_list;
+               while(a) {
+                       struct olsr_route_entry *e = malloc(sizeof(struct 
olsr_route_entry));
+                       if (!e) {
+                               perror("initializing interfaces");
+                               return NULL;
+                       }
+                       memset(e, 0, sizeof(struct olsr_route_entry));
+                       e->destination = a->address;
+                       e->link_type = OLSRLINK_SYMMETRIC;
+                       e->time_left = (OLSR_MSG_INTERVAL << 2);
+                       e->gateway = NULL;
+                       e->iface = settings->ifaces[i];
+                       e->metric = 0;
+                       e->lq = 0xFF;
+                       e->nlq = 0xFF;
+                       e->next = Local_interfaces;
+                       Local_interfaces = e;
+                       a = a->next;
+               }
+       }
 
        gettimeofday(&last_out, NULL);
        refresh_routes();
@@ -409,8 +656,12 @@
                if ((len > 0) && (from_port == OLSR_PORT)) {
                        olsr_recv(buffer, len);
                }
-               usleep(500000);
+               usleep(200000);
                gettimeofday(&now, NULL);
+               if (last_out.tv_sec == now.tv_sec)
+                       continue;
+               /* Remove expired entries */
+               olsr_garbage_collector(Local_interfaces);
                refresh_routes();
                last_out = now;
                for (i = 0; i < settings->n_ifaces; i++)

Modified: branches/vde-router/vde-2/src/vde_router/vder_olsr.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_olsr.h        2012-01-23 
12:41:31 UTC (rev 538)
+++ branches/vde-router/vde-2/src/vde_router/vder_olsr.h        2012-01-29 
02:59:45 UTC (rev 539)
@@ -11,6 +11,7 @@
 #define OLSRMSG_TC             0xca
 
 #define OLSRLINK_SYMMETRIC 0x06
+#define OLSRLINK_UNKNOWN 0x08
 #define OLSRLINK_MPR   0x0a
 
 struct __attribute__((packed)) olsr_link
@@ -38,9 +39,6 @@
 struct __attribute__((packed)) olsr_hmsg_tc
 {
        uint16_t ansn;
-       uint32_t addr;
-       uint8_t  lq;
-       uint8_t  nlq;
        uint16_t reserved;
 };
 

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
vde-users mailing list
vde-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vde-users

Reply via email to