Skip to content

Commit 4bbd8ae

Browse files
committed
Add support for vde+bridge versions compilation
1 parent 06dbaa4 commit 4bbd8ae

32 files changed

+1136
-41
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.idea/
22
katharanp
3+
vde_ext
34
tmp

Makefile

+16-34
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,26 @@
11
#!/usr/bin/make -f
22

3-
PLUGIN_NAME=kathara/katharanp
4-
PLUGIN_CONTAINER=katharanp
5-
63
.PHONY: create-builder delete-builder test all_arm64 all_push_arm64 all_amd64 all_push_amd64
74

8-
all_arm64: test clean_arm64 plugin_arm64 delete-builder
9-
all_push_arm64: all_arm64 push_arm64 delete-builder
5+
clean_%: delete-builder
6+
cd bridge && make clean_$*
7+
cd vde && make clean_$*
8+
9+
all_arm64: create-builder
10+
cd bridge && make all_arm64
11+
cd vde && make all_arm64
1012

11-
all_amd64: test clean_amd64 plugin_amd64 delete-builder
12-
all_push_amd64: all_amd64 push_amd64 delete-builder
13+
all_push_arm64: create-builder
14+
cd bridge && make all_push_arm64
15+
cd vde && make all_push_arm64
1316

14-
test:
15-
cat ./plugin-src/config.json | python3 -m json.tool
17+
all_amd64: create-builder
18+
cd bridge && make all_amd64
19+
cd vde && make all_amd64
1620

17-
clean_%: delete-builder
18-
docker plugin rm -f ${PLUGIN_NAME}:$* || true
19-
docker rm -f ${PLUGIN_CONTAINER}_rootfs || true
20-
rm -rf ./img-src/katharanp
21-
rm -rf ./go-src/src/katharanp
22-
rm -rf ./plugin-src/rootfs
23-
24-
gobuild_docker_%:
25-
docker run -ti --rm -v `pwd`/go-src/:/root/go-src golang:alpine3.18 /bin/sh -c "apk add -U make && cd /root/go-src && make gobuild_$*"
26-
27-
image_%: gobuild_docker_% create-builder
28-
mv ./go-src/src/katharanp ./img-src/
29-
docker buildx build --platform linux/$* --load -t ${PLUGIN_CONTAINER}:rootfs ./img-src/
30-
docker create --platform linux/$* --name ${PLUGIN_CONTAINER}_rootfs ${PLUGIN_CONTAINER}:rootfs
31-
mkdir -p ./plugin-src/rootfs
32-
docker export ${PLUGIN_CONTAINER}_rootfs | tar -x -C ./plugin-src/rootfs
33-
docker rm -vf ${PLUGIN_CONTAINER}_rootfs
34-
docker rmi ${PLUGIN_CONTAINER}:rootfs
35-
36-
plugin_%: image_%
37-
docker plugin create ${PLUGIN_NAME}:$* ./plugin-src/
38-
rm -rf ./plugin-src/rootfs
39-
40-
push_%: clean_% plugin_%
41-
docker plugin push ${PLUGIN_NAME}:$*
21+
all_push_amd64: create-builder
22+
cd bridge && make all_push_amd64
23+
cd vde && make all_push_amd64
4224

4325
create-builder: delete-builder
4426
docker buildx create --name kat-np-builder --use

bridge/Makefile

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/make -f
2+
3+
PLUGIN_NAME=kathara/katharanp
4+
PLUGIN_CONTAINER=katharanp
5+
6+
.PHONY: test all_arm64 all_push_arm64 all_amd64 all_push_amd64
7+
8+
all_arm64: test clean_arm64 plugin_arm64
9+
all_push_arm64: all_arm64 push_arm64
10+
11+
all_amd64: test clean_amd64 plugin_amd64
12+
all_push_amd64: all_amd64 push_amd64
13+
14+
test:
15+
cat ./plugin-src/config.json | python3 -m json.tool
16+
17+
clean_%:
18+
docker plugin rm -f ${PLUGIN_NAME}:$* || true
19+
docker rm -f ${PLUGIN_CONTAINER}_rootfs || true
20+
rm -rf ./img-src/katharanp
21+
rm -rf ./go-src/katharanp
22+
rm -rf ./plugin-src/rootfs
23+
24+
gobuild_docker_%:
25+
docker run -ti --rm -v `pwd`/go-src/:/root/go-src golang:alpine3.14 /bin/sh -c "apk add -U make && cd /root/go-src && make gobuild_$*"
26+
27+
image_%: gobuild_docker_%
28+
mv ./go-src/katharanp ./img-src/
29+
docker buildx build --platform linux/$* --load -t ${PLUGIN_CONTAINER}:rootfs ./img-src/
30+
docker create --platform linux/$* --name ${PLUGIN_CONTAINER}_rootfs ${PLUGIN_CONTAINER}:rootfs
31+
mkdir -p ./plugin-src/rootfs
32+
docker export ${PLUGIN_CONTAINER}_rootfs | tar -x -C ./plugin-src/rootfs
33+
docker rm -vf ${PLUGIN_CONTAINER}_rootfs
34+
docker rmi ${PLUGIN_CONTAINER}:rootfs
35+
36+
plugin_%: image_%
37+
docker plugin create ${PLUGIN_NAME}:$* ./plugin-src/
38+
rm -rf ./plugin-src/rootfs
39+
40+
push_%: clean_% plugin_%
41+
docker plugin push ${PLUGIN_NAME}:$*

