Subject: [manet] AODVv2 Review from an implementation perspective

From: Lotte Steenbrink <[email-masked]>
Date: Wed, 29 Oct 2014 19:59:27 +0100

Dear MANET WG members,

I would like to share the experiences that I've gained by implementing AODVv2
for my Bachelor's Thesis with the Working Group.
My review is still based on the old version of AODVv2, namely draft-ietf-manet-aodvv2-04,
but because IETF91 is approaching fast, I'll publish it anyway and follow up
with another, smaller one regarding the changes from version 05 in the next few days.

It is important to note that I only implemented the core feature set imperative
for AODVv2 to be able to function as a routing protocol. *not* implemented are:

- AckReqs / RREP-ACKs
- alternate metrics
- multiple interfaces
- clients and Client Networks
- buffering
- addresses, TLVs, and features that are marked as optional

This also means that I did not go through the numerous sections on optional
features in detail. In consequence, my review does not cover them. You can find
a full summary of what I implemented at [1].

On the technical side of things, please note that I implemented AODVV2
over 6LowPAN for RIOT[2], an Operating System targeted mainly at embedded devices
for the Internet of Things. While much of the code should be portable to Linux,
it does have its quirks and there are some problems that I just didn't run into
(for example to problem of getting the Linux network stack to work with a
reactive protocol, as discussed earlier on this list[3]).

I used Henning Rogge's oonf-api[4] to build and parse RFC5444 packets.

Here we go:

