mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-15 10:42:40 -04:00
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/20250218043210.732959-1-xiyou.wangcong@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -853,23 +853,30 @@ __skb_flow_dissect_ports(const struct sk_buff *skb,
|
||||
void *target_container, const void *data,
|
||||
int nhoff, u8 ip_proto, int hlen)
|
||||
{
|
||||
enum flow_dissector_key_id dissector_ports = FLOW_DISSECTOR_KEY_MAX;
|
||||
struct flow_dissector_key_ports *key_ports;
|
||||
struct flow_dissector_key_ports_range *key_ports_range = NULL;
|
||||
struct flow_dissector_key_ports *key_ports = NULL;
|
||||
__be32 ports;
|
||||
|
||||
if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS))
|
||||
dissector_ports = FLOW_DISSECTOR_KEY_PORTS;
|
||||
else if (dissector_uses_key(flow_dissector,
|
||||
FLOW_DISSECTOR_KEY_PORTS_RANGE))
|
||||
dissector_ports = FLOW_DISSECTOR_KEY_PORTS_RANGE;
|
||||
key_ports = skb_flow_dissector_target(flow_dissector,
|
||||
FLOW_DISSECTOR_KEY_PORTS,
|
||||
target_container);
|
||||
|
||||
if (dissector_ports == FLOW_DISSECTOR_KEY_MAX)
|
||||
if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS_RANGE))
|
||||
key_ports_range = skb_flow_dissector_target(flow_dissector,
|
||||
FLOW_DISSECTOR_KEY_PORTS_RANGE,
|
||||
target_container);
|
||||
|
||||
if (!key_ports && !key_ports_range)
|
||||
return;
|
||||
|
||||
key_ports = skb_flow_dissector_target(flow_dissector,
|
||||
dissector_ports,
|
||||
target_container);
|
||||
key_ports->ports = __skb_flow_get_ports(skb, nhoff, ip_proto,
|
||||
data, hlen);
|
||||
ports = __skb_flow_get_ports(skb, nhoff, ip_proto, data, hlen);
|
||||
|
||||
if (key_ports)
|
||||
key_ports->ports = ports;
|
||||
|
||||
if (key_ports_range)
|
||||
key_ports_range->tp.ports = ports;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -924,6 +931,7 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
|
||||
struct flow_dissector *flow_dissector,
|
||||
void *target_container)
|
||||
{
|
||||
struct flow_dissector_key_ports_range *key_ports_range = NULL;
|
||||
struct flow_dissector_key_ports *key_ports = NULL;
|
||||
struct flow_dissector_key_control *key_control;
|
||||
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,
|
||||
key_control->addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
|
||||
}
|
||||
|
||||
if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS))
|
||||
if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS)) {
|
||||
key_ports = skb_flow_dissector_target(flow_dissector,
|
||||
FLOW_DISSECTOR_KEY_PORTS,
|
||||
target_container);
|
||||
else if (dissector_uses_key(flow_dissector,
|
||||
FLOW_DISSECTOR_KEY_PORTS_RANGE))
|
||||
key_ports = skb_flow_dissector_target(flow_dissector,
|
||||
FLOW_DISSECTOR_KEY_PORTS_RANGE,
|
||||
target_container);
|
||||
|
||||
if (key_ports) {
|
||||
key_ports->src = flow_keys->sport;
|
||||
key_ports->dst = flow_keys->dport;
|
||||
}
|
||||
if (dissector_uses_key(flow_dissector,
|
||||
FLOW_DISSECTOR_KEY_PORTS_RANGE)) {
|
||||
key_ports_range = skb_flow_dissector_target(flow_dissector,
|
||||
FLOW_DISSECTOR_KEY_PORTS_RANGE,
|
||||
target_container);
|
||||
key_ports_range->tp.src = flow_keys->sport;
|
||||
key_ports_range->tp.dst = flow_keys->dport;
|
||||
}
|
||||
|
||||
if (dissector_uses_key(flow_dissector,
|
||||
FLOW_DISSECTOR_KEY_FLOW_LABEL)) {
|
||||
|
||||
@@ -542,8 +542,12 @@ static void detach_program(struct bpf_flow *skel, int prog_fd)
|
||||
|
||||
static int set_port_drop(int pf, bool multi_port)
|
||||
{
|
||||
char dst_port[16];
|
||||
|
||||
snprintf(dst_port, sizeof(dst_port), "%d", CFG_PORT_INNER);
|
||||
|
||||
SYS(fail, "tc qdisc add dev lo ingress");
|
||||
SYS(fail_delete_qdisc, "tc filter add %s %s %s %s %s %s %s %s %s %s",
|
||||
SYS(fail_delete_qdisc, "tc filter add %s %s %s %s %s %s %s %s %s %s %s %s",
|
||||
"dev lo",
|
||||
"parent FFFF:",
|
||||
"protocol", pf == PF_INET6 ? "ipv6" : "ip",
|
||||
@@ -551,6 +555,7 @@ static int set_port_drop(int pf, bool multi_port)
|
||||
"flower",
|
||||
"ip_proto udp",
|
||||
"src_port", multi_port ? "8-10" : "9",
|
||||
"dst_port", dst_port,
|
||||
"action drop");
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ ALL_TESTS="
|
||||
test_port_range_ipv4_tcp
|
||||
test_port_range_ipv6_udp
|
||||
test_port_range_ipv6_tcp
|
||||
test_port_range_ipv4_udp_drop
|
||||
"
|
||||
|
||||
NUM_NETIFS=4
|
||||
@@ -194,6 +195,51 @@ test_port_range_ipv6_tcp()
|
||||
__test_port_range $proto $ip_proto $sip $dip $mode "$name"
|
||||
}
|
||||
|
||||
test_port_range_ipv4_udp_drop()
|
||||
{
|
||||
local proto=ipv4
|
||||
local ip_proto=udp
|
||||
local sip=192.0.2.1
|
||||
local dip=192.0.2.2
|
||||
local mode="-4"
|
||||
local name="IPv4 UDP Drop"
|
||||
local dmac=$(mac_get $h2)
|
||||
local smac=$(mac_get $h1)
|
||||
local sport_min=2000
|
||||
local sport_max=3000
|
||||
local sport_mid=$((sport_min + (sport_max - sport_min) / 2))
|
||||
local dport=5000
|
||||
|
||||
RET=0
|
||||
|
||||
tc filter add dev $swp1 ingress protocol $proto handle 101 pref 1 \
|
||||
flower src_ip $sip dst_ip $dip ip_proto $ip_proto \
|
||||
src_port $sport_min-$sport_max \
|
||||
dst_port $dport \
|
||||
action drop
|
||||
|
||||
# Test ports outside range - should pass
|
||||
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
|
||||
-t $ip_proto "sp=$((sport_min - 1)),dp=$dport"
|
||||
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
|
||||
-t $ip_proto "sp=$((sport_max + 1)),dp=$dport"
|
||||
|
||||
# Test ports inside range - should be dropped
|
||||
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
|
||||
-t $ip_proto "sp=$sport_min,dp=$dport"
|
||||
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
|
||||
-t $ip_proto "sp=$sport_mid,dp=$dport"
|
||||
$MZ $mode $h1 -c 1 -q -p 100 -a $smac -b $dmac -A $sip -B $dip \
|
||||
-t $ip_proto "sp=$sport_max,dp=$dport"
|
||||
|
||||
tc_check_packets "dev $swp1 ingress" 101 3
|
||||
check_err $? "Filter did not drop the expected number of packets"
|
||||
|
||||
tc filter del dev $swp1 ingress protocol $proto pref 1 handle 101 flower
|
||||
|
||||
log_test "Port range matching - $name"
|
||||
}
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
h1=${NETIFS[p1]}
|
||||
|
||||
Reference in New Issue
Block a user