l3mdev.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. * struct l3mdev_ops - l3mdev operations
  15. *
  16. * @l3mdev_fib_table: Get FIB table id to use for lookups
  17. *
  18. * @l3mdev_get_rtable: Get cached IPv4 rtable (dst_entry) for device
  19. *
  20. * @l3mdev_get_saddr: Get source address for a flow
  21. *
  22. * @l3mdev_get_rt6_dst: Get cached IPv6 rt6_info (dst_entry) for device
  23. */
  24. struct l3mdev_ops {
  25. u32 (*l3mdev_fib_table)(const struct net_device *dev);
  26. /* IPv4 ops */
  27. struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev,
  28. const struct flowi4 *fl4);
  29. int (*l3mdev_get_saddr)(struct net_device *dev,
  30. struct flowi4 *fl4);
  31. /* IPv6 ops */
  32. struct dst_entry * (*l3mdev_get_rt6_dst)(const struct net_device *dev,
  33. const struct flowi6 *fl6);
  34. };
  35. #ifdef CONFIG_NET_L3_MASTER_DEV
  36. int l3mdev_master_ifindex_rcu(const struct net_device *dev);
  37. static inline int l3mdev_master_ifindex(struct net_device *dev)
  38. {
  39. int ifindex;
  40. rcu_read_lock();
  41. ifindex = l3mdev_master_ifindex_rcu(dev);
  42. rcu_read_unlock();
  43. return ifindex;
  44. }
  45. static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
  46. {
  47. struct net_device *dev;
  48. int rc = 0;
  49. if (likely(ifindex)) {
  50. rcu_read_lock();
  51. dev = dev_get_by_index_rcu(net, ifindex);
  52. if (dev)
  53. rc = l3mdev_master_ifindex_rcu(dev);
  54. rcu_read_unlock();
  55. }
  56. return rc;
  57. }
  58. /* get index of an interface to use for FIB lookups. For devices
  59. * enslaved to an L3 master device FIB lookups are based on the
  60. * master index
  61. */
  62. static inline int l3mdev_fib_oif_rcu(struct net_device *dev)
  63. {
  64. return l3mdev_master_ifindex_rcu(dev) ? : dev->ifindex;
  65. }
  66. static inline int l3mdev_fib_oif(struct net_device *dev)
  67. {
  68. int oif;
  69. rcu_read_lock();
  70. oif = l3mdev_fib_oif_rcu(dev);
  71. rcu_read_unlock();
  72. return oif;
  73. }
  74. u32 l3mdev_fib_table_rcu(const struct net_device *dev);
  75. u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
  76. static inline u32 l3mdev_fib_table(const struct net_device *dev)
  77. {
  78. u32 tb_id;
  79. rcu_read_lock();
  80. tb_id = l3mdev_fib_table_rcu(dev);
  81. rcu_read_unlock();
  82. return tb_id;
  83. }
  84. static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev,
  85. const struct flowi4 *fl4)
  86. {
  87. if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rtable)
  88. return dev->l3mdev_ops->l3mdev_get_rtable(dev, fl4);
  89. return NULL;
  90. }
  91. static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
  92. {
  93. struct net_device *dev;
  94. bool rc = false;
  95. if (ifindex == 0)
  96. return false;
  97. rcu_read_lock();
  98. dev = dev_get_by_index_rcu(net, ifindex);
  99. if (dev)
  100. rc = netif_is_l3_master(dev);
  101. rcu_read_unlock();
  102. return rc;
  103. }
  104. static inline int l3mdev_get_saddr(struct net *net, int ifindex,
  105. struct flowi4 *fl4)
  106. {
  107. struct net_device *dev;
  108. int rc = 0;
  109. if (ifindex) {
  110. rcu_read_lock();
  111. dev = dev_get_by_index_rcu(net, ifindex);
  112. if (dev && netif_is_l3_master(dev) &&
  113. dev->l3mdev_ops->l3mdev_get_saddr) {
  114. rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4);
  115. }
  116. rcu_read_unlock();
  117. }
  118. return rc;
  119. }
  120. static inline struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev,
  121. const struct flowi6 *fl6)
  122. {
  123. if (netif_is_l3_master(dev) && dev->l3mdev_ops->l3mdev_get_rt6_dst)
  124. return dev->l3mdev_ops->l3mdev_get_rt6_dst(dev, fl6);
  125. return NULL;
  126. }
  127. static inline
  128. struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
  129. const struct flowi6 *fl6)
  130. {
  131. struct dst_entry *dst = NULL;
  132. struct net_device *dev;
  133. dev = dev_get_by_index(net, fl6->flowi6_oif);
  134. if (dev) {
  135. dst = l3mdev_get_rt6_dst(dev, fl6);
  136. dev_put(dev);
  137. }
  138. return dst;
  139. }
  140. #else
  141. static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev)
  142. {
  143. return 0;
  144. }
  145. static inline int l3mdev_master_ifindex(struct net_device *dev)
  146. {
  147. return 0;
  148. }
  149. static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
  150. {
  151. return 0;
  152. }
  153. static inline int l3mdev_fib_oif_rcu(struct net_device *dev)
  154. {
  155. return dev ? dev->ifindex : 0;
  156. }
  157. static inline int l3mdev_fib_oif(struct net_device *dev)
  158. {
  159. return dev ? dev->ifindex : 0;
  160. }
  161. static inline u32 l3mdev_fib_table_rcu(const struct net_device *dev)
  162. {
  163. return 0;
  164. }
  165. static inline u32 l3mdev_fib_table(const struct net_device *dev)
  166. {
  167. return 0;
  168. }
  169. static inline u32 l3mdev_fib_table_by_index(struct net *net, int ifindex)
  170. {
  171. return 0;
  172. }
  173. static inline struct rtable *l3mdev_get_rtable(const struct net_device *dev,
  174. const struct flowi4 *fl4)
  175. {
  176. return NULL;
  177. }
  178. static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
  179. {
  180. return false;
  181. }
  182. static inline int l3mdev_get_saddr(struct net *net, int ifindex,
  183. struct flowi4 *fl4)
  184. {
  185. return 0;
  186. }
  187. static inline
  188. struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev,
  189. const struct flowi6 *fl6)
  190. {
  191. return NULL;
  192. }
  193. static inline
  194. struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
  195. const struct flowi6 *fl6)
  196. {
  197. return NULL;
  198. }
  199. #endif
  200. #endif /* _NET_L3MDEV_H_ */