Skip to content

Commit c1aad57

Browse files
committed
Merge pull request #8 from milosgajdos83/macvtap
2 parents 720ad14 + 96327ec commit c1aad57

8 files changed

+339
-90
lines changed

examples/tenus_macvlanns_linux.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
func main() {
12-
macVlanHost, err := tenus.NewMacVlanLinkWithOptions("eth1", tenus.MacVlanOptions{Mode: "bridge", MacVlanDev: "macvlanHostIfc"})
12+
macVlanHost, err := tenus.NewMacVlanLinkWithOptions("eth1", tenus.MacVlanOptions{Mode: "bridge", Dev: "macvlanHostIfc"})
1313
if err != nil {
1414
log.Fatal(err)
1515
}
@@ -27,7 +27,7 @@ func main() {
2727
fmt.Println(err)
2828
}
2929

30-
macVlanDocker, err := tenus.NewMacVlanLinkWithOptions("eth1", tenus.MacVlanOptions{Mode: "bridge", MacVlanDev: "macvlanDckrIfc"})
30+
macVlanDocker, err := tenus.NewMacVlanLinkWithOptions("eth1", tenus.MacVlanOptions{Mode: "bridge", Dev: "macvlanDckrIfc"})
3131
if err != nil {
3232
log.Fatal(err)
3333
}

examples/tenus_macvtapns_linux.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net"
7+
8+
"github.com/milosgajdos83/tenus"
9+
)
10+
11+
func main() {
12+
macVlanHost, err := tenus.NewMacVlanLinkWithOptions("eth1", tenus.MacVlanOptions{Mode: "bridge", Dev: "macvlnHost"})
13+
if err != nil {
14+
log.Fatal(err)
15+
}
16+
17+
macVlanHostIp, macVlanHostIpNet, err := net.ParseCIDR("10.0.41.2/16")
18+
if err != nil {
19+
log.Fatal(err)
20+
}
21+
22+
if err := macVlanHost.SetLinkIp(macVlanHostIp, macVlanHostIpNet); err != nil {
23+
fmt.Println(err)
24+
}
25+
26+
if err = macVlanHost.SetLinkUp(); err != nil {
27+
fmt.Println(err)
28+
}
29+
30+
macVtapDocker, err := tenus.NewMacVtapLinkWithOptions("eth1", tenus.MacVlanOptions{Mode: "bridge", Dev: "mvtDckrIfc"})
31+
if err != nil {
32+
log.Fatal(err)
33+
}
34+
35+
pid, err := tenus.DockerPidByName("mvtapdckr", "/var/run/docker.sock")
36+
if err != nil {
37+
log.Fatal(err)
38+
}
39+
40+
if err := macVtapDocker.SetLinkNetNsPid(pid); err != nil {
41+
log.Fatal(err)
42+
}
43+
44+
macVtapDckrIp, macVtapDckrIpNet, err := net.ParseCIDR("10.0.41.3/16")
45+
if err != nil {
46+
log.Fatal(err)
47+
}
48+
49+
if err := macVtapDocker.SetLinkNetInNs(pid, macVtapDckrIp, macVtapDckrIpNet, nil); err != nil {
50+
log.Fatal(err)
51+
}
52+
}

macvlan_linux.go

+52-48
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import (
77
"github.com/docker/libcontainer/netlink"
88
)
99

