From d95faf745be50c948cc26e5d870da8fb870de887 Mon Sep 17 00:00:00 2001
From: Cory Snider <csnider@mirantis.com>
Date: Mon, 6 Mar 2023 17:50:30 -0500
Subject: [PATCH] libnet/d/overlay: extract VNI match rule builder

The iptables rule clause used to match on the VNI of VXLAN datagrams
looks like line noise to the uninitiated. It doesn't help that the
expression is repeated twice and neither copy has any commentary.
DRY out the rule builder to a common function, and document what the
rule does and how it works.

Signed-off-by: Cory Snider <csnider@mirantis.com>
---
 .../libnetwork/drivers/overlay/encryption.go  | 12 +++-----
 .../drivers/overlay/encryption_u32.go         | 30 +++++++++++++++++++
 2 files changed, 34 insertions(+), 8 deletions(-)
 create mode 100644 components/engine/vendor/github.com/docker/libnetwork/drivers/overlay/encryption_u32.go

diff --git a/components/engine/vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go b/components/engine/vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go
index a97e73df82..be09c70d7a 100644
--- a/components/engine/vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go
+++ b/components/engine/vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go
@@ -200,11 +200,9 @@ func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error {
 
 func programMangle(vni uint32, add bool) (err error) {
 	var (
-		p      = strconv.FormatUint(uint64(vxlanPort), 10)
-		c      = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8)
 		m      = strconv.FormatUint(uint64(r), 10)
 		chain  = "OUTPUT"
-		rule   = []string{"-p", "udp", "--dport", p, "-m", "u32", "--u32", c, "-j", "MARK", "--set-mark", m}
+		rule   = append(matchVXLAN(overlayutils.VXLANUDPPort(), vni), "-j", "MARK", "--set-mark", m)
 		a      = "-A"
 		action = "install"
 	)
@@ -227,12 +225,10 @@ func programMangle(vni uint32, add bool) (err error) {
 
 func programInput(vni uint32, add bool) (err error) {
 	var (
-		port       = strconv.FormatUint(uint64(vxlanPort), 10)
-		vniMatch   = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8)
-		plainVxlan = []string{"-p", "udp", "--dport", port, "-m", "u32", "--u32", vniMatch, "-j"}
+		plainVxlan = matchVXLAN(overlayutils.VXLANUDPPort(), vni)
 		ipsecVxlan = append([]string{"-m", "policy", "--dir", "in", "--pol", "ipsec"}, plainVxlan...)
-		block      = append(plainVxlan, "DROP")
-		accept     = append(ipsecVxlan, "ACCEPT")
+		block      = append(plainVxlan, "-j", "DROP")
+		accept     = append(ipsecVxlan, "-j", "ACCEPT")
 		chain      = "INPUT"
 		action     = iptables.Append
 		msg        = "add"
diff --git a/components/engine/vendor/github.com/docker/libnetwork/drivers/overlay/encryption_u32.go b/components/engine/vendor/github.com/docker/libnetwork/drivers/overlay/encryption_u32.go
new file mode 100644
index 0000000000..c93f7c96fc
--- /dev/null
+++ b/components/engine/vendor/github.com/docker/libnetwork/drivers/overlay/encryption_u32.go
@@ -0,0 +1,30 @@
+package overlay
+
+import (
+	"fmt"
+	"strconv"
+)
+
+// matchVXLAN 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 matchVXLAN(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}
+}
-- 
2.33.0

