xdp_rxq_info_kern.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* SPDX-License-Identifier: GPL-2.0
  2. * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc.
  3. *
  4. * Example howto extract XDP RX-queue info
  5. */
  6. #include <uapi/linux/bpf.h>
  7. #include "bpf_helpers.h"
  8. /* Config setup from with userspace
  9. *
  10. * User-side setup ifindex in config_map, to verify that
  11. * ctx->ingress_ifindex is correct (against configured ifindex)
  12. */
  13. struct config {
  14. __u32 action;
  15. int ifindex;
  16. };
  17. struct bpf_map_def SEC("maps") config_map = {
  18. .type = BPF_MAP_TYPE_ARRAY,
  19. .key_size = sizeof(int),
  20. .value_size = sizeof(struct config),
  21. .max_entries = 1,
  22. };
  23. /* Common stats data record (shared with userspace) */
  24. struct datarec {
  25. __u64 processed;
  26. __u64 issue;
  27. };
  28. struct bpf_map_def SEC("maps") stats_global_map = {
  29. .type = BPF_MAP_TYPE_PERCPU_ARRAY,
  30. .key_size = sizeof(u32),
  31. .value_size = sizeof(struct datarec),
  32. .max_entries = 1,
  33. };
  34. #define MAX_RXQs 64
  35. /* Stats per rx_queue_index (per CPU) */
  36. struct bpf_map_def SEC("maps") rx_queue_index_map = {
  37. .type = BPF_MAP_TYPE_PERCPU_ARRAY,
  38. .key_size = sizeof(u32),
  39. .value_size = sizeof(struct datarec),
  40. .max_entries = MAX_RXQs + 1,
  41. };
  42. SEC("xdp_prog0")
  43. int xdp_prognum0(struct xdp_md *ctx)
  44. {
  45. void *data_end = (void *)(long)ctx->data_end;
  46. void *data = (void *)(long)ctx->data;
  47. struct datarec *rec, *rxq_rec;
  48. int ingress_ifindex;
  49. struct config *config;
  50. u32 key = 0;
  51. /* Global stats record */
  52. rec = bpf_map_lookup_elem(&stats_global_map, &key);
  53. if (!rec)
  54. return XDP_ABORTED;
  55. rec->processed++;
  56. /* Accessing ctx->ingress_ifindex, cause BPF to rewrite BPF
  57. * instructions inside kernel to access xdp_rxq->dev->ifindex
  58. */
  59. ingress_ifindex = ctx->ingress_ifindex;
  60. config = bpf_map_lookup_elem(&config_map, &key);
  61. if (!config)
  62. return XDP_ABORTED;
  63. /* Simple test: check ctx provided ifindex is as expected */
  64. if (ingress_ifindex != config->ifindex) {
  65. /* count this error case */
  66. rec->issue++;
  67. return XDP_ABORTED;
  68. }
  69. /* Update stats per rx_queue_index. Handle if rx_queue_index
  70. * is larger than stats map can contain info for.
  71. */
  72. key = ctx->rx_queue_index;
  73. if (key >= MAX_RXQs)
  74. key = MAX_RXQs;
  75. rxq_rec = bpf_map_lookup_elem(&rx_queue_index_map, &key);
  76. if (!rxq_rec)
  77. return XDP_ABORTED;
  78. rxq_rec->processed++;
  79. if (key == MAX_RXQs)
  80. rxq_rec->issue++;
  81. return config->action;
  82. }
  83. char _license[] SEC("license") = "GPL";