diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/bmf/Makefile olsrd-f7757d63a5d0/lib/bmf/Makefile
--- olsrd-a5b9cf969979/lib/bmf/Makefile	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/bmf/Makefile	2008-02-29 10:50:43.000000000 +0100
@@ -34,7 +34,7 @@
 
 OLSRD_PLUGIN =	true
 PLUGIN_NAME =	olsrd_bmf
-PLUGIN_VER =	1.5.2
+PLUGIN_VER =	1.5.3
 
 TOPDIR = ../..
 include $(TOPDIR)/Makefile.inc
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/bmf/README_BMF.txt olsrd-f7757d63a5d0/lib/bmf/README_BMF.txt
--- olsrd-a5b9cf969979/lib/bmf/README_BMF.txt	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/bmf/README_BMF.txt	2008-02-29 10:50:43.000000000 +0100
@@ -1,6 +1,6 @@
 BASIC MULTICAST FORWARDING PLUGIN FOR OLSRD
 by Erik Tromp (erik.tromp@nl.thalesgroup.com, erik_tromp@hotmail.com)
-Version 1.5.2
+Version 1.5.3
 
 1. Introduction
 ---------------
@@ -17,14 +17,14 @@
 2. How to build and install
 ---------------------------
 
-Download the olsr-bmf-v1.5.2.tar.gz file and save it into your OLSRD
+Download the olsr-bmf-v1.5.3.tar.gz file and save it into your OLSRD
 base install directory.
 
 Change directory (cd) to your OLSRD base install directory.
 
 At the command prompt, type:
 
-  tar -zxvf ./olsr-bmf-v1.5.2.tar.gz
+  tar -zxvf ./olsr-bmf-v1.5.3.tar.gz
 
 then type:
 
@@ -47,7 +47,7 @@
 To configure BMF in OLSR, you must edit the file /etc/olsrd.conf
 to load the BMF plugin. For example, add the following lines:
 
-  LoadPlugin "olsrd_bmf.so.1.5.2"
+  LoadPlugin "olsrd_bmf.so.1.5.3"
   {
     # No PlParam entries required for basic operation
   }
@@ -63,19 +63,18 @@
 
 Look at the output; it should list the BMF plugin, e.g.:
 
-  ---------- Plugin loader ----------
-  Library: olsrd_bmf.so.1.5.2
-  OLSRD Basic Multicast Forwarding plugin 1.5.2 (Dec  7 2007 09:08:19)
+  ---------- LOADING LIBRARY olsrd_bmf.so.1.5.3 ----------
+  OLSRD Basic Multicast Forwarding (BMF) plugin 1.5.3 (Feb 24 2008 17:58:02)
     (C) Thales Communications Huizen, Netherlands
-    Erik Tromp (erik.tromp@nl.thalesgroup.com)
-  Checking plugin interface version...  4 - OK
-  Trying to fetch plugin init function... OK
-  Trying to fetch param function... OK
+    Erik Tromp (eriktromp@users.sourceforge.net)
+  Checking plugin interface version:  5 - OK
+  Trying to fetch plugin init function: OK
+  Trying to fetch parameter table and it's size...
   Sending parameters...
-  "NonOlsrIf"/"eth0"... OK
+  "NonOlsrIf"/"eth0"... NonOlsrIf: OK
   Running plugin_init function...
-  OLSRD Basic Multicast Forwarding (BMF) plugin: opened 6 sockets
-  ---------- LIBRARY LOADED ----------
+  OLSRD Basic Multicast Forwarding (BMF) plugin: opened 5 sockets
+  ---------- LIBRARY olsrd_bmf.so.1.5.3 LOADED ----------
 
 
 4. How to check if it works
@@ -190,7 +189,7 @@
 The following gives an overview of all plugin parameters that can be
 configured:
 
-  LoadPlugin "olsrd_bmf.so.1.5.2"
+  LoadPlugin "olsrd_bmf.so.1.5.3"
   {
     # Specify the name of the BMF network interface.
     # Defaults to "bmf0".
@@ -344,7 +343,7 @@
 interfaces one by one as "NonOlsrIf" parameters in the BMF plugin section
 of /etc/olsrd.conf. For example:
 
-  LoadPlugin "olsrd_bmf.so.1.5.2"
+  LoadPlugin "olsrd_bmf.so.1.5.3"
   {
     # Non-OLSR interfaces to participate in the multicast flooding
     PlParam     "NonOlsrIf"  "eth2"
@@ -402,7 +401,7 @@
 the BMF network interface, by editing the /etc/olsrd.conf file.
 For example:
 
-  LoadPlugin "olsrd_bmf.so.1.5.2"
+  LoadPlugin "olsrd_bmf.so.1.5.3"
   {
       PlParam "BmfInterfaceIp" "10.10.10.4/24"
   }
@@ -540,6 +539,13 @@
 10. Version history
 -------------------
 
+24 February 2008: Version 1.5.3
+
+* Fixed a bug so that dying or dead end edges are not taken into account.
+  As of OLSRd version 0.5.4 , stale TC entries are not cleaned up, but
+  marked with a flag OLSR_TC_EDGE_DOWN. This flag was not taken into account
+  by BMF.
+
 7 December 2007: Version 1.5.2
 
 * Fixed a bug that would cause BMF to always send encapsulated broadcast
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/bmf/src/Bmf.h olsrd-f7757d63a5d0/lib/bmf/src/Bmf.h
--- olsrd-a5b9cf969979/lib/bmf/src/Bmf.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/bmf/src/Bmf.h	2008-02-29 10:50:43.000000000 +0100
@@ -45,7 +45,7 @@
 /* BMF plugin data */
 #define PLUGIN_NAME "OLSRD Basic Multicast Forwarding (BMF) plugin"
 #define PLUGIN_NAME_SHORT "OLSRD BMF"
-#define PLUGIN_VERSION "1.5.2 (" __DATE__ " " __TIME__ ")"
+#define PLUGIN_VERSION "1.5.3 (" __DATE__ " " __TIME__ ")"
 #define PLUGIN_COPYRIGHT "  (C) Thales Communications Huizen, Netherlands"
 #define PLUGIN_AUTHOR "  Erik Tromp (eriktromp@users.sourceforge.net)"
 #define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION "\n" PLUGIN_COPYRIGHT "\n" PLUGIN_AUTHOR
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/bmf/src/NetworkInterfaces.c olsrd-f7757d63a5d0/lib/bmf/src/NetworkInterfaces.c
--- olsrd-a5b9cf969979/lib/bmf/src/NetworkInterfaces.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/bmf/src/NetworkInterfaces.c	2008-02-29 10:50:43.000000000 +0100
@@ -62,7 +62,7 @@
 #include "defs.h" /* olsr_cnf */
 #include "link_set.h" /* get_link_set() */
 #include "lq_route.h" /* MIN_LINK_QUALITY */
-#include "tc_set.h" /* olsr_lookup_tc_entry(), olsr_tc_lookup_dst() */
+#include "tc_set.h" /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */
 #include "net_olsr.h" /* ipequal */
 
 /* Plugin includes */
@@ -402,10 +402,17 @@
  * ------------------------------------------------------------------------- */
 static float CalcEtx(float loss, float neigh_loss) 
 {
+#ifdef USE_FPM
+  if (loss < fpmtof(MIN_LINK_QUALITY) || neigh_loss < fpmtof(MIN_LINK_QUALITY))
+  {
+    return fpmtof(INFINITE_ETX);
+  }
+#else
   if (loss < MIN_LINK_QUALITY || neigh_loss < MIN_LINK_QUALITY)
   {
     return INFINITE_ETX;
   }
+#endif
   else
   {
     return 1.0 / (loss * neigh_loss);
@@ -568,6 +575,9 @@
     /* TODO: get_link_set() is not thread-safe! */
     for (walker = get_link_set(); walker != NULL; walker = walker->next) 
     {
+#ifndef NODEBUG
+      struct ipaddr_str buf;
+#endif
       union olsr_ip_addr* neighborMainIp;
       struct link_entry* bestLinkToNeighbor;
       struct tc_entry* tcLastHop;
@@ -583,7 +593,7 @@
         "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
         PLUGIN_NAME_SHORT,
         intf->ifName,
-        olsr_ip_to_string(&walker->neighbor_iface_addr));
+        olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
       neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
 
@@ -595,7 +605,7 @@
           9,
           "%s: ----> Not forwarding to %s: is source of pkt\n",
           PLUGIN_NAME_SHORT,
-          olsr_ip_to_string(&walker->neighbor_iface_addr));
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
         continue; /* for */
       }
@@ -607,7 +617,7 @@
           9,
           "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
           PLUGIN_NAME_SHORT,
-          olsr_ip_to_string(&walker->neighbor_iface_addr));
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
         continue; /* for */
       }
@@ -619,7 +629,7 @@
           9,
           "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
           PLUGIN_NAME_SHORT,
-          olsr_ip_to_string(&walker->neighbor_iface_addr));
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
         continue; /* for */
       }
@@ -632,7 +642,7 @@
           9,
           "%s: ----> Not forwarding to %s: link is timing out\n",
           PLUGIN_NAME_SHORT,
-          olsr_ip_to_string(&walker->neighbor_iface_addr));
+          olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
 
         continue; /* for */
       }
@@ -642,7 +652,7 @@
         9,
         "%s: ----> Forwarding pkt to %s will cost %5.2f\n",
         PLUGIN_NAME_SHORT,
-        olsr_ip_to_string(&walker->neighbor_iface_addr),
+        olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
         walker->link_cost);
 
       /* If the candidate neighbor is best reached via another interface, then skip 
@@ -659,7 +669,7 @@
             9,
             "%s: ----> Not forwarding to %s: no link found\n",
             PLUGIN_NAME_SHORT,
-            olsr_ip_to_string(&walker->neighbor_iface_addr));
+            olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
         }
         else
         {
@@ -669,7 +679,7 @@
             9,
             "%s: ----> Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %5.2f\n",
             PLUGIN_NAME_SHORT,
-            olsr_ip_to_string(&walker->neighbor_iface_addr),
+            olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
             bestIntf->int_name,
             bestLinkToNeighbor->link_cost);
         }
@@ -679,12 +689,15 @@
 
       if (forwardedBy != NULL)
       {
+#ifndef NODEBUG
+        struct ipaddr_str forwardedByBuf, niaBuf;
+#endif
         OLSR_PRINTF(
           9,
           "%s: ----> 2-hop path from %s via me to %s will cost %5.2f\n",
           PLUGIN_NAME_SHORT,
-          olsr_ip_to_string(forwardedBy),
-          olsr_ip_to_string(&walker->neighbor_iface_addr),
+          olsr_ip_to_string(&forwardedByBuf, forwardedBy),
+          olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
           previousLinkCost + walker->link_cost);
       }
 
@@ -698,24 +711,31 @@
         tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
         if (tcLastHop != NULL)
         {
-          struct topo_dst* tcDest;
-
-          /* TODO: olsr_tc_lookup_dst() is not thread-safe. */
-          tcDest = olsr_tc_lookup_dst(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
+          struct tc_edge_entry* tc_edge;
 
-          /* Rely on short-circuit boolean evaluation */
-          if (tcDest != NULL && previousLinkCost + walker->link_cost > tcDest->link_cost)
+          /* TODO: olsr_lookup_tc_edge() is not thread-safe. */
+          tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
+          
+          /* We are not interested in dead-end or dying edges. */
+          if (tc_edge != NULL && (tc_edge->flags & OLSR_TC_EDGE_DOWN) == 0)
           {
-            OLSR_PRINTF(
-              9,
-              "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
-              PLUGIN_NAME_SHORT,
-              olsr_ip_to_string(&walker->neighbor_iface_addr),
-              olsr_ip_to_string(forwardedBy),
-              olsr_ip_to_string(&walker->neighbor_iface_addr),
-              tcDest->link_cost);
+            if (previousLinkCost + walker->link_cost > tc_edge->link_cost)
+            {
+#ifndef NODEBUG
+              struct ipaddr_str neighbor_iface_buf, forw_buf;
+              olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
+#endif
+              OLSR_PRINTF(
+                9,
+                "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
+                PLUGIN_NAME_SHORT,
+                neighbor_iface_buf.buf,
+                olsr_ip_to_string(&forw_buf, forwardedBy),
+                neighbor_iface_buf.buf,
+                tc_edge->link_cost);
 
-            continue; /* for */
+              continue; /* for */
+            } /* if */
           } /* if */
         } /* if */
       } /* if */
@@ -742,8 +762,13 @@
 #else /* USING_THALES_LINK_COST_ROUTING */
         
     struct link_entry* walker;
+#ifdef USE_FPM
+    float previousLinkEtx = 2 * fpmtof(INFINITE_ETX);
+    float bestEtx = 2 * fpmtof(INFINITE_ETX);
+#else
     float previousLinkEtx = 2 * INFINITE_ETX;
     float bestEtx = 2 * INFINITE_ETX;
+#endif
 
     if (forwardedBy != NULL)
     {
@@ -753,8 +778,13 @@
       {
         previousLinkEtx =
           CalcEtx(
+#ifdef USE_FPM
+            fpmtof(bestLinkFromForwarder->loss_link_quality),
+            fpmtof(bestLinkFromForwarder->neigh_link_quality));
+#else
             bestLinkFromForwarder->loss_link_quality,
             bestLinkFromForwarder->neigh_link_quality);
+#endif
       }
     }
 
@@ -825,10 +855,19 @@
 
       /* Calculate the link quality (ETX) of the link to the found neighbor */
       currEtx = CalcEtx(
+#ifdef USE_FPM
+        fpmtof(walker->loss_link_quality),
+        fpmtof(walker->neigh_link_quality));
+#else
         walker->loss_link_quality,
         walker->neigh_link_quality);
+#endif
  
+#ifdef USE_FPM
+      if (currEtx >= fpmtof(INFINITE_ETX))
+#else
       if (currEtx >= INFINITE_ETX)
+#endif
       {
         OLSR_PRINTF(
           9,
@@ -879,10 +918,15 @@
             olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
             bestIntf->int_name,
             CalcEtx(
+#ifdef USE_FPM
+              fpmtof(bestLinkToNeighbor->loss_link_quality),
+              fpmtof(bestLinkToNeighbor->neigh_link_quality)));
+#else
               bestLinkToNeighbor->loss_link_quality,
               bestLinkToNeighbor->neigh_link_quality));
