Merge pull request #45281 from corhere/libnet/overlay-bpf-harder

libnetwork/drivers/overlay: only program xt_bpf rules
This commit is contained in:
Sebastiaan van Stijn 2023-04-07 01:12:12 +02:00 committed by GitHub
commit 1bdceb8a65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 17 additions and 76 deletions

View file

@ -2,6 +2,7 @@ package overlay
import (
"fmt"
"strconv"
"strings"
"golang.org/x/net/bpf"
@ -45,3 +46,15 @@ func marshalXTBPF(prog []bpf.RawInstruction) string { //nolint:unused
}
return b.String()
}
// matchVXLAN returns an iptables rule fragment which matches VXLAN datagrams
// with the given destination port and VXLAN Network ID utilizing the xt_bpf
// netfilter kernel module. The returned slice's backing array is guaranteed not
// to alias any other slice's.
func matchVXLAN(port, vni uint32) []string {
dport := strconv.FormatUint(uint64(port), 10)
vniMatch := marshalXTBPF(vniMatchBPF(vni))
// https://ipset.netfilter.org/iptables-extensions.man.html#lbAH
return []string{"-p", "udp", "--dport", dport, "-m", "bpf", "--bytecode", vniMatch}
}

View file

@ -18,7 +18,6 @@ import (
"github.com/docker/docker/libnetwork/iptables"
"github.com/docker/docker/libnetwork/ns"
"github.com/docker/docker/libnetwork/types"
"github.com/hashicorp/go-multierror"
"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
)
@ -226,31 +225,7 @@ func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error {
return nil
}
type matchVXLANFunc func(port, vni uint32) []string
// programVXLANRuleFunc returns a function which tries calling programWithMatch
// with the u32 match, falling back to the BPF match if installing u32 variant
// of the rules fails.
func programVXLANRuleFunc(programWithMatch func(matchVXLAN matchVXLANFunc, vni uint32, add bool) error) func(vni uint32, add bool) error {
return func(vni uint32, add bool) error {
if add {
if err := programWithMatch(matchVXLANWithU32, vni, add); err != nil {
// That didn't work. Maybe the xt_u32 module isn't available? Try again with xt_bpf.
err2 := programWithMatch(matchVXLANWithBPF, vni, add)
if err2 != nil {
return multierror.Append(err, err2)
}
}
return nil
} else {
// Delete both flavours.
err := programWithMatch(matchVXLANWithU32, vni, add)
return multierror.Append(err, programWithMatch(matchVXLANWithBPF, vni, add)).ErrorOrNil()
}
}
}
var programMangle = programVXLANRuleFunc(func(matchVXLAN matchVXLANFunc, vni uint32, add bool) error {
func programMangle(vni uint32, add bool) error {
var (
m = strconv.FormatUint(mark, 10)
chain = "OUTPUT"
@ -272,9 +247,9 @@ var programMangle = programVXLANRuleFunc(func(matchVXLAN matchVXLANFunc, vni uin
}
return nil
})
}
var programInput = programVXLANRuleFunc(func(matchVXLAN matchVXLANFunc, vni uint32, add bool) error {
func programInput(vni uint32, add bool) error {
var (
plainVxlan = matchVXLAN(overlayutils.VXLANUDPPort(), vni)
chain = "INPUT"
@ -315,7 +290,7 @@ var programInput = programVXLANRuleFunc(func(matchVXLAN matchVXLANFunc, vni uint
}
return nil
})
}
func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (fSA *netlink.XfrmState, rSA *netlink.XfrmState, err error) {
var (

View file

@ -1,17 +0,0 @@
package overlay
import (
"strconv"
)
// matchVXLANWithBPF returns an iptables rule fragment which matches VXLAN
// datagrams with the given destination port and VXLAN Network ID utilizing the
// xt_bpf netfilter kernel module. The returned slice's backing array is
// guaranteed not to alias any other slice's.
func matchVXLANWithBPF(port, vni uint32) []string {
dport := strconv.FormatUint(uint64(port), 10)
vniMatch := marshalXTBPF(vniMatchBPF(vni))
// https://ipset.netfilter.org/iptables-extensions.man.html#lbAH
return []string{"-p", "udp", "--dport", dport, "-m", "bpf", "--bytecode", vniMatch}
}

View file

@ -1,30 +0,0 @@
package overlay
import (
"fmt"
"strconv"
)
// matchVXLANWithU32 returns an iptables rule fragment which matches VXLAN
// datagrams with the given destination port and VXLAN Network ID utilizing the
// xt_u32 netfilter kernel module. The returned slice's backing array is
// guaranteed not to alias any other slice's.
func matchVXLANWithU32(port, vni uint32) []string {
dport := strconv.FormatUint(uint64(port), 10)
// The u32 expression language is documented in iptables-extensions(8).
// https://ipset.netfilter.org/iptables-extensions.man.html#lbCK
//
// 0>>22&0x3C ; Compute number of octets in IPv4 header
// @ ; Make this the new offset into the packet
// ; (jump to start of UDP header)
// 12&0xFFFFFF00 ; Read 32-bit value at offset 12 and mask off the bottom octet
// = ; Test whether the value is equal to a constant
//
// A UDP header is eight octets long so offset 12 from the start of the
// UDP header is four octets into the payload: the VNI field of the
// VXLAN header.
vniMatch := fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8)
return []string{"-p", "udp", "--dport", dport, "-m", "u32", "--u32", vniMatch}
}