0001
0002
0003
0004 #include <linux/bpf.h>
0005 #include <bpf/bpf_helpers.h>
0006 #include <linux/if_ether.h>
0007
0008 #include <stddef.h>
0009 #include <stdint.h>
0010
0011 char _license[] SEC("license") = "GPL";
0012
0013
0014 volatile const int GLOBAL_USER_MTU;
0015 volatile const __u32 GLOBAL_USER_IFINDEX;
0016
0017
0018 __u32 global_bpf_mtu_xdp = 0;
0019 __u32 global_bpf_mtu_tc = 0;
0020
0021 SEC("xdp")
0022 int xdp_use_helper_basic(struct xdp_md *ctx)
0023 {
0024 __u32 mtu_len = 0;
0025
0026 if (bpf_check_mtu(ctx, 0, &mtu_len, 0, 0))
0027 return XDP_ABORTED;
0028
0029 return XDP_PASS;
0030 }
0031
0032 SEC("xdp")
0033 int xdp_use_helper(struct xdp_md *ctx)
0034 {
0035 int retval = XDP_PASS;
0036 __u32 mtu_len = 0;
0037 __u32 ifindex = 0;
0038 int delta = 0;
0039
0040
0041 if (GLOBAL_USER_IFINDEX > 0)
0042 ifindex = GLOBAL_USER_IFINDEX;
0043
0044 if (bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0)) {
0045
0046 retval = XDP_ABORTED;
0047 goto out;
0048 }
0049
0050 if (mtu_len != GLOBAL_USER_MTU)
0051 retval = XDP_DROP;
0052
0053 out:
0054 global_bpf_mtu_xdp = mtu_len;
0055 return retval;
0056 }
0057
0058 SEC("xdp")
0059 int xdp_exceed_mtu(struct xdp_md *ctx)
0060 {
0061 void *data_end = (void *)(long)ctx->data_end;
0062 void *data = (void *)(long)ctx->data;
0063 __u32 ifindex = GLOBAL_USER_IFINDEX;
0064 __u32 data_len = data_end - data;
0065 int retval = XDP_ABORTED;
0066 __u32 mtu_len = 0;
0067 int delta;
0068 int err;
0069
0070
0071 delta = GLOBAL_USER_MTU - (data_len - ETH_HLEN) + 1;
0072
0073 err = bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0);
0074 if (err) {
0075 retval = XDP_PASS;
0076 if (err != BPF_MTU_CHK_RET_FRAG_NEEDED)
0077 retval = XDP_DROP;
0078 }
0079
0080 global_bpf_mtu_xdp = mtu_len;
0081 return retval;
0082 }
0083
0084 SEC("xdp")
0085 int xdp_minus_delta(struct xdp_md *ctx)
0086 {
0087 int retval = XDP_PASS;
0088 void *data_end = (void *)(long)ctx->data_end;
0089 void *data = (void *)(long)ctx->data;
0090 __u32 ifindex = GLOBAL_USER_IFINDEX;
0091 __u32 data_len = data_end - data;
0092 __u32 mtu_len = 0;
0093 int delta;
0094
0095
0096 delta = -((data_len - ETH_HLEN) + 1);
0097
0098
0099
0100
0101 if (bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0))
0102 retval = XDP_ABORTED;
0103
0104 global_bpf_mtu_xdp = mtu_len;
0105 return retval;
0106 }
0107
0108 SEC("xdp")
0109 int xdp_input_len(struct xdp_md *ctx)
0110 {
0111 int retval = XDP_PASS;
0112 void *data_end = (void *)(long)ctx->data_end;
0113 void *data = (void *)(long)ctx->data;
0114 __u32 ifindex = GLOBAL_USER_IFINDEX;
0115 __u32 data_len = data_end - data;
0116
0117
0118
0119
0120
0121
0122
0123 __u32 mtu_len = data_len - ETH_HLEN;
0124
0125 if (bpf_check_mtu(ctx, ifindex, &mtu_len, 0, 0))
0126 retval = XDP_ABORTED;
0127
0128 global_bpf_mtu_xdp = mtu_len;
0129 return retval;
0130 }
0131
0132 SEC("xdp")
0133 int xdp_input_len_exceed(struct xdp_md *ctx)
0134 {
0135 int retval = XDP_ABORTED;
0136 __u32 ifindex = GLOBAL_USER_IFINDEX;
0137 int err;
0138
0139
0140
0141
0142
0143
0144 __u32 mtu_len = GLOBAL_USER_MTU;
0145
0146 mtu_len += 1;
0147
0148 err = bpf_check_mtu(ctx, ifindex, &mtu_len, 0, 0);
0149 if (err == BPF_MTU_CHK_RET_FRAG_NEEDED)
0150 retval = XDP_PASS ;
0151
0152 global_bpf_mtu_xdp = mtu_len;
0153 return retval;
0154 }
0155
0156 SEC("tc")
0157 int tc_use_helper(struct __sk_buff *ctx)
0158 {
0159 int retval = BPF_OK;
0160 __u32 mtu_len = 0;
0161 int delta = 0;
0162
0163 if (bpf_check_mtu(ctx, 0, &mtu_len, delta, 0)) {
0164 retval = BPF_DROP;
0165 goto out;
0166 }
0167
0168 if (mtu_len != GLOBAL_USER_MTU)
0169 retval = BPF_REDIRECT;
0170 out:
0171 global_bpf_mtu_tc = mtu_len;
0172 return retval;
0173 }
0174
0175 SEC("tc")
0176 int tc_exceed_mtu(struct __sk_buff *ctx)
0177 {
0178 __u32 ifindex = GLOBAL_USER_IFINDEX;
0179 int retval = BPF_DROP;
0180 __u32 skb_len = ctx->len;
0181 __u32 mtu_len = 0;
0182 int delta;
0183 int err;
0184
0185
0186 delta = GLOBAL_USER_MTU - (skb_len - ETH_HLEN) + 1;
0187
0188 err = bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0);
0189 if (err) {
0190 retval = BPF_OK;
0191 if (err != BPF_MTU_CHK_RET_FRAG_NEEDED)
0192 retval = BPF_DROP;
0193 }
0194
0195 global_bpf_mtu_tc = mtu_len;
0196 return retval;
0197 }
0198
0199 SEC("tc")
0200 int tc_exceed_mtu_da(struct __sk_buff *ctx)
0201 {
0202
0203 void *data_end = (void *)(long)ctx->data_end;
0204 void *data = (void *)(long)ctx->data;
0205 __u32 ifindex = GLOBAL_USER_IFINDEX;
0206 __u32 data_len = data_end - data;
0207 int retval = BPF_DROP;
0208 __u32 mtu_len = 0;
0209 int delta;
0210 int err;
0211
0212
0213 delta = GLOBAL_USER_MTU - (data_len - ETH_HLEN) + 1;
0214
0215 err = bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0);
0216 if (err) {
0217 retval = BPF_OK;
0218 if (err != BPF_MTU_CHK_RET_FRAG_NEEDED)
0219 retval = BPF_DROP;
0220 }
0221
0222 global_bpf_mtu_tc = mtu_len;
0223 return retval;
0224 }
0225
0226 SEC("tc")
0227 int tc_minus_delta(struct __sk_buff *ctx)
0228 {
0229 int retval = BPF_OK;
0230 __u32 ifindex = GLOBAL_USER_IFINDEX;
0231 __u32 skb_len = ctx->len;
0232 __u32 mtu_len = 0;
0233 int delta;
0234
0235
0236 delta = -((skb_len - ETH_HLEN) + 1);
0237
0238
0239
0240
0241 if (bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0))
0242 retval = BPF_DROP;
0243
0244 global_bpf_mtu_xdp = mtu_len;
0245 return retval;
0246 }
0247
0248 SEC("tc")
0249 int tc_input_len(struct __sk_buff *ctx)
0250 {
0251 int retval = BPF_OK;
0252 __u32 ifindex = GLOBAL_USER_IFINDEX;
0253
0254
0255
0256
0257
0258
0259 __u32 mtu_len = GLOBAL_USER_MTU;
0260
0261 if (bpf_check_mtu(ctx, ifindex, &mtu_len, 0, 0))
0262 retval = BPF_DROP;
0263
0264 global_bpf_mtu_xdp = mtu_len;
0265 return retval;
0266 }
0267
0268 SEC("tc")
0269 int tc_input_len_exceed(struct __sk_buff *ctx)
0270 {
0271 int retval = BPF_DROP;
0272 __u32 ifindex = GLOBAL_USER_IFINDEX;
0273 int err;
0274
0275
0276
0277
0278
0279
0280 __u32 mtu_len = GLOBAL_USER_MTU;
0281
0282 mtu_len += 1;
0283
0284 err = bpf_check_mtu(ctx, ifindex, &mtu_len, 0, 0);
0285 if (err == BPF_MTU_CHK_RET_FRAG_NEEDED)
0286 retval = BPF_OK;
0287
0288 global_bpf_mtu_xdp = mtu_len;
0289 return retval;
0290 }