10+
// Default MacVlan mode
11+
const (
12+
default_mode = "bridge"
13+
)
14+
1015
// Supported macvlan modes by tenus package
1116
var MacVlanModes = map[string]bool{
1217
"private": true,
@@ -17,7 +22,7 @@ var MacVlanModes = map[string]bool{
1722
// MacVlanOptions allows you to specify some options for macvlan link.
1823
type MacVlanOptions struct {
1924
// macvlan device name
20-
MacVlanDev string
25+
Dev string
2126
// macvlan mode
2227
Mode string
2328
// MAC address
@@ -47,13 +52,12 @@ type MacVlanLink struct {
4752
// NewMacVlanLink creates macvlan network link
4853
//
4954
// It is equivalent of running:
50-
// ip link add name mc${RANDOM STRING} link ${master interface} type macvlan mode ${mode}
55+
// ip link add name mc${RANDOM STRING} link ${master interface} type macvlan
5156
// NewMacVlanLink returns MacVlaner which is initialized to a pointer of type MacVlanLink if the
5257
// macvlan link was created successfully on the Linux host. Newly created link is assigned
53-
// a random name starting with "mc". It sets the macvlan mode the parameter passed as argument.
54-
// If incorrect network mode is passed as a paramter, it sets the macvlan mode to "bridge".
58+
// a random name starting with "mc". It sets the macvlan mode to "bridge" mode which is a default.
5559
// It returns error if the link could not be created.
56-
func NewMacVlanLink(masterDev string, mode string) (MacVlaner, error) {
60+
func NewMacVlanLink(masterDev string) (MacVlaner, error) {
5761
macVlanDev := makeNetInterfaceName("mc")
5862

5963
if ok, err := NetInterfaceNameValid(masterDev); !ok {
@@ -64,15 +68,7 @@ func NewMacVlanLink(masterDev string, mode string) (MacVlaner, error) {
6468
return nil, fmt.Errorf("Master MAC VLAN device %s does not exist on the host", masterDev)
6569
}
6670

67-
if mode != "" {
68-
if _, ok := MacVlanModes[mode]; !ok {
69-
return nil, fmt.Errorf("Unsupported MacVlan mode specified: %s", mode)
70-
}
71-
} else {
72-
mode = "bridge"
73-
}
74-
75-
if err := netlink.NetworkLinkAddMacVlan(masterDev, macVlanDev, mode); err != nil {
71+
if err := netlink.NetworkLinkAddMacVlan(masterDev, macVlanDev, default_mode); err != nil {
7672
return nil, err
7773
}
7874

@@ -91,7 +87,7 @@ func NewMacVlanLink(masterDev string, mode string) (MacVlaner, error) {
9187
ifc: macVlanIfc,
9288
},
9389
masterIfc: masterIfc,
94-
mode: mode,
90+
mode: default_mode,
9591
}, nil
9692
}
9793

@@ -101,12 +97,9 @@ func NewMacVlanLink(masterDev string, mode string) (MacVlaner, error) {
10197
// It is equivalent of running:
10298
// ip link add name ${macvlan name} link ${master interface} address ${macaddress} type macvlan mode ${mode}
10399
// NewMacVlanLinkWithOptions returns MacVlaner which is initialized to a pointer of type MacVlanLink if the
104-
// macvlan link was created successfully on the Linux host. It returns error if the macvlan link could not be created.
100+
// macvlan link was created successfully on the Linux host. If particular option is empty, it sets default value if possible.
101+
// It returns error if the macvlan link could not be created or if incorrect options have been passed.
105102
func NewMacVlanLinkWithOptions(masterDev string, opts MacVlanOptions) (MacVlaner, error) {
106-
macVlanDev := opts.MacVlanDev
107-
mode := opts.Mode
108-
macaddr := opts.MacAddr
109-
110103
if ok, err := NetInterfaceNameValid(masterDev); !ok {
111104
return nil, err
112105
}
@@ -115,42 +108,23 @@ func NewMacVlanLinkWithOptions(masterDev string, opts MacVlanOptions) (MacVlaner
115108
return nil, fmt.Errorf("Master MAC VLAN device %s does not exist on the host", masterDev)
116109
}
117110

118-
if macVlanDev != "" {
119-
if ok, err := NetInterfaceNameValid(macVlanDev); !ok {
120-
return nil, err
121-
}
122-
123-
if _, err := net.InterfaceByName(macVlanDev); err == nil {
124-
return nil, fmt.Errorf("MAC VLAN device %s already assigned on the host", macVlanDev)
125-
}
126-
} else {
127-
macVlanDev = makeNetInterfaceName("mc")
128-
}
129-
130-
if mode != "" {
131-
if _, ok := MacVlanModes[mode]; !ok {
132-
return nil, fmt.Errorf("Unsupported MacVlan mode specified: %s", mode)
133-
}
134-
} else {
135-
mode = "bridge"
111+
if err := validateMacVlanOptions(&opts); err != nil {
112+
return nil, err
136113
}
137114

138-
if err := netlink.NetworkLinkAddMacVlan(masterDev, macVlanDev, opts.Mode); err != nil {
115+
if err := netlink.NetworkLinkAddMacVlan(masterDev, opts.Dev, opts.Mode); err != nil {
139116
return nil, err
140117
}
141118

142-
macVlanIfc, err := net.InterfaceByName(macVlanDev)
119+
macVlanIfc, err := net.InterfaceByName(opts.Dev)
143120
if err != nil {
144121
return nil, fmt.Errorf("Could not find the new interface: %s", err)
145122
}
146123

147-
if macaddr != "" {
148-
if _, err = net.ParseMAC(macaddr); err == nil {
149-
if err := netlink.NetworkSetMacAddress(macVlanIfc, macaddr); err != nil {
150-
if errDel := DeleteLink(macVlanIfc.Name); err != nil {
151-
return nil, fmt.Errorf("Incorrect options specified. Attempt to delete the link failed: %s",
152-
errDel)
153-
}
124+
if opts.MacAddr != "" {
125+
if err := netlink.NetworkSetMacAddress(macVlanIfc, opts.MacAddr); err != nil {
126+
if errDel := DeleteLink(macVlanIfc.Name); errDel != nil {
127+
return nil, fmt.Errorf("Incorrect options specified. Attempt to delete the link failed: %s", errDel)
154128
}
155129
}
156130
}
@@ -165,7 +139,7 @@ func NewMacVlanLinkWithOptions(masterDev string, opts MacVlanOptions) (MacVlaner
165139
ifc: macVlanIfc,
166140
},
167141
masterIfc: masterIfc,
168-
mode: mode,
142+
mode: opts.Mode,
169143
}, nil
170144
}
171145

@@ -183,3 +157,33 @@ func (macvln *MacVlanLink) MasterNetInterface() *net.Interface {
183157
func (macvln *MacVlanLink) Mode() string {
184158
return macvln.mode
185159
}
160+
161+
func validateMacVlanOptions(opts *MacVlanOptions) error {
162+
if opts.Dev != "" {
163+
if ok, err := NetInterfaceNameValid(opts.Dev); !ok {
164+
return err
165+
}
166+
167+
if _, err := net.InterfaceByName(opts.Dev); err == nil {
168+
return fmt.Errorf("MAC VLAN device %s already assigned on the host", opts.Dev)
169+
}
170+
} else {
171+
opts.Dev = makeNetInterfaceName("mc")
172+
}
173+
174+
if opts.Mode != "" {
175+
if _, ok := MacVlanModes[opts.Mode]; !ok {
176+
return fmt.Errorf("Unsupported MacVlan mode specified: %s", opts.Mode)
177+
}
178+
} else {
179+
opts.Mode = default_mode
180+
}
181+
182+
if opts.MacAddr != "" {
183+
if _, err := net.ParseMAC(opts.MacAddr); err == nil {
184+
return fmt.Errorf("Incorrect MAC ADDRESS specified: %s", opts.MacAddr)
185+
}
186+
}
187+
188+
return nil
189+
}

macvlan_linux_test.go

+9-11
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ import (
77
)
88

99
type macvlnTest struct {
10-
masterDev string
11-
macvlanMode string
10+
masterDev string
1211
}
1312

1413
var macvlnTests = []macvlnTest{
15-
{"master01", "bridge"},
16-
{"master02", "private"},
14+
{"master01"},
1715
}
1816

1917
func Test_NewMacVlanLink(t *testing.T) {
@@ -30,9 +28,9 @@ func Test_NewMacVlanLink(t *testing.T) {
3028
time.Sleep(10 * time.Millisecond)
3129
}
3230

33-
mvln, err := NewMacVlanLink(tt.masterDev, tt.macvlanMode)
31+
mvln, err := NewMacVlanLink(tt.masterDev)
3432
if err != nil {
35-
t.Fatalf("NewMacVlanLink(%s, %s) failed to run: %s", tt.masterDev, tt.macvlanMode, err)
33+
t.Fatalf("NewMacVlanLink(%s) failed to run: %s", tt.masterDev, err)
3634
}
3735

3836
mvlnName := mvln.NetInterface().Name
@@ -49,14 +47,14 @@ func Test_NewMacVlanLink(t *testing.T) {
4947

5048
if testRes.linkType != "macvlan" {
5149
tl.teardown()
52-
t.Fatalf("NewMacVlanLink(%s, %s) failed: expected macvlan, returned %s",
53-
tt.masterDev, tt.macvlanMode, testRes.linkType)
50+
t.Fatalf("NewMacVlanLink(%s) failed: expected macvlan, returned %s",
51+
tt.masterDev, testRes.linkType)
5452
}
5553

56-
if testRes.linkData != tt.macvlanMode {
54+
if testRes.linkData != "bridge" {
5755
tl.teardown()
58-
t.Fatalf("NewMacVlanLink(%s, %s) failed: expected %s, returned %s",
59-
tt.masterDev, tt.macvlanMode, tt.macvlanMode, testRes.linkData)
56+
t.Fatalf("NewMacVlanLink(%s) failed: expected bridge, returned %s",
57+
tt.masterDev, testRes.linkData)
6058
}
6159

6260
if err := tl.teardown(); err != nil {

0 commit comments

Comments
 (0)