1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * include/net/l3mdev.h - L3 master device API
4 * Copyright (c) 2015 Cumulus Networks
5 * Copyright (c) 2015 David Ahern <dsa@cumulusnetworks.com>
11 #include <net/fib_rules.h>
19 #define L3MDEV_TYPE_MAX (__L3MDEV_TYPE_MAX - 1)
21 typedef int (*lookup_by_table_id_t
)(struct net
*net
, u32 table_d
);
24 * struct l3mdev_ops - l3mdev operations
26 * @l3mdev_fib_table: Get FIB table id to use for lookups
28 * @l3mdev_l3_rcv: Hook in L3 receive path
30 * @l3mdev_l3_out: Hook in L3 output path
32 * @l3mdev_link_scope_lookup: IPv6 lookup for linklocal and mcast destinations
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
,
44 struct dst_entry
* (*l3mdev_link_scope_lookup
)(const struct net_device
*dev
,
48 #ifdef CONFIG_NET_L3_MASTER_DEV
50 int l3mdev_table_lookup_register(enum l3mdev_type l3type
,
51 lookup_by_table_id_t fn
);
53 void l3mdev_table_lookup_unregister(enum l3mdev_type l3type
,
54 lookup_by_table_id_t fn
);
56 int l3mdev_ifindex_lookup_by_table_id(enum l3mdev_type l3type
, struct net
*net
,
59 int l3mdev_fib_rule_match(struct net
*net
, struct flowi
*fl
,
60 struct fib_lookup_arg
*arg
);
62 void l3mdev_update_flow(struct net
*net
, struct flowi
*fl
);
64 int l3mdev_master_ifindex_rcu(const struct net_device
*dev
);
65 static inline int l3mdev_master_ifindex(struct net_device
*dev
)
70 ifindex
= l3mdev_master_ifindex_rcu(dev
);
76 static inline int l3mdev_master_ifindex_by_index(struct net
*net
, int ifindex
)
78 struct net_device
*dev
;
84 dev
= dev_get_by_index_rcu(net
, ifindex
);
86 rc
= l3mdev_master_ifindex_rcu(dev
);
95 struct net_device
*l3mdev_master_dev_rcu(const struct net_device
*_dev
)
97 /* netdev_master_upper_dev_get_rcu calls
98 * list_first_or_null_rcu to walk the upper dev list.
99 * list_first_or_null_rcu does not handle a const arg. We aren't
100 * making changes, just want the master device from that list so
101 * typecast to remove the const
103 struct net_device
*dev
= (struct net_device
*)_dev
;
104 struct net_device
*master
;
109 if (netif_is_l3_master(dev
))
111 else if (netif_is_l3_slave(dev
))
112 master
= netdev_master_upper_dev_get_rcu(dev
);
119 int l3mdev_master_upper_ifindex_by_index_rcu(struct net
*net
, int ifindex
);
121 int l3mdev_master_upper_ifindex_by_index(struct net
*net
, int ifindex
)
124 ifindex
= l3mdev_master_upper_ifindex_by_index_rcu(net
, ifindex
);
130 u32
l3mdev_fib_table_rcu(const struct net_device
*dev
);
131 u32
l3mdev_fib_table_by_index(struct net
*net
, int ifindex
);
132 static inline u32
l3mdev_fib_table(const struct net_device
*dev
)
137 tb_id
= l3mdev_fib_table_rcu(dev
);
143 static inline bool netif_index_is_l3_master(struct net
*net
, int ifindex
)
145 struct net_device
*dev
;
153 dev
= dev_get_by_index_rcu(net
, ifindex
);
155 rc
= netif_is_l3_master(dev
);
162 struct dst_entry
*l3mdev_link_scope_lookup(struct net
*net
, struct flowi6
*fl6
);
165 struct sk_buff
*l3mdev_l3_rcv(struct sk_buff
*skb
, u16 proto
)
167 struct net_device
*master
= NULL
;
169 if (netif_is_l3_slave(skb
->dev
))
170 master
= netdev_master_upper_dev_get_rcu(skb
->dev
);
171 else if (netif_is_l3_master(skb
->dev
) ||
172 netif_has_l3_rx_handler(skb
->dev
))
175 if (master
&& master
->l3mdev_ops
->l3mdev_l3_rcv
)
176 skb
= master
->l3mdev_ops
->l3mdev_l3_rcv(master
, skb
, proto
);
182 struct sk_buff
*l3mdev_ip_rcv(struct sk_buff
*skb
)
184 return l3mdev_l3_rcv(skb
, AF_INET
);
188 struct sk_buff
*l3mdev_ip6_rcv(struct sk_buff
*skb
)
190 return l3mdev_l3_rcv(skb
, AF_INET6
);
194 struct sk_buff
*l3mdev_l3_out(struct sock
*sk
, struct sk_buff
*skb
, u16 proto
)
196 struct net_device
*dev
= skb_dst(skb
)->dev
;
198 if (netif_is_l3_slave(dev
)) {
199 struct net_device
*master
;
201 master
= netdev_master_upper_dev_get_rcu(dev
);
202 if (master
&& master
->l3mdev_ops
->l3mdev_l3_out
)
203 skb
= master
->l3mdev_ops
->l3mdev_l3_out(master
, sk
,
211 struct sk_buff
*l3mdev_ip_out(struct sock
*sk
, struct sk_buff
*skb
)
213 return l3mdev_l3_out(sk
, skb
, AF_INET
);
217 struct sk_buff
*l3mdev_ip6_out(struct sock
*sk
, struct sk_buff
*skb
)
219 return l3mdev_l3_out(sk
, skb
, AF_INET6
);
223 static inline int l3mdev_master_ifindex_rcu(const struct net_device
*dev
)
227 static inline int l3mdev_master_ifindex(struct net_device
*dev
)
232 static inline int l3mdev_master_ifindex_by_index(struct net
*net
, int ifindex
)
238 int l3mdev_master_upper_ifindex_by_index_rcu(struct net
*net
, int ifindex
)
243 int l3mdev_master_upper_ifindex_by_index(struct net
*net
, int ifindex
)
249 struct net_device
*l3mdev_master_dev_rcu(const struct net_device
*dev
)
254 static inline u32
l3mdev_fib_table_rcu(const struct net_device
*dev
)
258 static inline u32
l3mdev_fib_table(const struct net_device
*dev
)
262 static inline u32
l3mdev_fib_table_by_index(struct net
*net
, int ifindex
)
267 static inline bool netif_index_is_l3_master(struct net
*net
, int ifindex
)
273 struct dst_entry
*l3mdev_link_scope_lookup(struct net
*net
, struct flowi6
*fl6
)
279 struct sk_buff
*l3mdev_ip_rcv(struct sk_buff
*skb
)
285 struct sk_buff
*l3mdev_ip6_rcv(struct sk_buff
*skb
)
291 struct sk_buff
*l3mdev_ip_out(struct sock
*sk
, struct sk_buff
*skb
)
297 struct sk_buff
*l3mdev_ip6_out(struct sock
*sk
, struct sk_buff
*skb
)
303 int l3mdev_table_lookup_register(enum l3mdev_type l3type
,
304 lookup_by_table_id_t fn
)
310 void l3mdev_table_lookup_unregister(enum l3mdev_type l3type
,
311 lookup_by_table_id_t fn
)
316 int l3mdev_ifindex_lookup_by_table_id(enum l3mdev_type l3type
, struct net
*net
,
323 int l3mdev_fib_rule_match(struct net
*net
, struct flowi
*fl
,
324 struct fib_lookup_arg
*arg
)
329 void l3mdev_update_flow(struct net
*net
, struct flowi
*fl
)
334 #endif /* _NET_L3MDEV_H_ */