From Sven-Ola Tuecke <sven-ola@gmx.de>: add support for fixedpoint math
authorHannes Gredler <hannes@gredler.at>
Thu, 14 Feb 2008 08:56:01 +0000 (09:56 +0100)
committerHannes Gredler <hannes@gredler.at>
Thu, 14 Feb 2008 08:56:01 +0000 (09:56 +0100)
Fixed point math replaces floating point calculations by integer counterparts.
The 20 higher bits of a typical 32 bit hold the digits before the decimal
point > 1.0, the lower 12 bits hold the digits after the decimal point. An
old trick, e.g. used in gaming to speed up calculations, because long (+-*/)
long is always faster than float (+-*/). Of course, all calculations and
automatic number conversions have to be found and adpated.
To help in debugging, added and #ifdef USE_FPM to toggle betwenn FPM and
normal maths. One can remove that at a later stage if we are sure it works
correct. For this, I added CPPFLAGS+=USE_FPM to the central Makefile.inc.
Also critical: When using 20+12 bits, one have to check for overflows and
underflows. This is done by a number of assert() statements active only if
you compile with "make DEBUG=1". The olsrd compiled in this way will of
course save no CPU cycles.

27 files changed:
Makefile.inc
lib/bmf/src/NetworkInterfaces.c
lib/dot_draw/src/olsrd_dot_draw.c
lib/httpinfo/src/olsrd_httpinfo.c
lib/nameservice/src/mapwrite.c
lib/nameservice/src/nameservice.c
lib/tas/src/plugin.c
lib/txtinfo/src/olsrd_txtinfo.c
src/fpm.c [new file with mode: 0644]
src/fpm.h [new file with mode: 0644]
src/hysteresis.c
src/hysteresis.h
src/link_set.c
src/link_set.h
src/lq_mpr.c
src/lq_packet.c
src/lq_packet.h
src/lq_route.c
src/lq_route.h
src/packet.h
src/process_package.c
src/routing_table.c
src/routing_table.h
src/tc_set.c
src/tc_set.h
src/two_hop_neighbor_table.c
src/two_hop_neighbor_table.h

index 05d5489..4147022 100644 (file)
@@ -150,6 +150,9 @@ CPPFLAGS += $(EXTRA_CPPFLAGS)
 # 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)
index 42a1291..0969cbf 100644 (file)
@@ -402,10 +402,17 @@ void RestoreSpoofFilter(void)
  * ------------------------------------------------------------------------- */
 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);
@@ -742,8 +749,13 @@ void FindNeighbors(
 #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 +765,13 @@ void FindNeighbors(
       {
         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 +842,19 @@ void FindNeighbors(
 
       /* 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,8 +905,13 @@ void FindNeighbors(
             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 */
@@ -918,8 +949,13 @@ void FindNeighbors(
           if (tc_edge != NULL)
           {
             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)
             {
index 305631b..666350d 100644 (file)
@@ -154,7 +154,11 @@ static void
 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 @@ ipc_print_neigh_link(const struct neighbor_entry *neighbor)
     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,
+               olsr_etx_to_string(etx),
                style);
   
   if (neighbor->is_mpr) {
@@ -339,10 +343,10 @@ ipc_print_tc_link(const struct tc_entry *entry, const struct tc_edge_entry *dst_
 {
   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));
+               olsr_etx_to_string(olsr_calc_tc_etx(dst_entry)));
 }
 
 
index d43116c..ba9001a 100644 (file)
@@ -763,8 +763,8 @@ static int build_route(char *buf, olsr_u32_t bufsize, const struct rt_entry * rt
                    "<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>",
+                   olsr_etx_to_string(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 @@ static int build_neigh_body(char *buf, olsr_u32_t bufsize)
     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>", olsr_etx_to_string(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",
+                       olsr_etx_to_string(link->loss_link_quality),
                        link->lost_packets,
                        link->total_packets,
-                       link->neigh_link_quality,
-                       olsr_calc_link_etx(link));
+                       olsr_etx_to_string(link->neigh_link_quality),
+                       olsr_etx_to_string(olsr_calc_link_etx(link)));
     }
     size += snprintf(&buf[size], bufsize-size, "</tr>\n");
   }
@@ -1059,12 +1059,12 @@ static int build_topo_body(char *buf, olsr_u32_t bufsize)
           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",
+                               olsr_etx_to_string(tc_edge->link_quality),
+                               olsr_etx_to_string(tc_edge->inverse_link_quality),
+                               olsr_etx_to_string(olsr_calc_tc_etx(tc_edge)));
           }
           size += snprintf(&buf[size], bufsize-size, "</tr>\n");
 
