From f1f3e0248b57e37a0fad8e8fe6846a5f9022afc6 Mon Sep 17 00:00:00 2001 From: Dongli Zhang Date: Fri, 22 Oct 2021 11:21:01 -0700 Subject: [PATCH 1/1] xen-netfront: send GARP during live migration This is based on commit be9eb2f00fa7, to reproduce the panic during live migration on purpose. The idea of the patch is to send GARP on purpose during live migration. Since it is very hard to reproduce the corner case on purpose, the patch would bypass q->enqueue() in __dev_queue_xmit(). [ 150.829622] xen_netfront: xendebug: arp_send() eth0 [ 150.837206] arp: xendebug: mark sk_buff as xendebug eth0 [ 150.844146] xendebug: bypass q->enqueue for eth0 [ 150.851117] BUG: unable to handle page fault for address: 000000000000e004 [ 150.861064] #PF: supervisor write access in kernel mode [ 150.868164] #PF: error_code(0x0002) - not-present page [ 150.875220] PGD 0 P4D 0 [ 150.878688] Oops: 0002 [#1] SMP PTI [ 150.883495] CPU: 10 PID: 148 Comm: xenwatch Kdump: loaded Tainted: G W 5.15.0-rc5xen+ #3 [ 150.896093] Hardware name: Xen HVM domU, BIOS 4.4.4OVM 06/18/2021 [ 150.903967] RIP: 0010:_raw_spin_lock_irqsave+0x19/0x30 ... ... [ 150.937989] RSP: 0018:ffffb523816f3c98 EFLAGS: 00010046 [ 150.944636] RAX: 0000000000000000 RBX: 0000000000000202 RCX: 000000000000002a [ 150.953802] RDX: 0000000000000001 RSI: 0000000000000000 RDI: 000000000000e004 [ 150.963047] RBP: 000000000000de00 R08: 0000000000000202 R09: 000000000000de00 [ 150.972058] R10: 0000000000000008 R11: ffffb523816f3ba8 R12: ffff892bcacd0000 [ 150.980858] R13: ffff892bccc26100 R14: 0000000000000202 R15: 0000000000000001 [ 150.989956] FS: 0000000000000000(0000) GS:ffff892cbf900000(0000) knlGS:0000000000000000 [ 150.999916] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 151.007124] CR2: 000000000000e004 CR3: 0000000112aec001 CR4: 00000000001706e0 [ 151.016049] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 151.024973] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 151.033706] Call Trace: [ 151.036899] xennet_start_xmit+0x16d/0x5a0 [xen_netfront] [ 151.043849] dev_hard_start_xmit+0xc4/0x1f0 [ 151.048039] __dev_queue_xmit+0x741/0x990 [ 151.051458] arp_send+0x1a/0x20 [ 151.054177] netback_changed+0xe30/0xef0 [xen_netfront] [ 151.058651] ? xenbus_read_driver_state+0x34/0x60 [ 151.062765] xenwatch_thread+0x98/0x160 [ 151.066520] ? wait_woken+0x60/0x60 [ 151.070056] ? find_watch+0x40/0x40 [ 151.073529] kthread+0x115/0x140 [ 151.076823] ? set_kthread_struct+0x40/0x40 [ 151.080845] ret_from_fork+0x22/0x30 [ 151.084350] Modules linked in: xen_kbdfront xen_fbfront xen_netfront xen_blkfront [ 151.091098] CR2: 000000000000e004 Signed-off-by: Dongli Zhang --- drivers/net/xen-netfront.c | 22 +++++++++++++++++++++- include/linux/skbuff.h | 2 ++ net/core/dev.c | 7 +++++++ net/ipv4/arp.c | 6 ++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index e31b98403f31..6ce625ab7e37 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -180,6 +181,20 @@ struct netfront_rx_info { struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1]; }; +static void xennet_send_garp(struct net_device *dev) +{ + struct in_device *in_dev = __in_dev_get_rtnl(dev); + const struct in_ifaddr *ifa; + + in_dev_for_each_ifa_rtnl(ifa, in_dev) { + pr_alert("xendebug: arp_send() %s\n", dev->name); + arp_send(ARPOP_REQUEST, ETH_P_ARP, + ifa->ifa_local, dev, + ifa->ifa_local, NULL, + dev->dev_addr, NULL); + } +} + /* * Access macros for acquiring freeing slots in tx_skbs[]. */ @@ -2188,8 +2203,13 @@ static int talk_to_netback(struct xenbus_device *dev, } rtnl_lock(); - if (info->queues) + if (info->queues) { xennet_destroy_queues(info); + /* + * To send GARP on purpose during live migration + */ + xennet_send_garp(info->netdev); + } /* For the case of a reconnect reset the "broken" indicator. */ info->broken = false; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 841e2f0f5240..036ec1307990 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -938,6 +938,8 @@ struct sk_buff { /* only useable after checking ->active_extensions != 0 */ struct skb_ext *extensions; #endif + + int xendebug; }; #ifdef __KERNEL__ diff --git a/net/core/dev.c b/net/core/dev.c index 7ee9fecd3aff..2861565bd499 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4166,11 +4166,18 @@ static int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) q = rcu_dereference_bh(txq->qdisc); trace_net_dev_queue(skb); + + if (skb->xendebug == 0x29) { + pr_alert("xendebug: bypass q->enqueue for %s\n", dev->name); + goto bypass; + } + if (q->enqueue) { rc = __dev_xmit_skb(skb, q, dev, txq); goto out; } +bypass: /* The device has no queue. Common case for software devices: * loopback, all the sorts of tunnels... diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 922dd73e5740..51cb43a6469b 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -315,6 +315,12 @@ static void arp_send_dst(int type, int ptype, __be32 dest_ip, if (!skb) return; + if (type == ARPOP_REQUEST && + dest_ip == src_ip) { + pr_alert("xendebug: mark sk_buff as xendebug %s\n", dev->name); + skb->xendebug = 0x29; + } + skb_dst_set(skb, dst_clone(dst)); arp_xmit(skb); } -- 2.17.1