Skip to content

Commit f82ff59

Browse files
committed
Merge branch 'L3_master_device'
David Ahern says: ==================== net: L3 master device The VRF device is essentially a Layer 3 master device used to associate netdevices with a specific routing table and to influence FIB lookups via 'ip rules' and controlling the oif/iif used for the lookup. This series generalizes the VRF into L3 master device, l3mdev. Similar to switchdev it has a Kconfig option and separate set of operations in net_device allowing it to be completely compiled out if not wanted. The l3mdev methods rely on the 'master' aspect and use of netdev_master_upper_dev_get_rcu to retrieve the master device from a given netdevice if it is enslaved to an L3_MASTER. The VRF device is converted to use the l3mdev operations. At the end the vrf_ptr is no longer and removed, as are all direct references to VRF. The end result is a much simpler implementation for VRF. Thanks to Nikolay for suggestions (eg., use of the master linkage which is the key to making this work) and to Roopa, Andy and Shrijeet for early reviews. v3 - added license header to l3mdev.c - export symbols in l3mdev.c for use with GPL modules - removed netdevice header from l3mdev.h (not needed) and fixed typo in comment v2 - rebased to top of net-next - addressed Niks comments (checking master, removing extra lines, and flipping the order of patches 1 and 2) ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents e6934f3 + 9478d12 commit f82ff59

File tree

21 files changed

+356
-276
lines changed

21 files changed

+356
-276
lines changed

MAINTAINERS

Lines changed: 7 additions & 1 deletion
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
@@ -11266,7 +11273,6 @@ M: Shrijeet Mukherjee <[email protected]>
1126611273
1126711274
S: Maintained
1126811275
F: drivers/net/vrf.c
11269-
F: include/net/vrf.h
1127011276
F: Documentation/networking/vrf.txt
1127111277

1127211278
VT1211 HARDWARE MONITOR DRIVER

drivers/net/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ config NLMON
299299
config NET_VRF
300300
tristate "Virtual Routing and Forwarding (Lite)"
301301
depends on IP_MULTIPLE_TABLES && IPV6_MULTIPLE_TABLES
302+
depends on NET_L3_MASTER_DEV
302303
---help---
303304
This option enables the support for mapping interfaces into VRF's. The
304305
support enables VRF devices.

drivers/net/vrf.c

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include <net/rtnetlink.h>
3535
#include <net/route.h>
3636
#include <net/addrconf.h>
37-
#include <net/vrf.h>
37+
#include <net/l3mdev.h>
3838

3939
#define DRV_NAME "vrf"
4040
#define DRV_VERSION "1.0"
@@ -44,6 +44,21 @@
4444
#define vrf_master_get_rcu(dev) \
4545
((struct net_device *)rcu_dereference(dev->rx_handler_data))
4646

