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 02:14:16 +0100 [thread overview]
Message-ID: <20241113021416.418a338c@elisabeth> (raw)
In-Reply-To: <20241112040618.1804081-7-david@gibson.dropbear.id.au>
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//
> 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.
> +
> +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.
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.
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.
> +
> + info("NDP: sending unsolicited RA, next in %llds", (long long)interval);
> +
> + ndp_ra(c, &in6addr_ll_all_nodes);
> +
> + next_ra = now->tv_sec + interval;
> +}
> diff --git a/ndp.h b/ndp.h
> index abe6d02..41c2000 100644
> --- a/ndp.h
> +++ b/ndp.h
> @@ -6,7 +6,10 @@
> #ifndef NDP_H
> #define NDP_H
>
> +struct icmp6hdr;
> +
> int ndp(const struct ctx *c, const struct icmp6hdr *ih,
> const struct in6_addr *saddr, const struct pool *p);
> +void ndp_timer(const struct ctx *c, const struct timespec *now);
>
> #endif /* NDP_H */
> diff --git a/passt.c b/passt.c
> index fac6101..454ac8e 100644
> --- a/passt.c
> +++ b/passt.c
> @@ -52,6 +52,7 @@
> #include "arch.h"
> #include "log.h"
> #include "tcp_splice.h"
> +#include "ndp.h"
>
> #define EPOLL_EVENTS 8
>
> @@ -110,6 +111,8 @@ static void post_handler(struct ctx *c, const struct timespec *now)
>
> flow_defer_handler(c, now);
> #undef CALL_PROTO_HANDLER
> +
> + ndp_timer(c, now);
> }
>
> /**
--
Stefano
next prev parent reply other threads:[~2024-11-13 1:14 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 [this message]
2024-11-13 3:01 ` David Gibson
2024-11-13 8:18 ` Stefano Brivio
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=20241113021416.418a338c@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).