tcp_tos_reflect_kern.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018 Facebook
  4. *
  5. * BPF program to automatically reflect TOS option from received syn packet
  6. *
  7. * Use load_sock_ops to load this BPF program.
  8. */
  9. #include <uapi/linux/bpf.h>
  10. #include <uapi/linux/tcp.h>
  11. #include <uapi/linux/if_ether.h>
  12. #include <uapi/linux/if_packet.h>
  13. #include <uapi/linux/ip.h>
  14. #include <uapi/linux/ipv6.h>
  15. #include <uapi/linux/in.h>
  16. #include <linux/socket.h>
  17. #include "bpf_helpers.h"
  18. #include "bpf_endian.h"
  19. #define DEBUG 1
  20. #define bpf_printk(fmt, ...) \
  21. ({ \
  22. char ____fmt[] = fmt; \
  23. bpf_trace_printk(____fmt, sizeof(____fmt), \
  24. ##__VA_ARGS__); \
  25. })
  26. SEC("sockops")
  27. int bpf_basertt(struct bpf_sock_ops *skops)
  28. {
  29. char header[sizeof(struct ipv6hdr)];
  30. struct ipv6hdr *hdr6;
  31. struct iphdr *hdr;
  32. int hdr_size = 0;
  33. int save_syn = 1;
  34. int tos = 0;
  35. int rv = 0;
  36. int op;
  37. op = (int) skops->op;
  38. #ifdef DEBUG
  39. bpf_printk("BPF command: %d\n", op);
  40. #endif
  41. switch (op) {
  42. case BPF_SOCK_OPS_TCP_LISTEN_CB:
  43. rv = bpf_setsockopt(skops, SOL_TCP, TCP_SAVE_SYN,
  44. &save_syn, sizeof(save_syn));
  45. break;
  46. case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
  47. if (skops->family == AF_INET)
  48. hdr_size = sizeof(struct iphdr);
  49. else
  50. hdr_size = sizeof(struct ipv6hdr);
  51. rv = bpf_getsockopt(skops, SOL_TCP, TCP_SAVED_SYN,
  52. header, hdr_size);
  53. if (!rv) {
  54. if (skops->family == AF_INET) {
  55. hdr = (struct iphdr *) header;
  56. tos = hdr->tos;
  57. if (tos != 0)
  58. bpf_setsockopt(skops, SOL_IP, IP_TOS,
  59. &tos, sizeof(tos));
  60. } else {
  61. hdr6 = (struct ipv6hdr *) header;
  62. tos = ((hdr6->priority) << 4 |
  63. (hdr6->flow_lbl[0]) >> 4);
  64. if (tos)
  65. bpf_setsockopt(skops, SOL_IPV6,
  66. IPV6_TCLASS,
  67. &tos, sizeof(tos));
  68. }
  69. rv = 0;
  70. }
  71. break;
  72. default:
  73. rv = -1;
  74. }
  75. #ifdef DEBUG
  76. bpf_printk("Returning %d\n", rv);
  77. #endif
  78. skops->reply = rv;
  79. return 1;
  80. }
  81. char _license[] SEC("license") = "GPL";