-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathveth_linux.go
216 lines (180 loc) · 6.64 KB
/
veth_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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
package tenus
import (
"fmt"
"net"
"os"
"syscall"
"github.com/docker/libcontainer/netlink"
"github.com/docker/libcontainer/system"
)
// VethOptions allows you to specify options for veth link.
type VethOptions struct {
// Veth pair's peer interface name
PeerName string
// TX queue length
TxQueueLen int
}
// Vether embeds Linker interface and adds few more functions mostly to handle peer link interface
type Vether interface {
// Linker interface
Linker
// PeerNetInterface returns peer network interface
PeerNetInterface() *net.Interface
// SetPeerLinkUp sets peer link up - which also brings up the other peer in VethPair
SetPeerLinkUp() error
// DeletePeerLink deletes peer link - this also deletes the other peer in VethPair
DeletePeerLink() error
// SetPeerLinkIp configures peer link's IP address
SetPeerLinkIp(net.IP, *net.IPNet) error
// SetPeerLinkNsToDocker sends peer link into Docker
SetPeerLinkNsToDocker(string, string) error
// SetPeerLinkNsPid sends peer link into container specified by PID
SetPeerLinkNsPid(int) error
// SetPeerLinkNsFd sends peer link into container specified by path
SetPeerLinkNsFd(string) error
// SetPeerLinkNetInNs configures peer link's IP network in network namespace specified by PID
SetPeerLinkNetInNs(int, net.IP, *net.IPNet, *net.IP) error
}
// VethPair is a Link. Veth links are created in pairs called peers.
type VethPair struct {
Link
// Peer network interface
peerIfc *net.Interface
}
// NewVethPair creates a pair of veth network links.
//
// It is equivalent of running:
// ip link add name veth${RANDOM STRING} type veth peer name veth${RANDOM STRING}.
// NewVethPair returns Vether which is initialized to a pointer of type VethPair if the
// veth link was successfully created on Linux host. Newly created pair of veth links
// are assigned random names starting with "veth".
// NewVethPair returns error if the veth pair could not be created.
func NewVethPair() (Vether, error) {
ifcName := makeNetInterfaceName("veth")
peerName := makeNetInterfaceName("veth")
if err := netlink.NetworkCreateVethPair(ifcName, peerName, 0); 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)
}
peerIfc, err := net.InterfaceByName(peerName)
if err != nil {
return nil, fmt.Errorf("Could not find the new interface: %s", err)
}
return &VethPair{
Link: Link{
ifc: newIfc,
},
peerIfc: peerIfc,
}, nil
}
// NewVethPairWithOptions creates a pair of veth network links.
//
// It is equivalent of running:
// ip link add name ${first device name} type veth peer name ${second device name}
// NewVethPairWithOptions returns Vether which is initialized to a pointer of type VethPair if the
// veth link was successfully created on the Linux host. It accepts VethOptions which allow you to set
// peer interface name. It returns error if the veth pair could not be created.
func NewVethPairWithOptions(ifcName string, opts VethOptions) (Vether, error) {
peerName := opts.PeerName
txQLen := opts.TxQueueLen
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 peerName != "" {
if ok, err := NetInterfaceNameValid(peerName); !ok {
return nil, err
}
if _, err := net.InterfaceByName(peerName); err == nil {
return nil, fmt.Errorf("Interface name %s already assigned on the host", peerName)
}
} else {
peerName = makeNetInterfaceName("veth")
}
if txQLen < 0 {
return nil, fmt.Errorf("TX queue length must be a positive integer: %d", txQLen)
}
if err := netlink.NetworkCreateVethPair(ifcName, peerName, txQLen); 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)
}
peerIfc, err := net.InterfaceByName(peerName)
if err != nil {
return nil, fmt.Errorf("Could not find the new interface: %s", err)
}
return &VethPair{
Link: Link{
ifc: newIfc,
},
peerIfc: peerIfc,
}, nil
}
// NetInterface returns veth link's primary network interface
func (veth *VethPair) NetInterface() *net.Interface {
return veth.ifc
}
// NetInterface returns veth link's peer network interface
func (veth *VethPair) PeerNetInterface() *net.Interface {
return veth.peerIfc
}
// SetPeerLinkUp sets peer link up
func (veth *VethPair) SetPeerLinkUp() error {
return netlink.NetworkLinkUp(veth.peerIfc)
}
// DeletePeerLink deletes peer link. It also deletes the other peer interface in VethPair
func (veth *VethPair) DeletePeerLink() error {
return netlink.NetworkLinkDel(veth.peerIfc.Name)
}
// SetPeerLinkIp configures peer link's IP address
func (veth *VethPair) SetPeerLinkIp(ip net.IP, nw *net.IPNet) error {
return netlink.NetworkLinkAddIp(veth.peerIfc, ip, nw)
}
// SetPeerLinkNsToDocker sends peer link into Docker
func (veth *VethPair) SetPeerLinkNsToDocker(name string, dockerHost string) error {
pid, err := DockerPidByName(name, dockerHost)
if err != nil {
return fmt.Errorf("Failed to find docker %s : %s", name, err)
}
return netlink.NetworkSetNsPid(veth.peerIfc, pid)
}
// SetPeerLinkNsPid sends peer link into container specified by PID
func (veth *VethPair) SetPeerLinkNsPid(nspid int) error {
return netlink.NetworkSetNsPid(veth.peerIfc, nspid)
}
// SetPeerLinkNsFd sends peer link into container specified by path
func (veth *VethPair) SetPeerLinkNsFd(nspath string) error {
fd, err := syscall.Open(nspath, syscall.O_RDONLY, 0)
if err != nil {
return fmt.Errorf("Could not attach to Network namespace: %s", err)
}
return netlink.NetworkSetNsFd(veth.peerIfc, fd)
}
// SetPeerLinkNetInNs configures peer link's IP network in network namespace specified by PID
func (veth *VethPair) SetPeerLinkNetInNs(nspid int, ip net.IP, network *net.IPNet, gw *net.IP) error {
origNs, _ := NetNsHandle(os.Getpid())
defer syscall.Close(int(origNs))
defer system.Setns(origNs, syscall.CLONE_NEWNET)
if err := SetNetNsToPid(nspid); err != nil {
return fmt.Errorf("Setting network namespace failed: %s", err)
}
if err := netlink.NetworkLinkAddIp(veth.peerIfc, ip, network); err != nil {
return fmt.Errorf("Unable to set IP: %s in pid: %d network namespace", ip.String(), nspid)
}
if err := netlink.NetworkLinkUp(veth.peerIfc); err != nil {
return fmt.Errorf("Unable to bring %s interface UP: %d", veth.peerIfc.Name, nspid)
}
if gw != nil {
if err := netlink.AddDefaultGw(gw.String(), veth.peerIfc.Name); err != nil {
return fmt.Errorf("Unable to set Default gateway: %s in pid: %d network namespace", gw.String(), nspid)
}
}
return nil
}