From Sven-Ola Tuecke: 110-bmf-v152
authorHannes Gredler <hannes@gredler.at>
Fri, 28 Dec 2007 10:14:55 +0000 (11:14 +0100)
committerHannes Gredler <hannes@gredler.at>
Fri, 28 Dec 2007 10:14:55 +0000 (11:14 +0100)
  Grabbed a copy of eric's plugin and adapted that to HEAD

lib/bmf/Makefile
lib/bmf/README_BMF.txt
lib/bmf/src/Address.c
lib/bmf/src/Bmf.c
lib/bmf/src/Bmf.h
lib/bmf/src/NetworkInterfaces.c
lib/bmf/src/NetworkInterfaces.h
lib/bmf/src/olsrd_plugin.c

index 38e03c7..8263408 100644 (file)
@@ -34,7 +34,7 @@
 
 OLSRD_PLUGIN = true
 PLUGIN_NAME =  olsrd_bmf
-PLUGIN_VER =   1.5
+PLUGIN_VER =   1.5.2
 
 TOPDIR = ../..
 include $(TOPDIR)/Makefile.inc
index e49bd0e..b2c3fb7 100644 (file)
@@ -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.1
+Version 1.5.2
 
 1. Introduction
 ---------------
@@ -17,14 +17,14 @@ in the past 3-6 seconds are forwarded.
 2. How to build and install
 ---------------------------
 
-Download the olsr-bmf-v1.5.1.tar.gz file and save it into your OLSRD
+Download the olsr-bmf-v1.5.2.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.1.tar.gz
+  tar -zxvf ./olsr-bmf-v1.5.2.tar.gz
 
 then type:
 
@@ -47,7 +47,7 @@ Set permissions, e.g.:
 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.1"
+  LoadPlugin "olsrd_bmf.so.1.5.2"
   {
     # No PlParam entries required for basic operation
   }
@@ -64,8 +64,8 @@ olsrd daemon by entering at the shell prompt:
 Look at the output; it should list the BMF plugin, e.g.:
 
   ---------- Plugin loader ----------
-  Library: olsrd_bmf.so.1.5.1
-  OLSRD Basic Multicast Forwarding plugin 1.5.1 (Sep  4 2007 11:13:43)
+  Library: olsrd_bmf.so.1.5.2
+  OLSRD Basic Multicast Forwarding plugin 1.5.2 (Dec  7 2007 09:08:19)
     (C) Thales Communications Huizen, Netherlands
     Erik Tromp (erik.tromp@nl.thalesgroup.com)
   Checking plugin interface version...  4 - OK
@@ -190,7 +190,7 @@ the /etc/olsrd.conf file.
 The following gives an overview of all plugin parameters that can be
 configured:
 
