Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * include/net/l3mdev.h - L3 master device API
0004  * Copyright (c) 2015 Cumulus Networks
0005  * Copyright (c) 2015 David Ahern <dsa@cumulusnetworks.com>
0006  */
0007 #ifndef _NET_L3MDEV_H_
0008 #define _NET_L3MDEV_H_
0009 
0010 #include <net/dst.h>
0011 #include <net/fib_rules.h>
0012 
0013 enum l3mdev_type {
0014     L3MDEV_TYPE_UNSPEC,
0015     L3MDEV_TYPE_VRF,
0016     __L3MDEV_TYPE_MAX
0017 };
0018 
0019 #define L3MDEV_TYPE_MAX (__L3MDEV_TYPE_MAX - 1)
0020 
0021 typedef int (*lookup_by_table_id_t)(struct net *net, u32 table_d);
0022 
0023 /**
0024  * struct l3mdev_ops - l3mdev operations
0025  *
0026  * @l3mdev_fib_table: Get FIB table id to use for lookups
0027  *
0028  * @l3mdev_l3_rcv:    Hook in L3 receive path
0029  *
0030  * @l3mdev_l3_out:    Hook in L3 output path
0031  *
0032  * @l3mdev_link_scope_lookup: IPv6 lookup for linklocal and mcast destinations
0033  */
0034 
0035 struct l3mdev_ops {
0036     u32     (*l3mdev_fib_table)(const struct net_device *dev);
0037     struct sk_buff * (*l3mdev_l3_rcv)(struct net_device *dev,
0038                       struct sk_buff *skb, u16 proto);
0039     struct sk_buff * (*l3mdev_l3_out)(struct net_device *dev,
0040                       struct sock *sk, struct sk_buff *skb,
0041                       u16 proto);
0042 
0043     /* IPv6 ops */
0044     struct dst_entry * (*l3mdev_link_scope_lookup)(const struct net_device *dev,
0045                          struct flowi6 *fl6);
0046 };
0047 
0048 #ifdef CONFIG_NET_L3_MASTER_DEV
0049 
0050 int l3mdev_table_lookup_register(enum l3mdev_type l3type,
0051                  lookup_by_table_id_t fn);
0052 
0053 void l3mdev_table_lookup_unregister(enum l3mdev_type l3type,
0054                     lookup_by_table_id_t fn);
0055 
0056 int l3mdev_ifindex_lookup_by_table_id(enum l3mdev_type l3type, struct net *net,
0057                       u32 table_id);
0058 
0059 int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
0060               struct fib_lookup_arg *arg);
0061 
0062 void l3mdev_update_flow(struct net *net, struct flowi *fl);
0063 
0064 int l3mdev_master_ifindex_rcu(const struct net_device *dev);
0065 static inline int l3mdev_master_ifindex(struct net_device *dev)
0066 {
0067     int ifindex;
0068 
0069     rcu_read_lock();
0070     ifindex = l3mdev_master_ifindex_rcu(dev);
0071     rcu_read_unlock();
0072 
0073     return ifindex;
0074 }
0075 
0076 static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
0077 {
0078     struct net_device *dev;
0079     int rc = 0;
0080 
0081     if (likely(ifindex)) {
0082         rcu_read_lock();
0083 
0084         dev = dev_get_by_index_rcu(net, ifindex);
0085         if (dev)
0086             rc = l3mdev_master_ifindex_rcu(dev);
0087 
0088         rcu_read_unlock();
0089     }
0090 
0091     return rc;
0092 }
0093 
0094 static inline
0095 struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
0096 {
0097     /* netdev_master_upper_dev_get_rcu calls
0098      * list_first_or_null_rcu to walk the upper dev list.
0099      * list_first_or_null_rcu does not handle a const arg. We aren't
0100      * making changes, just want the master device from that list so
0101      * typecast to remove the const
0102      */
0103     struct net_device *dev = (struct net_device *)_dev;
0104     struct net_device *master;
0105 
0106     if (!dev)
0107         return NULL;
0108 
0109     if (netif_is_l3_master(dev))
0110         master = dev;
0111     else if (netif_is_l3_slave(dev))
0112         master = netdev_master_upper_dev_get_rcu(dev);
0113     else
0114         master = NULL;
0115 
0116     return master;
0117 }
0118 
0119 int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex);
0120 static inline
0121 int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
0122 {
0123     rcu_read_lock();
0124     ifindex = l3mdev_master_upper_ifindex_by_index_rcu(net, ifindex);
0125     rcu_read_unlock();
0126 
0127     return ifindex;
0128 }
0129 
0130 u32 l3mdev_fib_table_rcu(const struct net_device *dev);
0131 u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
0132 static inline u32 l3mdev_fib_table(const struct net_device *dev)
0133 {
0134     u32 tb_id;
0135 
0136     rcu_read_lock();
0137     tb_id = l3mdev_fib_table_rcu(dev);
0138     rcu_read_unlock();
0139 
0140     return tb_id;
0141 }
0142 
0143 static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
0144 {
0145     struct net_device *dev;
0146     bool rc = false;
0147 
0148     if (ifindex == 0)
0149         return false;
0150 
0151     rcu_read_lock();
0152 
0153     dev = dev_get_by_index_rcu(net, ifindex);
0154     if (dev)
0155         rc = netif_is_l3_master(dev);
0156 
0157     rcu_read_unlock();
0158 
0159     return rc;
0160 }
0161 
0162 struct dst_entry *l3mdev_link_scope_lookup(struct net *net, struct flowi6 *fl6);
0163 
0164 static inline
0165 struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
0166 {
0167     struct net_device *master = NULL;
0168 
0169     if (netif_is_l3_slave(skb->dev))
0170         master = netdev_master_upper_dev_get_rcu(skb->dev);
0171     else if (netif_is_l3_master(skb->dev) ||
0172          netif_has_l3_rx_handler(skb->dev))
0173         master = skb->dev;
0174 
0175     if (master && master->l3mdev_ops->l3mdev_l3_rcv)
0176         skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto);
0177 
0178     return skb;
0179 }
0180 
0181 static inline
0182 struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
0183 {
0184     return l3mdev_l3_rcv(skb, AF_INET);
0185 }
0186 
0187 static inline
0188 struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
0189 {
0190     return l3mdev_l3_rcv(skb, AF_INET6);
0191 }
0192 
0193 static inline
0194 struct sk_buff *l3mdev_l3_out(struct sock *sk, struct sk_buff *skb, u16 proto)
0195 {
0196     struct net_device *dev = skb_dst(skb)->dev;
0197 
0198     if (netif_is_l3_slave(dev)) {
0199         struct net_device *master;
0200 
0201         master = netdev_master_upper_dev_get_rcu(dev);
0202         if (master && master->l3mdev_ops->l3mdev_l3_out)
0203             skb = master->l3mdev_ops->l3mdev_l3_out(master, sk,
0204                                 skb, proto);
0205     }
0206 
0207     return skb;
0208 }
0209 
0210 static inline
0211 struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb)
0212 {
0213     return l3mdev_l3_out(sk, skb, AF_INET);
0214 }
0215 
0216 static inline
0217 struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb)
0218 {
0219     return l3mdev_l3_out(sk, skb, AF_INET6);
0220 }
0221 #else
0222 
0223 static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev)
0224 {
0225     return 0;
0226 }
0227 static inline int l3mdev_master_ifindex(struct net_device *dev)
0228 {
0229     return 0;
0230 }
0231 
0232 static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
0233 {
0234     return 0;
0235 }
0236 
0237 static inline
0238 int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
0239 {
0240     return 0;
0241 }
0242 static inline
0243 int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
0244 {
0245     return 0;
0246 }
0247 
0248 static inline
0249 struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev)
0250 {
0251     return NULL;
0252 }
0253 
0254 static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev)
0255 {
0256     return 0;
0257 }
0258 static inline u32 l3mdev_fib_table(const struct net_device *dev)
0259 {
0260     return 0;
0261 }
0262 static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
0263 {
0264     return 0;
0265 }
0266 
0267 static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
0268 {
0269     return false;
0270 }
0271 
0272 static inline
0273 struct dst_entry *l3mdev_link_scope_lookup(struct net *net, struct flowi6 *fl6)
0274 {
0275     return NULL;
0276 }
0277 
0278 static inline
0279 struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
0280 {
0281     return skb;
0282 }
0283 
0284 static inline
0285 struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
0286 {
0287     return skb;
0288 }
0289 
0290 static inline
0291 struct sk_buff *l3mdev_ip_out(struct sock *sk, struct sk_buff *skb)
0292 {
0293     return skb;
0294 }
0295 
0296 static inline
0297 struct sk_buff *l3mdev_ip6_out(struct sock *sk, struct sk_buff *skb)
0298 {
0299     return skb;
0300 }
0301 
0302 static inline
0303 int l3mdev_table_lookup_register(enum l3mdev_type l3type,
0304                  lookup_by_table_id_t fn)
0305 {
0306     return -EOPNOTSUPP;
0307 }
0308 
0309 static inline
0310 void l3mdev_table_lookup_unregister(enum l3mdev_type l3type,
0311                     lookup_by_table_id_t fn)
0312 {
0313 }
0314 
0315 static inline
0316 int l3mdev_ifindex_lookup_by_table_id(enum l3mdev_type l3type, struct net *net,
0317                       u32 table_id)
0318 {
0319     return -ENODEV;
0320 }
0321 
0322 static inline
0323 int l3mdev_fib_rule_match(struct net *net, struct flowi *fl,
0324               struct fib_lookup_arg *arg)
0325 {
0326     return 1;
0327 }
0328 static inline
0329 void l3mdev_update_flow(struct net *net, struct flowi *fl)
0330 {
0331 }
0332 #endif
0333 
0334 #endif /* _NET_L3MDEV_H_ */