at v5.3 6.3 kB view raw
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 13/** 14 * struct l3mdev_ops - l3mdev operations 15 * 16 * @l3mdev_fib_table: Get FIB table id to use for lookups 17 * 18 * @l3mdev_l3_rcv: Hook in L3 receive path 19 * 20 * @l3mdev_l3_out: Hook in L3 output path 21 * 22 * @l3mdev_link_scope_lookup: IPv6 lookup for linklocal and mcast destinations 23 */ 24 25struct l3mdev_ops { 26 u32 (*l3mdev_fib_table)(const struct net_device *dev); 27 struct sk_buff * (*l3mdev_l3_rcv)(struct net_device *dev, 28 struct sk_buff *skb, u16 proto); 29 struct sk_buff * (*l3mdev_l3_out)(struct net_device *dev, 30 struct sock *sk, struct sk_buff *skb, 31 u16 proto); 32 33 /* IPv6 ops */ 34 struct dst_entry * (*l3mdev_link_scope_lookup)(const struct net_device *dev, 35 struct flowi6 *fl6); 36}; 37 38#ifdef CONFIG_NET_L3_MASTER_DEV 39 40int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, 41 struct fib_lookup_arg *arg); 42 43void l3mdev_update_flow(struct net *net, struct flowi *fl); 44 45int l3mdev_master_ifindex_rcu(const struct net_device *dev); 46static inline int l3mdev_master_ifindex(struct net_device *dev) 47{ 48 int ifindex; 49 50 rcu_read_lock(); 51 ifindex = l3mdev_master_ifindex_rcu(dev); 52 rcu_read_unlock(); 53 54 return ifindex; 55} 56 57static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 58{ 59 struct net_device *dev; 60 int rc = 0; 61 62 if (likely(ifindex)) { 63 rcu_read_lock(); 64 65 dev = dev_get_by_index_rcu(net, ifindex); 66 if (dev) 67 rc = l3mdev_master_ifindex_rcu(dev); 68 69 rcu_read_unlock(); 70 } 71 72 return rc; 73} 74 75static inline 76struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev) 77{ 78 /* netdev_master_upper_dev_get_rcu calls 79 * list_first_or_null_rcu to walk the upper dev list. 80 * list_first_or_null_rcu does not handle a const arg. We aren't 81 * making changes, just want the master device from that list so 82 * typecast to remove the const 83 */ 84 struct net_device *dev = (struct net_device *)_dev; 85 struct net_device *master; 86 87 if (!dev) 88 return NULL; 89 90 if (netif_is_l3_master(dev)) 91 master = dev; 92 else if (netif_is_l3_slave(dev)) 93 master = netdev_master_upper_dev_get_rcu(dev); 94 else 95 master = NULL; 96 97 return master; 98} 99 100int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex); 101static inline 102int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex) 103{ 104 rcu_read_lock(); 105 ifindex = l3mdev_master_upper_ifindex_by_index_rcu(net, ifindex); 106 rcu_read_unlock(); 107 108 return ifindex; 109} 110 111u32 l3mdev_fib_table_rcu(const struct net_device *dev); 112u32 l3mdev_fib_table_by_index(struct net *net, int ifindex); 113static inline u32 l3mdev_fib_table(const struct net_device *dev) 114{ 115 u32 tb_id; 116 117 rcu_read_lock(); 118 tb_id = l3mdev_fib_table_rcu(dev); 119 rcu_read_unlock(); 120 121 return tb_id; 122} 123 124static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 125{ 126 struct net_device *dev; 127 bool rc = false; 128 129 if (ifindex == 0) 130 return false; 131 132 rcu_read_lock(); 133 134 dev = dev_get_by_index_rcu(net, ifindex); 135 if (dev) 136 rc = netif_is_l3_master(dev); 137 138 rcu_read_unlock(); 139 140 return rc; 141} 142 143struct dst_entry *l3mdev_link_scope_lookup(struct net *net, struct flowi6 *fl6); 144 145static inline 146struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto) 147{ 148 struct net_device *master = NULL; 149 150 if (netif_is_l3_slave(skb->dev)) 151 master = netdev_master_upper_dev_get_rcu(skb->dev); 152 else if (netif_is_l3_master(skb->dev) || 153 netif_has_l3_rx_handler(skb->dev)) 154 master = skb->dev; 155 156 if (master && master->l3mdev_ops->l3mdev_l3_rcv) 157 skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto); 158 159 return skb; 160} 161 162static inline 163struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb) 164{ 165 return l3mdev_l3_rcv(skb, AF_INET); 166} 167 168static inline 169struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb) 170{ 171 return l3mdev_l3_rcv(skb, AF_INET6); 172} 173 174static inline 175struct sk_buff *l3mdev_l3_out(struct sock *sk, struct sk_buff *skb, u16 proto) 176{ 177 struct net_device *dev = skb_dst(skb)->dev; 178 179 if (netif_is_l3_slave(dev)) { 180 struct net_device *master; 181 182 master = netdev_master_upper_dev_get_rcu(dev); 183 if (master && master->l3mdev_ops->l3mdev_l3_out) 184 skb = master->l3mdev_ops->l3mdev_l3_out(master, sk, 185 skb, proto); 186 } 187 188 return skb; 189} 190 191static inline 192struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb) 193{ 194 return l3mdev_l3_out(sk, skb, AF_INET); 195} 196 197static inline 198struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb) 199{ 200 return l3mdev_l3_out(sk, skb, AF_INET6); 201} 202#else 203 204static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev) 205{ 206 return 0; 207} 208static inline int l3mdev_master_ifindex(struct net_device *dev) 209{ 210 return 0; 211} 212 213static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 214{ 215 return 0; 216} 217 218static inline 219int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex) 220{ 221 return 0; 222} 223static inline 224int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex) 225{ 226 return 0; 227} 228 229static inline 230struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev) 231{ 232 return NULL; 233} 234 235static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev) 236{ 237 return 0; 238} 239static inline u32 l3mdev_fib_table(const struct net_device *dev) 240{ 241 return 0; 242} 243static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) 244{ 245 return 0; 246} 247 248static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 249{ 250 return false; 251} 252 253static inline 254struct dst_entry *l3mdev_link_scope_lookup(struct net *net, struct flowi6 *fl6) 255{ 256 return NULL; 257} 258 259static inline 260struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb) 261{ 262 return skb; 263} 264 265static inline 266struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb) 267{ 268 return skb; 269} 270 271static inline 272struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb) 273{ 274 return skb; 275} 276 277static inline 278struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb) 279{ 280 return skb; 281} 282 283static inline 284int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, 285 struct fib_lookup_arg *arg) 286{ 287 return 1; 288} 289static inline 290void l3mdev_update_flow(struct net *net, struct flowi *fl) 291{ 292} 293#endif 294 295#endif /* _NET_L3MDEV_H_ */