net: Introduce VRF related flags and helpers
authorDavid Ahern <dsa@cumulusnetworks.com>
Thu, 13 Aug 2015 20:59:00 +0000 (14:59 -0600)
committerDavid S. Miller <davem@davemloft.net>
Fri, 14 Aug 2015 05:43:20 +0000 (22:43 -0700)
Add a VRF_MASTER flag for interfaces and helper functions for determining
if a device is a VRF_MASTER.

Add link attribute for passing VRF_TABLE id.

Add vrf_ptr to netdevice.

Add various macros for determining if a device is a VRF device, the index
of the master VRF device and table associated with VRF device.

Signed-off-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
include/net/vrf.h [new file with mode: 0644]
include/uapi/linux/if_link.h

index 607b5f41f46f93e506adbefd7b3ed11ed8acfb67..f7a6ef2fae3a46a82aba6088b25ed15afd0f6952 100644 (file)
@@ -1289,6 +1289,7 @@ enum netdev_priv_flags {
        IFF_XMIT_DST_RELEASE_PERM       = 1<<22,
        IFF_IPVLAN_MASTER               = 1<<23,
        IFF_IPVLAN_SLAVE                = 1<<24,
+       IFF_VRF_MASTER                  = 1<<25,
 };
 
 #define IFF_802_1Q_VLAN                        IFF_802_1Q_VLAN
