Skip to content

Commit ddba8b4

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 ddba8b4

10 files changed

Lines changed: 470 additions & 134 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
@@ -3,7 +3,6 @@ package openflow15
33
import (
44
"encoding/binary"
55
"errors"
6-
76
"k8s.io/klog/v2"
87

98
"antrea.io/libOpenflow/protocol"
@@ -380,10 +379,8 @@ func (p *ContinuationPropStack) UnmarshalBinary(data []byte) error {
380379
return errors.New("the []byte is too short to unmarshal a full ContinuationPropStack message")
381380
}
382381
n += int(p.PropHeader.Len())
383-
for _, eachStack := range p.Stack {
384-
data[n] = eachStack
385-
n++
386-
}
382+
p.Stack = make([]byte, int(p.Length)-n)
383+
copy(p.Stack, data[n:])
387384
return nil
388385
}
389386

@@ -776,13 +773,17 @@ type PacketIn2PropPacket struct {
776773

777774
func (p *PacketIn2PropPacket) Len() (n uint16) {
778775
n = p.PropHeader.Len() + p.Packet.Len()
776+
return uint16(p.ActLength())
777+
}
779778

779+
func (p *PacketIn2PropPacket) ActLength() 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.ActLength())
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 += getPacketIn2PropertyLength(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 += getPacketIn2PropertyLength(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 += getPacketIn2PropertyLength(prop)
12621284
}
1285+
return props, err
1286+
}
12631287

1264-
return nil
1288+
func getPacketIn2PropertyLength(prop Property) int {
1289+
overflowedMsg, ok := prop.(OverFlowedMessage)
1290+
if ok {
1291+
return overflowedMsg.ActLength()
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: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
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

918
func Test_PacketIn2UnMarshal(t *testing.T) {
@@ -12,3 +21,108 @@ func Test_PacketIn2UnMarshal(t *testing.T) {
1221
err := pktIn2.UnmarshalBinary(msgBytes)
1322
assert.NoError(t, err)
1423
}
24+
25+
func TestPacketIn2UnMarshalWithLargePacket(t *testing.T) {
26+
for _, tt := range []struct {
27+
name string
28+
packetLength uint16
29+
bytesSize int
30+
messageLength uint16
31+
}{
32+
{"SmallPacket", 64, 96, 96},
33+
{"MediumPacket", 1500, 1528, 1528},
34+
{"LargePacket", 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.Equal(t, tt.bytesSize, len(messageBytes))
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.messageLength, 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+
bytesSize int
72+
messageLength uint16
73+
}{
74+
{"SmallPacket", 64, 112, 112},
75+
{"MediumPacket", 1500, 1548, 1548},
76+
{"LargePacket", 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.Equal(t, tt.bytesSize, len(messageBytes))
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.messageLength, 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)