Skip to content

Commit 2d0e0bd

Browse files
ssrikant20mdlayher
authored andcommitted
ovs: Handle port range parsing for tp_dst and tp_src keys (#46)
* Handle port range parsing for tp_dst and tp_src keys Parsing of a flow with tp_dst and tp_src in port/mask format does not work. Currently parseIntMatch() assumes only a single port in tp_dst and tp_src and not a port-range. As a result parsing a flow with port range fails. This fix adds logic to parse tp_dst and tp_src in port-range format in a flow. tp_dst=0xea60/0xffe0 * Simplied parsePort and added new testcase
1 parent 2bfa88b commit 2d0e0bd

File tree

5 files changed

+142
-6
lines changed

5 files changed

+142
-6
lines changed

AUTHORS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ Contributors
1111
Michael Ben-Ami <[email protected]>
1212
Tejas Kokje <[email protected]>
1313
Kei Nohguchi <[email protected]>
14-
Neal Shrader <[email protected]>
14+
Neal Shrader <[email protected]>
15+
Sangeetha Srikanth <[email protected]>

ovs/flow_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,19 @@ func TestFlowMarshalText(t *testing.T) {
278278
},
279279
s: "priority=400,ip,nw_dst=192.0.2.1,table=45,idle_timeout=0,actions=conjunction(123,1/2)",
280280
},
281+
{
282+
desc: "TP Port Range",
283+
f: &Flow{
284+
InPort: 72,
285+
Matches: []Match{
286+
TransportSourceMaskedPort(0xea60, 0xffe0),
287+
TransportDestinationMaskedPort(60000, 0xffe0),
288+
},
289+
Table: 55,
290+
Actions: []Action{Drop()},
291+
},
292+
s: "priority=0,in_port=72,tp_src=0xea60/0xffe0,tp_dst=0xea60/0xffe0,table=55,idle_timeout=0,actions=drop",
293+
},
281294
}
282295

283296
for _, tt := range tests {
@@ -737,6 +750,22 @@ func TestFlowUnmarshalText(t *testing.T) {
737750
},
738751
},
739752
},
753+
{
754+
desc: "TP Port Range",
755+
s: "priority=3000,tcp,in_port=72,tp_src=0xea60/0xffe0,tp_dst=0xea60/0xffe0,table=0,idle_timeout=0,actions=drop",
756+
f: &Flow{
757+
Priority: 3000,
758+
Protocol: ProtocolTCPv4,
759+
InPort: 72,
760+
Matches: []Match{
761+
TransportSourceMaskedPort(60000, 0xffe0),
762+
TransportDestinationMaskedPort(0xea60, 0xffe0),
763+
},
764+
Table: 0,
765+
IdleTimeout: 0,
766+
Actions: []Action{Drop()},
767+
},
768+
},
740769
}
741770

742771
for _, tt := range tests {

ovs/matchflow_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,19 @@ func TestMatchFlowMarshalText(t *testing.T) {
203203
},
204204
s: "tcp,tcp_flags=+syn+ack,nw_dst=192.0.2.1,tp_dst=22,table=45",
205205
},
206+
{
207+
desc: "TP port range flow",
208+
f: &MatchFlow{
209+
Protocol: ProtocolUDPv4,
210+
InPort: 33,
211+
Matches: []Match{
212+
NetworkDestination("192.0.2.1"),
213+
TransportDestinationMaskedPort(0xea60, 0xffe0),
214+
},
215+
Table: 55,
216+
},
217+
s: "udp,in_port=33,nw_dst=192.0.2.1,tp_dst=0xea60/0xffe0,table=55",
218+
},
206219
}
207220

208221
for _, tt := range tests {

ovs/matchparser.go

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ func parseMatch(key string, value string) (Match, error) {
3131
return parseMACMatch(key, value)
3232
case icmpType, nwProto:
3333
return parseIntMatch(key, value, math.MaxUint8)
34-
case tpSRC, tpDST, ctZone:
34+
case ctZone:
3535
return parseIntMatch(key, value, math.MaxUint16)
36+
case tpSRC, tpDST:
37+
return parsePort(key, value, math.MaxUint16)
3638
case conjID:
3739
return parseIntMatch(key, value, math.MaxUint32)
3840
case arpSPA:
@@ -104,10 +106,6 @@ func parseIntMatch(key string, value string, max int) (Match, error) {
104106
return ICMPType(uint8(t)), nil
105107
case nwProto:
106108
return NetworkProtocol(uint8(t)), nil
107-
case tpSRC:
108-
return TransportSourcePort(uint16(t)), nil
109-
case tpDST:
110-
return TransportDestinationPort(uint16(t)), nil
111109
case ctZone:
112110
return ConnectionTrackingZone(uint16(t)), nil
113111
case conjID:
@@ -117,6 +115,51 @@ func parseIntMatch(key string, value string, max int) (Match, error) {
117115
return nil, fmt.Errorf("no action matched for %s=%s", key, value)
118116
}
119117

118+
// parsePort parses a port or port/mask Match value from the input key and value,
119+
// with a maximum possible value of max.
120+
func parsePort(key string, value string, max int) (Match, error) {
121+
122+
var values []uint64
123+
//Split the string
124+
ss := strings.Split(value, "/")
125+
126+
//If input is just port
127+
switch len(ss) {
128+
case 1:
129+
val, err := parseClampInt(value, max)
130+
if err != nil {
131+
return nil, err
132+
}
133+
values = append(values, uint64(val))
134+
values = append(values, 0)
135+
// If input is port/mask
136+
case 2:
137+
for _, s := range ss {
138+
val, err := parseHexUint64(s)
139+
if err != nil {
140+
return nil, err
141+
}
142+
// Return error if val > 65536 (uint16)
143+
if val > uint64(max) {
144+
return nil, fmt.Errorf("integer %d too large; %d > %d", val, val, max)
145+
}
146+
147+
values = append(values, val)
148+
}
149+
default:
150+
return nil, fmt.Errorf("invalid value, no action matched for %s=%s", key, value)
151+
}
152+
153+
switch key {
154+
case tpSRC:
155+
return TransportSourceMaskedPort(uint16(values[0]), uint16(values[1])), nil
156+
case tpDST:
157+
return TransportDestinationMaskedPort(uint16(values[0]), uint16(values[1])), nil
158+
}
159+
// Return error if input is invalid
160+
return nil, fmt.Errorf("no action matched for %s=%s", key, value)
161+
}
162+
120163
// parseMACMatch parses a MAC address Match value from the input key and value.
121164
func parseMACMatch(key string, value string) (Match, error) {
122165
mac, err := net.ParseMAC(value)

ovs/matchparser_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,56 @@ func Test_parseMatch(t *testing.T) {
295295
s: "conj_id=nope",
296296
invalid: true,
297297
},
298+
{
299+
desc: "tp_dst out of range 65536/0xffe0",
300+
s: "tp_dst=65536/0xffe0",
301+
invalid: true,
302+
},
303+
{
304+
desc: "tp_dst out of range 0x10000/0xffe0",
305+
s: "tp_dst=0x10000/0xffe0",
306+
invalid: true,
307+
},
308+
{
309+
desc: "tp_dst out of range 0xea60/0x10000",
310+
s: "tp_dst=0xea60/0x10000",
311+
invalid: true,
312+
},
313+
{
314+
desc: "tp_dst 0xea60/0xffe0",
315+
s: "tp_dst=0xea60/0xffe0",
316+
m: TransportDestinationMaskedPort(0xea60, 0xffe0),
317+
},
318+
{
319+
desc: "tp_dst 0xea60/0xffe0/0xdddd",
320+
s: "tp_dst=0xea60/0xffe0/0xdddd",
321+
invalid: true,
322+
},
323+
{
324+
desc: "tp_src out of range 65536/0xffe0",
325+
s: "tp_src=65536/0xffe0",
326+
invalid: true,
327+
},
328+
{
329+
desc: "tp_src out of range 0x10000/0xffe0",
330+
s: "tp_src=0x10000/0xffe0",
331+
invalid: true,
332+
},
333+
{
334+
desc: "tp_src out of range 0xea60/0x10000",
335+
s: "tp_src=0xea60/0x10000",
336+
invalid: true,
337+
},
338+
{
339+
desc: "tp_src 0xea60/0xffe0",
340+
s: "tp_src=0xea60/0xffe0",
341+
m: TransportSourceMaskedPort(0xea60, 0xffe0),
342+
},
343+
{
344+
desc: "tp_src 0xea60/0xffe0/0xdddd",
345+
s: "tp_src=0xea60/0xffe0/0xdddd",
346+
invalid: true,
347+
},
298348
}
299349

300350
for _, tt := range tests {

0 commit comments

Comments
 (0)