General condition of the draft
==============================

    Structure
    ---------

    As far as I can see, the aim seems to be to follow a bottom-up approach and first
    introduce every concept needed for the implementation of more complex components.

    One example for this is Section 7.5.  Handling a Received RteMsg:
    It contains references to earlier sections 5.4. and  6.1., with the latter
    containing a reference to earlier section 5.6.

    While this approach makes very much sense in theory, I found that it made me
    read the draft more often: At first, I read it from cover to cover,
    with the first sections seeming reasonable, but without context. Then, I went
    through it again, looking for the top-level concepts that I could implement
    (I found most of them in the last 2/3 of the draft). During this implementation,
    I then was able to go back to the first 1/3 to use the concepts described.
    A re-ordering of the content in a way that may guide the reader more may
    make the document more inviting.

    Below, you can find a rough suggestion for a possible re-ordering of the first
    9 sections. I kept the original numbering to make referencing the sections easier.
    My reasoning for the suggested changes was the following:

    * Sections 5. Data Structures and 6. AODVv2 Operations on Route Table Entries
      often reference fields of Route Messages (i.e. RREQ, RREP and RERR) which are
      yet to be introduced in Section 7.  Routing Messages RREQ and RREP (RteMsgs).

      To me, it would be more intuitive if the Message Format was introduced first,
      giving the reader insight into the content and workings of Route Messages.

      My placement of 8.  Route Maintenance and RERR Messages right behind seems a
      bit off, but I am still unsure how to resolve this. However, it might make sense
      to follow the example of 7.  Routing Messages RREQ and RREP (RteMsgs) and
      introduce the packet format before describing its handling. The RERR format is
      described in 8.3.  RERR Generation. I'd suggest to add a new dedicated subsection
      (I called it “?.?   RERR Structure ”), containing the first 6 paragraphs of
      subsection 8.3. The "new" 8.3. would then start with “There are two kinds of
      events indicating that packets cannot be delivered to certain destinations”.

    * Even though it talks about Packet rather than Message headers, I'd have expected
      Section 5.4.   AODVv2 Message Header Fields and Information Elements to be grouped
      somewhere near the Message format descriptions. 9.  Unknown Message and TLV Types
      also contains a remark I'd have expected near the message format descriptions.
      However, both apply to all messages (i.e. the ones described in 7. as well as 8.),
      so putting them in either 7. or 8. would not make sense. This is why I added
      a new section for them (called “Message format considerations”, a working title
      with much need for improvement).

    Table of Contents

       1.  Overview  . . . . . . . . . . . . . . . . . . . . . . . . . .   4
       2.  Terminology . . . . . . . . . . . . . . . . . . . . . . . . .   5
       3.  Notational Conventions  . . . . . . . . . . . . . . . . . . .   7
       4.  Applicability Statement . . . . . . . . . . . . . . . . . . .   8
       ?.  Message format considerations . . . . . . . . . . . . . . . .   ?
         5.4.  AODVv2 Message Header Fields and Information Elements . .  13
         9.  Unknown Message and TLV Types . . . . . . . . . . . . . . .  32
       7.  Routing Messages RREQ and RREP (RteMsgs)  . . . . . . . . . .  20
         7.1.  Route Discovery Retries and Buffering . . . . . . . . . .  21
         7.2.  RteMsg Structure  . . . . . . . . . . . . . . . . . . . .  22
         7.3.  RREQ Generation . . . . . . . . . . . . . . . . . . . . .  23
         7.4.  RREP Generation . . . . . . . . . . . . . . . . . . . . .  24
         7.5.  Handling a Received RteMsg  . . . . . . . . . . . . . . .  25
           7.5.1.  Additional Handling for Incoming RREQ . . . . . . . .  26
           7.5.2.  Additional Handling for Incoming RREP . . . . . . . .  26
         7.6.  Suppressing Redundant RREQ messages . . . . . . . . . . .  27
       8.  Route Maintenance and RERR Messages . . . . . . . . . . . . .  27
         ?.?   RERR Structure  . . . . . . . . . . . . . . . . . . . . .  ??
         8.1.  Maintaining Route Lifetimes During Packet Forwarding  . .  28
         8.2.  Active Next-hop Router
               Adjacency Monitoring  . . . . . . . . . . . . . . . . . .  28
         8.3.  RERR Generation . . . . . . . . . . . . . . . . . . . . .  28
           8.3.1.  Case 1: Undeliverable Packet  . . . . . . . . . . . .  30
           8.3.2.  Case 2: Broken Link . . . . . . . . . . . . . . . . .  30
         8.4.  Receiving and Handling RERR Messages  . . . . . . . . . .  31
       5.  Data Structures . . . . . . . . . . . . . . . . . . . . . . .  10
         5.1.  Route Table Entry . . . . . . . . . . . . . . . . . . . .  10
         5.2.  Bidirectional Connectivity and Blacklists . . . . . . . .  11
         5.3.  Router Clients and Client Networks  . . . . . . . . . . .  12
         5.5.  Sequence Numbers  . . . . . . . . . . . . . . . . . . . .  14
         5.6.  Enabling Alternate Metrics  . . . . . . . . . . . . . . .  14
         5.7.  RREQ Table: Received RREQ Messages  . . . . . . . . . . .  16
       6.  AODVv2 Operations on Route Table Entries  . . . . . . . . . .  17
         6.1.  Evaluating Incoming Routing Information . . . . . . . . .  18
         6.2.  Applying Route Updates To Route Table Entries . . . . . .  19
         6.3.  Route Table Entry Timeouts  . . . . . . . . . . . . . . .  20

    Scope
    -----

    The AODVv2 Draft contains a lot of additional, optional features. I understand
    that this has historic reasons. However, this may make it hard for a new reader
    to grasp the essence of the AODVv2 routing protocol. It may also make it harder to
    find irregularities in the core of the draft specification.
    Some or all of these features may be useful or even important in the future,
    but, in my opinion, in its current state the draft may benefit from a re-evaluation
    of their importance.
    Removing them temporarily (or moving them to an additional draft) would make
    it easier to focus on the core of the protocol. After the core spec is finished,
    the optional features can be adjusted to its new state if necessary.
    This also provides he chance for re-evaluation of their wording.
    (One example for this is the AckReq vs. RREP_ACK complex, which is discussed
    in more detail later in this document.)

    For my thesis, I put together snippets of the draft which I thought described
    a “minimal version” of AODVv2 containing only the bare necessities which can
    be found at [1]. Although not very polished (because mostly intended for personal
    use), this may be a starting point for an AODVv2 boilerplate draft.

    Style and consistency
    ---------------------

    As Thomas Heide Clausen pointed out[5], the draft often consists of continuous
    text instead of a more "bullet point-y" style. I agree with Mr. Clausen that
    this may be not optional for the implementation process.
    AODVv2 does have sections which exhibit a more concise style (for example Sections
    7.3. - 7.5.2. or Section 8.1), which I found very comfortable during implementation.
    I would suggest to (partly) render sections 6.1, 8.31, 8.3.2, 7.1, and 5.7
    in this style as well. In case this is approved by the WG, I'd be happy to help
    with the rewriting.

    I am also in favor of this kind of style over any kind of pseudo-code, which
    may be harder to read (especially if it has not been defined beforehand) and
    demands more complicated context switches (code-to-code instead of text-to-code)
    from the implementor.

    The draft specification mainly employs CamelCase, but switches to snake_case
    on some occasions. This makes sense for all-caps constant names which would
    be otherwise unreadable, but vocabulary such as Metric_TLV, SeqNum_TLV,
    OrigSeqNum_TLV, TargSeqNum_TLV, RREQ_Gen, RREP_Gen, Current_Time, Dest_1,
    or Dest_2 seems inconsistent.
    This might be a minor issue, but I believe the general polishedness of the
    draft may benefit from a more consistent adoption of CamelCase, such as:
    MetricTLV, SeqNumTLV, OrigSeqNumTLV, TargSeqNumTLV, RREQGen, RREPGen,
    CurrentTime, Dest1, and Dest2.

    In section 5.1.  Route Table Entry, the draft mentions a "routing table entry"
    instead of using the term "route table", which is employed through the rest
    of the draft. The same glitch can be found in sections 5.5, 6.1. and 8.4..
    Again, this is a minor issue, but one that has caused some initial confusion.
    (This has been pointed out in an earlier e-mail [6])

    Locality
    --------

    Descriptions of some features can be found scattered across the document.
    A dedicated (sub)section which describes them might be helpful to the reader
    in finding and understanding them. Specifically, i would like to point out
    the following two features:

    - As discussed in section 5.1., routes will expire after a certain amount of
      time. At first sight, it seemed to me that there are two criteria for when
      a route may be considered Expired.

      The first can be found in Section 5.1.  Route Table Entry:

          After an idle route
          remains Idle for MAX_IDLETIME, it becomes an Expired route.

      And the second in Section 6.2.  Applying Route Updates To Route Table Entries:

         o  If RteMsg.VALIDITY_TIME is included, then
            Route.ExpirationTime := Current_Time + RteMsg.VALIDITY_TIME,
            otherwise, Route.ExpirationTime := Current_Time + (ACTIVE_INTERVAL
            + MAX_IDLETIME).

      To my eyes, the first excerpt looked like a stand-alone instruction.
      However, since it takes ACTIVE_INTERVAL time for a route to turn Idle,
      Section 5.1. describes exactly the same thing as Section 6.2.
      (provided RteMsg.VALIDITY_TIME is not included).

      I didn't pay attention properly, and first checked for both conditions,
      later on realizing that I was checking for the same thing twice.
      This is why, to me, it would make more sense to outline the nature of Expired
      routes (and the like) and then point to section 6.2. for more details. Another
      possible approach would be to adjust the wording to be identical in the discussed
      parts of sections 5.1. and 6.2., making it clear that they're talking about
      the same thing.

    - AODVv2 describes a Cost() function which returns the cost of a link L or a route R.
      It is briefly discussed in section 5.6 and referenced in sections 6.1., 6.2.,
      and 7.5. The description in section 6.1. does not specify in which range the
      values returned by the Cost() function(s) may be. To my mind, a small
      (sub)section describing what exactly Cost(L) and Cost(R) means and which
      range of values to expect from them would improve the quality of the draft.

    Clarity
    -------

    An earlier version of this review contained criticism of the use of the word
    “relevant” in the following part of Section 6.1 Evaluating Incoming Routing Information:

        Whenever an AODVv2 router (HandlingRtr)
        handles an incoming RteMsg (i.e., RREQ or RREP), for every relevant
        address (RteMsg.Address) in the RteMsg, HandlingRtr searches its
        route table to see if there is a route table entry with the same
        Metric Type of the RteMsg, matching RteMsg.Address.

    My criticism was as follows:

        The draft specification gives no pointers on what might qualify as a
        "relevant" address. From the context of the Draft, I concluded that
        only the OrigNode address of a RREQ and only the TargNode address of a
        RREP are associated with a Sequence number.  In consequence, only the
        OrigNode Address of a RREQ and the TargNode address of a RREP qualify as
        a "relevant" address, because only their metric can be compared
        to the one noted in the routing table (if such an entry exists).

    However, in the changelogs of draft-ietf-manet-aodvv2-04, one can find the remark

        o  Reworded text to avoid use of "relevant".

    This rewording seems to have consisted of removing the word "relevant" from
    the paragraph cited above. Assuming my assumptions as stated above are correct,
    I would like to suggest another rewording, since

    a) Not every address is associated with a SeqNum (for example the TargNode Address
       of a RREQ) or a Metric TLV (same example). Still, section 6.1. instructs the
       implementor to add a route table entry for them, pointing towards section 6.2. --
       which then requires metric and SeqNum TLVs that don't exist.
       This seems like a loophole to me.

    b) Adding -for example- the TargNode Address of a RREQ to the routing table,
       when, at this point in the route discovery, there is no guarantee that this
       route even exists seems counterproductive to me.

    A possible second rewording could be along the lines of

        Whenever an AODVv2 router (HandlingRtr)
        handles an incoming RteMsg (i.e., RREQ or RREP), for every relevant
        address (RteMsg.Address) in the RteMsg, HandlingRtr searches its
        route table to see if there is a route table entry with the same
        Metric Type of the RteMsg, matching RteMsg.Address.
        Addresses that qualify as relevant are:
        * The OrigNode Address of a RREQ
        * The TargNode Address of a RREP

