Skip to content

Commit

Permalink
net: Introduce VRF related flags and helpers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Ahern authored and David S. Miller committed Aug 14, 2015
1 parent 0344338 commit 4e3c899
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 0 deletions.
20 changes: 20 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down
139 changes: 139 additions & 0 deletions include/net/vrf.h
Original file line number Diff line number Diff line change
@@ -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 */
9 changes: 9 additions & 0 deletions include/uapi/linux/if_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 4e3c899

Please sign in to comment.