+#endif
         }
-        
+
         continue; /* for */
       }
 
@@ -915,11 +959,17 @@
           /* TODO: olsr_lookup_tc_edge() is not thread-safe. */
           tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
 
-          if (tc_edge != NULL)
+          /* We are not interested in dead-end or dying edges. */
+          if (tc_edge != NULL && (tc_edge->flags & OLSR_TC_EDGE_DOWN) == 0)
           {
             float tcEtx = CalcEtx(
+#ifdef USE_FPM
+              fpmtof(tc_edge->link_quality),
+              fpmtof(tc_edge->inverse_link_quality));
+#else
               tc_edge->link_quality,
               tc_edge->inverse_link_quality);
+#endif
 
             if (previousLinkEtx + currEtx > tcEtx)
             {
@@ -1494,9 +1544,9 @@
       BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
 
       newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
-	  }
-	  else
-	  {
+    }
+    else
+    {
       /* Downcast to correct sockaddr subtype */
       newIf->intAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
     }
@@ -1510,9 +1560,9 @@
       BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
 
       newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
-	  }
-	  else
-	  {
+    }
+    else
+    {
       /* Downcast to correct sockaddr subtype */
       newIf->broadAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr;
     }
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/dot_draw/src/olsrd_dot_draw.c olsrd-f7757d63a5d0/lib/dot_draw/src/olsrd_dot_draw.c
--- olsrd-a5b9cf969979/lib/dot_draw/src/olsrd_dot_draw.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/dot_draw/src/olsrd_dot_draw.c	2008-02-29 10:50:43.000000000 +0100
@@ -154,7 +154,11 @@
 ipc_print_neigh_link(const struct neighbor_entry *neighbor)
 {
   struct ipaddr_str mainaddrstrbuf, strbuf;
+#ifdef USE_FPM
+  fpm etx = itofpm(0);
+#else
   double etx = 0.0;
+#endif
   const char *style;
   const char *adr = olsr_ip_to_string(&mainaddrstrbuf, &olsr_cnf->main_addr);
   struct link_entry* link;
@@ -169,10 +173,10 @@
     style = "solid";
   }
     
-  ipc_send_fmt("\"%s\" -> \"%s\"[label=\"%.2f\", style=%s];\n",
+  ipc_send_fmt("\"%s\" -> \"%s\"[label=\"%s\", style=%s];\n",
                adr,
                olsr_ip_to_string(&strbuf, &neighbor->neighbor_main_addr),
-               etx,
+               etxtoa(etx),
                style);
   
   if (neighbor->is_mpr) {
@@ -263,6 +267,7 @@
     return;
   }
   olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n", inet_ntoa(pin.sin_addr));
+  close(ipc_connection); /* close connection after one output */
   pcf_event(1, 1, 1);
 }
 
@@ -339,10 +344,10 @@
 {
   struct ipaddr_str strbuf1, strbuf2;
 
-  ipc_send_fmt("\"%s\" -> \"%s\"[label=\"%.2f\"];\n",
+  ipc_send_fmt("\"%s\" -> \"%s\"[label=\"%s\"];\n",
                olsr_ip_to_string(&strbuf1, &entry->addr),
                olsr_ip_to_string(&strbuf2, &dst_entry->T_dest_addr),
-               olsr_calc_tc_etx(dst_entry));
+               etxtoa(olsr_calc_tc_etx(dst_entry)));
 }
 
 
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/httpinfo/src/olsrd_httpinfo.c olsrd-f7757d63a5d0/lib/httpinfo/src/olsrd_httpinfo.c
--- olsrd-a5b9cf969979/lib/httpinfo/src/olsrd_httpinfo.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/httpinfo/src/olsrd_httpinfo.c	2008-02-29 10:50:43.000000000 +0100
@@ -763,8 +763,8 @@
                    "<td align=\"center\">%d</td>",
                    rt->rt_best->rtp_metric.hops);
   size += snprintf(&buf[size], bufsize-size,
-                   "<td align=\"right\">%.3f</td>",
-                   rt->rt_best->rtp_metric.etx);
+                   "<td align=\"right\">%s</td>",
+                   etxtoa(rt->rt_best->rtp_metric.etx));
   size += snprintf(&buf[size], bufsize-size,
                    "<td align=\"center\">%s</td></tr>\n",
                    if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
@@ -984,19 +984,19 @@
     size += snprintf(&buf[size], bufsize-size, "<tr>");
     size += build_ipaddr_with_link(&buf[size], bufsize, &link->local_iface_addr, -1);
     size += build_ipaddr_with_link(&buf[size], bufsize, &link->neighbor_iface_addr, -1);
-    size += snprintf(&buf[size], bufsize-size, "<td align=\"right\">%0.2f</td>", link->L_link_quality);
+    size += snprintf(&buf[size], bufsize-size, "<td align=\"right\">%s</td>", fpmtoa(link->L_link_quality));
     if (olsr_cnf->lq_level > 0) {
       size += snprintf(&buf[size], bufsize-size,
-                       "<td align=\"right\">%0.2f</td>"
+                       "<td align=\"right\">%s</td>"
                        "<td>%d</td>"
                        "<td>%d</td>"
-                       "<td align=\"right\">%0.2f</td>"
-                       "<td align=\"right\">%0.2f</td>\n",
-                       link->loss_link_quality,
+                       "<td align=\"right\">%s</td>"
+                       "<td align=\"right\">%s</td>\n",
+                       fpmtoa(link->loss_link_quality),
                        link->lost_packets,
                        link->total_packets,
-                       link->neigh_link_quality,
-                       olsr_calc_link_etx(link));
+                       fpmtoa(link->neigh_link_quality),
+                       etxtoa(olsr_calc_link_etx(link)));
     }
     size += snprintf(&buf[size], bufsize-size, "</tr>\n");
   }
@@ -1059,12 +1059,12 @@
           size += build_ipaddr_with_link(&buf[size], bufsize, &tc->addr, -1);
           if (olsr_cnf->lq_level > 0) {
               size += snprintf(&buf[size], bufsize-size,
-                               "<td align=\"right\">%0.2f</td>"
-                               "<td align=\"right\">%0.2f</td>"
-                               "<td align=\"right\">%0.2f</td>\n",
-                               tc_edge->link_quality,
-                               tc_edge->inverse_link_quality,
-                               olsr_calc_tc_etx(tc_edge));
+                               "<td align=\"right\">%s</td>"
+                               "<td align=\"right\">%s</td>"
+                               "<td align=\"right\">%s</td>\n",
+                               fpmtoa(tc_edge->link_quality),
+                               fpmtoa(tc_edge->inverse_link_quality),
+                               etxtoa(olsr_calc_tc_etx(tc_edge)));
           }
           size += snprintf(&buf[size], bufsize-size, "</tr>\n");
 
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/nameservice/src/mapwrite.c olsrd-f7757d63a5d0/lib/nameservice/src/mapwrite.c
--- olsrd-a5b9cf969979/lib/nameservice/src/mapwrite.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/nameservice/src/mapwrite.c	2008-02-29 10:50:43.000000000 +0100
@@ -167,13 +167,12 @@
       /*
        * To speed up processing, Links with both positions are named PLink()
        */
-      if (0 > fprintf(fmap, "PLink('%s','%s',%f,%f,%f,%s,%s);\n", 
+      if (0 > fprintf(fmap, "PLink('%s','%s',%s,%s,%s,%s,%s);\n", 
             olsr_ip_to_string(&strbuf1, &tc_edge->T_dest_addr),
             olsr_ip_to_string(&strbuf2, &tc->addr), 
-            tc_edge->link_quality,
-            tc_edge->inverse_link_quality,
-            (tc_edge->link_quality * tc_edge->inverse_link_quality) ?
-              1.0 / (tc_edge->link_quality * tc_edge->inverse_link_quality) : 0.0,
+            fpmtoa(tc_edge->link_quality),
+            fpmtoa(tc_edge->inverse_link_quality),
+            etxtoa(olsr_calc_tc_etx(tc_edge)),
             lla, llb))
       {
         return;
@@ -184,13 +183,12 @@
       /*
        * If one link end pos is unkown, only send Link()
        */
-      if (0 > fprintf(fmap, "Link('%s','%s',%f,%f,%f);\n", 
+      if (0 > fprintf(fmap, "Link('%s','%s',%s,%s,%s);\n", 
             olsr_ip_to_string(&strbuf1, &tc_edge->T_dest_addr),
             olsr_ip_to_string(&strbuf2, &tc->addr), 
-            tc_edge->link_quality,
-            tc_edge->inverse_link_quality,
-            (tc_edge->link_quality * tc_edge->inverse_link_quality) ?
-              1.0 / (tc_edge->link_quality * tc_edge->inverse_link_quality) : 0.0))
+            fpmtoa(tc_edge->link_quality),
+            fpmtoa(tc_edge->inverse_link_quality),
+            etxtoa(olsr_calc_tc_etx(tc_edge))))
       {
         return;
       }
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/nameservice/src/nameservice.c olsrd-f7757d63a5d0/lib/nameservice/src/nameservice.c
--- olsrd-a5b9cf969979/lib/nameservice/src/nameservice.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/nameservice/src/nameservice.c	2008-02-29 10:50:43.000000000 +0100
@@ -1196,9 +1196,9 @@
 			/*
 			 * first is better, swap the pointers.
 			 */
-			OLSR_PRINTF(6, "NAME PLUGIN: nameserver %s, etx %.3f\n",
+			OLSR_PRINTF(6, "NAME PLUGIN: nameserver %s, etx %s\n",
 						olsr_ip_to_string(&strbuf, &rt1->rt_dst.prefix),
-						rt1->rt_best->rtp_metric.etx);
+						etxtoa(rt1->rt_best->rtp_metric.etx));
 
 			rt[nameserver_idx] = rt2;
 			rt[nameserver_idx+1] = rt1;
@@ -1248,9 +1248,9 @@
 
 				/* enqueue it on the head of list */
 				*nameserver_routes = route;
-				OLSR_PRINTF(6, "NAME PLUGIN: found nameserver %s, etx %.3f",
+				OLSR_PRINTF(6, "NAME PLUGIN: found nameserver %s, etx %s",
 							olsr_ip_to_string(&strbuf, &name->ip),
-							route->rt_best->rtp_metric.etx);
+							etxtoa(route->rt_best->rtp_metric.etx));
 
 				/* find the closet one */
 				select_best_nameserver(nameserver_routes);
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/secure/README_SECURE olsrd-f7757d63a5d0/lib/secure/README_SECURE
--- olsrd-a5b9cf969979/lib/secure/README_SECURE	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/secure/README_SECURE	2008-02-29 10:50:43.000000000 +0100
@@ -39,7 +39,7 @@
   To make olsrd load the secure OLSR plugin add the
   following in the olsrd configuration file:
 
-LoadPlugin "olsrd_secure.so.0.4"
+LoadPlugin "olsrd_secure.so.0.5"
 {
     PlParam     "Keyfile"   "FILENAME"
 }
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/secure/src/olsrd_secure.c olsrd-f7757d63a5d0/lib/secure/src/olsrd_secure.c
--- olsrd-a5b9cf969979/lib/secure/src/olsrd_secure.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/secure/src/olsrd_secure.c	2008-02-29 10:50:43.000000000 +0100
@@ -132,29 +132,26 @@
 
 char keyfile[FILENAME_MAX+1];
 char aes_key[16];
-/* Input interface */
-static struct interface *olsr_in_if;
 
 /* Event function to register with the sceduler */
 #if 0
 static void olsr_event(void);
 #endif
-static int send_challenge(const union olsr_ip_addr *);
-static int ifchange(struct interface *, int);
-static int send_cres(union olsr_ip_addr *, union olsr_ip_addr *, olsr_u32_t, struct stamp *);
-static int send_rres(union olsr_ip_addr *, union olsr_ip_addr *, olsr_u32_t);
-static int parse_challenge(char *);
-static int parse_cres(char *);
+static int send_challenge(struct interface *olsr_if, const union olsr_ip_addr *);
+static int send_cres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, olsr_u32_t, struct stamp *);
+static int send_rres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, olsr_u32_t);
+static int parse_challenge(struct interface *olsr_if, char *);
+static int parse_cres(struct interface *olsr_if, char *);
 static int parse_rres(char *);
-static int check_auth(char *, int *);
+static int check_auth(struct interface *olsr_if, char *, int *);
 #if 0
 static int ipc_send(char *, int);
 #endif
 static int add_signature(olsr_u8_t *, int*);
-static int validate_packet(const char *, int*);
-static void packet_parser(int);
+static int validate_packet(struct interface *olsr_if, const char *, int*);
+static char *secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length);
 static void timeout_timestamps(void*);
-static int check_timestamp(const union olsr_ip_addr *, time_t);
+static int check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *, time_t);
 static struct stamp *lookup_timestamp_entry(const union olsr_ip_addr *);
 static int read_key_from_file(const char *);
 
@@ -168,7 +165,6 @@
 int
 secure_plugin_init(void)
 {
-  struct interface *ints;
   int i;
 
 
@@ -199,24 +195,8 @@
   /* Register the packet transform function */
   add_ptf(&add_signature);
 
-  /* register ifchange function */
-  add_ifchgf(&ifchange);
-
-  /* Hijack OLSR socket parser functions */
-  ints = ifnet;
-  while(ints)
-    {
-      olsr_printf(1, "[ENC]Hijacking %s socket %d\n", ints->int_name, ints->olsr_socket);
-      fflush(stdout);
-      remove_olsr_socket(ints->olsr_socket, olsr_input);
-      add_olsr_socket(ints->olsr_socket, &packet_parser);
-     
-      /* Reducing maxmessagesize */
-      net_reserve_bufspace(ints, sizeof(struct s_olsrmsg));
-
-      ints = ints->int_next;
-    }
-
+  olsr_preprocessor_add_function(&secure_preprocessor);
+  
   /* Register timeout - poll every 2 seconds */
   olsr_register_scheduler_event(&timeout_timestamps, NULL, 2, 0 , NULL);
 
@@ -235,6 +215,7 @@
 void
 secure_plugin_exit(void)
 {
+  olsr_preprocessor_remove_function(&secure_preprocessor);
 }
 
 
@@ -257,148 +238,32 @@
 }
 #endif
 
