Skip to content

Commit 3c8cd16

Browse files
committed
Add support for large packet in the packetIn2 message
1. Refine the inbound function in openflow stream. 2. Fix byte slice copy issues. 3. Fix the potential overflow issue when encoding packetOut message Signed-off-by: Wenying Dong <wenying.dong@broadcom.com>
1 parent 212303d commit 3c8cd16

10 files changed

Lines changed: 471 additions & 135 deletions

File tree

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.16.0
1+
v0.17.0

openflow13/bundles.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,20 +136,21 @@ func (p *BundlePropertyExperimenter) MarshalBinary() (data []byte, err error) {
136136
}
137137

138138
func (p *BundlePropertyExperimenter) UnmarshalBinary(data []byte) error {
139-
if len(data) < int(p.Len()) {
140-
return errors.New("the []byte is too short to unmarshal a full BundlePropertyExperimenter message")
141-
}
142139
n := 0
143140
p.Type = binary.BigEndian.Uint16(data[n:])
144141
n += 2
145142
p.Length = binary.BigEndian.Uint16(data[n:])
143+
if len(data) < int(p.Length) {
144+
return errors.New("the []byte is too short to unmarshal a full BundlePropertyExperimenter message")
145+
}
146146
n += 2
147147
p.ExperimenterID = binary.BigEndian.Uint32(data[n:])
148148
n += 4
149149
p.ExperimenterType = binary.BigEndian.Uint32(data[n:])
150150
n += 4
151-
if len(data) < int(p.Length) {
152-
p.data = data[n:]
151+
if n < int(p.Length) {
152+
p.data = make([]byte, int(p.Length)-n)
153+
copy(p.data, data[n:])
153154
}
154155
return nil
155156
}

openflow13/nx_action.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1686,7 +1686,8 @@ func NewUserdata(userdata []byte) *NXActionController2PropUserdata {
16861686
a.PropHeader = new(PropHeader)
16871687
a.Type = NXAC2PT_USERDATA
16881688
a.Length = a.PropHeader.Len() + uint16(len(a.Userdata))
1689-
a.Userdata = userdata
1689+
a.Userdata = make([]byte, len(userdata))
1690+
copy(a.Userdata, userdata)
16901691
return a
16911692
}
16921693

openflow15/bundles.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,20 +139,21 @@ func (p *BundlePropertyExperimenter) MarshalBinary() (data []byte, err error) {
139139
}
140140

141141
func (p *BundlePropertyExperimenter) UnmarshalBinary(data []byte) error {
142-
if len(data) < int(p.Len()) {
143-
return errors.New("the []byte is too short to unmarshal a full BundlePropertyExperimenter message")
144-
}
145142
n := 0
146143
p.Type = binary.BigEndian.Uint16(data[n:])
147144
n += 2
148145
p.Length = binary.BigEndian.Uint16(data[n:])
146+
if len(data) < int(p.Length) {
147+
return errors.New("the []byte is too short to unmarshal a full BundlePropertyExperimenter message")
148+
}
149149
n += 2
150150
p.ExperimenterID = binary.BigEndian.Uint32(data[n:])
151151
n += 4
152152
p.ExperimenterType = binary.BigEndian.Uint32(data[n:])
153153
n += 4
154-
if len(data) < int(p.Length) {
155-
p.data = data[n:]
154+
if n < int(p.Length) {
155+
p.data = make([]byte, int(p.Length)-n)
156+
copy(p.data, data[n:])
156157
}
157158
return nil
158159
}

openflow15/nx_action.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,8 @@ func (a *NXActionNote) UnmarshalBinary(data []byte) error {
13701370
return errors.New("the []byte is too short to unmarshal a full NXActionNote message")
13711371
}
13721372
n := a.NXActionHeader.Len()
1373-
a.Note = data[n:a.Length]
1373+
a.Note = make([]byte, a.Length-n)
1374+
copy(a.Note, data[n:a.Length])
13741375
return nil
13751376
}
13761377

@@ -1699,7 +1700,8 @@ func (a *NXActionController2PropUserdata) UnmarshalBinary(data []byte) error {
16991700
}
17001701
n += int(a.PropHeader.Len())
17011702

1702-
a.Userdata = data[n:a.Length]
1703+
a.Userdata = make([]byte, int(a.Length)-n)
1704+
copy(a.Userdata, data[n:a.Length])
17031705
return nil
17041706
}
17051707

