0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/ip.h>
0034 #include <linux/udp.h>
0035 #include <net/udp.h>
0036 #include "en.h"
0037 #include "en/port.h"
0038 #include "eswitch.h"
0039
0040 static int mlx5e_test_health_info(struct mlx5e_priv *priv)
0041 {
0042 struct mlx5_core_health *health = &priv->mdev->priv.health;
0043
0044 return health->fatal_error ? 1 : 0;
0045 }
0046
0047 static int mlx5e_test_link_state(struct mlx5e_priv *priv)
0048 {
0049 u8 port_state;
0050
0051 if (!netif_carrier_ok(priv->netdev))
0052 return 1;
0053
0054 port_state = mlx5_query_vport_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_VNIC_VPORT, 0);
0055 return port_state == VPORT_STATE_UP ? 0 : 1;
0056 }
0057
0058 static int mlx5e_test_link_speed(struct mlx5e_priv *priv)
0059 {
0060 u32 speed;
0061
0062 if (!netif_carrier_ok(priv->netdev))
0063 return 1;
0064
0065 return mlx5e_port_linkspeed(priv->mdev, &speed);
0066 }
0067
0068 struct mlx5ehdr {
0069 __be32 version;
0070 __be64 magic;
0071 };
0072
0073 #ifdef CONFIG_INET
0074
0075 #define MLX5E_TEST_PKT_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) +\
0076 sizeof(struct udphdr) + sizeof(struct mlx5ehdr))
0077 #define MLX5E_TEST_MAGIC 0x5AEED15C001ULL
0078
0079 static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
0080 {
0081 struct sk_buff *skb = NULL;
0082 struct mlx5ehdr *mlxh;
0083 struct ethhdr *ethh;
0084 struct udphdr *udph;
0085 struct iphdr *iph;
0086 int iplen;
0087
0088 skb = netdev_alloc_skb(priv->netdev, MLX5E_TEST_PKT_SIZE);
0089 if (!skb) {
0090 netdev_err(priv->netdev, "\tFailed to alloc loopback skb\n");
0091 return NULL;
0092 }
0093
0094 net_prefetchw(skb->data);
0095 skb_reserve(skb, NET_IP_ALIGN);
0096
0097
0098 ethh = skb_push(skb, ETH_HLEN);
0099 skb_reset_mac_header(skb);
0100
0101 skb_set_network_header(skb, skb->len);
0102 iph = skb_put(skb, sizeof(struct iphdr));
0103
0104 skb_set_transport_header(skb, skb->len);
0105 udph = skb_put(skb, sizeof(struct udphdr));
0106
0107
0108 ether_addr_copy(ethh->h_dest, priv->netdev->dev_addr);
0109 eth_zero_addr(ethh->h_source);
0110 ethh->h_proto = htons(ETH_P_IP);
0111
0112
0113 udph->source = htons(9);
0114 udph->dest = htons(9);
0115 udph->len = htons(sizeof(struct mlx5ehdr) + sizeof(struct udphdr));
0116 udph->check = 0;
0117
0118
0119 iph->ihl = 5;
0120 iph->ttl = 32;
0121 iph->version = 4;
0122 iph->protocol = IPPROTO_UDP;
0123 iplen = sizeof(struct iphdr) + sizeof(struct udphdr) +
0124 sizeof(struct mlx5ehdr);
0125 iph->tot_len = htons(iplen);
0126 iph->frag_off = 0;
0127 iph->saddr = 0;
0128 iph->daddr = 0;
0129 iph->tos = 0;
0130 iph->id = 0;
0131 ip_send_check(iph);
0132
0133
0134 mlxh = skb_put(skb, sizeof(*mlxh));
0135 mlxh->version = 0;
0136 mlxh->magic = cpu_to_be64(MLX5E_TEST_MAGIC);
0137
0138 skb->csum = 0;
0139 skb->ip_summed = CHECKSUM_PARTIAL;
0140 udp4_hwcsum(skb, iph->saddr, iph->daddr);
0141
0142 skb->protocol = htons(ETH_P_IP);
0143 skb->pkt_type = PACKET_HOST;
0144 skb->dev = priv->netdev;
0145
0146 return skb;
0147 }
0148
0149 struct mlx5e_lbt_priv {
0150 struct packet_type pt;
0151 struct completion comp;
0152 bool loopback_ok;
0153 bool local_lb;
0154 };
0155
0156 static int
0157 mlx5e_test_loopback_validate(struct sk_buff *skb,
0158 struct net_device *ndev,
0159 struct packet_type *pt,
0160 struct net_device *orig_ndev)
0161 {
0162 struct mlx5e_lbt_priv *lbtp = pt->af_packet_priv;
0163 struct mlx5ehdr *mlxh;
0164 struct ethhdr *ethh;
0165 struct udphdr *udph;
0166 struct iphdr *iph;
0167
0168
0169 if (MLX5E_TEST_PKT_SIZE - ETH_HLEN > skb_headlen(skb))
0170 goto out;
0171
0172 ethh = (struct ethhdr *)skb_mac_header(skb);
0173 if (!ether_addr_equal(ethh->h_dest, orig_ndev->dev_addr))
0174 goto out;
0175
0176 iph = ip_hdr(skb);
0177 if (iph->protocol != IPPROTO_UDP)
0178 goto out;
0179
0180
0181 udph = (struct udphdr *)((u8 *)iph + 4 * iph->ihl);
0182 if (udph->dest != htons(9))
0183 goto out;
0184
0185 mlxh = (struct mlx5ehdr *)((char *)udph + sizeof(*udph));
0186 if (mlxh->magic != cpu_to_be64(MLX5E_TEST_MAGIC))
0187 goto out;
0188
0189
0190 lbtp->loopback_ok = true;
0191 complete(&lbtp->comp);
0192 out:
0193 kfree_skb(skb);
0194 return 0;
0195 }
0196
0197 static int mlx5e_test_loopback_setup(struct mlx5e_priv *priv,
0198 struct mlx5e_lbt_priv *lbtp)
0199 {
0200 int err = 0;
0201
0202
0203 err = mlx5_nic_vport_query_local_lb(priv->mdev, &lbtp->local_lb);
0204 if (err)
0205 return err;
0206
0207 if (!lbtp->local_lb) {
0208 err = mlx5_nic_vport_update_local_lb(priv->mdev, true);
0209 if (err)
0210 return err;
0211 }
0212
0213 err = mlx5e_refresh_tirs(priv, true, false);
0214 if (err)
0215 goto out;
0216
0217 lbtp->loopback_ok = false;
0218 init_completion(&lbtp->comp);
0219
0220 lbtp->pt.type = htons(ETH_P_IP);
0221 lbtp->pt.func = mlx5e_test_loopback_validate;
0222 lbtp->pt.dev = priv->netdev;
0223 lbtp->pt.af_packet_priv = lbtp;
0224 dev_add_pack(&lbtp->pt);
0225
0226 return 0;
0227
0228 out:
0229 if (!lbtp->local_lb)
0230 mlx5_nic_vport_update_local_lb(priv->mdev, false);
0231
0232 return err;
0233 }
0234
0235 static void mlx5e_test_loopback_cleanup(struct mlx5e_priv *priv,
0236 struct mlx5e_lbt_priv *lbtp)
0237 {
0238 if (!lbtp->local_lb)
0239 mlx5_nic_vport_update_local_lb(priv->mdev, false);
0240
0241 dev_remove_pack(&lbtp->pt);
0242 mlx5e_refresh_tirs(priv, false, false);
0243 }
0244
0245 static int mlx5e_cond_loopback(struct mlx5e_priv *priv)
0246 {
0247 if (is_mdev_switchdev_mode(priv->mdev))
0248 return -EOPNOTSUPP;
0249
0250 return 0;
0251 }
0252
0253 #define MLX5E_LB_VERIFY_TIMEOUT (msecs_to_jiffies(200))
0254 static int mlx5e_test_loopback(struct mlx5e_priv *priv)
0255 {
0256 struct mlx5e_lbt_priv *lbtp;
0257 struct sk_buff *skb = NULL;
0258 int err;
0259
0260 if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
0261 netdev_err(priv->netdev,
0262 "\tCan't perform loopback test while device is down\n");
0263 return -ENODEV;
0264 }
0265
0266 lbtp = kzalloc(sizeof(*lbtp), GFP_KERNEL);
0267 if (!lbtp)
0268 return -ENOMEM;
0269 lbtp->loopback_ok = false;
0270
0271 err = mlx5e_test_loopback_setup(priv, lbtp);
0272 if (err)
0273 goto out;
0274
0275 skb = mlx5e_test_get_udp_skb(priv);
0276 if (!skb) {
0277 err = -ENOMEM;
0278 goto cleanup;
0279 }
0280
0281 skb_set_queue_mapping(skb, 0);
0282 err = dev_queue_xmit(skb);
0283 if (err) {
0284 netdev_err(priv->netdev,
0285 "\tFailed to xmit loopback packet err(%d)\n",
0286 err);
0287 goto cleanup;
0288 }
0289
0290 wait_for_completion_timeout(&lbtp->comp, MLX5E_LB_VERIFY_TIMEOUT);
0291 err = !lbtp->loopback_ok;
0292
0293 cleanup:
0294 mlx5e_test_loopback_cleanup(priv, lbtp);
0295 out:
0296 kfree(lbtp);
0297 return err;
0298 }
0299 #endif
0300
0301 typedef int (*mlx5e_st_func)(struct mlx5e_priv *);
0302
0303 struct mlx5e_st {
0304 char name[ETH_GSTRING_LEN];
0305 mlx5e_st_func st_func;
0306 mlx5e_st_func cond_func;
0307 };
0308
0309 static struct mlx5e_st mlx5e_sts[] = {
0310 { "Link Test", mlx5e_test_link_state },
0311 { "Speed Test", mlx5e_test_link_speed },
0312 { "Health Test", mlx5e_test_health_info },
0313 #ifdef CONFIG_INET
0314 { "Loopback Test", mlx5e_test_loopback, mlx5e_cond_loopback },
0315 #endif
0316 };
0317
0318 #define MLX5E_ST_NUM ARRAY_SIZE(mlx5e_sts)
0319
0320 void mlx5e_self_test(struct net_device *ndev, struct ethtool_test *etest,
0321 u64 *buf)
0322 {
0323 struct mlx5e_priv *priv = netdev_priv(ndev);
0324 int i, count = 0;
0325
0326 mutex_lock(&priv->state_lock);
0327 netdev_info(ndev, "Self test begin..\n");
0328
0329 for (i = 0; i < MLX5E_ST_NUM; i++) {
0330 struct mlx5e_st st = mlx5e_sts[i];
0331
0332 if (st.cond_func && st.cond_func(priv))
0333 continue;
0334 netdev_info(ndev, "\t[%d] %s start..\n", i, st.name);
0335 buf[count] = st.st_func(priv);
0336 netdev_info(ndev, "\t[%d] %s end: result(%lld)\n", i, st.name, buf[count]);
0337 count++;
0338 }
0339
0340 mutex_unlock(&priv->state_lock);
0341
0342 for (i = 0; i < count; i++) {
0343 if (buf[i]) {
0344 etest->flags |= ETH_TEST_FL_FAILED;
0345 break;
0346 }
0347 }
0348 netdev_info(ndev, "Self test out: status flags(0x%x)\n",
0349 etest->flags);
0350 }
0351
0352 int mlx5e_self_test_fill_strings(struct mlx5e_priv *priv, u8 *data)
0353 {
0354 int i, count = 0;
0355
0356 for (i = 0; i < MLX5E_ST_NUM; i++) {
0357 struct mlx5e_st st = mlx5e_sts[i];
0358
0359 if (st.cond_func && st.cond_func(priv))
0360 continue;
0361 if (data)
0362 strcpy(data + count * ETH_GSTRING_LEN, st.name);
0363 count++;
0364 }
0365 return count;
0366 }
0367
0368 int mlx5e_self_test_num(struct mlx5e_priv *priv)
0369 {
0370 return mlx5e_self_test_fill_strings(priv, NULL);
0371 }