• Roopa Prabhu's avatar
    ipv6: fix multipath route replace error recovery · c59231c8
    Roopa Prabhu authored
    [ Upstream commit 6b9ea5a6 ]
    
    Problem:
    The ecmp route replace support for ipv6 in the kernel, deletes the
    existing ecmp route too early, ie when it installs the first nexthop.
    If there is an error in installing the subsequent nexthops, its too late
    to recover the already deleted existing route leaving the fib
    in an inconsistent state.
    
    This patch reduces the possibility of this by doing the following:
    a) Changes the existing multipath route add code to a two stage process:
      build rt6_infos + insert them
    	ip6_route_add rt6_info creation code is moved into
    	ip6_route_info_create.
    b) This ensures that most errors are caught during building rt6_infos
      and we fail early
    c) Separates multipath add and del code. Because add needs the special
      two stage mode in a) and delete essentially does not care.
    d) In any event if the code fails during inserting a route again, a
      warning is printed (This should be unlikely)
    
    Before the patch:
    $ip -6 route show
    3000:1000:1000:1000::2 via fe80::202:ff:fe00:b dev swp49s0 metric 1024
    3000:1000:1000:1000::2 via fe80::202:ff:fe00:d dev swp49s1 metric 1024
    3000:1000:1000:1000::2 via fe80::202:ff:fe00:f dev swp49s2 metric 1024
    
    /* Try replacing the route with a duplicate nexthop */
    $ip -6 route change 3000:1000:1000:1000::2/128 nexthop via
    fe80::202:ff:fe00:b dev swp49s0 nexthop via fe80::202:ff:fe00:d dev
    swp49s1 nexthop via fe80::202:ff:fe00:d dev swp49s1
    RTNETLINK answers: File exists
    
    $ip -6 route show
    /* previously added ecmp route 3000:1000:1000:1000::2 dissappears from
     * kernel */
    
    After the patch:
    $ip -6 route show
    3000:1000:1000:1000::2 via fe80::202:ff:fe00:b dev swp49s0 metric 1024
    3000:1000:1000:1000::2 via fe80::202:ff:fe00:d dev swp49s1 metric 1024
    3000:1000:1000:1000::2 via fe80::202:ff:fe00:f dev swp49s2 metric 1024
    
    /* Try replacing the route with a duplicate nexthop */
    $ip -6 route change 3000:1000:1000:1000::2/128 nexthop via
    fe80::202:ff:fe00:b dev swp49s0 nexthop via fe80::202:ff:fe00:d dev
    swp49s1 nexthop via fe80::202:ff:fe00:d dev swp49s1
    RTNETLINK answers: File exists
    
    $ip -6 route show
    3000:1000:1000:1000::2 via fe80::202:ff:fe00:b dev swp49s0 metric 1024
    3000:1000:1000:1000::2 via fe80::202:ff:fe00:d dev swp49s1 metric 1024
    3000:1000:1000:1000::2 via fe80::202:ff:fe00:f dev swp49s2 metric 1024
    
    Fixes: 27596472 ("ipv6: fix ECMP route replacement")
    Signed-off-by: default avatarRoopa Prabhu <roopa@cumulusnetworks.com>
    Reviewed-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
    Acked-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    c59231c8
route.c 82.1 KB