-
Notifications
You must be signed in to change notification settings - Fork 54.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
net: Introduce L3 Master device abstraction
L3 master devices allow users of the abstraction to influence FIB lookups for enslaved devices. Current API provides a means for the master device to return a specific FIB table for an enslaved device, to return an rtable/custom dst and influence the OIF used for fib lookups. Signed-off-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Showing
8 changed files
with
246 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* include/net/l3mdev.h - L3 master device API | ||
* Copyright (c) 2015 Cumulus Networks | ||
* Copyright (c) 2015 David Ahern <dsa@cumulusnetworks.com> | ||
* | ||
* 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 _NET_L3MDEV_H_ | ||
#define _NET_L3MDEV_H_ | ||
|
||
/** | ||
* struct l3mdev_ops - l3mdev operations | ||
* | ||
* @l3mdev_fib_table: Get FIB table id to use for lookups | ||
* | ||
* @l3mdev_get_rtable: Get cached IPv4 rtable (dst_entry) for device | ||
*/ | ||
|
||
struct l3mdev_ops { | ||
u32 (*l3mdev_fib_table)(const struct net_device *dev); | ||
struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev, | ||
const struct flowi4 *fl4); | ||
}; | ||
|
||
#ifdef CONFIG_NET_L3_MASTER_DEV | ||
|
||
int l3mdev_master_ifindex_rcu(struct net_device *dev); | ||
static inline int l3mdev_master_ifindex(struct net_device *dev) | ||
{ | ||
int ifindex; | ||
|
||
rcu_read_lock(); | ||
ifindex = l3mdev_master_ifindex_rcu(dev); | ||
rcu_read_unlock(); | ||
|
||
return ifindex; | ||
} | ||
|
||
/* get index of an interface to use for FIB lookups. For devices | ||
* enslaved to an L3 master device FIB lookups are based on the | ||
* master index | ||
*/ | ||
static inline int l3mdev_fib_oif_rcu(struct net_device *dev) | ||
{ | ||
return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex; | ||
} | ||
|
||
static inline int l3mdev_fib_oif(struct net_device *dev) | ||
{ | ||
int oif; | ||
|
||
rcu_read_lock(); | ||
oif = l3mdev_fib_oif_rcu(dev); | ||
rcu_read_unlock(); | ||
|
||
return oif; | ||
} | ||
|
||
u32 l3mdev_fib_table_rcu(const struct net_device *dev); | ||
u32 l3mdev_fib_table_by_index(struct net *net, int ifindex); | ||
static inline u32 l3mdev_fib_table(const struct net_device *dev) | ||
{ | ||
u32 tb_id; | ||
|
||
rcu_read_lock(); | ||
tb_id = l3mdev_fib_table_rcu(dev); | ||
rcu_read_unlock(); | ||
|
||
return tb_id; | ||
} | ||
|
||
static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, | ||
const struct flowi4 *fl4) | ||
{ | ||
if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rtable) | ||
return dev->l3mdev_ops->l3mdev_get_rtable(dev, fl4); | ||
|
||
return NULL; | ||
} | ||
|
||
#else | ||
|
||
static inline int l3mdev_master_ifindex_rcu(struct net_device *dev) | ||
{ | ||
return 0; | ||
} | ||
static inline int l3mdev_master_ifindex(struct net_device *dev) | ||
{ | ||
return 0; | ||
} | ||
|
||
static inline int l3mdev_fib_oif_rcu(struct net_device *dev) | ||
{ | ||
return dev ? dev->ifindex : 0; | ||
} | ||
static inline int l3mdev_fib_oif(struct net_device *dev) | ||
{ | ||
return dev ? dev->ifindex : 0; | ||
} | ||
|
||
static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev) | ||
{ | ||
return 0; | ||
} | ||
static inline u32 l3mdev_fib_table(const struct net_device *dev) | ||
{ | ||
return 0; | ||
} | ||
static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) | ||
{ | ||
return 0; | ||
} | ||
|
||
static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, | ||
const struct flowi4 *fl4) | ||
{ | ||
return NULL; | ||
} | ||
|
||
#endif | ||
|
||
#endif /* _NET_L3MDEV_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# | ||
# Configuration for L3 master device support | ||
# | ||
|
||
config NET_L3_MASTER_DEV | ||
bool "L3 Master device support" | ||
depends on INET || IPV6 | ||
---help--- | ||
This module provides glue between core networking code and device | ||
drivers to support L3 master devices like VRF. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# | ||
# Makefile for the L3 device API | ||
# | ||
|
||
obj-$(CONFIG_NET_L3_MASTER_DEV) += l3mdev.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* net/l3mdev/l3mdev.c - L3 master device implementation | ||
* Copyright (c) 2015 Cumulus Networks | ||
* Copyright (c) 2015 David Ahern <dsa@cumulusnetworks.com> | ||
* | ||
* 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. | ||
*/ | ||
|
||
#include <linux/netdevice.h> | ||
#include <net/l3mdev.h> | ||
|
||
/** | ||
* l3mdev_master_ifindex - get index of L3 master device | ||
* @dev: targeted interface | ||
*/ | ||
|
||
int l3mdev_master_ifindex_rcu(struct net_device *dev) | ||
{ | ||
int ifindex = 0; | ||
|
||
if (!dev) | ||
return 0; | ||
|
||
if (netif_is_l3_master(dev)) { | ||
ifindex = dev->ifindex; | ||
} else if (dev->flags & IFF_SLAVE) { | ||
struct net_device *master; | ||
|
||
master = netdev_master_upper_dev_get_rcu(dev); | ||
if (master && netif_is_l3_master(master)) | ||
ifindex = master->ifindex; | ||
} | ||
|
||
return ifindex; | ||
} | ||
EXPORT_SYMBOL_GPL(l3mdev_master_ifindex_rcu); | ||
|
||
/** | ||
* l3mdev_fib_table - get FIB table id associated with an L3 | ||
* master interface | ||
* @dev: targeted interface | ||
*/ | ||
|
||
u32 l3mdev_fib_table_rcu(const struct net_device *dev) | ||
{ | ||
u32 tb_id = 0; | ||
|
||
if (!dev) | ||
return 0; | ||
|
||
if (netif_is_l3_master(dev)) { | ||
if (dev->l3mdev_ops->l3mdev_fib_table) | ||
tb_id = dev->l3mdev_ops->l3mdev_fib_table(dev); | ||
} else if (dev->flags & IFF_SLAVE) { | ||
/* Users of netdev_master_upper_dev_get_rcu need non-const, | ||
* but current inet_*type functions take a const | ||
*/ | ||
struct net_device *_dev = (struct net_device *) dev; | ||
const struct net_device *master; | ||
|
||
master = netdev_master_upper_dev_get_rcu(_dev); | ||
if (master && netif_is_l3_master(master) && | ||
master->l3mdev_ops->l3mdev_fib_table) | ||
tb_id = master->l3mdev_ops->l3mdev_fib_table(master); | ||
} | ||
|
||
return tb_id; | ||
} | ||
EXPORT_SYMBOL_GPL(l3mdev_fib_table_rcu); | ||
|
||
u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) | ||
{ | ||
struct net_device *dev; | ||
u32 tb_id = 0; | ||
|
||
if (!ifindex) | ||
return 0; | ||
|
||
rcu_read_lock(); | ||
|
||
dev = dev_get_by_index_rcu(net, ifindex); | ||
if (dev) | ||
tb_id = l3mdev_fib_table_rcu(dev); | ||
|
||
rcu_read_unlock(); | ||
|
||
return tb_id; | ||
} | ||
EXPORT_SYMBOL_GPL(l3mdev_fib_table_by_index); |