Skip to content

Commit 5bcd3d1

Browse files
committed
Merge branch 'flow_dissector-fix-handling-of-mixed-port-and-port-range-keys'
Cong Wang says: ==================== flow_dissector: Fix handling of mixed port and port-range keys This patchset contains two fixes for flow_dissector handling of mixed port and port-range keys, for both tc-flower case and bpf case. Each of them also comes with a selftest. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 346b341 + 15de6ba commit 5bcd3d1

File tree

3 files changed

+81
-21
lines changed

3 files changed

+81
-21
lines changed

net/core/flow_dissector.c

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -853,23 +853,30 @@ __skb_flow_dissect_ports(const struct sk_buff *skb,
853853
void *target_container, const void *data,
854854
int nhoff, u8 ip_proto, int hlen)
855855
{
856-
enum flow_dissector_key_id dissector_ports = FLOW_DISSECTOR_KEY_MAX;
857-
struct flow_dissector_key_ports *key_ports;
856+
struct flow_dissector_key_ports_range *key_ports_range = NULL;
857+
struct flow_dissector_key_ports *key_ports = NULL;
858+
__be32 ports;
858859

859860
if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS))
860-
dissector_ports = FLOW_DISSECTOR_KEY_PORTS;
861-
else if (dissector_uses_key(flow_dissector,
862-
FLOW_DISSECTOR_KEY_PORTS_RANGE))
863-
dissector_ports = FLOW_DISSECTOR_KEY_PORTS_RANGE;
861+
key_ports = skb_flow_dissector_target(flow_dissector,
862+
FLOW_DISSECTOR_KEY_PORTS,
863+
target_container);
864864

865-
if (dissector_ports == FLOW_DISSECTOR_KEY_MAX)
865+
if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS_RANGE))
866+
key_ports_range = skb_flow_dissector_target(flow_dissector,
867+
FLOW_DISSECTOR_KEY_PORTS_RANGE,
868+
target_container);
869+
870+
if (!key_ports && !key_ports_range)
866871
return;
867872

868-
key_ports = skb_flow_dissector_target(flow_dissector,
869-
dissector_ports,
870-
target_container);
871-
key_ports->ports = __skb_flow_get_ports(skb, nhoff, ip_proto,
872-
data, hlen);
873+
ports = __skb_flow_get_ports(skb, nhoff, ip_proto, data, hlen);
874+
875+
if (key_ports)
876+
key_ports->ports = ports;
877+
878+
if (key_ports_range)
879+
key_ports_range->tp.ports = ports;
873880
}
874881

875882
static void
@@ -924,6 +931,7 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
924931
struct flow_dissector *flow_dissector,
925932
void *target_container)
926933
{
934+
struct flow_dissector_key_ports_range *key_ports_range = NULL;
927935
struct flow_dissector_key_ports *key_ports = NULL;
928936
struct flow_dissector_key_control *key_control;
929937
struct flow_dissector_key_basic *key_basic;
@@ -968,20 +976,21 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
968976
key_control->addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
969977
}
970978

971-
if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS))
979+
if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS)) {
972980
key_ports = skb_flow_dissector_target(flow_dissector,
973981
FLOW_DISSECTOR_KEY_PORTS,
974982
target_container);
975-
else if (dissector_uses_key(flow_dissector,
976-
FLOW_DISSECTOR_KEY_PORTS_RANGE))
977-
key_ports = skb_flow_dissector_target(flow_dissector,
978-
FLOW_DISSECTOR_KEY_PORTS_RANGE,
979-
target_container);
980-
981-
if (key_ports) {
982983
key_ports->src = flow_keys->sport;
983984
key_ports->dst = flow_keys->dport;
984985
}
986+
if (dissector_uses_key(flow_dissector,
987+
FLOW_DISSECTOR_KEY_PORTS_RANGE)) {
988+
key_ports_range = skb_flow_dissector_target(flow_dissector,
989+
FLOW_DISSECTOR_KEY_PORTS_RANGE,
990+
target_container);
991+
key_ports_range->tp.src = flow_keys->sport;
992+
key_ports_range->tp.dst = flow_keys->dport;
993+
}
985994

986995
if (dissector_uses_key(flow_dissector,
987996
FLOW_DISSECTOR_KEY_FLOW_LABEL)) {

tools/testing/selftests/bpf/prog_tests/flow_dissector_classification.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,15 +542,20 @@ static void detach_program(struct bpf_flow *skel, int prog_fd)
542542

543543
static int set_port_drop(int pf, bool multi_port)
544544
{
545+
char dst_port[16];
546+
547+
snprintf(dst_port, sizeof(dst_port), "%d", CFG_PORT_INNER);
548+
545549
SYS(fail, "tc qdisc add dev lo ingress");
546-
SYS(fail_delete_qdisc, "tc filter add %s %s %s %s %s %s %s %s %s %s",
550+
SYS(fail_delete_qdisc, "tc filter add %s %s %s %s %s %s %s %s %s %s %s %s",
547551
"dev lo",
548552
"parent FFFF:",
549553
"protocol", pf == PF_INET6 ? "ipv6" : "ip",
550554
"pref 1337",
551555
"flower",
552556
"ip_proto udp",
553557
"src_port", multi_port ? "8-10" : "9",
558+
"dst_port", dst_port,
554559
"action drop");
555560
return 0;
556561

tools/testing/selftests/net/forwarding/tc_flower_port_range.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ ALL_TESTS="
2020
test_port_range_ipv4_tcp
2121
test_port_range_ipv6_udp
2222
test_port_range_ipv6_tcp
23+
test_port_range_ipv4_udp_drop
2324
"
2425

2526
NUM_NETIFS=4
@@ -194,6 +195,51 @@ test_port_range_ipv6_tcp()
194195
__test_port_range $proto $ip_proto $sip $dip $mode "$name"
195196
}
196197

198+
test_port_range_ipv4_udp_drop()
199+
{
200+
local proto=ipv4
201+
local ip_proto=udp
202+
local sip=192.0.2.1
203+
local dip=192.0.2.2
204+
local mode="-4"
205+
local name="IPv4 UDP Drop"
206+
local dmac=$(mac_get $h2)
207+
local smac=$(mac_get $h1)
208+
local sport_min=2000
209+
local sport_max=3000
210+
local sport_mid=$((sport_min + (sport_max - sport_min) / 2))
211+
local dport=5000
212+
213+
RET=0
214+
215+
tc filter add dev $swp1 ingress protocol $proto handle 101 pref 1 \
216+
flower src_ip $sip dst_ip $dip ip_proto $ip_proto \
217+
src_port $sport_min-$sport_max \
218+
dst_port $dport \
219+
action drop
220+
221+
# Test ports outside range - should pass
222+
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
223+
-t $ip_proto "sp=$((sport_min - 1)),dp=$dport"
224+
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
225+
-t $ip_proto "sp=$((sport_max + 1)),dp=$dport"
226+
227+
# Test ports inside range - should be dropped
228+
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
229+
-t $ip_proto "sp=$sport_min,dp=$dport"
230+
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
231+
-t $ip_proto "sp=$sport_mid,dp=$dport"
232+
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
233+
-t $ip_proto "sp=$sport_max,dp=$dport"
234+
235+
tc_check_packets "dev $swp1 ingress" 101 3
236+
check_err $? "Filter did not drop the expected number of packets"
237+
238+
tc filter del dev $swp1 ingress protocol $proto pref 1 handle 101 flower
239+
240+
log_test "Port range matching - $name"
241+
}
242+
197243
setup_prepare()
198244
{
199245
h1=${NETIFS[p1]}

0 commit comments

Comments
 (0)