Reported problems
=================

    During my work on AODVv2 so far, I opened a few issues on the tracker and the
    Mailing list. For the sake of completeness, I will list them again.

    * The Route.Broken flag appears to be redundant [7]
    * AckReq vs RREP_ACK seem to be two mechanisms serving the same purpose [8]
      (The Mailing List discussion around this topic can be found here [9])
    * It is unclear what happens if Active routes exceed RERR packet size [10]
      (The Mailing List discussion around this topic can be found here [11])
    * Issue concerning RREQ redundancy check methodology and order [12]

Message Format
==============

    As far as I know, the way AODVv2 adopts RFC 5444 has been subject to
    controversy in the past, but since it is one of my main struggles with the
    draft, I'm going to have to discuss it yet again.

    In general, I had trouble figuring out how to start building the packets. While
    the specification provides guidelines on which data to put where, "the big picture"
    is missing. The sketches in Appendix A. were a starting point, but while they
    are explicit in what needs to be in a packet, they do not contain information
    about the structure of the information (which makes sense).

    When I consulted the Draft's text to figure this out, the notation with which
    the contents of a Route Message are specified was not very intuitive to me.
    One example is the following:

        4.   RREP.OrigSeqNumTLV[OrigNodeNdx]  := Route[OrigNode].Seqnum
        5.   RREP.TargSeqNumTLV[TargNodeNdx]  := RREP_Gen's SeqNum

    Looking through my notes, what seemed to confuse me was:
    - what does OrigNodeNdx mean? Assuming "Ndx" is short for Index, what is
    the index of the Originating node?
    - what does the notation "message.TLV[Ndx]" mean? Assuming [Ndx] is used to
    describe content at place Ndx of some kind of array, why is there an array of
    values in one TLV?
    - what are the types of these SeqNumTLVs? Are they both of type SeqNum or of
    type OrigNodeSeqNum and TargNodeSeqNum? Table 15.3. lists all three as valid
    TLV types, how does this go together?

    It turned out that there are actually *two* Message Formats being described
    in the AODVv2 Draft, even though this is not explicitly stated.

    What I have been able to reconstruct until now is the following:
    The first and original Message Format springs from the wish to send as few
    bytes as possible over the air. The second format was adopted after some
    suggestions by Henning Rogge and aims to make use of RFC5444's features:
    Modularity, readability and easy extensibility. I dubbed them "the minimal
    version" and "the verbose version". They differ in the way Metric,
    Metric Type and Sequence Number TLVs are stored.
    I understood them to work as follows:

    * Minimal *
        There are three Multi-value Address Block TLVs: One for all Metric
        values, one for all Metric Types and one for all Sequence Numbers.

        These Multi-value TLVs are all associated with the *range* between the
        first address whose information they store (denoted by index-start) and
        the last address whose information they store (denoted by index-stop).

        Because RFC 5444 only supports ranges for TLVs associated with more than
        one address, this means that this range may include addresses whose
        information is not stored in these multi-value TLVs. RFC5444 mandates
        that, if a range is specified, there has to be a TLV value for every
        address block in the range.

        The minimal approach may save bytes if multiple values of one type are present
        (For example Originating and Target Node Sequence Numbers in RREPs),
        but it also means that additional bytes may have to be added to stuff these TLVs:

        Suppose a protocol extension MyExtension extends RREQ with an address MyAddress,
        and a Sequence Number MyMetric. MyAddress would be the third address of
        the Address Block. Since no Metric for TargNode is stored, an
        interruption in the sequence between index-start (the OrigNode address)
        and index-stop (MyAddress) exists. This may be resolved in two ways.
        The Metric TLV would either have to be stuffed with an invalid
        and arbitrary TargNode Metric, or a new TLV of a different type
        would have to be added to the address block.
        The draft does not provide any pointers on how the packet format provided
        may be extended correctly.

        After figuring this out, the content description discussed above made sense
        as well. In my opinion, it would have been very helpful to have something
        like the above explanation noted and/or illustrated in the beginning of
        Section 7.2.

    * Verbose *
        Metric, Metric Type and Sequence Number are stored in a TLV each. Each of
        these TLVs is associated with one address, giving it context (i.e. an
        address which has a TLV of type RFC5444_MSGTLV_ORIGSEQNUM can be assumed
        to be an Originating node Address).
        Since the fashion in which additional data should be appended is described
        in RFC 5444, there is no need for explicit instructions in the AODVv2 draft.

    I hope I described the two versions correctly.

    I decided to implement the verbose version because I found it easier to grasp,
    read and extend. The schema-based compression suggested by Henning Rogge[13]
    looked promising to me in order to further reduce packet size if necessary,
    and as far as I understood it would only work with the verbose approach because
    address order may not be respected.
    The resulting packets did not exceed the 81 bytes of payload that IEEE 802.15.4 left me.

    In the spirit of this message format, I also decided to stray from the
    specification when storing the Metric Type:

    The Draft suggests to add a special "Metric Type" TLV for every Metric TLV
    that is added. This seemed like unnecessary overhead to me, and since
    RFC 5444 offers the nice feature of extension types, I decided to make use of
    it in order to specify the Metric Type of each Metric TLV. So, for example,
    a TLV that stores the Metric of an Originating Node in a RREQ may look like this:

    type:        RFC5444_MSGTLV_METRIC
        exttype: AODVV2_DEFAULT_METRIC_TYPE
    length:      1
    value:       1

    If I understood RFC5444 correctly, this saves bytes in both message format
    types described above, which is why I would suggest the adoption of this.
    However, I think it is important to stress that I do not suggest an immediate
    change: In my opinion, it is imperative to sort the existing format(s) out,
    describe them clearly and *then* have a look at what can be improved or optimized.

    In case this approach is approved by the Working Group, I would like to
    help with the changes, if the authors are interested.

