Skip to content

Commit 1b69c6d

Browse files
David Aherndavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 007979e commit 1b69c6d

File tree

8 files changed

+246
-0
lines changed

8 files changed

+246
-0
lines changed

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6095,6 +6095,13 @@ F: Documentation/auxdisplay/ks0108
60956095
F: drivers/auxdisplay/ks0108.c
60966096
F: include/linux/ks0108.h
60976097

6098+
L3MDEV
6099+
M: David Ahern <[email protected]>
6100+
6101+
S: Maintained
6102+
F: net/l3mdev
6103+
F: include/net/l3mdev.h
6104+
60986105
LAPB module
60996106
61006107
S: Orphan

include/linux/netdevice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,6 +1587,9 @@ struct net_device {
15871587
#ifdef CONFIG_NET_SWITCHDEV
15881588
const struct switchdev_ops *switchdev_ops;
15891589
#endif
1590+
#ifdef CONFIG_NET_L3_MASTER_DEV
1591+
const struct l3mdev_ops *l3mdev_ops;
1592+
#endif
15901593

15911594
const struct header_ops *header_ops;
15921595

include/net/l3mdev.h

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* include/net/l3mdev.h - L3 master device API
3+
* Copyright (c) 2015 Cumulus Networks
4+
* Copyright (c) 2015 David Ahern <[email protected]>
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*/
11+
#ifndef _NET_L3MDEV_H_
12+
#define _NET_L3MDEV_H_
13+
14+
/**
15+
* struct l3mdev_ops - l3mdev operations
16+
*
17+
* @l3mdev_fib_table: Get FIB table id to use for lookups
18+
*
19+
* @l3mdev_get_rtable: Get cached IPv4 rtable (dst_entry) for device
20+
*/
21+
22+
struct l3mdev_ops {
23+
u32 (*l3mdev_fib_table)(const struct net_device *dev);
24+
struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev,
25+
const struct flowi4 *fl4);
26+
};
27+
28+
#ifdef CONFIG_NET_L3_MASTER_DEV
29+
30+
int l3mdev_master_ifindex_rcu(struct net_device *dev);
31+
static inline int l3mdev_master_ifindex(struct net_device *dev)
32+
{
33+
int ifindex;
34+
35+
rcu_read_lock();
36+
ifindex = l3mdev_master_ifindex_rcu(dev);
37+
rcu_read_unlock();
38+
39+
return ifindex;
40+
}
41+
42+
/* get index of an interface to use for FIB lookups. For devices
43+
* enslaved to an L3 master device FIB lookups are based on the
44+
* master index
45+
*/
46+
static inline int l3mdev_fib_oif_rcu(struct net_device *dev)
47+
{
48+
return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex;
49+
}
50+
51+
static inline int l3mdev_fib_oif(struct net_device *dev)
52+
{
53+
int oif;
54+
55+
rcu_read_lock();
56+
oif = l3mdev_fib_oif_rcu(dev);
57+
rcu_read_unlock();
58+
59+
return oif;
60+
}
61+
62+
u32 l3mdev_fib_table_rcu(const struct net_device *dev);
63+
u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
64+
static inline u32 l3mdev_fib_table(const struct net_device *dev)
65+
{
66+
u32 tb_id;
67+
68+
rcu_read_lock();
69+
tb_id = l3mdev_fib_table_rcu(dev);
70+
rcu_read_unlock();
71+
72+
return tb_id;
73+
}
74+
75+
static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev,
76+
const struct flowi4 *fl4)
77+
{
78+
if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rtable)
79+
return dev->l3mdev_ops->l3mdev_get_rtable(dev, fl4);
80+
81+
return NULL;
82+
}
83+
84+
#else
85+
86+
static inline int l3mdev_master_ifindex_rcu(struct net_device *dev)
87+
{
88+
return 0;
89+
}
90+
static inline int l3mdev_master_ifindex(struct net_device *dev)
91+
{
92+
return 0;
93+
}
94+
95+
static inline int l3mdev_fib_oif_rcu(struct net_device *dev)
96+
{
97+
return dev ? dev->ifindex : 0;
98+
}
99+
static inline int l3mdev_fib_oif(struct net_device *dev)
100+
{
101+
return dev ? dev->ifindex : 0;
102+
}
103+
104+
static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev)
105+
{
106+
return 0;
107+
}
108+
static inline u32 l3mdev_fib_table(const struct net_device *dev)
109+
{
110+
return 0;
111+
}
112+
static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
113+
{
114+
return 0;
115+
}
116+
117+
static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev,
118+
const struct flowi4 *fl4)
119+
{
120+
return NULL;
121+
}
122+
123+
#endif
124+
125+
#endif /* _NET_L3MDEV_H_ */

