1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2019 Synopsys, Inc. and/or its affiliates.
4 * stmmac Selftests Support
6 * Author: Jose Abreu <joabreu@synopsys.com>
8 * Ported from stmmac by:
9 * Copyright (C) 2021 Oleksij Rempel <o.rempel@pengutronix.de>
12 #include <linux/phy.h>
13 #include <net/selftests.h>
17 struct net_packet_attrs
{
18 const unsigned char *src
;
19 const unsigned char *dst
;
32 struct net_test_priv
{
33 struct net_packet_attrs
*packet
;
34 struct packet_type pt
;
35 struct completion comp
;
47 static u8 net_test_next_id
;
49 #define NET_TEST_PKT_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \
50 sizeof(struct netsfhdr))
51 #define NET_TEST_PKT_MAGIC 0xdeadcafecafedeadULL
52 #define NET_LB_TIMEOUT msecs_to_jiffies(200)
54 static struct sk_buff
*net_test_get_skb(struct net_device
*ndev
,
55 struct net_packet_attrs
*attr
)
57 struct sk_buff
*skb
= NULL
;
58 struct udphdr
*uhdr
= NULL
;
59 struct tcphdr
*thdr
= NULL
;
60 struct netsfhdr
*shdr
;
65 size
= attr
->size
+ NET_TEST_PKT_SIZE
;
68 size
+= sizeof(struct tcphdr
);
70 size
+= sizeof(struct udphdr
);
72 if (attr
->max_size
&& attr
->max_size
> size
)
73 size
= attr
->max_size
;
75 skb
= netdev_alloc_skb(ndev
, size
);
81 ehdr
= skb_push(skb
, ETH_HLEN
);
82 skb_reset_mac_header(skb
);
84 skb_set_network_header(skb
, skb
->len
);
85 ihdr
= skb_put(skb
, sizeof(*ihdr
));
87 skb_set_transport_header(skb
, skb
->len
);
89 thdr
= skb_put(skb
, sizeof(*thdr
));
91 uhdr
= skb_put(skb
, sizeof(*uhdr
));
93 eth_zero_addr(ehdr
->h_dest
);
96 ether_addr_copy(ehdr
->h_source
, attr
->src
);
98 ether_addr_copy(ehdr
->h_dest
, attr
->dst
);
100 ehdr
->h_proto
= htons(ETH_P_IP
);
103 thdr
->source
= htons(attr
->sport
);
104 thdr
->dest
= htons(attr
->dport
);
105 thdr
->doff
= sizeof(struct tcphdr
) / 4;
108 uhdr
->source
= htons(attr
->sport
);
109 uhdr
->dest
= htons(attr
->dport
);
110 uhdr
->len
= htons(sizeof(*shdr
) + sizeof(*uhdr
) + attr
->size
);
112 uhdr
->len
= htons(attr
->max_size
-
113 (sizeof(*ihdr
) + sizeof(*ehdr
)));
121 ihdr
->protocol
= IPPROTO_TCP
;
123 ihdr
->protocol
= IPPROTO_UDP
;
124 iplen
= sizeof(*ihdr
) + sizeof(*shdr
) + attr
->size
;
126 iplen
+= sizeof(*thdr
);
128 iplen
+= sizeof(*uhdr
);
131 iplen
= attr
->max_size
- sizeof(*ehdr
);
133 ihdr
->tot_len
= htons(iplen
);
135 ihdr
->saddr
= htonl(attr
->ip_src
);
136 ihdr
->daddr
= htonl(attr
->ip_dst
);
141 shdr
= skb_put(skb
, sizeof(*shdr
));
143 shdr
->magic
= cpu_to_be64(NET_TEST_PKT_MAGIC
);
144 attr
->id
= net_test_next_id
;
145 shdr
->id
= net_test_next_id
++;
148 skb_put(skb
, attr
->size
);
149 if (attr
->max_size
&& attr
->max_size
> skb
->len
)
150 skb_put(skb
, attr
->max_size
- skb
->len
);
153 skb
->ip_summed
= CHECKSUM_PARTIAL
;
155 thdr
->check
= ~tcp_v4_check(skb
->len
, ihdr
->saddr
,
157 skb
->csum_start
= skb_transport_header(skb
) - skb
->head
;
158 skb
->csum_offset
= offsetof(struct tcphdr
, check
);
160 udp4_hwcsum(skb
, ihdr
->saddr
, ihdr
->daddr
);
163 skb
->protocol
= htons(ETH_P_IP
);
164 skb
->pkt_type
= PACKET_HOST
;
170 static int net_test_loopback_validate(struct sk_buff
*skb
,
171 struct net_device
*ndev
,
172 struct packet_type
*pt
,
173 struct net_device
*orig_ndev
)
175 struct net_test_priv
*tpriv
= pt
->af_packet_priv
;
176 const unsigned char *src
= tpriv
->packet
->src
;
177 const unsigned char *dst
= tpriv
->packet
->dst
;
178 struct netsfhdr
*shdr
;
184 skb
= skb_unshare(skb
, GFP_ATOMIC
);
188 if (skb_linearize(skb
))
190 if (skb_headlen(skb
) < (NET_TEST_PKT_SIZE
- ETH_HLEN
))
193 ehdr
= (struct ethhdr
*)skb_mac_header(skb
);
195 if (!ether_addr_equal_unaligned(ehdr
->h_dest
, dst
))
200 if (!ether_addr_equal_unaligned(ehdr
->h_source
, src
))
205 if (tpriv
->double_vlan
)
206 ihdr
= (struct iphdr
*)(skb_network_header(skb
) + 4);
208 if (tpriv
->packet
->tcp
) {
209 if (ihdr
->protocol
!= IPPROTO_TCP
)
212 thdr
= (struct tcphdr
*)((u8
*)ihdr
+ 4 * ihdr
->ihl
);
213 if (thdr
->dest
!= htons(tpriv
->packet
->dport
))
216 shdr
= (struct netsfhdr
*)((u8
*)thdr
+ sizeof(*thdr
));
218 if (ihdr
->protocol
!= IPPROTO_UDP
)
221 uhdr
= (struct udphdr
*)((u8
*)ihdr
+ 4 * ihdr
->ihl
);
222 if (uhdr
->dest
!= htons(tpriv
->packet
->dport
))
225 shdr
= (struct netsfhdr
*)((u8
*)uhdr
+ sizeof(*uhdr
));
228 if (shdr
->magic
!= cpu_to_be64(NET_TEST_PKT_MAGIC
))
230 if (tpriv
->packet
->id
!= shdr
->id
)
234 complete(&tpriv
->comp
);
240 static int __net_test_loopback(struct net_device
*ndev
,
241 struct net_packet_attrs
*attr
)
243 struct net_test_priv
*tpriv
;
244 struct sk_buff
*skb
= NULL
;
247 tpriv
= kzalloc(sizeof(*tpriv
), GFP_KERNEL
);
252 init_completion(&tpriv
->comp
);
254 tpriv
->pt
.type
= htons(ETH_P_IP
);
255 tpriv
->pt
.func
= net_test_loopback_validate
;
256 tpriv
->pt
.dev
= ndev
;
257 tpriv
->pt
.af_packet_priv
= tpriv
;
258 tpriv
->packet
= attr
;
259 dev_add_pack(&tpriv
->pt
);
261 skb
= net_test_get_skb(ndev
, attr
);
267 ret
= dev_direct_xmit(skb
, attr
->queue_mapping
);
270 } else if (ret
> 0) {
276 attr
->timeout
= NET_LB_TIMEOUT
;
278 wait_for_completion_timeout(&tpriv
->comp
, attr
->timeout
);
279 ret
= tpriv
->ok
? 0 : -ETIMEDOUT
;
282 dev_remove_pack(&tpriv
->pt
);
287 static int net_test_netif_carrier(struct net_device
*ndev
)
289 return netif_carrier_ok(ndev
) ? 0 : -ENOLINK
;
292 static int net_test_phy_phydev(struct net_device
*ndev
)
294 return ndev
->phydev
? 0 : -EOPNOTSUPP
;
297 static int net_test_phy_loopback_enable(struct net_device
*ndev
)
302 return phy_loopback(ndev
->phydev
, true);
305 static int net_test_phy_loopback_disable(struct net_device
*ndev
)
310 return phy_loopback(ndev
->phydev
, false);
313 static int net_test_phy_loopback_udp(struct net_device
*ndev
)
315 struct net_packet_attrs attr
= { };
317 attr
.dst
= ndev
->dev_addr
;
318 return __net_test_loopback(ndev
, &attr
);
321 static int net_test_phy_loopback_udp_mtu(struct net_device
*ndev
)
323 struct net_packet_attrs attr
= { };
325 attr
.dst
= ndev
->dev_addr
;
326 attr
.max_size
= ndev
->mtu
;
327 return __net_test_loopback(ndev
, &attr
);
330 static int net_test_phy_loopback_tcp(struct net_device
*ndev
)
332 struct net_packet_attrs attr
= { };
334 attr
.dst
= ndev
->dev_addr
;
336 return __net_test_loopback(ndev
, &attr
);
339 static const struct net_test
{
340 char name
[ETH_GSTRING_LEN
];
341 int (*fn
)(struct net_device
*ndev
);
342 } net_selftests
[] = {
345 .fn
= net_test_netif_carrier
,
347 .name
= "PHY dev is present ",
348 .fn
= net_test_phy_phydev
,
350 /* This test should be done before all PHY loopback test */
351 .name
= "PHY internal loopback, enable ",
352 .fn
= net_test_phy_loopback_enable
,
354 .name
= "PHY internal loopback, UDP ",
355 .fn
= net_test_phy_loopback_udp
,
357 .name
= "PHY internal loopback, MTU ",
358 .fn
= net_test_phy_loopback_udp_mtu
,
360 .name
= "PHY internal loopback, TCP ",
361 .fn
= net_test_phy_loopback_tcp
,
363 /* This test should be done after all PHY loopback test */
364 .name
= "PHY internal loopback, disable",
365 .fn
= net_test_phy_loopback_disable
,
369 void net_selftest(struct net_device
*ndev
, struct ethtool_test
*etest
, u64
*buf
)
371 int count
= net_selftest_get_count();
374 memset(buf
, 0, sizeof(*buf
) * count
);
375 net_test_next_id
= 0;
377 if (etest
->flags
!= ETH_TEST_FL_OFFLINE
) {
378 netdev_err(ndev
, "Only offline tests are supported\n");
379 etest
->flags
|= ETH_TEST_FL_FAILED
;
384 for (i
= 0; i
< count
; i
++) {
385 buf
[i
] = net_selftests
[i
].fn(ndev
);
386 if (buf
[i
] && (buf
[i
] != -EOPNOTSUPP
))
387 etest
->flags
|= ETH_TEST_FL_FAILED
;
390 EXPORT_SYMBOL_GPL(net_selftest
);
392 int net_selftest_get_count(void)
394 return ARRAY_SIZE(net_selftests
);
396 EXPORT_SYMBOL_GPL(net_selftest_get_count
);
398 void net_selftest_get_strings(u8
*data
)
402 for (i
= 0; i
< net_selftest_get_count(); i
++)
403 ethtool_sprintf(&data
, "%2d. %s", i
+ 1,
404 net_selftests
[i
].name
);
406 EXPORT_SYMBOL_GPL(net_selftest_get_strings
);
408 MODULE_DESCRIPTION("Common library for generic PHY ethtool selftests");
409 MODULE_LICENSE("GPL v2");
410 MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");