Skip to content

Commit 17daef6

Browse files
gwenyaaboch
authored andcommitted
vlan: add support for flags and qos maps
Signed-off-by: Gwendolyn <[email protected]>
1 parent b929916 commit 17daef6

File tree

4 files changed

+310
-3
lines changed

4 files changed

+310
-3
lines changed

link.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,15 @@ func (bridge *Bridge) Type() string {
290290
// Vlan links have ParentIndex set in their Attrs()
291291
type Vlan struct {
292292
LinkAttrs
293-
VlanId int
294-
VlanProtocol VlanProtocol
293+
VlanId int
294+
VlanProtocol VlanProtocol
295+
IngressQosMap map[uint32]uint32
296+
EgressQosMap map[uint32]uint32
297+
ReorderHdr *bool
298+
Gvrp *bool
299+
LooseBinding *bool
300+
Mvrp *bool
301+
BridgeBinding *bool
295302
}
296303

297304
func (vlan *Vlan) Attrs() *LinkAttrs {

link_linux.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,6 +1683,73 @@ func (h *Handle) linkModify(link Link, flags int) error {
16831683
native.PutUint16(b, uint16(link.VlanId))
16841684
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
16851685
data.AddRtAttr(nl.IFLA_VLAN_ID, b)
1686+
var vlanFlags uint32
1687+
var vlanFlagsMask uint32
1688+
if link.ReorderHdr != nil {
1689+
vlanFlagsMask |= nl.VLAN_FLAG_REORDER_HDR
1690+
if *link.ReorderHdr {
1691+
vlanFlags |= nl.VLAN_FLAG_REORDER_HDR
1692+
} else {
1693+
vlanFlags &= ^uint32(nl.VLAN_FLAG_REORDER_HDR)
1694+
}
1695+
}
1696+
if link.Gvrp != nil {
1697+
vlanFlagsMask |= nl.VLAN_FLAG_GVRP
1698+
if *link.Gvrp {
1699+
vlanFlags |= nl.VLAN_FLAG_GVRP
1700+
} else {
1701+
vlanFlags &= ^uint32(nl.VLAN_FLAG_GVRP)
1702+
}
1703+
}
1704+
if link.Mvrp != nil {
1705+
vlanFlagsMask |= nl.VLAN_FLAG_MVRP
1706+
if *link.Mvrp {
1707+
vlanFlags |= nl.VLAN_FLAG_MVRP
1708+
} else {
1709+
vlanFlags &= ^uint32(nl.VLAN_FLAG_MVRP)
1710+
}
1711+
}
1712+
if link.LooseBinding != nil {
1713+
vlanFlagsMask |= nl.VLAN_FLAG_LOOSE_BINDING
1714+
if *link.LooseBinding {
1715+
vlanFlags |= nl.VLAN_FLAG_LOOSE_BINDING
1716+
} else {
1717+
vlanFlags &= ^uint32(nl.VLAN_FLAG_LOOSE_BINDING)
1718+
}
1719+
}
1720+
if link.BridgeBinding != nil {
1721+
vlanFlagsMask |= nl.VLAN_FLAG_BRIDGE_BINDING
1722+
if *link.BridgeBinding {
1723+
vlanFlags |= nl.VLAN_FLAG_BRIDGE_BINDING
1724+
} else {
1725+
vlanFlags &= ^uint32(nl.VLAN_FLAG_BRIDGE_BINDING)
1726+
}
1727+
}
1728+
1729+
buf := &bytes.Buffer{}
1730+
buf.Write(nl.Uint32Attr(vlanFlags))
1731+
buf.Write(nl.Uint32Attr(vlanFlagsMask))
1732+
data.AddRtAttr(nl.IFLA_VLAN_FLAGS, buf.Bytes())
1733+
1734+
if link.IngressQosMap != nil {
1735+
ingressMap := data.AddRtAttr(nl.IFLA_VLAN_INGRESS_QOS, nil)
1736+
for from, to := range link.IngressQosMap {
1737+
buf := &bytes.Buffer{}
1738+
buf.Write(nl.Uint32Attr(from))
1739+
buf.Write(nl.Uint32Attr(to))
1740+
ingressMap.AddRtAttr(nl.IFLA_VLAN_QOS_MAPPING, buf.Bytes())
1741+
}
1742+
}
1743+
1744+
if link.EgressQosMap != nil {
1745+
egressMap := data.AddRtAttr(nl.IFLA_VLAN_EGRESS_QOS, nil)
1746+
for from, to := range link.EgressQosMap {
1747+
buf := &bytes.Buffer{}
1748+
buf.Write(nl.Uint32Attr(from))
1749+
buf.Write(nl.Uint32Attr(to))
1750+
egressMap.AddRtAttr(nl.IFLA_VLAN_QOS_MAPPING, buf.Bytes())
1751+
}
1752+
}
16861753

16871754
if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
16881755
data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
@@ -2801,12 +2868,65 @@ func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) {
28012868
}
28022869
}
28032870

2871+
func parseVlanQosMap(data []byte) map[uint32]uint32 {
2872+
values, err := nl.ParseRouteAttr(data)
2873+
if err != nil {
2874+
return nil
2875+
}
2876+
2877+
qosMap := make(map[uint32]uint32)
2878+
2879+
for _, value := range values {
2880+
switch value.Attr.Type {
2881+
case nl.IFLA_VLAN_QOS_MAPPING:
2882+
from := native.Uint32(value.Value[:4])
2883+
to := native.Uint32(value.Value[4:])
2884+
qosMap[from] = to
2885+
}
2886+
}
2887+
2888+
return qosMap
2889+
}
2890+
28042891
func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
28052892
vlan := link.(*Vlan)
28062893
for _, datum := range data {
28072894
switch datum.Attr.Type {
28082895
case nl.IFLA_VLAN_ID:
28092896
vlan.VlanId = int(native.Uint16(datum.Value[0:2]))
2897+
case nl.IFLA_VLAN_FLAGS:
2898+
flags := native.Uint32(datum.Value[0:4])
2899+
trueVal := true
2900+
falseVal := false
2901+
if flags&nl.VLAN_FLAG_REORDER_HDR != 0 {
2902+
vlan.ReorderHdr = &trueVal
2903+
} else {
2904+
vlan.ReorderHdr = &falseVal
2905+
}
2906+
if flags&nl.VLAN_FLAG_GVRP != 0 {
2907+
vlan.Gvrp = &trueVal
2908+
} else {
2909+
vlan.Gvrp = &falseVal
2910+
}
2911+
if flags&nl.VLAN_FLAG_LOOSE_BINDING != 0 {
2912+
vlan.LooseBinding = &trueVal
2913+
} else {
2914+
vlan.LooseBinding = &falseVal
2915+
}
2916+
if flags&nl.VLAN_FLAG_MVRP != 0 {
2917+
vlan.Mvrp = &trueVal
2918+
} else {
2919+
vlan.Mvrp = &falseVal
2920+
}
2921+
if flags&nl.VLAN_FLAG_BRIDGE_BINDING != 0 {
2922+
vlan.BridgeBinding = &trueVal
2923+
} else {
2924+
vlan.BridgeBinding = &falseVal
2925+
}
2926+
case nl.IFLA_VLAN_EGRESS_QOS:
2927+
vlan.EgressQosMap = parseVlanQosMap(datum.Value)
2928+
case nl.IFLA_VLAN_INGRESS_QOS:
2929+
vlan.IngressQosMap = parseVlanQosMap(datum.Value)
28102930
case nl.IFLA_VLAN_PROTOCOL:
28112931
vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2])))
28122932
}

