github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/drivers/overlay/bpf.go (about)

     1  package overlay
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"golang.org/x/net/bpf"
     9  )
    10  
    11  // vniMatchBPF returns a BPF program suitable for passing to the iptables and
    12  // ip6tables bpf match which matches on the VXAN Network ID of encapsulated
    13  // packets. The program assumes that it will be used in a rule which only
    14  // matches UDP datagrams.
    15  func vniMatchBPF(vni uint32) []bpf.RawInstruction {
    16  	asm, err := bpf.Assemble([]bpf.Instruction{
    17  		// Load offset of UDP payload into X.
    18  		bpf.LoadExtension{Num: bpf.ExtPayloadOffset}, // ld poff
    19  		bpf.TAX{}, // tax
    20  
    21  		bpf.LoadIndirect{Off: 4, Size: 4},                      // ld [x + 4] ; Load VXLAN ID into top 24 bits of A
    22  		bpf.ALUOpConstant{Op: bpf.ALUOpShiftRight, Val: 8},     // rsh #8     ; A >>= 8
    23  		bpf.JumpIf{Cond: bpf.JumpEqual, Val: vni, SkipTrue: 1}, // jeq $vni, match
    24  		bpf.RetConstant{Val: 0},                                // ret #0
    25  		bpf.RetConstant{Val: ^uint32(0)},                       // match: ret #-1
    26  	})
    27  	// bpf.Assemble() only errors if an instruction is invalid. As the only variable
    28  	// part of the program is an instruction value for which the entire range is
    29  	// valid, whether the program can be successfully assembled is independent of
    30  	// the input. Given that the only recourse is to fix this function and
    31  	// recompile, there's little value in bubbling the error up to the caller.
    32  	if err != nil {
    33  		panic(err)
    34  	}
    35  	return asm
    36  }
    37  
    38  // marshalXTBPF marshals a BPF program into the "decimal" byte code format
    39  // which is suitable for passing to the [iptables bpf match].
    40  //
    41  //	iptables -m bpf --bytecode
    42  //
    43  // [iptables bpf match]: https://ipset.netfilter.org/iptables-extensions.man.html#lbAH
    44  func marshalXTBPF(prog []bpf.RawInstruction) string { //nolint:unused
    45  	var b strings.Builder
    46  	fmt.Fprintf(&b, "%d", len(prog))
    47  	for _, ins := range prog {
    48  		fmt.Fprintf(&b, ",%d %d %d %d", ins.Op, ins.Jt, ins.Jf, ins.K)
    49  	}
    50  	return b.String()
    51  }
    52  
    53  // matchVXLAN returns an iptables rule fragment which matches VXLAN datagrams
    54  // with the given destination port and VXLAN Network ID utilizing the xt_bpf
    55  // netfilter kernel module. The returned slice's backing array is guaranteed not
    56  // to alias any other slice's.
    57  func matchVXLAN(port, vni uint32) []string {
    58  	dport := strconv.FormatUint(uint64(port), 10)
    59  	vniMatch := marshalXTBPF(vniMatchBPF(vni))
    60  
    61  	// https://ipset.netfilter.org/iptables-extensions.man.html#lbAH
    62  	return []string{"-p", "udp", "--dport", dport, "-m", "bpf", "--bytecode", vniMatch}
    63  }