index 67774d8..1545616 100644 (file)
@@ -167,13 +167,12 @@ void mapwrite_work(FILE* fmap)
       /*
        * 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,
+            olsr_etx_to_string(tc_edge->link_quality),
+            olsr_etx_to_string(tc_edge->inverse_link_quality),
+            olsr_etx_to_string(olsr_calc_tc_etx(tc_edge)),
             lla, llb))
       {
         return;
@@ -184,13 +183,12 @@ void mapwrite_work(FILE* fmap)
       /*
        * 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))
+            olsr_etx_to_string(tc_edge->link_quality),
+            olsr_etx_to_string(tc_edge->inverse_link_quality),
+            olsr_etx_to_string(olsr_calc_tc_etx(tc_edge))))
       {
         return;
       }
index dedb199..329067d 100644 (file)
@@ -1196,9 +1196,9 @@ select_best_nameserver(struct rt_entry **rt)
                        /*
                         * 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);
+                                               olsr_etx_to_string(rt1->rt_best->rtp_metric.etx));
 
                        rt[nameserver_idx] = rt2;
                        rt[nameserver_idx+1] = rt1;
@@ -1248,9 +1248,9 @@ write_resolv_file(void)
 
                                /* 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);
+                                                       olsr_etx_to_string(route->rt_best->rtp_metric.etx));
 
                                /* find the closet one */
                                select_best_nameserver(nameserver_routes);
index 6e62c9b..a679773 100644 (file)
@@ -105,19 +105,25 @@ static void __attribute__((constructor)) banner(void)
 
 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);
+           olsr_etx_to_string(iterLinkTab->L_link_quality),
+           olsr_etx_to_string(iterLinkTab->loss_link_quality),
+           olsr_etx_to_string(iterLinkTab->neigh_link_quality),
+           olsr_etx_to_string(etx));
 
   iterLinkTab = iterLinkTab->next;
 
@@ -281,9 +287,9 @@ int iterTcTabNext(char *buff, int len)
 
   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));
+                   olsr_etx_to_string(olsr_calc_tc_etx(tc_edge)));
 
     if (res < len)
       buff += res;
index edcc98f..602c7e5 100644 (file)
@@ -308,15 +308,15 @@ static void ipc_print_neigh_link(void)
     /* 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,
+                   olsr_etx_to_string(link->L_link_quality)
+                   olsr_etx_to_string(link->loss_link_quality),
                    link->lost_packets, 
                    link->total_packets,
-                   link->neigh_link_quality
-                   olsr_calc_link_etx(link));
+                   olsr_etx_to_string(link->neigh_link_quality)
+                   olsr_etx_to_string(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 @@ static void ipc_print_routes(void)
 
         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,
+                   olsr_etx_to_string(rt->rt_best->rtp_metric.etx),
                    if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));
     }
     ipc_sendf("\n");
@@ -385,12 +385,12 @@ static void ipc_print_topology(void)
         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));
+                       olsr_etx_to_string(tc_edge->link_quality),
+                       olsr_etx_to_string(tc_edge->inverse_link_quality),
+                       olsr_etx_to_string(olsr_calc_tc_etx(tc_edge)));
 
         } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
     } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
diff --git a/src/fpm.c b/src/fpm.c
new file mode 100644 (file)
index 0000000..5efe545
--- /dev/null
+++ b/src/fpm.c
@@ -0,0 +1,181 @@
+/*
+ * 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"
+
+#if !defined(NDEBUG) && defined(USE_FPM)
+
+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 /* !defined(NDEBUG) && defined(USE_FPM) */
+
+const char *olsr_etx_to_string(
+#ifdef USE_FPM
+fpm etx
+#else
+float etx
+#endif
+)
+{
+  static int idx = 0;
+  static char ret[4][20];
+
+  if (etx >= INFINITE_ETX) {
+    return "INF";
+  }
+  idx = (idx + 1) % (sizeof(ret) / sizeof(ret[0]));
+#ifdef USE_FPM
+  snprintf(ret[idx], sizeof(ret[0]), "%lld.%lld", (long long)((sfpm)etx >> FPM_BIT),
+           (long long)(100 * (ufpm) ((sfpm)(etx) & FPM_MSK) >> FPM_BIT));
+#else
+  snprintf(ret[idx], sizeof(ret[0]), "%.3f", etx);
+#endif
+  return ret[idx];
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff --git a/src/fpm.h b/src/fpm.h
new file mode 100644 (file)
index 0000000..6ae82e4
--- /dev/null
+++ b/src/fpm.h
@@ -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)
+
+#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
+
+#endif /* USE_FPM */
+
+const char *olsr_etx_to_string(
+#ifdef USE_FPM
+fpm
+#else
+float
+#endif
+);
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
index 58d1684..698a149 100644 (file)
 #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 @@ update_hysteresis_incoming(union olsr_ip_addr *remote, struct interface *local,
 #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), olsr_etx_to_string(lnk->L_link_quality));
 #endif
 
       /* 
@@ -198,10 +220,14 @@ update_hysteresis_incoming(union olsr_ip_addr *remote, struct interface *local,
            {
              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), olsr_etx_to_string(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++;
index aae3c1f..7ce66ab 100644 (file)
 
 #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);
index f9ac507..f989090 100644 (file)
@@ -241,7 +241,11 @@ get_best_link_to_neighbor(const union olsr_ip_addr *remote)
   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 = ftofpm(-1.0);
+#else
   float curr_lq = -1.0;
+#endif
   
   // main address lookup
 
@@ -305,12 +309,20 @@ get_best_link_to_neighbor(const union olsr_ip_addr *remote)
 
     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 @@ static void set_loss_link_multiplier(struct link_entry *entry)
   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 @@ static void set_loss_link_multiplier(struct link_entry *entry)
     // 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 @@ add_link_entry(const union olsr_ip_addr *local,
       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 @@ add_link_entry(const union olsr_ip_addr *local,
       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 @@ add_link_entry(const union olsr_ip_addr *local,
 
   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 @@ olsr_time_out_hysteresis(void)
           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),
+                      olsr_etx_to_string(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 @@ void olsr_print_link_set(void)
   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,
+                olsr_etx_to_string(walker->L_link_quality),
+                olsr_etx_to_string(walker->loss_link_quality),
                walker->lost_packets,
                 walker->total_packets,
-               walker->neigh_link_quality,
-                etx);
+               olsr_etx_to_string(walker->neigh_link_quality),
+                olsr_etx_to_string(etx));
   }
 #endif
 }
@@ -992,7 +1047,11 @@ static void update_packet_loss_worker(struct link_entry *entry, int lost)
 {
   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 @@ static void update_packet_loss_worker(struct link_entry *entry, int lost)
 
   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 @@ void olsr_update_dijkstra_link_qualities(void)
   }
 }
 
-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
 }
index 9ddd647..d7034ac 100644 (file)
@@ -66,7 +66,11 @@ struct link_entry
   /*
    *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 @@ struct link_entry
   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 @@ olsr_print_link_set(void);
 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
 
index eb49297..ce30d4f 100644 (file)
@@ -51,7 +51,11 @@ void olsr_calculate_lq_mpr(void)
   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 @@ void olsr_calculate_lq_mpr(void)
            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 @@ void olsr_calculate_lq_mpr(void)
              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 @@ void olsr_calculate_lq_mpr(void)
               // 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;
index 1523b6f..3e39300 100644 (file)
@@ -232,8 +232,13 @@ create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
           }
           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 @@ serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
 
               // 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 @@ serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
       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;
index 87f9b5d..868c2f3 100644 (file)
@@ -94,8 +94,13 @@ struct lq_hello_neighbor
 {
   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_s32(const olsr_u8_t **p, olsr_32_t *var)
 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); }
index 1ea0f86..155778a 100644 (file)
@@ -104,9 +104,9 @@ olsr_spf_add_cand_tree (struct avl_tree *tree,
   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);
+              olsr_etx_to_string(tc->path_etx));
 #endif
 
   avl_insert(tree, &tc->cand_tree_node, AVL_DUP);
@@ -126,9 +126,9 @@ olsr_spf_del_cand_tree (struct avl_tree *tree,
 #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);
+              olsr_etx_to_string(tc->path_etx));
 #endif
 
   avl_delete(tree, &tc->cand_tree_node);
@@ -149,10 +149,11 @@ olsr_spf_add_path_list (struct list_node *head, int *path_count,
   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) : "-");
+              olsr_etx_to_string(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 @@ olsr_spf_extract_best (struct avl_tree *tree)
 }
 
 
-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 @@ static void
 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);
+              olsr_etx_to_string(tc->path_etx));
 #endif
 
   /*
@@ -238,7 +231,12 @@ olsr_spf_relax (struct avl_tree *cand_tree, struct tc_entry *tc)
      * 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",
@@ -274,7 +272,8 @@ olsr_spf_relax (struct avl_tree *cand_tree, struct tc_entry *tc)
                   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>",
+                  tc->next_hop ? olsr_ip_to_string(
+                    &nbuf, &tc->next_hop->neighbor_iface_addr) : "<none>",
                   new_tc->hops);
 #endif
 
index b87f327..1ce225b 100644 (file)
 #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
index 9c4fe3a..c8d5cc0 100644 (file)
 
 #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 hello_message
 
 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;
 };
index 4cc6b75..2f922e9 100644 (file)
@@ -137,7 +137,11 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
 
                       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 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
 
                   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 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
                       // 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 @@ process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_me
 
                   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 @@ linking_this_2_entries(struct neighbor_entry *neighbor, struct neighbor_2_entry
 
   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 @@ olsr_hello_tap(struct hello_message *message,
 
   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 @@ olsr_hello_tap(struct hello_message *message,
 
       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 @@ olsr_hello_tap(struct hello_message *message,
         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;
 
index 242a9bb..f897e42 100644 (file)
@@ -426,10 +426,17 @@ olsr_get_nh(const struct rt_entry *rt)
 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 @@ olsr_rtp_to_string(const struct rt_path *rtp)
 
   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,
+           olsr_etx_to_string(rtp->rtp_metric.etx),
            rtp->rtp_metric.hops,
            rtp->rtp_version);
 
@@ -691,9 +698,9 @@ olsr_print_routing_table(const struct avl_tree *tree)
          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,
+             olsr_etx_to_string(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),
index e60468b..06b7c71 100644 (file)
 /* a composite metric is used for path selection */
 struct rt_metric
 {
+#ifdef USE_FPM
+  fpm                   etx;
+#else
   float                 etx;
+#endif
   olsr_u32_t           hops;
 };
 
