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 #include <net/fib_rules.h> 15 16 /** 17 * struct l3mdev_ops - l3mdev operations 18 * 19 * @l3mdev_fib_table: Get FIB table id to use for lookups 20 * 21 * @l3mdev_get_rtable: Get cached IPv4 rtable (dst_entry) for device 22 * 23 * @l3mdev_get_saddr: Get source address for a flow 24 * 25 * @l3mdev_get_rt6_dst: Get cached IPv6 rt6_info (dst_entry) for device 26 */ 27 28 struct l3mdev_ops { 29 u32 (*l3mdev_fib_table)(const struct net_device *dev); 30 struct sk_buff * (*l3mdev_l3_rcv)(struct net_device *dev, 31 struct sk_buff *skb, u16 proto); 32 33 /* IPv4 ops */ 34 struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev, 35 const struct flowi4 *fl4); 36 int (*l3mdev_get_saddr)(struct net_device *dev, 37 struct flowi4 *fl4); 38 39 /* IPv6 ops */ 40 struct dst_entry * (*l3mdev_get_rt6_dst)(const struct net_device *dev, 41 struct flowi6 *fl6); 42 }; 43 44 #ifdef CONFIG_NET_L3_MASTER_DEV 45 46 int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, 47 struct fib_lookup_arg *arg); 48 49 int l3mdev_master_ifindex_rcu(const struct net_device *dev); 50 static inline int l3mdev_master_ifindex(struct net_device *dev) 51 { 52 int ifindex; 53 54 rcu_read_lock(); 55 ifindex = l3mdev_master_ifindex_rcu(dev); 56 rcu_read_unlock(); 57 58 return ifindex; 59 } 60 61 static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 62 { 63 struct net_device *dev; 64 int rc = 0; 65 66 if (likely(ifindex)) { 67 rcu_read_lock(); 68 69 dev = dev_get_by_index_rcu(net, ifindex); 70 if (dev) 71 rc = l3mdev_master_ifindex_rcu(dev); 72 73 rcu_read_unlock(); 74 } 75 76 return rc; 77 } 78 79 /* get index of an interface to use for FIB lookups. For devices 80 * enslaved to an L3 master device FIB lookups are based on the 81 * master index 82 */ 83 static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 84 { 85 return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex; 86 } 87 88 static inline int l3mdev_fib_oif(struct net_device *dev) 89 { 90 int oif; 91 92 rcu_read_lock(); 93 oif = l3mdev_fib_oif_rcu(dev); 94 rcu_read_unlock(); 95 96 return oif; 97 } 98 99 u32 l3mdev_fib_table_rcu(const struct net_device *dev); 100 u32 l3mdev_fib_table_by_index(struct net *net, int ifindex); 101 static inline u32 l3mdev_fib_table(const struct net_device *dev) 102 { 103 u32 tb_id; 104 105 rcu_read_lock(); 106 tb_id = l3mdev_fib_table_rcu(dev); 107 rcu_read_unlock(); 108 109 return tb_id; 110 } 111 112 static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 113 const struct flowi4 *fl4) 114 { 115 if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rtable) 116 return dev->l3mdev_ops->l3mdev_get_rtable(dev, fl4); 117 118 return NULL; 119 } 120 121 static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 122 { 123 struct net_device *dev; 124 bool rc = false; 125 126 if (ifindex == 0) 127 return false; 128 129 rcu_read_lock(); 130 131 dev = dev_get_by_index_rcu(net, ifindex); 132 if (dev) 133 rc = netif_is_l3_master(dev); 134 135 rcu_read_unlock(); 136 137 return rc; 138 } 139 140 int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4); 141 142 struct dst_entry *l3mdev_get_rt6_dst(struct net *net, struct flowi6 *fl6); 143 144 static inline 145 struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto) 146 { 147 struct net_device *master = NULL; 148 149 if (netif_is_l3_slave(skb->dev)) 150 master = netdev_master_upper_dev_get_rcu(skb->dev); 151 else if (netif_is_l3_master(skb->dev)) 152 master = skb->dev; 153 154 if (master && master->l3mdev_ops->l3mdev_l3_rcv) 155 skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto); 156 157 return skb; 158 } 159 160 static inline 161 struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb) 162 { 163 return l3mdev_l3_rcv(skb, AF_INET); 164 } 165 166 static inline 167 struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb) 168 { 169 return l3mdev_l3_rcv(skb, AF_INET6); 170 } 171 172 #else 173 174 static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev) 175 { 176 return 0; 177 } 178 static inline int l3mdev_master_ifindex(struct net_device *dev) 179 { 180 return 0; 181 } 182 183 static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex) 184 { 185 return 0; 186 } 187 188 static inline int l3mdev_fib_oif_rcu(struct net_device *dev) 189 { 190 return dev ? dev->ifindex : 0; 191 } 192 static inline int l3mdev_fib_oif(struct net_device *dev) 193 { 194 return dev ? dev->ifindex : 0; 195 } 196 197 static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev) 198 { 199 return 0; 200 } 201 static inline u32 l3mdev_fib_table(const struct net_device *dev) 202 { 203 return 0; 204 } 205 static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex) 206 { 207 return 0; 208 } 209 210 static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev, 211 const struct flowi4 *fl4) 212 { 213 return NULL; 214 } 215 216 static inline bool netif_index_is_l3_master(struct net *net, int ifindex) 217 { 218 return false; 219 } 220 221 static inline int l3mdev_get_saddr(struct net *net, int ifindex, 222 struct flowi4 *fl4) 223 { 224 return 0; 225 } 226 227 static inline 228 struct dst_entry *l3mdev_get_rt6_dst(struct net *net, struct flowi6 *fl6) 229 { 230 return NULL; 231 } 232 233 static inline 234 struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb) 235 { 236 return skb; 237 } 238 239 static inline 240 struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb) 241 { 242 return skb; 243 } 244 245 static inline 246 int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, 247 struct fib_lookup_arg *arg) 248 { 249 return 1; 250 } 251 #endif 252 253 #endif /* _NET_L3MDEV_H_ */ 254