-/* XXX - ToDo */
-static int
-ifchange(struct interface *ifn, int action)
+static char *
+secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length)
 {
-
-  switch(action)
-    {
-    case(IFCHG_IF_ADD):
-      printf("SEC: interface %s added\n\n", ifn->int_name);
-      olsr_printf(1, "[ENC]Hijacking %s socket %d\n", ifn->int_name, ifn->olsr_socket);
-      remove_olsr_socket(ifn->olsr_socket, olsr_input);
-      add_olsr_socket(ifn->olsr_socket, &packet_parser);
-      /* Reducing maxmessagesize */
-      net_reserve_bufspace(ifn, sizeof(struct s_olsrmsg));
-      break;
-
-    case(IFCHG_IF_REMOVE):
-      printf("SEC: interface %s removed\n\n", ifn->int_name);
-      olsr_printf(1, "[ENC]Removing %s socket %d\n", ifn->int_name, ifn->olsr_socket);
-      remove_olsr_socket(ifn->olsr_socket, &packet_parser);
-      break;
-
-    case(IFCHG_IF_UPDATE):
-      printf("SEC: interface %s updated\n\n", ifn->int_name);
-      break;
-      
-    default:
-      break;
-    }
-  return 0;
+  struct olsr *olsr = (struct olsr *)packet;
+  struct ipaddr_str buf;
   
-}
+  /*
+   * Check for challenge/response messages
+   */
+  check_auth(olsr_if, packet, length);
+
+  /*
+   * Check signature
+   */
 
-
-static void
-packet_parser(int fd)
-{
-  /* sockaddr_in6 is bigger than sockaddr !!!! */
-  struct sockaddr_storage from;
-  socklen_t fromlen;
-  int cc;
-  union olsr_ip_addr from_addr;
-  union
+  if(!validate_packet(olsr_if, packet, length))
   {
-    char	buf[MAXMESSAGESIZE+1];
-    struct	olsr olsr;
-  } inbuf;
-
-
-  for (;;) 
-    {
-      struct ipaddr_str buf;
-      fromlen = sizeof(struct sockaddr_storage);
-
-      cc = recvfrom(fd, (void *)&inbuf, sizeof (inbuf), 0, (struct sockaddr *)&from, &fromlen);
-
-      if (cc <= 0) 
-	{
-	  if (cc < 0 && errno != EWOULDBLOCK)
-	    {
-	      olsr_printf(1, "[ENC]error recvfrom: %s", strerror(errno));
-	    }
-	  break;
-	}
-
-      if(olsr_cnf->ip_version == AF_INET)
-	{
-	  /* IPv4 sender address */
-	  memcpy(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr, olsr_cnf->ipsize);
-	}
-      else
-	{
-	  /* IPv6 sender address */
-	  memcpy(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr, olsr_cnf->ipsize);
-	}
-
-      /*
-      olsr_printf(1, "[ENC]message from %s size %d\n",
-		  olsr_ip_to_string(&from_addr),
-		  cc);
-      */
-
-      /* are we talking to ourselves? */
-      if(if_ifwithaddr(&from_addr) != NULL)
-      	return;
-
-
-      /*
-       *setting global from addr
-       */
-      //printf("Recieved data on socket %d\n", socknr);
-
-
-      if((olsr_in_if = if_ifwithsock(fd)) == NULL)
-	{
-          struct ipaddr_str buf;
-	  olsr_printf(1, "[ENC]Could not find input interface for message from %s size %d\n",
-		      olsr_ip_to_string(&buf, &from_addr),
-		      cc);
-	  return ;
-	}
-
-      /*
-       * Check for challenge/response messages
-       */
-      check_auth(inbuf.buf, &cc);
-
-      /*
-       * Check signature
-       */
-
-      if(!validate_packet(inbuf.buf, &cc))
-	{
-	  olsr_printf(1, "[ENC]Rejecting packet from %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr));
-	  return;
-	}
-
-
-      olsr_printf(1, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr), cc);
-
-
-      /* Fix OLSR packet header */
-      inbuf.olsr.olsr_packlen = htons(cc);
+    olsr_printf(1, "[ENC]Rejecting packet from %s\n", olsr_ip_to_string(&buf, from_addr));
+    return NULL;
+  }
 
-      
-      //olsr_printf(1, "Recieved a packet from %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr));
+  olsr_printf(1, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string(&buf, from_addr), *length);
 
-      //printf("\nCC: %d FROMLEN: %d\n\n", cc, fromlen);
-      if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
-	break;
-      else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
-	break;
-
-
-      /*
-       * &from - sender
-       * &inbuf.olsr 
-       * cc - bytes read
-       */
-      parse_packet(&inbuf.olsr, cc, olsr_in_if, &from_addr);
-    
-    }
+  /* Fix OLSR packet header */
+  olsr->olsr_packlen = htons(*length);
+  return packet;
 }
 
 
@@ -411,7 +276,7 @@
  *
  */
 static int
