[PATCH 04/17] net: ipv6: Add Neighbor Discovery Protocol (NDP)

Simon Glass sjg at chromium.org
Thu Sep 1 04:26:46 CEST 2022


Hi Viacheslav,

On Tue, 30 Aug 2022 at 07:01, Viacheslav Mitrofanov
<v.v.mitrofanov at yadro.com> wrote:
>
> Implement basic of NDP. It doesn't include such things as Router
> Solicitation, Router Advertisement and Redirect. It just has Neighbor
> Solicitation and Neighbor Advertisement. Only these two features are used
> in u-boot IPv6. Implementation of some NDP functions uses API that was
> exposed in "net: ipv6: Add IPv6 basic primitives".
>
> Also this patch inlcudes update in Makefile to build NDP.
>
> Signed-off-by: Viacheslav Mitrofanov <v.v.mitrofanov at yadro.com>
> ---
>  include/ndisc.h |  65 ++++++++++++
>  net/Makefile    |   1 +
>  net/ndisc.c     | 276 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 342 insertions(+)
>  create mode 100644 include/ndisc.h
>  create mode 100644 net/ndisc.c
>
> diff --git a/include/ndisc.h b/include/ndisc.h
> new file mode 100644
> index 0000000000..7debdd79d6
> --- /dev/null
> +++ b/include/ndisc.h
> @@ -0,0 +1,65 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2013 Allied Telesis Labs NZ
> + * Chris Packham, <judge.packham at gmail.com>
> + *
> + * Copyright (C) 2022 YADRO
> + * Viacheslav Mitrofanov <v.v.mitrofanov at yadro.com>
> + */
> +
> +#ifndef __NDISC_H__
> +#define __NDISC_H__
> +
> +#include <ndisc.h>
> +
> +struct nd_msg {

comment

> +       struct icmp6hdr icmph;
> +       struct in6_addr target;
> +       __u8            opt[0];
> +};
> +
> +struct echo_msg {

comment

> +       struct icmp6hdr icmph;
> +       __u16           id;
> +       __u16           sequence;
> +};
> +
> +/* IPv6 destination address of packet waiting for ND */
> +extern struct in6_addr net_nd_sol_packet_ip6;
> +/* MAC destination address of packet waiting for ND */
> +extern uchar *net_nd_packet_mac;
> +/* pointer to packet waiting to be transmitted after ND is resolved */
> +extern uchar *net_nd_tx_packet;
> +/* size of packet waiting to be transmitted */
> +extern int net_nd_tx_packet_size;
> +/* the timer for ND resolution */
> +extern ulong net_nd_timer_start;
> +/* the number of requests we have sent so far */
> +extern int net_nd_try;
> +
> +#ifdef CONFIG_IPV6
> +void ndisc_init(void);
> +void ndisc_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len);
> +void ndisc_request(void);
> +int ndisc_timeout_check(void);

comments

> +#else
> +static inline void ndisc_init(void)
> +{
> +}
> +
> +static inline void
> +ndisc_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
> +{
> +}
> +
> +static inline void ndisc_request(void)
> +{
> +}
> +
> +static inline int ndisc_timeout_check(void)
> +{
> +       return 0;
> +}
> +#endif
> +
> +#endif /* __NDISC_H__ */
> diff --git a/net/Makefile b/net/Makefile
> index 4ea2a14f27..766dd04135 100644
> --- a/net/Makefile
> +++ b/net/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_DM_MDIO)  += mdio-uclass.o
>  obj-$(CONFIG_DM_MDIO_MUX) += mdio-mux-uclass.o
>  obj-$(CONFIG_NET)      += eth_common.o
>  obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
> +obj-$(CONFIG_IPV6)     += ndisc.o
>  obj-$(CONFIG_NET)      += net.o
>  obj-$(CONFIG_IPV6)     += net6.o
>  obj-$(CONFIG_CMD_NFS)  += nfs.o
> diff --git a/net/ndisc.c b/net/ndisc.c
> new file mode 100644
> index 0000000000..1bd06211f1
> --- /dev/null
> +++ b/net/ndisc.c
> @@ -0,0 +1,276 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2013 Allied Telesis Labs NZ
> + * Chris Packham, <judge.packham at gmail.com>
> + *
> + * Copyright (C) 2022 YADRO
> + * Viacheslav Mitrofanov <v.v.mitrofanov at yadro.com>
> + */
> +
> +/*
> + * Neighbour Discovery for IPv6
> + */

Single-line comment style is /* ... */

> +
> +#include <common.h>
> +#include <net.h>
> +#include <net6.h>
> +#include <ndisc.h>
> +
> +/* IPv6 destination address of packet waiting for ND */
> +struct in6_addr net_nd_sol_packet_ip6 = ZERO_IPV6_ADDR;

Should these be static? Can we put them in a struct and attach them to
the uclass or driver?

> +/* IPv6 address we are expecting ND advert from */
> +static struct in6_addr net_nd_rep_packet_ip6 = ZERO_IPV6_ADDR;
> +/* MAC destination address of packet waiting for ND */
> +uchar *net_nd_packet_mac;
> +/* pointer to packet waiting to be transmitted after ND is resolved */
> +uchar *net_nd_tx_packet;
> +static uchar net_nd_packet_buf[PKTSIZE_ALIGN + PKTALIGN];
> +/* size of packet waiting to be transmitted */
> +int net_nd_tx_packet_size;
> +/* the timer for ND resolution */
> +ulong net_nd_timer_start;
> +/* the number of requests we have sent so far */
> +int net_nd_try;
> +
> +#define IP6_NDISC_OPT_SPACE(len) (((len) + 2 + 7) & ~7)
> +
> +/**
> + * Insert an option into a neighbor discovery packet.
> + * Returns the number of bytes inserted (which may be >= len)

Need to document args and use sphinx format (please fix globally)

> + */
> +static int
> +ndisc_insert_option(struct nd_msg *ndisc, int type, u8 *data, int len)
> +{
> +       int space = IP6_NDISC_OPT_SPACE(len);
> +
> +       ndisc->opt[0] = type;
> +       ndisc->opt[1] = space >> 3;
> +       memcpy(&ndisc->opt[2], data, len);
> +       len += 2;
> +
> +       /* fill the remainder with 0 */
> +       if ((space - len) > 0)

(drop extra brackets?)

> +               memset(&ndisc->opt[len], 0, space - len);

'\0'

> +
> +       return space;
> +}
> +
> +/**
> + * Extract the Ethernet address from a neighbor discovery packet.
> + * Note that the link layer address could be anything but the only networking
> + * media that u-boot supports is Ethernet so we assume we're extracting a 6
> + * byte Ethernet MAC address.
> + */
> +static void ndisc_extract_enetaddr(struct nd_msg *ndisc, uchar enetaddr[6])
> +{
> +       memcpy(enetaddr, &ndisc->opt[2], 6);
> +}

[..]

Regards,
Simon


More information about the U-Boot mailing list