47+
struct slave {
48+
struct list_head list;
49+
struct net_device *dev;
50+
};
51+
52+
struct slave_queue {
53+
struct list_head all_slaves;
54+
};
55+
56+
struct net_vrf {
57+
struct slave_queue queue;
58+
struct rtable *rth;
59+
u32 tb_id;
60+
};
61+
4762
struct pcpu_dstats {
4863
u64 tx_pkts;
4964
u64 tx_bytes;
@@ -395,18 +410,15 @@ static void __vrf_insert_slave(struct slave_queue *queue, struct slave *slave)
395410

396411
static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
397412
{
398-
struct net_vrf_dev *vrf_ptr = kmalloc(sizeof(*vrf_ptr), GFP_KERNEL);
399413
struct slave *slave = kzalloc(sizeof(*slave), GFP_KERNEL);
400414
struct net_vrf *vrf = netdev_priv(dev);
401415
struct slave_queue *queue = &vrf->queue;
402416
int ret = -ENOMEM;
403417

404-
if (!slave || !vrf_ptr)
418+
if (!slave)
405419
goto out_fail;
406420

407421
slave->dev = port_dev;
408-
vrf_ptr->ifindex = dev->ifindex;
409-
vrf_ptr->tb_id = vrf->tb_id;
410422

411423
/* register the packet handler for slave ports */
412424
ret = netdev_rx_handler_register(port_dev, vrf_handle_frame, dev);
@@ -423,22 +435,20 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
423435

424436
port_dev->flags |= IFF_SLAVE;
425437
__vrf_insert_slave(queue, slave);
426-
rcu_assign_pointer(port_dev->vrf_ptr, vrf_ptr);
427438
cycle_netdev(port_dev);
428439

429440
return 0;
430441

431442
out_unregister:
432443
netdev_rx_handler_unregister(port_dev);
433444
out_fail:
434-
kfree(vrf_ptr);
435445
kfree(slave);
436446
return ret;
437447
}
438448

439449
static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
440450
{
441-
if (netif_is_vrf(port_dev) || vrf_is_slave(port_dev))
451+
if (netif_is_l3_master(port_dev) || vrf_is_slave(port_dev))
442452
return -EINVAL;
443453

444454
return do_vrf_add_slave(dev, port_dev);
@@ -447,21 +457,15 @@ static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
447457
/* inverse of do_vrf_add_slave */
448458
static int do_vrf_del_slave(struct net_device *dev, struct net_device *port_dev)
449459
{
450-
struct net_vrf_dev *vrf_ptr = rtnl_dereference(port_dev->vrf_ptr);
451460
struct net_vrf *vrf = netdev_priv(dev);
452461
struct slave_queue *queue = &vrf->queue;
453462
struct slave *slave;
454463

455-
RCU_INIT_POINTER(port_dev->vrf_ptr, NULL);
456-
457464
netdev_upper_dev_unlink(port_dev, dev);
458465
port_dev->flags &= ~IFF_SLAVE;
459466

460467
netdev_rx_handler_unregister(port_dev);
461468

462-
/* after netdev_rx_handler_unregister for synchronize_rcu */
463-
kfree(vrf_ptr);
464-
465469
cycle_netdev(port_dev);
466470

467471
slave = __vrf_find_slave_dev(queue, port_dev);
@@ -529,6 +533,33 @@ static const struct net_device_ops vrf_netdev_ops = {
529533
.ndo_del_slave = vrf_del_slave,
530534
};
531535

536+
static u32 vrf_fib_table(const struct net_device *dev)
537+
{
538+
struct net_vrf *vrf = netdev_priv(dev);
539+
540+
return vrf->tb_id;
541+
}
542+
543+
static struct rtable *vrf_get_rtable(const struct net_device *dev,
544+
const struct flowi4 *fl4)
545+
{
546+
struct rtable *rth = NULL;
547+
548+
if (!(fl4->flowi4_flags & FLOWI_FLAG_VRFSRC)) {
549+
struct net_vrf *vrf = netdev_priv(dev);
550+
551+
rth = vrf->rth;
552+
atomic_inc(&rth->dst.__refcnt);
553+
}
554+
555+
return rth;
556+
}
557+
558+
static const struct l3mdev_ops vrf_l3mdev_ops = {
559+
.l3mdev_fib_table = vrf_fib_table,
560+
.l3mdev_get_rtable = vrf_get_rtable,
561+
};
562+
532563
static void vrf_get_drvinfo(struct net_device *dev,
533564
struct ethtool_drvinfo *info)
534565
{
@@ -546,6 +577,7 @@ static void vrf_setup(struct net_device *dev)
546577

547578
/* Initialize the device structure. */
548579
dev->netdev_ops = &vrf_netdev_ops;
580+
dev->l3mdev_ops = &vrf_l3mdev_ops;
549581
dev->ethtool_ops = &vrf_ethtool_ops;
550582
dev->destructor = free_netdev;
551583

@@ -572,45 +604,29 @@ static int vrf_validate(struct nlattr *tb[], struct nlattr *data[])
572604

573605
static void vrf_dellink(struct net_device *dev, struct list_head *head)
574606
{
575-
struct net_vrf_dev *vrf_ptr = rtnl_dereference(dev->vrf_ptr);
576-
577-
RCU_INIT_POINTER(dev->vrf_ptr, NULL);
578-
kfree_rcu(vrf_ptr, rcu);
579607
unregister_netdevice_queue(dev, head);
580608
}
581609

582610
static int vrf_newlink(struct net *src_net, struct net_device *dev,
583611
struct nlattr *tb[], struct nlattr *data[])
584612
{
585613
struct net_vrf *vrf = netdev_priv(dev);
586-
struct net_vrf_dev *vrf_ptr;
587614
int err;
588615

589616
if (!data || !data[IFLA_VRF_TABLE])
590617
return -EINVAL;
591618

592619
vrf->tb_id = nla_get_u32(data[IFLA_VRF_TABLE]);
593620

594-
dev->priv_flags |= IFF_VRF_MASTER;
595-
596-
err = -ENOMEM;
597-
vrf_ptr = kmalloc(sizeof(*dev->vrf_ptr), GFP_KERNEL);
598-
if (!vrf_ptr)
599-
goto out_fail;
600-
601-
vrf_ptr->ifindex = dev->ifindex;
602-
vrf_ptr->tb_id = vrf->tb_id;
621+
dev->priv_flags |= IFF_L3MDEV_MASTER;
603622

604623
err = register_netdevice(dev);
605624
if (err < 0)
606625
goto out_fail;
607626

608-
rcu_assign_pointer(dev->vrf_ptr, vrf_ptr);
609-
610627
return 0;
611628

612629
out_fail:
613-
kfree(vrf_ptr);
614630
free_netdev(dev);
615631
return err;
616632
}
@@ -654,10 +670,9 @@ static int vrf_device_event(struct notifier_block *unused,
654670

655671
/* only care about unregister events to drop slave references */
656672
if (event == NETDEV_UNREGISTER) {
657-
struct net_vrf_dev *vrf_ptr = rtnl_dereference(dev->vrf_ptr);
658673
struct net_device *vrf_dev;
659674

660-
if (!vrf_ptr || netif_is_vrf(dev))
675+
if (netif_is_l3_master(dev))
661676
goto out;
662677

663678
vrf_dev = netdev_master_upper_dev_get(dev);

include/linux/netdevice.h

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ struct net_device_ops {
12581258
* @IFF_LIVE_ADDR_CHANGE: device supports hardware address
12591259
* change when it's running
12601260
* @IFF_MACVLAN: Macvlan device
1261-
* @IFF_VRF_MASTER: device is a VRF master
1261+
* @IFF_L3MDEV_MASTER: device is an L3 master device
12621262
* @IFF_NO_QUEUE: device can run without qdisc attached
12631263
* @IFF_OPENVSWITCH: device is a Open vSwitch master
12641264
*/
@@ -1283,7 +1283,7 @@ enum netdev_priv_flags {
12831283
IFF_XMIT_DST_RELEASE_PERM = 1<<17,
12841284
IFF_IPVLAN_MASTER = 1<<18,
12851285
IFF_IPVLAN_SLAVE = 1<<19,
1286-
IFF_VRF_MASTER = 1<<20,
1286+
IFF_L3MDEV_MASTER = 1<<20,
12871287
IFF_NO_QUEUE = 1<<21,
12881288
IFF_OPENVSWITCH = 1<<22,
12891289
};
@@ -1308,7 +1308,7 @@ enum netdev_priv_flags {
13081308
#define IFF_XMIT_DST_RELEASE_PERM IFF_XMIT_DST_RELEASE_PERM
13091309
#define IFF_IPVLAN_MASTER IFF_IPVLAN_MASTER
13101310
#define IFF_IPVLAN_SLAVE IFF_IPVLAN_SLAVE
1311-
#define IFF_VRF_MASTER IFF_VRF_MASTER
1311+
#define IFF_L3MDEV_MASTER IFF_L3MDEV_MASTER
13121312
#define IFF_NO_QUEUE IFF_NO_QUEUE
13131313
#define IFF_OPENVSWITCH IFF_OPENVSWITCH
13141314

@@ -1427,7 +1427,6 @@ enum netdev_priv_flags {
14271427
* @dn_ptr: DECnet specific data
14281428
* @ip6_ptr: IPv6 specific data
14291429
* @ax25_ptr: AX.25 specific data
1430-
* @vrf_ptr: VRF specific data
14311430
* @ieee80211_ptr: IEEE 802.11 specific data, assign before registering
14321431
*
14331432
* @last_rx: Time of last Rx
@@ -1587,6 +1586,9 @@ struct net_device {
15871586
#ifdef CONFIG_NET_SWITCHDEV
15881587
const struct switchdev_ops *switchdev_ops;
15891588
#endif
1589+
#ifdef CONFIG_NET_L3_MASTER_DEV
1590+
const struct l3mdev_ops *l3mdev_ops;
1591+
#endif
15901592

15911593
const struct header_ops *header_ops;
15921594

@@ -1646,7 +1648,6 @@ struct net_device {
16461648
struct dn_dev __rcu *dn_ptr;
16471649
struct inet6_dev __rcu *ip6_ptr;
16481650
void *ax25_ptr;
1649-
struct net_vrf_dev __rcu *vrf_ptr;
16501651
struct wireless_dev *ieee80211_ptr;
16511652
struct wpan_dev *ieee802154_ptr;
16521653
#if IS_ENABLED(CONFIG_MPLS_ROUTING)
@@ -3824,9 +3825,9 @@ static inline bool netif_supports_nofcs(struct net_device *dev)
38243825
return dev->priv_flags & IFF_SUPP_NOFCS;
38253826
}
38263827

3827-
static inline bool netif_is_vrf(const struct net_device *dev)
3828+
static inline bool netif_is_l3_master(const struct net_device *dev)
38283829
{
3829-
return dev->priv_flags & IFF_VRF_MASTER;
3830+
return dev->priv_flags & IFF_L3MDEV_MASTER;
38303831
}
38313832

38323833
static inline bool netif_is_bridge_master(const struct net_device *dev)
@@ -3839,27 +3840,6 @@ static inline bool netif_is_ovs_master(const struct net_device *dev)
38393840
return dev->priv_flags & IFF_OPENVSWITCH;
38403841
}
38413842

3842-
static inline bool netif_index_is_vrf(struct net *net, int ifindex)
3843-
{
3844-
bool rc = false;
3845-
3846-
#if IS_ENABLED(CONFIG_NET_VRF)
3847-
struct net_device *dev;
3848-
3849-
if (ifindex == 0)
3850-
return false;
3851-
3852-
rcu_read_lock();
3853-
3854-
dev = dev_get_by_index_rcu(net, ifindex);
3855-
if (dev)
3856-
rc = netif_is_vrf(dev);
3857-
3858-
rcu_read_unlock();
3859-
#endif
3860-
return rc;
3861-
}
3862-
38633843
/* This device needs to keep skb dst for qdisc enqueue or ndo_start_xmit() */
38643844
static inline void netif_keep_dst(struct net_device *dev)
38653845
{

0 commit comments

Comments
 (0)