Handling links to 1-hop neighbors
=================================

    AODVv2 describes two ways of checking and monitoring connectivity to direct
    neighbors:
    5.2.  Bidirectional Connectivity and Blacklists describes the AckReq mechanism,
    which is used to fill a blacklist for nodes to which a bidirectional link
    could not be established. (The RREP_ACK mechanism described in Section 13.5.
    may fall in this category also)
    8.2.  Active Next-hop Router Adjacency Monitoring described mechanisms which
    may be used to monitor the connectivity to 1-hop neighbors. If a known link
    breaks, these mechanisms trigger the dispatching of a RERR message. This does
    not have any effect on the blacklist described in Section 5.2.

    If I understood the draft correctly, these 2 mechanisms are not equivalent,
    because while Section 5.2. checks for bidirectional connectivity to avoid the
    use of a unidirectional link, the mechanisms in Section 8.2. only kick in
    *after* a link has broken. They are not consulted concerning the possible
    unidirectionality of a link directly and, since they do not have an effect on
    the blacklist described in 5.2., can't warn about unidirectional links
    indirectly either.

    Since I did not implement the AckReq mechanism, I relied solely on RIOTs
    implementation of the IPv6 Neighbor Discovery to detect broken links.
    This fell on my foot when I accidentally created the following scenario:

    I was testing my implementation on a 4x4 grid of emulated RIOT nodes, with
    nodes trying to establish a route towards other nodes that were at least 3 hops away.
    Due to a bug, some nodes would receive RREQs from 2-hop neighbors *directly*,
    making them think that those 2 hop neighbors were actually direct neighbors and
    adding them as a next hop towards the originating node to the routing table.
    (In short, I accidentally created unidirectional links in an environment that
    was supposed to be perfect)

    Now, when a RREP traveled back that path and reached the node that added a 2 hop
    neighbor as the next hop towards the originating node, the node would
    look return said 2 hop neighbor as the next hop. The network stack would try to
    send the RREP to the returned 2 hop neighbor, notice that the 2 hop neighbor
    is not in the neighbor cache and thus initiate another, "recursive", route discovery.

    I "fixed" this by not adding any routes to the routing table if the RREQ came
    from a node unknown to the neighbor cache, but this feels like a hacky fix to me–
    and additionally, it's a deviation from the draft.

    As far as I understood it, the only way to get rid of unidirectional routes is
    to blacklist them after they've been added to the routing table.

    Since the approaches mentioned in Section 8.2. may be proactive, they might
    be helpful for the blacklisting of nodes as well. Of course we can't and
    shouldn't make other parties edit AODVv2's blacklists, but I believe that
    tying the efforts of sections 5.2. and 8.2. a bit more closely together
    might be beneficiary. My hacky fix as described above is one approach
    (one might add the addition of the offending node to the blacklist, if a
    blacklist is implemented), but I'm sure more elegant solutions are possible
    as well.

    However, if a solution for this problem already exists and I missed it, I'd
    love to help state the solution more clearly.