-check_auth(char *pck, int *size __attribute__((unused)))
+check_auth(struct interface *olsr_if, char *pck, int *size __attribute__((unused)))
 {
 
   olsr_printf(3, "[ENC]Checking packet for challenge response message...\n");
@@ -419,11 +284,11 @@
   switch(pck[4])
     {
     case(TYPE_CHALLENGE):
-      parse_challenge(&pck[4]);
+      parse_challenge(olsr_if, &pck[4]);
       break;
 
     case(TYPE_CRESPONSE):
-      parse_cres(&pck[4]);
+      parse_cres(olsr_if, &pck[4]);
       break;
 
     case(TYPE_RRESPONSE):
@@ -523,7 +388,7 @@
 
 
 static int
-validate_packet(const char *pck, int *size)
+validate_packet(struct interface *olsr_if, const char *pck, int *size)
 {
   int packetsize;
   olsr_u8_t sha1_hash[SIGNATURE_SIZE];
@@ -639,7 +504,7 @@
   /* Check timestamp */
   rec_time = ntohl(sig->sig.timestamp);
 
-  if(!check_timestamp((const union olsr_ip_addr *)&sig->originator, rec_time))
+  if(!check_timestamp(olsr_if, (const union olsr_ip_addr *)&sig->originator, rec_time))
     {
       struct ipaddr_str buf;
       olsr_printf(1, "[ENC]Timestamp missmatch in packet from %s!\n",
@@ -656,7 +521,7 @@
 
 
 int
-check_timestamp(const union olsr_ip_addr *originator, time_t tstamp)
+check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *originator, time_t tstamp)
 {
   struct stamp *entry;
   int diff;
@@ -667,7 +532,7 @@
     {
       /* Initiate timestamp negotiation */
 
-      send_challenge(originator);
+      send_challenge(olsr_if, originator);
 
       return 0;
     }
@@ -711,7 +576,7 @@
  */
 
 int
-send_challenge(const union olsr_ip_addr *new_host)
+send_challenge(struct interface *olsr_if, const union olsr_ip_addr *new_host)
 {
   struct challengemsg cmsg;
   struct stamp *entry;
@@ -759,10 +624,10 @@
 	      challenge);
 
   /* Add to buffer */
-  net_outbuffer_push(olsr_in_if, &cmsg, sizeof(struct challengemsg));
+  net_outbuffer_push(olsr_if, &cmsg, sizeof(struct challengemsg));
 
   /* Send the request */
-  net_output(olsr_in_if);
+  net_output(olsr_if);
 
   /* Create new entry */
   entry = malloc(sizeof(struct stamp));
@@ -790,7 +655,7 @@
 }
 
 int
-parse_cres(char *in_msg)
+parse_cres(struct interface *olsr_if, char *in_msg)
 {
   struct c_respmsg *msg;
   olsr_u8_t sha1_hash[SIGNATURE_SIZE];
@@ -886,7 +751,7 @@
 	      entry->diff);
 
   /* Send response-response */
-  send_rres((union olsr_ip_addr *)&msg->originator, 
+  send_rres(olsr_if, (union olsr_ip_addr *)&msg->originator, 
 	    (union olsr_ip_addr *)&msg->destination, 
 	    ntohl(msg->challenge));
 
@@ -993,7 +858,7 @@
 
 
 int
-parse_challenge(char *in_msg)
+parse_challenge(struct interface *olsr_if, char *in_msg)
 {
   struct challengemsg *msg;
   olsr_u8_t sha1_hash[SIGNATURE_SIZE];
@@ -1075,7 +940,7 @@
 
   /* Build and send response */
 
-  send_cres((union olsr_ip_addr *)&msg->originator, 
+  send_cres(olsr_if, (union olsr_ip_addr *)&msg->originator, 
 	    (union olsr_ip_addr *)&msg->destination, 
 	    ntohl(msg->challenge),
 	    entry);
@@ -1093,7 +958,7 @@
  *
  */
 int
-send_cres(union olsr_ip_addr *to, union olsr_ip_addr *from, olsr_u32_t chal_in, struct stamp *entry)
+send_cres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, olsr_u32_t chal_in, struct stamp *entry)
 {
   struct c_respmsg crmsg;
   olsr_u32_t challenge;
@@ -1162,9 +1027,9 @@
 	      challenge);
 
   /* Add to buffer */
-  net_outbuffer_push(olsr_in_if, &crmsg, sizeof(struct c_respmsg));
+  net_outbuffer_push(olsr_if, &crmsg, sizeof(struct c_respmsg));
   /* Send the request */
-  net_output(olsr_in_if);
+  net_output(olsr_if);
 
   return 1;
 }
@@ -1180,7 +1045,7 @@
  *
  */
 static int
-send_rres(union olsr_ip_addr *to, union olsr_ip_addr *from, olsr_u32_t chal_in)
+send_rres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, olsr_u32_t chal_in)
 {
   struct r_respmsg rrmsg;
   struct ipaddr_str buf;
@@ -1240,10 +1105,10 @@
 	      olsr_ip_to_string(&buf, to));
 
   /* add to buffer */
-  net_outbuffer_push(olsr_in_if, &rrmsg, sizeof(struct r_respmsg));
+  net_outbuffer_push(olsr_if, &rrmsg, sizeof(struct r_respmsg));
 
   /* Send the request */
-  net_output(olsr_in_if);
+  net_output(olsr_if);
 
   return 1;
 }
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/tas/src/plugin.c olsrd-f7757d63a5d0/lib/tas/src/plugin.c
--- olsrd-a5b9cf969979/lib/tas/src/plugin.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/tas/src/plugin.c	2008-02-29 10:50:43.000000000 +0100
@@ -105,19 +105,25 @@
 
 int iterLinkTabNext(char *buff, int len)
 {
+#ifdef USE_FPM
+  fpm etx;
+#else
   double etx;
+#endif
 
   if (iterLinkTab == NULL)
     return -1;
 
   etx = olsr_calc_link_etx(iterLinkTab);
 
-  snprintf(buff, len, "local~%s~remote~%s~main~%s~hysteresis~%f~lq~%f~nlq~%f~etx~%f~",
+  snprintf(buff, len, "local~%s~remote~%s~main~%s~hysteresis~%s~lq~%s~nlq~%s~etx~%s~",
            rawIpAddrToString(&iterLinkTab->local_iface_addr, ipAddrLen),
            rawIpAddrToString(&iterLinkTab->neighbor_iface_addr, ipAddrLen),
            rawIpAddrToString(&iterLinkTab->neighbor->neighbor_main_addr, ipAddrLen),
-           iterLinkTab->L_link_quality, iterLinkTab->loss_link_quality,
-           iterLinkTab->neigh_link_quality, etx);
+           fpmtoa(iterLinkTab->L_link_quality),
+           fpmtoa(iterLinkTab->loss_link_quality),
+           fpmtoa(iterLinkTab->neigh_link_quality),
+           etxtoa(etx));
 
   iterLinkTab = iterLinkTab->next;
 
@@ -281,9 +287,9 @@
 
   OLSR_FOR_ALL_TC_EDGE_ENTRIES(iterTcTab, tc_edge) {
 
-    res = snprintf(buff, len, "[~%d~address~%s~etx~%f~]~", i,
+    res = snprintf(buff, len, "[~%d~address~%s~etx~%s~]~", i,
                    rawIpAddrToString(&tc_edge->T_dest_addr, ipAddrLen),
-                   olsr_calc_tc_etx(tc_edge));
+                   etxtoa(olsr_calc_tc_etx(tc_edge)));
 
     if (res < len)
       buff += res;
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/lib/txtinfo/src/olsrd_txtinfo.c olsrd-f7757d63a5d0/lib/txtinfo/src/olsrd_txtinfo.c
--- olsrd-a5b9cf969979/lib/txtinfo/src/olsrd_txtinfo.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/lib/txtinfo/src/olsrd_txtinfo.c	2008-02-29 10:50:43.000000000 +0100
@@ -308,15 +308,15 @@
     /* Link set */
     link = link_set;
     while(link)	{
-	ipc_sendf( "%s\t%s\t%0.2f\t%0.2f\t%d\t%d\t%0.2f\t%0.2f\t\n",
+	ipc_sendf( "%s\t%s\t%s\t%s\t%d\t%d\t%s\t%s\t\n",
                    olsr_ip_to_string(&buf1, &link->local_iface_addr),
                    olsr_ip_to_string(&buf2, &link->neighbor_iface_addr),
-                   link->L_link_quality, 
-                   link->loss_link_quality,
+                   fpmtoa(link->L_link_quality), 
+                   fpmtoa(link->loss_link_quality),
                    link->lost_packets, 
                    link->total_packets,
-                   link->neigh_link_quality, 
-                   olsr_calc_link_etx(link));
+                   fpmtoa(link->neigh_link_quality), 
+                   etxtoa(olsr_calc_link_etx(link)));
         link = link->next;
     }
     ipc_sendf("\nTable: Neighbors\nIP address\tSYM\tMPR\tMPRS\tWillingness\t2 Hop Neighbors\n");
@@ -362,12 +362,12 @@
 
         rt = rt_tree_node->data;
 
-        ipc_sendf( "%s/%d\t%s\t%d\t%.3f\t%s\t\n",
+        ipc_sendf( "%s/%d\t%s\t%d\t%s\t%s\t\n",
                    olsr_ip_to_string(&buf1, &rt->rt_dst.prefix),
                    rt->rt_dst.prefix_len,
                    olsr_ip_to_string(&buf2, &rt->rt_best->rtp_nexthop.gateway),
                    rt->rt_best->rtp_metric.hops,
-                   rt->rt_best->rtp_metric.etx,
+                   etxtoa(rt->rt_best->rtp_metric.etx),
                    if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
     }
     ipc_sendf("\n");
@@ -385,12 +385,12 @@
         struct tc_edge_entry *tc_edge;
         OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
             struct ipaddr_str dstbuf, addrbuf;
-            ipc_sendf( "%s\t%s\t%0.2f\t%0.2f\t%0.2f\n", 
+            ipc_sendf( "%s\t%s\t%s\t%s\t%s\n", 
                        olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr),
                        olsr_ip_to_string(&addrbuf, &tc->addr), 
-                       tc_edge->link_quality,
-                       tc_edge->inverse_link_quality,
-                       olsr_calc_tc_etx(tc_edge));
+                       fpmtoa(tc_edge->link_quality),
+                       fpmtoa(tc_edge->inverse_link_quality),
+                       etxtoa(olsr_calc_tc_etx(tc_edge)));
 
         } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
     } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/Makefile olsrd-f7757d63a5d0/Makefile
--- olsrd-a5b9cf969979/Makefile	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/Makefile	2008-02-29 10:50:43.000000000 +0100
@@ -36,7 +36,7 @@
 # the copyright holders.
 #
 
-VERS =		0.5.5
+VERS =		0.5.6pre
 
 TOPDIR = .
 include Makefile.inc
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/Makefile.inc olsrd-f7757d63a5d0/Makefile.inc
--- olsrd-a5b9cf969979/Makefile.inc	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/Makefile.inc	2008-02-29 10:50:43.000000000 +0100
@@ -150,6 +150,9 @@
 # we have plugins with the old interface
 #CPPFLAGS +=	-DSUPPORT_OLD_PLUGIN_VERSIONS=1
 
+# use the new fixed point math stuff
+CPPFLAGS +=     -DUSE_FPM
+
 # search sources and headers in current dir and in src/
 SRCS +=		$(wildcard src/*.c *.c)
 HDRS +=		$(wildcard src/*.h *.h)
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/fpm.c olsrd-f7757d63a5d0/src/fpm.c
--- olsrd-a5b9cf969979/src/fpm.c	1970-01-01 01:00:00.000000000 +0100
+++ olsrd-f7757d63a5d0/src/fpm.c	2008-02-29 10:50:43.000000000 +0100
@@ -0,0 +1,208 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008, Sven-Ola Tuecke (sven-ola@gmx.de)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright 
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in 
+ *   the documentation and/or other materials provided with the 
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include "fpm.h"
+
+#ifdef USE_FPM
+
+#ifndef NDEBUG
+
+fpm itofpm(int i)
+{
+  fpm r;
+  assert(FPM_MIN <= i && i <= FPM_MAX);
+  r = (fpm)itofpm_def(i);
+  return r;
+}
+
+fpm ftofpm(float f)
+{
+  fpm r;
+  assert(FPM_MIN <= (sfpm)f && (sfpm)f <= FPM_MAX);
+  r = (fpm)(sfpm)ftofpm_def(f);
+  return r;
+}
+
+int fpmtoi(fpm a)
+{
+  int r = fpmtoi_def((sfpm)a);
+  return r;
+}
+
+float fpmtof(fpm a)
+{
+  float r = fpmtof_def((sfpm)a);
+  return r;
+}
+
+fpm fpmadd(fpm a, fpm b)
+{
+  fpm r;
+  assert(0 > (sfpm)a || 0 > (sfpm)b || FPM_INT_MAX - (sfpm)a >= (sfpm)b);
+  assert(0 <= (sfpm)a || 0 <= (sfpm)b || (sfpm)a >= FPM_INT_MIN - (sfpm)b);
+  r = (fpm)fpmadd_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmsub(fpm a, fpm b)
+{
+  fpm r;
+  assert(0 > (sfpm)a || 0 <= (sfpm)b || (sfpm)a < FPM_INT_MAX + (sfpm)b);
+  assert(0 <= (sfpm)a || 0 > (sfpm)b || (sfpm)a >= FPM_INT_MIN + (sfpm)b);
+  r = (fpm)fpmsub_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmmul(fpm a, fpm b)
+{
+  fpm r;
+  assert((0 < (sfpm)a) != (0 < (sfpm)b) || ((double)(sfpm)a) * ((double)(sfpm)b) <= (double)FPM_INT_MAX);
+  assert((0 < (sfpm)a) == (0 < (sfpm)b) || ((double)(sfpm)a) * ((double)(sfpm)b) >= (double)FPM_INT_MIN);
+  r = (fpm)fpmmul_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmdiv(fpm a, fpm b) {
+  fpm r;
+  assert(FPM_INT_MIN <= ((long long)(sfpm)a << FPM_BIT) && ((long long)(sfpm)a << FPM_BIT) <= FPM_INT_MAX);
+  r = (fpm)fpmdiv_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmimul(int a, fpm b)
+{
+  fpm r;
+  assert((0 < a) != (0 < (sfpm)b) || ((double)a * (double)(sfpm)b) <= (double)FPM_INT_MAX);
+  assert((0 < a) == (0 < (sfpm)b) || ((double)a * (double)(sfpm)b) >= (double)FPM_INT_MIN);
+  r = (fpm)fpmimul_def(a, (sfpm)b);
+  return r;
+}
+
+fpm fpmmuli(fpm a, int b)
+{
+  fpm r;
+  assert((0 < (sfpm)a) != (0 < b) || ((double)(sfpm)a * (double)b) <= (double)FPM_INT_MAX);
+  assert((0 < (sfpm)a) == (0 < b) || ((double)(sfpm)a * (double)b) >= (double)FPM_INT_MIN);
+  r = (fpm)fpmmuli_def((sfpm)a, b);
+  return r;
+}
+
+fpm fpmidiv(fpm a, int b)
+{
+  fpm r;
+  r = (fpm)fpmidiv_def((sfpm)a, b);
+  return r;
+}
+
+#if 0
+fpm fpmlmul(fpm a, fpm b)
+{
+  fpm r;
+  assert((0 < (sfpm)a) != (0 < (sfpm)b) || ((double)(sfpm)a * (double)(sfpm)b / FPM_NUM) <= (double)FPM_INT_MAX);
+  assert((0 < (sfpm)a) == (0 < (sfpm)b) || ((double)(sfpm)a * (double)(sfpm)b / FPM_NUM) >= (double)FPM_INT_MIN);
+  r = (fpm)fpmlmul_def((sfpm)a, (sfpm)b);
+  return r;
+}
+
+fpm fpmldiv(fpm a, fpm b) {
+  fpm r;
+  r = (fpm)fpmldiv_def((sfpm)a, (sfpm)b);
+  return r;
+}
+#endif
+
+#endif /* !NDEBUG */
+
+fpm atofpm(const char *s)
+{
+  float r = 0.0;
+  sscanf(s, "%f", &r);
+  return ftofpm(r);
+}
+
+const char *fpmtoa(fpm a)
+{
+  static int idx = 0;
+  static char ret[4][20];
+
+  idx = (idx + 1) % (sizeof(ret) / sizeof(ret[0]));
+  snprintf(ret[idx], sizeof(ret[0]), "%ld.%03ld", (sfpm)a >> FPM_BIT,
+    (1000 * ((sfpm)(a) & FPM_MSK) + (FPM_NUM / 2)) >> FPM_BIT);
+  return ret[idx];
+}
+
+const char *etxtoa(fpm etx)
+{
+  return etx >= INFINITE_ETX ? "INF" : fpmtoa(etx);
+}
+
+#else /* USE_FPM */
+
+float atofpm(const char *s)
+{
+  float r = 0.0;
+  sscanf(s, "%f", &r);
+  return r;
+}
+
+const char *fpmtoa(float a)
+{
+  static int idx = 0;
+  static char ret[4][20];
+
+  idx = (idx + 1) % (sizeof(ret) / sizeof(ret[0]));
+  snprintf(ret[idx], sizeof(ret[0]), "%.3f", a);
+  return ret[idx];
+}
+
+const char *etxtoa(float etx)
+{
+  return etx >= INFINITE_ETX ? "INF" : fpmtoa(etx);
+}
+
+#endif /* USE_FPM */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/fpm.h olsrd-f7757d63a5d0/src/fpm.h
--- olsrd-a5b9cf969979/src/fpm.h	1970-01-01 01:00:00.000000000 +0100
+++ olsrd-f7757d63a5d0/src/fpm.h	2008-02-29 10:50:43.000000000 +0100
@@ -0,0 +1,187 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2008, Sven-Ola Tuecke (sven-ola@gmx.de)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright 
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in 
+ *   the documentation and/or other materials provided with the 
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+#ifndef _FPM_H
+#define _FPM_H
+
+#ifdef USE_FPM
+
+#if 0
+
+/* 
+ * Use this to find implicit number conversions when compiling
+ * Note: comparing pointers is unsigned, so do not use to run.
+ */
+typedef void* fpm;
+typedef signed long sfpm;
+typedef unsigned long ufpm;
+#define FPM_BIT 12
+
+#elif 0
+
+/*
+ * Use this for extra long 64 bit calculations
+ */
+typedef long long fpm;
+typedef signed long long sfpm;
+typedef unsigned long long ufpm;
+#define FPM_BIT 24
+
+#else
+
+/*
+ * The standard math should function with only 32 bits
+ */
+typedef long fpm;
+typedef signed long sfpm;
+typedef unsigned long ufpm;
+#define FPM_BIT 12
+ 
+#endif
+
+#define FPM_NUM (1 << FPM_BIT)
+#define FPM_MSK (FPM_NUM - 1)
+#define FPM_MAX ((sfpm)(~(ufpm)0 >> 1) >> FPM_BIT)
+#define FPM_MIN ((sfpm)-1 - FPM_MAX)
+#define FPM_INT_MAX ((sfpm)(~(ufpm)0 >> 1))
+#define FPM_INT_MIN ((sfpm)-1 - FPM_INT_MAX)
+
+#define itofpm_def(a) (fpm)((sfpm)((a) << FPM_BIT))
+#define ftofpm_def(a) (fpm)((sfpm)((a) * FPM_NUM))
+#define fpmtoi_def(a) (int)((sfpm)(a) >> FPM_BIT)
+#define fpmtof_def(a) ((float)(sfpm)(a) / FPM_NUM)
+
+#define fpmadd_def(a, b) (fpm)((sfpm)(a) + (sfpm)(b))
+#define fpmsub_def(a, b) (fpm)((sfpm)(a) - (sfpm)(b))
+#define fpmmul_def(a, b) (fpm)(((sfpm)(a) * (sfpm)(b)) >> FPM_BIT)
+#define fpmdiv_def(a, b) (fpm)(((sfpm)(a) << FPM_BIT) / (sfpm)(b))
+
+/*
+ * Special: first or second factor is an integer
+ */
+#define fpmimul_def(a, b) (fpm)((int)(a) * (sfpm)(b))
+#define fpmmuli_def(a, b) (fpm)((sfpm)(a) * (int)(b))
+
+/*
+ * Special: divisor is an integer
+ */
+#define fpmidiv_def(a, b) (fpm)((sfpm)(a) / (int)(b))
+
+#if 0
+/*
+ * Special: uses long long for larger numbers, currently unused
+ */
+#define fpmlmul_def(a, b) (sfpm)(((long long)(a) * (b)) >> FPM_BIT)
+#define fpmldiv_def(a, b) (sfpm)(((long long)(a) << FPM_BIT) / (b))
+#endif
+
+#ifdef NDEBUG
+
+#define itofpm itofpm_def
+#define ftofpm ftofpm_def
+#define fpmtoi fpmtoi_def
+#define fpmtof fpmtof_def
+
+#define fpmadd fpmadd_def
+#define fpmsub fpmsub_def
+#define fpmmul fpmmul_def
+#define fpmdiv fpmdiv_def
+#define fpmimul fpmimul_def
+#define fpmmuli fpmmuli_def
+#define fpmidiv fpmidiv_def
+
+#if 0
+#define fpmlmul fpmlmul_def
+#define fpmldiv fpmldiv_def
+#endif
+
+#else /* NDEBUG */
+
+fpm itofpm(int i);
+fpm ftofpm(float f);
+int fpmtoi(fpm a);
+float fpmtof(fpm a);
+
+fpm fpmadd(fpm a, fpm b);
+fpm fpmsub(fpm a, fpm b);
+fpm fpmmul(fpm a, fpm b);
+fpm fpmdiv(fpm a, fpm b);
+fpm fpmimul(int a, fpm b);
+fpm fpmmuli(fpm a, int b);
+fpm fpmidiv(fpm a, int b);
+
+#if 0
+fpm fpmlmul(fpm a, fpm b);
+fpm fpmldiv(fpm a, fpm b);
+#endif
+  
+#endif /* NDEBUG */
+
+#define INFINITE_ETX itofpm(FPM_MAX)
+#define MIN_LINK_QUALITY ftofpm(0.01)
+#define ZERO_ETX itofpm(0)
+#define CEIL_LQDIFF ftofpm(1.1)
+#define FLOOR_LQDIFF ftofpm(0.9)
+
+fpm atofpm(const char *);
+const char *fpmtoa(fpm);
+const char *etxtoa(fpm);
+
+#else /* USE_FPM */
+
+#define INFINITE_ETX ((float)(1 << 30))
+#define ZERO_ETX 0.0
+#define MIN_LINK_QUALITY 0.01
+#define CEIL_LQDIFF 1.1
+#define FLOOR_LQDIFF 0.9
+
+float atofpm(const char *);
+const char *fpmtoa(float);
+const char *etxtoa(float);
+
+#endif /* USE_FPM */
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/hysteresis.c olsrd-f7757d63a5d0/src/hysteresis.c
--- olsrd-a5b9cf969979/src/hysteresis.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/hysteresis.c	2008-02-29 10:50:43.000000000 +0100
@@ -48,23 +48,45 @@
 #include "net_olsr.h"
 #include "ipcalc.h"
 
+#ifdef USE_FPM
+#define hscaling ftofpm(olsr_cnf->hysteresis_param.scaling)
+#define hhigh    ftofpm(olsr_cnf->hysteresis_param.thr_high)
+#define hlow     ftofpm(olsr_cnf->hysteresis_param.thr_low)
+#else
 #define hscaling olsr_cnf->hysteresis_param.scaling
 #define hhigh    olsr_cnf->hysteresis_param.thr_high
 #define hlow     olsr_cnf->hysteresis_param.thr_low
+#endif
 
+#ifdef USE_FPM
+fpm
+olsr_hyst_calc_stability(fpm old_quality)
+{
+  return fpmadd(fpmmul(fpmsub(itofpm(1), hscaling), old_quality), hscaling);
+}
+#else
 float
 olsr_hyst_calc_stability(float old_quality)
 {
   return (((1 - hscaling) * old_quality) + hscaling);
 }
+#endif
 
 
 
+#ifdef USE_FPM
+fpm
+olsr_hyst_calc_instability(fpm old_quality)
+{
+  return fpmmul(fpmsub(itofpm(1), hscaling), old_quality);
+}
+#else
 float
 olsr_hyst_calc_instability(float old_quality)
 {
   return ((1 - hscaling) * old_quality);
 }
+#endif
 
 
 
@@ -182,7 +204,7 @@
 #endif
       lnk->L_link_quality = olsr_hyst_calc_stability(lnk->L_link_quality);
 #ifdef DEBUG
-      OLSR_PRINTF(3, "HYST[%s]: %0.3f\n", olsr_ip_to_string(&buf, remote), lnk->L_link_quality);
+      OLSR_PRINTF(3, "HYST[%s]: %s\n", olsr_ip_to_string(&buf, remote), fpmtoa(lnk->L_link_quality));
 #endif
 
       /* 
@@ -198,10 +220,14 @@
 	    {
 	      lnk->L_link_quality = olsr_hyst_calc_instability(lnk->L_link_quality);
 #ifdef DEBUG
-	      OLSR_PRINTF(5, "HYST[%s] PACKET LOSS! %0.3f\n",
-			  olsr_ip_to_string(&buf, remote), lnk->L_link_quality);
+	      OLSR_PRINTF(5, "HYST[%s] PACKET LOSS! %s\n",
+			  olsr_ip_to_string(&buf, remote), fpmtoa(lnk->L_link_quality));
 #endif
+#ifdef USE_FPM
+	      if(lnk->L_link_quality < ftofpm(olsr_cnf->hysteresis_param.thr_low))
+#else
 	      if(lnk->L_link_quality < olsr_cnf->hysteresis_param.thr_low)
+#endif
 		break;
 
 	      lnk->olsr_seqno++;
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/hysteresis.h olsrd-f7757d63a5d0/src/hysteresis.h
--- olsrd-a5b9cf969979/src/hysteresis.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/hysteresis.h	2008-02-29 10:50:43.000000000 +0100
@@ -42,14 +42,25 @@
 
 #include "link_set.h"
 
+#ifdef USE_FPM
+fpm
+olsr_hyst_calc_stability(fpm);
+#else
 float
-olsr_hyst_calc_stability(float);
+olsr_hyst_calc_stability
+(float);
+#endif
 
 int
 olsr_process_hysteresis(struct link_entry *);
 
+#ifdef USE_FPM
+fpm
+olsr_hyst_calc_instability(fpm);
+#else
 float
 olsr_hyst_calc_instability(float);
+#endif
 
 void
 olsr_update_hysteresis_hello(struct link_entry *, double);
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/link_set.c olsrd-f7757d63a5d0/src/link_set.c
--- olsrd-a5b9cf969979/src/link_set.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/link_set.c	2008-02-29 10:50:43.000000000 +0100
@@ -241,7 +241,11 @@
   const union olsr_ip_addr *main_addr;
   struct link_entry *walker, *good_link, *backup_link;
   int curr_metric = MAX_IF_METRIC;
+#ifdef USE_FPM
+  fpm curr_lq = itofpm(-1);
+#else
   float curr_lq = -1.0;
+#endif
   
   // main address lookup
 
@@ -305,12 +309,20 @@
 
     else
     {
+#ifdef USE_FPM
+      fpm tmp_lq;
+#else
       float tmp_lq;
+#endif
 
       // calculate the bi-directional link quality - we select the link
       // with the best link quality
 
+#ifdef USE_FPM
+      tmp_lq = fpmmul(walker->loss_link_quality, walker->neigh_link_quality);
+#else
       tmp_lq = walker->loss_link_quality * walker->neigh_link_quality;
+#endif
 
       // is this link better than anything we had before?
 	      
@@ -344,7 +356,11 @@
   struct interface *inter;
   struct olsr_if *cfg_inter;
   struct olsr_lq_mult *mult;
+#ifdef USE_FPM
+  fpm val = itofpm(-1);
+#else
   float val = -1.0;
+#endif
   union olsr_ip_addr null_addr;
 
   // find the interface for the link
@@ -369,15 +385,28 @@
     // use the default multiplier only if there isn't any entry that
     // has a matching IP address
 
+#ifdef USE_FPM
+    if ((ipequal(&mult->addr, &null_addr) && val < itofpm(0)) ||
+#else
     if ((ipequal(&mult->addr, &null_addr) && val < 0.0) ||
+#endif
         ipequal(&mult->addr, &entry->neighbor_iface_addr))
+#ifdef USE_FPM
+      val = ftofpm(mult->val);
+#else
       val = mult->val;
+#endif
   }
 
   // if we have not found an entry, then use the default multiplier
 
+#ifdef USE_FPM
+  if (val < itofpm(0))
+    val = itofpm(1);
+#else
   if (val < 0)
     val = 1.0;
+#endif
 
   // store the multiplier
 
@@ -532,7 +561,11 @@
       new_link->olsr_seqno_valid = OLSR_FALSE;
     }
 
+#ifdef USE_FPM
+  new_link->L_link_quality = itofpm(0);
+#else
   new_link->L_link_quality = 0.0;
+#endif
 
   if (olsr_cnf->lq_level > 0)
     {
@@ -554,6 +587,16 @@
       set_loss_link_multiplier(new_link);
     }
 
+#ifdef USE_FPM
+  new_link->loss_link_quality = itofpm(0);
+  new_link->neigh_link_quality = itofpm(0);
+
+  new_link->loss_link_quality2 = itofpm(0);
+  new_link->neigh_link_quality2 = itofpm(0);
+
+  new_link->saved_loss_link_quality = itofpm(0);
+  new_link->saved_neigh_link_quality = itofpm(0);
+#else
   new_link->loss_link_quality = 0.0;
   new_link->neigh_link_quality = 0.0;
 
@@ -562,6 +605,7 @@
 
   new_link->saved_loss_link_quality = 0.0;
   new_link->saved_neigh_link_quality = 0.0;
+#endif
 
   /* Add to queue */
   new_link->next = link_set;
@@ -929,7 +973,9 @@
           struct ipaddr_str buf;
 #endif
 	  tmp_link_set->L_link_quality = olsr_hyst_calc_instability(tmp_link_set->L_link_quality);
-	  OLSR_PRINTF(1, "HYST[%s] HELLO timeout %0.3f\n", olsr_ip_to_string(&buf, &tmp_link_set->neighbor_iface_addr), tmp_link_set->L_link_quality);
+	  OLSR_PRINTF(1, "HYST[%s] HELLO timeout %s\n",
+                      olsr_ip_to_string(&buf, &tmp_link_set->neighbor_iface_addr),
+                      fpmtoa(tmp_link_set->L_link_quality));
 	  /* Update hello_timeout - NO SLACK THIS TIME */
 	  tmp_link_set->hello_timeout = GET_TIMESTAMP(tmp_link_set->last_htime*1000);
 	  /* Recalculate status */
@@ -969,21 +1015,30 @@
   for (walker = link_set; walker != NULL; walker = walker->next)
   {
     struct ipaddr_str buf;
+#ifdef USE_FPM
+    fpm etx;
+
+    if (walker->loss_link_quality < MIN_LINK_QUALITY || walker->neigh_link_quality < MIN_LINK_QUALITY)
+      etx = itofpm(0);
+    else
+      etx = fpmdiv(itofpm(1), fpmmul(walker->loss_link_quality, walker->neigh_link_quality));
+#else
     float etx;
 
     if (walker->loss_link_quality < MIN_LINK_QUALITY || walker->neigh_link_quality < MIN_LINK_QUALITY)
       etx = 0.0;
     else
       etx = 1.0 / (walker->loss_link_quality * walker->neigh_link_quality);
+#endif
 
-    OLSR_PRINTF(1, "%-*s  %5.3f  %5.3f  %-3d    %-3d    %5.3f  %.2f\n",
+    OLSR_PRINTF(1, "%-*s  %s  %s  %-3d    %-3d    %s  %s\n",
                 addrsize, olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
-                walker->L_link_quality,
-                walker->loss_link_quality,
+                fpmtoa(walker->L_link_quality),
+                fpmtoa(walker->loss_link_quality),
 		walker->lost_packets,
                 walker->total_packets,
-		walker->neigh_link_quality,
-                etx);
+		fpmtoa(walker->neigh_link_quality),
+                etxtoa(etx));
   }
 #endif
 }
@@ -992,7 +1047,11 @@
 {
   unsigned char mask = 1 << (entry->loss_index & 7);
   const int idx = entry->loss_index >> 3;
+#ifdef USE_FPM
+  fpm rel_lq, saved_lq;
+#else
   double rel_lq, saved_lq;
+#endif
 
   if (lost == 0)
     {
@@ -1040,28 +1099,51 @@
 
   saved_lq = entry->saved_loss_link_quality;
 
+#ifdef USE_FPM
+  if (saved_lq == itofpm(0))
+    saved_lq = itofpm(-1);
+#else
   if (saved_lq == 0.0)
     saved_lq = -1.0;
+#endif
 
   // calculate the new link quality
   //
   // start slowly: receive the first packet => link quality = 1 / n
   //               (n = window size)
+#ifdef USE_FPM
+  entry->loss_link_quality = fpmdiv(
+    itofpm(entry->total_packets - entry->lost_packets),
+    olsr_cnf->lq_wsize < (2 * 4) ? itofpm(olsr_cnf->lq_wsize):
+    fpmidiv(fpmimul(4,fpmadd(fpmmuli(fpmsub(fpmidiv(itofpm(olsr_cnf->lq_wsize),4),
+                                            itofpm(1)),(int)entry->total_packets),
+                             itofpm(olsr_cnf->lq_wsize))),
+            (olsr_32_t)olsr_cnf->lq_wsize));
+#else
   entry->loss_link_quality =
     (float)(entry->total_packets - entry->lost_packets) /
     (float)(olsr_cnf->lq_wsize < (2 * 4) ? olsr_cnf->lq_wsize: 
     4 * (((float)olsr_cnf->lq_wsize / 4 - 1) * entry->total_packets + olsr_cnf->lq_wsize) / olsr_cnf->lq_wsize);
+#endif
     
   // multiply the calculated link quality with the user-specified multiplier
 
+#ifdef USE_FPM
+  entry->loss_link_quality = fpmmul(entry->loss_link_quality, entry->loss_link_multiplier);
+#else
   entry->loss_link_quality *= entry->loss_link_multiplier;
+#endif
 
   // if the link quality has changed by more than 10 percent,
   // print the new link quality table
 
+#ifdef USE_FPM
+  rel_lq = fpmdiv(entry->loss_link_quality, saved_lq);
+#else
   rel_lq = entry->loss_link_quality / saved_lq;
+#endif
 
-  if (rel_lq > 1.1 || rel_lq < 0.9)
+  if (rel_lq > CEIL_LQDIFF || rel_lq < FLOOR_LQDIFF)
     {
       entry->saved_loss_link_quality = entry->loss_link_quality;
 
@@ -1191,10 +1273,20 @@
   }
 }
 
-float olsr_calc_link_etx(const struct link_entry *link)
+#ifdef USE_FPM
+fpm
+#else
+float
+#endif
+olsr_calc_link_etx(const struct link_entry *link)
 {
   return link->loss_link_quality < MIN_LINK_QUALITY ||
          link->neigh_link_quality < MIN_LINK_QUALITY
+#ifdef USE_FPM
+             ? itofpm(0)
+             : fpmdiv(itofpm(1), fpmmul(link->loss_link_quality, link->neigh_link_quality));
+#else
              ? 0.0
              : 1.0 / (link->loss_link_quality * link->neigh_link_quality);
+#endif
 }
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/link_set.h olsrd-f7757d63a5d0/src/link_set.h
--- olsrd-a5b9cf969979/src/link_set.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/link_set.h	2008-02-29 10:50:43.000000000 +0100
@@ -66,7 +66,11 @@
   /*
    *Hysteresis
    */
+#ifdef USE_FPM
+  fpm L_link_quality;
+#else
   float L_link_quality;
+#endif
   int L_link_pending;
   clock_t L_LOST_LINK_time;
   clock_t hello_timeout; /* When we should receive a new HELLO */
@@ -87,18 +91,31 @@
   unsigned int lost_packets;
   unsigned int total_packets;
 
+#ifdef USE_FPM
+  fpm loss_link_quality;
+  fpm loss_link_quality2;
+  fpm loss_link_multiplier;
+#else
   double loss_link_quality;
   double loss_link_quality2;
   double loss_link_multiplier;
+#endif
 
   unsigned int loss_index;
 
   unsigned char loss_bitmap[16];
 
+#ifdef USE_FPM
+  fpm neigh_link_quality, neigh_link_quality2;
+
+  fpm saved_loss_link_quality;
+  fpm saved_neigh_link_quality;
+#else
   double neigh_link_quality, neigh_link_quality2;
 
   double saved_loss_link_quality;
   double saved_neigh_link_quality;
+#endif
 
   struct link_entry *next;
 };
@@ -152,7 +169,12 @@
 void
 olsr_update_dijkstra_link_qualities(void);
 
-float olsr_calc_link_etx(const struct link_entry *);
+#ifdef USE_FPM
+fpm
+#else
+float
+#endif
+olsr_calc_link_etx(const struct link_entry *);
 
 #endif
 
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/linux/apm.c olsrd-f7757d63a5d0/src/linux/apm.c
--- olsrd-a5b9cf969979/src/linux/apm.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/linux/apm.c	2008-02-29 10:50:43.000000000 +0100
@@ -104,7 +104,11 @@
 #define USE_APM    1
 #define USE_ACPI   2
 
-static int method, fd_index;
+static int method;
+
+static int fd_index;
+
+static int ac_power_on;
 
 /* Prototypes */
 
@@ -126,7 +130,7 @@
   method = -1;
   OLSR_PRINTF(3, "Initializing APM\n");
 
-  if(((fd_index = acpi_probe()) >= 0) && apm_read_acpi(&ainfo))
+  if((((fd_index = acpi_probe()) >= 0) || ac_power_on) && apm_read_acpi(&ainfo))
     method = USE_ACPI;
   else if(apm_read_apm(&ainfo))
     method = USE_APM;
@@ -139,7 +143,7 @@
 
 
 void
-apm_printinfo(struct olsr_apm_info *ainfo __attribute__((unused)))
+apm_printinfo(struct olsr_apm_info *ainfo)
 {
   OLSR_PRINTF(5, "APM info:\n\tAC status %d\n\tBattery percentage %d%%\n\tBattery time left %d mins\n\n",
 	      ainfo->ac_line_status,
@@ -237,15 +241,26 @@
   FILE *fd;
   int bat_max = 5000; /* Find some sane value */
   int bat_val = 0;
-  
-  printf("READING ACPI\n");
+  int result;
+ 
+  /* reporbe in case ac status changed */
+  fd_index = acpi_probe();
 
+  /* No battery was found */
   if(fd_index < 0)
     {
-      /* No battery was found or AC power was detected */
-      ainfo->ac_line_status = OLSR_AC_POWERED;
-      ainfo->battery_percentage = 100;
-      return 1;
+      /* but we have ac */
+      if(ac_power_on)
+        {
+           ainfo->ac_line_status = OLSR_AC_POWERED;
+
+           ainfo->battery_percentage = -1;
+
+           return 1;
+        }
+
+      /* not enough info */
+      return 0;
     }
 
   /* Get maxvalue */
@@ -282,8 +297,11 @@
     }
   fclose(fd);
 
-  ainfo->ac_line_status = OLSR_BATTERY_POWERED;
-  ainfo->battery_percentage = bat_val * 100 / bat_max;
+  ainfo->ac_line_status = ac_power_on ? OLSR_AC_POWERED : OLSR_BATTERY_POWERED;
+
+  result = bat_val * 100 / bat_max;
+
+  ainfo->battery_percentage = result > 100 ? 100 : result;
 
   return 1;
 }
@@ -295,6 +313,7 @@
   unsigned int i;
   
   /* First check for AC power */
+  ac_power_on = 0;
 
   for(i = 0; i < ACPI_AC_CNT; i++)
     {
@@ -316,8 +335,13 @@
 	  continue;
       
       /* Running on AC power */
-      if(!strcasecmp(s2, "on-line"))
-	return -1;
+      if(!strcasecmp(s2, "on-line")) {
+
+        /* ac power enabled */
+        ac_power_on = 1;
+
+	break;
+      }
     }
 
   /* Only checking the first found battery entry... */
@@ -333,6 +357,7 @@
 
       /* Extract info */
       rc = fscanf(fd, "%s %s", s1, s2);
+
       /* Close info entry */
       fclose(fd);
 
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/lq_mpr.c olsrd-f7757d63a5d0/src/lq_mpr.c
--- olsrd-a5b9cf969979/src/lq_mpr.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/lq_mpr.c	2008-02-29 10:50:43.000000000 +0100
@@ -51,7 +51,11 @@
   struct neighbor_list_entry *walker;
   int i, k;
   struct neighbor_entry *neigh;
+#ifdef USE_FPM
+  fpm best, best_1hop;
+#else
   double best, best_1hop;
+#endif
   olsr_bool mpr_changes = OLSR_FALSE;
 
   for(i = 0; i < HASHSIZE; i++)
@@ -89,7 +93,11 @@
            neigh2 != &two_hop_neighbortable[i];
            neigh2 = neigh2->next)
         {
+#ifdef USE_FPM
+          best_1hop = itofpm(-1);
+#else
           best_1hop = -1.0;
+#endif
 
           // check whether this 2-hop neighbour is also a neighbour
 
@@ -111,7 +119,11 @@
 	      if (!lnk)
 		continue;
 
+#ifdef USE_FPM
+              best_1hop = fpmmul(lnk->loss_link_quality, lnk->neigh_link_quality);
+#else
               best_1hop = lnk->loss_link_quality * lnk->neigh_link_quality;
+#endif
 
               // see wether we find a better route via an MPR
 
@@ -145,7 +157,11 @@
               // yet selected
 
               neigh = NULL;
+#ifdef USE_FPM
+              best = itofpm(-1);
+#else
               best = -1.0;
+#endif
 
               for (walker = neigh2->neighbor_2_nblist.next;
                    walker != &neigh2->neighbor_2_nblist;
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/lq_packet.c olsrd-f7757d63a5d0/src/lq_packet.c
--- olsrd-a5b9cf969979/src/lq_packet.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/lq_packet.c	2008-02-29 10:50:43.000000000 +0100
@@ -232,8 +232,13 @@
           }
           else {
             OLSR_PRINTF(0, "Error: link_qualtiy undefined");
+#ifdef USE_FPM
+            neigh->link_quality = itofpm(0);
+            neigh->neigh_link_quality = itofpm(0);
+#else
             neigh->link_quality = 0.0;
             neigh->neigh_link_quality = 0.0;
+#endif
           }          
 
           // queue the neighbour entry
@@ -445,8 +450,13 @@
 
               // add the corresponding link quality
 
+#ifdef USE_FPM
+              buff[size++] = fpmtoi(fpmmuli(neigh->link_quality, 255));
+              buff[size++] = fpmtoi(fpmmuli(neigh->neigh_link_quality, 255));
+#else
               buff[size++] = (unsigned char)(neigh->link_quality * 255);
               buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
+#endif
 
               // pad
 
@@ -559,8 +569,13 @@
       size += olsr_cnf->ipsize;
 
       // add the corresponding link quality
+#ifdef USE_FPM
+      buff[size++] = fpmtoi(fpmmuli(neigh->link_quality, 255));
+      buff[size++] = fpmtoi(fpmmuli(neigh->neigh_link_quality, 255));
+#else
       buff[size++] = (unsigned char)(neigh->link_quality * 255);
       buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
+#endif
 
       // pad
       buff[size++] = 0;
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/lq_packet.h olsrd-f7757d63a5d0/src/lq_packet.h
--- olsrd-a5b9cf969979/src/lq_packet.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/lq_packet.h	2008-02-29 10:50:43.000000000 +0100
@@ -94,8 +94,13 @@
 {
   olsr_u8_t                link_type;
   olsr_u8_t                neigh_type;
+#ifdef USE_FPM
+  fpm                      link_quality;
+  fpm                      neigh_link_quality;
+#else
   double                   link_quality;
   double                   neigh_link_quality;
+#endif
   union olsr_ip_addr       addr;
   struct lq_hello_neighbor *next;
 };
@@ -150,7 +155,11 @@
 static INLINE void    pkt_get_double(const olsr_u8_t **p, double *var)             { *var = me_to_double(**p);                       *p += sizeof(olsr_u8_t); }
 static INLINE void pkt_get_ipaddress(const olsr_u8_t **p, union olsr_ip_addr *var) { memcpy(var, *p, olsr_cnf->ipsize);              *p += olsr_cnf->ipsize; }
 static INLINE void pkt_get_prefixlen(const olsr_u8_t **p, olsr_u8_t *var)          { *var = netmask_to_prefix(*p, olsr_cnf->ipsize); *p += olsr_cnf->ipsize; }
+#ifdef USE_FPM
+static INLINE void        pkt_get_lq(const olsr_u8_t **p, fpm *var)                { *var = fpmidiv(itofpm(**p), 255);               *p += sizeof(olsr_u8_t); }
+#else
 static INLINE void        pkt_get_lq(const olsr_u8_t **p, double *var)             { *var = (const double)**p / 255.0;               *p += sizeof(olsr_u8_t); }
+#endif
 
 static INLINE void        pkt_ignore_u8(const olsr_u8_t **p) { *p += sizeof(olsr_u8_t); }
 static INLINE void       pkt_ignore_u16(const olsr_u8_t **p) { *p += sizeof(olsr_u16_t); }
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/lq_route.c olsrd-f7757d63a5d0/src/lq_route.c
--- olsrd-a5b9cf969979/src/lq_route.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/lq_route.c	2008-02-29 10:50:43.000000000 +0100
@@ -104,9 +104,9 @@
   tc->cand_tree_node.data = tc;
 
 #ifdef DEBUG
-  OLSR_PRINTF(1, "SPF: insert candidate %s, cost %f\n",
+  OLSR_PRINTF(1, "SPF: insert candidate %s, cost %s\n",
               olsr_ip_to_string(&buf, &tc->addr),
-              tc->path_etx);
+              etxtoa(tc->path_etx));
 #endif
 
   avl_insert(tree, &tc->cand_tree_node, AVL_DUP);
@@ -126,9 +126,9 @@
 #ifndef NODEBUG
   struct ipaddr_str buf;
 #endif
-  OLSR_PRINTF(1, "SPF: delete candidate %s, cost %f\n",
+  OLSR_PRINTF(1, "SPF: delete candidate %s, cost %s\n",
               olsr_ip_to_string(&buf, &tc->addr),
-              tc->path_etx);
+              etxtoa(tc->path_etx));
 #endif
 
   avl_delete(tree, &tc->cand_tree_node);
@@ -149,10 +149,11 @@
   tc->path_list_node.data = tc;
 
 #ifdef DEBUG
-  OLSR_PRINTF(1, "SPF: append path %s, cost %f, via %s\n",
+  OLSR_PRINTF(1, "SPF: append path %s, cost %s, via %s\n",
               olsr_ip_to_string(&pathbuf, &tc->addr),
-              tc->path_etx,
-              tc->next_hop ? olsr_ip_to_string(&nbuf, &tc->next_hop->neighbor_iface_addr) : "-");
+              etxtoa(tc->path_etx),
+              tc->next_hop ? olsr_ip_to_string(
+                &nbuf, &tc->next_hop->neighbor_iface_addr) : "-");
 #endif
 
   list_add_before(head, &tc->path_list_node);
@@ -173,18 +174,6 @@
 }
 
 
-const char *olsr_etx_to_string(float etx)
-{
-  static char buff[20];
-
-  if (etx == INFINITE_ETX) {
-    return "INF";
-  }
-  snprintf(buff, sizeof(buff), "%.6f", etx);
-  return buff;
-}
-
-
 /*
  * olsr_spf_relax
  *
@@ -196,15 +185,19 @@
 olsr_spf_relax (struct avl_tree *cand_tree, struct tc_entry *tc)
 {
   struct avl_node *edge_node;
+#ifdef USE_FPM
+  fpm new_etx;
+#else
   float new_etx;
+#endif
 
 #ifdef DEBUG
 #ifndef NODEBUG
   struct ipaddr_str buf, nbuf;
 #endif
-  OLSR_PRINTF(1, "SPF: exploring node %s, cost %f\n",
+  OLSR_PRINTF(1, "SPF: exploring node %s, cost %s\n",
               olsr_ip_to_string(&buf, &tc->addr),
-              tc->path_etx);
+              etxtoa(tc->path_etx));
 #endif
 
   /*
@@ -238,12 +231,17 @@
      * total quality of the path through this vertex
      * to the destination of this edge
      */
+#ifdef USE_FPM
+    new_etx = INFINITE_ETX <= tc->path_etx || INFINITE_ETX <= tc_edge->etx
+      ? INFINITE_ETX : fpmadd(tc->path_etx, tc_edge->etx);
+#else
     new_etx = tc->path_etx + tc_edge->etx;
+#endif
 
 #ifdef DEBUG
       OLSR_PRINTF(1, "SPF:   exploring edge %s, cost %s\n",
                   olsr_ip_to_string(&buf, &tc_edge->T_dest_addr),
-                  olsr_etx_to_string(new_etx));
+                  etxtoa(new_etx));
 #endif
 
       /* 
@@ -272,9 +270,10 @@
 #ifdef DEBUG
       OLSR_PRINTF(1, "SPF:   better path to %s, cost %s -> %s, via %s, hops %u\n",
                   olsr_ip_to_string(&buf, &new_tc->addr),
-                  olsr_etx_to_string(new_tc->path_etx),
-                  olsr_etx_to_string(new_etx),
-                  tc->next_hop ? olsr_ip_to_string(&nbuf, &tc->next_hop->neighbor_iface_addr) : "<none>",
+                  etxtoa(new_tc->path_etx),
+                  etxtoa(new_etx),
+                  tc->next_hop ? olsr_ip_to_string(
+                    &nbuf, &tc->next_hop->neighbor_iface_addr) : "<none>",
                   new_tc->hops);
 #endif
 
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/lq_route.h olsrd-f7757d63a5d0/src/lq_route.h
--- olsrd-a5b9cf969979/src/lq_route.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/lq_route.h	2008-02-29 10:50:43.000000000 +0100
@@ -41,11 +41,6 @@
 #ifndef _LQ_ROUTE_H
 #define _LQ_ROUTE_H
 
-#define INFINITE_ETX ((float)(1 << 30))
-#define ZERO_ETX 0.0
-#define MIN_LINK_QUALITY 0.01
-
 void olsr_calculate_routing_table(void);
-const char *olsr_etx_to_string(float);
 
 #endif
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/mantissa.c olsrd-f7757d63a5d0/src/mantissa.c
--- olsrd-a5b9cf969979/src/mantissa.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/mantissa.c	2008-02-29 10:50:43.000000000 +0100
@@ -130,3 +130,40 @@
     const olsr_u8_t b = me & 0x0F;
     return ((16 + a) << b) * VTIME_SCALE_FACTOR / 16.0;
 }
+
+#if 0
+/*
+ * Since the original VTIME_SCALE_FACTOR simply divides
+ * values by 16 (equals >> 4), we can shorten calculations.
+ * For details refer to RFC 3626 (search for "mantissa").
+ */
+olsr_u8_t fpm_to_me(const fpm interval)
+{
+  olsr_u8_t a = 0, b = 0; /* Underflow defaults */
+  const unsigned int unscaled_interval = (sfpm)interval >> (FPM_BIT - 4);
+
+  while (unscaled_interval >= (1U << b)) b++;
+
+  if (0 < b) {
+    b--;
+    if (15 < b) {
+      a = 15; /* Overflow defaults */
+      b = 15;
+    }
+    else
+    {
+      assert(FPM_BIT >= 8);
+      a = ((sfpm)interval >> (FPM_BIT + b - 8)) - 16;
+    }
+  }
+  return (a << 4) | (b & 0x0F);
+}
+
+fpm me_to_fpm(const olsr_u8_t me)
+{
+  const olsr_u8_t a = me >> 4;
+  const olsr_u8_t b = me & 0x0F;
+  assert(FPM_BIT >= 8);
+  return (fpm)(((sfpm)a + 16) << (b + FPM_BIT - 8));
+}
+#endif
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/olsr.c olsrd-f7757d63a5d0/src/olsr.c
--- olsrd-a5b9cf969979/src/olsr.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/olsr.c	2008-02-29 10:50:43.000000000 +0100
@@ -555,25 +555,32 @@
 
 
 /**
- *Wrapper for malloc(3) that does error-checking
+ * Wrapper for malloc(3) that does error-checking
  *
- *@param size the number of bytes to allocalte
- *@param caller a string identifying the caller for
- *use in error messaging
+ * @param size the number of bytes to allocalte
+ * @param caller a string identifying the caller for
+ * use in error messaging
  *
- *@return a void pointer to the memory allocated
+ * @return a void pointer to the memory allocated
  */
 void *
 olsr_malloc(size_t size, const char *id)
 {
-  void *ptr = malloc(size);
-  if(ptr == 0) 
-    {
+  void *ptr;
+
+  /*
+   * Not all the callers do a proper cleaning of memory.
+   * Clean it on behalf of those.
+   */
+  ptr = calloc(1, size);
+
+  if (!ptr) {
       const char * const err_msg = strerror(errno);
       OLSR_PRINTF(1, "OUT OF MEMORY: %s\n", err_msg);
       olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %s\n", err_msg);
       olsr_exit(id, EXIT_FAILURE);
-    }
+  }
+
   return ptr;
 }
 
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/packet.h olsrd-f7757d63a5d0/src/packet.h
--- olsrd-a5b9cf969979/src/packet.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/packet.h	2008-02-29 10:50:43.000000000 +0100
@@ -43,13 +43,19 @@
 
 #include "olsr_protocol.h"
 #include "interfaces.h"
+#include "fpm.h"
 
 struct hello_neighbor
 {
   olsr_u8_t             status;
   olsr_u8_t             link;
+#ifdef USE_FPM
+  fpm                   link_quality;
+  fpm                   neigh_link_quality;
+#else
   double                link_quality;
   double                neigh_link_quality;
+#endif
   union olsr_ip_addr    main_address;
   union olsr_ip_addr    address;
   struct hello_neighbor *next;
@@ -70,8 +76,13 @@
 
 struct tc_mpr_addr
 {
+#ifdef USE_FPM
+  fpm                link_quality;
+  fpm                neigh_link_quality;
+#else
   double             link_quality;
   double             neigh_link_quality;
+#endif
   union olsr_ip_addr address;
   struct tc_mpr_addr *next;
 };
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/parser.c olsrd-f7757d63a5d0/src/parser.c
--- olsrd-a5b9cf969979/src/parser.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/parser.c	2008-02-29 10:50:43.000000000 +0100
@@ -71,6 +71,7 @@
 unsigned int cpu_overload_exit = 0;
 
 struct parse_function_entry *parse_functions;
+struct preprocessor_function_entry *preprocessor_functions;
 
 static char inbuf[MAXMESSAGESIZE+1];
 
@@ -154,6 +155,59 @@
   return 0;
 }
 
+void
+olsr_preprocessor_add_function(preprocessor_function *function)
+{
+  struct preprocessor_function_entry *new_entry;
+
+  OLSR_PRINTF(3, "Parser: registering preprocessor\n");
+ 
+
+  new_entry = olsr_malloc(sizeof(struct preprocessor_function_entry), "Register preprocessor function");
+
+  new_entry->function = function;
+
+  /* Queue */
+  new_entry->next = preprocessor_functions;
+  preprocessor_functions = new_entry;
+
+  OLSR_PRINTF(3, "Registered preprocessor function\n");
+
+}
+
+
+
+int
+olsr_preprocessor_remove_function(preprocessor_function *function)
+{
+  struct preprocessor_function_entry *entry, *prev;
+
+  entry = preprocessor_functions;
+  prev = NULL;
+
+  while(entry)
+    {
+      if(entry->function == function)
+	{
+	  if(entry == preprocessor_functions)
+	    {
+		  preprocessor_functions = entry->next;
+	    }
+	  else
+	    {
+	      prev->next = entry->next;
+	    }
+	  free(entry);
+	  return 1;
+	}
+
+      prev = entry;
+      entry = entry->next;
+    }
+
+  return 0;
+}
+
 
 /**
  *Process a newly received OLSR packet. Checks the type
@@ -388,6 +442,9 @@
 {
   struct interface *olsr_in_if;
   union olsr_ip_addr from_addr;
+  struct preprocessor_function_entry *entry;
+  char *packet;
+  
   cpu_overload_exit = 0;
   
   for (;;) 
@@ -460,12 +517,26 @@
 	  return ;
 	}
 
+      // call preprocessors
+      entry = preprocessor_functions;
+      packet = &inbuf[0];
+      
+      while(entry)
+        {
+	      packet = entry->function(packet, olsr_in_if, &from_addr, &cc);
+	      // discard package ?
+	      if (packet == NULL) {
+	        return;
+	      }
+	      entry = entry->next;
+        }
+      
       /*
        * &from - sender
        * &inbuf.olsr 
        * cc - bytes read
        */
-      parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
+      parse_packet((struct olsr *)packet, cc, olsr_in_if, &from_addr);
     
     }
 }
@@ -490,6 +561,8 @@
   struct interface *olsr_in_if;
   union olsr_ip_addr from_addr;
   olsr_u16_t pcklen;
+  struct preprocessor_function_entry *entry;
+  char *packet;
 
   /* Host emulator receives IP address first to emulate
      direct link */
@@ -559,6 +632,20 @@
       return;
     }
   
+  // call preprocessors
+  entry = preprocessor_functions;
+  packet = &inbuf[0];
+  
+  while(entry)
+    {
+      packet = entry->function(packet, olsr_in_if, &from_addr, &cc);
+      // discard package ?
+      if (packet == NULL) {
+        return;
+      }
+      entry = entry->next;
+    }
+  
   /*
    * &from - sender
    * &inbuf.olsr 
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/parser.h olsrd-f7757d63a5d0/src/parser.h
--- olsrd-a5b9cf969979/src/parser.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/parser.h	2008-02-29 10:50:43.000000000 +0100
@@ -57,9 +57,18 @@
   struct parse_function_entry *next;
 };
 
-
 extern struct parse_function_entry *parse_functions;
 
+typedef char *preprocessor_function(char *packet, struct interface *, union olsr_ip_addr *, int *length);
+
+struct preprocessor_function_entry
+{
+  preprocessor_function *function;
+  struct preprocessor_function_entry *next;
+};
+
+extern struct preprocessor_function_entry *preprocessor_functions;
+
 void
 parser_set_disp_pack_in(olsr_bool);
 
@@ -79,6 +88,12 @@
 olsr_parser_remove_function(parse_function, olsr_u32_t, int);
 
 void
+olsr_preprocessor_add_function(preprocessor_function);
+
+int
+olsr_preprocessor_remove_function(preprocessor_function);
+
+void
 parse_packet(struct olsr *, int, struct interface *, union olsr_ip_addr *);
 
 #endif
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/process_package.c olsrd-f7757d63a5d0/src/process_package.c
--- olsrd-a5b9cf969979/src/process_package.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/process_package.c	2008-02-29 10:50:43.000000000 +0100
@@ -137,7 +137,11 @@
 
                       if (walker->neighbor == neighbor)
                         {
+#ifdef USE_FPM
+                          walker->path_link_quality = itofpm(0);
+#else
                           walker->path_link_quality = 0.0;
+#endif
                         }
                     }
                 }
@@ -236,7 +240,11 @@
 
                   if (walker->neighbor == neighbor)
                     {
+#ifdef USE_FPM
+                      fpm new_second_hop_link_quality, new_path_link_quality;
+#else
                       double new_second_hop_link_quality, new_path_link_quality;
+#endif
 
                       // path link quality = link quality between us
                       // and our one-hop neighbor x link quality between
@@ -253,16 +261,28 @@
                       // the link quality between the 1-hop neighbour and the
                       // 2-hop neighbour
 
+#ifdef USE_FPM
+                      new_second_hop_link_quality = 
+                        fpmmul(message_neighbors->link_quality,
+                               message_neighbors->neigh_link_quality);
+#else
                       new_second_hop_link_quality = 
                         message_neighbors->link_quality *
                         message_neighbors->neigh_link_quality;
+#endif
 
                       // the total quality for the route
                       // "us --- 1-hop --- 2-hop"
 
+#ifdef USE_FPM
+                      new_path_link_quality =
+                        fpmmul(new_second_hop_link_quality,
+                        fpmmul(lnk->loss_link_quality, lnk->neigh_link_quality));
+#else
                       new_path_link_quality =
                         new_second_hop_link_quality *
                         lnk->loss_link_quality * lnk->neigh_link_quality;
+#endif
 
                       // Only copy the link quality if it is better than what we have
                       // for this 2-hop neighbor
@@ -312,21 +332,34 @@
 
                   if (walker->neighbor == neighbor)
                     {
+#ifdef USE_FPM
+                      fpm saved_lq, rel_lq;
+#else
                       double saved_lq, rel_lq;
+#endif
 
                       // saved previous total link quality
 
                       saved_lq = walker->saved_path_link_quality;
 
+#ifdef USE_FPM
+                      if (saved_lq == itofpm(0))
+                        saved_lq = itofpm(-1);
+#else
                       if (saved_lq == 0.0)
                         saved_lq = -1.0;
+#endif
 
                       // if the link cost has changed by more than 10
                       // percent, signal
 
+#ifdef USE_FPM
+                      rel_lq = fpmdiv(walker->path_link_quality, saved_lq);
+#else
                       rel_lq = walker->path_link_quality / saved_lq;
+#endif
 
-                      if (rel_lq > 1.1 || rel_lq < 0.9)
+                      if (rel_lq > CEIL_LQDIFF || rel_lq < FLOOR_LQDIFF)
                         {
                           walker->saved_path_link_quality =
                             walker->path_link_quality;
@@ -362,9 +395,15 @@
 
   list_of_1_neighbors->neighbor = neighbor;
 
+#ifdef USE_FPM
+  list_of_1_neighbors->path_link_quality = itofpm(0);
+  list_of_1_neighbors->saved_path_link_quality = itofpm(0);
+  list_of_1_neighbors->second_hop_link_quality = itofpm(0);
+#else
   list_of_1_neighbors->path_link_quality = 0.0;
   list_of_1_neighbors->saved_path_link_quality = 0.0;
   list_of_1_neighbors->second_hop_link_quality = 0.0;
+#endif
 
   /* Queue */
   two_hop_neighbor->neighbor_2_nblist.next->prev = list_of_1_neighbors;
@@ -511,8 +550,13 @@
 
   if (olsr_cnf->lq_level > 0)
     {
+#ifdef USE_FPM
+      fpm saved_lq;
+      fpm rel_lq;
+#else
       double saved_lq;
       double rel_lq;
+#endif
       struct hello_neighbor *walker;
       // just in case our neighbor has changed its HELLO interval
       olsr_update_packet_loss_hello_int(lnk, message->htime);
@@ -527,8 +571,13 @@
 
       saved_lq = lnk->saved_neigh_link_quality;
 
+#ifdef USE_FPM
+      if (saved_lq == itofpm(0))
+        saved_lq = itofpm(-1);
+#else
       if (saved_lq == 0.0)
         saved_lq = -1.0;
+#endif
 
       // memorize our neighbour's idea of the link quality, so that we
       // know the link quality in both directions
@@ -537,14 +586,22 @@
         lnk->neigh_link_quality = walker->link_quality;
 
       else
+#ifdef USE_FPM
+        lnk->neigh_link_quality = itofpm(0);
+#else
         lnk->neigh_link_quality = 0.0;
+#endif
 
       // if the link quality has changed by more than 10 percent,
       // print the new link quality table
 
+#ifdef USE_FPM
+      rel_lq = fpmdiv(lnk->neigh_link_quality, saved_lq);
+#else
       rel_lq = lnk->neigh_link_quality / saved_lq;
+#endif
 
-      if (rel_lq > 1.1 || rel_lq < 0.9)
+      if (rel_lq > CEIL_LQDIFF || rel_lq < FLOOR_LQDIFF)
         {
           lnk->saved_neigh_link_quality = lnk->neigh_link_quality;
 
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/routing_table.c olsrd-f7757d63a5d0/src/routing_table.c
--- olsrd-a5b9cf969979/src/routing_table.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/routing_table.c	2008-02-29 10:50:43.000000000 +0100
@@ -426,10 +426,17 @@
 static olsr_bool
 olsr_cmp_rtp(const struct rt_path *rtp1, const struct rt_path *rtp2, const struct rt_path *inetgw)
 {
+#ifdef USE_FPM
+    fpm etx1 = rtp1->rtp_metric.etx;
+    fpm etx2 = rtp2->rtp_metric.etx;
+    if (inetgw == rtp1) etx1 = fpmmul(etx1, ftofpm(olsr_cnf->lq_nat_thresh));
+    if (inetgw == rtp2) etx2 = fpmmul(etx2, ftofpm(olsr_cnf->lq_nat_thresh));
+#else
     float etx1 = rtp1->rtp_metric.etx;
     float etx2 = rtp2->rtp_metric.etx;
     if (inetgw == rtp1) etx1 *= olsr_cnf->lq_nat_thresh;
     if (inetgw == rtp2) etx2 *= olsr_cnf->lq_nat_thresh;
+#endif
 
     /* etx comes first */
     if (etx1 < etx2) {
@@ -647,12 +654,12 @@
 
   snprintf(buff, sizeof(buff),
            "%s/%u from %s via %s, "
-           "etx %.3f, metric %u, v %u",
+           "etx %s, metric %u, v %u",
            olsr_ip_to_string(&prefixstr, &rt->rt_dst.prefix),
            rt->rt_dst.prefix_len,
            olsr_ip_to_string(&origstr, &rtp->rtp_originator),
            olsr_ip_to_string(&gwstr, &rtp->rtp_nexthop.gateway),
-           rtp->rtp_metric.etx,
+           etxtoa(rtp->rtp_metric.etx),
            rtp->rtp_metric.hops,
            rtp->rtp_version);
 
@@ -691,9 +698,9 @@
          rtp_tree_node != NULL;
          rtp_tree_node = avl_walk_next_c(rtp_tree_node)) {
       const struct rt_path * const rtp = rtp_tree_node->data;
-      printf("\tfrom %s, etx %.3f, metric %u, via %s, %s, v %u\n",
+      printf("\tfrom %s, etx %s, metric %u, via %s, %s, v %u\n",
              olsr_ip_to_string(&origstr, &rtp->rtp_originator),
-             rtp->rtp_metric.etx,
+             etxtoa(rtp->rtp_metric.etx),
              rtp->rtp_metric.hops,
              olsr_ip_to_string(&gwstr, &rtp->rtp_nexthop.gateway),
              if_ifwithindex_name(rt->rt_nexthop.iif_index),
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/routing_table.h olsrd-f7757d63a5d0/src/routing_table.h
--- olsrd-a5b9cf969979/src/routing_table.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/routing_table.h	2008-02-29 10:50:43.000000000 +0100
@@ -64,7 +64,11 @@
 /* a composite metric is used for path selection */
 struct rt_metric
 {
+#ifdef USE_FPM
+  fpm                   etx;
+#else
   float                 etx;
+#endif
   olsr_u32_t 	        hops;
 };
 
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/tc_set.c olsrd-f7757d63a5d0/src/tc_set.c
--- olsrd-a5b9cf969979/src/tc_set.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/tc_set.c	2008-02-29 10:50:43.000000000 +0100
@@ -287,12 +287,12 @@
   struct tc_entry *tc = tc_edge->tc;
 
   snprintf(buf, sizeof(buf),
-           "%s > %s, lq %.3f, inv-lq %.3f, etx %.3f",
+           "%s > %s, lq %s, inv-lq %s, etx %s",
            olsr_ip_to_string(&addrbuf, &tc->addr),
            olsr_ip_to_string(&dstbuf, &tc_edge->T_dest_addr),
-           tc_edge->link_quality,
-           tc_edge->inverse_link_quality,
-           tc_edge->etx);
+           fpmtoa(tc_edge->link_quality),
+           fpmtoa(tc_edge->inverse_link_quality),
+           etxtoa(tc_edge->etx));
 
   return buf;
 }
@@ -326,11 +326,15 @@
     return;
   }
 
-  if (tc_edge->link_quality < MIN_LINK_QUALITY &&
+  if (tc_edge->link_quality < MIN_LINK_QUALITY ||
       tc_edge->inverse_link_quality < MIN_LINK_QUALITY) {
     tc_edge->etx = INFINITE_ETX;
   } else {
+#ifdef USE_FPM
+    tc_edge->etx = fpmdiv(itofpm(1), fpmmul(tc_edge->link_quality, tc_edge->inverse_link_quality));
+#else
     tc_edge->etx = 1.0 / (tc_edge->link_quality * tc_edge->inverse_link_quality);
+#endif
   }
 }
 
@@ -343,7 +347,12 @@
 struct tc_edge_entry *
 olsr_add_tc_edge_entry(struct tc_entry *tc, union olsr_ip_addr *addr,
                        olsr_u16_t ansn, unsigned int vtime,
-                       float link_quality, float neigh_link_quality)
+#ifdef USE_FPM
+                       fpm link_quality, fpm neigh_link_quality
+#else
+                       float link_quality, float neigh_link_quality
+#endif
+                       )
 {
 #if !defined(NODEBUG) && defined(DEBUG)
   struct ipaddr_str buf;
@@ -373,8 +382,13 @@
      * Set the link quality to 1.0 to mimikry a hopcount alike
      * behaviour for nodes not supporting the LQ extensions.
      */
+#ifdef USE_FPM
+    tc_edge->link_quality = itofpm(1);
+    tc_edge->inverse_link_quality = itofpm(1);
+#else
     tc_edge->link_quality = 1.0;
     tc_edge->inverse_link_quality = 1.0;
+#endif
   }
 
   /*
@@ -387,10 +401,6 @@
    */
   tc_edge->tc = tc;
 
-#ifdef DEBUG
-  OLSR_PRINTF(1, "TC: add edge entry %s\n", olsr_tc_edge_to_string(tc_edge));
-#endif
-
   /*
    * Check if the neighboring router and the inverse edge is in the lsdb.
    * Create short cuts to the inverse edge for faster SPF execution.
@@ -423,6 +433,10 @@
    */
   olsr_calc_tc_edge_entry_etx(tc_edge);
 
+#ifdef DEBUG
+  OLSR_PRINTF(1, "TC: add edge entry %s\n", olsr_tc_edge_to_string(tc_edge));
+#endif
+
   return tc_edge;
 }
 
@@ -514,23 +528,43 @@
  * Determine if a etx change was more than 10%
  * Need to know this for triggering a SPF calculation.
  */
+#ifdef USE_FPM
+static olsr_bool
+olsr_etx_significant_change(fpm etx1, fpm etx2)
+{
+  fpm rel_lq;
+
+  if (etx1 == ZERO_ETX || etx2 == ZERO_ETX) {
+    return OLSR_TRUE;
+  }
+
+  rel_lq = fpmdiv(etx1, etx2);
+
+  if (rel_lq > CEIL_LQDIFF || rel_lq < FLOOR_LQDIFF) {
+    return OLSR_TRUE;
+  }
+
+  return OLSR_FALSE;
+}
+#else
 static olsr_bool
 olsr_etx_significant_change(float etx1, float etx2)
 {
   float rel_lq;
 
-  if (etx1 == 0.0 || etx2 == 0.0) {
+  if (etx1 == ZERO_ETX || etx2 == ZERO_ETX) {
     return OLSR_TRUE;
   }
 
   rel_lq = etx1 / etx2;
 
-  if (rel_lq > 1.1 || rel_lq < 0.9) {
+  if (rel_lq > CEIL_LQDIFF || rel_lq < FLOOR_LQDIFF) {
     return OLSR_TRUE;
   }
 
   return OLSR_FALSE;
 }
+#endif
 
 /**
  * Update an edge registered on an entry.
@@ -546,7 +580,11 @@
                     olsr_u8_t type, const unsigned char **curr)
 {
   struct tc_edge_entry *tc_edge;
+#ifdef USE_FPM
+  fpm link_quality, neigh_link_quality;
+#else
   double link_quality, neigh_link_quality;
+#endif
   union olsr_ip_addr neighbor;
   int edge_change;
 
@@ -563,8 +601,13 @@
     pkt_get_lq(curr, &neigh_link_quality);
     pkt_ignore_u16(curr);
   } else {
+#ifdef USE_FPM
+    link_quality = itofpm(1);
+    neigh_link_quality = itofpm(1);
+#else
     link_quality = 1.0;
     neigh_link_quality = 1.0;
+#endif
   }
 
   /* First check if we know this edge */
@@ -710,31 +753,42 @@
 
   OLSR_PRINTF(1,
               "\n--- %02d:%02d:%02d.%02d ------------------------------------------------- TOPOLOGY\n\n"
-              "%-*s %-*s %-5s  %-5s  %s\n",
+              "%-*s %-*s %-5s  %-5s  %s  %s\n",
               nowtm->tm_hour, nowtm->tm_min, nowtm->tm_sec, (int)now.tv_usec / 10000,
-              ipwidth, "Source IP addr", ipwidth, "Dest IP addr", "LQ", "ILQ", "ETX");
+              ipwidth, "Source IP addr", ipwidth, "Dest IP addr", "LQ", "ILQ", "ETX", "UP");
 
   OLSR_FOR_ALL_TC_ENTRIES(tc) {
     struct tc_edge_entry *tc_edge;
     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
       struct ipaddr_str addrbuf, dstaddrbuf;
-      OLSR_PRINTF(1, "%-*s %-*s  %5.3f  %5.3f  %.2f\n",
+      OLSR_PRINTF(1, "%-*s %-*s  %s  %s  %s  %s\n",
                   ipwidth, olsr_ip_to_string(&addrbuf, &tc->addr),
                   ipwidth, olsr_ip_to_string(&dstaddrbuf, &tc_edge->T_dest_addr),
-                  tc_edge->link_quality,
-                  tc_edge->inverse_link_quality,
-                  olsr_calc_tc_etx(tc_edge));
+                  fpmtoa(tc_edge->link_quality),
+                  fpmtoa(tc_edge->inverse_link_quality),
+                  etxtoa(olsr_calc_tc_etx(tc_edge)),
+                  tc_edge->flags & OLSR_TC_EDGE_DOWN ? "DOWN" : "UP");
     } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
 #endif
 }
 
-float olsr_calc_tc_etx(const struct tc_edge_entry *tc_edge)
+#ifdef USE_FPM
+fpm
+#else
+float
+#endif
+olsr_calc_tc_etx(const struct tc_edge_entry *tc_edge)
 {
   return tc_edge->link_quality < MIN_LINK_QUALITY ||
          tc_edge->inverse_link_quality < MIN_LINK_QUALITY
+#ifdef USE_FPM
+             ? itofpm(0)
+             : fpmdiv(itofpm(1), fpmmul(tc_edge->link_quality, tc_edge->inverse_link_quality));
+#else
              ? 0.0
              : 1.0 / (tc_edge->link_quality * tc_edge->inverse_link_quality);
+#endif
 }
 
 /*
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/tc_set.h olsrd-f7757d63a5d0/src/tc_set.h
--- olsrd-a5b9cf969979/src/tc_set.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/tc_set.h	2008-02-29 10:50:43.000000000 +0100
@@ -63,9 +63,15 @@
   clock_t            T_time; /* expiration timer, timer_node key */
   olsr_u16_t         T_seq; /* sequence number of the advertised neighbor set */
   olsr_u16_t         flags; /* misc flags */
+#ifdef USE_FPM
+  fpm                etx; /* metric used for SPF calculation */
+  fpm                link_quality;
+  fpm                inverse_link_quality;
+#else
   float              etx; /* metric used for SPF calculation */
   float              link_quality;
   float              inverse_link_quality;
+#endif
 };
 
 #define OLSR_TC_EDGE_DOWN (1 << 0) /* this edge is down */
