[VOL-4005] Add support for matches on MPLS fields
Change-Id: If74dbb747b22cb0ea66e65f4b256d76f6894695c
diff --git a/internal/pkg/openflow/flowMod_test.go b/internal/pkg/openflow/flowMod_test.go
new file mode 100644
index 0000000..8465cb9
--- /dev/null
+++ b/internal/pkg/openflow/flowMod_test.go
@@ -0,0 +1,436 @@
+/*
+ Copyright 2021 the original author or authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package openflow
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "github.com/opencord/ofagent-go/internal/pkg/holder"
+ "github.com/opencord/ofagent-go/internal/pkg/mock"
+ "github.com/stretchr/testify/assert"
+ "net"
+ "testing"
+
+ "github.com/opencord/goloxi"
+ "github.com/opencord/goloxi/of13"
+ ofp "github.com/opencord/goloxi/of13"
+)
+
+func TestOFConnection_handleFlowAdd(t *testing.T) {
+ ofc := &OFConnection{
+ VolthaClient: &holder.VolthaServiceClientHolder{},
+ }
+ ofc.VolthaClient.Set(mock.MockVolthaClient{})
+
+ callables := []func(t *testing.T) *ofp.FlowAdd{getUpstreamOnuFlow, getUpstreamOLTFlow, getOnuDownstreamFlow,
+ getOLTDownstreamSingleMplsTagFlow, getOLTDownstreamDoubleMplsTagFlow}
+ for _, callable := range callables {
+ ofc.handleFlowAdd(context.Background(), callable(t))
+ }
+}
+
+func getUpstreamOnuFlow(t *testing.T) *ofp.FlowAdd {
+ flowAdd := &ofp.FlowAdd{
+ FlowMod: &ofp.FlowMod{
+ Header: &ofp.Header{
+ Version: 0,
+ Type: ofp.OFPFCAdd,
+ Length: 0,
+ Xid: 10,
+ },
+ Cookie: 114560316889735549,
+ TableId: 0,
+ Priority: 1000,
+ Match: ofp.Match{
+ OxmList: []goloxi.IOxm{&of13.NxmInPort{
+ Oxm: &of13.Oxm{
+ TypeLen: 0,
+ },
+ Value: 16,
+ },
+ &of13.OxmVlanVid{
+ Oxm: &of13.Oxm{
+ TypeLen: 0,
+ },
+ Value: 4096,
+ }},
+ },
+ Instructions: []ofp.IInstruction{
+ &ofp.InstructionGotoTable{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITGotoTable,
+ Len: 8,
+ },
+ TableId: 1,
+ },
+ &ofp.InstructionMeter{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITMeter,
+ },
+ MeterId: 1,
+ },
+ },
+ },
+ }
+ flowAddJson, err := json.Marshal(flowAdd)
+ assert.NoError(t, err)
+
+ fmt.Printf("Onu Flow Add Json: %s\n", flowAddJson)
+ return flowAdd
+}
+
+func getUpstreamOLTFlow(t *testing.T) *ofp.FlowAdd {
+ flowAdd := &ofp.FlowAdd{
+ FlowMod: &ofp.FlowMod{
+ Header: &ofp.Header{
+ Version: 0,
+ Type: ofp.OFPFCAdd,
+ Length: 0,
+ Xid: 10,
+ },
+ Cookie: 114560316889735549,
+ TableId: 1,
+ Priority: 1000,
+ Match: ofp.Match{
+ OxmList: []goloxi.IOxm{
+ &of13.OxmInPort{
+ Value: ofp.Port(16),
+ },
+ &of13.OxmVlanVid{
+ Oxm: &of13.Oxm{
+ TypeLen: 0,
+ },
+ Value: 4096,
+ }},
+ },
+ Instructions: []ofp.IInstruction{
+ &ofp.InstructionMeter{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITMeter,
+ },
+ MeterId: 1,
+ },
+ },
+ },
+ }
+
+ actions := &ofp.InstructionApplyActions{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITApplyActions,
+ },
+ }
+ actions.Actions = append(actions.Actions, &ofp.ActionPushVlan{
+ Action: &ofp.Action{
+ Type: ofp.OFPATPushVLAN,
+ },
+ Ethertype: 0x8100,
+ },
+ &ofp.ActionPushMpls{
+ Action: &ofp.Action{
+ Type: ofp.OFPATPushMpls,
+ },
+ Ethertype: 0x8847,
+ },
+ &ofp.ActionSetField{
+ Action: &ofp.Action{
+ Type: ofp.OFPATSetField,
+ },
+ Field: &ofp.OxmMplsLabel{
+ Value: 10,
+ },
+ },
+ &ofp.ActionSetField{
+ Action: &ofp.Action{
+ Type: ofp.OFPATSetField,
+ },
+ Field: &ofp.OxmMplsBos{
+ Value: 1,
+ },
+ },
+ &ofp.ActionSetField{
+ Action: &ofp.Action{
+ Type: ofp.OFPATSetField,
+ },
+ Field: &ofp.OxmEthSrc{
+ Value: net.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd, 0xee},
+ },
+ },
+ &ofp.ActionSetField{
+ Action: &ofp.Action{
+ Type: ofp.OFPATSetField,
+ },
+ Field: &ofp.OxmEthDst{
+ Value: net.HardwareAddr{0xee, 0xdd, 0xcc, 0xbb, 0xaa},
+ },
+ },
+ &ofp.ActionSetMplsTtl{
+ Action: &ofp.Action{
+ Type: ofp.OFPATSetMplsTtl,
+ },
+ MplsTtl: 64,
+ },
+ )
+
+ flowAdd.Instructions = append(flowAdd.Instructions, actions)
+ flowAddJson, err := json.Marshal(flowAdd)
+ assert.NoError(t, err)
+
+ fmt.Printf("OLT Flow Add Json: %s\n", flowAddJson)
+ return flowAdd
+}
+
+func getOnuDownstreamFlow(t *testing.T) *ofp.FlowAdd {
+ flowAdd := &ofp.FlowAdd{
+ FlowMod: &ofp.FlowMod{
+ Header: &ofp.Header{
+ Version: 3,
+ Type: 0,
+ Xid: 0,
+ },
+ Cookie: 114560316889735549,
+ TableId: 2,
+ Priority: 1000,
+ Flags: 0,
+ Match: ofp.Match{
+ Type: 0,
+ Length: 0,
+ OxmList: []goloxi.IOxm{
+ &of13.OxmInPort{
+ Value: ofp.Port(65536),
+ },
+ &of13.OxmVlanVid{
+ Value: 4096,
+ }},
+ },
+ Instructions: []ofp.IInstruction{
+ &ofp.InstructionMeter{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITMeter,
+ },
+ MeterId: 1,
+ },
+ },
+ },
+ }
+
+ actions := &ofp.InstructionApplyActions{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITApplyActions,
+ },
+ }
+ actions.Actions = append(actions.Actions,
+ &ofp.ActionOutput{
+ Action: &ofp.Action{
+ Type: ofp.OFPATOutput,
+ },
+ Port: 16,
+ })
+
+ flowAdd.Instructions = append(flowAdd.Instructions, actions)
+ flowAddJson, err := json.Marshal(flowAdd)
+ assert.NoError(t, err)
+
+ fmt.Printf("Onu Downstream Flow Add Json: %s\n", flowAddJson)
+ return flowAdd
+
+}
+
+func getOLTDownstreamSingleMplsTagFlow(t *testing.T) *ofp.FlowAdd {
+ flowAdd := &ofp.FlowAdd{
+ FlowMod: &ofp.FlowMod{
+ Header: &ofp.Header{
+ Version: 3,
+ Type: 0,
+ Xid: 0,
+ },
+ Cookie: 114560316889735549,
+ TableId: 0,
+ Priority: 1000,
+ Flags: 0,
+ Match: ofp.Match{
+ OxmList: []goloxi.IOxm{
+ &of13.OxmInPort{
+ Value: ofp.Port(65536),
+ },
+ &of13.OxmEthType{
+ Value: ofp.EthernetType(0x8847),
+ },
+ &of13.OxmMplsBos{
+ Value: 1,
+ },
+ &of13.OxmVlanVid{
+ Oxm: &of13.Oxm{
+ TypeLen: 0,
+ },
+ Value: 4096,
+ },
+ &of13.OxmEthSrc{
+ Value: net.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd},
+ },
+ },
+ },
+ Instructions: []ofp.IInstruction{
+ &ofp.InstructionGotoTable{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITGotoTable,
+ },
+ TableId: 1,
+ },
+ &ofp.InstructionMeter{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITMeter,
+ },
+ MeterId: 1,
+ },
+ },
+ },
+ }
+
+ actions := &ofp.InstructionApplyActions{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITApplyActions,
+ },
+ }
+ actions.Actions = append(actions.Actions,
+ &ofp.ActionOutput{
+ Action: &ofp.Action{
+ Type: ofp.OFPATOutput,
+ },
+ Port: 16,
+ },
+ &ofp.ActionDecMplsTtl{
+ Action: &ofp.Action{
+ Type: ofp.OFPATDecMplsTtl,
+ },
+ },
+ &ofp.ActionSetMplsTtl{
+ Action: &ofp.Action{
+ Type: ofp.OFPATSetMplsTtl,
+ },
+ MplsTtl: 64,
+ },
+ &ofp.ActionPopMpls{
+ Action: &ofp.Action{
+ Type: ofp.OFPATPopMpls,
+ },
+ Ethertype: 0x8847,
+ },
+ )
+
+ flowAdd.Instructions = append(flowAdd.Instructions, actions)
+ flowAddJson, err := json.Marshal(flowAdd)
+ assert.NoError(t, err)
+
+ fmt.Printf("Olt Downstream (Single MPLS tag) Flow Add Json: %s\n", flowAddJson)
+ return flowAdd
+}
+
+func getOLTDownstreamDoubleMplsTagFlow(t *testing.T) *ofp.FlowAdd {
+ flowAdd := &ofp.FlowAdd{
+ FlowMod: &ofp.FlowMod{
+ Header: &ofp.Header{
+ Version: 3,
+ Type: 0,
+ Xid: 0,
+ },
+ Cookie: 114560316889735549,
+ TableId: 0,
+ Priority: 1000,
+ Flags: 0,
+ Match: ofp.Match{
+ OxmList: []goloxi.IOxm{
+ &of13.OxmInPort{
+ Value: ofp.Port(65536),
+ },
+ &of13.OxmEthType{
+ Oxm: &of13.Oxm{
+ TypeLen: 0,
+ },
+ Value: ofp.EthernetType(0x8847),
+ },
+ &of13.OxmMplsBos{
+ Value: 1,
+ },
+ &of13.OxmVlanVid{
+ Value: 4096,
+ },
+ &of13.OxmEthSrc{
+ Value: net.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd},
+ },
+ },
+ },
+ Instructions: []ofp.IInstruction{
+ &ofp.InstructionGotoTable{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITGotoTable,
+ },
+ TableId: 1,
+ },
+ &ofp.InstructionMeter{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITMeter,
+ },
+ MeterId: 1,
+ },
+ },
+ },
+ }
+
+ actions := &ofp.InstructionApplyActions{
+ Instruction: &ofp.Instruction{
+ Type: ofp.OFPITApplyActions,
+ },
+ }
+ actions.Actions = append(actions.Actions,
+ &ofp.ActionOutput{
+ Action: &ofp.Action{
+ Type: ofp.OFPATOutput,
+ },
+ Port: 16,
+ },
+ &ofp.ActionDecMplsTtl{
+ Action: &ofp.Action{
+ Type: ofp.OFPATDecMplsTtl,
+ },
+ },
+ &ofp.ActionSetMplsTtl{
+ Action: &ofp.Action{
+ Type: ofp.OFPATSetMplsTtl,
+ },
+ MplsTtl: 64,
+ },
+ &ofp.ActionPopMpls{
+ Action: &ofp.Action{
+ Type: ofp.OFPATPopMpls,
+ },
+ Ethertype: 0x8847,
+ },
+ &ofp.ActionPopMpls{
+ Action: &ofp.Action{
+ Type: ofp.OFPATPopMpls,
+ },
+ Ethertype: 0x8847,
+ },
+ )
+
+ flowAdd.Instructions = append(flowAdd.Instructions, actions)
+ flowAddJson, err := json.Marshal(flowAdd)
+ assert.NoError(t, err)
+ fmt.Printf("Olt Downstream (Double MPLS tag) Flow Add Json: %s\n", flowAddJson)
+ return flowAdd
+}