Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / net / ipv6 / route.c
index e3a224b..5a5aeb9 100644 (file)
@@ -1147,15 +1147,16 @@ static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *
        return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
 }
 
-static struct dst_entry *ip6_route_input_lookup(struct net *net,
-                                               struct net_device *dev,
-                                               struct flowi6 *fl6, int flags)
+struct dst_entry *ip6_route_input_lookup(struct net *net,
+                                        struct net_device *dev,
+                                        struct flowi6 *fl6, int flags)
 {
        if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG)
                flags |= RT6_LOOKUP_F_IFACE;
 
        return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input);
 }
+EXPORT_SYMBOL_GPL(ip6_route_input_lookup);
 
 void ip6_route_input(struct sk_buff *skb)
 {
@@ -1164,7 +1165,7 @@ void ip6_route_input(struct sk_buff *skb)
        int flags = RT6_LOOKUP_F_HAS_SADDR;
        struct ip_tunnel_info *tun_info;
        struct flowi6 fl6 = {
-               .flowi6_iif = l3mdev_fib_oif(skb->dev),
+               .flowi6_iif = skb->dev->ifindex,
                .daddr = iph->daddr,
                .saddr = iph->saddr,
                .flowlabel = ip6_flowinfo(iph),
@@ -1188,12 +1189,15 @@ static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table
 struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
                                         struct flowi6 *fl6, int flags)
 {
-       struct dst_entry *dst;
        bool any_src;
 
-       dst = l3mdev_get_rt6_dst(net, fl6);
-       if (dst)
-               return dst;
+       if (rt6_need_strict(&fl6->daddr)) {
+               struct dst_entry *dst;
+
+               dst = l3mdev_link_scope_lookup(net, fl6);
+               if (dst)
+                       return dst;
+       }
 
        fl6->flowi6_iif = LOOPBACK_IFINDEX;
 
@@ -1604,7 +1608,9 @@ static unsigned int ip6_mtu(const struct dst_entry *dst)
        rcu_read_unlock();
 
 out:
-       return min_t(unsigned int, mtu, IP6_MAX_MTU);
+       mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
+
+       return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
 }
 
 static struct dst_entry *icmp6_dst_gc_list;
@@ -2565,8 +2571,16 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 {
        u32 tb_id;
        struct net *net = dev_net(idev->dev);
-       struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
-                                           DST_NOCOUNT);
+       struct net_device *dev = net->loopback_dev;
+       struct rt6_info *rt;
+
+       /* use L3 Master device as loopback for host routes if device
+        * is enslaved and address is not link local or multicast
+        */
+       if (!rt6_need_strict(addr))
+               dev = l3mdev_master_dev_rcu(idev->dev) ? : dev;
+
+       rt = ip6_dst_alloc(net, dev, DST_NOCOUNT);
        if (!rt)
                return ERR_PTR(-ENOMEM);
 
@@ -3345,11 +3359,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
        } else {
                fl6.flowi6_oif = oif;
 
-               if (netif_index_is_l3_master(net, oif)) {
-                       fl6.flowi6_flags = FLOWI_FLAG_L3MDEV_SRC |
-                                          FLOWI_FLAG_SKIP_NH_OIF;
-               }
-
                rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
        }