@@ -84,7 +90,11 @@
   struct avl_tree    edge_tree; /* subtree for edges */
   struct avl_tree    prefix_tree; /* subtree for prefixes */
   struct link_entry  *next_hop; /* SPF calculated link to the 1st hop neighbor */
+#ifdef USE_FPM
+  fpm                path_etx; /* SPF calculated distance, cand_tree_node key */
+#else
   float              path_etx; /* SPF calculated distance, cand_tree_node key */
+#endif
   olsr_u16_t         msg_seq; /* sequence number of the tc message */
   olsr_u8_t          msg_hops; /* hopcount as per the tc message */
   olsr_u8_t          hops; /* SPF calculated hopcount */
@@ -142,11 +152,22 @@
                                           union olsr_ip_addr *);
 struct tc_edge_entry *olsr_add_tc_edge_entry(struct tc_entry *,
                                              union olsr_ip_addr *, olsr_u16_t,
-                                             unsigned int, float, float);
+                                             unsigned int,
+#ifdef USE_FPM
+                                             fpm, fpm
+#else
+                                             float, float
+#endif
+                                             );
 void olsr_delete_tc_entry(struct tc_entry *);
 void olsr_delete_tc_edge_entry(struct tc_edge_entry *);
 void olsr_calc_tc_edge_entry_etx(struct tc_edge_entry *);