bridge/go-src/Makefile

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/make -f
2+
3+
.PHONY: gobuild_%
4+
5+
gobuild_%:
6+
go mod download
7+
GOOS=linux GOARCH=$* go build src/katharanp.go src/common_utils.go src/bridge_utils.go src/veth_utils.go
8+
chmod 777 ./katharanp
9+

bridge/go-src/go.mod

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module github.com/KatharaFramework/NetworkPlugin
2+
3+
replace github.com/Sirupsen/logrus => github.com/sirupsen/logrus v1.8.1
4+
5+
go 1.16
6+
7+
require (
8+
github.com/Microsoft/go-winio v0.5.0 // indirect
9+
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
10+
github.com/docker/go-connections v0.4.0 // indirect
11+
github.com/docker/go-plugins-helpers v0.0.0-20210623094020-7ef169fb8b8e
12+
github.com/docker/libnetwork v0.8.0-dev.2.0.20210525090646-64b7a4574d14
13+
github.com/godbus/dbus/v5 v5.0.4 // indirect
14+
github.com/google/uuid v1.3.0
15+
github.com/ishidawataru/sctp v0.0.0-20210707070123-9a39160e9062 // indirect
16+
github.com/vishvananda/netlink v1.1.0
17+
golang.org/x/net v0.0.0-20210716203947-853a461950ff // indirect
18+
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
19+
gotest.tools/v3 v3.0.3 // indirect
20+
)

bridge/go-src/go.sum

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
2+
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
3+
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
4+
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
5+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
6+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
8+
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
9+
github.com/docker/go-plugins-helpers v0.0.0-20210623094020-7ef169fb8b8e h1:/PFdW1q3vu60M64mEZqAGbJdS5UHxJr/nTwEZ8KTyjs=
10+
github.com/docker/go-plugins-helpers v0.0.0-20210623094020-7ef169fb8b8e/go.mod h1:LFyLie6XcDbyKGeVK6bHe+9aJTYCxWLBg5IrJZOaXKA=
11+
github.com/docker/libnetwork v0.8.0-dev.2.0.20210525090646-64b7a4574d14 h1:GZvuJOpa10/Yl2EinacWoMqJ+XtNPbikclDZvNXBNO8=
12+
github.com/docker/libnetwork v0.8.0-dev.2.0.20210525090646-64b7a4574d14/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
13+
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
14+
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
15+
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
16+
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
17+
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
18+
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
19+
github.com/ishidawataru/sctp v0.0.0-20210707070123-9a39160e9062 h1:G1+wBT0dwjIrBdLy0MIG0i+E4CQxEnedHXdauJEIH6g=
20+
github.com/ishidawataru/sctp v0.0.0-20210707070123-9a39160e9062/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg=
21+
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
22+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
23+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
24+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
25+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
26+
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
27+
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
28+
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
29+
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
30+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
31+
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
32+
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
33+
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
34+
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
35+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
36+
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
37+
golang.org/x/net v0.0.0-20210716203947-853a461950ff h1:j2EK/QoxYNBsXI4R7fQkkRUk8y6wnOBI+6hgPdP/6Ds=
38+
golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
39+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
40+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
41+
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
42+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
43+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
44+
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
45+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
46+
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
47+
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
48+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
49+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
50+
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
51+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
52+
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
53+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
54+
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
55+
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=

bridge/go-src/src/bridge_utils.go

