Update to new avl/list iteration macros
[olsrd.git] / src / olsr.c
index 3ad2ec5..a7b2f58 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * The olsr.org Optimized Link-State Routing daemon(olsrd)
  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
 #include "defs.h"
 #include "olsr.h"
 #include "link_set.h"
-#include "two_hop_neighbor_table.h"
 #include "tc_set.h"
 #include "duplicate_set.h"
-#include "mpr_selector_set.h"
 #include "mid_set.h"
-#include "mpr.h"
 #include "lq_mpr.h"
 #include "olsr_spf.h"
 #include "scheduler.h"
-#include "apm.h"
-#include "misc.h"
 #include "neighbor_table.h"
-#include "log.h"
 #include "lq_packet.h"
 #include "common/avl.h"
 #include "net_olsr.h"
 #include "lq_plugin.h"
 #include "olsr_logging.h"
+#include "os_system.h"
+#include "os_apm.h"
 
+#include <assert.h>
 #include <stdarg.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -80,9 +78,8 @@ bool changes_force;
  * Process changes functions
  */
 
-struct pcf
-{
-  int (*function)(int, int, int);
+struct pcf {
+  int (*function) (int, int, int);
   struct pcf *next;
 };
 
@@ -113,7 +110,7 @@ get_msg_seqno(void)
 
 
 void
-register_pcf(int (*f)(int, int, int))
+register_pcf(int (*f) (int, int, int))
 {
   struct pcf *new_pcf;
 
@@ -140,26 +137,22 @@ olsr_process_changes(void)
 {
   struct pcf *tmp_pc_list;
 
-  if(changes_neighborhood)
+  if (changes_neighborhood)
     OLSR_DEBUG(LOG_MAIN, "CHANGES IN NEIGHBORHOOD\n");
-  if(changes_topology)
+  if (changes_topology)
     OLSR_DEBUG(LOG_MAIN, "CHANGES IN TOPOLOGY\n");
-  if(changes_hna)
+  if (changes_hna)
     OLSR_DEBUG(LOG_MAIN, "CHANGES IN HNA\n");
 
-  if(!changes_force &&
-     0 >= olsr_cnf->lq_dlimit)
+  if (!changes_force && 0 >= olsr_cnf->lq_dlimit)
     return;
 
-  if(!changes_neighborhood &&
-     !changes_topology &&
-     !changes_hna)
+  if (!changes_neighborhood && !changes_topology && !changes_hna)
     return;
 
-  if (olsr_cnf->log_target_stderr && olsr_cnf->clear_screen && isatty(STDOUT_FILENO))
-  {
-      clear_console();
-      printf("       *** %s (%s on %s) ***\n", olsrd_version, build_date, build_host);
+  if (olsr_cnf->log_target_stderr && olsr_cnf->clear_screen && isatty(STDOUT_FILENO)) {
+    os_clear_console();
+    printf("       *** %s (%s on %s) ***\n", olsrd_version, build_date, build_host);
   }
 
   if (changes_neighborhood) {
@@ -168,25 +161,19 @@ olsr_process_changes(void)
 
   /* calculate the routing table */
   if (changes_neighborhood || changes_topology || changes_hna) {
-    olsr_calculate_routing_table();
+    olsr_calculate_routing_table(false);
   }
 
   olsr_print_link_set();
   olsr_print_neighbor_table();
-  olsr_print_two_hop_neighbor_table();
   olsr_print_tc_table();
   olsr_print_mid_set();
   olsr_print_duplicate_table();
   olsr_print_hna_set();
 
-  for(tmp_pc_list = pcf_list;
-      tmp_pc_list != NULL;
-      tmp_pc_list = tmp_pc_list->next)
-    {
-      tmp_pc_list->function(changes_neighborhood,
-                           changes_topology,
-                           changes_hna);
-    }
+  for (tmp_pc_list = pcf_list; tmp_pc_list != NULL; tmp_pc_list = tmp_pc_list->next) {
+    tmp_pc_list->function(changes_neighborhood, changes_topology, changes_hna);
+  }
 
   changes_neighborhood = false;
   changes_topology = false;
@@ -198,7 +185,8 @@ olsr_process_changes(void)
  * Callback for the periodic route calculation.
  */
 static void
-olsr_trigger_forced_update(void *unused __attribute__((unused))) {
+olsr_trigger_forced_update(void *unused __attribute__ ((unused)))
+{
 
   changes_force = true;
   changes_neighborhood = true;
@@ -217,7 +205,7 @@ void
 olsr_init_tables(void)
 {
   /* Some cookies for stats keeping */
-  static struct olsr_cookie_info *periodic_spf_timer_cookie = NULL;
+  static struct olsr_timer_info *periodic_spf_timer_info = NULL;
 
   changes_topology = false;
   changes_neighborhood = false;
@@ -235,9 +223,6 @@ olsr_init_tables(void)
   /* Initialize routing table */
   olsr_init_routing_table();
 
-  /* Initialize two hop table */
-  olsr_init_two_hop_table();
-
   /* Initialize topology */
   olsr_init_tc();
 
@@ -247,19 +232,36 @@ olsr_init_tables(void)
   /* Initialize HNA set */
   olsr_init_hna_set();
 
-  /* Initialize MPRS */
-  olsr_init_mprs();
-
   /* Start periodic SPF and RIB recalculation */
-  if (olsr_cnf->lq_dinter > 0.0) {
-    periodic_spf_timer_cookie = olsr_alloc_cookie("Periodic SPF",
-                                                  OLSR_COOKIE_TYPE_TIMER);
-    olsr_start_timer((unsigned int)(olsr_cnf->lq_dinter * MSEC_PER_SEC), 5,
-                     OLSR_TIMER_PERIODIC, &olsr_trigger_forced_update, NULL,
-                     periodic_spf_timer_cookie->ci_id);
+  if (olsr_cnf->lq_dinter > 0) {
+    periodic_spf_timer_info = olsr_alloc_timerinfo("Periodic SPF", &olsr_trigger_forced_update, true);
+    olsr_start_timer(olsr_cnf->lq_dinter, 5,
+                     NULL, periodic_spf_timer_info);
   }
 }
 
+/**
+ * Shared code to write the message header
+ */
+uint8_t *olsr_put_msg_hdr(uint8_t **curr, struct olsr_message *msg)
+{
+  uint8_t *sizeptr;
+
+  assert(msg);
+  assert(curr);
+
+  pkt_put_u8(curr, msg->type);
+  pkt_put_reltime(curr, msg->vtime);
+  sizeptr = *curr;
+  pkt_put_u16(curr, msg->size);
+  pkt_put_ipaddress(curr, &msg->originator);
+  pkt_put_u8(curr, msg->ttl);
+  pkt_put_u8(curr, msg->hopcnt);
+  pkt_put_u16(curr, msg->seqno);
+
+  return sizeptr;
+}
+
 /**
  *Check if a message is to be forwarded and forward
  *it if necessary.
@@ -269,191 +271,124 @@ olsr_init_tables(void)
  *@returns positive if forwarded
  */
 int
-olsr_forward_message(union olsr_message *m, struct interface *in_if,
-                    union olsr_ip_addr *from_addr)
+olsr_forward_message(struct olsr_message *msg, uint8_t *binary, struct interface *in_if, union olsr_ip_addr *from_addr)
 {
   union olsr_ip_addr *src;
-  struct neighbor_entry *neighbor;
-  int msgsize;
-  struct interface *ifn;
-
-  /*
-   * Sven-Ola: We should not flood the mesh with overdue messages. Because
-   * of a bug in parser.c:parse_packet, we have a lot of messages because
-   * all older olsrd's have lq_fish enabled.
-   */
-  if (AF_INET == olsr_cnf->ip_version)
-  {
-    if (m->v4.ttl < 2 || 255 < (int)m->v4.hopcnt + (int)m->v4.ttl) return 0;
-  }
-  else
-  {
-    if (m->v6.ttl < 2|| 255 < (int)m->v6.hopcnt + (int)m->v6.ttl) return 0;
-  }
+  struct nbr_entry *neighbor;
+  struct interface *ifn, *iterator;
+  uint8_t *tmp;
+#if !defined REMOVE_LOG_DEBUG
+  struct ipaddr_str buf;
+#endif
 
   /* Lookup sender address */
   src = olsr_lookup_main_addr_by_alias(from_addr);
-  if(!src)
+  if (!src)
     src = from_addr;
 
-  neighbor=olsr_lookup_neighbor_table(src);
-  if(!neighbor)
+  neighbor = olsr_lookup_nbr_entry(src, true);
+  if (!neighbor) {
+    OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d because no nbr entry found for %s\n",
+        msg->type, olsr_ip_to_string(&buf, src));
     return 0;
-
-  if(neighbor->status != SYM)
+  }
+  if (!neighbor->is_sym) {
+    OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d because received by non-symmetric neighbor %s\n",
+        msg->type, olsr_ip_to_string(&buf, src));
     return 0;
+  }
 
   /* Check MPR */
-  if(olsr_lookup_mprs_set(src) == NULL) {
+  if (neighbor->mprs_count == 0) {
+    OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d because we are no MPR for %s\n",
+        msg->type, olsr_ip_to_string(&buf, src));
     /* don't forward packages if not a MPR */
     return 0;
   }
 
   /* check if we already forwarded this message */
-  if (olsr_message_is_duplicate(m)) {
-    return 0; /* it's a duplicate, forget about it */
+  if (olsr_is_duplicate_message(msg, true, NULL)) {
+    OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d from %s because we already forwarded it.\n",
+        msg->type, olsr_ip_to_string(&buf, src));
+    return 0;                   /* it's a duplicate, forget about it */
   }
 
   /* Treat TTL hopcnt */
-  if(olsr_cnf->ip_version == AF_INET)
-    {
-      /* IPv4 */
-      m->v4.hopcnt++;
-      m->v4.ttl--;
-    }
-  else
-    {
-      /* IPv6 */
-      m->v6.hopcnt++;
-      m->v6.ttl--;
-    }
-
-  /* Update packet data */
-  msgsize = ntohs(m->v4.olsr_msgsize);
+  msg->hopcnt++;
+  msg->ttl--;
+  tmp = binary;
+  olsr_put_msg_hdr(&tmp, msg);
+
+  if (msg->ttl == 0) {
+    OLSR_DEBUG(LOG_PACKET_PARSING, "Not forwarding message type %d from %s because TTL is 0.\n",
+        msg->type, olsr_ip_to_string(&buf, src));
+    return 0;                   /* TTL 0, forget about it */
+  }
+  OLSR_DEBUG(LOG_PACKET_PARSING, "Forwarding message type %d from %s.\n",
+      msg->type, olsr_ip_to_string(&buf, src));
 
   /* looping trough interfaces */
-  OLSR_FOR_ALL_INTERFACES(ifn) {
-    if(net_output_pending(ifn)) {
+  OLSR_FOR_ALL_INTERFACES(ifn, iterator) {
+    if (net_output_pending(ifn)) {
       /* dont forward to incoming interface if interface is mode ether */
       if (in_if->mode == IF_MODE_ETHER && ifn == in_if)
         continue;
 
-           /*
-            * Check if message is to big to be piggybacked
-            */
-           if(net_outbuffer_push(ifn, m, msgsize) != msgsize) {
-             /* Send */
-             net_output(ifn);
-             /* Buffer message */
-             set_buffer_timer(ifn);
-
-             if(net_outbuffer_push(ifn, m, msgsize) != msgsize) {
-          OLSR_WARN(LOG_NETWORKING, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
+      /*
+       * Check if message is to big to be piggybacked
+       */
+      if (net_outbuffer_push(ifn, binary, msg->size) != msg->size) {
+        /* Send */
+        net_output(ifn);
+        /* Buffer message */
+        set_buffer_timer(ifn);
+
+        if (net_outbuffer_push(ifn, binary, msg->size) != msg->size) {
+          OLSR_WARN(LOG_NETWORKING, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msg->size);
         }
-           }
+      }
+    } else {
+      /* No forwarding pending */
+      set_buffer_timer(ifn);
+
+      if (net_outbuffer_push(ifn, binary, msg->size) != msg->size) {
+        OLSR_WARN(LOG_NETWORKING, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msg->size);
+      }
     }
-    else {
-           /* No forwarding pending */
-           set_buffer_timer(ifn);
-
-           if(net_outbuffer_push(ifn, m, msgsize) != msgsize) {
-             OLSR_WARN(LOG_NETWORKING, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize);
-           }
-         }
-  } OLSR_FOR_ALL_INTERFACES_END(ifn);
+  }
 
   return 1;
 }
 
-/**
- * Wrapper for the timer callback.
- */
 static void
-olsr_expire_buffer_timer(void *context)
+olsr_update_willingness(void *foo __attribute__ ((unused)))
 {
-  struct interface *ifn;
-
-  ifn = (struct interface *)context;
-
-  /*
-   * Clear the pointer to indicate that this timer has
-   * been expired and needs to be restarted in case there
-   * will be another message queued in the future.
-   */
-  ifn->buffer_hold_timer = NULL;
-
-  /*
-   * Do we have something to emit ?
-   */
-  if (!net_output_pending(ifn)) {
-    return;
-  }
-
-  OLSR_DEBUG(LOG_NETWORKING, "Buffer Holdtimer for %s timed out, sending data.\n", ifn->int_name);
-
-  net_output(ifn);
-}
+  int tmp_will = olsr_cnf->willingness;
 
-/*
- * set_buffer_timer
- *
- * Kick a hold-down timer which defers building of a message.
- * This has the desired effect that olsr messages get bigger.
- */
-void
-set_buffer_timer(struct interface *ifn)
-{
+  /* Re-calculate willingness */
+  olsr_calculate_willingness();
 
-  /*
-   * Bail if there is already a timer running.
-   */
-  if (ifn->buffer_hold_timer) {
-    return;
+  if (tmp_will != olsr_cnf->willingness) {
+    OLSR_INFO(LOG_MAIN, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
   }
-
-  /*
-   * This is the first message since the last time this interface has
-   * been drained. Flush the buffer in second or so.
-   */
-  ifn->buffer_hold_timer =
-    olsr_start_timer(OLSR_BUFFER_HOLD_TIME, OLSR_BUFFER_HOLD_JITTER,
-                     OLSR_TIMER_ONESHOT, &olsr_expire_buffer_timer, ifn,
-                     buffer_hold_timer_cookie->ci_id);
 }
 
 void
 olsr_init_willingness(void)
 {
   /* Some cookies for stats keeping */
-  static struct olsr_cookie_info *willingness_timer_cookie = NULL;
+  static struct olsr_timer_info *willingness_timer_info = NULL;
 
   if (olsr_cnf->willingness_auto) {
     OLSR_INFO(LOG_MAIN, "Initialize automatic willingness...\n");
     /* Run it first and then periodic. */
     olsr_update_willingness(NULL);
 
-    willingness_timer_cookie = olsr_alloc_cookie("Update Willingness",
-                                                 OLSR_COOKIE_TYPE_TIMER);
-    olsr_start_timer((unsigned int)olsr_cnf->will_int * MSEC_PER_SEC, 5,
-                     OLSR_TIMER_PERIODIC, &olsr_update_willingness, NULL,
-                     willingness_timer_cookie->ci_id);
-  }
-}
-
-static void
-olsr_update_willingness(void *foo __attribute__((unused)))
-{
-  int tmp_will = olsr_cnf->willingness;
-
-  /* Re-calculate willingness */
-  olsr_cnf->willingness = olsr_calculate_willingness();
-
-  if(tmp_will != olsr_cnf->willingness) {
-    OLSR_INFO(LOG_MAIN, "Local willingness updated: old %d new %d\n", tmp_will, olsr_cnf->willingness);
+    willingness_timer_info = olsr_alloc_timerinfo("Update Willingness", &olsr_update_willingness, true);
+    olsr_start_timer(olsr_cnf->will_int, 5, NULL, willingness_timer_info);
   }
 }
 
-
 /**
  *Calculate this nodes willingness to act as a MPR
  *based on either a fixed value or the power status
@@ -462,31 +397,40 @@ olsr_update_willingness(void *foo __attribute__((unused)))
  *@return a 8bit value from 0-7 representing the willingness
  */
 
-uint8_t
+void
 olsr_calculate_willingness(void)
 {
   struct olsr_apm_info ainfo;
+  struct millitxt_buf tbuf;
 
   /* If fixed willingness */
-  if(!olsr_cnf->willingness_auto)
-    return olsr_cnf->willingness;
+  if (!olsr_cnf->willingness_auto)
+    return;
 
-  if(apm_read(&ainfo) < 1)
-    return WILL_DEFAULT;
+  if (os_apm_read(&ainfo) < 1) {
+    olsr_cnf->willingness = WILL_DEFAULT;
+    olsr_cnf->willingness_auto = false;
+    OLSR_WARN(LOG_MAIN, "Cannot read APM info, setting willingness to default value (%d)", olsr_cnf->willingness);
+    return;
+  }
 
-  apm_printinfo(&ainfo);
+  os_apm_printinfo(&ainfo);
 
   /* If AC powered */
-  if(ainfo.ac_line_status == OLSR_AC_POWERED)
-    return 6;
-
+  if (ainfo.ac_line_status == OLSR_AC_POWERED) {
+    olsr_cnf->willingness = 6;
+  }
+  else {
   /* If battery powered
    *
    * juice > 78% will: 3
    * 78% > juice > 26% will: 2
    * 26% > juice will: 1
    */
-  return (ainfo.battery_percentage / 26);
+    olsr_cnf->willingness = (ainfo.battery_percentage / 26);
+  }
+  OLSR_INFO(LOG_MAIN, "Willingness set to %d - next update in %s secs\n",
+      olsr_cnf->willingness, olsr_milli_to_txt(&tbuf, olsr_cnf->will_int));
 }
 
 const char *
@@ -494,23 +438,22 @@ olsr_msgtype_to_string(uint8_t msgtype)
 {
   static char type[20];
 
-  switch(msgtype)
-    {
-    case(HELLO_MESSAGE):
-      return "HELLO";
-    case(TC_MESSAGE):
-      return "TC";
-    case(MID_MESSAGE):
-      return "MID";
-    case(HNA_MESSAGE):
-      return "HNA";
-    case(LQ_HELLO_MESSAGE):
-      return("LQ-HELLO");
-    case(LQ_TC_MESSAGE):
-      return("LQ-TC");
-    default:
-      break;
-    }
+  switch (msgtype) {
+  case (HELLO_MESSAGE):
+    return "HELLO";
+  case (TC_MESSAGE):
+    return "TC";
+  case (MID_MESSAGE):
+    return "MID";
+  case (HNA_MESSAGE):
+    return "HNA";
+  case (LQ_HELLO_MESSAGE):
+    return ("LQ-HELLO");
+  case (LQ_TC_MESSAGE):
+    return ("LQ-TC");
+  default:
+    break;
+  }
 
   snprintf(type, sizeof(type), "UNKNOWN(%d)", msgtype);
   return type;
@@ -522,21 +465,18 @@ olsr_link_to_string(uint8_t linktype)
 {
   static char type[20];
 
-  switch(linktype)
-    {
-    case(UNSPEC_LINK):
-      return "UNSPEC";
-    case(ASYM_LINK):
-      return "ASYM";
-    case(SYM_LINK):
-      return "SYM";
-    case(LOST_LINK):
-      return "LOST";
-    case(HIDE_LINK):
-      return "HIDE";
-    default:
-      break;
-    }
+  switch (linktype) {
+  case (UNSPEC_LINK):
+    return "UNSPEC";
+  case (ASYM_LINK):
+    return "ASYM";
+  case (SYM_LINK):
+    return "SYM";
+  case (LOST_LINK):
+    return "LOST";
+  default:
+    break;
+  }
 
   snprintf(type, sizeof(type), "UNKNOWN(%d)", linktype);
   return type;
@@ -548,17 +488,16 @@ olsr_status_to_string(uint8_t status)
 {
   static char type[20];
 
-  switch(status)
-    {
-    case(NOT_NEIGH):
-      return "NOT NEIGH";
-    case(SYM_NEIGH):
-      return "NEIGHBOR";
-    case(MPR_NEIGH):
-      return "MPR";
-    default:
-      break;
-    }
+  switch (status) {
+  case (NOT_NEIGH):
+    return "NOT NEIGH";
+  case (SYM_NEIGH):
+    return "NEIGHBOR";
+  case (MPR_NEIGH):
+    return "MPR";
+  default:
+    break;
+  }
 
   snprintf(type, sizeof(type), "UNKNOWN(%d)", status);
   return type;
@@ -578,7 +517,7 @@ olsr_exit(int val)
   fflush(stdout);
   olsr_cnf->exit_value = val;
   if (app_state == STATE_INIT) {
-    exit(val);
+    os_exit(val);
   }
   app_state = STATE_SHUTDOWN;
 }
@@ -594,7 +533,7 @@ olsr_exit(int val)
  * @return a void pointer to the memory allocated
  */
 void *
-olsr_malloc(size_t size, const char *id __attribute__((unused)))
+olsr_malloc(size_t size, const char *id __attribute__ ((unused)))
 {
   void *ptr;