Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / net / l3mdev / l3mdev.c
index c4a1c3e..8da86ce 100644 (file)
@@ -100,15 +100,14 @@ u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
 EXPORT_SYMBOL_GPL(l3mdev_fib_table_by_index);
 
 /**
- *     l3mdev_get_rt6_dst - IPv6 route lookup based on flow. Returns
- *                          cached route for L3 master device if relevant
- *                          to flow
+ *     l3mdev_link_scope_lookup - IPv6 route lookup based on flow for link
+ *                          local and multicast addresses
  *     @net: network namespace for device index lookup
  *     @fl6: IPv6 flow struct for lookup
  */
 
-struct dst_entry *l3mdev_get_rt6_dst(struct net *net,
-                                    struct flowi6 *fl6)
+struct dst_entry *l3mdev_link_scope_lookup(struct net *net,
+                                          struct flowi6 *fl6)
 {
        struct dst_entry *dst = NULL;
        struct net_device *dev;
@@ -121,70 +120,15 @@ struct dst_entry *l3mdev_get_rt6_dst(struct net *net,
                        dev = netdev_master_upper_dev_get_rcu(dev);
 
                if (dev && netif_is_l3_master(dev) &&
-                   dev->l3mdev_ops->l3mdev_get_rt6_dst)
-                       dst = dev->l3mdev_ops->l3mdev_get_rt6_dst(dev, fl6);
+                   dev->l3mdev_ops->l3mdev_link_scope_lookup)
+                       dst = dev->l3mdev_ops->l3mdev_link_scope_lookup(dev, fl6);
 
                rcu_read_unlock();
        }
 
        return dst;
 }
-EXPORT_SYMBOL_GPL(l3mdev_get_rt6_dst);
-
-/**
- *     l3mdev_get_saddr - get source address for a flow based on an interface
- *                        enslaved to an L3 master device
- *     @net: network namespace for device index lookup
- *     @ifindex: Interface index
- *     @fl4: IPv4 flow struct
- */
-
-int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4)
-{
-       struct net_device *dev;
-       int rc = 0;
-
-       if (ifindex) {
-               rcu_read_lock();
-
-               dev = dev_get_by_index_rcu(net, ifindex);
-               if (dev && netif_is_l3_slave(dev))
-                       dev = netdev_master_upper_dev_get_rcu(dev);
-
-               if (dev && netif_is_l3_master(dev) &&
-                   dev->l3mdev_ops->l3mdev_get_saddr)
-                       rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4);
-
-               rcu_read_unlock();
-       }
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(l3mdev_get_saddr);
-
-int l3mdev_get_saddr6(struct net *net, const struct sock *sk,
-                     struct flowi6 *fl6)
-{
-       struct net_device *dev;
-       int rc = 0;
-
-       if (fl6->flowi6_oif) {
-               rcu_read_lock();
-
-               dev = dev_get_by_index_rcu(net, fl6->flowi6_oif);
-               if (dev && netif_is_l3_slave(dev))
-                       dev = netdev_master_upper_dev_get_rcu(dev);
-
-               if (dev && netif_is_l3_master(dev) &&
-                   dev->l3mdev_ops->l3mdev_get_saddr6)
-                       rc = dev->l3mdev_ops->l3mdev_get_saddr6(dev, sk, fl6);
-
-               rcu_read_unlock();
-       }
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(l3mdev_get_saddr6);
+EXPORT_SYMBOL_GPL(l3mdev_link_scope_lookup);
 
 /**
  *     l3mdev_fib_rule_match - Determine if flowi references an
@@ -222,3 +166,38 @@ out:
 
        return rc;
 }
+
+void l3mdev_update_flow(struct net *net, struct flowi *fl)
+{
+       struct net_device *dev;
+       int ifindex;
+
+       rcu_read_lock();
+
+       if (fl->flowi_oif) {
+               dev = dev_get_by_index_rcu(net, fl->flowi_oif);
+               if (dev) {
+                       ifindex = l3mdev_master_ifindex_rcu(dev);
+                       if (ifindex) {
+                               fl->flowi_oif = ifindex;
+                               fl->flowi_flags |= FLOWI_FLAG_SKIP_NH_OIF;
+                               goto out;
+                       }
+               }
+       }
+
+       if (fl->flowi_iif) {
+               dev = dev_get_by_index_rcu(net, fl->flowi_iif);
+               if (dev) {
+                       ifindex = l3mdev_master_ifindex_rcu(dev);
+                       if (ifindex) {
+                               fl->flowi_iif = ifindex;
+                               fl->flowi_flags |= FLOWI_FLAG_SKIP_NH_OIF;
+                       }
+               }
+       }
+
+out:
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(l3mdev_update_flow);