mana_bpf.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2. /* Copyright (c) 2021, Microsoft Corporation. */
  3. #include <linux/inetdevice.h>
  4. #include <linux/etherdevice.h>
  5. #include <linux/mm.h>
  6. #include <linux/bpf.h>
  7. #include <linux/bpf_trace.h>
  8. #include <net/xdp.h>
  9. #include <net/mana/mana.h>
  10. void mana_xdp_tx(struct sk_buff *skb, struct net_device *ndev)
  11. {
  12. u16 txq_idx = skb_get_queue_mapping(skb);
  13. struct netdev_queue *ndevtxq;
  14. int rc;
  15. __skb_push(skb, ETH_HLEN);
  16. ndevtxq = netdev_get_tx_queue(ndev, txq_idx);
  17. __netif_tx_lock(ndevtxq, smp_processor_id());
  18. rc = mana_start_xmit(skb, ndev);
  19. __netif_tx_unlock(ndevtxq);
  20. if (dev_xmit_complete(rc))
  21. return;
  22. dev_kfree_skb_any(skb);
  23. ndev->stats.tx_dropped++;
  24. }
  25. static int mana_xdp_xmit_fm(struct net_device *ndev, struct xdp_frame *frame,
  26. u16 q_idx)
  27. {
  28. struct sk_buff *skb;
  29. skb = xdp_build_skb_from_frame(frame, ndev);
  30. if (unlikely(!skb))
  31. return -ENOMEM;
  32. skb_set_queue_mapping(skb, q_idx);
  33. mana_xdp_tx(skb, ndev);
  34. return 0;
  35. }
  36. int mana_xdp_xmit(struct net_device *ndev, int n, struct xdp_frame **frames,
  37. u32 flags)
  38. {
  39. struct mana_port_context *apc = netdev_priv(ndev);
  40. struct mana_stats_tx *tx_stats;
  41. int i, count = 0;
  42. u16 q_idx;
  43. if (unlikely(!apc->port_is_up))
  44. return 0;
  45. q_idx = smp_processor_id() % ndev->real_num_tx_queues;
  46. for (i = 0; i < n; i++) {
  47. if (mana_xdp_xmit_fm(ndev, frames[i], q_idx))
  48. break;
  49. count++;
  50. }
  51. tx_stats = &apc->tx_qp[q_idx].txq.stats;
  52. u64_stats_update_begin(&tx_stats->syncp);
  53. tx_stats->xdp_xmit += count;
  54. u64_stats_update_end(&tx_stats->syncp);
  55. return count;
  56. }
  57. u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq,
  58. struct xdp_buff *xdp, void *buf_va, uint pkt_len)
  59. {
  60. struct mana_stats_rx *rx_stats;
  61. struct bpf_prog *prog;
  62. u32 act = XDP_PASS;
  63. rcu_read_lock();
  64. prog = rcu_dereference(rxq->bpf_prog);
  65. if (!prog)
  66. goto out;
  67. xdp_init_buff(xdp, PAGE_SIZE, &rxq->xdp_rxq);
  68. xdp_prepare_buff(xdp, buf_va, XDP_PACKET_HEADROOM, pkt_len, false);
  69. act = bpf_prog_run_xdp(prog, xdp);
  70. rx_stats = &rxq->stats;
  71. switch (act) {
  72. case XDP_PASS:
  73. case XDP_TX:
  74. case XDP_DROP:
  75. break;
  76. case XDP_REDIRECT:
  77. rxq->xdp_rc = xdp_do_redirect(ndev, xdp, prog);
  78. if (!rxq->xdp_rc) {
  79. rxq->xdp_flush = true;
  80. u64_stats_update_begin(&rx_stats->syncp);
  81. rx_stats->packets++;
  82. rx_stats->bytes += pkt_len;
  83. rx_stats->xdp_redirect++;
  84. u64_stats_update_end(&rx_stats->syncp);
  85. break;
  86. }
  87. fallthrough;
  88. case XDP_ABORTED:
  89. trace_xdp_exception(ndev, prog, act);
  90. break;
  91. default:
  92. bpf_warn_invalid_xdp_action(ndev, prog, act);
  93. }
  94. out:
  95. rcu_read_unlock();
  96. return act;
  97. }
  98. struct bpf_prog *mana_xdp_get(struct mana_port_context *apc)
  99. {
  100. ASSERT_RTNL();
  101. return apc->bpf_prog;
  102. }
  103. static struct bpf_prog *mana_chn_xdp_get(struct mana_port_context *apc)
  104. {
  105. return rtnl_dereference(apc->rxqs[0]->bpf_prog);
  106. }
  107. /* Set xdp program on channels */
  108. void mana_chn_setxdp(struct mana_port_context *apc, struct bpf_prog *prog)
  109. {
  110. struct bpf_prog *old_prog = mana_chn_xdp_get(apc);
  111. unsigned int num_queues = apc->num_queues;
  112. int i;
  113. ASSERT_RTNL();
  114. if (old_prog == prog)
  115. return;
  116. if (prog)
  117. bpf_prog_add(prog, num_queues);
  118. for (i = 0; i < num_queues; i++)
  119. rcu_assign_pointer(apc->rxqs[i]->bpf_prog, prog);
  120. if (old_prog)
  121. for (i = 0; i < num_queues; i++)
  122. bpf_prog_put(old_prog);
  123. }
  124. static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog,
  125. struct netlink_ext_ack *extack)
  126. {
  127. struct mana_port_context *apc = netdev_priv(ndev);
  128. struct bpf_prog *old_prog;
  129. struct gdma_context *gc;
  130. gc = apc->ac->gdma_dev->gdma_context;
  131. old_prog = mana_xdp_get(apc);
  132. if (!old_prog && !prog)
  133. return 0;
  134. if (prog && ndev->mtu > MANA_XDP_MTU_MAX) {
  135. netdev_err(ndev, "XDP: mtu:%u too large, mtu_max:%lu\n",
  136. ndev->mtu, MANA_XDP_MTU_MAX);
  137. NL_SET_ERR_MSG_MOD(extack, "XDP: mtu too large");
  138. return -EOPNOTSUPP;
  139. }
  140. /* One refcnt of the prog is hold by the caller already, so
  141. * don't increase refcnt for this one.
  142. */
  143. apc->bpf_prog = prog;
  144. if (old_prog)
  145. bpf_prog_put(old_prog);
  146. if (apc->port_is_up)
  147. mana_chn_setxdp(apc, prog);
  148. if (prog)
  149. ndev->max_mtu = MANA_XDP_MTU_MAX;
  150. else
  151. ndev->max_mtu = gc->adapter_mtu - ETH_HLEN;
  152. return 0;
  153. }
  154. int mana_bpf(struct net_device *ndev, struct netdev_bpf *bpf)
  155. {
  156. struct netlink_ext_ack *extack = bpf->extack;
  157. int ret;
  158. switch (bpf->command) {
  159. case XDP_SETUP_PROG:
  160. return mana_xdp_set(ndev, bpf->prog, extack);
  161. default:
  162. return -EOPNOTSUPP;
  163. }
  164. return ret;
  165. }