Skip to content

Commit 68cf136

Browse files
wangling94aboch
authored andcommitted
1. filter match support vlanId and srcMac, dstMac.
2. filter action support vlan pop/push.
1 parent 56a588b commit 68cf136

File tree

4 files changed

+245
-5
lines changed

4 files changed

+245
-5
lines changed

filter.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,35 @@ func NewCsumAction() *CsumAction {
231231
}
232232
}
233233

234+
type VlanAct int8
235+
236+
type VlanAction struct {
237+
ActionAttrs
238+
Action VlanAct
239+
VlanID uint16
240+
}
241+
242+
const (
243+
TCA_VLAN_ACT_POP VlanAct = 1
244+
TCA_VLAN_ACT_PUSH VlanAct = 2
245+
)
246+
247+
func (action *VlanAction) Type() string {
248+
return "vlan"
249+
}
250+
251+
func (action *VlanAction) Attrs() *ActionAttrs {
252+
return &action.ActionAttrs
253+
}
254+
255+
func NewVlanAction() *VlanAction {
256+
return &VlanAction{
257+
ActionAttrs: ActionAttrs{
258+
Action: TC_ACT_PIPE,
259+
},
260+
}
261+
}
262+
234263
type MirredAct uint8
235264

236265
func (a MirredAct) String() string {

filter_linux.go

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ type Flower struct {
6565
EncSrcIPMask net.IPMask
6666
EncDestPort uint16
6767
EncKeyId uint32
68+
SrcMac net.HardwareAddr
69+
DestMac net.HardwareAddr
70+
VlanId uint16
6871
SkipHw bool
6972
SkipSw bool
7073
IPProto *nl.IPProto
@@ -135,6 +138,15 @@ func (filter *Flower) encode(parent *nl.RtAttr) error {
135138
if filter.EncKeyId != 0 {
136139
parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
137140
}
141+
if filter.SrcMac != nil {
142+
parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_SRC, filter.SrcMac)
143+
}
144+
if filter.DestMac != nil {
145+
parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_DST, filter.DestMac)
146+
}
147+
if filter.VlanId != 0 {
148+
parent.AddRtAttr(nl.TCA_FLOWER_KEY_VLAN_ID, nl.Uint16Attr(filter.VlanId))
149+
}
138150
if filter.IPProto != nil {
139151
ipproto := *filter.IPProto
140152
parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize())
@@ -201,6 +213,13 @@ func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
201213
filter.EncDestPort = ntohs(datum.Value)
202214
case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
203215
filter.EncKeyId = ntohl(datum.Value)
216+
case nl.TCA_FLOWER_KEY_ETH_SRC:
217+
filter.SrcMac = datum.Value
218+
case nl.TCA_FLOWER_KEY_ETH_DST:
219+
filter.DestMac = datum.Value
220+
case nl.TCA_FLOWER_KEY_VLAN_ID:
221+
filter.VlanId = native.Uint16(datum.Value[0:2])
222+
filter.EthType = unix.ETH_P_8021Q
204223
case nl.TCA_FLOWER_KEY_IP_PROTO:
205224
val := new(nl.IPProto)
206225
*val = nl.IPProto(datum.Value[0])
@@ -622,6 +641,22 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
622641
}
623642
toTcGen(action.Attrs(), &mirred.TcGen)
624643
aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize())
644+
case *VlanAction:
645+
table := attr.AddRtAttr(tabIndex, nil)
646+
tabIndex++
647+
table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("vlan"))
648+
aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
649+
vlan := nl.TcVlan{
650+
Action: int32(action.Action),
651+
}
652+
toTcGen(action.Attrs(), &vlan.TcGen)
653+
aopts.AddRtAttr(nl.TCA_VLAN_PARMS, vlan.Serialize())
654+
if action.Action == TCA_VLAN_ACT_PUSH && action.VlanID == 0 {
655+
return fmt.Errorf("vlan id is required for push action")
656+
}
657+
if action.VlanID != 0 {
658+
aopts.AddRtAttr(nl.TCA_VLAN_PUSH_VLAN_ID, nl.Uint16Attr(action.VlanID))
659+
}
625660
case *TunnelKeyAction:
626661
table := attr.AddRtAttr(tabIndex, nil)
627662
tabIndex++
@@ -792,6 +827,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
792827
action = &CsumAction{}
793828
case "gact":
794829
action = &GenericAction{}
830+
case "vlan":
831+
action = &VlanAction{}
795832
case "tunnel_key":
796833
action = &TunnelKeyAction{}
797834
case "skbedit":
@@ -822,7 +859,17 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
822859
tcTs := nl.DeserializeTcf(adatum.Value)
823860
actionTimestamp = toTimeStamp(tcTs)
824861
}
825-
862+
case "vlan":
863+
switch adatum.Attr.Type {
864+
case nl.TCA_VLAN_PARMS:
865+
vlan := *nl.DeserializeTcVlan(adatum.Value)
866+
action.(*VlanAction).ActionAttrs = ActionAttrs{}
867+
toAttrs(&vlan.TcGen, action.Attrs())
868+
action.(*VlanAction).Action = VlanAct(vlan.Action)
869+
case nl.TCA_VLAN_PUSH_VLAN_ID:
870+
vlanId := native.Uint16(adatum.Value[0:2])
871+
action.(*VlanAction).VlanID = vlanId
872+
}
826873
case "tunnel_key":
827874
switch adatum.Attr.Type {
828875
case nl.TCA_TUNNEL_KEY_PARMS:

filter_test.go

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,14 @@ func TestFilterFlowerAddDel(t *testing.T) {
17681768
}
17691769

17701770
testMask := net.CIDRMask(24, 32)
1771+
srcMac, err := net.ParseMAC("2C:54:91:88:C9:E3")
1772+
if err != nil {
1773+
t.Fatal(err)
1774+
}
1775+
destMac, err := net.ParseMAC("2C:54:91:88:C9:E5")
1776+
if err != nil {
1777+
t.Fatal(err)
1778+
}
17711779

17721780
ipproto := new(nl.IPProto)
17731781
*ipproto = nl.IPPROTO_TCP
@@ -1790,10 +1798,19 @@ func TestFilterFlowerAddDel(t *testing.T) {
17901798
EncSrcIPMask: testMask,
17911799
EncDestPort: 8472,
17921800
EncKeyId: 1234,
1801+
SrcMac: srcMac,
1802+
DestMac: destMac,
17931803
IPProto: ipproto,
17941804
DestPort: 1111,
17951805
SrcPort: 1111,
17961806
Actions: []Action{
1807+
&VlanAction{
1808+
ActionAttrs: ActionAttrs{
1809+
Action: TC_ACT_PIPE,
1810+
},
1811+
Action: TCA_VLAN_ACT_PUSH,
1812+
VlanID: 1234,
1813+
},
17971814
&MirredAction{
17981815
ActionAttrs: ActionAttrs{
17991816
Action: TC_ACT_STOLEN,
@@ -1871,8 +1888,31 @@ func TestFilterFlowerAddDel(t *testing.T) {
18711888
if filter.SrcPort != flower.SrcPort {
18721889
t.Fatalf("Flower SrcPort doesn't match")
18731890
}
1891+
if !(filter.SrcMac.String() == flower.SrcMac.String()) {
1892+
t.Fatalf("Flower SrcMac doesn't match")
1893+
}
1894+
if !(filter.DestMac.String() == flower.DestMac.String()) {
1895+
t.Fatalf("Flower DestMac doesn't match")
1896+
}
18741897

1875-
mia, ok := flower.Actions[0].(*MirredAction)
1898+
vla, ok := flower.Actions[0].(*VlanAction)
1899+
if !ok {
1900+
t.Fatal("Unable to find vlan action")
1901+
}
1902+
1903+
if vla.Attrs().Action != TC_ACT_PIPE {
1904+
t.Fatal("Vlan action isn't TC_ACT_PIPE")
1905+
}
1906+
1907+
if vla.Action != TCA_VLAN_ACT_PUSH {
1908+
t.Fatal("Second Vlan action isn't push")
1909+
}
1910+
1911+
if vla.VlanID != 1234 {
1912+
t.Fatal("Second Vlan action vlanId isn't correct")
1913+
}
1914+
1915+
mia, ok := flower.Actions[1].(*MirredAction)
18761916
if !ok {
18771917
t.Fatal("Unable to find mirred action")
18781918
}
@@ -1889,7 +1929,7 @@ func TestFilterFlowerAddDel(t *testing.T) {
18891929
t.Fatal("Incorrect mirred action stats")
18901930
}
18911931

1892-
ga, ok := flower.Actions[1].(*GenericAction)
1932+
ga, ok := flower.Actions[2].(*GenericAction)
18931933
if !ok {
18941934
t.Fatal("Unable to find generic action")
18951935
}
@@ -1917,6 +1957,94 @@ func TestFilterFlowerAddDel(t *testing.T) {
19171957
t.Fatal("Failed to remove filter")
19181958
}
19191959

1960+
filter = &Flower{
1961+
FilterAttrs: FilterAttrs{
1962+
LinkIndex: link.Attrs().Index,
1963+
Parent: MakeHandle(0xffff, 0),
1964+
Priority: 1,
1965+
Protocol: unix.ETH_P_8021Q,
1966+
},
1967+
EthType: unix.ETH_P_8021Q,
1968+
VlanId: 2046,
1969+
Actions: []Action{
1970+
&VlanAction{
1971+
ActionAttrs: ActionAttrs{
1972+
Action: TC_ACT_PIPE,
1973+
},
1974+
Action: TCA_VLAN_ACT_POP,
1975+
},
1976+
&MirredAction{
1977+
ActionAttrs: ActionAttrs{
1978+
Action: TC_ACT_STOLEN,
1979+
},
1980+
MirredAction: TCA_EGRESS_REDIR,
1981+
Ifindex: redir.Attrs().Index,
1982+
},
1983+
},
1984+
}
1985+
1986+
if err := FilterAdd(filter); err != nil {
1987+
t.Fatal(err)
1988+
}
1989+
1990+
time.Sleep(time.Second)
1991+
filters, err = FilterList(link, MakeHandle(0xffff, 0))
1992+
if err != nil {
1993+
t.Fatal(err)
1994+
}
1995+
if len(filters) != 1 {
1996+
t.Fatal("Failed to add filter")
1997+
}
1998+
flower, ok = filters[0].(*Flower)
1999+
if !ok {
2000+
t.Fatal("Filter is the wrong type")
2001+
}
2002+
2003+
if filter.VlanId != flower.VlanId {
2004+
t.Fatalf("Flower VlanId doesn't match")
2005+
}
2006+
2007+
vla, ok = flower.Actions[0].(*VlanAction)
2008+
if !ok {
2009+
t.Fatal("Unable to find vlan action")
2010+
}
2011+
2012+
if vla.Attrs().Action != TC_ACT_PIPE {
2013+
t.Fatal("Vlan action isn't TC_ACT_PIPE")
2014+
}
2015+
2016+
if vla.Action != TCA_VLAN_ACT_POP {
2017+
t.Fatal("First Vlan action isn't pop")
2018+
}
2019+
2020+
mia, ok = flower.Actions[1].(*MirredAction)
2021+
if !ok {
2022+
t.Fatal("Unable to find mirred action")
2023+
}
2024+
2025+
if mia.Attrs().Action != TC_ACT_STOLEN {
2026+
t.Fatal("Mirred action isn't TC_ACT_STOLEN")
2027+
}
2028+
2029+
if mia.Timestamp == nil || mia.Timestamp.Installed == 0 {
2030+
t.Fatal("Incorrect mirred action timestamp")
2031+
}
2032+
2033+
if mia.Statistics == nil {
2034+
t.Fatal("Incorrect mirred action stats")
2035+
}
2036+
2037+
if err := FilterDel(filter); err != nil {
2038+
t.Fatal(err)
2039+
}
2040+
filters, err = FilterList(link, MakeHandle(0xffff, 0))
2041+
if err != nil {
2042+
t.Fatal(err)
2043+
}
2044+
if len(filters) != 0 {
2045+
t.Fatal("Failed to remove filter")
2046+
}
2047+
19202048
if err := QdiscDel(qdisc); err != nil {
19212049
t.Fatal(err)
19222050
}

nl/tc_linux.go

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ const (
115115
SizeofTcConnmark = SizeofTcGen + 0x04
116116
SizeofTcCsum = SizeofTcGen + 0x04
117117
SizeofTcMirred = SizeofTcGen + 0x08
118+
SizeofTcVlan = SizeofTcGen + 0x04
118119
SizeofTcTunnelKey = SizeofTcGen + 0x04
119120
SizeofTcSkbEdit = SizeofTcGen
120121
SizeofTcPolice = 2*SizeofTcRateSpec + 0x20
@@ -816,6 +817,41 @@ func (x *TcMirred) Serialize() []byte {
816817
return (*(*[SizeofTcMirred]byte)(unsafe.Pointer(x)))[:]
817818
}
818819

820+
const (
821+
TCA_VLAN_UNSPEC = iota
822+
TCA_VLAN_TM
823+
TCA_VLAN_PARMS
824+
TCA_VLAN_PUSH_VLAN_ID
825+
TCA_VLAN_PUSH_VLAN_PROTOCOL
826+
TCA_VLAN_PAD
827+
TCA_VLAN_PUSH_VLAN_PRIORITY
828+
TCA_VLAN_PUSH_ETH_DST
829+
TCA_VLAN_PUSH_ETH_SRC
830+
TCA_VLAN_MAX
831+
)
832+
833+
//struct tc_vlan {
834+
// tc_gen;
835+
// int v_action;
836+
//};
837+
838+
type TcVlan struct {
839+
TcGen
840+
Action int32
841+
}
842+
843+
func (msg *TcVlan) Len() int {
844+
return SizeofTcVlan
845+
}
846+
847+
func DeserializeTcVlan(b []byte) *TcVlan {
848+
return (*TcVlan)(unsafe.Pointer(&b[0:SizeofTcVlan][0]))
849+
}
850+
851+
func (x *TcVlan) Serialize() []byte {
852+
return (*(*[SizeofTcVlan]byte)(unsafe.Pointer(x)))[:]
853+
}
854+
819855
const (
820856
TCA_TUNNEL_KEY_UNSPEC = iota
821857
TCA_TUNNEL_KEY_TM
@@ -1239,8 +1275,8 @@ const (
12391275
)
12401276

12411277
// /* TCA_PEDIT_KEY_EX_HDR_TYPE_NETWROK is a special case for legacy users. It
1242-
// * means no specific header type - offset is relative to the network layer
1243-
// */
1278+
// - means no specific header type - offset is relative to the network layer
1279+
// */
12441280
type PeditHeaderType uint16
12451281

12461282
const (

0 commit comments

Comments
 (0)