tcx.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /* Copyright (c) 2023 Isovalent */
  3. #ifndef __NET_TCX_H
  4. #define __NET_TCX_H
  5. #include <linux/bpf.h>
  6. #include <linux/bpf_mprog.h>
  7. #include <net/sch_generic.h>
  8. struct mini_Qdisc;
  9. struct tcx_entry {
  10. struct mini_Qdisc __rcu *miniq;
  11. struct bpf_mprog_bundle bundle;
  12. u32 miniq_active;
  13. struct rcu_head rcu;
  14. };
  15. struct tcx_link {
  16. struct bpf_link link;
  17. struct net_device *dev;
  18. };
  19. static inline void tcx_set_ingress(struct sk_buff *skb, bool ingress)
  20. {
  21. #ifdef CONFIG_NET_XGRESS
  22. skb->tc_at_ingress = ingress;
  23. #endif
  24. }
  25. #ifdef CONFIG_NET_XGRESS
  26. static inline struct tcx_entry *tcx_entry(struct bpf_mprog_entry *entry)
  27. {
  28. struct bpf_mprog_bundle *bundle = entry->parent;
  29. return container_of(bundle, struct tcx_entry, bundle);
  30. }
  31. static inline struct tcx_link *tcx_link(const struct bpf_link *link)
  32. {
  33. return container_of(link, struct tcx_link, link);
  34. }
  35. void tcx_inc(void);
  36. void tcx_dec(void);
  37. static inline void tcx_entry_sync(void)
  38. {
  39. /* bpf_mprog_entry got a/b swapped, therefore ensure that
  40. * there are no inflight users on the old one anymore.
  41. */
  42. synchronize_rcu();
  43. }
  44. static inline void
  45. tcx_entry_update(struct net_device *dev, struct bpf_mprog_entry *entry,
  46. bool ingress)
  47. {
  48. ASSERT_RTNL();
  49. if (ingress)
  50. rcu_assign_pointer(dev->tcx_ingress, entry);
  51. else
  52. rcu_assign_pointer(dev->tcx_egress, entry);
  53. }
  54. static inline struct bpf_mprog_entry *
  55. tcx_entry_fetch(struct net_device *dev, bool ingress)
  56. {
  57. ASSERT_RTNL();
  58. if (ingress)
  59. return rcu_dereference_rtnl(dev->tcx_ingress);
  60. else
  61. return rcu_dereference_rtnl(dev->tcx_egress);
  62. }
  63. static inline struct bpf_mprog_entry *tcx_entry_create_noprof(void)
  64. {
  65. struct tcx_entry *tcx = kzalloc_noprof(sizeof(*tcx), GFP_KERNEL);
  66. if (tcx) {
  67. bpf_mprog_bundle_init(&tcx->bundle);
  68. return &tcx->bundle.a;
  69. }
  70. return NULL;
  71. }
  72. #define tcx_entry_create(...) alloc_hooks(tcx_entry_create_noprof(__VA_ARGS__))
  73. static inline void tcx_entry_free(struct bpf_mprog_entry *entry)
  74. {
  75. kfree_rcu(tcx_entry(entry), rcu);
  76. }
  77. static inline struct bpf_mprog_entry *
  78. tcx_entry_fetch_or_create(struct net_device *dev, bool ingress, bool *created)
  79. {
  80. struct bpf_mprog_entry *entry = tcx_entry_fetch(dev, ingress);
  81. *created = false;
  82. if (!entry) {
  83. entry = tcx_entry_create();
  84. if (!entry)
  85. return NULL;
  86. *created = true;
  87. }
  88. return entry;
  89. }
  90. static inline void tcx_skeys_inc(bool ingress)
  91. {
  92. tcx_inc();
  93. if (ingress)
  94. net_inc_ingress_queue();
  95. else
  96. net_inc_egress_queue();
  97. }
  98. static inline void tcx_skeys_dec(bool ingress)
  99. {
  100. if (ingress)
  101. net_dec_ingress_queue();
  102. else
  103. net_dec_egress_queue();
  104. tcx_dec();
  105. }
  106. static inline void tcx_miniq_inc(struct bpf_mprog_entry *entry)
  107. {
  108. ASSERT_RTNL();
  109. tcx_entry(entry)->miniq_active++;
  110. }
  111. static inline void tcx_miniq_dec(struct bpf_mprog_entry *entry)
  112. {
  113. ASSERT_RTNL();
  114. tcx_entry(entry)->miniq_active--;
  115. }
  116. static inline bool tcx_entry_is_active(struct bpf_mprog_entry *entry)
  117. {
  118. ASSERT_RTNL();
  119. return bpf_mprog_total(entry) || tcx_entry(entry)->miniq_active;
  120. }
  121. static inline enum tcx_action_base tcx_action_code(struct sk_buff *skb,
  122. int code)
  123. {
  124. switch (code) {
  125. case TCX_PASS:
  126. skb->tc_index = qdisc_skb_cb(skb)->tc_classid;
  127. fallthrough;
  128. case TCX_DROP:
  129. case TCX_REDIRECT:
  130. return code;
  131. case TCX_NEXT:
  132. default:
  133. return TCX_NEXT;
  134. }
  135. }
  136. #endif /* CONFIG_NET_XGRESS */
  137. #if defined(CONFIG_NET_XGRESS) && defined(CONFIG_BPF_SYSCALL)
  138. int tcx_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog);
  139. int tcx_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
  140. int tcx_prog_detach(const union bpf_attr *attr, struct bpf_prog *prog);
  141. void tcx_uninstall(struct net_device *dev, bool ingress);
  142. int tcx_prog_query(const union bpf_attr *attr,
  143. union bpf_attr __user *uattr);
  144. static inline void dev_tcx_uninstall(struct net_device *dev)
  145. {
  146. ASSERT_RTNL();
  147. tcx_uninstall(dev, true);
  148. tcx_uninstall(dev, false);
  149. }
  150. #else
  151. static inline int tcx_prog_attach(const union bpf_attr *attr,
  152. struct bpf_prog *prog)
  153. {
  154. return -EINVAL;
  155. }
  156. static inline int tcx_link_attach(const union bpf_attr *attr,
  157. struct bpf_prog *prog)
  158. {
  159. return -EINVAL;
  160. }
  161. static inline int tcx_prog_detach(const union bpf_attr *attr,
  162. struct bpf_prog *prog)
  163. {
  164. return -EINVAL;
  165. }
  166. static inline int tcx_prog_query(const union bpf_attr *attr,
  167. union bpf_attr __user *uattr)
  168. {
  169. return -EINVAL;
  170. }
  171. static inline void dev_tcx_uninstall(struct net_device *dev)
  172. {
  173. }
  174. #endif /* CONFIG_NET_XGRESS && CONFIG_BPF_SYSCALL */
  175. #endif /* __NET_TCX_H */