From: Stefano Brivio <sbrivio@redhat.com>
To: David Gibson <david@gibson.dropbear.id.au>
Cc: passt-dev@passt.top
Subject: Re: [PATCH 6/6] ndp: Send unsolicited Router Advertisements
Date: Wed, 13 Nov 2024 09:18:05 +0100 [thread overview]
Message-ID: <20241113091805.6f6e2f6a@elisabeth> (raw)
In-Reply-To: <ZzQWfOxjjkFU02yc@zatzit>
On Wed, 13 Nov 2024 14:01:16 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:
> On Wed, Nov 13, 2024 at 02:14:16AM +0100, Stefano Brivio wrote:
> > Kind of nits only, the whole series looks good to me otherwise:
> >
> > On Tue, 12 Nov 2024 15:06:18 +1100
> > David Gibson <david@gibson.dropbear.id.au> wrote:
> >
> > > Currently, our NDP implementation only sends Router Advertisements (RA)
> > > when it receives a Router Solicitation (RS) from the guest. However,
> > > RFC 4861 requires that we periodically send unsolicited RAs.
> > >
> > > Linux as a guest also requires this: it will send an RS when a link first
> > > comes up, but the route it gets from this will have a finite lifetime (we
> > > set this to 65535s, the maximum allowed, around 18 hours). When that
> > > expires the guest will not send a new RS, but instead expects the route to
> > > have been renewed (if still valid) by an unsolicited RA.
> > >
> > > Implement sending unsolicited RAs on a partially randomised timer, as
> > > required by RFC 4861. The RFC also specifies that solicited RAs should
> > > also be delayed, or even not omitted, if the next unsolicited RA is soon
> >
> > s/not//
>
> Fixed.
>
> > > enough. For now we don't do that, always sending an immediate RA in
> > > response to an RS. We can get away with this because in our use cases
> > > we expect to just have passt itself and the guest on the link, rather than
> > > a large broadcast domain.
> > >
> > > Link: https://github.com/kubevirt/kubevirt/issues/13191
> > > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > > ---
> > > ip.h | 9 +++++++++
> > > ndp.c | 41 +++++++++++++++++++++++++++++++++++++++++
> > > ndp.h | 3 +++
> > > passt.c | 3 +++
> > > 4 files changed, 56 insertions(+)
> > >
> > > diff --git a/ip.h b/ip.h
> > > index b8d4a5b..0742612 100644
> > > --- a/ip.h
> > > +++ b/ip.h
> > > @@ -92,4 +92,13 @@ struct ipv6_opt_hdr {
> > >
> > > char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *proto,
> > > size_t *dlen);
> > > +
> > > +/* IPv6 link-local all-nodes multicast adddress, ff02::1 */
> > > +static const struct in6_addr in6addr_ll_all_nodes = {
> > > + .s6_addr = {
> > > + 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
> > > + },
> > > +};
> > > +
> > > #endif /* IP_H */
> > > diff --git a/ndp.c b/ndp.c
> > > index c5fbccf..8c019df 100644
> > > --- a/ndp.c
> > > +++ b/ndp.c
> > > @@ -372,3 +372,44 @@ int ndp(const struct ctx *c, const struct icmp6hdr *ih,
> > >
> > > return 1;
> > > }
> > > +
> > > +/* Default interval between unsolicited RAs (seconds) */
> > > +#define DEFAULT_MAX_RTR_ADV_INTERVAL 600 /* RFC 4861, 6.2.1 */
> > > +
> > > +/* Minimum required interval between RAs (seconds) */
> > > +#define MIN_DELAY_BETWEEN_RAS 3 /* RFC 4861, 10 */
> >
> > By the way, I think this is still all correct, as I quickly double
> > checked it against RFC 8319. If you're not aware: see also sections 3
> > and 4 there.
>
> Ah, thanks for checking. I didn't think to look for a superseding RFC.
>
> > > +
> > > +static time_t next_ra;
> > > +
> > > +/**
> > > + * ndp_timer() - Send unsolicited NDP messages if necessary
> > > + * @c: Execution context
> > > + * @now: Current (monotonic) time
> > > + */
> > > +void ndp_timer(const struct ctx *c, const struct timespec *now)
> > > +{
> > > + time_t max_rtr_adv_interval = DEFAULT_MAX_RTR_ADV_INTERVAL;
> > > + time_t min_rtr_adv_interval, interval;
> > > +
> > > + if (c->no_ra || now->tv_sec < next_ra)
> > > + return;
> > > +
> > > + /* We must advertise before the route's lifetime expires */
> > > + max_rtr_adv_interval = MIN(max_rtr_adv_interval, RT_LIFETIME - 1);
> > > +
> > > + /* But we must not go smaller than the minimum delay */
> > > + max_rtr_adv_interval = MAX(max_rtr_adv_interval, MIN_DELAY_BETWEEN_RAS);
> > > +
> > > + /* RFC 4861, 6.2.1 */
> > > + min_rtr_adv_interval = MAX(max_rtr_adv_interval / 3,
> > > + MIN_DELAY_BETWEEN_RAS);
> > > +
> > > + interval = min_rtr_adv_interval +
> > > + random() % (max_rtr_adv_interval - min_rtr_adv_interval);
> >
> > So, I would have called srandom() before this, especially in the case
> > we get, one day, two instances of passt advertising at the same
> > time.
>
> Good point, I'll add that.
>
> > But Coverity is more annoying than I am and reports:
> >
> > /home/sbrivio/passt/ndp.c:408:3:
> > Type: Calling risky function (DC.WEAK_CRYPTO)
> >
> > /home/sbrivio/passt/ndp.c:408:3:
> > dont_call: "random" should not be used for security-related applications, because linear congruential algorithms are too easy to break.
> > /home/sbrivio/passt/ndp.c:408:3:
> > remediation: Use a compliant random number generator, such as "/dev/random" or "/dev/urandom" on Unix-like systems, and CNG (Cryptography API: Next Generation) on Windows.
> >
> > Of course it's all bogus but I would have a *slight* preference to get
> > rid of this, by either picking a fixed interval deviation at the
> > beginning with getrandom(), or using something like tcp_init_seq()
> > modulo something << 600.
>
> I don't think the latter approach really works. Using the time as the
> basic input means its still subject to two passt instances (say)
> starting at the same time on the same link picking the same values and
> keeping on sending their announcements in lockstep.
Well, but the seeds would be different (I would still factor
hash_secret in), so we would start out of sync right away, and we would
use a fine-grained time resolution to pick a coarser one, which adds
(enough) to the pseudorandomness.
> Picking a random interval once is better. Still, I don't particularly
> like deviating from the RFC's recommendations just to keep a fussy
> tool happy.
Oh, I thought it would still fit the recommendation, but now I read RFC
4861 6.2.4 again and it definitely doesn't.
> > Alternatively, we could also keep /dev/random or /dev/urandom open but
> > it looks totally overkill. At that point I'd rather keep random()
> > here.
>
> Also a waste of /dev/random entropy, IMO.
>
> Surely there must be some way we can suppress the Coverity whinge.
That adds more maintenance burden than having a warning at this point,
so I'd rather not try to suppress anything. If the tcp_init_seq()-like
thing works, I'd be happy, otherwise let's leave this like it is.
--
Stefano
prev parent reply other threads:[~2024-11-13 8:18 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-12 4:06 [PATCH 0/6] ndp: Unsolicited RAs David Gibson
2024-11-12 4:06 ` [PATCH 1/6] ndp: Remove redundant update to addr_seen David Gibson
2024-11-12 4:06 ` [PATCH 2/6] ndp: Add ndp_send() helper David Gibson
2024-11-12 4:06 ` [PATCH 3/6] ndp: Split out helpers for sending specific NDP message types David Gibson
2024-11-13 1:14 ` Stefano Brivio
2024-11-13 2:07 ` David Gibson
2024-11-12 4:06 ` [PATCH 4/6] ndp: Use struct assignment in preference to memcpy() for IPv6 addresses David Gibson
2024-11-12 4:06 ` [PATCH 5/6] ndp: Make route lifetime a #define David Gibson
2024-11-12 4:06 ` [PATCH 6/6] ndp: Send unsolicited Router Advertisements David Gibson
2024-11-13 1:14 ` Stefano Brivio
2024-11-13 3:01 ` David Gibson
2024-11-13 8:18 ` Stefano Brivio [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241113091805.6f6e2f6a@elisabeth \
--to=sbrivio@redhat.com \
--cc=david@gibson.dropbear.id.au \
--cc=passt-dev@passt.top \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).