index d069c2c..ac53584 100644 (file)
@@ -287,12 +287,12 @@ olsr_tc_edge_to_string(struct tc_edge_entry *tc_edge)
   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);
+           olsr_etx_to_string(tc_edge->link_quality),
+           olsr_etx_to_string(tc_edge->inverse_link_quality),
+           olsr_etx_to_string(tc_edge->etx));
 
   return buf;
 }
@@ -326,11 +326,15 @@ olsr_calc_tc_edge_entry_etx(struct tc_edge_entry *tc_edge)
     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 @@ olsr_calc_tc_edge_entry_etx(struct tc_edge_entry *tc_edge)
 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 @@ olsr_add_tc_edge_entry(struct tc_entry *tc, union olsr_ip_addr *addr,
      * 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 @@ olsr_add_tc_edge_entry(struct tc_entry *tc, union olsr_ip_addr *addr,
    */
   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_add_tc_edge_entry(struct tc_entry *tc, union olsr_ip_addr *addr,
    */
   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 @@ olsr_delete_outdated_tc_edges(struct tc_entry *tc, olsr_u16_t ansn)
  * 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_tc_update_edge(struct tc_entry *tc, unsigned int vtime_s, olsr_u16_t ansn,
                     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 @@ olsr_tc_update_edge(struct tc_entry *tc, unsigned int vtime_s, olsr_u16_t ansn,
     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 */
@@ -718,23 +761,33 @@ olsr_print_tc_table(void)
     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\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));
+                  olsr_etx_to_string(tc_edge->link_quality),
+                  olsr_etx_to_string(tc_edge->inverse_link_quality),
+                  olsr_etx_to_string(olsr_calc_tc_etx(tc_edge)));
     } 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
 }
 
 /*
index 4f268d0..e604069 100644 (file)
@@ -63,9 +63,15 @@ struct tc_edge_entry
   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 tc_entry
   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 @@ struct tc_edge_entry *olsr_lookup_tc_edge(struct tc_entry *,
                                           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
index 917f439..0a11545 100644 (file)
@@ -262,9 +262,9 @@ olsr_print_two_hop_neighbor_table(void)
         } 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);
+                    olsr_etx_to_string(entry->path_link_quality));
       }
     }
   }
index a20ab12..04e8c2e 100644 (file)
@@ -44,6 +44,7 @@
 
 #include "defs.h"
 #include "hashing.h"
+#include "fpm.h"
 
 #define        NB2S_COVERED    0x1             /* node has been covered by a MPR */
 
 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;
 };