File: network_utils_bridge.go

package info (click to toggle)
incus 6.0.5-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 24,428 kB
  • sloc: sh: 16,313; ansic: 3,121; python: 457; makefile: 337; ruby: 51; sql: 50; lisp: 6
file content (103 lines) | stat: -rw-r--r-- 3,060 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package network

import (
	"context"
	"fmt"
	"os"
	"strings"

	"github.com/lxc/incus/v6/internal/server/ip"
	"github.com/lxc/incus/v6/internal/server/state"
	"github.com/lxc/incus/v6/shared/util"
)

// BridgeVLANFilteringStatus returns whether VLAN filtering is enabled on a bridge interface.
func BridgeVLANFilteringStatus(interfaceName string) (string, error) {
	content, err := os.ReadFile(fmt.Sprintf("/sys/class/net/%s/bridge/vlan_filtering", interfaceName))
	if err != nil {
		return "", fmt.Errorf("Failed getting bridge VLAN status for %q: %w", interfaceName, err)
	}

	return strings.TrimSpace(string(content)), nil
}

// BridgeVLANFilterSetStatus sets the status of VLAN filtering on a bridge interface.
func BridgeVLANFilterSetStatus(interfaceName string, status string) error {
	err := os.WriteFile(fmt.Sprintf("/sys/class/net/%s/bridge/vlan_filtering", interfaceName), []byte(status), 0)
	if err != nil {
		return fmt.Errorf("Failed enabling VLAN filtering on bridge %q: %w", interfaceName, err)
	}

	return nil
}

// BridgeVLANDefaultPVID returns the VLAN default port VLAN ID (PVID).
func BridgeVLANDefaultPVID(interfaceName string) (string, error) {
	content, err := os.ReadFile(fmt.Sprintf("/sys/class/net/%s/bridge/default_pvid", interfaceName))
	if err != nil {
		return "", fmt.Errorf("Failed getting bridge VLAN default PVID for %q: %w", interfaceName, err)
	}

	return strings.TrimSpace(string(content)), nil
}

// BridgeVLANSetDefaultPVID sets the VLAN default port VLAN ID (PVID).
func BridgeVLANSetDefaultPVID(interfaceName string, vlanID string) error {
	err := os.WriteFile(fmt.Sprintf("/sys/class/net/%s/bridge/default_pvid", interfaceName), []byte(vlanID), 0)
	if err != nil {
		return fmt.Errorf("Failed setting bridge VLAN default PVID for %q: %w", interfaceName, err)
	}

	return nil
}

// IsNativeBridge returns whether the bridge name specified is a Linux native bridge.
func IsNativeBridge(bridgeName string) bool {
	return util.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", bridgeName))
}

// AttachInterface attaches an interface to a bridge.
func AttachInterface(s *state.State, bridgeName string, devName string) error {
	if IsNativeBridge(bridgeName) {
		link := &ip.Link{Name: devName}
		err := link.SetMaster(bridgeName)
		if err != nil {
			return err
		}
	} else {
		vswitch, err := s.OVS()
		if err != nil {
			return fmt.Errorf("Failed to connect to OVS: %w", err)
		}

		err = vswitch.CreateBridgePort(context.TODO(), bridgeName, devName, true)
		if err != nil {
			return err
		}
	}

	return nil
}

// DetachInterface detaches an interface from a bridge.
func DetachInterface(s *state.State, bridgeName string, devName string) error {
	if IsNativeBridge(bridgeName) {
		link := &ip.Link{Name: devName}
		err := link.SetNoMaster()
		if err != nil {
			return err
		}
	} else {
		vswitch, err := s.OVS()
		if err != nil {
			return fmt.Errorf("Failed to connect to OVS: %w", err)
		}

		err = vswitch.DeleteBridgePort(context.TODO(), bridgeName, devName)
		if err != nil {
			return err
		}
	}

	return nil
}