net: Add IPv6 support to l3mdev
authorDavid Ahern <dsa@cumulusnetworks.com>
Mon, 12 Oct 2015 18:47:07 +0000 (11:47 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 13 Oct 2015 11:55:04 +0000 (04:55 -0700)
Add operations to retrieve cached IPv6 dst entry from l3mdev device
and lookup IPv6 source address.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/l3mdev.h

index 44a19a1711048edf24e56c4f298f86a7cdd77789..774d85b2d5d97734b79eadea20f090ebf684b057 100644 (file)
  * @l3mdev_get_rtable: Get cached IPv4 rtable (dst_entry) for device
  *
  * @l3mdev_get_saddr: Get source address for a flow
+ *
+ * @l3mdev_get_rt6_dst: Get cached IPv6 rt6_info (dst_entry) for device
  */
 
 struct l3mdev_ops {
        u32             (*l3mdev_fib_table)(const struct net_device *dev);
+
+       /* IPv4 ops */
        struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev,
                                             const struct flowi4 *fl4);
        void            (*l3mdev_get_saddr)(struct net_device *dev,
                                            struct flowi4 *fl4);
+
+       /* IPv6 ops */
+       struct dst_entry * (*l3mdev_get_rt6_dst)(const struct net_device *dev,
+                                                const struct flowi6 *fl6);
 };
 
 #ifdef CONFIG_NET_L3_MASTER_DEV
@@ -123,6 +131,31 @@ static inline void l3mdev_get_saddr(struct net *net, int ifindex,
        }
 }
 
+static inline struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev,
+                                                  const struct flowi6 *fl6)
+{
+       if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rt6_dst)
+               return dev->l3mdev_ops->l3mdev_get_rt6_dst(dev, fl6);
+
+       return NULL;
+}
+
+static inline
+struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
+                                       const struct flowi6 *fl6)
+{
+       struct dst_entry *dst = NULL;
+       struct net_device *dev;
+
+       dev = dev_get_by_index(net, fl6->flowi6_oif);
+       if (dev) {
+               dst = l3mdev_get_rt6_dst(dev, fl6);
+               dev_put(dev);
+       }
+
+       return dst;
+}
+
 #else
 
 static inline int l3mdev_master_ifindex_rcu(struct net_device *dev)
@@ -171,6 +204,19 @@ static inline void l3mdev_get_saddr(struct net *net, int ifindex,
                                    struct flowi4 *fl4)
 {
 }
+
+static inline
+struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev,
+                                    const struct flowi6 *fl6)
+{
+       return NULL;
+}
+static inline
+struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
+                                       const struct flowi6 *fl6)
+{
+       return NULL;
+}
 #endif
 
 #endif /* _NET_L3MDEV_H_ */