-float olsr_calc_tc_etx(const struct tc_edge_entry *);
+#ifdef USE_FPM
+fpm
+#else
+float
+#endif
+olsr_calc_tc_etx(const struct tc_edge_entry *);
 void olsr_set_tc_edge_timer(struct tc_edge_entry *, unsigned int);
 
 #endif
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/two_hop_neighbor_table.c olsrd-f7757d63a5d0/src/two_hop_neighbor_table.c
--- olsrd-a5b9cf969979/src/two_hop_neighbor_table.c	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/two_hop_neighbor_table.c	2008-02-29 10:50:43.000000000 +0100
@@ -262,9 +262,9 @@
         } else {
           OLSR_PRINTF(1, "                 ");
         }
-        OLSR_PRINTF(1, "%-15s  %5.3f\n",
+        OLSR_PRINTF(1, "%-15s  %s\n",
                     olsr_ip_to_string(&buf, &entry->neighbor->neighbor_main_addr),
-                    entry->path_link_quality);
+                    fpmtoa(entry->path_link_quality));
       }
     }
   }
diff --exclude='.hg*' -Nur olsrd-a5b9cf969979/src/two_hop_neighbor_table.h olsrd-f7757d63a5d0/src/two_hop_neighbor_table.h
--- olsrd-a5b9cf969979/src/two_hop_neighbor_table.h	2008-02-06 19:32:49.000000000 +0100
+++ olsrd-f7757d63a5d0/src/two_hop_neighbor_table.h	2008-02-29 10:50:43.000000000 +0100
@@ -44,6 +44,7 @@
 
 #include "defs.h"
 #include "hashing.h"
+#include "fpm.h"
 
 #define	NB2S_COVERED 	0x1		/* node has been covered by a MPR */
 
@@ -51,9 +52,15 @@
 struct neighbor_list_entry 
 {
   struct	neighbor_entry *neighbor;
+#ifdef USE_FPM
+  fpm           second_hop_link_quality;
+  fpm           path_link_quality;
+  fpm           saved_path_link_quality;
+#else
   double        second_hop_link_quality;
   double        path_link_quality;
   double        saved_path_link_quality;
+#endif
   struct	neighbor_list_entry *next;
   struct	neighbor_list_entry *prev;
 };
