| From b842873600687335280024d84248261ee20ecae6 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 19 Mar 2021 14:33:37 -0400 |
| Subject: neighbour: Disregard DEAD dst in neigh_update |
| |
| From: Tong Zhu <zhutong@amazon.com> |
| |
| [ Upstream commit d47ec7a0a7271dda08932d6208e4ab65ab0c987c ] |
| |
| After a short network outage, the dst_entry is timed out and put |
| in DST_OBSOLETE_DEAD. We are in this code because arp reply comes |
| from this neighbour after network recovers. There is a potential |
| race condition that dst_entry is still in DST_OBSOLETE_DEAD. |
| With that, another neighbour lookup causes more harm than good. |
| |
| In best case all packets in arp_queue are lost. This is |
| counterproductive to the original goal of finding a better path |
| for those packets. |
| |
| I observed a worst case with 4.x kernel where a dst_entry in |
| DST_OBSOLETE_DEAD state is associated with loopback net_device. |
| It leads to an ethernet header with all zero addresses. |
| A packet with all zero source MAC address is quite deadly with |
| mac80211, ath9k and 802.11 block ack. It fails |
| ieee80211_find_sta_by_ifaddr in ath9k (xmit.c). Ath9k flushes tx |
| queue (ath_tx_complete_aggr). BAW (block ack window) is not |
| updated. BAW logic is damaged and ath9k transmission is disabled. |
| |
| Signed-off-by: Tong Zhu <zhutong@amazon.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/core/neighbour.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| diff --git a/net/core/neighbour.c b/net/core/neighbour.c |
| index 2fe4bbb6b80c..8339978d46ff 100644 |
| --- a/net/core/neighbour.c |
| +++ b/net/core/neighbour.c |
| @@ -1380,7 +1380,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, |
| * we can reinject the packet there. |
| */ |
| n2 = NULL; |
| - if (dst) { |
| + if (dst && dst->obsolete != DST_OBSOLETE_DEAD) { |
| n2 = dst_neigh_lookup_skb(dst, skb); |
| if (n2) |
| n1 = n2; |
| -- |
| 2.30.2 |
| |