xref: /linux/include/net/l3mdev.h (revision fee6d4c777a125e56de9370db3b2bf359bf958d6)
1 /*
2  * include/net/l3mdev.h - L3 master device API
3  * Copyright (c) 2015 Cumulus Networks
4  * Copyright (c) 2015 David Ahern <dsa@cumulusnetworks.com>
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 static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
85 {
86 	struct net_device *dev;
87 	bool rc = false;
88 
89 	if (ifindex == 0)
90 		return false;
91 
92 	rcu_read_lock();
93 
94 	dev = dev_get_by_index_rcu(net, ifindex);
95 	if (dev)
96 		rc = netif_is_l3_master(dev);
97 
98 	rcu_read_unlock();
99 
100 	return rc;
101 }
102 
103 #else
104 
105 static inline int l3mdev_master_ifindex_rcu(struct net_device *dev)
106 {
107 	return 0;
108 }
109 static inline int l3mdev_master_ifindex(struct net_device *dev)
110 {
111 	return 0;
112 }
113 
114 static inline int l3mdev_fib_oif_rcu(struct net_device *dev)
115 {
116 	return dev ? dev->ifindex : 0;
117 }
118 static inline int l3mdev_fib_oif(struct net_device *dev)
119 {
120 	return dev ? dev->ifindex : 0;
121 }
122 
123 static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev)
124 {
125 	return 0;
126 }
127 static inline u32 l3mdev_fib_table(const struct net_device *dev)
128 {
129 	return 0;
130 }
131 static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
132 {
133 	return 0;
134 }
135 
136 static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev,
137 					       const struct flowi4 *fl4)
138 {
139 	return NULL;
140 }
141 
142 static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
143 {
144 	return false;
145 }
146 
147 #endif
148 
149 #endif /* _NET_L3MDEV_H_ */
150