|  | 
| 9 | 9 | #define ping_cmd "ping -q -c1 -w1 127.0.0.1 > /dev/null" | 
| 10 | 10 | 
 | 
| 11 | 11 | #include "test_tc_link.skel.h" | 
|  | 12 | + | 
|  | 13 | +#include "netlink_helpers.h" | 
| 12 | 14 | #include "tc_helpers.h" | 
| 13 | 15 | 
 | 
| 14 | 16 | void serial_test_tc_links_basic(void) | 
| @@ -1787,6 +1789,65 @@ void serial_test_tc_links_ingress(void) | 
| 1787 | 1789 | 	test_tc_links_ingress(BPF_TCX_INGRESS, false, false); | 
| 1788 | 1790 | } | 
| 1789 | 1791 | 
 | 
|  | 1792 | +struct qdisc_req { | 
|  | 1793 | +	struct nlmsghdr  n; | 
|  | 1794 | +	struct tcmsg     t; | 
|  | 1795 | +	char             buf[1024]; | 
|  | 1796 | +}; | 
|  | 1797 | + | 
|  | 1798 | +static int qdisc_replace(int ifindex, const char *kind, bool block) | 
|  | 1799 | +{ | 
|  | 1800 | +	struct rtnl_handle rth = { .fd = -1 }; | 
|  | 1801 | +	struct qdisc_req req; | 
|  | 1802 | +	int err; | 
|  | 1803 | + | 
|  | 1804 | +	err = rtnl_open(&rth, 0); | 
|  | 1805 | +	if (!ASSERT_OK(err, "open_rtnetlink")) | 
|  | 1806 | +		return err; | 
|  | 1807 | + | 
|  | 1808 | +	memset(&req, 0, sizeof(req)); | 
|  | 1809 | +	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)); | 
|  | 1810 | +	req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE | NLM_F_REQUEST; | 
|  | 1811 | +	req.n.nlmsg_type = RTM_NEWQDISC; | 
|  | 1812 | +	req.t.tcm_family = AF_UNSPEC; | 
|  | 1813 | +	req.t.tcm_ifindex = ifindex; | 
|  | 1814 | +	req.t.tcm_parent = 0xfffffff1; | 
|  | 1815 | + | 
|  | 1816 | +	addattr_l(&req.n, sizeof(req), TCA_KIND, kind, strlen(kind) + 1); | 
|  | 1817 | +	if (block) | 
|  | 1818 | +		addattr32(&req.n, sizeof(req), TCA_INGRESS_BLOCK, 1); | 
|  | 1819 | + | 
|  | 1820 | +	err = rtnl_talk(&rth, &req.n, NULL); | 
|  | 1821 | +	ASSERT_OK(err, "talk_rtnetlink"); | 
|  | 1822 | +	rtnl_close(&rth); | 
|  | 1823 | +	return err; | 
|  | 1824 | +} | 
|  | 1825 | + | 
|  | 1826 | +void serial_test_tc_links_dev_chain0(void) | 
|  | 1827 | +{ | 
|  | 1828 | +	int err, ifindex; | 
|  | 1829 | + | 
|  | 1830 | +	ASSERT_OK(system("ip link add dev foo type veth peer name bar"), "add veth"); | 
|  | 1831 | +	ifindex = if_nametoindex("foo"); | 
|  | 1832 | +	ASSERT_NEQ(ifindex, 0, "non_zero_ifindex"); | 
|  | 1833 | +	err = qdisc_replace(ifindex, "ingress", true); | 
|  | 1834 | +	if (!ASSERT_OK(err, "attaching ingress")) | 
|  | 1835 | +		goto cleanup; | 
|  | 1836 | +	ASSERT_OK(system("tc filter add block 1 matchall action skbmod swap mac"), "add block"); | 
|  | 1837 | +	err = qdisc_replace(ifindex, "clsact", false); | 
|  | 1838 | +	if (!ASSERT_OK(err, "attaching clsact")) | 
|  | 1839 | +		goto cleanup; | 
|  | 1840 | +	/* Heuristic: kern_sync_rcu() alone does not work; a wait-time of ~5s | 
|  | 1841 | +	 * triggered the issue without the fix reliably 100% of the time. | 
|  | 1842 | +	 */ | 
|  | 1843 | +	sleep(5); | 
|  | 1844 | +	ASSERT_OK(system("tc filter add dev foo ingress matchall action skbmod swap mac"), "add filter"); | 
|  | 1845 | +cleanup: | 
|  | 1846 | +	ASSERT_OK(system("ip link del dev foo"), "del veth"); | 
|  | 1847 | +	ASSERT_EQ(if_nametoindex("foo"), 0, "foo removed"); | 
|  | 1848 | +	ASSERT_EQ(if_nametoindex("bar"), 0, "bar removed"); | 
|  | 1849 | +} | 
|  | 1850 | + | 
| 1790 | 1851 | static void test_tc_links_dev_mixed(int target) | 
| 1791 | 1852 | { | 
| 1792 | 1853 | 	LIBBPF_OPTS(bpf_tc_opts, tc_opts, .handle = 1, .priority = 1); | 
|  | 
0 commit comments