File Index
Files and directories
Sign in
FILE

l3mdev.h

File preview with syntax highlighting.

linux-6.19.14/include/net/l3mdev.h C
  1/* SPDX-License-Identifier: GPL-2.0-or-later */
  2/*
  3 * include/net/l3mdev.h - L3 master device API
  4 * Copyright (c) 2015 Cumulus Networks
  5 * Copyright (c) 2015 David Ahern <dsa@cumulusnetworks.com>
  6 */
  7#ifndef _NET_L3MDEV_H_
  8#define _NET_L3MDEV_H_
  9
 10#include <net/dst.h>
 11#include <net/fib_rules.h>
 12
 13enum l3mdev_type {
 14	L3MDEV_TYPE_UNSPEC,
 15	L3MDEV_TYPE_VRF,
 16	__L3MDEV_TYPE_MAX
 17};
 18
 19#define L3MDEV_TYPE_MAX (__L3MDEV_TYPE_MAX - 1)
 20
 21typedef int (*lookup_by_table_id_t)(struct net *net, u32 table_d);
 22
 23/**
 24 * struct l3mdev_ops - l3mdev operations
 25 *
 26 * @l3mdev_fib_table: Get FIB table id to use for lookups
 27 *
 28 * @l3mdev_l3_rcv:    Hook in L3 receive path
 29 *
 30 * @l3mdev_l3_out:    Hook in L3 output path
 31 *
 32 * @l3mdev_link_scope_lookup: IPv6 lookup for linklocal and mcast destinations
 33 */
 34
 35struct l3mdev_ops {
 36	u32		(*l3mdev_fib_table)(const struct net_device *dev);
 37	struct sk_buff * (*l3mdev_l3_rcv)(struct net_device *dev,
 38					  struct sk_buff *skb, u16 proto);
 39	struct sk_buff * (*l3mdev_l3_out)(struct net_device *dev,
 40					  struct sock *sk, struct sk_buff *skb,
 41					  u16 proto);
 42
 43	/* IPv6 ops */
 44	struct dst_entry * (*l3mdev_link_scope_lookup)(const struct net_device *dev,
 45						 struct flowi6 *fl6);
 46};
 47
 48#ifdef CONFIG_NET_L3_MASTER_DEV
 49
 50int l3mdev_table_lookup_register(enum l3mdev_type l3type,
 51				 lookup_by_table_id_t fn);
 52
 53void l3mdev_table_lookup_unregister(enum l3mdev_type l3type,
 54				    lookup_by_table_id_t fn);
 55
 56int l3mdev_ifindex_lookup_by_table_id(enum l3mdev_type l3type, struct net *net,
 57				      u32 table_id);
 58
 59int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
 60			  struct fib_lookup_arg *arg);
 61
 62static inline
 63bool l3mdev_fib_rule_iif_match(const struct flowi *fl, int iifindex)
 64{
 65	return !(fl->flowi_flags & FLOWI_FLAG_L3MDEV_OIF) &&
 66	       fl->flowi_l3mdev == iifindex;
 67}
 68
 69static inline
 70bool l3mdev_fib_rule_oif_match(const struct flowi *fl, int oifindex)
 71{
 72	return fl->flowi_flags & FLOWI_FLAG_L3MDEV_OIF &&
 73	       fl->flowi_l3mdev == oifindex;
 74}
 75
 76void l3mdev_update_flow(struct net *net, struct flowi *fl);
 77
 78int l3mdev_master_ifindex_rcu(const struct net_device *dev);
 79static inline int l3mdev_master_ifindex(struct net_device *dev)
 80{
 81	int ifindex;
 82
 83	rcu_read_lock();
 84	ifindex = l3mdev_master_ifindex_rcu(dev);
 85	rcu_read_unlock();
 86
 87	return ifindex;
 88}
 89
 90static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
 91{
 92	struct net_device *dev;
 93	int rc = 0;
 94
 95	if (ifindex) {
 96		rcu_read_lock();
 97
 98		dev = dev_get_by_index_rcu(net, ifindex);
 99		if (dev)
100			rc = l3mdev_master_ifindex_rcu(dev);
101
102		rcu_read_unlock();
103	}
104
105	return rc;
106}
107
108static inline
109struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
110{
111	/* netdev_master_upper_dev_get_rcu calls
112	 * list_first_or_null_rcu to walk the upper dev list.
113	 * list_first_or_null_rcu does not handle a const arg. We aren't
114	 * making changes, just want the master device from that list so
115	 * typecast to remove the const
116	 */
117	struct net_device *dev = (struct net_device *)_dev;
118	struct net_device *master;
119
120	if (!dev)
121		return NULL;
122
123	if (netif_is_l3_master(dev))
124		master = dev;
125	else if (netif_is_l3_slave(dev))
126		master = netdev_master_upper_dev_get_rcu(dev);
127	else
128		master = NULL;
129
130	return master;
131}
132
133int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex);
134static inline
135int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
136{
137	rcu_read_lock();
138	ifindex = l3mdev_master_upper_ifindex_by_index_rcu(net, ifindex);
139	rcu_read_unlock();
140
141	return ifindex;
142}
143
144u32 l3mdev_fib_table_rcu(const struct net_device *dev);
145u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
146static inline u32 l3mdev_fib_table(const struct net_device *dev)
147{
148	u32 tb_id;
149
150	rcu_read_lock();
151	tb_id = l3mdev_fib_table_rcu(dev);
152	rcu_read_unlock();
153
154	return tb_id;
155}
156
157static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
158{
159	struct net_device *dev;
160	bool rc = false;
161
162	if (ifindex == 0)
163		return false;
164
165	rcu_read_lock();
166
167	dev = dev_get_by_index_rcu(net, ifindex);
168	if (dev)
169		rc = netif_is_l3_master(dev);
170
171	rcu_read_unlock();
172
173	return rc;
174}
175
176struct dst_entry *l3mdev_link_scope_lookup(struct net *net, struct flowi6 *fl6);
177
178static inline
179struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
180{
181	struct net_device *master = NULL;
182
183	if (netif_is_l3_slave(skb->dev))
184		master = netdev_master_upper_dev_get_rcu(skb->dev);
185	else if (netif_is_l3_master(skb->dev) ||
186		 netif_has_l3_rx_handler(skb->dev))
187		master = skb->dev;
188
189	if (master && master->l3mdev_ops->l3mdev_l3_rcv)
190		skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto);
191
192	return skb;
193}
194
195static inline
196struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
197{
198	return l3mdev_l3_rcv(skb, AF_INET);
199}
200
201static inline
202struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
203{
204	return l3mdev_l3_rcv(skb, AF_INET6);
205}
206
207static inline
208struct sk_buff *l3mdev_l3_out(struct sock *sk, struct sk_buff *skb, u16 proto)
209{
210	struct net_device *dev = skb_dst(skb)->dev;
211
212	if (netif_is_l3_slave(dev)) {
213		struct net_device *master;
214
215		rcu_read_lock();
216		master = netdev_master_upper_dev_get_rcu(dev);
217		if (master && master->l3mdev_ops->l3mdev_l3_out)
218			skb = master->l3mdev_ops->l3mdev_l3_out(master, sk,
219								skb, proto);
220		rcu_read_unlock();
221	}
222
223	return skb;
224}
225
226static inline
227struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb)
228{
229	return l3mdev_l3_out(sk, skb, AF_INET);
230}
231
232static inline
233struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb)
234{
235	return l3mdev_l3_out(sk, skb, AF_INET6);
236}
237#else
238
239static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev)
240{
241	return 0;
242}
243static inline int l3mdev_master_ifindex(struct net_device *dev)
244{
245	return 0;
246}
247
248static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
249{
250	return 0;
251}
252
253static inline
254int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
255{
256	return 0;
257}
258static inline
259int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
260{
261	return 0;
262}
263
264static inline
265struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev)
266{
267	return NULL;
268}
269
270static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev)
271{
272	return 0;
273}
274static inline u32 l3mdev_fib_table(const struct net_device *dev)
275{
276	return 0;
277}
278static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
279{
280	return 0;
281}
282
283static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
284{
285	return false;
286}
287
288static inline
289struct dst_entry *l3mdev_link_scope_lookup(struct net *net, struct flowi6 *fl6)
290{
291	return NULL;
292}
293
294static inline
295struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
296{
297	return skb;
298}
299
300static inline
301struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
302{
303	return skb;
304}
305
306static inline
307struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb)
308{
309	return skb;
310}
311
312static inline
313struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb)
314{
315	return skb;
316}
317
318static inline
319int l3mdev_table_lookup_register(enum l3mdev_type l3type,
320				 lookup_by_table_id_t fn)
321{
322	return -EOPNOTSUPP;
323}
324
325static inline
326void l3mdev_table_lookup_unregister(enum l3mdev_type l3type,
327				    lookup_by_table_id_t fn)
328{
329}
330
331static inline
332int l3mdev_ifindex_lookup_by_table_id(enum l3mdev_type l3type, struct net *net,
333				      u32 table_id)
334{
335	return -ENODEV;
336}
337
338static inline
339int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
340			  struct fib_lookup_arg *arg)
341{
342	return 1;
343}
344
345static inline
346bool l3mdev_fib_rule_iif_match(const struct flowi *fl, int iifindex)
347{
348	return false;
349}
350
351static inline
352bool l3mdev_fib_rule_oif_match(const struct flowi *fl, int oifindex)
353{
354	return false;
355}
356
357static inline
358void l3mdev_update_flow(struct net *net, struct flowi *fl)
359{
360}
361#endif
362
363#endif /* _NET_L3MDEV_H_ */
~/ Read-only file preview.