Skip to content

Commit

Permalink
Add unit tests for pkg/ovs/openflow (#4221)
Browse files Browse the repository at this point in the history
Signed-off-by: Hongliang Liu <lhongliang@vmware.com>
  • Loading branch information
hongliangl committed Oct 16, 2023
1 parent 62a440a commit dc0ca2d
Show file tree
Hide file tree
Showing 8 changed files with 4,032 additions and 21 deletions.
1,749 changes: 1,749 additions & 0 deletions pkg/ovs/openflow/ofctrl_action_test.go

Large diffs are not rendered by default.

1,688 changes: 1,670 additions & 18 deletions pkg/ovs/openflow/ofctrl_builder_test.go

Large diffs are not rendered by default.

167 changes: 167 additions & 0 deletions pkg/ovs/openflow/ofctrl_group_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright 2023 Antrea 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 (
"testing"

"antrea.io/libOpenflow/openflow15"
"antrea.io/libOpenflow/util"
"antrea.io/ofnet/ofctrl"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func getGroupMod(t *testing.T, g Group) *openflow15.GroupMod {
msgs, err := g.GetBundleMessages(AddMessage)
assert.NoError(t, err)
require.Equal(t, 1, len(msgs))
return msgs[0].GetMessage().(*openflow15.GroupMod)
}

func TestBucketBuilder(t *testing.T) {
testCases := []struct {
name string
bucketFn func(BucketBuilder) BucketBuilder
expectedProperty util.Message
expectedActionField openflow15.Action
expectedActionStr string
}{
{
name: "Weight",
bucketFn: func(fb BucketBuilder) BucketBuilder {
return fb.Weight(100)
},
expectedProperty: &openflow15.GroupBucketPropWeight{
Weight: 100,
},
expectedActionStr: "weight:100",
},
{
name: "LoadToRegField (all bits)",
bucketFn: func(fb BucketBuilder) BucketBuilder {
return fb.LoadToRegField(NewRegField(1, 0, 31), uint32(0xffff_ffff))
},
expectedActionField: &openflow15.ActionSetField{
Field: openflow15.MatchField{
Class: openflow15.OXM_CLASS_NXM_1,
Field: openflow15.NXM_NX_REG1,
Value: &openflow15.Uint32Message{Data: uint32(0xffff_ffff)},
Mask: &openflow15.Uint32Message{Data: uint32(0xffff_ffff)},
},
},
expectedActionStr: "set_field:0xffffffff->reg1",
},
{
name: "LoadToRegField (part bits)",
bucketFn: func(fb BucketBuilder) BucketBuilder {
return fb.LoadToRegField(NewRegField(1, 4, 15), uint32(0xf))
},
expectedActionField: &openflow15.ActionSetField{
Field: openflow15.MatchField{
Class: openflow15.OXM_CLASS_NXM_1,
Field: openflow15.NXM_NX_REG1,
Value: &openflow15.Uint32Message{Data: uint32(0xf0)},
Mask: &openflow15.Uint32Message{Data: uint32(0xfff0)},
},
},
expectedActionStr: "set_field:0xf0/0xfff0->reg1",
},
{
name: "LoadXXReg (all bits)",
bucketFn: func(fb BucketBuilder) BucketBuilder {
return fb.LoadXXReg(0, []byte{0x11, 0x22, 0x33, 0x44})
},
expectedActionField: &openflow15.ActionSetField{
Field: openflow15.MatchField{
Class: openflow15.OXM_CLASS_NXM_1,
Field: openflow15.NXM_NX_XXREG0,
Value: util.NewBuffer([]byte{0x11, 0x22, 0x33, 0x44}),
},
},
expectedActionStr: "set_field:0x11223344->xxreg0",
},
{
name: "SetTunnelDst (IPv4)",
bucketFn: func(fb BucketBuilder) BucketBuilder {
return fb.SetTunnelDst(ipv4Addr1)
},
expectedActionField: &openflow15.ActionSetField{
Field: openflow15.MatchField{
Class: openflow15.OXM_CLASS_NXM_1,
Field: openflow15.NXM_NX_TUN_IPV4_DST,
Value: &openflow15.TunnelIpv4DstField{
TunnelIpv4Dst: ipv4Addr1,
},
},
},
expectedActionStr: "set_field:1.1.1.1->tun_dst",
},
{
name: "SetTunnelDst (IPv6)",
bucketFn: func(fb BucketBuilder) BucketBuilder {
return fb.SetTunnelDst(ipv6Addr1)
},
expectedActionField: &openflow15.ActionSetField{
Field: openflow15.MatchField{
Class: openflow15.OXM_CLASS_NXM_1,
Field: openflow15.NXM_NX_TUN_IPV6_DST,
Value: &openflow15.Ipv6DstField{
Ipv6Dst: ipv6Addr1,
},
},
},
expectedActionStr: "set_field:fec0::1111->tun_ipv6_dst",
},
{
name: "ResubmitToTable",
bucketFn: func(fb BucketBuilder) BucketBuilder {
return fb.ResubmitToTable(tableID1)
},
expectedActionField: &openflow15.NXActionResubmitTable{
TableID: tableID1,
},
expectedActionStr: "resubmit:100",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
g := &ofGroup{ofctrl: &ofctrl.Group{}}
groupMod := getGroupMod(t, tc.bucketFn(g.Bucket()).Done())
assert.Equal(t, 1, len(groupMod.Buckets))

actions := groupMod.Buckets[0].Actions
properties := groupMod.Buckets[0].Properties

if tc.expectedProperty != nil {
require.Equal(t, 1, len(properties))
assert.Equal(t, tc.expectedProperty, properties[0])
}
if tc.expectedActionField != nil {
require.Equal(t, 1, len(actions))
action := actions[0]
switch expected := tc.expectedActionField.(type) {
case *openflow15.ActionSetField:
checkActionSetField(t, expected, action)
case *openflow15.NXActionResubmitTable:
assert.Equal(t, expected.TableID, action.(*openflow15.NXActionResubmitTable).TableID)
default:
t.Fatalf("Unknown type %v", action)
}
}
assert.Contains(t, GroupModToString(groupMod), tc.expectedActionStr)
})
}
}
85 changes: 85 additions & 0 deletions pkg/ovs/openflow/ofctrl_meter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2023 Antrea 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 (
"testing"

"antrea.io/libOpenflow/openflow15"
"antrea.io/libOpenflow/util"
"antrea.io/ofnet/ofctrl"
"github.com/stretchr/testify/assert"
)

func getMeterMod(t *testing.T, m Meter) *openflow15.MeterMod {
msgs, err := m.GetBundleMessages(AddMessage)
assert.NoError(t, err)
assert.Equal(t, 1, len(msgs))
return msgs[0].GetMessage().(*openflow15.MeterMod)
}

func TestMeterBandBuilder(t *testing.T) {
m := &ofMeter{ofctrl: &ofctrl.Meter{}}

t.Run("MeterType", func(t *testing.T) {
testCases := []struct {
meterType ofctrl.MeterType
expectedBandType util.Message
}{
{ofctrl.MeterDrop, &openflow15.MeterBandDrop{}},
{ofctrl.MeterDSCPRemark, &openflow15.MeterBandDSCP{}},
{ofctrl.MeterExperimenter, &openflow15.MeterBandExperimenter{}},
}
for _, tc := range testCases {
m.ResetMeterBands()
meter := m.MeterBand().MeterType(tc.meterType).Done()
meterMod := getMeterMod(t, meter)
assert.Equal(t, 1, len(meterMod.MeterBands))
assert.IsType(t, tc.expectedBandType, meterMod.MeterBands[0])
}
})
t.Run("Rate", func(t *testing.T) {
m.ResetMeterBands()
rate := uint32(100)
meter := m.MeterBand().MeterType(ofctrl.MeterDSCPRemark).Rate(rate).Done()
meterMod := getMeterMod(t, meter)
assert.Equal(t, 1, len(meterMod.MeterBands))
assert.Equal(t, rate, meterMod.MeterBands[0].(*openflow15.MeterBandDSCP).MeterBandHeader.Rate)
})
t.Run("Burst", func(t *testing.T) {
m.ResetMeterBands()
burst := uint32(100)
meter := m.MeterBand().MeterType(ofctrl.MeterDSCPRemark).Burst(burst).Done()
meterMod := getMeterMod(t, meter)
assert.Equal(t, 1, len(meterMod.MeterBands))
assert.Equal(t, burst, meterMod.MeterBands[0].(*openflow15.MeterBandDSCP).MeterBandHeader.BurstSize)
})
t.Run("PrecLevel", func(t *testing.T) {
m.ResetMeterBands()
precLevel := uint8(100)
meter := m.MeterBand().MeterType(ofctrl.MeterDSCPRemark).PrecLevel(precLevel).Done()
meterMod := getMeterMod(t, meter)
assert.Equal(t, 1, len(meterMod.MeterBands))
assert.Equal(t, precLevel, meterMod.MeterBands[0].(*openflow15.MeterBandDSCP).PrecLevel)
})
t.Run("Experimenter", func(t *testing.T) {
m.ResetMeterBands()
experimenter := uint32(100)
meter := m.MeterBand().MeterType(ofctrl.MeterExperimenter).Experimenter(experimenter).Done()
meterMod := getMeterMod(t, meter)
assert.Equal(t, 1, len(meterMod.MeterBands))
assert.Equal(t, experimenter, meterMod.MeterBands[0].(*openflow15.MeterBandExperimenter).Experimenter)
})
}
2 changes: 1 addition & 1 deletion pkg/ovs/openflow/ofctrl_packetout.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func (b *ofPacketOutBuilder) SetEthPacket(packet *protocol.Ethernet) PacketOutBu
return b
}

// AddSetIPToSAction sets the IP_TOS field in the packet-out message. The action clears the two ECN bits as 0,
// AddSetIPTOSAction sets the IP_TOS field in the packet-out message. The action clears the two ECN bits as 0,
// and only 2-7 bits of the DSCP field in IP header is set.
func (b *ofPacketOutBuilder) AddSetIPTOSAction(data uint8) PacketOutBuilder {
field, _ := openflow15.FindFieldHeaderByName(NxmFieldIPToS, true)
Expand Down
Loading

0 comments on commit dc0ca2d

Please sign in to comment.