OBAMP: reset tree links if I lose the tree link with my tree parent
[olsrd.git] / lib / obamp / src / obamp.c
index c42fd05..e9b23e5 100644 (file)
@@ -305,6 +305,7 @@ activate_tree_link(struct OBAMP_tree_link_ack *ack)
       if (tmp->neighbor_ip_addr.v4.s_addr == ack->router_id.v4.s_addr) {
 
         tmp->isTree = 1;
+        myState->TreeHeartBeat = TREE_HEARTBEAT;
         OLSR_DEBUG(LOG_PLUGINS, "Tree link to %s activated", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
         return;
 
@@ -346,10 +347,16 @@ obamp_hello(struct in_addr *addr)
 static void
 tree_link_req(struct in_addr *addr)
 {
-
+  if (myState->TreeRequestDelay == 0) { 
   struct OBAMP_tree_link_req req;
   struct sockaddr_in si_other;
+  #if !defined(REMOVE_LOG_DEBUG)
+  struct ipaddr_str buf;
+  #endif
 
+  OLSR_DEBUG(LOG_PLUGINS, "Sending tree request to: %s", ip4_to_string(&buf, *addr));
   memset(&req, 0, sizeof(req));
   req.MessageID = OBAMP_TREE_REQ;
   //TODO: refresh IP address
@@ -363,8 +370,11 @@ tree_link_req(struct in_addr *addr)
   si_other.sin_family = AF_INET;
   si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
   si_other.sin_addr = *addr;
+  myState->TreeRequestDelay=5;
   sendto(sdudp, &req, sizeof(struct OBAMP_tree_link_req), 0, (struct sockaddr *)&si_other, sizeof(si_other));
 }
+else OLSR_DEBUG(LOG_PLUGINS,"Do not send Tree Link Request because there is another one running");
+}
 
 static void
 tree_link_ack(struct OBAMP_tree_link_req *req)
@@ -565,6 +575,7 @@ reset_tree_links(void)
   struct ObampNode *tmp;
   struct list_head *pos;
 
+  OLSR_DEBUG(LOG_PLUGINS,"Reset Tree Links Now");
   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
 
     list_for_each(pos, &ListOfObampNodes) {
@@ -577,6 +588,8 @@ reset_tree_links(void)
 
   memset(&myState->ParentId.v4, 0, sizeof(myState->ParentId.v4));
   memset(&myState->OldParentId.v4, 1, sizeof(myState->OldParentId.v4));
+  myState->TreeCreateSequenceNumber=0;
+
 
 };
 
@@ -621,7 +634,8 @@ CoreElection(void)
         myState->CoreAddress = myState->myipaddr;
         myState->iamcore = 1;
         myState->TreeCreateSequenceNumber = 0;
-        reset_tree_links();
+        OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
+       reset_tree_links();
         OLSR_DEBUG(LOG_PLUGINS, "I'm the core");
       }
     } else {
@@ -630,7 +644,8 @@ CoreElection(void)
       } else {                  //core changed
         myState->iamcore = 0;
         myState->CoreAddress.v4.s_addr = smallestIP;
-        reset_tree_links();
+        OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
+       reset_tree_links();
         OLSR_DEBUG(LOG_PLUGINS, "CoreElection: current Core is - %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
       }
     }
@@ -642,6 +657,7 @@ CoreElection(void)
     myState->CoreAddress = myState->myipaddr;
     myState->iamcore = 1;
     myState->TreeCreateSequenceNumber = 0;
+    OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
     reset_tree_links();
 
 
@@ -749,6 +765,43 @@ decap_data(char *buffer)
 
 }
 
+
+
+static int
+CheckDataFromTreeLink(char *buffer)
+{
+
+  struct ObampNode *tmp;               //temp pointers used when parsing the list
+  struct list_head *pos;
+  struct OBAMP_data_message4 *data_msg;
+
+  data_msg = (struct OBAMP_data_message4 *)buffer;
+
+  if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
+
+    //Scroll the list
+    list_for_each(pos, &ListOfObampNodes) {
+      tmp = list_entry(pos, struct ObampNode, list);
+      //Scroll the list until we find the entry relative to the last hop of the packet we are processing
+      if (memcmp(&tmp->neighbor_ip_addr.v4, &data_msg->last_hop, sizeof(struct in_addr)) == 0) {
+
+        if (tmp->isTree == 1) {  //OK we receive data from a neighbor that we have a tree link with
+          return 1;
+        }
+
+       else{
+          OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DATA PACKET SENT BY NOT TREE NEIGHBOR");
+          return 0;
+       }
+      }
+    }
+  }
+
+  return 0;
+
+}
+
+
 static int
 CheckDupData(char *buffer)
 {
@@ -799,15 +852,18 @@ forward_obamp_data(char *buffer)
 
 #if !defined(REMOVE_LOG_DEBUG)
   struct ipaddr_str buf;
+  struct ipaddr_str buf2;
 #endif
   struct ObampNode *tmp;               //temp pointers used when parsing the list
   struct list_head *pos;
   struct OBAMP_data_message4 *data_msg;
-
   struct sockaddr_in si_other;
+  struct in_addr temporary;
 
 
   data_msg = (struct OBAMP_data_message4 *)buffer;
+  temporary.s_addr  = data_msg->last_hop;
+  data_msg->last_hop = myState->myipaddr.v4.s_addr;
 
   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
 
@@ -815,10 +871,9 @@ forward_obamp_data(char *buffer)
     list_for_each(pos, &ListOfObampNodes) {
       tmp = list_entry(pos, struct ObampNode, list);
 
-      if (tmp->isTree == 1 && memcmp(&tmp->neighbor_ip_addr.v4, &data_msg->last_hop, sizeof(struct in_addr)) != 0) {
-
+      if (tmp->isTree == 1 && memcmp(&tmp->neighbor_ip_addr.v4, &temporary.s_addr, 4) != 0) {
+        OLSR_DEBUG(LOG_PLUGINS, "FORWARDING OBAMP DATA TO node %s because come from %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4), ip4_to_string(&buf2,temporary));
         //FORWARD DATA
-        data_msg->last_hop = myState->myipaddr.v4.s_addr;
 
 
         memset((char *)&si_other, 0, sizeof(si_other));
@@ -828,7 +883,6 @@ forward_obamp_data(char *buffer)
         //sendto(sdudp, data_msg, sizeof(struct OBAMP_data_message), 0, (struct sockaddr *)&si_other, sizeof(si_other));
        sendto(sdudp, data_msg, 17+data_msg->datalen, 0, (struct sockaddr *)&si_other, sizeof(si_other));
 
-        OLSR_DEBUG(LOG_PLUGINS, "FORWARDING OBAMP DATA TO node %s ", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
 
       }
     }
@@ -877,7 +931,6 @@ static void
 manage_tree_create(char *packet)
 {
 
-
   struct OBAMP_tree_create *msg;
 
 #if !defined(REMOVE_LOG_DEBUG)
@@ -887,7 +940,7 @@ manage_tree_create(char *packet)
 
   struct ObampNode *tmp;               //temp pointers used when parsing the list
   struct list_head *pos;
-
+  OLSR_DEBUG(LOG_PLUGINS,"manage_tree_create");
   msg = (struct OBAMP_tree_create *)packet;
 
   if (msg->MessageID != OBAMP_TREECREATE) {
@@ -903,32 +956,49 @@ manage_tree_create(char *packet)
     if (myState->iamcore == 1) {        //I'm core and receiving tree create over a loop
       return;
     } else {
-      if (myState->TreeCreateSequenceNumber < msg->SequenceNumber) {    //If tree create is not a duplicate
-        myState->TreeCreateSequenceNumber = msg->SequenceNumber;
-        myState->TreeHeartBeat = TREE_HEARTBEAT;
 
 
-        myState->OldParentId.v4 = myState->ParentId.v4;
-        myState->ParentId.v4 = msg->router_id.v4;
+      if ( (((msg->SequenceNumber > myState->TreeCreateSequenceNumber) && ((msg->SequenceNumber - myState->TreeCreateSequenceNumber ) <= 127)) || ((myState->TreeCreateSequenceNumber > msg->SequenceNumber) && ((myState->TreeCreateSequenceNumber - msg->SequenceNumber) > 127 ))    /*myState->TreeCreateSequenceNumber < msg->SequenceNumber*/) || myState->TreeCreateSequenceNumber == 0 ) {    //If tree create is not a duplicate
+        OLSR_DEBUG(LOG_PLUGINS, "myState->TreeCreateSequenceNumber < msg->SequenceNumber --- %d < %d",myState->TreeCreateSequenceNumber,msg->SequenceNumber);
+       myState->TreeCreateSequenceNumber = msg->SequenceNumber;
 
-        if (memcmp(&myState->OldParentId.v4, &myState->ParentId.v4, sizeof(struct in_addr)) != 0)       //If it changed
+       //A bug was fixed here a battlemeshv3
+        //myState->OldParentId.v4 = myState->ParentId.v4;
+        //myState->ParentId.v4 = msg->router_id.v4;
+
+        //if (memcmp(&myState->OldParentId.v4, &myState->ParentId.v4, sizeof(struct in_addr)) != 0)       //If it changed
+        if (memcmp(&msg->router_id.v4, &myState->ParentId.v4, sizeof(struct in_addr)) != 0)       //If it changed
         {
-          OLSR_DEBUG(LOG_PLUGINS, "Parent changed requesting tree link");
-          reset_tree_links();
+          OLSR_DEBUG(LOG_PLUGINS, "Receiving a tree message from a link that is not parent");
+         if (DoIHaveATreeLink() == 0 ) {
+          OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
+         reset_tree_links();
           myState->ParentId.v4 = msg->router_id.v4;
           myState->OldParentId.v4 = myState->ParentId.v4;
           tree_link_req(&msg->router_id.v4);
+         }
+         else {
+         //I have a tree link already, evaluate new parent ??
+         
+         }
         }
-        if (list_empty(&ListOfObampNodes) == 0) {       //if the list is NOT empty
+       else { //Receiving a TreeCreate from my parent so I can refresh hearthbeat
+        myState->TreeHeartBeat = TREE_HEARTBEAT;
+       }
+        
+       //FORWARD the tree message on the mesh
+       if (list_empty(&ListOfObampNodes) == 0) {       //if the list is NOT empty
 
           //Scroll the list
           list_for_each(pos, &ListOfObampNodes) {
             tmp = list_entry(pos, struct ObampNode, list);
 
             if (tmp->isMesh == 1 && memcmp(&tmp->neighbor_ip_addr.v4, &msg->router_id.v4, sizeof(struct in_addr)) != 0) {       //Is neighbor and not the originator of this tree create
+               if (DoIHaveATreeLink() == 1 ) { //I forward only if I have a link tree to the core ready
               tree_create_forward_to(&tmp->neighbor_ip_addr.v4, msg);
               OLSR_DEBUG(LOG_PLUGINS, "FORWARDING TREE CREATE ORIGINATOR %s TO node %s ", ip4_to_string(&buf2, msg->router_id.v4),
                          ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
+               }
 
             }
           }
@@ -936,6 +1006,8 @@ manage_tree_create(char *packet)
           OLSR_DEBUG(LOG_PLUGINS, "Very strange, list cannot be empty here !");
         }
       } else {
+       
+        OLSR_DEBUG(LOG_PLUGINS, "myState->TreeCreateSequenceNumber < msg->SequenceNumber --- %d < %d",myState->TreeCreateSequenceNumber,msg->SequenceNumber);
         OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DUP TREE CREATE");
       }
     }
@@ -977,7 +1049,7 @@ ObampSignalling(int skfd, void *data __attribute__ ((unused)), unsigned int flag
     case OBAMP_DATA:
       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_DATA from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
 
-      if (CheckDupData(buffer)) {
+      if (CheckDupData(buffer) && CheckDataFromTreeLink(buffer) ) {
         forward_obamp_data(buffer);
         decap_data(buffer);
       }
@@ -1349,6 +1421,11 @@ mesh_create(void *x)
         if (tmp->isMesh == 0 && tmp->isTree == 1) {
 
           tmp->isTree = 0;
+       
+        if (memcmp(&tmp->neighbor_ip_addr.v4, &myState->ParentId.v4, sizeof(struct in_addr)) == 0) {
+               OLSR_DEBUG(LOG_PLUGINS,"RESET TREE LINKS: I lost tree link with my PARENT");
+               reset_tree_links();
+       }       
 
         }
       }
@@ -1382,10 +1459,13 @@ purge_nodes(void *x)
   if (myState->TreeHeartBeat > 0)
     myState->TreeHeartBeat--;
 
-  if (myState->TreeHeartBeat == 0 && myState->iamcore == 0)
-    reset_tree_links();
-
+  if (myState->TreeRequestDelay > 0)
+    myState->TreeRequestDelay--;
 
+  if (myState->TreeHeartBeat == 0 && myState->iamcore == 0){ 
+    OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
+    reset_tree_links();
+    }
 
 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: Timer Expired Purging Nodes");
 
@@ -1619,6 +1699,7 @@ InitOBAMP(void)
   myState = olsr_malloc(sizeof(struct ObampNodeState), "OBAMPNodeState");
   myState->iamcore = 1;
   myState->TreeHeartBeat = 0;
+  myState->TreeRequestDelay = 0;
   memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
   myState->CoreAddress = myState->myipaddr;