nib: implement public NIB functions up to link-local AR#7014
nib: implement public NIB functions up to link-local AR#7014miri64 merged 5 commits intoRIOT-OS:masterfrom
Conversation
78d83d9 to
4ee3005
Compare
4ee3005 to
4770f82
Compare
|
No longer WIP, but due to the link-local only nature and some lingering bugs in evtimer still experimental. If you want to test with |
I did this, but I noticed that |
The ncache command isn't implemented with NIB so this doesn't surprise me and my plan is to write a new command altogether for the nib (similar to Linux'
Will look into that. |
"Fixed" but there is still some issue, that after a node gets to PROBE state that the other node doesn't answer. Will debug [edit]next week[/edit]. |
|
Fixed + added shell command |
(I moved the shell command to #6988, when I rebase it, the commit will disappear) |
a439a94 to
3d380ae
Compare
|
Rebased and adopted to current master and #6988. |
|
Added #7179 as dependency. |
64e0830 to
e99e28c
Compare
sys/include/net/gnrc/ipv6/nib.h
Outdated
| * @brief Recalculate reachability timeout time. | ||
| * | ||
| * This message type is for the event of recalculating the reachability timeout | ||
| * time. The expected message context is a valid [interface](_nib_iface_t). |
There was a problem hiding this comment.
Don't know why this reference is there anyway... #7456 moves that to gnrc_netif2_t and _nib_iface_t is internal and thus not in the generated doc...
sys/include/net/gnrc/ipv6/nib.h
Outdated
| void gnrc_ipv6_nib_init_iface(kernel_pid_t iface); | ||
|
|
||
| /** | ||
| * @brief Get link-layer address of next hop to a destination address |
sys/include/net/gnrc/ipv6/nib.h
Outdated
| gnrc_ipv6_nib_nc_t *nce); | ||
|
|
||
| /** | ||
| * @brief Handle a received ICMPv6 packet |
There was a problem hiding this comment.
here and same for following funcs
| * packet. | ||
| * @param[in] icmpv6_len The number of bytes at @p icmpv6. | ||
| */ | ||
| void gnrc_ipv6_nib_handle_pkt(kernel_pid_t iface, const ipv6_hdr_t *ipv6, |
There was a problem hiding this comment.
the function only handles icmpv6. should we put that info somewhere into the name of the func?
There was a problem hiding this comment.
I think the function name is sufficiently long. If someone does not check by here that the neighbor information base only concerns NDP (and thus ICMPv6) they should not meddle with this function anyway.
|
Addressed first round of comments |
| * handed to the SL2AO handler function). | ||
| * @param[in] aro ARO that carries the address registration information. | ||
| * @param[in] sllao SL2AO associated with the ARO. | ||
| * @param[in] sl2ao SL2AO associated with the ARO. |
There was a problem hiding this comment.
Doccheck said its broken :P
|
I think there are more instances where the doc should've used third person at the beginning of the sentence. Not just those that I pointed out. |
3f7bd1d to
e0038c5
Compare
|
And rebased again ^^ |
cgundogan
left a comment
There was a problem hiding this comment.
second round .. not finished yet.
| if ((nce == NULL) || !(nce->mode & _NC) || | ||
| (memcmp(&nce->eui64, &aro->eui64, sizeof(aro->eui64)) == 0)) { | ||
| #if GNRC_IPV6_NIB_CONF_MULTIHOP_DAD | ||
| /* TODO */ |
There was a problem hiding this comment.
Could you add a TODO to the doxygen? It should be obvious somewhere that multihop DAD is not working currently.
There was a problem hiding this comment.
Will do in sys/include/net/gnrc/ipv6/nib.h
| #if GNRC_IPV6_NIB_CONF_MULTIHOP_DAD | ||
| /* TODO */ | ||
| #endif | ||
| if (byteorder_ntohs(aro->ltime) != 0) { |
There was a problem hiding this comment.
4 levels of indentation .. if it's no hassle, could you try to remove some nestedness here?
| * @param[in] nbr_sol The neighbor solicitation carrying the original ARO | ||
| * (handed over as @ref icmpv6_hdr_t, since it is just | ||
| * handed to @ref _handle_aro()). | ||
| * @param[in] aro The original riginal ARO |
| { | ||
| gnrc_pktsnip_t *reply_aro = NULL; | ||
|
|
||
| if (aro != NULL) { |
There was a problem hiding this comment.
why not assert this? Is it possible that – by design – NULL is passed to this function as aro? If not by design, then this is an unexpected behaviour and should be handled on the caller side.
There was a problem hiding this comment.
Yes, if the message does not contain an ARO this function is called regardless (to keep 6LR-mixins minimal), to check that fact.
| ipv6_addr_to_str(addr_str, &nbr->ipv6, sizeof(addr_str)), | ||
| (unsigned)iface->retrans_time); | ||
| assert((netif != NULL) && (iface != NULL)); | ||
| #if GNRC_IPV6_NIB_CONF_ARSM |
There was a problem hiding this comment.
Hm, strange. This file is called _nib-arsm.c. Why shouldn't GNRC_IPV6_NIB_CONF_ARSM be defined on this code path?
There was a problem hiding this comment.
Because sending Neighbor Solicitations is (originally) related to address resolution, but also required for other stuff (e.g. 6Lo address registration and SLAAC). Welcome to NDP hell ;-).
There was a problem hiding this comment.
(the ARSM-only part starts in l172)
| if ((nce != NULL) && (nce->mode & _NC) && | ||
| ((nce->l2addr_len != l2addr_len) || | ||
| (memcmp(nce->l2addr, sl2ao + 1, nce->l2addr_len) != 0)) && | ||
| /* a 6LR MUST NOT modify an existing NCE based on an SLLAO in an RS |
| nce->info &= ~GNRC_IPV6_NIB_NC_INFO_IS_ROUTER; | ||
| } | ||
| #if GNRC_IPV6_NIB_CONF_ARSM | ||
| /* a 6LR MUST NOT modify an existing NCE based on an SLLAO in an RS |
| #endif | ||
| } | ||
|
|
||
| void _handle_sl2ao(kernel_pid_t iface, const ipv6_hdr_t *ipv6, |
There was a problem hiding this comment.
I have to admit, I don't like this function. It's too complex and I spent a lot of time to understand what's going on here – and I am quite certain I will spent the same amount of time a year later from now. Please try to remove the nested if - else hell. The Clean Code approach would be to split this function into several smaller (inlined) ones with well-documented and obvious names. I am not sure whether that's the solution for us, but the current implementation is very unreadable and IMO unmaintainable in the future.
There was a problem hiding this comment.
I don't like it either, but that's exactly how the RFC reads. Welcome to NDP hell ;-)
There was a problem hiding this comment.
Will try to fix it though.
| if (tl2ao != NULL) { | ||
| l2addr_len = _get_l2addr_len(netif, tl2ao); | ||
| if (l2addr_len == 0U) { | ||
| DEBUG("nib: Unexpected TLLAO length. Ignoring TLLAO\n"); |
| if (nib_netif->reach_time == 0) { | ||
| /* (re-)initialize PNRG with current system time as seed to get | ||
| * better randomization in reachable time */ | ||
| random_init(xtimer_now_usec()); |
There was a problem hiding this comment.
There's no need to re-seed the PRNG iff the start seed is distinct on all nodes. And the latter is what we should aim for.
There was a problem hiding this comment.
And btw, you break here the PRNG for all applications that use this random interface with the same PRNG state.
There was a problem hiding this comment.
There's no need to re-seed the PRNG iff the start seed is distinct on all nodes. And the latter is what we should aim for.
But it is not the case now. Also: this is a very standard approach to get a distinct random number.
And btw, you break here the PRNG for all applications that use this random interface with the same PRNG state.
If re-seeding breaks your PNRG then your PNRG is broken
There was a problem hiding this comment.
Sorry, let me rephrase:
You are using the system/global PRNG state here. The moment you re-seed, the PRNG for all applications that make use of the system/global state do not produce deterministic results anymore. A PRNG is supposed to yield deterministic results.
Oh and btw: random_init() is not thread-safe. So please let the seeding be performed at auto_init() once, like it's the case now, or provide a separate PRNG state for NIB that can be re-seeded without global effects.
There was a problem hiding this comment.
or provide a separate PRNG state for NIB that can be re-seeded without global effects.
and even then I doubt that re-seeding provides "better randomization".
There was a problem hiding this comment.
and even then I doubt that re-seeding provides "better randomization".
Why are you doubting that? Currently the PNRG is always seeded with 0, there are plans to use the luid as seed (making it different but deterministic for different nodes). This reseed uses the reception time of the first received solicited NA from all neighbors, which is always naturally random, due to the different air times of both NS and NA, so it is by definition "better randomization" than using the PNRG with a deterministic seed.
There was a problem hiding this comment.
What about the other points?
random_init()is not thread-safe- you modify the global PRNG state which is potentially used by more thread than just the network stack
I propose that you factor out this re-seeding procedure into another PR and we continue the discussion there, so that we can continue here?
cgundogan
left a comment
There was a problem hiding this comment.
Third round. All in all it's okay. I have reported some minor-ish styling issues.
| * and 6LN | ||
| * - join solicited nodes group of link-local address here for address | ||
| * resolution here | ||
| * - join all router group of link-local address here on router node here |
There was a problem hiding this comment.
I'm not fixing a note to myself :P
There was a problem hiding this comment.
I was just pointing it out .. you can decide what you do with it (:
| * - join solicited nodes group of link-local address here for address | ||
| * resolution here | ||
| * - join all router group of link-local address here on router node here | ||
| * - become an router advertising interface here on non-6LR here */ |
There was a problem hiding this comment.
I'm not fixing a note to myself :P
| mutex_lock(&_nib_mutex); | ||
| nib_iface = _nib_iface_get(iface); | ||
| assert(nib_iface != NULL); | ||
| /* TODO: |
There was a problem hiding this comment.
question: should we put this into doxygen to make this TODO more obviouvs?
| int res = 0; | ||
|
|
||
| mutex_lock(&_nib_mutex); | ||
| do { /* XXX: hidden goto ;-) */ |
There was a problem hiding this comment.
Since when do we use these hidden gotos? Frankly said, I do not like this idea. It 1) gives another level of indentation, 2) is an unconditional jump the same way as goto (so the same disadvantages apply) and 3) bloats the code by two more lines. I am sure you can re-arrange the code to not use this hidden goto and it still results in a more readable version (:
There was a problem hiding this comment.
Since when do we use these hidden gotos? Frankly said, I do not like this idea.
Since @gebart proposed them as an alternative to "finally-gotos".
- gives another level of indentation,
Since when is there this hatred for levels of indentations? We are not the Linux kernel (where this Coding Convention lead to very weird code btw).
I am sure you can re-arrange the code to not use this hidden goto and it still results in a more readable version (:
I find it quite readable.
There was a problem hiding this comment.
mutex_lock(&_nib_mutex);
if (!ipv6_addr_is_link_local(dst)) {
/* TODO: Off-link next hop determination */
mutex_unlock(&_nib_mutex);
return -EHOSTUNREACH;
}
if ((iface == KERNEL_PID_UNDEF) ||
!_resolve_addr(dst, iface, pkt, nce, _nib_onl_get(dst, iface))) {
mutex_unlock(&_nib_mutex);
return -EHOSTUNREACH;
}
mutex_unlock(&_nib_mutex);
return 0;Isn't this so much simpler to read without any level of nestedness?!
There was a problem hiding this comment.
This adds 2 more function calls (mutex_unlock()), 6 in #7479 (mutex_unlock() + gnrc_netif2_release()), and even a more simpler version [edit]with only one additional mutex_unlock()[/edit]
int res = 0;
mutex_lock(&_nib_mutex);
if (!ipv6_addr_is_link_local(dst)) { /* TODO: Prefix-based on-link determination */
/* TODO: Off-link next hop determination */
mutex_unlock(&_nib_mutex);
return -EHOSTUNREACH;
}
if ((iface == KERNEL_PID_UNDEF) ||
!_resolve_addr(dst, iface, pkt, nce,
_nib_onl_get(dst, iface))) {
res = -EHOSTUNREACH;
}
mutex_unlock(&_nib_mutex);
return res;Adds 24 byte of ROM more on Cortex-M0.
|
|
||
| void gnrc_ipv6_nib_handle_pkt(kernel_pid_t iface, const ipv6_hdr_t *ipv6, | ||
| const icmpv6_hdr_t *icmpv6, size_t icmpv6_len) | ||
| { |
There was a problem hiding this comment.
So many TODOS that could end up in a nicely documented fashion => doxygen (:
There was a problem hiding this comment.
I'm not sure if putting TODOs in doxygen is productive here...
| else { | ||
| reply_flags |= NDP_NBR_ADV_FLAGS_O; | ||
| } | ||
| /* discard const qualifier */ |
| } | ||
| else { | ||
| reply_flags |= NDP_NBR_ADV_FLAGS_O; | ||
| } |
There was a problem hiding this comment.
else {
reply_flags |= NDP_NBR_ADV_FLAGS_O;
}
}
else {
reply_flags |= NDP_NBR_ADV_FLAGS_O;
}you were able to remove such code duplication in another PR, can you also apply this here, please?
There was a problem hiding this comment.
There it was at the end of a function, so I was just able to early exit. This is not possible here.
There was a problem hiding this comment.
I could use a "hidden goto" instead ;-)
| return; | ||
| } | ||
| /* pre-check option length */ | ||
| FOREACH_OPT(nbr_sol, opt, tmp_len) { |
| return; | ||
| } | ||
| /* pre-check option length */ | ||
| FOREACH_OPT(nbr_adv, opt, tmp_len) { |
|
Addressed comments. |
|
This PR seems to be in good state. The only – critically and blocking – discussion is about the re-seeding that I am strictly against. The discussion can be found in #7014 (comment) @tcschmidt @emmanuelsearch any opinions on this discussion? |
|
fixup commit looks good – pleasae squash! (: |
199551b to
58aad0d
Compare
|
Squashed. |
58aad0d to
c2a6984
Compare
|
Fixed and squashed errors reported by Murdock. |
|
( |
|
Fix looks sane, please squash. |
|
Squashed |
Implements link-local AR-capabilities for 6Lo and normal NDP with NDP model, including address registration for 6Lo (though not in effect, since there is no router discovery yet).
Still missing:
Depends on
#6380(closed),#6988(merged),#7064(merged) and#7179(merged) (and their respective dependencies)This PR is part of the network layer remodelling effort:
