bpf_skb_adjust_room sets the inner_protocol as skb->protocol for packets encapsulation. But that is not appropriate when pushing Ethernet header. Add an option to further specify encap L2 type and set the inner_protocol as ETH_P_TEB.
Unified · Split
| @@ -2484,6 +2484,10 @@ union bpf_attr { · 2483 unmodified lines | ||
| 2484 | 2484 | * Use with ENCAP_L3/L4 flags to further specify the tunnel |
| 2485 | 2485 | * type; *len* is the length of the inner MAC header. |
| 2486 | 2486 | * |
| 2487 | + * * **BPF_F_ADJ_ROOM_ENCAP_L2_ETH**: | |
| 2488 | + * Use with BPF_F_ADJ_ROOM_ENCAP_L2 flag to further specify the | |
| 2489 | + * L2 type as Ethernet. | |
| 2490 | + * | |
| 2487 | 2491 | * A call to this helper is susceptible to change the underlying |
| 2488 | 2492 | * packet buffer. Therefore, at load time, all checks on pointers |
| 2489 | 2493 | * previously done by the verifier are invalidated and must be |
| @@ -4916,6 +4920,7 @@ enum { · 2426 unmodified lines | ||
| 4916 | 4920 | BPF_F_ADJ_ROOM_ENCAP_L4_GRE = (1ULL << 3), |
| 4917 | 4921 | BPF_F_ADJ_ROOM_ENCAP_L4_UDP = (1ULL << 4), |
| 4918 | 4922 | BPF_F_ADJ_ROOM_NO_CSUM_RESET = (1ULL << 5), |
| 4923 | + BPF_F_ADJ_ROOM_ENCAP_L2_ETH = (1ULL << 6), | |
| 4919 | 4924 | }; |
| 4920 | 4925 | |
| 4921 | 4926 | enum { |
| @@ -3409,6 +3409,7 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb) · 3408 unmodified lines | ||
| 3409 | 3409 | BPF_F_ADJ_ROOM_ENCAP_L3_MASK | \ |
| 3410 | 3410 | BPF_F_ADJ_ROOM_ENCAP_L4_GRE | \ |
| 3411 | 3411 | BPF_F_ADJ_ROOM_ENCAP_L4_UDP | \ |
| 3412 | + BPF_F_ADJ_ROOM_ENCAP_L2_ETH | \ | |
| 3412 | 3413 | BPF_F_ADJ_ROOM_ENCAP_L2( \ |
| 3413 | 3414 | BPF_ADJ_ROOM_ENCAP_L2_MASK)) |
| 3414 | 3415 | |
| @@ -3445,6 +3446,10 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff, · 30 unmodified lines | ||
| 3445 | 3446 | flags & BPF_F_ADJ_ROOM_ENCAP_L4_UDP) |
| 3446 | 3447 | return -EINVAL; |
| 3447 | 3448 | |
| 3449 | + if (flags & BPF_F_ADJ_ROOM_ENCAP_L2_ETH && | |
| 3450 | + inner_mac_len < ETH_HLEN) | |
| 3451 | + return -EINVAL; | |
| 3452 | + | |
| 3448 | 3453 | if (skb->encapsulation) |
| 3449 | 3454 | return -EALREADY; |
| 3450 | 3455 | |
| @@ -3463,7 +3468,11 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff, · 12 unmodified lines | ||
| 3463 | 3468 | skb->inner_mac_header = inner_net - inner_mac_len; |
| 3464 | 3469 | skb->inner_network_header = inner_net; |
| 3465 | 3470 | skb->inner_transport_header = inner_trans; |
| 3466 | − skb_set_inner_protocol(skb, skb->protocol); | |
| 3471 | + | |
| 3472 | + if (flags & BPF_F_ADJ_ROOM_ENCAP_L2_ETH) | |
| 3473 | + skb_set_inner_protocol(skb, htons(ETH_P_TEB)); | |
| 3474 | + else | |
| 3475 | + skb_set_inner_protocol(skb, skb->protocol); | |
| 3467 | 3476 | |
| 3468 | 3477 | skb->encapsulation = 1; |
| 3469 | 3478 | skb_set_network_header(skb, mac_len); |
| @@ -2484,6 +2484,10 @@ union bpf_attr { · 2483 unmodified lines | ||
| 2484 | 2484 | * Use with ENCAP_L3/L4 flags to further specify the tunnel |
| 2485 | 2485 | * type; *len* is the length of the inner MAC header. |
| 2486 | 2486 | * |
| 2487 | + * * **BPF_F_ADJ_ROOM_ENCAP_L2_ETH**: | |
| 2488 | + * Use with BPF_F_ADJ_ROOM_ENCAP_L2 flag to further specify the | |
| 2489 | + * L2 type as Ethernet. | |
| 2490 | + * | |
| 2487 | 2491 | * A call to this helper is susceptible to change the underlying |
| 2488 | 2492 | * packet buffer. Therefore, at load time, all checks on pointers |
| 2489 | 2493 | * previously done by the verifier are invalidated and must be |
| @@ -4916,6 +4920,7 @@ enum { · 2426 unmodified lines | ||
| 4916 | 4920 | BPF_F_ADJ_ROOM_ENCAP_L4_GRE = (1ULL << 3), |
| 4917 | 4921 | BPF_F_ADJ_ROOM_ENCAP_L4_UDP = (1ULL << 4), |
| 4918 | 4922 | BPF_F_ADJ_ROOM_NO_CSUM_RESET = (1ULL << 5), |
| 4923 | + BPF_F_ADJ_ROOM_ENCAP_L2_ETH = (1ULL << 6), | |
| 4919 | 4924 | }; |
| 4920 | 4925 | |
| 4921 | 4926 | enum { |