Skip to content

Commit

Permalink
Merge pull request AliyunContainerService#81 from zhiyuan0x/bugfix/ip…
Browse files Browse the repository at this point in the history
…vlan

ipvlan: support vm based container and fix bugs
  • Loading branch information
BSWANG authored Dec 23, 2019
2 parents 161324c + 2c92cbe commit 0576c9a
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 12 deletions.
4 changes: 2 additions & 2 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 55 additions & 10 deletions plugin/driver/ipvlan.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ func (driver *ipvlanDriver) createSlaveIfNotExist(parentLink netlink.Link, slave
return nil, errors.Wrapf(err, "%s, add device %s error with another list device error %v",
driver.name, slaveName, e)
}

return link, nil
}

Expand Down Expand Up @@ -338,32 +339,74 @@ func (rule *redirectRule) isMatch(filter netlink.Filter) bool {
if len(u32.Sel.Keys) != 1 {
return false
}
if len(u32.Actions) != 1 {
return false
}

key := u32.Sel.Keys[0]
if key.Mask != rule.mask || key.Off != rule.offset || key.Val != rule.value {
return false
}

act, ok := u32.Actions[0].(*netlink.MirredAction)
return rule.isMatchActions(u32.Actions)
}

func (rule *redirectRule) isMatchActions(acts []netlink.Action) bool {
if len(acts) != 3 {
return false
}

tun, ok := acts[0].(*netlink.TunnelKeyAction)
if !ok {
return false
}
if act.Ifindex != rule.dstIndex || act.MirredAction != rule.redir {
if tun.Attrs().Action != netlink.TC_ACT_PIPE {
return false
}
if tun.Action != netlink.TCA_TUNNEL_KEY_UNSET {
return false
}

skbedit, ok := acts[1].(*netlink.SkbEditAction)
if !ok {
return false
}
if skbedit.Attrs().Action != netlink.TC_ACT_PIPE {
return false
}
if skbedit.PType == nil || *skbedit.PType != uint16(unix.PACKET_HOST) {
return false
}

mirred, ok := acts[2].(*netlink.MirredAction)
if !ok {
return false
}
if mirred.Attrs().Action != netlink.TC_ACT_STOLEN {
return false
}
if mirred.MirredAction != rule.redir {
return false
}
if mirred.Ifindex != rule.dstIndex {
return false
}

return true
}

func (rule *redirectRule) toU32Filter() *netlink.U32 {
func (rule *redirectRule) toActions() []netlink.Action {
mirredAct := netlink.NewMirredAction(rule.dstIndex)
mirredAct.MirredAction = netlink.TCA_INGRESS_REDIR

tunAct := netlink.NewTunnelKeyAction()
tunAct.Action = netlink.TCA_TUNNEL_KEY_UNSET

skbedit := netlink.NewSkbEditAction()
ptype := uint16(unix.PACKET_HOST)
skbedit.PType = &ptype

return []netlink.Action{tunAct, skbedit, mirredAct}
}

func (rule *redirectRule) toU32Filter() *netlink.U32 {
return &netlink.U32{
FilterAttrs: netlink.FilterAttrs{
LinkIndex: rule.index,
Expand All @@ -381,10 +424,7 @@ func (rule *redirectRule) toU32Filter() *netlink.U32 {
},
},
},
Actions: []netlink.Action{
tunAct,
mirredAct,
},
Actions: rule.toActions(),
}
}

Expand Down Expand Up @@ -441,6 +481,11 @@ func (driver *ipvlanDriver) setupInitNamespace(
return errors.Wrapf(err, "%s, set device %s up error", driver.name, slaveLink.Attrs().Name)
}
}
if slaveLink.Attrs().Flags&unix.IFF_NOARP == 0 {
if err := netlink.LinkSetARPOff(slaveLink); err != nil {
return errors.Wrapf(err, "%s, set device %s noarp error", driver.name, slaveLink.Attrs().Name)
}
}

ipNet := &net.IPNet{
IP: hostIP,
Expand Down
120 changes: 120 additions & 0 deletions plugin/driver/ipvlan_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package driver

import (
"net"
"os"
"runtime"
"testing"

"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
)

type tearDownNetlinkTest func()

func skipUnlessRoot(t *testing.T) {
if os.Getuid() != 0 {
t.Skip("Test requires root privileges.")
}
}

func setUpNetlinkTest(t *testing.T) tearDownNetlinkTest {
skipUnlessRoot(t)

// new temporary namespace so we don't pollute the host
// lock thread since the namespace is thread local
runtime.LockOSThread()
var err error
ns, err := netns.New()
if err != nil {
t.Fatal("Failed to create newns", ns)
}

return func() {
ns.Close()
runtime.UnlockOSThread()
}
}

func TestRedirectRule(t *testing.T) {
teardown := setUpNetlinkTest(t)
defer teardown()

foo := &netlink.Ifb{
LinkAttrs: netlink.LinkAttrs{
Name: "foo",
},
}
if err := netlink.LinkAdd(foo); err != nil {
t.Fatal(err)
}

bar := &netlink.Ifb{
LinkAttrs: netlink.LinkAttrs{
Name: "bar",
},
}
if err := netlink.LinkAdd(bar); err != nil {
t.Fatal(err)
}

link, err := netlink.LinkByName("foo")
if err != nil {
t.Fatal(err)
}
if err := netlink.LinkSetUp(link); err != nil {
t.Fatal(err)
}
redir, err := netlink.LinkByName("bar")
if err != nil {
t.Fatal(err)
}
if err := netlink.LinkSetUp(redir); err != nil {
t.Fatal(err)
}

// add qdisc
qdisc := &netlink.GenericQdisc{
QdiscAttrs: netlink.QdiscAttrs{
LinkIndex: link.Attrs().Index,
Parent: netlink.HANDLE_CLSACT,
Handle: netlink.HANDLE_CLSACT & 0xffff0000,
},
QdiscType: "clsact",
}
if err := netlink.QdiscAdd(qdisc); err != nil {
t.Fatalf("add qdisc error, %s", err)
}

// add filter
parent := uint32(netlink.HANDLE_CLSACT&0xffff0000 | netlink.HANDLE_MIN_EGRESS&0x0000ffff)

_, cidr, err := net.ParseCIDR("192.168.0.0/16")
if err != nil {
t.Fatalf("parse cidr error, %v", err)
}

rule, err := dstIPRule(link.Attrs().Index, cidr, redir.Attrs().Index, netlink.TCA_INGRESS_REDIR)
if err != nil {
t.Fatalf("failed to create rule, %v", err)
}

u32 := rule.toU32Filter()
u32.Parent = parent
if err := netlink.FilterAdd(u32); err != nil {
t.Fatalf("failed to add filter, %v", err)
}

// get filter
filters, err := netlink.FilterList(link, parent)
if err != nil {
t.Fatalf("failed to list filter, %v", err)
}
if len(filters) != 1 {
t.Fatalf("filters not match")
}

if !rule.isMatch(filters[0]) {
t.Fatalf("filter not match the rule")
}
}
24 changes: 24 additions & 0 deletions vendor/github.com/vishvananda/netlink/filter.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions vendor/github.com/vishvananda/netlink/filter_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions vendor/github.com/vishvananda/netlink/nl/tc_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 0576c9a

Please sign in to comment.