Browse code

libnetwork: Clean up sysfs-based operations

- The oldest kernel version currently supported is v3.10. Bridge
parameters can be set through netlink since v3.8 (see
torvalds/linux@25c71c7). As such, we don't need to fallback to sysfs to
set hairpin mode.
- `scanInterfaceStats()` is never called, so no need to keep it alive.
- Document why `default_pvid` is set through sysfs

Signed-off-by: Albin Kerouanton <albinker@gmail.com>

Albin Kerouanton authored on 2023/01/11 10:05:47
Showing 4 changed files
... ...
@@ -9,10 +9,8 @@ import (
9 9
 	"net"
10 10
 	"os"
11 11
 	"os/exec"
12
-	"path/filepath"
13 12
 	"strconv"
14 13
 	"sync"
15
-	"syscall"
16 14
 
17 15
 	"github.com/docker/docker/libnetwork/datastore"
18 16
 	"github.com/docker/docker/libnetwork/discoverapi"
... ...
@@ -891,32 +889,10 @@ func addToBridge(nlh *netlink.Handle, ifaceName, bridgeName string) error {
891 891
 
892 892
 func setHairpinMode(nlh *netlink.Handle, link netlink.Link, enable bool) error {
893 893
 	err := nlh.LinkSetHairpin(link, enable)
894
-	if err != nil && err != syscall.EINVAL {
895
-		// If error is not EINVAL something else went wrong, bail out right away
894
+	if err != nil {
896 895
 		return fmt.Errorf("unable to set hairpin mode on %s via netlink: %v",
897 896
 			link.Attrs().Name, err)
898 897
 	}
899
-
900
-	// Hairpin mode successfully set up
901
-	if err == nil {
902
-		return nil
903
-	}
904
-
905
-	// The netlink method failed with EINVAL which is probably because of an older
906
-	// kernel. Try one more time via the sysfs method.
907
-	path := filepath.Join("/sys/class/net", link.Attrs().Name, "brport/hairpin_mode")
908
-
909
-	var val []byte
910
-	if enable {
911
-		val = []byte{'1', '\n'}
912
-	} else {
913
-		val = []byte{'0', '\n'}
914
-	}
915
-
916
-	if err := os.WriteFile(path, val, 0644); err != nil {
917
-		return fmt.Errorf("unable to set hairpin mode on %s via sysfs: %v", link.Attrs().Name, err)
918
-	}
919
-
920 898
 	return nil
921 899
 }
922 900
 
... ...
@@ -124,6 +124,8 @@ func setDefaultVlan() {
124 124
 	}
125 125
 
126 126
 	brName := os.Args[2]
127
+	// IFLA_BR_VLAN_DEFAULT_PVID was added in Linux v4.4 (see torvalds/linux@0f963b7), so we can't use netlink for
128
+	// setting this until Docker drops support for CentOS/RHEL 7 (kernel 3.10, eol date: 2024-06-30).
127 129
 	path := filepath.Join("/sys/class/net", brName, "bridge/default_pvid")
128 130
 	data := []byte{'0', '\n'}
129 131
 
... ...
@@ -3,7 +3,6 @@ package osl
3 3
 import (
4 4
 	"fmt"
5 5
 	"net"
6
-	"regexp"
7 6
 	"sync"
8 7
 	"syscall"
9 8
 	"time"
... ...
@@ -418,30 +417,6 @@ func setInterfaceRoutes(nlh *netlink.Handle, iface netlink.Link, i *nwIface) err
418 418
 	return nil
419 419
 }
420 420
 
421
-// In older kernels (like the one in Centos 6.6 distro) sysctl does not have netns support. Therefore
422
-// we cannot gather the statistics from /sys/class/net/<dev>/statistics/<counter> files. Per-netns stats
423
-// are naturally found in /proc/net/dev in kernels which support netns (ifconfig relies on that).
424
-const (
425
-	base = "[ ]*%s:([ ]+[0-9]+){16}"
426
-)
427
-
428
-func scanInterfaceStats(data, ifName string, i *types.InterfaceStatistics) error {
429
-	var (
430
-		bktStr string
431
-		bkt    uint64
432
-	)
433
-
434
-	regex := fmt.Sprintf(base, ifName)
435
-	re := regexp.MustCompile(regex)
436
-	line := re.FindString(data)
437
-
438
-	_, err := fmt.Sscanf(line, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
439
-		&bktStr, &i.RxBytes, &i.RxPackets, &i.RxErrors, &i.RxDropped, &bkt, &bkt, &bkt,
440
-		&bkt, &i.TxBytes, &i.TxPackets, &i.TxErrors, &i.TxDropped, &bkt, &bkt, &bkt, &bkt)
441
-
442
-	return err
443
-}
444
-
445 421
 func checkRouteConflict(nlh *netlink.Handle, address *net.IPNet, family int) error {
446 422
 	routes, err := nlh.RouteList(nil, family)
447 423
 	if err != nil {
... ...
@@ -158,32 +158,6 @@ func verifyCleanup(t *testing.T, s Sandbox, wait bool) {
158 158
 	}
159 159
 }
160 160
 
161
-func TestScanStatistics(t *testing.T) {
162
-	data :=
163
-		"Inter-|   Receive                                                |  Transmit\n" +
164
-			"	face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed\n" +
165
-			"  eth0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0\n" +
166
-			" wlan0: 7787685   11141    0    0    0     0          0         0  1681390    7220    0    0    0     0       0          0\n" +
167
-			"    lo:  783782    1853    0    0    0     0          0         0   783782    1853    0    0    0     0       0          0\n" +
168
-			"lxcbr0:       0       0    0    0    0     0          0         0     9006      61    0    0    0     0       0          0\n"
169
-
170
-	i := &types.InterfaceStatistics{}
171
-
172
-	if err := scanInterfaceStats(data, "wlan0", i); err != nil {
173
-		t.Fatal(err)
174
-	}
175
-	if i.TxBytes != 1681390 || i.TxPackets != 7220 || i.RxBytes != 7787685 || i.RxPackets != 11141 {
176
-		t.Fatalf("Error scanning the statistics")
177
-	}
178
-
179
-	if err := scanInterfaceStats(data, "lxcbr0", i); err != nil {
180
-		t.Fatal(err)
181
-	}
182
-	if i.TxBytes != 9006 || i.TxPackets != 61 || i.RxBytes != 0 || i.RxPackets != 0 {
183
-		t.Fatalf("Error scanning the statistics")
184
-	}
185
-}
186
-
187 161
 func TestDisableIPv6DAD(t *testing.T) {
188 162
 	defer testutils.SetupTestOSContext(t)()
189 163