net/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ source "net/netlink/Kconfig"
232232
source "net/mpls/Kconfig"
233233
source "net/hsr/Kconfig"
234234
source "net/switchdev/Kconfig"
235+
source "net/l3mdev/Kconfig"
235236

236237
config RPS
237238
bool

net/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,6 @@ obj-$(CONFIG_HSR) += hsr/
7474
ifneq ($(CONFIG_NET_SWITCHDEV),)
7575
obj-y += switchdev/
7676
endif
77+
ifneq ($(CONFIG_NET_L3_MASTER_DEV),)
78+
obj-y += l3mdev/
79+
endif

net/l3mdev/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# Configuration for L3 master device support
3+
#
4+
5+
config NET_L3_MASTER_DEV
6+
bool "L3 Master device support"
7+
depends on INET || IPV6
8+
---help---
9+
This module provides glue between core networking code and device
10+
drivers to support L3 master devices like VRF.

net/l3mdev/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#
2+
# Makefile for the L3 device API
3+
#
4+
5+
obj-$(CONFIG_NET_L3_MASTER_DEV) += l3mdev.o

net/l3mdev/l3mdev.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* net/l3mdev/l3mdev.c - L3 master device implementation
3+
* Copyright (c) 2015 Cumulus Networks
4+
* Copyright (c) 2015 David Ahern <[email protected]>
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*/
11+
12+
#include <linux/netdevice.h>
13+
#include <net/l3mdev.h>
14+
15+
/**
16+
* l3mdev_master_ifindex - get index of L3 master device
17+
* @dev: targeted interface
18+
*/
19+
20+
int l3mdev_master_ifindex_rcu(struct net_device *dev)
21+
{
22+
int ifindex = 0;
23+
24+
if (!dev)
25+
return 0;
26+
27+
if (netif_is_l3_master(dev)) {
28+
ifindex = dev->ifindex;
29+
} else if (dev->flags & IFF_SLAVE) {
30+
struct net_device *master;
31+
32+
master = netdev_master_upper_dev_get_rcu(dev);
33+
if (master && netif_is_l3_master(master))
34+
ifindex = master->ifindex;
35+
}
36+
37+
return ifindex;
38+
}
39+
EXPORT_SYMBOL_GPL(l3mdev_master_ifindex_rcu);
40+
41+
/**
42+
* l3mdev_fib_table - get FIB table id associated with an L3
43+
* master interface
44+
* @dev: targeted interface
45+
*/
46+
47+
u32 l3mdev_fib_table_rcu(const struct net_device *dev)
48+
{
49+
u32 tb_id = 0;
50+
51+
if (!dev)
52+
return 0;
53+
54+
if (netif_is_l3_master(dev)) {
55+
if (dev->l3mdev_ops->l3mdev_fib_table)
56+
tb_id = dev->l3mdev_ops->l3mdev_fib_table(dev);
57+
} else if (dev->flags & IFF_SLAVE) {
58+
/* Users of netdev_master_upper_dev_get_rcu need non-const,
59+
* but current inet_*type functions take a const
60+
*/
61+
struct net_device *_dev = (struct net_device *) dev;
62+
const struct net_device *master;
63+
64+
master = netdev_master_upper_dev_get_rcu(_dev);
65+
if (master && netif_is_l3_master(master) &&
66+
master->l3mdev_ops->l3mdev_fib_table)
67+
tb_id = master->l3mdev_ops->l3mdev_fib_table(master);
68+
}
69+
70+
return tb_id;
71+
}
72+
EXPORT_SYMBOL_GPL(l3mdev_fib_table_rcu);
73+
74+
u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
75+
{
76+
struct net_device *dev;
77+
u32 tb_id = 0;
78+
79+
if (!ifindex)
80+
return 0;
81+
82+
rcu_read_lock();
83+
84+
dev = dev_get_by_index_rcu(net, ifindex);
85+
if (dev)
86+
tb_id = l3mdev_fib_table_rcu(dev);
87+
88+
rcu_read_unlock();
89+
90+
return tb_id;
91+
}
92+
EXPORT_SYMBOL_GPL(l3mdev_fib_table_by_index);

0 commit comments

Comments
 (0)