summaryrefslogtreecommitdiff
path: root/tools/testing
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing')
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/port_range_occ.sh26
-rwxr-xr-xtools/testing/selftests/net/amt.sh29
-rw-r--r--tools/testing/selftests/net/tun.c136
-rwxr-xr-xtools/testing/selftests/net/veth.sh46
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/route.json46
5 files changed, 283 insertions, 0 deletions
diff --git a/tools/testing/selftests/drivers/net/mlxsw/port_range_occ.sh b/tools/testing/selftests/drivers/net/mlxsw/port_range_occ.sh
index b1f0781f6b25..c7eba3f15066 100755
--- a/tools/testing/selftests/drivers/net/mlxsw/port_range_occ.sh
+++ b/tools/testing/selftests/drivers/net/mlxsw/port_range_occ.sh
@@ -9,6 +9,7 @@ lib_dir=$(dirname $0)/../../../net/forwarding
ALL_TESTS="
port_range_occ_test
+ port_range_occ_tmplt_test
"
NUM_NETIFS=2
source $lib_dir/lib.sh
@@ -101,6 +102,31 @@ port_range_occ_test()
log_test "port range occupancy"
}
+port_range_occ_tmplt_test()
+{
+ local occ
+
+ RET=0
+ occ=$(port_range_occ_get)
+
+ # Addition of a chain template should not impact occupancy.
+ tc chain add dev "$swp1" ingress chain 1 protocol ip \
+ flower ip_proto udp src_port 501-600 dst_port 701-800
+ check_err $? "Could not add chain template"
+
+ (( occ == $(port_range_occ_get) ))
+ check_err $? "Got occupancy $(port_range_occ_get), expected $occ"
+
+ # And just for completeness sake, neither should deletion.
+ tc chain del dev "$swp1" ingress chain 1
+ check_err $? "Could not delete chain template"
+
+ (( occ == $(port_range_occ_get) ))
+ check_err $? "Got occupancy $(port_range_occ_get), expected $occ"
+
+ log_test "port range occupancy after template create/destroy"
+}
+
trap cleanup EXIT
setup_prepare
diff --git a/tools/testing/selftests/net/amt.sh b/tools/testing/selftests/net/amt.sh
index 663744305e52..d13b20cccba9 100755
--- a/tools/testing/selftests/net/amt.sh
+++ b/tools/testing/selftests/net/amt.sh
@@ -150,6 +150,13 @@ setup_interface()
ip netns exec "${RELAY}" ip a a 10.0.0.2/24 dev relay_gw
ip netns exec "${RELAY}" ip link add amtr type amt mode relay \
local 10.0.0.2 dev relay_gw relay_port 2268 max_tunnels 4
+ # Count the IGMP and MLD queries that leave the relay through its own
+ # amt device; test_query_egress expects none.
+ ip netns exec "${RELAY}" tc qdisc add dev amtr clsact
+ ip netns exec "${RELAY}" tc filter add dev amtr egress pref 1 \
+ protocol ip flower ip_proto 0x2 action pass
+ ip netns exec "${RELAY}" tc filter add dev amtr egress pref 2 \
+ protocol ipv6 flower ip_proto icmpv6 type 130 action pass
ip netns exec "${RELAY}" ip a a 172.17.0.1/24 dev relay_src
ip netns exec "${RELAY}" ip a a 2001:db8:3::1/64 dev relay_src
ip netns exec "${SOURCE}" ip a a 172.17.0.2/24 dev src_relay
@@ -246,6 +253,27 @@ test_ipv6_forward()
fi
}
+# The relay sends its General Queries straight from the receive path, in
+# the same context that found the tunnel. A query queued on the amt device
+# instead could outlive the tunnel it was built for. The forwarding tests
+# above show that the gateway got its queries.
+test_query_egress()
+{
+ local n4 n6
+
+ n4=$(ip netns exec "${RELAY}" tc -s -j filter show dev amtr egress \
+ pref 1 | jq '[.[].options.actions[0].stats.packets // empty] | add // 0')
+ n6=$(ip netns exec "${RELAY}" tc -s -j filter show dev amtr egress \
+ pref 2 | jq '[.[].options.actions[0].stats.packets // empty] | add // 0')
+ if [ "$n4" -eq 0 ] && [ "$n6" -eq 0 ]; then
+ printf "TEST: %-60s [ OK ]\n" "amt relay queries bypass the amt device"
+ else
+ printf "TEST: %-60s [FAIL]\n" "amt relay queries bypass the amt device"
+ echo "IGMP queries on amtr egress: $n4, MLD queries: $n6" >&2
+ ERR=1
+ fi
+}
+
send_mcast4()
{
sleep 5
@@ -287,6 +315,7 @@ wait $pid || err=$?
if [ $err -eq 1 ]; then
ERR=1
fi
+test_query_egress
printf "TEST: %-50s" "IPv4 amt traffic forwarding torture"
send_mcast_torture4
printf " [ OK ]\n"
diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c
index abe488bac50b..afaa81c9bac5 100644
--- a/tools/testing/selftests/net/tun.c
+++ b/tools/testing/selftests/net/tun.c
@@ -9,6 +9,7 @@
#include <string.h>
#include <unistd.h>
#include <linux/if_tun.h>
+#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -542,6 +543,141 @@ TEST_F(tun, reattach_close_delete)
EXPECT_EQ(tun_delete(self->ifname), 0);
}
+FIXTURE(tun_vnet_gso)
+{
+ char ifname[IFNAMSIZ];
+ int fd;
+};
+
+FIXTURE_SETUP(tun_vnet_gso)
+{
+ int flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
+
+ memset(self->ifname, 0, sizeof(self->ifname));
+ self->fd = tun_open(self->ifname, flags, 0, 0, NULL);
+ ASSERT_GE(self->fd, 0);
+}
+
+FIXTURE_TEARDOWN(tun_vnet_gso)
+{
+ if (self->fd >= 0)
+ close(self->fd);
+}
+
+static int build_vlan_tcpv4_gso_packet(uint8_t *buf, int payload_len)
+{
+ uint16_t vlan_tag[2] = { htons(100), htons(ETH_P_IP) };
+ uint8_t *cur = buf + sizeof(struct virtio_net_hdr);
+ struct virtio_net_hdr vh = { 0 };
+ struct tcphdr tcph = { 0 };
+ uint32_t sum;
+
+ cur += build_eth(cur, ETH_P_8021Q, param_hwaddr_outer_src,
+ param_hwaddr_outer_dst);
+
+ /* 802.1Q tag: VID=100, inner protocol=ETH_P_IP */
+ memcpy(cur, vlan_tag, sizeof(vlan_tag));
+ cur += sizeof(vlan_tag);
+
+ cur += build_ipv4_header(cur, IPPROTO_TCP,
+ sizeof(tcph) + payload_len,
+ &param_ipaddr4_outer_src,
+ &param_ipaddr4_outer_dst);
+
+ tcph.source = htons(12345);
+ tcph.dest = htons(80);
+ tcph.seq = htonl(1);
+ tcph.doff = sizeof(tcph) / 4;
+ tcph.ack = 1;
+ tcph.window = htons(65535);
+ memcpy(cur, &tcph, sizeof(tcph));
+ memset(cur + sizeof(tcph), PKT_DATA, payload_len);
+
+ sum = add_csum((const uint8_t *)&param_ipaddr4_outer_src,
+ sizeof(param_ipaddr4_outer_src));
+ sum += add_csum((const uint8_t *)&param_ipaddr4_outer_dst,
+ sizeof(param_ipaddr4_outer_dst));
+ sum += htons(IPPROTO_TCP) + htons(sizeof(tcph) + payload_len);
+ sum += add_csum(cur, sizeof(tcph) + payload_len);
+ tcph.check = finish_ip_csum(sum);
+ memcpy(cur, &tcph, sizeof(tcph));
+ cur += sizeof(tcph) + payload_len;
+
+ vh.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+ vh.gso_size = 1400;
+ vh.hdr_len = (cur - buf) - sizeof(vh) - payload_len;
+ memcpy(buf, &vh, sizeof(vh));
+
+ return cur - buf;
+}
+
+TEST_F(tun_vnet_gso, vlan_tcpv4_gso_no_csum)
+{
+ struct virtio_net_hdr vh;
+ uint8_t pkt[4096] = { 0 };
+ int len, ret;
+
+ len = build_vlan_tcpv4_gso_packet(pkt, 2800);
+ memcpy(&vh, pkt, sizeof(vh));
+
+ /* Valid VLAN-tagged TCPv4 GSO with flags = 0 (no NEEDS_CSUM) */
+ vh.flags = 0;
+ memcpy(pkt, &vh, sizeof(vh));
+ ret = write(self->fd, pkt, len);
+ ASSERT_EQ(ret, len);
+
+ /* Valid VLAN-tagged TCPv4 GSO with flags = DATA_VALID */
+ vh.flags = VIRTIO_NET_HDR_F_DATA_VALID;
+ memcpy(pkt, &vh, sizeof(vh));
+ ret = write(self->fd, pkt, len);
+ ASSERT_EQ(ret, len);
+
+ /* Mismatched GSO type (TCPV6 on VLAN-tagged IPv4 packet) */
+ vh.flags = 0;
+ vh.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+ memcpy(pkt, &vh, sizeof(vh));
+ ret = write(self->fd, pkt, len);
+ ASSERT_EQ(ret, -1);
+ ASSERT_EQ(errno, EINVAL);
+
+ /* TCP header truncated after 10 bytes, without NEEDS_CSUM.
+ * Requires the transport header offset found by flow dissection:
+ * pulling only sizeof(struct iphdr) + sizeof(struct tcphdr) bytes
+ * from the mac header would accept this frame.
+ */
+ vh.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+ vh.hdr_len = ETH_HLEN + 4 + sizeof(struct iphdr) + 10;
+ memcpy(pkt, &vh, sizeof(vh));
+ ret = write(self->fd, pkt, sizeof(vh) + vh.hdr_len);
+ ASSERT_EQ(ret, -1);
+ ASSERT_EQ(errno, EINVAL);
+}
+
+TEST_F(tun_vnet_gso, vlan_tcpv4_gso_no_csum_64k)
+{
+ /* Ethernet frame of 65540 bytes: skb->len is above U16_MAX when the
+ * frame is flow-dissected, before eth_type_trans() pulls ETH_HLEN.
+ */
+ const int payload_len = 65540 - ETH_HLEN - 4 -
+ sizeof(struct iphdr) - sizeof(struct tcphdr);
+ struct virtio_net_hdr vh;
+ uint8_t *pkt;
+ int len, ret;
+
+ pkt = calloc(1, sizeof(vh) + 65540);
+ ASSERT_NE(pkt, NULL);
+
+ len = build_vlan_tcpv4_gso_packet(pkt, payload_len);
+ ASSERT_EQ(len, sizeof(vh) + 65540);
+ memcpy(&vh, pkt, sizeof(vh));
+
+ vh.flags = 0;
+ memcpy(pkt, &vh, sizeof(vh));
+ ret = write(self->fd, pkt, len);
+ free(pkt);
+ ASSERT_EQ(ret, len);
+}
+
FIXTURE(tun_vnet_udptnl)
{
char ifname[IFNAMSIZ];
diff --git a/tools/testing/selftests/net/veth.sh b/tools/testing/selftests/net/veth.sh
index 9709dd067c72..8b867e0675a7 100755
--- a/tools/testing/selftests/net/veth.sh
+++ b/tools/testing/selftests/net/veth.sh
@@ -9,6 +9,8 @@ readonly DST=1
readonly DST_NAT=100
readonly NS_SRC=$BASE$SRC
readonly NS_DST=$BASE$DST
+# shellcheck disable=SC2155 # prefer RO variable over return value from cmd
+readonly YNL="$(dirname "$(readlink -f "$0")")/../../../net/ynl/pyynl/cli.py"
# "baremetal" network used for raw UDP traffic
readonly BM_NET_V4=192.168.1.
@@ -74,6 +76,37 @@ chk_tso_flag() {
__chk_flag "$1" $2 $3 tcp-segmentation-offload
}
+chk_xdp_feature() {
+ local msg="$1"
+ local target=$2
+ local expected=$3
+ local feature=$4
+ local ifindex
+ local out
+ local st
+ local flag
+
+ ifindex=`ip netns exec $BASE$target cat /sys/class/net/veth$target/ifindex`
+ out=`ip netns exec $BASE$target "$YNL" --family netdev --do dev-get \
+ --output-json --json "{\"ifindex\": $ifindex}" 2>&1`
+ st=$?
+
+ printf "%-60s" "$msg"
+ if [ $st -ne 0 ]; then
+ echo " fail - ynl cli error: $out"
+ ret=1
+ return
+ fi
+
+ flag=`echo "$out" | grep -c "\"$feature\""`
+ if [ "$flag" = "$expected" ]; then
+ echo " ok "
+ else
+ echo " fail - expected $expected found $flag"
+ ret=1
+ fi
+}
+
chk_channels() {
local msg="$1"
local target=$2
@@ -222,6 +255,7 @@ fi
[ $CPUS -lt 2 ] && echo "Only one CPU available, some tests will be skipped"
[ $STRESS -gt 0 -a $CPUS -lt 3 ] && echo " stress test will be skipped, too"
+[ ! -f "$YNL" ] && echo "ynl cli not found, ndo-xmit tests will be skipped"
create_ns
chk_gro_flag "default - gro flag" $SRC off
@@ -283,6 +317,18 @@ chk_gro_flag " - peer gro flag" $SRC off
chk_tso_flag " - tso flag" $SRC on
chk_tso_flag " - peer tso flag" $DST on
ip -n $NS_DST link set dev veth$DST up
+if [ -f "$YNL" ]; then
+ chk_xdp_feature " - peer ndo-xmit" $SRC 1 ndo-xmit
+ # make sure the peer flag is set before disabling gro while down
+ ip netns exec $NS_DST ethtool -K veth$DST gro off
+ ip netns exec $NS_DST ethtool -K veth$DST gro on
+ chk_xdp_feature " - peer ndo-xmit re-armed" $SRC 1 ndo-xmit
+ ip -n $NS_DST link set dev veth$DST down
+ ip netns exec $NS_DST ethtool -K veth$DST gro off
+ ip -n $NS_DST link set dev veth$DST up
+ chk_xdp_feature " - peer ndo-xmit cleared" $SRC 0 ndo-xmit
+ ip netns exec $NS_DST ethtool -K veth$DST gro on
+fi
ip netns exec $NS_SRC ethtool -K veth$SRC tx-udp-segmentation off
ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
chk_gro " - aggregation with TSO off" 1
diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/route.json b/tools/testing/selftests/tc-testing/tc-tests/filters/route.json
index 2d5843aebd72..c3b6ff157d3e 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/filters/route.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/filters/route.json
@@ -412,5 +412,51 @@
"teardown": [
"$TC qdisc del dev $DEV1 ingress"
]
+ },
+ {
+ "id": "4000",
+ "name": "Change a wildcard route filter classid only (no routing attribute)",
+ "category": [
+ "filter",
+ "route"
+ ],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 ingress",
+ "$TC filter add dev $DEV1 parent ffff: protocol ip prio 100 route classid 1:1"
+ ],
+ "cmdUnderTest": "$TC filter change dev $DEV1 parent ffff: protocol ip prio 100 route classid 1:9",
+ "expExitCode": "0",
+ "verifyCmd": "$TC filter ls dev $DEV1 parent ffff:",
+ "matchPattern": "fh 0xffff8000 flowid 1:9",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 ingress"
+ ]
+ },
+ {
+ "id": "907a",
+ "name": "Try to change a route filter with no routing attribute and a non-wildcard handle",
+ "category": [
+ "filter",
+ "route"
+ ],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$TC qdisc add dev $DEV1 ingress",
+ "$TC filter add dev $DEV1 parent ffff: protocol ip prio 100 route from 1 to 1 classid 1:1"
+ ],
+ "cmdUnderTest": "$TC filter change dev $DEV1 parent ffff: protocol ip prio 100 handle 0x10001 route classid 1:2",
+ "expExitCode": "2",
+ "verifyCmd": "$TC filter ls dev $DEV1 parent ffff:",
+ "matchPattern": "fh 0x00010001 flowid 1:1 to 1 from 1",
+ "matchCount": "1",
+ "teardown": [
+ "$TC qdisc del dev $DEV1 ingress"
+ ]
}
]