[Olsr-dev] [PATCH v1 1/1] lq_packet: only report a neighbour once in a hello message

Conrad Lara (spam-protected)
Fri Jan 13 18:52:15 CET 2017


In the end I suspect the RX side needs to be done anyways since this does possibly open a Denial Of Service vulnerability (intentional routing table corruption) that could be exploited from a distance. 

The open nature of many networks does make an easy attack surface already, this however appears to (having. It actually tested on RF) to increases the attack surface due to the fact the receive side can not handle the data it is sent. Unlike most other attacks this however does not appear to require one to be the "stronger" RF signal to exploit either.

If this method is done then the RX side should also be modified to reject any packets that conflict with this definition (which I don't believe I see in this patch) as we know we could see those packets from older OLSR nodes and potentially could see it as an attack vector.

Also how does this sit with RFC3626? One section I keep trying to verify is under 6.1 - Hello Message Format

"A node must perform link sensing on each interface, in order to detect links between the interface and neighbor interfaces. Furthermore, a node must advertise its entire symmetric 1-hop neighborhood on each interface in order to perform neighbor detection. Hence, for a given interface, a HELLO message will contain a list of links on that interface (with associated link types), as well as a list of the entire neighborhood (with an associated neighbor types)."

In particular the line "entire neighborhood (with an associated neighbor types)." trying to wrap my head around if this actually requires the link data to be sent as one has two neighbor links in the neighborhood.  As Teco previously pointed out what is one of the links is in a different state. I believe this is why the announcement calls for all data in the RFC.

Sent from my iPhone

> On Jan 13, 2017, at 1:43 AM, Teco Boot <(spam-protected)> wrote:
> 
> Hmm, again "best".
> Fixing on TX solves for RX nodes that are not updated. 1-1, right?
> :-)
> 
> Teco
> 
> 
>> Op 13 jan. 2017, om 10:24 heeft Conrad Lara <(spam-protected)> het volgende geschreven:
>> 
>> Considering this has been tracked down to a commit on the receive side I tend to concur that this patch doesn't seem to be the best solution. 
>> 
>> I would rather see it resolved RX, especially since that immediately makes new versions compatible with older senders instead of mandating a minimum version of OLSRd be installed for systems to successfully communicate.
>> 
>> Will be at least few days before I can look deeper. 
>> 
>> Sent from my iPhone
>> 
>>> On Jan 13, 2017, at 12:56 AM, Teco Boot <(spam-protected)> wrote:
>>> 
>>> I don't think it is needed, and in fact wrong, to use the "better" link type.
>>> 
>>> The unspec is the link table entry that is for link info of other interfaces. 
>>> In fact it is questionable to send such link info on this interface. This 
>>> because the index is incomplete, the receiver cannot insert or update the 
>>> correct link entry in its table. 
>>> 
>>> Note: tcpdump info below is wrong, the LQ 0.00% is a decode of the wrong field.
>>> Actual value can be seen in hex, with -X.
>>> 
>>> What should the receiver do with such a hello message? For sure, the link
>>> table entry for "this interface", where the link-type != Unspec, shall be 
>>> updated. For the link-type = Unspec, the LQ of a matching entry could be 
>>> updated with this fresh info. But which entry is matching? In the topology
>>> below, there is only one "other interface". So best guessing would pick that 
>>> one. Still not sure, there could be a new third one. In cases with multiple 
>>> other interfaces, guessing is wrong, receiver cannot know which other interface 
>>> link entry to update.
>>> 
>>> See my other post, a solution would be defining a new hello message, with full 
>>> link index: both interface addresses of the link. Let's not go that way.
>>> 
>>> I suggest removing the "select best" logic, it makes no sense. The duplicate
>>> with link-type != Unspec shall be added, so as result two entries are send.
>>> This makes behavior consistent if first entry is link-type = Unspec or
>>> link-type != Unspec.
>>> 
>>> For deciding the approach on receiver, this needs more thoughts. Either 
>>> investigate the "best guess on what link entry to update" or ignore this unspec 
>>> info. Fot the latter, this link-type = Unspec entry can be removed from the 
>>> hello message, as it hasn't any purpose. Or I miss something.
>>> 
>>> Again, I did not fully analyse the code nor this patch. I am just worried we 
>>> take the wrong path fixing the issue.
>>> 
>>> Teco
>>> 
>>> 
>>>> Op 13 jan. 2017, om 09:05 heeft Ferry Huberts <(spam-protected)> het volgende geschreven:
>>>> 
>>>> From: "Iwan G. Flameling" <(spam-protected)>
>>>> 
>>>> A while ago we noticed that neighbours of nodes with multiple interfaces
>>>> on the same medium report infinite costs on their links to those nodes.
>>>> 
>>>> This problem is 100% reproducible.
>>>> 
>>>> Below is the setup in which we noticed the problem.
>>>> 
>>>>    wlan0                                                 wlan0
>>>>    172.31.175.97/16                           172.31.175.61/16
>>>> (((*))) ------------------------------------------------- (((*)))
>>>>    |                                                         |
>>>>    |                                                         |
>>>>    |                                                         |
>>>> ____|___   172.29.175.97/15   ________  172.29.175.61/15  ____|____
>>>> |         |-eth1.2580---------|        |--------eth1.2580-|         |
>>>> | Node 97 |                   | Switch |                  | Node 61 |
>>>> |_________|-eth2.2580---------|________|                  |_________|
>>>>           172.28.175.97/15
>>>> 
>>>> In this setup node 97 will report normal link costs for its (wired) links
>>>> to node 61 (see the first table below), while node 61 will report infinite
>>>> link costs for both its (wired) links to node 97 (see the second table
>>>> below).
>>>> 
>>>> Table: Links (node 97)
>>>> Local IP       Remote IP       Hyst.   LQ      NLQ     Cost
>>>> 172.29.175.97  172.29.175.61   0.000   1.000   1.000   0.100
>>>> 172.28.175.97  172.29.175.61   0.000   1.000   1.000   0.100
>>>> 172.31.175.97  172.31.175.61   0.000   1.000   1.000   1.000
>>>> 
>>>> Table: Links (node 61)
>>>> Local IP       Remote IP       Hyst.   LQ      NLQ     Cost
>>>> 172.29.175.61  172.29.175.97   0.000   1.000   0.000   INFINITE
>>>> 172.29.175.61  172.28.175.97   0.000   1.000   0.000   INFINITE
>>>> 172.31.175.61  172.31.175.97   0.000   1.000   1.000   1.000
>>>> 
>>>> Checking the HELLO messages that are received on node 61 from node 97,
>>>> we see the following:
>>>> 
>>>> [node 61] # tcpdump -vni eth1.2580 udp port 698
>>>> tcpdump: listening on eth1.2580, link-type EN10MB (Ethernet), capture size 262144 bytes
>>>> 06:21:23.528204 IP (tos 0xc0, ttl 1, id 42455, offset 0, flags [DF], proto UDP (17), length 80)
>>>>   172.28.175.97.698 > 255.255.255.255.698: OLSRv4, seq 0xf7c0, length 52
>>>>  Hello-LQ Message (0xc9), originator 172.31.175.97, ttl 1, hop 0
>>>>    vtime 3.000s, msg-seq 0x533d, length 48
>>>>    hello-time 1.000s, MPR willingness 3
>>>>      link-type Symmetric, neighbor-type Symmetric, len 12
>>>>        neighbor 172.29.175.61, link-quality 0.00%, neighbor-link-quality 0.00%
>>>>      link-type Unspecified, neighbor-type Symmetric, len 20
>>>>        neighbor 172.31.175.61, link-quality 0.00%, neighbor-link-quality 0.00%
>>>>        neighbor 172.29.175.61, link-quality 0.00%, neighbor-link-quality 0.00%
>>>> 
>>>> Node 61 receives HELLO messages from node 97 that report (amongst others):
>>>> 1- a  SYMMETRIC   link-type to node 61 (172.29.175.61)
>>>> 2- an UNSPECIFIED link-type to node 61 (172.29.175.61)
>>>> 
>>>> Clearly, this is 'confusing' and the root cause of why node 61 reports
>>>> infinite costs for the links, as shown above.
>>>> 
>>>> We pose that in a HELLO message the same neighbour should NEVER be
>>>> reported with conflicting information.
>>>> 
>>>> Proposed solution:
>>>> 
>>>> 1- NEVER report a neighbour more than once in a HELLO message
>>>> 2- Use the 'best' values for a neighbour that is reported in a HELLO
>>>> message
>>>> 
>>>> This requires:
>>>> 
>>>> 1- De-duplication of neighbours when constructing a HELLO message.
>>>> 
>>>> 2- When a neighbour is already present in the HELLO message
>>>> that is under construction then he 'best' values must be determined
>>>> and those in the neighbour that is already present should only be
>>>> overwritten if those are worse.
>>>> 
>>>> This patch implements that solution.
>>>> 
>>>> Signed-off-by: Iwan G. Flameling <(spam-protected)>
>>>> Signed-off-by: Ferry Huberts <(spam-protected)>
>>>> ---
>>>> src/lq_packet.c               |  52 ++++++++++++----
>>>> src/lq_plugin.c               |   5 +-
>>>> src/lq_plugin.h               |   4 +-
>>>> src/lq_plugin_default_ff.c    |  13 +++-
>>>> src/lq_plugin_default_ffeth.c |  13 +++-
>>>> src/lq_plugin_default_float.c |  19 +++++-
>>>> src/lq_plugin_default_fpm.c   |  19 +++++-
>>>> src/olsr_protocol.h           | 136 ++++++++++++++++++++++++++++++++++++++++++
>>>> 8 files changed, 236 insertions(+), 25 deletions(-)
>>>> 
>>>> diff --git a/src/lq_packet.c b/src/lq_packet.c
>>>> index d44e654..2e8e027 100644
>>>> --- a/src/lq_packet.c
>>>> +++ b/src/lq_packet.c
>>>> @@ -68,6 +68,21 @@ bool lq_tc_pending = false;
>>>> static uint32_t msg_buffer_aligned[(MAXMESSAGESIZE - OLSR_HEADERSIZE) / sizeof(uint32_t) + 1];
>>>> static unsigned char *const msg_buffer = (unsigned char *)msg_buffer_aligned;
>>>> 
>>>> +static struct lq_hello_neighbor * neigh_find(struct link_entry *link, struct lq_hello_message *lq_hello) {
>>>> +  struct lq_hello_neighbor *neigh;
>>>> +
>>>> +  assert(link);
>>>> +  assert(lq_hello);
>>>> +
>>>> +  for (neigh = lq_hello->neigh; neigh; neigh = neigh->next) {
>>>> +    if (ipequal(&link->neighbor_iface_addr, &neigh->addr)) {
>>>> +      return neigh;
>>>> +    }
>>>> +  }
>>>> +
>>>> +  return NULL ;
>>>> +}
>>>> +
>>>> static void
>>>> create_lq_hello(struct lq_hello_message *lq_hello, struct interface_olsr *outif)
>>>> {
>>>> @@ -92,46 +107,57 @@ create_lq_hello(struct lq_hello_message *lq_hello, struct interface_olsr *outif)
>>>> // loop through the link set
>>>> 
>>>> OLSR_FOR_ALL_LINK_ENTRIES(walker) {
>>>> +    uint8_t link_type;
>>>> +    uint8_t neigh_type;
>>>> 
>>>>  // allocate a neighbour entry
>>>> -    struct lq_hello_neighbor *neigh = olsr_malloc_lq_hello_neighbor("Build LQ_HELLO");
>>>> +    struct lq_hello_neighbor *neigh = neigh_find(walker, lq_hello);
>>>> +    bool neigh_is_new = (neigh == NULL );
>>>> +    neigh = neigh_is_new ? olsr_malloc_lq_hello_neighbor("Build LQ_HELLO") : neigh;
>>>> 
>>>>  // a) this neighbor interface IS NOT visible via the output interface
>>>>  if (!ipequal(&walker->local_iface_addr, &outif->ip_addr))
>>>> -      neigh->link_type = UNSPEC_LINK;
>>>> +      link_type = UNSPEC_LINK;
>>>> 
>>>>  // b) this neighbor interface IS visible via the output interface
>>>> 
>>>>  else
>>>> -      neigh->link_type = lookup_link_status(walker);
>>>> +      link_type = lookup_link_status(walker);
>>>> +
>>>> +    if (neigh_is_new || link_type_compare(neigh->link_type, link_type))
>>>> +      neigh->link_type = link_type;
>>>> 
>>>>  // set the entry's link quality
>>>> -    olsr_copy_hello_lq(neigh, walker);
>>>> +    olsr_copy_hello_lq(neigh, walker, neigh_is_new);
>>>> 
>>>>  // set the entry's neighbour type
>>>> 
>>>>  if (walker->neighbor->is_mpr)
>>>> -      neigh->neigh_type = MPR_NEIGH;
>>>> +      neigh_type = MPR_NEIGH;
>>>> 
>>>>  else if (walker->neighbor->status == SYM)
>>>> -      neigh->neigh_type = SYM_NEIGH;
>>>> +      neigh_type = SYM_NEIGH;
>>>> 
>>>>  else if (walker->neighbor->status == NOT_SYM)
>>>> -      neigh->neigh_type = NOT_NEIGH;
>>>> +      neigh_type = NOT_NEIGH;
>>>> 
>>>>  else {
>>>>    OLSR_PRINTF(0, "Error: neigh_type undefined");
>>>> -      neigh->neigh_type = NOT_NEIGH;
>>>> +      neigh_type = NOT_NEIGH;
>>>>  }
>>>> 
>>>> -    // set the entry's neighbour interface address
>>>> +    if (neigh_is_new || neigh_type_compare(neigh->neigh_type, neigh_type))
>>>> +      neigh->neigh_type = neigh_type;
>>>> 
>>>> -    neigh->addr = walker->neighbor_iface_addr;
>>>> +    if (neigh_is_new) {
>>>> +      // set the entry's neighbour interface address
>>>> 
>>>> -    // queue the neighbour entry
>>>> -    neigh->next = lq_hello->neigh;
>>>> -    lq_hello->neigh = neigh;
>>>> +      neigh->addr = walker->neighbor_iface_addr;
>>>> 
>>>> +      // queue the neighbour entry
>>>> +      neigh->next = lq_hello->neigh;
>>>> +      lq_hello->neigh = neigh;
>>>> +    }
>>>> }
>>>> OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
>>>> }
>>>> diff --git a/src/lq_plugin.c b/src/lq_plugin.c
>>>> index a917c84..01c6e4e 100644
>>>> --- a/src/lq_plugin.c
>>>> +++ b/src/lq_plugin.c
>>>> @@ -351,13 +351,14 @@ get_linkcost_scaled(olsr_linkcost cost, bool route)
>>>> *
>>>> * @param target pointer to target lq_hello_neighbor
>>>> * @param source pointer to source link_entry
>>>> + * @param force true to force the copy, otherwise only copy when source is 'better' than target
>>>> */
>>>> void
>>>> -olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source)
>>>> +olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source, bool force)
>>>> {
>>>> assert((const char *)target + sizeof(*target) >= (const char *)target->linkquality);
>>>> assert((const char *)source + sizeof(*source) >= (const char *)source->linkquality);
>>>> -  active_lq_handler->copy_link_lq_into_neigh(target->linkquality, source->linkquality);
>>>> +  active_lq_handler->copy_link_lq_into_neigh(target->linkquality, source->linkquality, force);
>>>> }
>>>> 
>>>> /**
>>>> diff --git a/src/lq_plugin.h b/src/lq_plugin.h
>>>> index 747a70c..26baba4 100644
>>>> --- a/src/lq_plugin.h
>>>> +++ b/src/lq_plugin.h
>>>> @@ -76,7 +76,7 @@ struct lq_handler {
>>>> void (*packet_loss_handler) (struct link_entry * entry, void *lq, bool lost);
>>>> 
>>>> void (*memorize_foreign_hello) (void *local, void *foreign);
>>>> -  void (*copy_link_lq_into_neigh) (void *target, void *source);
>>>> +  void (*copy_link_lq_into_neigh) (void *target, void *source, bool force);
>>>> void (*copy_link_lq_into_tc) (void *target, void *source);
>>>> void (*clear_hello) (void *target);
>>>> void (*clear_tc) (void *target);
>>>> @@ -134,7 +134,7 @@ const char *get_linkcost_text(olsr_linkcost cost, bool route, struct lqtextbuffe
>>>> double get_linkcost_scaled(olsr_linkcost cost, bool route);
>>>> 
>>>> void olsr_clear_hello_lq(struct link_entry */*link*/);
>>>> -void olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source);
>>>> +void olsr_copy_hello_lq(struct lq_hello_neighbor *target, struct link_entry *source, bool force);
>>>> void olsr_copylq_link_entry_2_tc_mpr_addr(struct tc_mpr_addr *target, struct link_entry *source);
>>>> void olsr_copylq_link_entry_2_tc_edge_entry(struct tc_edge_entry *target, struct link_entry *source);
>>>> void olsr_clear_tc_lq(struct tc_mpr_addr *target);
>>>> diff --git a/src/lq_plugin_default_ff.c b/src/lq_plugin_default_ff.c
>>>> index 3d6ba6a..fa617e3 100644
>>>> --- a/src/lq_plugin_default_ff.c
>>>> +++ b/src/lq_plugin_default_ff.c
>>>> @@ -70,7 +70,7 @@ static void default_lq_deserialize_hello_lq_pair_ff(const uint8_t ** curr, void
>>>> static int default_lq_serialize_tc_lq_pair_ff(unsigned char *buff, void *lq);
>>>> static void default_lq_deserialize_tc_lq_pair_ff(const uint8_t ** curr, void *lq);
>>>> 
>>>> -static void default_lq_copy_link2neigh_ff(void *t, void *s);
>>>> +static void default_lq_copy_link2neigh_ff(void *t, void *s, bool force);
>>>> static void default_lq_copy_link2tc_ff(void *target, void *source);
>>>> static void default_lq_clear_ff(void *target);
>>>> static void default_lq_clear_ff_hello(void *target);
>>>> @@ -371,11 +371,18 @@ default_lq_memorize_foreign_hello_ff(void *ptrLocal, void *ptrForeign)
>>>> }
>>>> 
>>>> static void
>>>> -default_lq_copy_link2neigh_ff(void *t, void *s)
>>>> +default_lq_copy_link2neigh_ff(void *t, void *s, bool force)
>>>> {
>>>> struct default_lq_ff *target = t;
>>>> struct default_lq_ff_hello *source = s;
>>>> -  *target = source->smoothed_lq;
>>>> +
>>>> +  if (force) {
>>>> +    *target = source->smoothed_lq;
>>>> +    return;
>>>> +  }
>>>> +
>>>> +  target->valueLq = MAX(target->valueLq, source->smoothed_lq.valueLq);
>>>> +  target->valueNlq = MAX(target->valueNlq, source->smoothed_lq.valueNlq);
>>>> }
>>>> 
>>>> static void
>>>> diff --git a/src/lq_plugin_default_ffeth.c b/src/lq_plugin_default_ffeth.c
>>>> index e78dcd7..0e9408e 100644
>>>> --- a/src/lq_plugin_default_ffeth.c
>>>> +++ b/src/lq_plugin_default_ffeth.c
>>>> @@ -72,7 +72,7 @@ static void default_lq_deserialize_hello_lq_pair_ffeth(const uint8_t ** curr, vo
>>>> static int default_lq_serialize_tc_lq_pair_ffeth(unsigned char *buff, void *lq);
>>>> static void default_lq_deserialize_tc_lq_pair_ffeth(const uint8_t ** curr, void *lq);
>>>> 
>>>> -static void default_lq_copy_link2neigh_ffeth(void *t, void *s);
>>>> +static void default_lq_copy_link2neigh_ffeth(void *t, void *s, bool force);
>>>> static void default_lq_copy_link2tc_ffeth(void *target, void *source);
>>>> static void default_lq_clear_ffeth(void *target);
>>>> static void default_lq_clear_ffeth_hello(void *target);
>>>> @@ -410,11 +410,18 @@ default_lq_memorize_foreign_hello_ffeth(void *ptrLocal, void *ptrForeign)
>>>> }
>>>> 
>>>> static void
>>>> -default_lq_copy_link2neigh_ffeth(void *t, void *s)
>>>> +default_lq_copy_link2neigh_ffeth(void *t, void *s, bool force)
>>>> {
>>>> struct default_lq_ffeth *target = t;
>>>> struct default_lq_ffeth_hello *source = s;
>>>> -  *target = source->smoothed_lq;
>>>> +
>>>> +  if (force) {
>>>> +    *target = source->smoothed_lq;
>>>> +    return;
>>>> +  }
>>>> +
>>>> +  target->valueLq = MAX(target->valueLq, source->smoothed_lq.valueLq);
>>>> +  target->valueNlq = MAX(target->valueNlq, source->smoothed_lq.valueNlq);
>>>> }
>>>> 
>>>> static void
>>>> diff --git a/src/lq_plugin_default_float.c b/src/lq_plugin_default_float.c
>>>> index 2e07686..f7e2031 100644
>>>> --- a/src/lq_plugin_default_float.c
>>>> +++ b/src/lq_plugin_default_float.c
>>>> @@ -59,6 +59,7 @@ static int default_lq_serialize_hello_lq_pair_float(unsigned char *buff, void *l
>>>> static void default_lq_deserialize_hello_lq_pair_float(const uint8_t ** curr, void *lq);
>>>> static int default_lq_serialize_tc_lq_pair_float(unsigned char *buff, void *lq);
>>>> static void default_lq_deserialize_tc_lq_pair_float(const uint8_t ** curr, void *lq);
>>>> +static void default_lq_copy_link2neigh_float(void *t, void *s, bool force);
>>>> static void default_lq_copy_link2tc_float(void *target, void *source);
>>>> static void default_lq_clear_float(void *target);
>>>> static const char *default_lq_print_float(void *ptr, char separator, struct lqtextbuffer *buffer);
>>>> @@ -74,7 +75,7 @@ struct lq_handler lq_etx_float_handler = {
>>>> 
>>>> &default_lq_packet_loss_worker_float,
>>>> &default_lq_memorize_foreign_hello_float,
>>>> -  &default_lq_copy_link2tc_float,
>>>> +  &default_lq_copy_link2neigh_float,
>>>> &default_lq_copy_link2tc_float,
>>>> &default_lq_clear_float,
>>>> &default_lq_clear_float,
>>>> @@ -207,6 +208,22 @@ default_lq_memorize_foreign_hello_float(void *ptrLocal, void *ptrForeign)
>>>> }
>>>> 
>>>> static void
>>>> +default_lq_copy_link2neigh_float(void *t, void *s, bool force)
>>>> +{
>>>> +  struct default_lq_float *target = t;
>>>> +  struct default_lq_float *source = s;
>>>> +
>>>> +  if (force) {
>>>> +    memcpy(target, source, sizeof(struct default_lq_float));
>>>> +    return;
>>>> +  }
>>>> +
>>>> +  target->lq = MAX(target->lq, source->lq);
>>>> +  target->nlq = MAX(target->nlq, source->nlq);
>>>> +  target->quickstart = MAX(target->quickstart, source->quickstart);
>>>> +}
>>>> +
>>>> +static void
>>>> default_lq_copy_link2tc_float(void *target, void *source)
>>>> {
>>>> memcpy(target, source, sizeof(struct default_lq_float));
>>>> diff --git a/src/lq_plugin_default_fpm.c b/src/lq_plugin_default_fpm.c
>>>> index fbfa0cf..2947f92 100644
>>>> --- a/src/lq_plugin_default_fpm.c
>>>> +++ b/src/lq_plugin_default_fpm.c
>>>> @@ -60,6 +60,7 @@ static int default_lq_serialize_hello_lq_pair_fpm(unsigned char *buff, void *lq)
>>>> static void default_lq_deserialize_hello_lq_pair_fpm(const uint8_t ** curr, void *lq);
>>>> static int default_lq_serialize_tc_lq_pair_fpm(unsigned char *buff, void *lq);
>>>> static void default_lq_deserialize_tc_lq_pair_fpm(const uint8_t ** curr, void *lq);
>>>> +static void default_lq_copy_link2neigh_fpm(void *t, void *s, bool force);
>>>> static void default_lq_copy_link2tc_fpm(void *target, void *source);
>>>> static void default_lq_clear_fpm(void *target);
>>>> static const char *default_lq_print_fpm(void *ptr, char separator, struct lqtextbuffer *buffer);
>>>> @@ -75,7 +76,7 @@ struct lq_handler lq_etx_fpm_handler = {
>>>> 
>>>> &default_lq_packet_loss_worker_fpm,
>>>> &default_lq_memorize_foreign_hello_fpm,
>>>> -  &default_lq_copy_link2tc_fpm,
>>>> +  &default_lq_copy_link2neigh_fpm,
>>>> &default_lq_copy_link2tc_fpm,
>>>> &default_lq_clear_fpm,
>>>> &default_lq_clear_fpm,
>>>> @@ -224,6 +225,22 @@ default_lq_copy_link2tc_fpm(void *target, void *source)
>>>> }
>>>> 
>>>> static void
>>>> +default_lq_copy_link2neigh_fpm(void *t, void *s, bool force)
>>>> +{
>>>> +  struct default_lq_fpm *target = t;
>>>> +  struct default_lq_fpm *source = s;
>>>> +
>>>> +  if (force) {
>>>> +    memcpy(target, source, sizeof(struct default_lq_fpm));
>>>> +    return;
>>>> +  }
>>>> +
>>>> +  target->valueLq = MAX(target->valueLq, source->valueLq);
>>>> +  target->valueNlq = MAX(target->valueNlq, source->valueNlq);
>>>> +  target->quickstart = MAX(target->quickstart, source->quickstart);
>>>> +}
>>>> +
>>>> +static void
>>>> default_lq_clear_fpm(void *target)
>>>> {
>>>> memset(target, 0, sizeof(struct default_lq_fpm));
>>>> diff --git a/src/olsr_protocol.h b/src/olsr_protocol.h
>>>> index a995db0..ed3e134 100644
>>>> --- a/src/olsr_protocol.h
>>>> +++ b/src/olsr_protocol.h
>>>> @@ -111,6 +111,83 @@ struct olsr;
>>>> #define HIDE_LINK             4
>>>> #define MAX_LINK              4
>>>> 
>>>> +/**
>>>> + * Compare two link types.
>>>> + *
>>>> + * <pre>
>>>> + * +-------------+------+------+--------+------+-----+
>>>> + * |             |        link_type_new              |
>>>> + * |             +------+------+--------+------+-----+
>>>> + * | link_type   | HIDE | LOST | UNSPEC | ASYM | SYM |
>>>> + * |-------------+------+------+--------+------+-----+
>>>> + * | HIDE        |  F   |  T   |   T    |  T   |  T  |
>>>> + * | LOST        |  F   |  F   |   T    |  T   |  T  |
>>>> + * | UNSPEC      |  F   |  F   |   F    |  T   |  T  |
>>>> + * | ASYM        |  F   |  F   |   F    |  F   |  T  |
>>>> + * | SYM         |  F   |  F   |   F    |  F   |  F  |
>>>> + * +-------------+------+------+--------+------+-----+
>>>> + * </pre>
>>>> + *
>>>> + * @param link_type a link type
>>>> + * @param link_type_new a (new) link type
>>>> + * @return true when link_type_new is 'better' than link_type
>>>> + */
>>>> +static INLINE bool link_type_compare(int link_type, int link_type_new) {
>>>> +  switch (link_type_new) {
>>>> +    case SYM_LINK:
>>>> +      switch (link_type) {
>>>> +        case SYM_LINK:
>>>> +          return false;
>>>> +
>>>> +        default:
>>>> +          return true;
>>>> +      }
>>>> +      break;
>>>> +
>>>> +    case ASYM_LINK:
>>>> +      switch (link_type) {
>>>> +        case SYM_LINK:
>>>> +        case ASYM_LINK:
>>>> +          return false;
>>>> +
>>>> +        default:
>>>> +          return true;
>>>> +      }
>>>> +      break;
>>>> +
>>>> +    case UNSPEC_LINK:
>>>> +      switch (link_type) {
>>>> +        case SYM_LINK:
>>>> +        case ASYM_LINK:
>>>> +        case UNSPEC_LINK:
>>>> +          return false;
>>>> +
>>>> +        default:
>>>> +          return true;
>>>> +      }
>>>> +      break;
>>>> +
>>>> +    case LOST_LINK:
>>>> +      switch (link_type) {
>>>> +        case SYM_LINK:
>>>> +        case ASYM_LINK:
>>>> +        case UNSPEC_LINK:
>>>> +        case LOST_LINK:
>>>> +          return false;
>>>> +
>>>> +        default:
>>>> +          return true;
>>>> +      }
>>>> +      break;
>>>> +
>>>> +    case HIDE_LINK:
>>>> +      return false;
>>>> +
>>>> +    default:
>>>> +      return true;
>>>> +  }
>>>> +}
>>>> +
>>>> static INLINE const char * linkTypeToString(int type) {
>>>> switch (type) {
>>>>  case ASYM_LINK:
>>>> @@ -140,6 +217,65 @@ static INLINE const char * linkTypeToString(int type) {
>>>> #define MPR_NEIGH             2
>>>> #define MAX_NEIGH             2
>>>> 
>>>> +/**
>>>> + * Compare two neighbour types.
>>>> + *
>>>> + * <pre>
>>>> + * +-------+------+-----+-----+
>>>> + * |       |     neigh_new    |
>>>> + * |       +------+-----+-----+
>>>> + * | neigh | NOT  | SYM | MPR |
>>>> + * |-------+------+-----+-----+
>>>> + * | NOT   |  F   |  T  |  T  |
>>>> + * | SYM   |  F   |  F  |  T  |
>>>> + * | MPR   |  F   |  F  |  F  |
>>>> + * +-------+------+-----+-----+
>>>> + * </pre>
>>>> + *
>>>> + * @param neigh a neighbour type
>>>> + * @param neigh_new a (new) neighbour type
>>>> + * @return true when neigh_new is 'better' than neigh
>>>> + */
>>>> +static INLINE bool neigh_type_compare(int neigh, int neigh_new) {
>>>> +  switch (neigh_new) {
>>>> +    case MPR_NEIGH:
>>>> +      switch (neigh) {
>>>> +        case MPR_NEIGH:
>>>> +          return false;
>>>> +
>>>> +        default:
>>>> +          return true;
>>>> +      }
>>>> +      break;
>>>> +
>>>> +    case SYM_NEIGH:
>>>> +      switch (neigh) {
>>>> +        case MPR_NEIGH:
>>>> +        case SYM_NEIGH:
>>>> +          return false;
>>>> +
>>>> +        default:
>>>> +          return true;
>>>> +      }
>>>> +      break;
>>>> +
>>>> +    case NOT_NEIGH:
>>>> +      switch (neigh) {
>>>> +        case MPR_NEIGH:
>>>> +        case SYM_NEIGH:
>>>> +        case NOT_NEIGH:
>>>> +          return false;
>>>> +
>>>> +        default:
>>>> +          return true;
>>>> +      }
>>>> +      break;
>>>> +
>>>> +    default:
>>>> +      return true;
>>>> +  }
>>>> +}
>>>> +
>>>> /*
>>>> *Neighbor status
>>>> */
>>>> -- 
>>>> 2.9.3
>>>> 
>>> 
>>> 
>>> -- 
>>> Olsr-dev mailing list
>>> (spam-protected)
>>> https://lists.olsr.org/mailman/listinfo/olsr-dev
>> 
> 




More information about the Olsr-dev mailing list