grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 3/3] net: fix ipv6 routing


From: Andrei Borzenkov
Subject: Re: [PATCH 3/3] net: fix ipv6 routing
Date: Sun, 9 Aug 2015 17:58:28 +0300

В Wed, 5 Aug 2015 14:36:39 -0400
Josef Bacik <address@hidden> пишет:

> Currently we cannot talk to ipv6 addresses outside of our local link area
> because we don't setup our routes properly nor do we talk to the router
> properly.  Currently net_ipv6_autoconf adds routes for the local link prefix 
> and
> ties it to the global link device.  This isn't helpful at all, we completely
> drop the router part of the router advertisement.  So instead create a 
> "default
> route" flag in routes and create a new route with the local link prefix and 
> the
> router source address.
> 

Note that RA does not always mean default route. You need to check
router lifetime to decide whether to use it as default route.

> The second part of this problem is that the routing code thinks in ipv4 terms,
> so it expects to find a route to the address we're looking for in our routing
> table.  If we find a gateway then we just look for which interface matches the
> network for the gateway.  This doesn't work for ipv6 since the router gives us
> its local link address, so the gateway will find the local link interface,
> instead of the global interface.  So to deal with this do a few things
> 

I am afraid it cannot be solved on routing table level. We need to bite
the bullet and add notion of interface zone and associate each link
local IPv6 address with interface it comes from (or sent to). This
automatically solves also the problem in your other patch as well as
this one by eliminating need to (attempt to) route link local in the
first place - it is simply sent to interface it is associated with.

It also means we probably need to support IPv6%scope notation for
addresses.

> 1) Create a new "default route" flag for any router advertisements we get when
> doing the ipv6 autoconf stuff.  Then we create a normal gateway route with the
> default route flag set.
> 
> 2) When looking for routes keep track of any default routes we find, and if we
> don't find an exact route that matches we use the default route, which will 
> set
> the gateway to the router, and then we will find the local link interface that
> matches this router.
> 
> 3) Translate the local link interface to the global link interface.  We build
> the ip packets based on the address on the interface, and this needs to have 
> the
> global address, not the local one.  So loop through our interfaces until we 
> find
> a global address with the same hwaddress as the local link interface and use
> that instead.  This way we get the right addresses on our IP packets.
> 

If I read RFC6724 correctly, we actually must prefer link-local
source address when speaking with link-local destination.

> With this patch I can now do net_ipv6_autoconf and immediately talk to ipv6
> addresses outside of my local network.  Thanks,
> 
> Signed-off-by: Josef Bacik <address@hidden>
> ---
>  grub-core/net/bootp.c                  |  2 +-
>  grub-core/net/drivers/ieee1275/ofnet.c |  2 +-
>  grub-core/net/icmp6.c                  | 50 ++++++++++------------
>  grub-core/net/net.c                    | 76 
> +++++++++++++++++++++-------------
>  include/grub/net.h                     | 28 ++++++++++++-
>  5 files changed, 99 insertions(+), 59 deletions(-)
> 
...
> diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c
> index 7953e68..fad04a9 100644
> --- a/grub-core/net/icmp6.c
> +++ b/grub-core/net/icmp6.c
> @@ -373,7 +373,10 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
>           if (ohdr->type == OPTION_PREFIX && ohdr->len == 4)
>             {
>               struct prefix_option *opt = (struct prefix_option *) ptr;
> +             struct grub_net_route *route;
>               struct grub_net_slaac_mac_list *slaac;
> +
> +             grub_net_network_level_netaddress_t netaddr;
>               if (!(opt->flags & FLAG_SLAAC)
>                   || (grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80
>                   || (grub_be_to_cpu32 (opt->preferred_lifetime)
> @@ -391,18 +394,12 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
>               for (slaac = card->slaac_list; slaac; slaac = slaac->next)
>                 {
>                   grub_net_network_level_address_t addr;
> -                 grub_net_network_level_netaddress_t netaddr;
> -
>                   if (slaac->address.type
>                       != GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET)
>                     continue;
>                   addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
>                   addr.ipv6[0] = opt->prefix[0];
>                   addr.ipv6[1] = grub_net_ipv6_get_id (&slaac->address);
> -                 netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
> -                 netaddr.ipv6.base[0] = opt->prefix[0];
> -                 netaddr.ipv6.base[1] = 0;
> -                 netaddr.ipv6.masksize = 64;
>  
>                   FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
>                   {
> @@ -410,29 +407,28 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
>                         && grub_net_addr_cmp (&inf->address, &addr) == 0)
>                       break;
>                   }
> -                 /* Update lease time if needed here once we have
> -                    lease times.  */
> -                 if (inf)
> -                   continue;
> +                 if (!inf)
> +                   slaac->slaac_counter++;
> +               }
>  
> -                 grub_dprintf ("net", "creating slaac\n");
> +             netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
> +             netaddr.ipv6.base[0] = opt->prefix[0];
> +             netaddr.ipv6.base[1] = 0;
> +             netaddr.ipv6.masksize = 64;
>  
> -                 {
> -                   char *name;
> -                   name = grub_xasprintf ("%s:%d",
> -                                          slaac->name, 
> slaac->slaac_counter++);
> -                   if (!name)
> -                     {
> -                       grub_errno = GRUB_ERR_NONE;
> -                       continue;
> -                     }
> -                   inf = grub_net_add_addr (name, 
> -                                            card, &addr,
> -                                            &slaac->address, 0);
> -                   grub_net_add_route (name, netaddr, inf);
> -                   grub_free (name);
> -                 }
> -               }

This kills SLAAC. Where global addresses now come from? You probably
get them from DHCPv6 but it does not mean we should drop SLAAC.

> +             FOR_NET_ROUTES(route)
> +             {
> +               if (!grub_memcmp(&route->gw, source, sizeof (route->gw)))
> +                 break;
> +             }
> +             /* Update lease time if needed here once we have
> +                lease times.  */
> +             if (route)
> +               continue;
> +
> +             grub_dprintf ("net", "creating default route\n");
> +
> +             grub_net_add_route_gw ("default6", netaddr, *source, 1);
>             }
>         }
>       if (ptr != nb->tail)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]