-  LoadPlugin "olsrd_bmf.so.1.5.1"
+  LoadPlugin "olsrd_bmf.so.1.5.2"
   {
     # Specify the name of the BMF network interface.
     # Defaults to "bmf0".
@@ -227,6 +227,19 @@ configured:
     # than broadcast packets (which are sent at a basic bit rate).
     PlParam "BmfMechanism" "UnicastPromiscuous"
 
+    # The number of times BMF will transmit the same packet whenever it decides
+    # to use broadcast to forward a packet. Defaults to 1. Not used if
+    # "BmfMechanism" is set to "UnicastPromiscuous".
+    PlParam "BroadcastRetransmitCount" "2"
+
+    # If the number of neighbors to forward to is less than or equal to the
+    # FanOutLimit, then packets to be relayed will be sent via unicast.
+    # If the number is greater than the FanOutLimit the packet goes out
+    # as broadcast. Legal values are 1...10. See MAX_UNICAST_NEIGHBORS
+    # as defined in NetworkInterfaces.h . Defaults to 2. Not used if
+    # "BmfMechanism" is set to "UnicastPromiscuous".
+    PlParam "FanOutLimit" "4"
+
     # List of non-OLSR interfaces to include
     PlParam     "NonOlsrIf"  "eth2"
     PlParam     "NonOlsrIf"  "eth3"
@@ -331,7 +344,7 @@ want to forward multicast and local-broadcast IP packets, specify these
 interfaces one by one as "NonOlsrIf" parameters in the BMF plugin section
 of /etc/olsrd.conf. For example:
 
-  LoadPlugin "olsrd_bmf.so.1.5.1"
+  LoadPlugin "olsrd_bmf.so.1.5.2"
   {
     # Non-OLSR interfaces to participate in the multicast flooding
     PlParam     "NonOlsrIf"  "eth2"
@@ -389,7 +402,7 @@ Therefore, override the default IP address and prefix length of
 the BMF network interface, by editing the /etc/olsrd.conf file.
 For example:
 
-  LoadPlugin "olsrd_bmf.so.1.5.1"
+  LoadPlugin "olsrd_bmf.so.1.5.2"
   {
       PlParam "BmfInterfaceIp" "10.10.10.4/24"
   }
@@ -442,13 +455,15 @@ output interface 0 (Oifs 0, "eth0"). The ":1" behind the Oifs numbers
 indicates the TTL thresholds, in this case packets with TTL value 1
 or less will not be forwarded.
 
-When you are connecting an OLSR-BMF network to another multicast network
-(e.g. a DVMRP network), you might be surprised that, when you ping the
-all-routers multicast address 224.0.0.1 from within the OLSR network,
-only the OLSR hosts respond. This is, however, compliant behaviour:
+Note that when you are connecting an OLSR-BMF network to another multicast
+network (e.g. a DVMRP-mrouted network), you might be surprised that, when
+you ping the all-routers multicast address 224.0.0.1 from within the OLSR
+network, only the OLSR hosts respond. This is, however, compliant behaviour:
 packets with their destination IP address in the range 224.0.0.0 -
 224.0.0.255 are not routed by normal multicast protocols (i.e. their
-TTL is implicitly assumed to be 1).
+TTL is implicitly assumed to be 1). It doesn't mean that multicast is
+not working; if your application uses a multicast address outisde the
+range 224.0.0.0 - 224.0.0.255, it should work.
 
 
 9. Common problems, FAQ
@@ -525,6 +540,14 @@ the BMF network interface, either by specifying the interface name itself
 10. Version history
 -------------------
 
+7 December 2007: Version 1.5.2
+
+* Fixed a bug that would cause BMF to always send encapsulated broadcast
+  packets twice --> thanks to Frank Renwick and Joseph Giovatto for finding
+  this bug :-)
+* Added the plugin parameters "BroadcastRetransmitCount" and "FanOutLimit";
+  thanks to Frank and Joe for the idea.
+
 3 September 2007: Version 1.5.1
 
 * Fixed a bug that would cause BMF to crash (and OLSR with it) if a link
index b9a0b5b..7e99125 100644 (file)
@@ -68,7 +68,10 @@ int EnableLocalBroadcast = 1;
  * Return     : success (0) or fail (1)
  * Data Used  : none
  * ------------------------------------------------------------------------- */