+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/docker/libnetwork/iptables"
8+
"github.com/docker/libnetwork/ns"
9+
"github.com/vishvananda/netlink"
10+
"github.com/vishvananda/netlink/nl"
11+
"golang.org/x/sys/unix"
12+
)
13+
14+
const (
15+
bridgePrefix = "kt"
16+
bridgeLen = 12
17+
)
18+
19+
func getBridgeName(netID string) string {
20+
return bridgePrefix + "-" + netID[:bridgeLen]
21+
}
22+
23+
func createBridge(netID string) (string, error) {
24+
bridgeName := getBridgeName(netID)
25+
26+
exists, err := bridgeInterfaceExists(bridgeName)
27+
if err != nil {
28+
return "", err
29+
}
30+
31+
if !exists {
32+
linkAttrs := netlink.NewLinkAttrs()
33+
linkAttrs.Name = bridgeName
34+
35+
if err := netlink.LinkAdd(&netlink.Bridge{
36+
LinkAttrs: linkAttrs,
37+
}); err != nil {
38+
return "", err
39+
}
40+
}
41+
42+
bridge, err := netlink.LinkByName(bridgeName)
43+
if err != nil {
44+
return "", err
45+
}
46+
47+
var bridgeRule = []string{"-i", bridgeName, "-o", bridgeName, "-j", "ACCEPT"}
48+
49+
// Install rule in IPv4
50+
var iptablev4 = iptables.GetIptable(iptables.IPv4)
51+
if err := iptablev4.ProgramRule(iptables.Filter, "FORWARD", iptables.Append, bridgeRule); err != nil {
52+
return "", err
53+
}
54+
55+
// Install rule in IPv6
56+
var iptablev6 = iptables.GetIptable(iptables.IPv6)
57+
if err := iptablev6.ProgramRule(iptables.Filter, "FORWARD", iptables.Append, bridgeRule); err != nil {
58+
return "", err
59+
}
60+
61+
if err := patchBridge(bridge); err != nil {
62+
return "", err
63+
}
64+
65+
return bridgeName, nil
66+
}
67+
68+
func patchBridge(bridge netlink.Link) error {
69+
// Creates a new RTM_NEWLINK request
70+
// NLM_F_ACK is used to receive acks when operations are executed
71+
req := nl.NewNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
72+
73+
// Search for the bridge interface by its index (and bring it UP too)
74+
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
75+
msg.Change = unix.IFF_UP
76+
msg.Flags = unix.IFF_UP
77+
msg.Index = int32(bridge.Attrs().Index)
78+
req.AddData(msg)
79+
80+
// Patch ageing_time and group_fwd_mask
81+
linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
82+
linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(bridge.Type()))
83+
84+
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
85+
data.AddRtAttr(nl.IFLA_BR_AGEING_TIME, nl.Uint32Attr(0))
86+
data.AddRtAttr(nl.IFLA_BR_GROUP_FWD_MASK, nl.Uint16Attr(0xfff8))
87+
88+
req.AddData(linkInfo)
89+
90+
// Execute the request. NETLINK_ROUTE is used to send link updates.
91+
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
92+
if err != nil {
93+
return err
94+
}
95+
96+
return nil
97+
}
98+
99+
func deleteBridge(netID string) error {
100+
bridgeName := getBridgeName(netID)
101+
102+
bridge, err := netlink.LinkByName(bridgeName)
103+
if err != nil {
104+
return err
105+
}
106+
107+
if err := netlink.LinkDel(bridge); err != nil {
108+
return err
109+
}
110+
111+
var bridgeRule = []string{"-i", bridgeName, "-o", bridgeName, "-j", "ACCEPT"}
112+
113+
// Delete rule in IPv4
114+
var iptablev4 = iptables.GetIptable(iptables.IPv4)
115+
if err := iptablev4.ProgramRule(iptables.Filter, "FORWARD", iptables.Delete, bridgeRule); err != nil {
116+
return err
117+
}
118+
119+
// Delete rule in IPv6
120+
var iptablev6 = iptables.GetIptable(iptables.IPv6)
121+
if err := iptablev6.ProgramRule(iptables.Filter, "FORWARD", iptables.Delete, bridgeRule); err != nil {
122+
return err
123+
}
124+
125+
return nil
126+
}
127+
128+
func attachInterfaceToBridge(bridgeName string, interfaceName string) error {
129+
bridge, err := netlink.LinkByName(bridgeName)
130+
if err != nil {
131+
return err
132+
}
133+
134+
iface, err := netlink.LinkByName(interfaceName)
135+
if err != nil {
136+
return err
137+
}
138+
139+
if err := netlink.LinkSetMaster(iface, bridge); err != nil {
140+
return err
141+
}
142+
if err := netlink.LinkSetUp(iface); err != nil {
143+
return err
144+
}
145+
146+
return nil
147+
}
148+
149+
func bridgeInterfaceExists(name string) (bool, error) {
150+
nlh := ns.NlHandle()
151+
link, err := nlh.LinkByName(name)
152+
153+
if err != nil {
154+
if strings.Contains(err.Error(), "Link not found") {
155+
return false, nil
156+
}
157+
158+
return false, fmt.Errorf("failed to check bridge interface existence: %v", err)
159+
}
160+
161+
if link.Type() == "bridge" {
162+
return true, nil
163+
}
164+
165+
return false, fmt.Errorf("existing interface %s is not a bridge", name)
166+
}

0 commit comments

Comments
 (0)