Interoperability
================

    The current version of AODVv2 has several hindrances for interoperability. In
    my opinion, it should be evaluated if all of these are inevitable.

    First, as pointed out by Christopher Dearlove[14] and Thomas Heide Clausen[15],
    AODVv2 in its current state lets the implementor choose any Next-hop Router
    Adjacency Monitoring they like, So if Alice's implementation is using RFC6130
    and Bob is using NHDP because he happens to have an implementation lying
    around somewhere, their routers will be unable to communicate even if they
    are in direct neighborhood to each other.
    Mr. Dearlove suggests to set a specify non-optional mechanism. I am in
    favor of this as well.

    Secondly, as previously mentioned, there are two message formats from which
    an implementor can choose. Apart from the fact that this is not very clear
    from the draft, this stands in the way of interoperability as well, and
    I would strongly suggest to slim down the draft to one message format.
    (For the reasons described above, I am in favor of keeping the "verbose format".)

The Code an be found at [16]. In case anyone is interested in actually compiling
and playing around with it, drop me an e-mail and I can save you time by walking
you through the setup process.
(And in case you have any comments on my code, I'd love to hear about and learn
from them.)

With kind regards,
Lotte Steenbrink

[1] https://github.com/Lotterleben/RIOT-AODVv2/blob/master/docs/aodvv2_minimal.txt
[2] https://github.com/RIOT-OS/RIOT
[3] http://www.ietf.org/mail-archive/web/manet/current/msg16131.html
[4] http://olsr.org/git/?p=oonf_api.git;a=summary
[5] http://trac.tools.ietf.org/wg/manet/trac/ticket/23
[6] http://www.ietf.org/mail-archive/web/manet/current/msg15530.html
[7] http://trac.tools.ietf.org/wg/manet/trac/ticket/39
[8] http://trac.tools.ietf.org/wg/manet/trac/ticket/40
[9] http://ietf.10.n7.nabble.com/41-aodvv2-AckReq-vs-RREP-ACK-td413274.html
[10] http://trac.tools.ietf.org/wg/manet/trac/ticket/42
[11] http://ietf.10.n7.nabble.com/42-aodvv2-What-happens-if-Active-routes-exceed-RERR-packet-size-td423497.html
[12] http://trac.tools.ietf.org/wg/manet/trac/ticket/56
[13] http://ietf.org/mail-archive/web/manet/current/msg14840.html and
    http://ietf.org/mail-archive/web/manet/current/msg14819.html
