<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">Hi,</div><div class="gmail_quote"><br></div><div class="gmail_quote">back from (two) business trips...</div><div class="gmail_quote"><br></div><div class="gmail_quote">On Mon, Jan 16, 2017 at 6:14 PM, Ferry Huberts <span dir="ltr"><<a href="mailto:mailings@hupie.com" target="_blank">mailings@hupie.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I think I may have stumbled onto a MUCH easier fix to this problem.<br>
<br>
<br>
The actual problem is quite involved (with fragmented hello messages etc) but it all boils down to a later UNSPEC link overwriting a previous SYM/ASYM/other link on the receiving end.<br>
<br>
Since the neighbours in a hello message are already ordered when the hello message is sent out, the following patch also solves it.<br>
<br>
Opinions?<br></blockquote><div><br></div><div>I like the idea of solve the problem by sorting, but I worry that doing so on the TX side is a bit "brittle"... its easy to break because there is nothing on the TX side that needs this order. And there will always be older Olsrd installations on many community networks.</div><div><br></div><div>How difficult would it be to do the sorting on the RX side in deserialize_hello() (process_package.c: 318..)?</div><div><br></div><div>Instead of building them into a single linked list, have an array with MAX_LINK lists, one for each link type... and then concatenate this lists before parsing in the right order.</div><div><br></div><div>This way we also fix the problem appearing again because of an outdated Olsrd sending bad data, right?</div><div><br></div><div>Henning</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
<br>
<br>
diff --git a/src/lq_packet.c b/src/lq_packet.c<br>
index d44e654..287f4b4 100644<br>
--- a/src/lq_packet.c<br>
+++ b/src/lq_packet.c<br>
@@ -326,7 +326,7 @@ serialize_common(struct olsr_common *comm)<br>
 static void<br>
 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface_olsr *outif)<br>
 {<br>
-  static const int LINK_ORDER[] = { SYM_LINK, UNSPEC_LINK, ASYM_LINK, LOST_LINK };<br>
+  static const int LINK_ORDER[] = { UNSPEC_LINK, LOST_LINK, ASYM_LINK, SYM_LINK };<br>
   int rem, size, req, expected_size = 0;<br>
   struct lq_hello_info_header *info_head;<br>
   struct lq_hello_neighbor *neigh;<br>
<div class="gmail-HOEnZb"><div class="gmail-h5"><br>
<br>
<br>
<br>
On 13/01/17 09:05, Ferry Huberts wrote:<br>
> From: "Iwan G. Flameling" <<a href="mailto:iwanovich@gmail.com">iwanovich@gmail.com</a>><br>
><br>
> A while ago we noticed that neighbours of nodes with multiple interfaces<br>
> on the same medium report infinite costs on their links to those nodes.<br>
><br>
> This problem is 100% reproducible.<br>
><br>
> Below is the setup in which we noticed the problem.<br>
><br>
>        wlan0                                                 wlan0<br>
>        <a href="http://172.31.175.97/16" rel="noreferrer" target="_blank">172.31.175.97/16</a>                           <a href="http://172.31.175.61/16" rel="noreferrer" target="_blank">172.31.175.61/16</a><br>
>     (((*))) ------------------------------<wbr>------------------- (((*)))<br>
>        |                                                         |<br>
>        |                                                         |<br>
>        |                                                         |<br>
>    ____|___   <a href="http://172.29.175.97/15" rel="noreferrer" target="_blank">172.29.175.97/15</a>   ________  <a href="http://172.29.175.61/15" rel="noreferrer" target="_blank">172.29.175.61/15</a>  ____|____<br>
>   |         |-eth1.2580---------|        |--------eth1.2580-|         |<br>
>   | Node 97 |                   | Switch |                  | Node 61 |<br>
>   |_________|-eth2.2580---------<wbr>|________|                  |_________|<br>
>               <a href="http://172.28.175.97/15" rel="noreferrer" target="_blank">172.28.175.97/15</a><br>
><br>
> In this setup node 97 will report normal link costs for its (wired) links<br>
> to node 61 (see the first table below), while node 61 will report infinite<br>
> link costs for both its (wired) links to node 97 (see the second table<br>
> below).<br>
><br>
>   Table: Links (node 97)<br>
>   Local IP       Remote IP       Hyst.   LQ      NLQ     Cost<br>
>   172.29.175.97  172.29.175.61   0.000   1.000   1.000   0.100<br>
>   172.28.175.97  172.29.175.61   0.000   1.000   1.000   0.100<br>
>   172.31.175.97  172.31.175.61   0.000   1.000   1.000   1.000<br>
><br>
>   Table: Links (node 61)<br>
>   Local IP       Remote IP       Hyst.   LQ      NLQ     Cost<br>
>   172.29.175.61  172.29.175.97   0.000   1.000   0.000   INFINITE<br>
>   172.29.175.61  172.28.175.97   0.000   1.000   0.000   INFINITE<br>
>   172.31.175.61  172.31.175.97   0.000   1.000   1.000   1.000<br>
><br>
> Checking the HELLO messages that are received on node 61 from node 97,<br>
> we see the following:<br>
><br>
>   [node 61] # tcpdump -vni eth1.2580 udp port 698<br>
>   tcpdump: listening on eth1.2580, link-type EN10MB (Ethernet), capture size 262144 bytes<br>
>   06:21:23.528204 IP (tos 0xc0, ttl 1, id 42455, offset 0, flags [DF], proto UDP (17), length 80)<br>
>       172.28.175.97.698 > 255.255.255.255.698: OLSRv4, seq 0xf7c0, length 52<br>
>      Hello-LQ Message (0xc9), originator 172.31.175.97, ttl 1, hop 0<br>
>        vtime 3.000s, msg-seq 0x533d, length 48<br>
>        hello-time 1.000s, MPR willingness 3<br>
>          link-type Symmetric, neighbor-type Symmetric, len 12<br>
>            neighbor 172.29.175.61, link-quality 0.00%, neighbor-link-quality 0.00%<br>
>          link-type Unspecified, neighbor-type Symmetric, len 20<br>
>            neighbor 172.31.175.61, link-quality 0.00%, neighbor-link-quality 0.00%<br>
>            neighbor 172.29.175.61, link-quality 0.00%, neighbor-link-quality 0.00%<br>
><br>
> Node 61 receives HELLO messages from node 97 that report (amongst others):<br>
> 1- a  SYMMETRIC   link-type to node 61 (172.29.175.61)<br>
> 2- an UNSPECIFIED link-type to node 61 (172.29.175.61)<br>
><br>
> Clearly, this is 'confusing' and the root cause of why node 61 reports<br>
> infinite costs for the links, as shown above.<br>
><br>
> We pose that in a HELLO message the same neighbour should NEVER be<br>
> reported with conflicting information.<br>
><br>
> Proposed solution:<br>
><br>
> 1- NEVER report a neighbour more than once in a HELLO message<br>
> 2- Use the 'best' values for a neighbour that is reported in a HELLO<br>
>    message<br>
><br>
> This requires:<br>
><br>
> 1- De-duplication of neighbours when constructing a HELLO message.<br>
><br>
> 2- When a neighbour is already present in the HELLO message<br>
>    that is under construction then he 'best' values must be determined<br>
>    and those in the neighbour that is already present should only be<br>
>    overwritten if those are worse.<br>
><br>
> This patch implements that solution.<br>
><br>
> Signed-off-by: Iwan G. Flameling <<a href="mailto:iwanovich@gmail.com">iwanovich@gmail.com</a>><br>
> Signed-off-by: Ferry Huberts <<a href="mailto:ferry.huberts@pelagic.nl">ferry.huberts@pelagic.nl</a>><br>
> ---<br>
>  src/lq_packet.c               |  52 ++++++++++++----<br>
>  src/lq_plugin.c               |   5 +-<br>
>  src/lq_plugin.h               |   4 +-<br>
>  src/lq_plugin_default_ff.c    |  13 +++-<br>
>  src/lq_plugin_default_ffeth.c |  13 +++-<br>
>  src/lq_plugin_default_float.c |  19 +++++-<br>
>  src/lq_plugin_default_fpm.c   |  19 +++++-<br>
>  src/olsr_protocol.h           | 136 ++++++++++++++++++++++++++++++<wbr>++++++++++++<br>
>  8 files changed, 236 insertions(+), 25 deletions(-)<br>
><br>
> diff --git a/src/lq_packet.c b/src/lq_packet.c<br>
> index d44e654..2e8e027 100644<br>
> --- a/src/lq_packet.c<br>
> +++ b/src/lq_packet.c<br>
> @@ -68,6 +68,21 @@ bool lq_tc_pending = false;<br>
>  static uint32_t msg_buffer_aligned[(<wbr>MAXMESSAGESIZE - OLSR_HEADERSIZE) / sizeof(uint32_t) + 1];<br>
>  static unsigned char *const msg_buffer = (unsigned char *)msg_buffer_aligned;<br>
><br>
> +static struct lq_hello_neighbor * neigh_find(struct link_entry *link, struct lq_hello_message *lq_hello) {<br>
> +  struct lq_hello_neighbor *neigh;<br>
> +<br>
> +  assert(link);<br>
> +  assert(lq_hello);<br>
> +<br>
> +  for (neigh = lq_hello->neigh; neigh; neigh = neigh->next) {<br>
> +    if (ipequal(&link->neighbor_<wbr>iface_addr, &neigh->addr)) {<br>
> +      return neigh;<br>
> +    }<br>
> +  }<br>
> +<br>
> +  return NULL ;<br>
> +}<br>
> +<br>
>  static void<br>
>  create_lq_hello(struct lq_hello_message *lq_hello, struct interface_olsr *outif)<br>
>  {<br>
> @@ -92,46 +107,57 @@ create_lq_hello(struct lq_hello_message *lq_hello, struct interface_olsr *outif)<br>
>    // loop through the link set<br>
><br>
>    OLSR_FOR_ALL_LINK_ENTRIES(<wbr>walker) {<br>
> +    uint8_t link_type;<br>
> +    uint8_t neigh_type;<br>
><br>
>      // allocate a neighbour entry<br>
> -    struct lq_hello_neighbor *neigh = olsr_malloc_lq_hello_neighbor(<wbr>"Build LQ_HELLO");<br>
> +    struct lq_hello_neighbor *neigh = neigh_find(walker, lq_hello);<br>
> +    bool neigh_is_new = (neigh == NULL );<br>
> +    neigh = neigh_is_new ? olsr_malloc_lq_hello_neighbor(<wbr>"Build LQ_HELLO") : neigh;<br>
><br>
>      // a) this neighbor interface IS NOT visible via the output interface<br>
>      if (!ipequal(&walker->local_<wbr>iface_addr, &outif->ip_addr))<br>
> -      neigh->link_type = UNSPEC_LINK;<br>
> +      link_type = UNSPEC_LINK;<br>
><br>
>      // b) this neighbor interface IS visible via the output interface<br>
><br>
>      else<br>
> -      neigh->link_type = lookup_link_status(walker);<br>
> +      link_type = lookup_link_status(walker);<br>
> +<br>
> +    if (neigh_is_new || link_type_compare(neigh->link_<wbr>type, link_type))<br>
> +      neigh->link_type = link_type;<br>
><br>
>      // set the entry's link quality<br>
> -    olsr_copy_hello_lq(neigh, walker);<br>
> +    olsr_copy_hello_lq(neigh, walker, neigh_is_new);<br>
><br>
>      // set the entry's neighbour type<br>
><br>
>      if (walker->neighbor->is_mpr)<br>
> -      neigh->neigh_type = MPR_NEIGH;<br>
> +      neigh_type = MPR_NEIGH;<br>
><br>
>      else if (walker->neighbor->status == SYM)<br>
> -      neigh->neigh_type = SYM_NEIGH;<br>
> +      neigh_type = SYM_NEIGH;<br>
><br>
>      else if (walker->neighbor->status == NOT_SYM)<br>
> -      neigh->neigh_type = NOT_NEIGH;<br>
> +      neigh_type = NOT_NEIGH;<br>
><br>
>      else {<br>
>        OLSR_PRINTF(0, "Error: neigh_type undefined");<br>
> -      neigh->neigh_type = NOT_NEIGH;<br>
> +      neigh_type = NOT_NEIGH;<br>
>      }<br>
><br>
> -    // set the entry's neighbour interface address<br>
> +    if (neigh_is_new || neigh_type_compare(neigh-><wbr>neigh_type, neigh_type))<br>
> +      neigh->neigh_type = neigh_type;<br>
><br>
> -    neigh->addr = walker->neighbor_iface_addr;<br>
> +    if (neigh_is_new) {<br>
> +      // set the entry's neighbour interface address<br>
><br>
> -    // queue the neighbour entry<br>
> -    neigh->next = lq_hello->neigh;<br>
> -    lq_hello->neigh = neigh;<br>
> +      neigh->addr = walker->neighbor_iface_addr;<br>
><br>
> +      // queue the neighbour entry<br>
> +      neigh->next = lq_hello->neigh;<br>
> +      lq_hello->neigh = neigh;<br>
> +    }<br>
>    }<br>
>    OLSR_FOR_ALL_LINK_ENTRIES_END(<wbr>walker);<br>
>  }<br>
> diff --git a/src/lq_plugin.c b/src/lq_plugin.c<br>
> index a917c84..01c6e4e 100644<br>
> --- a/src/lq_plugin.c<br>
> +++ b/src/lq_plugin.c<br>
> @@ -351,13 +351,14 @@ get_linkcost_scaled(olsr_<wbr>linkcost cost, bool route)<br>
>   *<br>
>   * @param target pointer to target lq_hello_neighbor<br>
>   * @param source pointer to source link_entry<br>
> + * @param force true to force the copy, otherwise only copy when source is 'better' than target<br>
>   */<br>
>  void<br>
> -olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source)<br>
> +olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source, bool force)<br>
>  {<br>
>    assert((const char *)target + sizeof(*target) >= (const char *)target->linkquality);<br>
>    assert((const char *)source + sizeof(*source) >= (const char *)source->linkquality);<br>
> -  active_lq_handler->copy_link_<wbr>lq_into_neigh(target-><wbr>linkquality, source->linkquality);<br>
> +  active_lq_handler->copy_link_<wbr>lq_into_neigh(target-><wbr>linkquality, source->linkquality, force);<br>
>  }<br>
><br>
>  /**<br>
> diff --git a/src/lq_plugin.h b/src/lq_plugin.h<br>
> index 747a70c..26baba4 100644<br>
> --- a/src/lq_plugin.h<br>
> +++ b/src/lq_plugin.h<br>
> @@ -76,7 +76,7 @@ struct lq_handler {<br>
>    void (*packet_loss_handler) (struct link_entry * entry, void *lq, bool lost);<br>
><br>
>    void (*memorize_foreign_hello) (void *local, void *foreign);<br>
> -  void (*copy_link_lq_into_neigh) (void *target, void *source);<br>
> +  void (*copy_link_lq_into_neigh) (void *target, void *source, bool force);<br>
>    void (*copy_link_lq_into_tc) (void *target, void *source);<br>
>    void (*clear_hello) (void *target);<br>
>    void (*clear_tc) (void *target);<br>
> @@ -134,7 +134,7 @@ const char *get_linkcost_text(olsr_<wbr>linkcost cost, bool route, struct lqtextbuffe<br>
>  double get_linkcost_scaled(olsr_<wbr>linkcost cost, bool route);<br>
><br>
>  void olsr_clear_hello_lq(struct link_entry */*link*/);<br>
> -void olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source);<br>
> +void olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source, bool force);<br>
>  void olsr_copylq_link_entry_2_tc_<wbr>mpr_addr(struct tc_mpr_addr *target, struct link_entry *source);<br>
>  void olsr_copylq_link_entry_2_tc_<wbr>edge_entry(struct tc_edge_entry *target, struct link_entry *source);<br>
>  void olsr_clear_tc_lq(struct tc_mpr_addr *target);<br>
> diff --git a/src/lq_plugin_default_ff.c b/src/lq_plugin_default_ff.c<br>
> index 3d6ba6a..fa617e3 100644<br>
> --- a/src/lq_plugin_default_ff.c<br>
> +++ b/src/lq_plugin_default_ff.c<br>
> @@ -70,7 +70,7 @@ static void default_lq_deserialize_hello_<wbr>lq_pair_ff(const uint8_t ** curr, void<br>
>  static int default_lq_serialize_tc_lq_<wbr>pair_ff(unsigned char *buff, void *lq);<br>
>  static void default_lq_deserialize_tc_lq_<wbr>pair_ff(const uint8_t ** curr, void *lq);<br>
><br>
> -static void default_lq_copy_link2neigh_ff(<wbr>void *t, void *s);<br>
> +static void default_lq_copy_link2neigh_ff(<wbr>void *t, void *s, bool force);<br>
>  static void default_lq_copy_link2tc_ff(<wbr>void *target, void *source);<br>
>  static void default_lq_clear_ff(void *target);<br>
>  static void default_lq_clear_ff_hello(void *target);<br>
> @@ -371,11 +371,18 @@ default_lq_memorize_foreign_<wbr>hello_ff(void *ptrLocal, void *ptrForeign)<br>
>  }<br>
><br>
>  static void<br>
> -default_lq_copy_link2neigh_<wbr>ff(void *t, void *s)<br>
> +default_lq_copy_link2neigh_<wbr>ff(void *t, void *s, bool force)<br>
>  {<br>
>    struct default_lq_ff *target = t;<br>
>    struct default_lq_ff_hello *source = s;<br>
> -  *target = source->smoothed_lq;<br>
> +<br>
> +  if (force) {<br>
> +    *target = source->smoothed_lq;<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  target->valueLq = MAX(target->valueLq, source->smoothed_lq.valueLq);<br>
> +  target->valueNlq = MAX(target->valueNlq, source->smoothed_lq.valueNlq);<br>
>  }<br>
><br>
>  static void<br>
> diff --git a/src/lq_plugin_default_ffeth.<wbr>c b/src/lq_plugin_default_ffeth.<wbr>c<br>
> index e78dcd7..0e9408e 100644<br>
> --- a/src/lq_plugin_default_ffeth.<wbr>c<br>
> +++ b/src/lq_plugin_default_ffeth.<wbr>c<br>
> @@ -72,7 +72,7 @@ static void default_lq_deserialize_hello_<wbr>lq_pair_ffeth(const uint8_t ** curr, vo<br>
>  static int default_lq_serialize_tc_lq_<wbr>pair_ffeth(unsigned char *buff, void *lq);<br>
>  static void default_lq_deserialize_tc_lq_<wbr>pair_ffeth(const uint8_t ** curr, void *lq);<br>
><br>
> -static void default_lq_copy_link2neigh_<wbr>ffeth(void *t, void *s);<br>
> +static void default_lq_copy_link2neigh_<wbr>ffeth(void *t, void *s, bool force);<br>
>  static void default_lq_copy_link2tc_ffeth(<wbr>void *target, void *source);<br>
>  static void default_lq_clear_ffeth(void *target);<br>
>  static void default_lq_clear_ffeth_hello(<wbr>void *target);<br>
> @@ -410,11 +410,18 @@ default_lq_memorize_foreign_<wbr>hello_ffeth(void *ptrLocal, void *ptrForeign)<br>
>  }<br>
><br>
>  static void<br>
> -default_lq_copy_link2neigh_<wbr>ffeth(void *t, void *s)<br>
> +default_lq_copy_link2neigh_<wbr>ffeth(void *t, void *s, bool force)<br>
>  {<br>
>    struct default_lq_ffeth *target = t;<br>
>    struct default_lq_ffeth_hello *source = s;<br>
> -  *target = source->smoothed_lq;<br>
> +<br>
> +  if (force) {<br>
> +    *target = source->smoothed_lq;<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  target->valueLq = MAX(target->valueLq, source->smoothed_lq.valueLq);<br>
> +  target->valueNlq = MAX(target->valueNlq, source->smoothed_lq.valueNlq);<br>
>  }<br>
><br>
>  static void<br>
> diff --git a/src/lq_plugin_default_float.<wbr>c b/src/lq_plugin_default_float.<wbr>c<br>
> index 2e07686..f7e2031 100644<br>
> --- a/src/lq_plugin_default_float.<wbr>c<br>
> +++ b/src/lq_plugin_default_float.<wbr>c<br>
> @@ -59,6 +59,7 @@ static int default_lq_serialize_hello_lq_<wbr>pair_float(unsigned char *buff, void *l<br>
>  static void default_lq_deserialize_hello_<wbr>lq_pair_float(const uint8_t ** curr, void *lq);<br>
>  static int default_lq_serialize_tc_lq_<wbr>pair_float(unsigned char *buff, void *lq);<br>
>  static void default_lq_deserialize_tc_lq_<wbr>pair_float(const uint8_t ** curr, void *lq);<br>
> +static void default_lq_copy_link2neigh_<wbr>float(void *t, void *s, bool force);<br>
>  static void default_lq_copy_link2tc_float(<wbr>void *target, void *source);<br>
>  static void default_lq_clear_float(void *target);<br>
>  static const char *default_lq_print_float(void *ptr, char separator, struct lqtextbuffer *buffer);<br>
> @@ -74,7 +75,7 @@ struct lq_handler lq_etx_float_handler = {<br>
><br>
>    &default_lq_packet_loss_<wbr>worker_float,<br>
>    &default_lq_memorize_foreign_<wbr>hello_float,<br>
> -  &default_lq_copy_link2tc_<wbr>float,<br>
> +  &default_lq_copy_link2neigh_<wbr>float,<br>
>    &default_lq_copy_link2tc_<wbr>float,<br>
>    &default_lq_clear_float,<br>
>    &default_lq_clear_float,<br>
> @@ -207,6 +208,22 @@ default_lq_memorize_foreign_<wbr>hello_float(void *ptrLocal, void *ptrForeign)<br>
>  }<br>
><br>
>  static void<br>
> +default_lq_copy_link2neigh_<wbr>float(void *t, void *s, bool force)<br>
> +{<br>
> +  struct default_lq_float *target = t;<br>
> +  struct default_lq_float *source = s;<br>
> +<br>
> +  if (force) {<br>
> +    memcpy(target, source, sizeof(struct default_lq_float));<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  target->lq = MAX(target->lq, source->lq);<br>
> +  target->nlq = MAX(target->nlq, source->nlq);<br>
> +  target->quickstart = MAX(target->quickstart, source->quickstart);<br>
> +}<br>
> +<br>
> +static void<br>
>  default_lq_copy_link2tc_float(<wbr>void *target, void *source)<br>
>  {<br>
>    memcpy(target, source, sizeof(struct default_lq_float));<br>
> diff --git a/src/lq_plugin_default_fpm.c b/src/lq_plugin_default_fpm.c<br>
> index fbfa0cf..2947f92 100644<br>
> --- a/src/lq_plugin_default_fpm.c<br>
> +++ b/src/lq_plugin_default_fpm.c<br>
> @@ -60,6 +60,7 @@ static int default_lq_serialize_hello_lq_<wbr>pair_fpm(unsigned char *buff, void *lq)<br>
>  static void default_lq_deserialize_hello_<wbr>lq_pair_fpm(const uint8_t ** curr, void *lq);<br>
>  static int default_lq_serialize_tc_lq_<wbr>pair_fpm(unsigned char *buff, void *lq);<br>
>  static void default_lq_deserialize_tc_lq_<wbr>pair_fpm(const uint8_t ** curr, void *lq);<br>
> +static void default_lq_copy_link2neigh_<wbr>fpm(void *t, void *s, bool force);<br>
>  static void default_lq_copy_link2tc_fpm(<wbr>void *target, void *source);<br>
>  static void default_lq_clear_fpm(void *target);<br>
>  static const char *default_lq_print_fpm(void *ptr, char separator, struct lqtextbuffer *buffer);<br>
> @@ -75,7 +76,7 @@ struct lq_handler lq_etx_fpm_handler = {<br>
><br>
>    &default_lq_packet_loss_<wbr>worker_fpm,<br>
>    &default_lq_memorize_foreign_<wbr>hello_fpm,<br>
> -  &default_lq_copy_link2tc_fpm,<br>
> +  &default_lq_copy_link2neigh_<wbr>fpm,<br>
>    &default_lq_copy_link2tc_fpm,<br>
>    &default_lq_clear_fpm,<br>
>    &default_lq_clear_fpm,<br>
> @@ -224,6 +225,22 @@ default_lq_copy_link2tc_fpm(<wbr>void *target, void *source)<br>
>  }<br>
><br>
>  static void<br>
> +default_lq_copy_link2neigh_<wbr>fpm(void *t, void *s, bool force)<br>
> +{<br>
> +  struct default_lq_fpm *target = t;<br>
> +  struct default_lq_fpm *source = s;<br>
> +<br>
> +  if (force) {<br>
> +    memcpy(target, source, sizeof(struct default_lq_fpm));<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  target->valueLq = MAX(target->valueLq, source->valueLq);<br>
> +  target->valueNlq = MAX(target->valueNlq, source->valueNlq);<br>
> +  target->quickstart = MAX(target->quickstart, source->quickstart);<br>
> +}<br>
> +<br>
> +static void<br>
>  default_lq_clear_fpm(void *target)<br>
>  {<br>
>    memset(target, 0, sizeof(struct default_lq_fpm));<br>
> diff --git a/src/olsr_protocol.h b/src/olsr_protocol.h<br>
> index a995db0..ed3e134 100644<br>
> --- a/src/olsr_protocol.h<br>
> +++ b/src/olsr_protocol.h<br>
> @@ -111,6 +111,83 @@ struct olsr;<br>
>  #define HIDE_LINK             4<br>
>  #define MAX_LINK              4<br>
><br>
> +/**<br>
> + * Compare two link types.<br>
> + *<br>
> + * <pre><br>
> + * +-------------+------+------+-<wbr>-------+------+-----+<br>
> + * |             |        link_type_new              |<br>
> + * |             +------+------+--------+------<wbr>+-----+<br>
> + * | link_type   | HIDE | LOST | UNSPEC | ASYM | SYM |<br>
> + * |-------------+------+------+-<wbr>-------+------+-----+<br>
> + * | HIDE        |  F   |  T   |   T    |  T   |  T  |<br>
> + * | LOST        |  F   |  F   |   T    |  T   |  T  |<br>
> + * | UNSPEC      |  F   |  F   |   F    |  T   |  T  |<br>
> + * | ASYM        |  F   |  F   |   F    |  F   |  T  |<br>
> + * | SYM         |  F   |  F   |   F    |  F   |  F  |<br>
> + * +-------------+------+------+-<wbr>-------+------+-----+<br>
> + * </pre><br>
> + *<br>
> + * @param link_type a link type<br>
> + * @param link_type_new a (new) link type<br>
> + * @return true when link_type_new is 'better' than link_type<br>
> + */<br>
> +static INLINE bool link_type_compare(int link_type, int link_type_new) {<br>
> +  switch (link_type_new) {<br>
> +    case SYM_LINK:<br>
> +      switch (link_type) {<br>
> +        case SYM_LINK:<br>
> +          return false;<br>
> +<br>
> +        default:<br>
> +          return true;<br>
> +      }<br>
> +      break;<br>
> +<br>
> +    case ASYM_LINK:<br>
> +      switch (link_type) {<br>
> +        case SYM_LINK:<br>
> +        case ASYM_LINK:<br>
> +          return false;<br>
> +<br>
> +        default:<br>
> +          return true;<br>
> +      }<br>
> +      break;<br>
> +<br>
> +    case UNSPEC_LINK:<br>
> +      switch (link_type) {<br>
> +        case SYM_LINK:<br>
> +        case ASYM_LINK:<br>
> +        case UNSPEC_LINK:<br>
> +          return false;<br>
> +<br>
> +        default:<br>
> +          return true;<br>
> +      }<br>
> +      break;<br>
> +<br>
> +    case LOST_LINK:<br>
> +      switch (link_type) {<br>
> +        case SYM_LINK:<br>
> +        case ASYM_LINK:<br>
> +        case UNSPEC_LINK:<br>
> +        case LOST_LINK:<br>
> +          return false;<br>
> +<br>
> +        default:<br>
> +          return true;<br>
> +      }<br>
> +      break;<br>
> +<br>
> +    case HIDE_LINK:<br>
> +      return false;<br>
> +<br>
> +    default:<br>
> +      return true;<br>
> +  }<br>
> +}<br>
> +<br>
>  static INLINE const char * linkTypeToString(int type) {<br>
>    switch (type) {<br>
>      case ASYM_LINK:<br>
> @@ -140,6 +217,65 @@ static INLINE const char * linkTypeToString(int type) {<br>
>  #define MPR_NEIGH             2<br>
>  #define MAX_NEIGH             2<br>
><br>
> +/**<br>
> + * Compare two neighbour types.<br>
> + *<br>
> + * <pre><br>
> + * +-------+------+-----+-----+<br>
> + * |       |     neigh_new    |<br>
> + * |       +------+-----+-----+<br>
> + * | neigh | NOT  | SYM | MPR |<br>
> + * |-------+------+-----+-----+<br>
> + * | NOT   |  F   |  T  |  T  |<br>
> + * | SYM   |  F   |  F  |  T  |<br>
> + * | MPR   |  F   |  F  |  F  |<br>
> + * +-------+------+-----+-----+<br>
> + * </pre><br>
> + *<br>
> + * @param neigh a neighbour type<br>
> + * @param neigh_new a (new) neighbour type<br>
> + * @return true when neigh_new is 'better' than neigh<br>
> + */<br>
> +static INLINE bool neigh_type_compare(int neigh, int neigh_new) {<br>
> +  switch (neigh_new) {<br>
> +    case MPR_NEIGH:<br>
> +      switch (neigh) {<br>
> +        case MPR_NEIGH:<br>
> +          return false;<br>
> +<br>
> +        default:<br>
> +          return true;<br>
> +      }<br>
> +      break;<br>
> +<br>
> +    case SYM_NEIGH:<br>
> +      switch (neigh) {<br>
> +        case MPR_NEIGH:<br>
> +        case SYM_NEIGH:<br>
> +          return false;<br>
> +<br>
> +        default:<br>
> +          return true;<br>
> +      }<br>
> +      break;<br>
> +<br>
> +    case NOT_NEIGH:<br>
> +      switch (neigh) {<br>
> +        case MPR_NEIGH:<br>
> +        case SYM_NEIGH:<br>
> +        case NOT_NEIGH:<br>
> +          return false;<br>
> +<br>
> +        default:<br>
> +          return true;<br>
> +      }<br>
> +      break;<br>
> +<br>
> +    default:<br>
> +      return true;<br>
> +  }<br>
> +}<br>
> +<br>
>  /*<br>
>   *Neighbor status<br>
>   */<br>
><br>
<br>
--<br>
</div></div><span class="gmail-HOEnZb"><font color="#888888">Ferry Huberts<br>
</font></span></blockquote></div><br></div></div>