-int DoLocalBroadcast(const char* enable, void* data __attribute__((unused)), set_plugin_parameter_addon addon  __attribute__((unused)))
+int DoLocalBroadcast(
+  const char* enable,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
 {
   if (strcmp(enable, "yes") == 0)
   {
index 345ea5c..a93f524 100644 (file)
@@ -56,6 +56,7 @@
 #include <netinet/udp.h> /* struct udphdr */
 
 /* OLSRD includes */
+#include "plugin_util.h" /* set_plugin_int */
 #include "defs.h" /* olsr_cnf, OLSR_PRINTF */
 #include "ipcalc.h"
 #include "olsr.h" /* olsr_printf */
 static pthread_t BmfThread;
 static int BmfThreadRunning = 0;
 
+/* unicast/broadcast fan out limit */
+int FanOutLimit = 2;
+
+int BroadcastRetransmitCount = 1;
+
 /* -------------------------------------------------------------------------
  * Function   : BmfPError
  * Description: Prints an error message at OLSR debug level 1.
@@ -152,15 +158,17 @@ static void EncapsulateAndForwardPacket(
 
   /* The next destination(s) */
   struct TBestNeighbors bestNeighborLinks;
-  int nPossibleNeighbors;
-  struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
+  struct link_entry* bestNeighbor;
 
+  int nPossibleNeighbors = 0;
+  struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
   int nPacketsToSend;
-  int nBytesWritten;
+  int sendUnicast; /* 0 = send broadcast; 1 = send unicast */
+
   int i;
 
-  /* Retrieve at most two best neigbors to forward the packet to */
-  GetBestTwoNeighbors(&bestNeighborLinks, intf, NULL, NULL, NULL, &nPossibleNeighbors);
+  /* Find at most 'FanOutLimit' best neigbors to forward the packet to */
+  FindNeighbors(&bestNeighborLinks, &bestNeighbor, intf, NULL, NULL, NULL, &nPossibleNeighbors);
 
   if (nPossibleNeighbors <= 0)
   {
@@ -178,29 +186,47 @@ static void EncapsulateAndForwardPacket(
   forwardTo.sin_family = AF_INET;
   forwardTo.sin_port = htons(BMF_ENCAP_PORT);
 
-  /* Start by filling in the local broadcast address */
+  /* Start by filling in the local broadcast address. This may be overwritten later. */
   forwardTo.sin_addr = intf->broadAddr.v4;
 
   /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
-   *   packet (to the best neighbor).
-   * - If the BMF mechanism is BM_BROADCAST,
-   *   - send one unicast packet if there is one possible neighbor,
-   *   - send two unicast packets if there are two possible neighbors, and
-   *   - only if there are more than two possible neighbors, then send an
-   *     (WLAN-air-expensive, less reliable) broadcast packet. */
-  if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors < 2)
+   *   unicast packet (to the best neighbor).
+   * - But if the BMF mechanism is BM_BROADCAST,
+   *   - send 'nPossibleNeighbors' unicast packets if there are up to
+   *     'FanOutLimit' possible neighbors,
+   *   - if there are more than 'FanOutLimit' possible neighbors, then
+   *     send a (WLAN-air-expensive, less reliable) broadcast packet. */
+  if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
   {
+    /* One unicast packet to the best neighbor */
     nPacketsToSend = 1;
+    sendUnicast = 1;
+    bestNeighborLinks.links[0] = bestNeighbor;
   }
-  else /* BmfMechanism == BM_BROADCAST && nPossibleNeighbors >= 2 */
+  else /* BmfMechanism == BM_BROADCAST */
   {
-    nPacketsToSend = 2;
-  }
+    if (nPossibleNeighbors <= FanOutLimit)
+    {
+      /* 'nPossibleNeighbors' unicast packets */
+      nPacketsToSend = nPossibleNeighbors;
+      sendUnicast = 1;
+    }
+    else /* nPossibleNeighbors > FanOutLimit */
+    {
+      /* One broadcast packet, possibly retransmitted as specified in the
+       * 'BroadcastRetransmitCount' plugin parameter */
+      nPacketsToSend = BroadcastRetransmitCount;
+      sendUnicast = 0;
+    } /* if */
+  } /* if */
 
   for (i = 0; i < nPacketsToSend; i++)
   {
-    if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors <= 2)
+    int nBytesWritten;
+
+    if (sendUnicast == 1)
     {
+      /* For unicast, overwrite the local broadcast address which was filled in above */
       forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
     }
 
@@ -284,8 +310,13 @@ static void BmfPacketCaptured(
 
   ipPacket = GetIpPacket(encapsulationUdpData);
 
-  /* Don't forward fragments of IP packets. Also, don't forward OLSR packets (UDP
-   * port 698) and BMF encapsulated packets */
+  /* Don't forward fragments of IP packets: there is no way to distinguish fragments
+   * of BMF encapsulation packets from other fragments.
+   * Well yes, there is the IP-ID, which can be kept in a list to relate a fragment
+   * to earlier sent BMF packets, but... sometimes the second fragment comes in earlier
+   * than the first fragment, so that the list is not yet up to date and the second
+   * fragment is not recognized as a BMF packet.
+   * Also, don't forward OLSR packets (UDP port 698) and BMF encapsulated packets */
   if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket))
   {
     return;
@@ -763,14 +794,16 @@ static void BmfEncapsulationPacketReceived(
     else if (iAmMpr)
     {
       struct TBestNeighbors bestNeighborLinks;
+      struct link_entry* bestNeighbor;
       int nPossibleNeighbors;
-      int nBytesWritten;
       int nPacketsToSend;
+      int sendUnicast; /* 0 = send broadcast; 1 = send unicast */
       int i;
 
       /* Retrieve at most two best neigbors to forward the packet to */
-      GetBestTwoNeighbors(
+      FindNeighbors(
         &bestNeighborLinks,
+        &bestNeighbor,
         walker,
         &mcSrc,
         forwardedBy,
@@ -789,31 +822,47 @@ static void BmfEncapsulationPacketReceived(
       }
 
       /* Compose destination of encapsulation packet.
-       * Start by filling in the local broadcast address. */
+       * Start by filling in the local broadcast address. This may be overwritten later. */
       forwardTo.sin_addr = walker->broadAddr.v4;
 
       /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
-       *   packet (to the best neighbor). Other neighbors listen promiscuously.
-       * - If the BMF mechanism is BM_BROADCAST,
-       *   - send one unicast packet if there is one possible neighbor,
-       *   - send two unicast packets if there are two possible neighbors, and
-       *   - only if there are more than two possible neighbors, then send an
-       *     (WLAN-air-expensive, less reliable) broadcast packet. */
-      if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors < 2)
+       *   unicast packet (to the best neighbor).
+       * - But if the BMF mechanism is BM_BROADCAST,
+       *   - send 'nPossibleNeighbors' unicast packets if there are up to
+       *     'FanOutLimit' possible neighbors,
+       *   - if there are more than 'FanOutLimit' possible neighbors, then
+       *     send a (WLAN-air-expensive, less reliable) broadcast packet. */
+      if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
       {
+        /* One unicast packet to the best neighbor */
         nPacketsToSend = 1;
+        sendUnicast = 1;
+        bestNeighborLinks.links[0] = bestNeighbor;
       }
-      else /* BmfMechanism == BM_BROADCAST && nPossibleNeighbors >= 2 */
+      else /* BmfMechanism == BM_BROADCAST */
       {
-        nPacketsToSend = 2;
-      }
+        if (nPossibleNeighbors <= FanOutLimit)
+        {
+          /* 'nPossibleNeighbors' unicast packets */
+          nPacketsToSend = nPossibleNeighbors;
+          sendUnicast = 1;
+        }
+        else /* nPossibleNeighbors > FanOutLimit */
+        {
+          /* One broadcast packet, possibly retransmitted as specified in the
+           * 'BroadcastRetransmitCount' plugin parameter */
+          nPacketsToSend = BroadcastRetransmitCount;
+          sendUnicast = 0;
+        } /* if */
+      } /* if */
 
       for (i = 0; i < nPacketsToSend; i++)
       {
-        if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors <= 2)
-        {
-          /* For unicast, overwrite the local broadcast address which was filled in
-           * above */
+        int nBytesWritten;
+
+        if (sendUnicast)
+        {    
+          /* For unicast, overwrite the local broadcast address which was filled in above */
           forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
         }
 
@@ -892,10 +941,10 @@ static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
   ipPacketLen = GetIpTotalLength(ipPacket);
   ipHeader = GetIpHeader(encapsulationUdpData);
 
-  /* Only forward multicast packets. If configured, also forward local broadcast packets */
   dstIp.v4 = ipHeader->ip_dst;
-
   broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
+
+  /* Only forward multicast packets. If configured, also forward local broadcast packets */
   if (IsMulticast(&dstIp) ||
       (EnableLocalBroadcast != 0 && ipequal(&dstIp, &broadAddr)))
   {
@@ -1414,6 +1463,33 @@ int InterfaceChange(struct interface* interf, int action)
   return 0;
 } /* InterfaceChange */
 
+
+/* -------------------------------------------------------------------------
+ * Function   : SetFanOutLimit
+ * Description: Overrule the default fan out limit value (2)
+ * Input      : value - fan out limit value (1...MAX_UNICAST_NEIGHBORS)
+ *              data - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : FanOutLimit
+ * ------------------------------------------------------------------------- */
+int SetFanOutLimit(
+  const char* value,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+  if (set_plugin_int(value, &FanOutLimit, addon) == 0)
+  {
+    /* Extra check if within range */
+    if (FanOutLimit >= 1 && FanOutLimit <= MAX_UNICAST_NEIGHBORS)
+    {
+      return 0;
+    }
+  }
+  return 1;
+}
+
 /* -------------------------------------------------------------------------
  * Function   : InitBmf
  * Description: Initialize the BMF plugin
index 29d0a27..69136be 100644 (file)
  *
  * ------------------------------------------------------------------------- */
 
+#include "olsrd_plugin.h" /* union set_plugin_parameter_addon */ 
+
 /* BMF plugin data */
 #define PLUGIN_NAME "OLSRD Basic Multicast Forwarding (BMF) plugin"
 #define PLUGIN_NAME_SHORT "OLSRD BMF"
-#define PLUGIN_VERSION "1.5.1 (" __DATE__ " " __TIME__ ")"
+#define PLUGIN_VERSION "1.5.2 (" __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
 /* Forward declaration of OLSR interface type */
 struct interface;
 
+extern int FanOutLimit;
+extern int BroadcastRetransmitCount;
+
 void BmfPError(const char* format, ...) __attribute__((format(printf, 1, 2)));
 union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip);
 int InterfaceChange(struct interface* interf, int action);
+int SetFanOutLimit(const char* value, void* data, set_plugin_parameter_addon addon);
 int InitBmf(struct interface* skipThisIntf);
 void CloseBmf(void);
-int RegisterBmfParameter(char* key, char* value);
 
 #endif /* _BMF_BMF_H */
index 8dbe9b5..42a1291 100644 (file)
@@ -128,7 +128,10 @@ int CapturePacketsOnOlsrInterfaces = 0;
  * Return     : success (0) or fail (1)
  * Data Used  : EtherTunTapIfName
  * ------------------------------------------------------------------------- */
-int SetBmfInterfaceName(const char* ifname, void* data __attribute__((unused)), set_plugin_parameter_addon addon  __attribute__((unused)))
+int SetBmfInterfaceName(
+  const char* ifname,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
 {
   strncpy(EtherTunTapIfName, ifname, IFNAMSIZ - 1);
   EtherTunTapIfName[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
@@ -147,7 +150,10 @@ int SetBmfInterfaceName(const char* ifname, void* data __attribute__((unused)),
  * Data Used  : EtherTunTapIp, EtherTunTapIpMask, EtherTunTapIpBroadcast,
  *              TunTapIpOverruled
  * ------------------------------------------------------------------------- */
-int SetBmfInterfaceIp(const char* ip, void* data __attribute__((unused)), set_plugin_parameter_addon addon  __attribute__((unused)))
+int SetBmfInterfaceIp(
+  const char* ip,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
 {
 #define IPV4_MAX_ADDRLEN 16
 #define IPV4_MAX_PREFIXLEN 32
@@ -217,7 +223,10 @@ int SetBmfInterfaceIp(const char* ip, void* data __attribute__((unused)), set_pl
  * Return     : success (0) or fail (1)
  * Data Used  : none
  * ------------------------------------------------------------------------- */
-int SetCapturePacketsOnOlsrInterfaces(const char* enable, void* data __attribute__((unused)), set_plugin_parameter_addon addon  __attribute__((unused)))
+int SetCapturePacketsOnOlsrInterfaces(
+  const char* enable,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
 {
   if (strcmp(enable, "yes") == 0)
   {
@@ -245,7 +254,10 @@ int SetCapturePacketsOnOlsrInterfaces(const char* enable, void* data __attribute
  * Return     : success (0) or fail (1)
  * Data Used  : none
  * ------------------------------------------------------------------------- */
-int SetBmfMechanism(const char* mechanism, void* data __attribute__((unused)), set_plugin_parameter_addon addon  __attribute__((unused)))
+int SetBmfMechanism(
+  const char* mechanism,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
 {
   if (strcmp(mechanism, "Broadcast") == 0)
   {
@@ -402,38 +414,45 @@ static float CalcEtx(float loss, float neigh_loss)
 #endif /* USING_THALES_LINK_COST_ROUTING */
 
 /* -------------------------------------------------------------------------
- * Function   : GetBestTwoNeighbors
- * Description: Find at most two best neighbors on a network interface to forward
- *              a BMF packet to
+ * Function   : FindNeighbors
+ * Description: Find the neighbors on a network interface to forward a BMF
+ *              packet to
  * Input      : intf - the network interface
  *              source - the source IP address of the BMF packet 
  *              forwardedBy - the IP address of the node that forwarded the BMF
  *                packet
  *              forwardedTo - the IP address of the node to which the BMF packet
  *                was directed
- * Output     : result - the list of the two best neighbors. If only one best
- *                neighbor is found, the second list entry is NULL. If no neigbors
- *                are found, the first and second list entries are both NULL.
+ * Output     : neighbors - list of (up to a number of 'FanOutLimit') neighbors.
+ *              bestNeighbor - the best neighbor (in terms of lowest cost or ETX
+ *                value)
  *              nPossibleNeighbors - number of found possible neighbors
- * Data Used  : none
+ * Data Used  : FanOutLimit
  * ------------------------------------------------------------------------- */
-void GetBestTwoNeighbors(
-  struct TBestNeighbors* result,
+void FindNeighbors(
+  struct TBestNeighbors* neighbors,
+  struct link_entry** bestNeighbor,
   struct TBmfInterface* intf,
   union olsr_ip_addr* source,
   union olsr_ip_addr* forwardedBy,
   union olsr_ip_addr* forwardedTo,
   int* nPossibleNeighbors)
 {
-  result->links[0] = NULL;
-  result->links[1] = NULL;
+  int i;
+
+  /* Initialize */
+  *bestNeighbor = NULL;
+  for (i = 0; i < MAX_UNICAST_NEIGHBORS; i++)
+  {
+    neighbors->links[i] = NULL;
+  }
+  *nPossibleNeighbors = 0;
 
   /* handle the non-LQ case */
 
   if (olsr_cnf->lq_level == 0)
   {
     struct link_entry* walker;
-    *nPossibleNeighbors = 0;
 
     /* TODO: get_link_set() is not thread-safe! */
     for (walker = get_link_set(); walker != NULL; walker = walker->next) 
@@ -506,18 +525,24 @@ void GetBestTwoNeighbors(
 
       /* Found a candidate neighbor to direct our packet to */
 
-      *nPossibleNeighbors += 1;
-
       /* In the non-LQ case, it is not possible to select neigbors
-       * by quality or cost. So just remember the first two found links. */
-      if (result->links[0] == NULL)
+       * by quality or cost. So just remember the first found link.
+       * TODO: come on, there must be something better than to simply
+       * select the first one found! */
+      if (*bestNeighbor == NULL)
       {
-        result->links[0] = walker;
+        *bestNeighbor = walker;
       }
-      else if (result->links[1] == NULL)
+
+      /* Fill the list with up to 'FanOutLimit' neighbors. If there
+       * are more neighbors, broadcast is used instead of unicast. In that
+       * case we do not need the list of neighbors. */
+      if (*nPossibleNeighbors < FanOutLimit)
       {
-        result->links[1] = walker;
-      } /* if */
+        neighbors->links[*nPossibleNeighbors] = walker;
+      }
+
+      *nPossibleNeighbors += 1;
     } /* for */
 
   }
@@ -529,8 +554,6 @@ void GetBestTwoNeighbors(
     struct link_entry* walker;
     float previousLinkCost = 2 * INFINITE_COST;
     float bestLinkCost = 2 * INFINITE_COST;
-    float oneButBestLinkCost = 2 * INFINITE_COST;
-    *nPossibleNeighbors = 0;
 
     if (forwardedBy != NULL)
     {
@@ -697,29 +720,30 @@ void GetBestTwoNeighbors(
         } /* if */
       } /* if */
 
-      *nPossibleNeighbors += 1;
-
-      /* Remember the best two links. If all are very bad, remember none. */
+      /* Remember the best neighbor. If all are very bad, remember none. */
       if (walker->link_cost < bestLinkCost)
       {
-        result->links[1] = result->links[0];
-        result->links[0] = walker;
+        *bestNeighbor = walker;
         bestLinkCost = walker->link_cost;
       }
-      else if (walker->link_cost < oneButBestLinkCost)
+
+      /* Fill the list with up to 'FanOutLimit' neighbors. If there
+       * are more neighbors, broadcast is used instead of unicast. In that
+       * case we do not need the list of neighbors. */
+      if (*nPossibleNeighbors < FanOutLimit)
       {
-        result->links[1] = walker;
-        oneButBestLinkCost = walker->link_cost;
-      } /* if */
+        neighbors->links[*nPossibleNeighbors] = walker;
+      }
+
+      *nPossibleNeighbors += 1;
+
     } /* for */
 
 #else /* USING_THALES_LINK_COST_ROUTING */
         
     struct link_entry* walker;
     float previousLinkEtx = 2 * INFINITE_ETX;
-    float bestEtx = 2 * INFINITE_ETX; 
-    float oneButBestEtx = 2 * INFINITE_ETX;
-    *nPossibleNeighbors = 0;
+    float bestEtx = 2 * INFINITE_ETX;
 
     if (forwardedBy != NULL)
     {
@@ -918,20 +942,22 @@ void GetBestTwoNeighbors(
         } /* if */
       } /* if */
 
-      *nPossibleNeighbors += 1;
-
-      /* Remember the best two links. If all are very bad, remember none. */
+      /* Remember the best neighbor. If all are very bad, remember none. */
       if (currEtx < bestEtx)
       {
-        result->links[1] = result->links[0];
-        result->links[0] = walker;
+        *bestNeighbor = walker;
         bestEtx = currEtx;
       }
-      else if (currEtx < oneButBestEtx)
+
+      /* Fill the list with up to 'FanOutLimit' neighbors. If there
+       * are more neighbors, broadcast is used instead of unicast. In that
+       * case we do not need the list of neighbors. */
+      if (*nPossibleNeighbors < FanOutLimit)
       {
-        result->links[1] = walker;
-        oneButBestEtx = currEtx;
-      } /* if */
+        neighbors->links[*nPossibleNeighbors] = walker;
+      }
+
+      *nPossibleNeighbors += 1;
     } /* for */
 
 #endif /* USING_THALES_LINK_COST_ROUTING */
@@ -939,7 +965,7 @@ void GetBestTwoNeighbors(
   } /* if */
 
   /* Display the result of the neighbor search */
-  if (result->links[0] == NULL)
+  if (*nPossibleNeighbors == 0)
   {
     OLSR_PRINTF(
       9,
@@ -954,28 +980,14 @@ void GetBestTwoNeighbors(
 #endif
     OLSR_PRINTF(
       9,
-      "%s: ----> Best neighbor%s to forward to on \"%s\": ",
+      "%s: ----> %d neighbors found on \"%s\"; best neighbor to forward to: %s\n",
       PLUGIN_NAME_SHORT,
-      *nPossibleNeighbors == 1 ? "" : "s",
-      intf->ifName);
-
-    OLSR_PRINTF(
-      9,
-      "%s",
-      olsr_ip_to_string(&buf, &result->links[0]->neighbor_iface_addr));
-
-    if (result->links[1] != NULL)
-    {
-      OLSR_PRINTF(
-        9,
-        ", %s",
-        olsr_ip_to_string(&buf, &result->links[1]->neighbor_iface_addr));
-    } /* if */
-
-    OLSR_PRINTF(9, "\n");
+      *nPossibleNeighbors,
+      intf->ifName,
+      olsr_ip_to_string(&buf, &(*bestNeighbor)->neighbor_iface_addr));
   } /* if */
 
-} /* GetBestTwoNeighbors */
+} /* FindNeighbors */
 
 /* -------------------------------------------------------------------------
  * Function   : CreateCaptureSocket
@@ -1798,7 +1810,10 @@ static int nNonOlsrIfs = 0;
  * Return     : success (0) or fail (1)
  * Data Used  : NonOlsrIfNames
  * ------------------------------------------------------------------------- */
-int AddNonOlsrBmfIf(const char* ifName, void* data __attribute__((unused)), set_plugin_parameter_addon addon  __attribute__((unused)))
+int AddNonOlsrBmfIf(
+  const char* ifName,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
 {
   assert(ifName != NULL);
 
index a39e293..6514846 100644 (file)
@@ -128,13 +128,15 @@ int SetBmfMechanism(const char* mechanism, void* data, set_plugin_parameter_addo
 int DeactivateSpoofFilter(void);
 void RestoreSpoofFilter(void);
 
+#define MAX_UNICAST_NEIGHBORS 10
 struct TBestNeighbors
 {
-  struct link_entry* links[2];
+  struct link_entry* links[MAX_UNICAST_NEIGHBORS];
 };
 
-void GetBestTwoNeighbors(
-  struct TBestNeighbors* result,
+void FindNeighbors(
+  struct TBestNeighbors* neighbors,
+  struct link_entry** bestNeighbor,
   struct TBmfInterface* intf,
   union olsr_ip_addr* source,
   union olsr_ip_addr* forwardedBy,
index e9dcddd..3625965 100644 (file)
 
 /* OLSRD includes */
 #include "olsrd_plugin.h"
+#include "plugin_util.h"
 #include "defs.h" /* olsr_u8_t, olsr_cnf */
 #include "scheduler.h" /* olsr_register_scheduler_event */
 
 /* BMF includes */
-#include "Bmf.h" /* InitBmf(), CloseBmf(), RegisterBmfParameter() */
+#include "Bmf.h" /* InitBmf(), CloseBmf() */
 #include "PacketHistory.h" /* InitPacketHistory() */
 #include "NetworkInterfaces.h" /* AddNonOlsrBmfIf(), SetBmfInterfaceIp(), ... */
 #include "Address.h" /* DoLocalBroadcast() */
@@ -123,6 +124,8 @@ static const struct olsrd_plugin_parameters plugin_parameters[] = {
     { .name = "BmfInterfaceIp", .set_plugin_parameter = &SetBmfInterfaceIp, .data = NULL },
     { .name = "CapturePacketsOnOlsrInterfaces", .set_plugin_parameter = &SetCapturePacketsOnOlsrInterfaces, .data = NULL },
     { .name = "BmfMechanism", .set_plugin_parameter = &SetBmfMechanism, .data = NULL },
+    { .name = "FanOutLimit", .set_plugin_parameter = &SetFanOutLimit, .data = NULL },
+    { .name = "BroadcastRetransmitCount", .set_plugin_parameter = &set_plugin_int, .data = &BroadcastRetransmitCount},
 };
 
 /* -------------------------------------------------------------------------