7e062cda7d
Core ---- - Support TCPv6 segmentation offload with super-segments larger than 64k bytes using the IPv6 Jumbogram extension header (AKA BIG TCP). - Generalize skb freeing deferral to per-cpu lists, instead of per-socket lists. - Add a netdev statistic for packets dropped due to L2 address mismatch (rx_otherhost_dropped). - Continue work annotating skb drop reasons. - Accept alternative netdev names (ALT_IFNAME) in more netlink requests. - Add VLAN support for AF_PACKET SOCK_RAW GSO. - Allow receiving skb mark from the socket as a cmsg. - Enable memcg accounting for veth queues, sysctl tables and IPv6. BPF --- - Add libbpf support for User Statically-Defined Tracing (USDTs). - Speed up symbol resolution for kprobes multi-link attachments. - Support storing typed pointers to referenced and unreferenced objects in BPF maps. - Add support for BPF link iterator. - Introduce access to remote CPU map elements in BPF per-cpu map. - Allow middle-of-the-road settings for the kernel.unprivileged_bpf_disabled sysctl. - Implement basic types of dynamic pointers e.g. to allow for dynamically sized ringbuf reservations without extra memory copies. Protocols --------- - Retire port only listening_hash table, add a second bind table hashed by port and address. Avoid linear list walk when binding to very popular ports (e.g. 443). - Add bridge FDB bulk flush filtering support allowing user space to remove all FDB entries matching a condition. - Introduce accept_unsolicited_na sysctl for IPv6 to implement router-side changes for RFC9131. - Support for MPTCP path manager in user space. - Add MPTCP support for fallback to regular TCP for connections that have never connected additional subflows or transmitted out-of-sequence data (partial support for RFC8684 fallback). - Avoid races in MPTCP-level window tracking, stabilize and improve throughput. - Support lockless operation of GRE tunnels with seq numbers enabled. - WiFi support for host based BSS color collision detection. - Add support for SO_TXTIME/SCM_TXTIME on CAN sockets. - Support transmission w/o flow control in CAN ISOTP (ISO 15765-2). - Support zero-copy Tx with TLS 1.2 crypto offload (sendfile). - Allow matching on the number of VLAN tags via tc-flower. - Add tracepoint for tcp_set_ca_state(). Driver API ---------- - Improve error reporting from classifier and action offload. - Add support for listing line cards in switches (devlink). - Add helpers for reporting page pool statistics with ethtool -S. - Add support for reading clock cycles when using PTP virtual clocks, instead of having the driver convert to time before reporting. This makes it possible to report time from different vclocks. - Support configuring low-latency Tx descriptor push via ethtool. - Separate Clause 22 and Clause 45 MDIO accesses more explicitly. New hardware / drivers ---------------------- - Ethernet: - Marvell's Octeon NIC PCI Endpoint support (octeon_ep) - Sunplus SP7021 SoC (sp7021_emac) - Add support for Renesas RZ/V2M (in ravb) - Add support for MediaTek mt7986 switches (in mtk_eth_soc) - Ethernet PHYs: - ADIN1100 industrial PHYs (w/ 10BASE-T1L and SQI reporting) - TI DP83TD510 PHY - Microchip LAN8742/LAN88xx PHYs - WiFi: - Driver for pureLiFi X, XL, XC devices (plfxlc) - Driver for Silicon Labs devices (wfx) - Support for WCN6750 (in ath11k) - Support Realtek 8852ce devices (in rtw89) - Mobile: - MediaTek T700 modems (Intel 5G 5000 M.2 cards) - CAN: - ctucanfd: add support for CTU CAN FD open-source IP core from Czech Technical University in Prague Drivers ------- - Delete a number of old drivers still using virt_to_bus(). - Ethernet NICs: - intel: support TSO on tunnels MPLS - broadcom: support multi-buffer XDP - nfp: support VF rate limiting - sfc: use hardware tx timestamps for more than PTP - mlx5: multi-port eswitch support - hyper-v: add support for XDP_REDIRECT - atlantic: XDP support (including multi-buffer) - macb: improve real-time perf by deferring Tx processing to NAPI - High-speed Ethernet switches: - mlxsw: implement basic line card information querying - prestera: add support for traffic policing on ingress and egress - Embedded Ethernet switches: - lan966x: add support for packet DMA (FDMA) - lan966x: add support for PTP programmable pins - ti: cpsw_new: enable bc/mc storm prevention - Qualcomm 802.11ax WiFi (ath11k): - Wake-on-WLAN support for QCA6390 and WCN6855 - device recovery (firmware restart) support - support setting Specific Absorption Rate (SAR) for WCN6855 - read country code from SMBIOS for WCN6855/QCA6390 - enable keep-alive during WoWLAN suspend - implement remain-on-channel support - MediaTek WiFi (mt76): - support Wireless Ethernet Dispatch offloading packet movement between the Ethernet switch and WiFi interfaces - non-standard VHT MCS10-11 support - mt7921 AP mode support - mt7921 IPv6 NS offload support - Ethernet PHYs: - micrel: ksz9031/ksz9131: cabletest support - lan87xx: SQI support for T1 PHYs - lan937x: add interrupt support for link detection Signed-off-by: Jakub Kicinski <kuba@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmKNMPQACgkQMUZtbf5S IrsRARAAuDyYs6jFYB3p+xazZdOnbF4iAgVv71+DQGvmsCl6CB9OrsNZMlvE85OL Q3gjcRbgjrkN4lhgI8DmiGYbsUJnAvVjFdNjccz1Z/vTLYvuIM0ol54MUp5S+9WY StncOJkOGJxxR/Gi5gzVmejPDsysU3Jik+hm/fpIcz8pybXxAsFKU5waY5qfl+/T TZepfV0VCfqRDjqcF1qA5+jJZNU8pdodQlZ1+mh8bwu6Jk1ZkWkj6Ov8MWdwQldr LnPeK/9hIGzkdJYHZfajxA3t8D0K5CHzSuih2bJ9ry8ZXgVBkXEThew778/R5izW uB0YZs9COFlrIP7XHjtRTy/2xHOdYIPlj2nWhVdfuQDX8Crvt4VRN6EZ1rjko1ZJ WanfG6WHF8NH5pXBRQbh3kIMKBnYn6OIzuCfCQSqd+niHcxFIM4vRiggeXI5C5TW vJgEWfK6X+NfDiFVa3xyCrEmp5ieA/pNecpwd8rVkql+MtFAAw4vfsotLKOJEAru J/XL6UE+YuLqIJV9ACZ9x1AFXXAo661jOxBunOo4VXhXVzWS9lYYz5r5ryIkgT/8 /Fr0zjANJWgfIuNdIBtYfQ4qG+LozGq038VA06RhFUAZ5tF9DzhqJs2Q2AFuWWBC ewCePJVqo1j2Ceq2mGonXRt47OEnlePoOxTk9W+cKZb7ZWE+zEo= =Wjii -----END PGP SIGNATURE----- Merge tag 'net-next-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next Pull networking updates from Jakub Kicinski: "Core ---- - Support TCPv6 segmentation offload with super-segments larger than 64k bytes using the IPv6 Jumbogram extension header (AKA BIG TCP). - Generalize skb freeing deferral to per-cpu lists, instead of per-socket lists. - Add a netdev statistic for packets dropped due to L2 address mismatch (rx_otherhost_dropped). - Continue work annotating skb drop reasons. - Accept alternative netdev names (ALT_IFNAME) in more netlink requests. - Add VLAN support for AF_PACKET SOCK_RAW GSO. - Allow receiving skb mark from the socket as a cmsg. - Enable memcg accounting for veth queues, sysctl tables and IPv6. BPF --- - Add libbpf support for User Statically-Defined Tracing (USDTs). - Speed up symbol resolution for kprobes multi-link attachments. - Support storing typed pointers to referenced and unreferenced objects in BPF maps. - Add support for BPF link iterator. - Introduce access to remote CPU map elements in BPF per-cpu map. - Allow middle-of-the-road settings for the kernel.unprivileged_bpf_disabled sysctl. - Implement basic types of dynamic pointers e.g. to allow for dynamically sized ringbuf reservations without extra memory copies. Protocols --------- - Retire port only listening_hash table, add a second bind table hashed by port and address. Avoid linear list walk when binding to very popular ports (e.g. 443). - Add bridge FDB bulk flush filtering support allowing user space to remove all FDB entries matching a condition. - Introduce accept_unsolicited_na sysctl for IPv6 to implement router-side changes for RFC9131. - Support for MPTCP path manager in user space. - Add MPTCP support for fallback to regular TCP for connections that have never connected additional subflows or transmitted out-of-sequence data (partial support for RFC8684 fallback). - Avoid races in MPTCP-level window tracking, stabilize and improve throughput. - Support lockless operation of GRE tunnels with seq numbers enabled. - WiFi support for host based BSS color collision detection. - Add support for SO_TXTIME/SCM_TXTIME on CAN sockets. - Support transmission w/o flow control in CAN ISOTP (ISO 15765-2). - Support zero-copy Tx with TLS 1.2 crypto offload (sendfile). - Allow matching on the number of VLAN tags via tc-flower. - Add tracepoint for tcp_set_ca_state(). Driver API ---------- - Improve error reporting from classifier and action offload. - Add support for listing line cards in switches (devlink). - Add helpers for reporting page pool statistics with ethtool -S. - Add support for reading clock cycles when using PTP virtual clocks, instead of having the driver convert to time before reporting. This makes it possible to report time from different vclocks. - Support configuring low-latency Tx descriptor push via ethtool. - Separate Clause 22 and Clause 45 MDIO accesses more explicitly. New hardware / drivers ---------------------- - Ethernet: - Marvell's Octeon NIC PCI Endpoint support (octeon_ep) - Sunplus SP7021 SoC (sp7021_emac) - Add support for Renesas RZ/V2M (in ravb) - Add support for MediaTek mt7986 switches (in mtk_eth_soc) - Ethernet PHYs: - ADIN1100 industrial PHYs (w/ 10BASE-T1L and SQI reporting) - TI DP83TD510 PHY - Microchip LAN8742/LAN88xx PHYs - WiFi: - Driver for pureLiFi X, XL, XC devices (plfxlc) - Driver for Silicon Labs devices (wfx) - Support for WCN6750 (in ath11k) - Support Realtek 8852ce devices (in rtw89) - Mobile: - MediaTek T700 modems (Intel 5G 5000 M.2 cards) - CAN: - ctucanfd: add support for CTU CAN FD open-source IP core from Czech Technical University in Prague Drivers ------- - Delete a number of old drivers still using virt_to_bus(). - Ethernet NICs: - intel: support TSO on tunnels MPLS - broadcom: support multi-buffer XDP - nfp: support VF rate limiting - sfc: use hardware tx timestamps for more than PTP - mlx5: multi-port eswitch support - hyper-v: add support for XDP_REDIRECT - atlantic: XDP support (including multi-buffer) - macb: improve real-time perf by deferring Tx processing to NAPI - High-speed Ethernet switches: - mlxsw: implement basic line card information querying - prestera: add support for traffic policing on ingress and egress - Embedded Ethernet switches: - lan966x: add support for packet DMA (FDMA) - lan966x: add support for PTP programmable pins - ti: cpsw_new: enable bc/mc storm prevention - Qualcomm 802.11ax WiFi (ath11k): - Wake-on-WLAN support for QCA6390 and WCN6855 - device recovery (firmware restart) support - support setting Specific Absorption Rate (SAR) for WCN6855 - read country code from SMBIOS for WCN6855/QCA6390 - enable keep-alive during WoWLAN suspend - implement remain-on-channel support - MediaTek WiFi (mt76): - support Wireless Ethernet Dispatch offloading packet movement between the Ethernet switch and WiFi interfaces - non-standard VHT MCS10-11 support - mt7921 AP mode support - mt7921 IPv6 NS offload support - Ethernet PHYs: - micrel: ksz9031/ksz9131: cabletest support - lan87xx: SQI support for T1 PHYs - lan937x: add interrupt support for link detection" * tag 'net-next-5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1809 commits) ptp: ocp: Add firmware header checks ptp: ocp: fix PPS source selector debugfs reporting ptp: ocp: add .init function for sma_op vector ptp: ocp: vectorize the sma accessor functions ptp: ocp: constify selectors ptp: ocp: parameterize input/output sma selectors ptp: ocp: revise firmware display ptp: ocp: add Celestica timecard PCI ids ptp: ocp: Remove #ifdefs around PCI IDs ptp: ocp: 32-bit fixups for pci start address Revert "net/smc: fix listen processing for SMC-Rv2" ath6kl: Use cc-disable-warning to disable -Wdangling-pointer selftests/bpf: Dynptr tests bpf: Add dynptr data slices bpf: Add bpf_dynptr_read and bpf_dynptr_write bpf: Dynptr support for ring buffers bpf: Add bpf_dynptr_from_mem for local dynptrs bpf: Add verifier support for dynptrs bpf: Suppress 'passing zero to PTR_ERR' warning bpf: Introduce bpf_arch_text_invalidate for bpf_prog_pack ...
685 lines
16 KiB
C
685 lines
16 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#include <kunit/test.h>
|
|
|
|
#include "utils.h"
|
|
|
|
struct mctp_test_route {
|
|
struct mctp_route rt;
|
|
struct sk_buff_head pkts;
|
|
};
|
|
|
|
static int mctp_test_route_output(struct mctp_route *rt, struct sk_buff *skb)
|
|
{
|
|
struct mctp_test_route *test_rt = container_of(rt, struct mctp_test_route, rt);
|
|
|
|
skb_queue_tail(&test_rt->pkts, skb);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* local version of mctp_route_alloc() */
|
|
static struct mctp_test_route *mctp_route_test_alloc(void)
|
|
{
|
|
struct mctp_test_route *rt;
|
|
|
|
rt = kzalloc(sizeof(*rt), GFP_KERNEL);
|
|
if (!rt)
|
|
return NULL;
|
|
|
|
INIT_LIST_HEAD(&rt->rt.list);
|
|
refcount_set(&rt->rt.refs, 1);
|
|
rt->rt.output = mctp_test_route_output;
|
|
|
|
skb_queue_head_init(&rt->pkts);
|
|
|
|
return rt;
|
|
}
|
|
|
|
static struct mctp_test_route *mctp_test_create_route(struct net *net,
|
|
struct mctp_dev *dev,
|
|
mctp_eid_t eid,
|
|
unsigned int mtu)
|
|
{
|
|
struct mctp_test_route *rt;
|
|
|
|
rt = mctp_route_test_alloc();
|
|
if (!rt)
|
|
return NULL;
|
|
|
|
rt->rt.min = eid;
|
|
rt->rt.max = eid;
|
|
rt->rt.mtu = mtu;
|
|
rt->rt.type = RTN_UNSPEC;
|
|
if (dev)
|
|
mctp_dev_hold(dev);
|
|
rt->rt.dev = dev;
|
|
|
|
list_add_rcu(&rt->rt.list, &net->mctp.routes);
|
|
|
|
return rt;
|
|
}
|
|
|
|
static void mctp_test_route_destroy(struct kunit *test,
|
|
struct mctp_test_route *rt)
|
|
{
|
|
unsigned int refs;
|
|
|
|
rtnl_lock();
|
|
list_del_rcu(&rt->rt.list);
|
|
rtnl_unlock();
|
|
|
|
skb_queue_purge(&rt->pkts);
|
|
if (rt->rt.dev)
|
|
mctp_dev_put(rt->rt.dev);
|
|
|
|
refs = refcount_read(&rt->rt.refs);
|
|
KUNIT_ASSERT_EQ_MSG(test, refs, 1, "route ref imbalance");
|
|
|
|
kfree_rcu(&rt->rt, rcu);
|
|
}
|
|
|
|
static struct sk_buff *mctp_test_create_skb(const struct mctp_hdr *hdr,
|
|
unsigned int data_len)
|
|
{
|
|
size_t hdr_len = sizeof(*hdr);
|
|
struct sk_buff *skb;
|
|
unsigned int i;
|
|
u8 *buf;
|
|
|
|
skb = alloc_skb(hdr_len + data_len, GFP_KERNEL);
|
|
if (!skb)
|
|
return NULL;
|
|
|
|
memcpy(skb_put(skb, hdr_len), hdr, hdr_len);
|
|
|
|
buf = skb_put(skb, data_len);
|
|
for (i = 0; i < data_len; i++)
|
|
buf[i] = i & 0xff;
|
|
|
|
return skb;
|
|
}
|
|
|
|
static struct sk_buff *__mctp_test_create_skb_data(const struct mctp_hdr *hdr,
|
|
const void *data,
|
|
size_t data_len)
|
|
{
|
|
size_t hdr_len = sizeof(*hdr);
|
|
struct sk_buff *skb;
|
|
|
|
skb = alloc_skb(hdr_len + data_len, GFP_KERNEL);
|
|
if (!skb)
|
|
return NULL;
|
|
|
|
memcpy(skb_put(skb, hdr_len), hdr, hdr_len);
|
|
memcpy(skb_put(skb, data_len), data, data_len);
|
|
|
|
return skb;
|
|
}
|
|
|
|
#define mctp_test_create_skb_data(h, d) \
|
|
__mctp_test_create_skb_data(h, d, sizeof(*d))
|
|
|
|
struct mctp_frag_test {
|
|
unsigned int mtu;
|
|
unsigned int msgsize;
|
|
unsigned int n_frags;
|
|
};
|
|
|
|
static void mctp_test_fragment(struct kunit *test)
|
|
{
|
|
const struct mctp_frag_test *params;
|
|
int rc, i, n, mtu, msgsize;
|
|
struct mctp_test_route *rt;
|
|
struct sk_buff *skb;
|
|
struct mctp_hdr hdr;
|
|
u8 seq;
|
|
|
|
params = test->param_value;
|
|
mtu = params->mtu;
|
|
msgsize = params->msgsize;
|
|
|
|
hdr.ver = 1;
|
|
hdr.src = 8;
|
|
hdr.dest = 10;
|
|
hdr.flags_seq_tag = MCTP_HDR_FLAG_TO;
|
|
|
|
skb = mctp_test_create_skb(&hdr, msgsize);
|
|
KUNIT_ASSERT_TRUE(test, skb);
|
|
|
|
rt = mctp_test_create_route(&init_net, NULL, 10, mtu);
|
|
KUNIT_ASSERT_TRUE(test, rt);
|
|
|
|
rc = mctp_do_fragment_route(&rt->rt, skb, mtu, MCTP_TAG_OWNER);
|
|
KUNIT_EXPECT_FALSE(test, rc);
|
|
|
|
n = rt->pkts.qlen;
|
|
|
|
KUNIT_EXPECT_EQ(test, n, params->n_frags);
|
|
|
|
for (i = 0;; i++) {
|
|
struct mctp_hdr *hdr2;
|
|
struct sk_buff *skb2;
|
|
u8 tag_mask, seq2;
|
|
bool first, last;
|
|
|
|
first = i == 0;
|
|
last = i == (n - 1);
|
|
|
|
skb2 = skb_dequeue(&rt->pkts);
|
|
|
|
if (!skb2)
|
|
break;
|
|
|
|
hdr2 = mctp_hdr(skb2);
|
|
|
|
tag_mask = MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO;
|
|
|
|
KUNIT_EXPECT_EQ(test, hdr2->ver, hdr.ver);
|
|
KUNIT_EXPECT_EQ(test, hdr2->src, hdr.src);
|
|
KUNIT_EXPECT_EQ(test, hdr2->dest, hdr.dest);
|
|
KUNIT_EXPECT_EQ(test, hdr2->flags_seq_tag & tag_mask,
|
|
hdr.flags_seq_tag & tag_mask);
|
|
|
|
KUNIT_EXPECT_EQ(test,
|
|
!!(hdr2->flags_seq_tag & MCTP_HDR_FLAG_SOM), first);
|
|
KUNIT_EXPECT_EQ(test,
|
|
!!(hdr2->flags_seq_tag & MCTP_HDR_FLAG_EOM), last);
|
|
|
|
seq2 = (hdr2->flags_seq_tag >> MCTP_HDR_SEQ_SHIFT) &
|
|
MCTP_HDR_SEQ_MASK;
|
|
|
|
if (first) {
|
|
seq = seq2;
|
|
} else {
|
|
seq++;
|
|
KUNIT_EXPECT_EQ(test, seq2, seq & MCTP_HDR_SEQ_MASK);
|
|
}
|
|
|
|
if (!last)
|
|
KUNIT_EXPECT_EQ(test, skb2->len, mtu);
|
|
else
|
|
KUNIT_EXPECT_LE(test, skb2->len, mtu);
|
|
|
|
kfree_skb(skb2);
|
|
}
|
|
|
|
mctp_test_route_destroy(test, rt);
|
|
}
|
|
|
|
static const struct mctp_frag_test mctp_frag_tests[] = {
|
|
{.mtu = 68, .msgsize = 63, .n_frags = 1},
|
|
{.mtu = 68, .msgsize = 64, .n_frags = 1},
|
|
{.mtu = 68, .msgsize = 65, .n_frags = 2},
|
|
{.mtu = 68, .msgsize = 66, .n_frags = 2},
|
|
{.mtu = 68, .msgsize = 127, .n_frags = 2},
|
|
{.mtu = 68, .msgsize = 128, .n_frags = 2},
|
|
{.mtu = 68, .msgsize = 129, .n_frags = 3},
|
|
{.mtu = 68, .msgsize = 130, .n_frags = 3},
|
|
};
|
|
|
|
static void mctp_frag_test_to_desc(const struct mctp_frag_test *t, char *desc)
|
|
{
|
|
sprintf(desc, "mtu %d len %d -> %d frags",
|
|
t->msgsize, t->mtu, t->n_frags);
|
|
}
|
|
|
|
KUNIT_ARRAY_PARAM(mctp_frag, mctp_frag_tests, mctp_frag_test_to_desc);
|
|
|
|
struct mctp_rx_input_test {
|
|
struct mctp_hdr hdr;
|
|
bool input;
|
|
};
|
|
|
|
static void mctp_test_rx_input(struct kunit *test)
|
|
{
|
|
const struct mctp_rx_input_test *params;
|
|
struct mctp_test_route *rt;
|
|
struct mctp_test_dev *dev;
|
|
struct sk_buff *skb;
|
|
|
|
params = test->param_value;
|
|
|
|
dev = mctp_test_create_dev();
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
|
|
|
rt = mctp_test_create_route(&init_net, dev->mdev, 8, 68);
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rt);
|
|
|
|
skb = mctp_test_create_skb(¶ms->hdr, 1);
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb);
|
|
|
|
__mctp_cb(skb);
|
|
|
|
mctp_pkttype_receive(skb, dev->ndev, &mctp_packet_type, NULL);
|
|
|
|
KUNIT_EXPECT_EQ(test, !!rt->pkts.qlen, params->input);
|
|
|
|
mctp_test_route_destroy(test, rt);
|
|
mctp_test_destroy_dev(dev);
|
|
}
|
|
|
|
#define RX_HDR(_ver, _src, _dest, _fst) \
|
|
{ .ver = _ver, .src = _src, .dest = _dest, .flags_seq_tag = _fst }
|
|
|
|
/* we have a route for EID 8 only */
|
|
static const struct mctp_rx_input_test mctp_rx_input_tests[] = {
|
|
{ .hdr = RX_HDR(1, 10, 8, 0), .input = true },
|
|
{ .hdr = RX_HDR(1, 10, 9, 0), .input = false }, /* no input route */
|
|
{ .hdr = RX_HDR(2, 10, 8, 0), .input = false }, /* invalid version */
|
|
};
|
|
|
|
static void mctp_rx_input_test_to_desc(const struct mctp_rx_input_test *t,
|
|
char *desc)
|
|
{
|
|
sprintf(desc, "{%x,%x,%x,%x}", t->hdr.ver, t->hdr.src, t->hdr.dest,
|
|
t->hdr.flags_seq_tag);
|
|
}
|
|
|
|
KUNIT_ARRAY_PARAM(mctp_rx_input, mctp_rx_input_tests,
|
|
mctp_rx_input_test_to_desc);
|
|
|
|
/* set up a local dev, route on EID 8, and a socket listening on type 0 */
|
|
static void __mctp_route_test_init(struct kunit *test,
|
|
struct mctp_test_dev **devp,
|
|
struct mctp_test_route **rtp,
|
|
struct socket **sockp)
|
|
{
|
|
struct sockaddr_mctp addr = {0};
|
|
struct mctp_test_route *rt;
|
|
struct mctp_test_dev *dev;
|
|
struct socket *sock;
|
|
int rc;
|
|
|
|
dev = mctp_test_create_dev();
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
|
|
|
rt = mctp_test_create_route(&init_net, dev->mdev, 8, 68);
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rt);
|
|
|
|
rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, &sock);
|
|
KUNIT_ASSERT_EQ(test, rc, 0);
|
|
|
|
addr.smctp_family = AF_MCTP;
|
|
addr.smctp_network = MCTP_NET_ANY;
|
|
addr.smctp_addr.s_addr = 8;
|
|
addr.smctp_type = 0;
|
|
rc = kernel_bind(sock, (struct sockaddr *)&addr, sizeof(addr));
|
|
KUNIT_ASSERT_EQ(test, rc, 0);
|
|
|
|
*rtp = rt;
|
|
*devp = dev;
|
|
*sockp = sock;
|
|
}
|
|
|
|
static void __mctp_route_test_fini(struct kunit *test,
|
|
struct mctp_test_dev *dev,
|
|
struct mctp_test_route *rt,
|
|
struct socket *sock)
|
|
{
|
|
sock_release(sock);
|
|
mctp_test_route_destroy(test, rt);
|
|
mctp_test_destroy_dev(dev);
|
|
}
|
|
|
|
struct mctp_route_input_sk_test {
|
|
struct mctp_hdr hdr;
|
|
u8 type;
|
|
bool deliver;
|
|
};
|
|
|
|
static void mctp_test_route_input_sk(struct kunit *test)
|
|
{
|
|
const struct mctp_route_input_sk_test *params;
|
|
struct sk_buff *skb, *skb2;
|
|
struct mctp_test_route *rt;
|
|
struct mctp_test_dev *dev;
|
|
struct socket *sock;
|
|
int rc;
|
|
|
|
params = test->param_value;
|
|
|
|
__mctp_route_test_init(test, &dev, &rt, &sock);
|
|
|
|
skb = mctp_test_create_skb_data(¶ms->hdr, ¶ms->type);
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb);
|
|
|
|
skb->dev = dev->ndev;
|
|
__mctp_cb(skb);
|
|
|
|
rc = mctp_route_input(&rt->rt, skb);
|
|
|
|
if (params->deliver) {
|
|
KUNIT_EXPECT_EQ(test, rc, 0);
|
|
|
|
skb2 = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc);
|
|
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, skb2);
|
|
KUNIT_EXPECT_EQ(test, skb->len, 1);
|
|
|
|
skb_free_datagram(sock->sk, skb2);
|
|
|
|
} else {
|
|
KUNIT_EXPECT_NE(test, rc, 0);
|
|
skb2 = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc);
|
|
KUNIT_EXPECT_NULL(test, skb2);
|
|
}
|
|
|
|
__mctp_route_test_fini(test, dev, rt, sock);
|
|
}
|
|
|
|
#define FL_S (MCTP_HDR_FLAG_SOM)
|
|
#define FL_E (MCTP_HDR_FLAG_EOM)
|
|
#define FL_TO (MCTP_HDR_FLAG_TO)
|
|
#define FL_T(t) ((t) & MCTP_HDR_TAG_MASK)
|
|
|
|
static const struct mctp_route_input_sk_test mctp_route_input_sk_tests[] = {
|
|
{ .hdr = RX_HDR(1, 10, 8, FL_S | FL_E | FL_TO), .type = 0, .deliver = true },
|
|
{ .hdr = RX_HDR(1, 10, 8, FL_S | FL_E | FL_TO), .type = 1, .deliver = false },
|
|
{ .hdr = RX_HDR(1, 10, 8, FL_S | FL_E), .type = 0, .deliver = false },
|
|
{ .hdr = RX_HDR(1, 10, 8, FL_E | FL_TO), .type = 0, .deliver = false },
|
|
{ .hdr = RX_HDR(1, 10, 8, FL_TO), .type = 0, .deliver = false },
|
|
{ .hdr = RX_HDR(1, 10, 8, 0), .type = 0, .deliver = false },
|
|
};
|
|
|
|
static void mctp_route_input_sk_to_desc(const struct mctp_route_input_sk_test *t,
|
|
char *desc)
|
|
{
|
|
sprintf(desc, "{%x,%x,%x,%x} type %d", t->hdr.ver, t->hdr.src,
|
|
t->hdr.dest, t->hdr.flags_seq_tag, t->type);
|
|
}
|
|
|
|
KUNIT_ARRAY_PARAM(mctp_route_input_sk, mctp_route_input_sk_tests,
|
|
mctp_route_input_sk_to_desc);
|
|
|
|
struct mctp_route_input_sk_reasm_test {
|
|
const char *name;
|
|
struct mctp_hdr hdrs[4];
|
|
int n_hdrs;
|
|
int rx_len;
|
|
};
|
|
|
|
static void mctp_test_route_input_sk_reasm(struct kunit *test)
|
|
{
|
|
const struct mctp_route_input_sk_reasm_test *params;
|
|
struct sk_buff *skb, *skb2;
|
|
struct mctp_test_route *rt;
|
|
struct mctp_test_dev *dev;
|
|
struct socket *sock;
|
|
int i, rc;
|
|
u8 c;
|
|
|
|
params = test->param_value;
|
|
|
|
__mctp_route_test_init(test, &dev, &rt, &sock);
|
|
|
|
for (i = 0; i < params->n_hdrs; i++) {
|
|
c = i;
|
|
skb = mctp_test_create_skb_data(¶ms->hdrs[i], &c);
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb);
|
|
|
|
skb->dev = dev->ndev;
|
|
__mctp_cb(skb);
|
|
|
|
rc = mctp_route_input(&rt->rt, skb);
|
|
}
|
|
|
|
skb2 = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc);
|
|
|
|
if (params->rx_len) {
|
|
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, skb2);
|
|
KUNIT_EXPECT_EQ(test, skb2->len, params->rx_len);
|
|
skb_free_datagram(sock->sk, skb2);
|
|
|
|
} else {
|
|
KUNIT_EXPECT_NULL(test, skb2);
|
|
}
|
|
|
|
__mctp_route_test_fini(test, dev, rt, sock);
|
|
}
|
|
|
|
#define RX_FRAG(f, s) RX_HDR(1, 10, 8, FL_TO | (f) | ((s) << MCTP_HDR_SEQ_SHIFT))
|
|
|
|
static const struct mctp_route_input_sk_reasm_test mctp_route_input_sk_reasm_tests[] = {
|
|
{
|
|
.name = "single packet",
|
|
.hdrs = {
|
|
RX_FRAG(FL_S | FL_E, 0),
|
|
},
|
|
.n_hdrs = 1,
|
|
.rx_len = 1,
|
|
},
|
|
{
|
|
.name = "single packet, offset seq",
|
|
.hdrs = {
|
|
RX_FRAG(FL_S | FL_E, 1),
|
|
},
|
|
.n_hdrs = 1,
|
|
.rx_len = 1,
|
|
},
|
|
{
|
|
.name = "start & end packets",
|
|
.hdrs = {
|
|
RX_FRAG(FL_S, 0),
|
|
RX_FRAG(FL_E, 1),
|
|
},
|
|
.n_hdrs = 2,
|
|
.rx_len = 2,
|
|
},
|
|
{
|
|
.name = "start & end packets, offset seq",
|
|
.hdrs = {
|
|
RX_FRAG(FL_S, 1),
|
|
RX_FRAG(FL_E, 2),
|
|
},
|
|
.n_hdrs = 2,
|
|
.rx_len = 2,
|
|
},
|
|
{
|
|
.name = "start & end packets, out of order",
|
|
.hdrs = {
|
|
RX_FRAG(FL_E, 1),
|
|
RX_FRAG(FL_S, 0),
|
|
},
|
|
.n_hdrs = 2,
|
|
.rx_len = 0,
|
|
},
|
|
{
|
|
.name = "start, middle & end packets",
|
|
.hdrs = {
|
|
RX_FRAG(FL_S, 0),
|
|
RX_FRAG(0, 1),
|
|
RX_FRAG(FL_E, 2),
|
|
},
|
|
.n_hdrs = 3,
|
|
.rx_len = 3,
|
|
},
|
|
{
|
|
.name = "missing seq",
|
|
.hdrs = {
|
|
RX_FRAG(FL_S, 0),
|
|
RX_FRAG(FL_E, 2),
|
|
},
|
|
.n_hdrs = 2,
|
|
.rx_len = 0,
|
|
},
|
|
{
|
|
.name = "seq wrap",
|
|
.hdrs = {
|
|
RX_FRAG(FL_S, 3),
|
|
RX_FRAG(FL_E, 0),
|
|
},
|
|
.n_hdrs = 2,
|
|
.rx_len = 2,
|
|
},
|
|
};
|
|
|
|
static void mctp_route_input_sk_reasm_to_desc(
|
|
const struct mctp_route_input_sk_reasm_test *t,
|
|
char *desc)
|
|
{
|
|
sprintf(desc, "%s", t->name);
|
|
}
|
|
|
|
KUNIT_ARRAY_PARAM(mctp_route_input_sk_reasm, mctp_route_input_sk_reasm_tests,
|
|
mctp_route_input_sk_reasm_to_desc);
|
|
|
|
struct mctp_route_input_sk_keys_test {
|
|
const char *name;
|
|
mctp_eid_t key_peer_addr;
|
|
mctp_eid_t key_local_addr;
|
|
u8 key_tag;
|
|
struct mctp_hdr hdr;
|
|
bool deliver;
|
|
};
|
|
|
|
/* test packet rx in the presence of various key configurations */
|
|
static void mctp_test_route_input_sk_keys(struct kunit *test)
|
|
{
|
|
const struct mctp_route_input_sk_keys_test *params;
|
|
struct mctp_test_route *rt;
|
|
struct sk_buff *skb, *skb2;
|
|
struct mctp_test_dev *dev;
|
|
struct mctp_sk_key *key;
|
|
struct netns_mctp *mns;
|
|
struct mctp_sock *msk;
|
|
struct socket *sock;
|
|
unsigned long flags;
|
|
int rc;
|
|
u8 c;
|
|
|
|
params = test->param_value;
|
|
|
|
dev = mctp_test_create_dev();
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
|
|
|
rt = mctp_test_create_route(&init_net, dev->mdev, 8, 68);
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rt);
|
|
|
|
rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, &sock);
|
|
KUNIT_ASSERT_EQ(test, rc, 0);
|
|
|
|
msk = container_of(sock->sk, struct mctp_sock, sk);
|
|
mns = &sock_net(sock->sk)->mctp;
|
|
|
|
/* set the incoming tag according to test params */
|
|
key = mctp_key_alloc(msk, params->key_local_addr, params->key_peer_addr,
|
|
params->key_tag, GFP_KERNEL);
|
|
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, key);
|
|
|
|
spin_lock_irqsave(&mns->keys_lock, flags);
|
|
mctp_reserve_tag(&init_net, key, msk);
|
|
spin_unlock_irqrestore(&mns->keys_lock, flags);
|
|
|
|
/* create packet and route */
|
|
c = 0;
|
|
skb = mctp_test_create_skb_data(¶ms->hdr, &c);
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb);
|
|
|
|
skb->dev = dev->ndev;
|
|
__mctp_cb(skb);
|
|
|
|
rc = mctp_route_input(&rt->rt, skb);
|
|
|
|
/* (potentially) receive message */
|
|
skb2 = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc);
|
|
|
|
if (params->deliver)
|
|
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, skb2);
|
|
else
|
|
KUNIT_EXPECT_PTR_EQ(test, skb2, NULL);
|
|
|
|
if (skb2)
|
|
skb_free_datagram(sock->sk, skb2);
|
|
|
|
mctp_key_unref(key);
|
|
__mctp_route_test_fini(test, dev, rt, sock);
|
|
}
|
|
|
|
static const struct mctp_route_input_sk_keys_test mctp_route_input_sk_keys_tests[] = {
|
|
{
|
|
.name = "direct match",
|
|
.key_peer_addr = 9,
|
|
.key_local_addr = 8,
|
|
.key_tag = 1,
|
|
.hdr = RX_HDR(1, 9, 8, FL_S | FL_E | FL_T(1)),
|
|
.deliver = true,
|
|
},
|
|
{
|
|
.name = "flipped src/dest",
|
|
.key_peer_addr = 8,
|
|
.key_local_addr = 9,
|
|
.key_tag = 1,
|
|
.hdr = RX_HDR(1, 9, 8, FL_S | FL_E | FL_T(1)),
|
|
.deliver = false,
|
|
},
|
|
{
|
|
.name = "peer addr mismatch",
|
|
.key_peer_addr = 9,
|
|
.key_local_addr = 8,
|
|
.key_tag = 1,
|
|
.hdr = RX_HDR(1, 10, 8, FL_S | FL_E | FL_T(1)),
|
|
.deliver = false,
|
|
},
|
|
{
|
|
.name = "tag value mismatch",
|
|
.key_peer_addr = 9,
|
|
.key_local_addr = 8,
|
|
.key_tag = 1,
|
|
.hdr = RX_HDR(1, 9, 8, FL_S | FL_E | FL_T(2)),
|
|
.deliver = false,
|
|
},
|
|
{
|
|
.name = "TO mismatch",
|
|
.key_peer_addr = 9,
|
|
.key_local_addr = 8,
|
|
.key_tag = 1,
|
|
.hdr = RX_HDR(1, 9, 8, FL_S | FL_E | FL_T(1) | FL_TO),
|
|
.deliver = false,
|
|
},
|
|
{
|
|
.name = "broadcast response",
|
|
.key_peer_addr = MCTP_ADDR_ANY,
|
|
.key_local_addr = 8,
|
|
.key_tag = 1,
|
|
.hdr = RX_HDR(1, 11, 8, FL_S | FL_E | FL_T(1)),
|
|
.deliver = true,
|
|
},
|
|
{
|
|
.name = "any local match",
|
|
.key_peer_addr = 12,
|
|
.key_local_addr = MCTP_ADDR_ANY,
|
|
.key_tag = 1,
|
|
.hdr = RX_HDR(1, 12, 8, FL_S | FL_E | FL_T(1)),
|
|
.deliver = true,
|
|
},
|
|
};
|
|
|
|
static void mctp_route_input_sk_keys_to_desc(
|
|
const struct mctp_route_input_sk_keys_test *t,
|
|
char *desc)
|
|
{
|
|
sprintf(desc, "%s", t->name);
|
|
}
|
|
|
|
KUNIT_ARRAY_PARAM(mctp_route_input_sk_keys, mctp_route_input_sk_keys_tests,
|
|
mctp_route_input_sk_keys_to_desc);
|
|
|
|
static struct kunit_case mctp_test_cases[] = {
|
|
KUNIT_CASE_PARAM(mctp_test_fragment, mctp_frag_gen_params),
|
|
KUNIT_CASE_PARAM(mctp_test_rx_input, mctp_rx_input_gen_params),
|
|
KUNIT_CASE_PARAM(mctp_test_route_input_sk, mctp_route_input_sk_gen_params),
|
|
KUNIT_CASE_PARAM(mctp_test_route_input_sk_reasm,
|
|
mctp_route_input_sk_reasm_gen_params),
|
|
KUNIT_CASE_PARAM(mctp_test_route_input_sk_keys,
|
|
mctp_route_input_sk_keys_gen_params),
|
|
{}
|
|
};
|
|
|
|
static struct kunit_suite mctp_test_suite = {
|
|
.name = "mctp",
|
|
.test_cases = mctp_test_cases,
|
|
};
|
|
|
|
kunit_test_suite(mctp_test_suite);
|