-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nib: implement public NIB functions up to link-local AR #7014
nib: implement public NIB functions up to link-local AR #7014
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
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 ^^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
riginal
{ | ||
gnrc_pktsnip_t *reply_aro = NULL; | ||
|
||
if (aro != NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SL2AO
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SL2AO
#endif | ||
} | ||
|
||
void _handle_sl2ao(kernel_pid_t iface, const ipv6_hdr_t *ipv6, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TL2AO
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not fixing a note to myself :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: should we put this into doxygen to make this TODO more obviouvs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int res = 0; | ||
|
||
mutex_lock(&_nib_mutex); | ||
do { /* XXX: hidden goto ;-) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So many TODOS that could end up in a nicely documented fashion => doxygen (:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if putting TODOs in doxygen is productive here...
else { | ||
reply_flags |= NDP_NBR_ADV_FLAGS_O; | ||
} | ||
/* discard const qualifier */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where is it discarded?
} | ||
else { | ||
reply_flags |= NDP_NBR_ADV_FLAGS_O; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could use a "hidden goto" instead ;-)
return; | ||
} | ||
/* pre-check option length */ | ||
FOREACH_OPT(nbr_sol, opt, tmp_len) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice idea (:
return; | ||
} | ||
/* pre-check option length */ | ||
FOREACH_OPT(nbr_adv, opt, tmp_len) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK
58aad0d
to
c2a6984
Compare
Fixed and squashed errors reported by Murdock. |
( |
c2a6984
to
5f93ff0
Compare
Fix looks sane, please squash. |
Squashed |
0540bea
to
6a7de28
Compare
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: