Skip to content

Commit 0dc3557

Browse files
vlrpligsilya
authored andcommittedFeb 20, 2025·
miniflow_extract: Push ct_tp_{src, dst} for later frags.
Ales reported that ct_tp_{src,dst} matches are working only for the first frag for the userspace datapath, whereas they are always working for later frags in the case of kernel datapath. The ipf propagates the info in packets metadata, but miniflow_extract() has no handling for them. Fix it by pushing the relevant fields in the miniflow. tp_{src,dst} are not set for later frags, so fill them with padding as ct_tp_{src,dst} are not aligned: struct flow { [...] ovs_be16 tp_src; /* 656 2 */ ovs_be16 tp_dst; /* 658 2 */ ovs_be16 ct_tp_src; /* 660 2 */ ovs_be16 ct_tp_dst; /* 662 2 */ [...] } The patch also includes two tests to exercise the behavior. Fixes: 4ea9669 ("Userspace datapath: Add fragmentation handling.") Reported-at: https://issues.redhat.com/browse/FDP-124 Signed-off-by: Paolo Valerio <[email protected]> Signed-off-by: Ilya Maximets <[email protected]>
1 parent b9ea2da commit 0dc3557

File tree

2 files changed

+189
-3
lines changed

2 files changed

+189
-3
lines changed
 

‎lib/flow.c

+18-3
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,14 @@ parse_ethertype(const void **datap, size_t *sizep)
402402
return htons(FLOW_DL_TYPE_NONE);
403403
}
404404

405+
static inline bool
406+
icmp6_is_nd(const struct icmp6_data_header *icmp6)
407+
{
408+
return (icmp6->icmp6_base.icmp6_code == 0 &&
409+
(icmp6->icmp6_base.icmp6_type == ND_NEIGHBOR_SOLICIT ||
410+
icmp6->icmp6_base.icmp6_type == ND_NEIGHBOR_ADVERT));
411+
}
412+
405413
/* Returns 'true' if the packet is an ND packet. In that case the '*nd_target'
406414
* and 'arp_buf[]' are filled in. If the packet is not an ND packet, 'false'
407415
* is returned and no values are filled in on '*nd_target' or 'arp_buf[]'. */
@@ -412,9 +420,7 @@ parse_icmpv6(const void **datap, size_t *sizep,
412420
const union ovs_16aligned_in6_addr **nd_target,
413421
struct eth_addr arp_buf[2], uint8_t *opt_type)
414422
{
415-
if (icmp6->icmp6_base.icmp6_code != 0 ||
416-
(icmp6->icmp6_base.icmp6_type != ND_NEIGHBOR_SOLICIT &&
417-
icmp6->icmp6_base.icmp6_type != ND_NEIGHBOR_ADVERT)) {
423+
if (!icmp6_is_nd(icmp6)) {
418424
return false;
419425
}
420426

@@ -1119,6 +1125,15 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
11191125
}
11201126
}
11211127
}
1128+
} else if (ct_nw_proto_p &&
1129+
(*ct_nw_proto_p == IPPROTO_TCP ||
1130+
*ct_nw_proto_p == IPPROTO_UDP ||
1131+
*ct_nw_proto_p == IPPROTO_SCTP ||
1132+
*ct_nw_proto_p == IPPROTO_ICMP ||
1133+
(*ct_nw_proto_p == IPPROTO_ICMPV6 && !icmp6_is_nd(data)))) {
1134+
miniflow_pad_from_64(mf, ct_tp_src);
1135+
miniflow_push_be16(mf, ct_tp_src, ct_tp_src);
1136+
miniflow_push_be16(mf, ct_tp_dst, ct_tp_dst);
11221137
}
11231138
out:
11241139
dst->map = mf.map;

‎tests/system-traffic.at

+171
Original file line numberDiff line numberDiff line change
@@ -3693,6 +3693,91 @@ OVS_CHECK_FRAG_LARGE()
36933693
OVS_TRAFFIC_VSWITCHD_STOP(["/Unsupported big reassembled v4 packet/d"])
36943694
AT_CLEANUP
36953695

3696+
AT_SETUP([conntrack - IPv4 fragmentation with ct orig match])
3697+
CHECK_CONNTRACK()
3698+
OVS_TRAFFIC_VSWITCHD_START()
3699+
3700+
ADD_NAMESPACES(at_ns0, at_ns1)
3701+
3702+
ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
3703+
ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
3704+
3705+
AT_DATA([flows.txt], [dnl
3706+
priority=1,action=drop
3707+
priority=10,arp,action=normal
3708+
priority=100,ip,ct_state=-trk,action=ct(table=0)
3709+
priority=100,in_port=2,icmp,ct_state=+rpl,action=1
3710+
priority=100,in_port=1,ip,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ct_state=+new+trk,action=ct(commit)
3711+
priority=100,in_port=1,ip,ct_nw_proto=1,ct_tp_src=8,ct_tp_dst=0,ct_state=+new+trk,action=ct(commit),2
3712+
])
3713+
3714+
AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
3715+
3716+
dnl Packet content:
3717+
dnl Ethernet II, Src: 50:54:00:00:00:0a, Dst: 50:54:00:00:00:09
3718+
dnl Type: IPv4 (0x0800)
3719+
dnl Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2
3720+
dnl Total Length: 1420
3721+
dnl Identification: 0x0001 (1)
3722+
dnl 001. .... = Flags: 0x1, More fragments
3723+
dnl 0... .... = Reserved bit: Not set
3724+
dnl .0.. .... = Don't fragment: Not set
3725+
dnl ..1. .... = More fragments: Set
3726+
dnl ...0 0000 0000 0000 = Fragment Offset: 0
3727+
dnl Time to Live: 64
3728+
dnl Protocol: UDP (17)
3729+
dnl User Datagram Protocol, Src Port: 1, Dst Port: 2
3730+
dnl Source Port: 1
3731+
dnl Destination Port: 2
3732+
dnl Length: 1608
3733+
dnl UDP payload (1392 bytes)
3734+
dnl Data (1392 bytes)
3735+
eth="50 54 00 00 00 09 50 54 00 00 00 0a 08 00"
3736+
ip="45 00 05 8c 00 01 20 00 40 11 3f 5c 0a 01 01 01 0a 01 01 02"
3737+
udp="00 01 00 02 06 48 dd 56"
3738+
data_len=$(seq 1392)
3739+
data=$(printf '00 %.0s' ${data_len})
3740+
packet="${eth} ${ip} ${udp} ${data}"
3741+
NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 ${packet} > /dev/null])
3742+
3743+
dnl Packet content:
3744+
dnl Ethernet II, Src: 50:54:00:00:00:0a, Dst: 50:54:00:00:00:09
3745+
dnl Type: IPv4 (0x0800)
3746+
dnl Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2
3747+
dnl 0100 .... = Version: 4
3748+
dnl .... 0101 = Header Length: 20 bytes (5)
3749+
dnl Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
3750+
dnl 0000 00.. = Differentiated Services Codepoint: Default (0)
3751+
dnl .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
3752+
dnl Total Length: 228
3753+
dnl Identification: 0x0001 (1)
3754+
dnl 000. .... = Flags: 0x0
3755+
dnl 0... .... = Reserved bit: Not set
3756+
dnl .0.. .... = Don't fragment: Not set
3757+
dnl ..0. .... = More fragments: Not set
3758+
dnl ...0 0000 1010 1111 = Fragment Offset: 1400
3759+
dnl Time to Live: 64
3760+
dnl Protocol: UDP (17)
3761+
dnl Data (208 bytes)
3762+
eth="50 54 00 00 00 09 50 54 00 00 00 0a 08 00"
3763+
ip="45 00 00 e4 00 01 00 af 40 11 63 55 0a 01 01 01 0a 01 01 02"
3764+
data_len=$(seq 208)
3765+
data=$(printf '00 %.0s' ${data_len})
3766+
packet="${eth} ${ip} ${data}"
3767+
NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 ${packet} > /dev/null])
3768+
3769+
NS_CHECK_EXEC([at_ns0], [ping -s 1600 -q -c 1 -W 1 10.1.1.2 | FORMAT_PING], [0], [dnl
3770+
1 packets transmitted, 1 received, 0% packet loss, time 0ms
3771+
])
3772+
3773+
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2) | sort], [0], [dnl
3774+
icmp,orig=(src=10.1.1.1,dst=10.1.1.2,id=<cleared>,type=8,code=0),reply=(src=10.1.1.2,dst=10.1.1.1,id=<cleared>,type=0,code=0)
3775+
udp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>)
3776+
])
3777+
3778+
OVS_TRAFFIC_VSWITCHD_STOP
3779+
AT_CLEANUP
3780+
36963781
AT_SETUP([conntrack - IPv4 fragmentation expiry])
36973782
CHECK_CONNTRACK()
36983783
OVS_TRAFFIC_VSWITCHD_START()
@@ -3990,6 +4075,92 @@ OVS_CHECK_FRAG_LARGE()
39904075
OVS_TRAFFIC_VSWITCHD_STOP(["/Unsupported big reassembled v6 packet/d"])
39914076
AT_CLEANUP
39924077

4078+
AT_SETUP([conntrack - IPv6 fragmentation with ct orig match])
4079+
CHECK_CONNTRACK()
4080+
OVS_TRAFFIC_VSWITCHD_START()
4081+
4082+
ADD_NAMESPACES(at_ns0, at_ns1)
4083+
4084+
ADD_VETH(p0, at_ns0, br0, "fc00::1/96", "50:54:00:00:00:09", [], "nodad")
4085+
ADD_VETH(p1, at_ns1, br0, "fc00::2/96", "50:54:00:00:00:0a", [], "nodad")
4086+
4087+
AT_DATA([flows.txt], [dnl
4088+
priority=1,action=drop
4089+
priority=10,ipv6,ct_state=-trk,action=ct(table=0)
4090+
priority=10,in_port=2,ipv6,ct_tp_src=128,ct_state=+trk+est+rpl,action=1
4091+
priority=10,in_port=1,ipv6,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ct_state=+new+trk,action=ct(commit)
4092+
priority=10,in_port=1,ipv6,ct_nw_proto=58,ct_tp_src=128,ct_tp_dst=0,ct_state=+new+trk,action=ct(commit),2
4093+
priority=100,icmp6,icmp_type=135,action=normal
4094+
priority=100,icmp6,icmp_type=136,action=normal
4095+
])
4096+
4097+
AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
4098+
4099+
dnl Packet content:
4100+
dnl Ethernet II, Src: 50:54:00:00:00:0a, Dst: 50:54:00:00:00:09
4101+
dnl Type: IPv6 (0x86dd)
4102+
dnl Internet Protocol Version 6, Src: fc00::1, Dst: fc00::2
4103+
dnl Payload Length: 1344
4104+
dnl Next Header: Fragment Header for IPv6 (44)
4105+
dnl Hop Limit: 64
4106+
dnl Fragment Header for IPv6
4107+
dnl Next header: UDP (17)
4108+
dnl Reserved octet: 0x00
4109+
dnl 0000 0000 0000 0... = Offset: 0 (0 bytes)
4110+
dnl .... .... .... .00. = Reserved bits: 0
4111+
dnl .... .... .... ...1 = More Fragments: Yes
4112+
dnl Identification: 0x9bdb1fa7
4113+
dnl User Datagram Protocol, Src Port: 1, Dst Port: 2
4114+
dnl Source Port: 1
4115+
dnl Destination Port: 2
4116+
dnl Length: 1608
4117+
dnl UDP payload (1328 bytes)
4118+
dnl Data (1328 bytes)
4119+
eth="50 54 00 00 00 09 50 54 00 00 00 0a 86 dd"
4120+
ipv6="60 00 00 00 05 40 2c 40 fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 \
4121+
fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 11 00 00 01 9b db 1f a7"
4122+
udp="00 01 00 02 06 48 fb 56"
4123+
data_len=$(seq 1328)
4124+
data=$(printf '00 %.0s' ${data_len})
4125+
packet="${eth} ${ipv6} ${udp} ${data}"
4126+
NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 ${packet} > /dev/null])
4127+
4128+
dnl IPv6 Packet content
4129+
dnl Ethernet II, Src: 50:54:00:00:00:0a, Dst: 50:54:00:00:00:09
4130+
dnl Type: IPv6 (0x86dd)
4131+
dnl Internet Protocol Version 6, Src: fc00::1, Dst: fc00::2
4132+
dnl Payload Length: 280
4133+
dnl Next Header: Fragment Header for IPv6 (44)
4134+
dnl Hop Limit: 64
4135+
dnl Fragment Header for IPv6
4136+
dnl Next header: UDP (17)
4137+
dnl Reserved octet: 0x00
4138+
dnl 0000 0101 0011 1... = Offset: 167 (1336 bytes)
4139+
dnl .... .... .... .00. = Reserved bits: 0
4140+
dnl .... .... .... ...0 = More Fragments: No
4141+
dnl Identification: 0x9bdb1fa7
4142+
dnl Data (272 bytes)
4143+
eth="50 54 00 00 00 09 50 54 00 00 00 0a 86 dd"
4144+
ipv6="60 00 00 00 01 18 2c 40 fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 \
4145+
fc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 11 00 05 38 9b db 1f a7"
4146+
data_len=$(seq 272)
4147+
data=$(printf '00 %.0s' ${data_len})
4148+
packet="${eth} ${ipv6} ${data}"
4149+
NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 ${packet} > /dev/null])
4150+
4151+
dnl Send also fragmented ICMPv6.
4152+
NS_CHECK_EXEC([at_ns0], [ping6 -s 1600 -q -c 1 -W 1 fc00::2 | FORMAT_PING], [0], [dnl
4153+
1 packets transmitted, 1 received, 0% packet loss, time 0ms
4154+
])
4155+
4156+
AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(fc00::2) | sort], [0], [dnl
4157+
icmpv6,orig=(src=fc00::1,dst=fc00::2,id=<cleared>,type=128,code=0),reply=(src=fc00::2,dst=fc00::1,id=<cleared>,type=129,code=0)
4158+
udp,orig=(src=fc00::1,dst=fc00::2,sport=<cleared>,dport=<cleared>),reply=(src=fc00::2,dst=fc00::1,sport=<cleared>,dport=<cleared>)
4159+
])
4160+
4161+
OVS_TRAFFIC_VSWITCHD_STOP
4162+
AT_CLEANUP
4163+
39934164
AT_SETUP([conntrack - IPv6 fragmentation expiry])
39944165
CHECK_CONNTRACK()
39954166
OVS_TRAFFIC_VSWITCHD_START()

0 commit comments

Comments
 (0)
Please sign in to comment.