[PATCH v4 1/3] net: ipv6: Add support for default gateway discovery.

Vyacheslav V. Mitrofanov v.v.mitrofanov at yadro.com
Mon Apr 24 09:58:02 CEST 2023


On Fri, 2023-04-21 at 17:08 -0700, emohandesi at linux.microsoft.com
wrote:
> 
> From: Ehsan Mohandesi <emohandesi at linux.microsoft.com>
> 
> In IPv6, the default gateway and prefix length are determined by
> receiving
> a router advertisement as defined in -
> https://www.rfc-editor.org/rfc/rfc4861.
> 
> Add support for sending router solicitation (RS) and processing
> router
> advertisements (RA).
> 
> If the RA has prefix info option and following conditions are met,
> then
> gatewayip6 and net_prefix_length of ip6addr env variables are
> initialized.
> These are later consumed by IPv6 code for non-local destination IP.
> 
> - "Router Lifetime" != 0
> - Prefix is NOT link-local prefix (0xfe80::/10)
> - L flag is 1
> - "Valid Lifetime" != 0
> 
> Timing Parameters:
> - MAX_RTR_SOLICITATION_DELAY (0-1s)
> - RTR_SOLICITATION_INTERVAL (4s) (min retransmit delay)
> - MAX_RTR_SOLICITATIONS (3 RS transmissions)
> 
> The functionality is enabled by CONFIG_IPV6_ROUTER_DISCOVERY and
> invoked
> automatically from net_init_loop().
> 
> Signed-off-by: Ehsan Mohandesi <emohandesi at linux.microsoft.com>
> ---
>  cmd/Kconfig     |   6 ++
>  include/ndisc.h |  35 ++++++++
>  include/net.h   |   2 +-
>  include/net6.h  |  40 ++++++++++
>  net/ndisc.c     | 243
> +++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  net/net.c       |  23 +++++-
>  net/net6.c      |   1 +
>  7 files changed, 338 insertions(+), 12 deletions(-)
> 
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index e45b884..6919d31 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -1916,6 +1916,12 @@ config CMD_NCSI
>           Normally this happens automatically before other network
>           operations.
> 
> +config IPV6_ROUTER_DISCOVERY
> +       bool "Do IPv6 router discovery"
> +       depends on IPV6
> +       help
> +         Will automatically perform router solicitation on first
> IPv6
> +         network operation
>  endif
> 
>  config CMD_ETHSW
> diff --git a/include/ndisc.h b/include/ndisc.h
> index f6f8eb6..12fa9e7 100644
> --- a/include/ndisc.h
> +++ b/include/ndisc.h
> @@ -19,6 +19,20 @@ struct nd_msg {
>         __u8            opt[0];
>  };
> 
> +/* struct rs_msg - ICMPv6 Router Solicitation message format */
> +struct rs_msg {
> +       struct icmp6hdr icmph;
> +       __u8            opt[0];
> +};
> +
> +/* struct ra_msg - ICMPv6 Router Advertisement message format */
> +struct ra_msg {
> +       struct icmp6hdr icmph;
> +       __u32   reachable_time;
> +       __u32   retransmission_timer;
> +       __u8    opt[0];
> +};
> +
>  /* struct echo_msg - ICMPv6 echo request/reply message format */
>  struct echo_msg {
>         struct icmp6hdr icmph;
> @@ -57,6 +71,11 @@ extern int net_nd_try;
>   */
>  void ndisc_init(void);
> 
> +/*
> + * ip6_send_rs() - Send IPv6 Router Solicitation Message
> + */
> +void ip6_send_rs(void);
> +
>  /**
>   * ndisc_receive() - Handle ND packet
>   *
> @@ -78,6 +97,8 @@ void ndisc_request(void);
>   * Return: 0 if no timeout, -1 otherwise
>   */
>  int ndisc_timeout_check(void);
> +bool validate_ra(struct ip6_hdr *ip6);
> +int process_ra(struct ip6_hdr *ip6, int len);
>  #else
>  static inline void ndisc_init(void)
>  {
> @@ -97,6 +118,20 @@ static inline int ndisc_timeout_check(void)
>  {
>         return 0;
>  }
> +
> +void ip6_send_rs(void)
> +{
> +}
> +
> +static inline bool validate_ra(struct ip6_hdr *ip6)
> +{
> +       return true;
> +}
> +
> +static inline int process_ra(struct ip6_hdr *ip6, int len)
> +{
> +       return 0;
> +}
>  #endif
> 
>  #endif /* __NDISC_H__ */
> diff --git a/include/net.h b/include/net.h
> index 399af5e..25c43b3 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -505,7 +505,7 @@ extern int          net_restart_wrap;       /*
> Tried all network devices */
> 
>  enum proto_t {
>         BOOTP, RARP, ARP, TFTPGET, DHCP, PING, PING6, DNS, NFS, CDP,
> NETCONS,
> -       SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI,
> WGET
> +       SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT, WOL, UDP, NCSI,
> WGET, RS
>  };
> 
>  extern char    net_boot_file_name[1024];/* Boot File name */
> diff --git a/include/net6.h b/include/net6.h
> index 2d7c5a0..beafc05 100644
> --- a/include/net6.h
> +++ b/include/net6.h
> @@ -81,8 +81,17 @@ struct udp_hdr {
>                           0x00, 0x00, 0x00, 0x00, \
>                           0x00, 0x00, 0x00, 0x00, \
>                           0x00, 0x00, 0x00, 0x00 } } }
> +/*
> + * All-routers multicast address is the link-local scope address to
> reach all
> + * routers.
> + */
> +#define ALL_ROUTERS_MULT_ADDR { { { 0xFF, 0x02, 0x00, 0x00, \
> +                                 0x00, 0x00, 0x00, 0x00, \
> +                                 0x00, 0x00, 0x00, 0x00, \
> +                                 0x00, 0x00, 0x00, 0x02 } } }
> 
>  #define IPV6_LINK_LOCAL_PREFIX 0xfe80
> +#define IPV6_LINK_LOCAL_MASK   0xffb0 /* The first 10-bit of address
> mask. */
> 
>  /* hop limit for neighbour discovery packets */
>  #define IPV6_NDISC_HOPLIMIT             255
> @@ -166,6 +175,37 @@ struct icmp6hdr {
>  #define icmp6_rt_lifetime      icmp6_dataun.u_nd_ra.rt_lifetime
>  } __packed;
> 
> +/*
> + * struct icmp6_ra_prefix_info - Prefix Information option of the
> ICMPv6 message
> + * The Prefix Information option provides hosts with on-link
> prefixes and
> + * prefixes for Address Autoconfiguration. Refer to RFC 4861 for
> more info.
> + */
> +struct icmp6_ra_prefix_info {
> +       u8      type;           /* Type is 3 for Prefix Information.
> */
> +       u8      len;            /* Len is 4 for Prefix Information.
> */
> +       /* The number of leading bits in the Prefix that are valid.
> */
> +       u8      prefix_len;
> +       u8      reserved1:6,    /* MUST be ignored by the receiver.
> */
> +               aac:1,          /* autonomous address-configuration
> flag */
> +       /* Indicates that this prefix can be used for on-link
> determination. */
> +               on_link:1;
> +       /*
> +        * The length of time in seconds that the prefix is valid for
> the
> +        * purpose of on-link determination.
> +        */
> +       __be32  valid_lifetime;
> +       /* The length of time addresses remain preferred. */
> +       __be32  preferred_lifetime;
> +       __be32  reserved2;      /* MUST be ignored by the receiver.
> */
> +       /*
> +        * Prefix is an IP address or a prefix of an IP address. The
> Prefix
> +        * Length field contains the number of valid leading bits in
> the prefix.
> +        * The bits in the prefix after the prefix length are
> reserved and MUST
> +        * be initialized to zero by the sender and ignored by the
> receiver.
> +        */
> +       struct in6_addr prefix;
> +};
> +
>  extern struct in6_addr const net_null_addr_ip6;        /* NULL IPv6
> address */
>  extern struct in6_addr net_gateway6;   /* Our gateways IPv6 address
> */
>  extern struct in6_addr net_ip6;        /* Our IPv6 addr (0 =
> unknown) */
> diff --git a/net/ndisc.c b/net/ndisc.c
> index 367dae7..0b27779 100644
> --- a/net/ndisc.c
> +++ b/net/ndisc.c
> @@ -13,6 +13,8 @@
>  #include <net.h>
>  #include <net6.h>
>  #include <ndisc.h>
> +#include <stdlib.h>
> +#include <linux/delay.h>
> 
>  /* IPv6 destination address of packet waiting for ND */
>  struct in6_addr net_nd_sol_packet_ip6 = ZERO_IPV6_ADDR;
> @@ -29,31 +31,37 @@ int net_nd_tx_packet_size;
>  ulong net_nd_timer_start;
>  /* the number of requests we have sent so far */
>  int net_nd_try;
> +struct in6_addr all_routers = ALL_ROUTERS_MULT_ADDR;
> +
> +#define MAX_RTR_SOLICITATIONS          3
> +/* The maximum time to delay sending the first router solicitation
> message. */
> +#define MAX_SOLICITATION_DELAY         1 // 1 second
> +/* The time to wait before sending the next router solicitation
> message. */
> +#define RTR_SOLICITATION_INTERVAL      4000 // 4 seconds
> 
>  #define IP6_NDISC_OPT_SPACE(len) (((len) + 2 + 7) & ~7)
> 
>  /**
>   * ndisc_insert_option() - Insert an option into a neighbor
> discovery packet
>   *
> - * @ndisc:     pointer to ND packet
> + * @opt:       pointer to the option element of the neighbor
> discovery packet
>   * @type:      option type to insert
>   * @data:      option data to insert
>   * @len:       data length
>   * Return: the number of bytes inserted (which may be >= len)
>   */
> -static int
> -ndisc_insert_option(struct nd_msg *ndisc, int type, u8 *data, int
> len)
> +static int ndisc_insert_option(__u8 *opt, 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);
> +       opt[0] = type;
> +       opt[1] = space >> 3;
> +       memcpy(&opt[2], data, len);
>         len += 2;
> 
>         /* fill the remainder with 0 */
>         if (space - len > 0)
> -               memset(&ndisc->opt[len], '\0', space - len);
> +               memset(&opt[len], '\0', space - len);
> 
>         return space;
>  }
> @@ -123,7 +131,7 @@ static void ip6_send_ns(struct in6_addr
> *neigh_addr)
> 
>         /* Set the target address and llsaddr option */
>         net_copy_ip6(&msg->target, neigh_addr);
> -       ndisc_insert_option(msg, ND_OPT_SOURCE_LL_ADDR, net_ethaddr,
> +       ndisc_insert_option(msg->opt, ND_OPT_SOURCE_LL_ADDR,
> net_ethaddr,
>                             INETHADDRSZ);
> 
>         /* checksum */
> @@ -137,6 +145,76 @@ static void ip6_send_ns(struct in6_addr
> *neigh_addr)
>         net_send_packet(net_tx_packet, (pkt - net_tx_packet));
>  }
> 
> +/*
> + * ip6_send_rs() - Send IPv6 Router Solicitation Message.
> + *
> + * A router solicitation is sent to discover a router. RS message
> creation is
> + * based on RFC 4861 section 4.1. Router Solicitation Message
> Format.
> + */
> +void ip6_send_rs(void)
> +{
> +       unsigned char enetaddr[6];
> +       struct rs_msg *msg;
> +       __u16 icmp_len;
> +       uchar *pkt;
> +       unsigned short csum;
> +       unsigned int pcsum;
> +       static unsigned int retry_count;
> +
> +       if (!ip6_is_unspecified_addr(&net_gateway6) &&
> +           net_prefix_length != 0) {
> +               net_set_state(NETLOOP_SUCCESS);
> +               return;
> +       } else if (retry_count >= MAX_RTR_SOLICITATIONS) {
> +               net_set_state(NETLOOP_FAIL);
> +               net_set_timeout_handler(0, NULL);
> +               retry_count = 0;
> +               return;
> +       }
> +
> +       printf("ROUTER SOLICITATION %d\n", retry_count + 1);
> +
> +       ip6_make_mult_ethdstaddr(enetaddr, &all_routers);
> +       /*
> +        * ICMP length is the size of ICMP header (8) + one option
> (8) = 16.
> +        * The option is 2 bytes of type and length + 6 bytes for
> MAC.
> +        */
> +       icmp_len = sizeof(struct icmp6hdr) +
> IP6_NDISC_OPT_SPACE(INETHADDRSZ);
> +
> +       pkt = (uchar *)net_tx_packet;
> +       pkt += net_set_ether(pkt, enetaddr, PROT_IP6);
> +       pkt += ip6_add_hdr(pkt, &net_link_local_ip6, &all_routers,
> PROT_ICMPV6,
> +                          IPV6_NDISC_HOPLIMIT, icmp_len);
> +
> +       /* ICMPv6 - RS */
> +       msg = (struct rs_msg *)pkt;
> +       msg->icmph.icmp6_type = IPV6_NDISC_ROUTER_SOLICITATION;
> +       msg->icmph.icmp6_code = 0;
> +       memset(&msg->icmph.icmp6_cksum, 0, sizeof(__be16));
> +       memset(&msg->icmph.icmp6_unused, 0, sizeof(__be32));
> +
> +       /* Set the llsaddr option */
> +       ndisc_insert_option(msg->opt, ND_OPT_SOURCE_LL_ADDR,
> net_ethaddr,
> +                           INETHADDRSZ);
> +
> +       /* checksum */
> +       pcsum = csum_partial((__u8 *)msg, icmp_len, 0);
> +       csum = csum_ipv6_magic(&net_link_local_ip6, &all_routers,
> +                              icmp_len, PROT_ICMPV6, pcsum);
> +       msg->icmph.icmp6_cksum = csum;
> +       pkt += icmp_len;
> +
> +       /* Wait up to 1 second if it is the first try to get the RA
> */
> +       if (retry_count == 0)
> +               udelay(((unsigned int)rand() % 1000000) *
> MAX_SOLICITATION_DELAY);
> +
> +       /* send it! */
> +       net_send_packet(net_tx_packet, (pkt - net_tx_packet));
> +
> +       retry_count++;
> +       net_set_timeout_handler(RTR_SOLICITATION_INTERVAL,
> ip6_send_rs);
> +}
> +
>  static void
>  ip6_send_na(uchar *eth_dst_addr, struct in6_addr *neigh_addr,
>             struct in6_addr *target)
> @@ -167,7 +245,7 @@ ip6_send_na(uchar *eth_dst_addr, struct in6_addr
> *neigh_addr,
>         msg->icmph.icmp6_dataun.u_nd_advt.override = 1;
>         /* Set the target address and lltargetaddr option */
>         net_copy_ip6(&msg->target, target);
> -       ndisc_insert_option(msg, ND_OPT_TARGET_LL_ADDR, net_ethaddr,
> +       ndisc_insert_option(msg->opt, ND_OPT_TARGET_LL_ADDR,
> net_ethaddr,
>                             INETHADDRSZ);
> 
>         /* checksum */
> @@ -223,6 +301,10 @@ int ndisc_timeout_check(void)
>         return 1;
>  }
> 
> +/*
> + * ndisc_init() - Make initial steps for ND state machine.
> + * Usually move variables into initial state.
> + */
>  void ndisc_init(void)
>  {
>         net_nd_packet_mac = NULL;
> @@ -234,12 +316,125 @@ void ndisc_init(void)
>         net_nd_tx_packet -= (ulong)net_nd_tx_packet % PKTALIGN;
>  }
> 
> +/*
> + * validate_ra() - Validate the router advertisement message.
> + *
> + * @ip6: Pointer to the router advertisement packet
> + *
> + * Check if the router advertisement message is valid. Conditions
> are
> + * according to RFC 4861 section 6.1.2. Validation of Router
> Advertisement
> + * Messages.
> + *
> + * Return: true if the message is valid and false if it is invalid.
> + */
> +bool validate_ra(struct ip6_hdr *ip6)
> +{
> +       struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
> +
> +       /* ICMP length (derived from the IP length) should be 16 or
> more octets. */
> +       if (ip6->payload_len < 16)
> +               return false;
> +
> +       /* Source IP Address should be a valid link-local address. */
> +       if ((ntohs(ip6->saddr.s6_addr16[0]) & IPV6_LINK_LOCAL_MASK)
> !=
> +           IPV6_LINK_LOCAL_PREFIX)
> +               return false;
> +
> +       /*
> +        * The IP Hop Limit field should have a value of 255, i.e.,
> the packet
> +        * could not possibly have been forwarded by a router.
> +        */
> +       if (ip6->hop_limit != 255)
> +               return false;
> +
> +       /* ICMP checksum has already been checked in net_ip6_handler.
> */
> +
> +       if (icmp->icmp6_code != 0)
> +               return false;
> +
> +       return true;
> +}
> +
> +/*
> + * process_ra() - Process the router advertisement packet.
> + *
> + * @ip6: Pointer to the router advertisement packet
> + * @len: Length of the router advertisement packet
> + *
> + * Process the received router advertisement message.
> + * Although RFC 4861 requires retaining at least two router
> addresses, we only
> + * keep one because of the U-Boot limitations and its goal of
> lightweight code.
> + *
> + * Return: 0 - RA is a default router and contains valid prefix
> information.
> + * Non-zero - RA options are invalid or do not indicate it is a
> default router
> + * or do not contain valid prefix information.
> + */
> +int process_ra(struct ip6_hdr *ip6, int len)
> +{
> +       /* Pointer to the ICMP section of the packet */
> +       struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
> +       struct ra_msg *msg = (struct ra_msg *)icmp;
> +       int remaining_option_len = len - IP6_HDR_SIZE - sizeof(struct
> ra_msg);
> +       unsigned short int option_len;  /* Length of each option */
> +       /* Pointer to the ICMPv6 message options */
> +       unsigned char *option = NULL;
> +       /* 8-bit identifier of the type of ICMPv6 option */
> +       unsigned char type = 0;
> +       struct icmp6_ra_prefix_info *prefix = NULL;
> +
> +       /* Ignore the packet if router lifetime is 0. */
> +       if (!icmp->icmp6_rt_lifetime)
> +               return -EOPNOTSUPP;
> +
> +       /* Processing the options */
> +       option = msg->opt;
> +       while (remaining_option_len > 0) {
> +               /* The 2nd byte of the option is its length. */
> +               option_len = option[1];
> +               /* All included options should have a positive
> length. */
> +               if (option_len == 0)
> +                       return -EINVAL;
> +
> +               type = option[0];
> +               /* All option types except Prefix Information are
> ignored. */
> +               switch (type) {
> +               case ND_OPT_SOURCE_LL_ADDR:
> +               case ND_OPT_TARGET_LL_ADDR:
> +               case ND_OPT_REDIRECT_HDR:
> +               case ND_OPT_MTU:
> +                       break;
> +               case ND_OPT_PREFIX_INFO:
> +                       prefix = (struct icmp6_ra_prefix_info
> *)option;
> +                       /* The link-local prefix 0xfe80::/10 is
> ignored. */
> +                       if ((ntohs(prefix->prefix.s6_addr16[0]) &
> +                            IPV6_LINK_LOCAL_MASK) ==
> IPV6_LINK_LOCAL_PREFIX)
> +                               break;
> +                       if (prefix->on_link && ntohl(prefix-
> >valid_lifetime)) {
> +                               net_prefix_length = prefix-
> >prefix_len;
> +                               net_gateway6 = ip6->saddr;
> +                               return 0;
> +                       }
> +                       break;
> +               default:
> +                       debug("Unknown IPv6 Neighbor Discovery Option
> 0x%x\n",
> +                             type);
> +               }
> +
> +               option_len <<= 3; /* Option length is a multiple of
> 8. */
> +               remaining_option_len -= option_len;
> +               option += option_len;
> +       }
> +
> +       return -EADDRNOTAVAIL;
> +}
> +
>  int ndisc_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int
> len)
>  {
>         struct icmp6hdr *icmp =
>             (struct icmp6hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);
>         struct nd_msg *ndisc = (struct nd_msg *)icmp;
>         uchar neigh_eth_addr[6];
> +       int err = 0;    // The error code returned calling functions.
> 
>         switch (icmp->icmp6_type) {
>         case IPV6_NDISC_NEIGHBOUR_SOLICITATION:
> @@ -280,6 +475,36 @@ int ndisc_receive(struct ethernet_hdr *et,
> struct ip6_hdr *ip6, int len)
>                         net_nd_packet_mac = NULL;
>                 }
>                 break;
> +       case IPV6_NDISC_ROUTER_SOLICITATION:
> +               break;
> +       case IPV6_NDISC_ROUTER_ADVERTISEMENT:
> +               debug("Received router advertisement for %pI6c from
> %pI6c\n",
> +                     &ip6->daddr, &ip6->saddr);
> +               /*
> +                * If gateway and prefix are set, the RA packet is
> ignored. The
> +                * reason is that the U-Boot code is supposed to be
> as compact
> +                * as possible and does not need to take care of
> multiple
> +                * routers. In addition to that, U-Boot does not want
> to handle
> +                * scenarios like a router setting its lifetime to
> zero to
> +                * indicate it is not routing anymore. U-Boot program
> has a
> +                * short life when the system boots up and does not
> need such
> +                * sophistication.
> +                */
> +               if (!ip6_is_unspecified_addr(&net_gateway6) &&
> +                   net_prefix_length != 0) {
> +                       break;
> +               }
> +               if (!validate_ra(ip6)) {
> +                       debug("Invalid router advertisement
> message.\n");
> +                       break;
> +               }
> +               err = process_ra(ip6, len);
> +               if (err)
> +                       debug("Ignored router advertisement. Error:
> %d\n", err);
> +               else
> +                       printf("Set gatewayip6: %pI6c, prefix_length:
> %d\n",
> +                              &net_gateway6, net_prefix_length);
> +               break;
>         default:
>                 debug("Unexpected ICMPv6 type 0x%x\n", icmp-
> >icmp6_type);
>                 return -1;
> diff --git a/net/net.c b/net/net.c
> index c9a749f..9d15329 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -24,7 +24,7 @@
>   *                     - name of bootfile
>   *     Next step:      ARP
>   *
> - * LINK_LOCAL:
> + * LINKLOCAL:
>   *
>   *     Prerequisites:  - own ethernet address
>   *     We want:        - own IP address
> @@ -122,6 +122,7 @@
>  #endif
>  #include <net/tcp.h>
>  #include <net/wget.h>
> +#include "net_rand.h"
> 
>  /** BOOTP EXTENTIONS **/
> 
> @@ -346,6 +347,8 @@ void net_auto_load(void)
> 
>  static int net_init_loop(void)
>  {
> +       static bool first_call = true;
> +
>         if (eth_get_dev()) {
>                 memcpy(net_ethaddr, eth_get_ethaddr(), 6);
> 
> @@ -365,6 +368,12 @@ static int net_init_loop(void)
>                  */
>                 return -ENONET;
> 
> +       if (IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY))
> +               if (first_call && use_ip6) {
> +                       first_call = false;
> +                       srand_mac(); /* This is for rand used in
> ip6_send_rs. */
> +                       net_loop(RS);
> +               }
>         return 0;
>  }
> 
> @@ -574,6 +583,10 @@ restart:
>                         ncsi_probe_packages();
>                         break;
>  #endif
> +               case RS:
> +                       if (IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY))
> +                               ip6_send_rs();
> +                       break;
>                 default:
>                         break;
>                 }
> @@ -671,7 +684,13 @@ restart:
>                         x = time_handler;
>                         time_handler = (thand_f *)0;
>                         (*x)();
> -               }
> +               } else if (IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY))
> +                       if (time_handler && protocol == RS)
> +                               if
> (!ip6_is_unspecified_addr(&net_gateway6) &&
> +                                   net_prefix_length != 0) {
> +                                       net_set_state(NETLOOP_SUCCESS
> );
> +                                       net_set_timeout_handler(0,
> NULL);
> +                               }
> 
>                 if (net_state == NETLOOP_FAIL)
>                         ret = net_start_again();
> diff --git a/net/net6.c b/net/net6.c
> index 75577bc..2dd64c0 100644
> --- a/net/net6.c
> +++ b/net/net6.c
> @@ -413,6 +413,7 @@ int net_ip6_handler(struct ethernet_hdr *et,
> struct ip6_hdr *ip6, int len)
>                         break;
>                 case IPV6_NDISC_NEIGHBOUR_SOLICITATION:
>                 case IPV6_NDISC_NEIGHBOUR_ADVERTISEMENT:
> +               case IPV6_NDISC_ROUTER_ADVERTISEMENT:
>                         ndisc_receive(et, ip6, len);
>                         break;
>                 default:
> --
> 1.8.3.1
> 
> 

Tested on Si-five Hi-five Unmatched board (RISC-V)

Good. Thanks!

Tested-by: Viacheslav Mitrofanov <v.v.mitrofanov at yadro.com>Reviewed-by: 
Viacheslav Mitrofanov <v.v.mitrofanov at yadro.com>


More information about the U-Boot mailing list