openflow15/nxt_message.go

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -380,10 +380,8 @@ func (p *ContinuationPropStack) UnmarshalBinary(data []byte) error {
380380
return errors.New("the []byte is too short to unmarshal a full ContinuationPropStack message")
381381
}
382382
n += int(p.PropHeader.Len())
383-
for _, eachStack := range p.Stack {
384-
data[n] = eachStack
385-
n++
386-
}
383+
p.Stack = make([]byte, int(p.Length)-n)
384+
copy(p.Stack, data[n:])
387385
return nil
388386
}
389387

@@ -775,14 +773,17 @@ type PacketIn2PropPacket struct {
775773
}
776774

777775
func (p *PacketIn2PropPacket) Len() (n uint16) {
778-
n = p.PropHeader.Len() + p.Packet.Len()
776+
return uint16(p.actualLength())
777+
}
779778

779+
func (p *PacketIn2PropPacket) actualLength() int {
780+
n := int(p.PropHeader.Len()) + int(p.Packet.Len())
780781
// Round it to closest multiple of 8
781782
return ((n + 7) / 8) * 8
782783
}
783784

784785
func (p *PacketIn2PropPacket) MarshalBinary() (data []byte, err error) {
785-
data = make([]byte, p.Len())
786+
data = make([]byte, p.actualLength())
786787
var b []byte
787788
n := 0
788789

@@ -1195,6 +1196,7 @@ func DecodePacketIn2Prop(data []byte) (Property, error) {
11951196
var p Property
11961197
switch t {
11971198
case NXPINT_PACKET:
1199+
klog.V(7).InfoS("Decoding a packetIn with property NXPINT_PACKET", "data_length", len(data))
11981200
p = new(PacketIn2PropPacket)
11991201
case NXPINT_FULL_LEN:
12001202
p = new(PacketIn2PropFullLen)
@@ -1235,33 +1237,60 @@ func (p *PacketIn2) Len() (n uint16) {
12351237
}
12361238

12371239
func (p *PacketIn2) MarshalBinary() (data []byte, err error) {
1238-
data = make([]byte, p.Len())
1240+
return marshalMultipleProperties(p.Props)
1241+
}
1242+
1243+
func (p *PacketIn2) UnmarshalBinary(data []byte) error {
1244+
props, err := unmarshalPacketIn2MultipleProperties(data)
1245+
if err != nil {
1246+
return err
1247+
}
1248+
p.Props = append(p.Props, props...)
1249+
return nil
1250+
}
1251+
1252+
func marshalMultipleProperties(props []Property) (data []byte, err error) {
1253+
totalLen := 0
1254+
for _, prop := range props {
1255+
totalLen += getPropertyLength(prop)
1256+
}
1257+
1258+
data = make([]byte, totalLen)
12391259
n := 0
12401260

1241-
for _, prop := range p.Props {
1261+
for _, prop := range props {
12421262
b, err := prop.MarshalBinary()
12431263
if err != nil {
12441264
return nil, err
12451265
}
12461266
copy(data[n:], b)
1247-
n += int(prop.Len())
1267+
n += getPropertyLength(prop)
12481268
}
12491269
return
12501270
}
12511271

1252-
func (p *PacketIn2) UnmarshalBinary(data []byte) error {
1253-
n := 0
1272+
func unmarshalPacketIn2MultipleProperties(data []byte) ([]Property, error) {
1273+
var props []Property
1274+
var err error
12541275

1276+
n := 0
12551277
for n < len(data) {
12561278
prop, err := DecodePacketIn2Prop(data[n:])
12571279
if err != nil {
12581280
break
12591281
}
1260-
p.Props = append(p.Props, prop)
1261-
n += int(prop.Len())
1282+
props = append(props, prop)
1283+
n += getPropertyLength(prop)
12621284
}
1285+
return props, err
1286+
}
12631287

1264-
return nil
1288+
func getPropertyLength(prop Property) int {
1289+
propPacket, ok := prop.(*PacketIn2PropPacket)
1290+
if ok {
1291+
return propPacket.actualLength()
1292+
}
1293+
return int(prop.Len())
12651294
}
12661295

12671296
func NewPacketIn2(props []Property) *VendorHeader {
@@ -1286,31 +1315,15 @@ func (p *Resume) Len() (n uint16) {
12861315
}
12871316

12881317
func (p *Resume) MarshalBinary() (data []byte, err error) {
1289-
data = make([]byte, p.Len())
1290-
n := 0
1291-
1292-
for _, prop := range p.Props {
1293-
b, err := prop.MarshalBinary()
1294-
if err != nil {
1295-
return nil, err
1296-
}
1297-
copy(data[n:], b)
1298-
n += int(prop.Len())
1299-
}
1300-
return
1318+
return marshalMultipleProperties(p.Props)
13011319
}
13021320

13031321
func (p *Resume) UnmarshalBinary(data []byte) error {
1304-
n := 0
1305-
1306-
for n < len(data) {
1307-
prop, err := DecodePacketIn2Prop(data[n:])
1308-
if err != nil {
1309-
break
1310-
}
1311-
p.Props = append(p.Props, prop)
1312-
n += int(prop.Len())
1322+
props, err := unmarshalPacketIn2MultipleProperties(data)
1323+
if err != nil {
1324+
return err
13131325
}
1326+
p.Props = append(p.Props, props...)
13141327
return nil
13151328
}
13161329

@@ -1338,6 +1351,7 @@ func decodeVendorData(experimenterType uint32, data []byte) (msg util.Message, e
13381351
msg = new(BundleAdd)
13391352
case Type_PacketIn2:
13401353
msg = new(PacketIn2)
1354+
klog.V(7).InfoS("Decoding a PacketIn2 message", "data_length", len(data))
13411355
}
13421356
err = msg.UnmarshalBinary(data)
13431357
if err != nil {

openflow15/nxt_message_test.go

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,128 @@
11
package openflow15
22

33
import (
4+
"net"
45
"testing"
56

67
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
10+
"antrea.io/libOpenflow/protocol"
11+
"antrea.io/libOpenflow/util"
12+
)
13+
14+
var (
15+
xID = uint32(0x123456)
716
)
817

9-
func Test_PacketIn2UnMarshal(t *testing.T) {
18+
func Test_PacketIn2Unmarshal(t *testing.T) {
1019
msgBytes := []byte{0, 0, 0, 50, 1, 0, 94, 20, 50, 173, 34, 101, 235, 44, 251, 123, 8, 0, 70, 192, 0, 32, 0, 0, 64, 0, 1, 2, 15, 169, 192, 168, 0, 5, 225, 20, 50, 173, 148, 4, 0, 0, 18, 0, 218, 61, 225, 20, 50, 173, 0, 0, 0, 0, 0, 0, 0, 3, 0, 5, 33, 0, 0, 0, 0, 4, 0, 16, 0, 0, 0, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 6, 0, 32, 128, 0, 0, 4, 0, 0, 0, 6, 128, 1, 1, 16, 0, 0, 0, 3, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 7, 0, 5, 3, 0, 0, 0}
1120
pktIn2 := new(PacketIn2)
1221
err := pktIn2.UnmarshalBinary(msgBytes)
1322
assert.NoError(t, err)
1423
}
24+
25+
func TestPacketIn2MarshalUnmarshal(t *testing.T) {
26+
for _, tt := range []struct {
27+
name string
28+
packetLength uint16
29+
expectedMarshalledBytes int
30+
expectedMessageLength uint16
31+
}{
32+
{"SmallPacket", 64, 96, 96},
33+
{"MediumPacket", 1500, 1528, 1528},
34+
{"LargePacketOverflow", 65530, 65560, 24},
35+
} {
36+
t.Run(tt.name, func(t *testing.T) {
37+
ethPacket := generateEthernetPacket(tt.packetLength)
38+
pktIn2PacketProp := &PacketIn2PropPacket{
39+
PropHeader: &PropHeader{
40+
Type: uint16(NXPINT_PACKET),
41+
},
42+
Packet: ethPacket,
43+
}
44+
pktIn2TableProp := &PacketIn2PropTableID{
45+
PropHeader: &PropHeader{
46+
Type: uint16(NXPINT_TABLE_ID),
47+
},
48+
TableID: 1,
49+
}
50+
pktIn2Msg := NewPacketIn2([]Property{pktIn2PacketProp, pktIn2TableProp})
51+
pktIn2Msg.Header.Xid = xID
52+
messageBytes, err := pktIn2Msg.MarshalBinary()
53+
require.NoError(t, err)
54+
assert.Len(t, messageBytes, tt.expectedMarshalledBytes)
55+
56+
decodedMsg, err := Parse(messageBytes)
57+
require.NoError(t, err)
58+
decodedVendorHeader, ok := decodedMsg.(*VendorHeader)
59+
require.True(t, ok)
60+
assert.Equal(t, tt.expectedMessageLength, decodedVendorHeader.Header.Length)
61+
assert.Equal(t, uint32(NxExperimenterID), decodedVendorHeader.Vendor)
62+
assert.Equal(t, uint32(Type_PacketIn2), decodedVendorHeader.ExperimenterType)
63+
})
64+
}
65+
}
66+
67+
func TestPacketOutMarshalUnmarshal(t *testing.T) {
68+
for _, tt := range []struct {
69+
name string
70+
packetLength uint16
71+
expectedMarshalledBytes int
72+
expectedMessageLength uint16
73+
}{
74+
{"SmallPacket", 64, 112, 112},
75+
{"MediumPacket", 1500, 1548, 1548},
76+
{"LargePacketOverflow", 65530, 65578, 42},
77+
} {
78+
t.Run(tt.name, func(t *testing.T) {
79+
ethPacket := generateEthernetPacket(tt.packetLength)
80+
packetBytes, err := ethPacket.MarshalBinary()
81+
require.NoError(t, err)
82+
packetOut := NewPacketOut()
83+
packetOut.Header.Xid = xID
84+
packetOut.Data = &ethPacket
85+
packetOut.Match = *NewMatch()
86+
packetOut.Match.AddField(*NewInPortField(1))
87+
packetOut.AddAction(NewActionOutput(30))
88+
messageBytes, err := packetOut.MarshalBinary()
89+
require.NoError(t, err)
90+
assert.Len(t, messageBytes, tt.expectedMarshalledBytes)
91+
92+
decodedMsg, err := Parse(messageBytes)
93+
require.NoError(t, err)
94+
decodedPacketOut, ok := decodedMsg.(*PacketOut)
95+
require.True(t, ok)
96+
assert.Equal(t, tt.expectedMessageLength, decodedPacketOut.Header.Length)
97+
decodedPkt, ok := decodedPacketOut.Data.(*util.Buffer)
98+
require.True(t, ok)
99+
assert.Equal(t, packetBytes, decodedPkt.Bytes())
100+
})
101+
}
102+
}
103+
104+
func generateEthernetPacket(packetLength uint16) protocol.Ethernet {
105+
ipPacketLength := packetLength - 14
106+
udpPacketLength := ipPacketLength - 20
107+
udpPayloadLength := udpPacketLength - 8
108+
return protocol.Ethernet{
109+
HWDst: []byte{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF},
110+
HWSrc: []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66},
111+
Ethertype: 0x0800,
112+
Data: &protocol.IPv4{
113+
Version: 0x45,
114+
IHL: 0x00,
115+
Length: ipPacketLength,
116+
NWDst: net.ParseIP("192.168.0.1").To4(),
117+
NWSrc: net.ParseIP("192.168.0.2").To4(),
118+
Protocol: protocol.Type_UDP,
119+
Data: &protocol.UDP{
120+
PortSrc: 1234,
121+
PortDst: 5678,
122+
Length: udpPacketLength,
123+
Checksum: 0,
124+
Data: make([]byte, udpPayloadLength),
125+
},
126+
},
127+
}
128+
}

0 commit comments

Comments
 (0)