@@ -1316,6 +1317,7 @@ enum netdev_priv_flags {
 #define IFF_XMIT_DST_RELEASE_PERM      IFF_XMIT_DST_RELEASE_PERM
 #define IFF_IPVLAN_MASTER              IFF_IPVLAN_MASTER
 #define IFF_IPVLAN_SLAVE               IFF_IPVLAN_SLAVE
+#define IFF_VRF_MASTER                 IFF_VRF_MASTER
 
 /**
  *     struct net_device - The DEVICE structure.
@@ -1432,6 +1434,7 @@ enum netdev_priv_flags {
  *     @dn_ptr:        DECnet specific data
  *     @ip6_ptr:       IPv6 specific data
  *     @ax25_ptr:      AX.25 specific data
+ *     @vrf_ptr:       VRF specific data
  *     @ieee80211_ptr: IEEE 802.11 specific data, assign before registering
  *
  *     @last_rx:       Time of last Rx
@@ -1650,6 +1653,7 @@ struct net_device {
        struct dn_dev __rcu     *dn_ptr;
        struct inet6_dev __rcu  *ip6_ptr;
        void                    *ax25_ptr;
+       struct net_vrf_dev __rcu *vrf_ptr;
        struct wireless_dev     *ieee80211_ptr;
        struct wpan_dev         *ieee802154_ptr;
 #if IS_ENABLED(CONFIG_MPLS_ROUTING)
@@ -3808,6 +3812,22 @@ static inline bool netif_supports_nofcs(struct net_device *dev)
        return dev->priv_flags & IFF_SUPP_NOFCS;
 }
 
+static inline bool netif_is_vrf(const struct net_device *dev)
+{
+       return dev->priv_flags & IFF_VRF_MASTER;
+}
+
+static inline bool netif_index_is_vrf(struct net *net, int ifindex)
+{
+       struct net_device *dev = dev_get_by_index_rcu(net, ifindex);
+       bool rc = false;
+
+       if (dev)
+               rc = netif_is_vrf(dev);
+
+       return rc;
+}
+
 /* This device needs to keep skb dst for qdisc enqueue or ndo_start_xmit() */
 static inline void netif_keep_dst(struct net_device *dev)
 {
diff --git a/include/net/vrf.h b/include/net/vrf.h
new file mode 100644 (file)
index 0000000..0484d29
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * include/net/net_vrf.h - adds vrf dev structure definitions
+ * Copyright (c) 2015 Cumulus Networks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_NET_VRF_H
+#define __LINUX_NET_VRF_H
+
+struct net_vrf_dev {
+       struct rcu_head         rcu;
+       int                     ifindex; /* ifindex of master dev */
+       u32                     tb_id;   /* table id for VRF */
+};
+
+struct slave {
+       struct list_head        list;
+       struct net_device       *dev;
+};
+
+struct slave_queue {
+       struct list_head        all_slaves;
+       int                     num_slaves;
+};
+
+struct net_vrf {
+       struct slave_queue      queue;
+       struct rtable           *rth;
+       u32                     tb_id;
+};
+
+
+#if IS_ENABLED(CONFIG_NET_VRF)
+/* called with rcu_read_lock() */
+static inline int vrf_master_ifindex_rcu(const struct net_device *dev)
+{
+       struct net_vrf_dev *vrf_ptr;
+       int ifindex = 0;
+
+       if (!dev)
+               return 0;
+
+       if (netif_is_vrf(dev))
+               ifindex = dev->ifindex;
+       else {
+               vrf_ptr = rcu_dereference(dev->vrf_ptr);
+               if (vrf_ptr)
+                       ifindex = vrf_ptr->ifindex;
+       }
+
+       return ifindex;
+}
+
+/* called with rcu_read_lock */
+static inline int vrf_dev_table_rcu(const struct net_device *dev)
+{
+       int tb_id = 0;
+
+       if (dev) {
+               struct net_vrf_dev *vrf_ptr;
+
+               vrf_ptr = rcu_dereference(dev->vrf_ptr);
+               if (vrf_ptr)
+                       tb_id = vrf_ptr->tb_id;
+       }
+       return tb_id;
+}
+
+static inline int vrf_dev_table(const struct net_device *dev)
+{
+       int tb_id;
+
+       rcu_read_lock();
+       tb_id = vrf_dev_table_rcu(dev);
+       rcu_read_unlock();
+
+       return tb_id;
+}
+
+/* called with rtnl */
+static inline int vrf_dev_table_rtnl(const struct net_device *dev)
+{
+       int tb_id = 0;
+
+       if (dev) {
+               struct net_vrf_dev *vrf_ptr;
+
+               vrf_ptr = rtnl_dereference(dev->vrf_ptr);
+               if (vrf_ptr)
+                       tb_id = vrf_ptr->tb_id;
+       }
+       return tb_id;
+}
+
+/* caller has already checked netif_is_vrf(dev) */
+static inline struct rtable *vrf_dev_get_rth(const struct net_device *dev)
+{
+       struct rtable *rth = ERR_PTR(-ENETUNREACH);
+       struct net_vrf *vrf = netdev_priv(dev);
+
+       if (vrf) {
+               rth = vrf->rth;
+               atomic_inc(&rth->dst.__refcnt);
+       }
+       return rth;
+}
+
+#else
+static inline int vrf_master_ifindex_rcu(const struct net_device *dev)
+{
+       return 0;
+}
+
+static inline int vrf_dev_table_rcu(const struct net_device *dev)
+{
+       return 0;
+}
+
+static inline int vrf_dev_table(const struct net_device *dev)
+{
+       return 0;
+}
+
+static inline int vrf_dev_table_rtnl(const struct net_device *dev)
+{
+       return 0;
+}
+
+static inline struct rtable *vrf_dev_get_rth(const struct net_device *dev)
+{
+       return ERR_PTR(-ENETUNREACH);
+}
+#endif
+
+#endif /* __LINUX_NET_VRF_H */
index d450be36add200bdd5c9d8d92aafc0d8c34845aa..313c305fd1ad47c862fa0c4da2c44c7a496c47af 100644 (file)
@@ -341,6 +341,15 @@ enum macvlan_macaddr_mode {
 
 #define MACVLAN_FLAG_NOPROMISC 1
 
+/* VRF section */
+enum {
+       IFLA_VRF_UNSPEC,
+       IFLA_VRF_TABLE,
+       __IFLA_VRF_MAX
+};
+
+#define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1)
+
 /* IPVLAN section */
 enum {
        IFLA_IPVLAN_UNSPEC,