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: Josef Bacik
Subject: Re: [PATCH 3/3] net: fix ipv6 routing
Date: Mon, 10 Aug 2015 10:00:09 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0

On 08/09/2015 10:58 AM, Andrei Borzenkov wrote:
В 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.

I've been reading the spec a lot recently and I couldn't figure out a way to differentiate between a default route and just another route. From my reading if we get multipe RA's we're supposed to just round robin through them until we get the one that works, obviously taking into account when the router lifetime expires and such. We don't take into account the lifetime at all except to see if it is set to 0, otherwise we never expire anything. We should probably build this out in the future, but for now just picking whichever router comes first as the default route will work most of the time.


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.

I'll try and work something out that is better than this patch.


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.

Right if we're talking to a link-local destination, but when talking to a global link destination the format is

src-ip: global address for the interface
dst-ip: global address for destination
src-mac: our mac
dst-mac: the mac of the default route

Which is why I did that weird translation.


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.

Eesh I just ripped that out didn't I? Sorry about that, I'll rework this again. I think I'll do like you said above, just kind of create an interface with different scopes and that way if you use both slaac and dhcp and get the same address we don't end up with two different interfaces. And then I'll come up with something to tie the routers to the interfaces and rework the route stuff so it is a bit cleaner. This will probably be towards the end of the week, I've found some weird timeout problem in the TCP stack I'm trying to track down, once I've figured that out I'll rework this patch. Thanks,

Josef



reply via email to

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