[14] http://www.ietf.org/mail-archive/web/manet/current/msg16461.html
[15] http://www.ietf.org/mail-archive/web/manet/current/msg16048.html
[16] https://github.com/Lotterleben/RIOT/tree/aodvv2/sys/net/routing/aodvv2

---

From: Christopher Dearlove <[email-masked]>
Date: Wed, 29 Oct 2014 19:25:12 +0000

Just picking up one detail for this post.

>       address block in the range.

I would suggest taking a look at RFC 7188. That is only specified for OLSRv2 and NHDP, but it's an approach that could (and I would venture to suggest, should) be applied more widely. The authors decided for various reasons not to attempt to make it an update of RFC 5444, but could have done so (and still might suggest that at some point).

The key feature I'm referring to is the inclusion of an UNSPECIFIED value as a TV value - or the equivalent for link metrics of a value that conveys no information. (Other details in RFC 7188 are also well worth consideration, such as disallowing message rejection based solely on not recognising a TLV or TLV value, and how to handle short or long values. But this posting is not about those.)

So, for example (using an NHDP example) suppose we have four addresses that numbers 0 and 1 are SYMMETRIC and 3 is LOST, and we choose not to reorder them. (Actually we can always order them to avoid this in NHDP, but that's not entirely trivial.) Then we can use a multivalue LINK_STATUS TLV covering all four addresses that has single values SYMMETRIC, SYMMETRIC, UNSPECIFIED, LOST.