link_test.go

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"net"
1111
"os"
1212
"os/exec"
13+
"reflect"
1314
"sort"
1415
"strings"
1516
"syscall"
@@ -919,13 +920,178 @@ func TestLinkAddDelVlan(t *testing.T) {
919920
t.Fatal(err)
920921
}
921922

922-
testLinkAddDel(t, &Vlan{LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}, 900, VLAN_PROTOCOL_8021Q})
923+
testLinkAddDel(t, &Vlan{
924+
LinkAttrs: LinkAttrs{
925+
Name: "bar",
926+
ParentIndex: parent.Attrs().Index,
927+
},
928+
VlanId: 900,
929+
VlanProtocol: VLAN_PROTOCOL_8021Q,
930+
})
923931

924932
if err := LinkDel(parent); err != nil {
925933
t.Fatal(err)
926934
}
927935
}
928936

937+
func TestLinkAddVlanWithQosMaps(t *testing.T) {
938+
tearDown := setUpNetlinkTest(t)
939+
defer tearDown()
940+
941+
parent := &Dummy{LinkAttrs{Name: "foo"}}
942+
if err := LinkAdd(parent); err != nil {
943+
t.Fatal(err)
944+
}
945+
946+
ingressMap := map[uint32]uint32{
947+
0: 2,
948+
1: 3,
949+
2: 5,
950+
}
951+
952+
egressMap := map[uint32]uint32{
953+
1: 3,
954+
2: 5,
955+
3: 7,
956+
}
957+
958+
vlan := &Vlan{
959+
LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
960+
VlanId: 900,
961+
VlanProtocol: VLAN_PROTOCOL_8021Q,
962+
IngressQosMap: ingressMap,
963+
EgressQosMap: egressMap,
964+
}
965+
if err := LinkAdd(vlan); err != nil {
966+
t.Fatal(err)
967+
}
968+
969+
link, err := LinkByName("bar")
970+
if err != nil {
971+
t.Fatal(err)
972+
}
973+
974+
if vlan, ok := link.(*Vlan); !ok {
975+
t.Fatalf("unexpected link type: %T", link)
976+
} else {
977+
if !reflect.DeepEqual(vlan.IngressQosMap, ingressMap) {
978+
t.Fatalf("expected ingress qos map to be %v, got %v", ingressMap, vlan.IngressQosMap)
979+
}
980+
if !reflect.DeepEqual(vlan.EgressQosMap, egressMap) {
981+
t.Fatalf("expected egress qos map to be %v, got %v", egressMap, vlan.EgressQosMap)
982+
}
983+
}
984+
}
985+
986+
func TestLinkAddVlanWithFlags(t *testing.T) {
987+
tearDown := setUpNetlinkTest(t)
988+
defer tearDown()
989+
990+
parent := &Dummy{LinkAttrs{Name: "foo"}}
991+
if err := LinkAdd(parent); err != nil {
992+
t.Fatal(err)
993+
}
994+
valueTrue := true
995+
valueFalse := false
996+
vlan := &Vlan{
997+
LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
998+
VlanId: 900,
999+
VlanProtocol: VLAN_PROTOCOL_8021Q,
1000+
Gvrp: &valueTrue,
1001+
Mvrp: &valueFalse,
1002+
BridgeBinding: &valueFalse,
1003+
LooseBinding: &valueFalse,
1004+
ReorderHdr: &valueTrue,
1005+
}
1006+
if err := LinkAdd(vlan); err != nil {
1007+
t.Fatal(err)
1008+
}
1009+
1010+
link, err := LinkByName("bar")
1011+
if err != nil {
1012+
t.Fatal(err)
1013+
}
1014+
1015+
if vlan, ok := link.(*Vlan); !ok {
1016+
t.Fatalf("unexpected link type: %T", link)
1017+
} else {
1018+
if vlan.Gvrp == nil || *vlan.Gvrp != true {
1019+
t.Fatalf("expected gvrp to be true, got %v", vlan.Gvrp)
1020+
}
1021+
if vlan.Mvrp == nil || *vlan.Mvrp != false {
1022+
t.Fatalf("expected mvrp to be false, got %v", vlan.Mvrp)
1023+
}
1024+
if vlan.BridgeBinding == nil || *vlan.BridgeBinding != false {
1025+
t.Fatalf("expected bridge binding to be false, got %v", vlan.BridgeBinding)
1026+
}
1027+
if vlan.LooseBinding == nil || *vlan.LooseBinding != false {
1028+
t.Fatalf("expected loose binding to be false, got %v", vlan.LooseBinding)
1029+
}
1030+
if vlan.ReorderHdr == nil || *vlan.ReorderHdr != true {
1031+
t.Fatalf("expected reorder hdr to be true, got %v", vlan.ReorderHdr)
1032+
}
1033+
}
1034+
}
1035+
1036+
func TestLinkModifyVlanFlags(t *testing.T) {
1037+
tearDown := setUpNetlinkTest(t)
1038+
defer tearDown()
1039+
1040+
parent := &Dummy{LinkAttrs{Name: "foo"}}
1041+
if err := LinkAdd(parent); err != nil {
1042+
t.Fatal(err)
1043+
}
1044+
valueTrue := true
1045+
valueFalse := false
1046+
vlan := &Vlan{
1047+
LinkAttrs: LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index},
1048+
VlanId: 900,
1049+
VlanProtocol: VLAN_PROTOCOL_8021Q,
1050+
Gvrp: &valueTrue,
1051+
Mvrp: &valueFalse,
1052+
BridgeBinding: &valueFalse,
1053+
LooseBinding: &valueFalse,
1054+
ReorderHdr: &valueTrue,
1055+
}
1056+
if err := LinkAdd(vlan); err != nil {
1057+
t.Fatal(err)
1058+
}
1059+
1060+
vlan = &Vlan{
1061+
LinkAttrs: LinkAttrs{Name: "bar"},
1062+
BridgeBinding: &valueTrue,
1063+
}
1064+
1065+
if err := LinkModify(vlan); err != nil {
1066+
t.Fatal(err)
1067+
}
1068+
1069+
link, err := LinkByName("bar")
1070+
if err != nil {
1071+
t.Fatal(err)
1072+
}
1073+
1074+
if vlan, ok := link.(*Vlan); !ok {
1075+
t.Fatalf("unexpected link type: %T", link)
1076+
} else {
1077+
if vlan.Gvrp == nil || *vlan.Gvrp != true {
1078+
t.Fatalf("expected gvrp to be true, got %v", vlan.Gvrp)
1079+
}
1080+
if vlan.Mvrp == nil || *vlan.Mvrp != false {
1081+
t.Fatalf("expected mvrp to be false, got %v", vlan.Mvrp)
1082+
}
1083+
if vlan.BridgeBinding == nil || *vlan.BridgeBinding != true {
1084+
t.Fatalf("expected bridge binding to be true, got %v", vlan.BridgeBinding)
1085+
}
1086+
if vlan.LooseBinding == nil || *vlan.LooseBinding != false {
1087+
t.Fatalf("expected loose binding to be false, got %v", vlan.LooseBinding)
1088+
}
1089+
if vlan.ReorderHdr == nil || *vlan.ReorderHdr != true {
1090+
t.Fatalf("expected reorder hdr to be true, got %v", vlan.ReorderHdr)
1091+
}
1092+
}
1093+
}
1094+
9291095
func TestLinkAddDelMacvlan(t *testing.T) {
9301096
tearDown := setUpNetlinkTest(t)
9311097
defer tearDown()

nl/link_linux.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ const (
3131
IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL
3232
)
3333

34+
const (
35+
IFLA_VLAN_QOS_UNSPEC = iota
36+
IFLA_VLAN_QOS_MAPPING
37+
IFLA_VLAN_QOS_MAX = IFLA_VLAN_QOS_MAPPING
38+
)
39+
40+
const (
41+
VLAN_FLAG_REORDER_HDR = 1 << iota
42+
VLAN_FLAG_GVRP
43+
VLAN_FLAG_LOOSE_BINDING
44+
VLAN_FLAG_MVRP
45+
VLAN_FLAG_BRIDGE_BINDING
46+
)
47+
3448
const (
3549
IFLA_NETKIT_UNSPEC = iota
3650
IFLA_NETKIT_PEER_INFO

0 commit comments

Comments
 (0)