-
Notifications
You must be signed in to change notification settings - Fork 61
/
bridge_linux.go
153 lines (127 loc) · 4.48 KB
/
bridge_linux.go
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package tenus
import (
"bytes"
"fmt"
"net"
"github.com/docker/libcontainer/netlink"
)
// Bridger embeds Linker interface and adds one extra function.
type Bridger interface {
// Linker interface
Linker
// AddSlaveIfc adds network interface to the network bridge
AddSlaveIfc(*net.Interface) error
//RemoveSlaveIfc removes network interface from the network bridge
RemoveSlaveIfc(*net.Interface) error
}
// Bridge is Link which has zero or more slave network interfaces.
// Bridge implements Bridger interface.
type Bridge struct {
Link
slaveIfcs []net.Interface
}
// NewBridge creates new network bridge on Linux host.
//
// It is equivalent of running: ip link add name br${RANDOM STRING} type bridge
// NewBridge returns Bridger which is initialized to a pointer of type Bridge if the
// bridge was created successfully on the Linux host. Newly created bridge is assigned
// a random name starting with "br".
// It returns error if the bridge could not be created.
func NewBridge() (Bridger, error) {
brDev := makeNetInterfaceName("br")
if ok, err := NetInterfaceNameValid(brDev); !ok {
return nil, err
}
if _, err := net.InterfaceByName(brDev); err == nil {
return nil, fmt.Errorf("Interface name %s already assigned on the host", brDev)
}
if err := netlink.NetworkLinkAdd(brDev, "bridge"); err != nil {
return nil, err
}
newIfc, err := net.InterfaceByName(brDev)
if err != nil {
return nil, fmt.Errorf("Could not find the new interface: %s", err)
}
return &Bridge{
Link: Link{
ifc: newIfc,
},
}, nil
}
// NewBridge creates new network bridge on Linux host with the name passed as a parameter.
// It is equivalent of running: ip link add name ${ifcName} type bridge
// It returns error if the bridge can not be created.
func NewBridgeWithName(ifcName string) (Bridger, error) {
if ok, err := NetInterfaceNameValid(ifcName); !ok {
return nil, err
}
if _, err := net.InterfaceByName(ifcName); err == nil {
return nil, fmt.Errorf("Interface name %s already assigned on the host", ifcName)
}
if err := netlink.NetworkLinkAdd(ifcName, "bridge"); err != nil {
return nil, err
}
newIfc, err := net.InterfaceByName(ifcName)
if err != nil {
return nil, fmt.Errorf("Could not find the new interface: %s", err)
}
return &Bridge{
Link: Link{
ifc: newIfc,
},
}, nil
}
// BridgeFromName returns a tenus network bridge from an existing bridge of given name on the Linux host.
// It returns error if the bridge of the given name cannot be found.
func BridgeFromName(ifcName string) (Bridger, error) {
if ok, err := NetInterfaceNameValid(ifcName); !ok {
return nil, err
}
newIfc, err := net.InterfaceByName(ifcName)
if err != nil {
return nil, fmt.Errorf("Could not find the new interface: %s", err)
}
return &Bridge{
Link: Link{
ifc: newIfc,
},
}, nil
}
// AddToBridge adds network interfaces to network bridge.
// It is equivalent of running: ip link set ${netIfc name} master ${netBridge name}
// It returns error when it fails to add the network interface to bridge.
func AddToBridge(netIfc, netBridge *net.Interface) error {
return netlink.NetworkSetMaster(netIfc, netBridge)
}
// AddToBridge adds network interfaces to network bridge.
// It is equivalent of running: ip link set dev ${netIfc name} nomaster
// It returns error when it fails to remove the network interface from the bridge.
func RemoveFromBridge(netIfc *net.Interface) error {
return netlink.NetworkSetNoMaster(netIfc)
}
// AddSlaveIfc adds network interface to network bridge.
// It is equivalent of running: ip link set ${ifc name} master ${bridge name}
// It returns error if the network interface could not be added to the bridge.
func (br *Bridge) AddSlaveIfc(ifc *net.Interface) error {
if err := netlink.NetworkSetMaster(ifc, br.ifc); err != nil {
return err
}
br.slaveIfcs = append(br.slaveIfcs, *ifc)
return nil
}
// RemoveSlaveIfc removes network interface from the network bridge.
// It is equivalent of running: ip link set dev ${netIfc name} nomaster
// It returns error if the network interface is not in the bridge or
// it could not be removed from the bridge.
func (br *Bridge) RemoveSlaveIfc(ifc *net.Interface) error {
if err := netlink.NetworkSetNoMaster(ifc); err != nil {
return err
}
for index, i := range br.slaveIfcs {
// I could reflect.DeepEqual(), but there is not point to import reflect for one operation
if i.Name == ifc.Name && bytes.Equal(i.HardwareAddr, ifc.HardwareAddr) {
br.slaveIfcs = append(br.slaveIfcs[:index], br.slaveIfcs[index+1:]...)
}
}
return nil
}