From 85410f108fd876e368e66ce1ba6eaa30f4ebefab Mon Sep 17 00:00:00 2001 From: dlg Date: Sat, 26 Feb 2022 04:46:34 +0000 Subject: [PATCH] add the mbuf tag that prevents loops in vxlan_encap, not vxlan_output. vxlan_output calls ether_output, which will do arp for ipv4 packets. if arp hasn't resolved an address for a peer yet, it will queue the packet and transmit it again after resolution completes. the way it outputs is to call the interface output routine again, which is vxlan_output. if we tag the packet in vxlan_output before arp, and then arp calls vxlan_output again, it looks like a loop and drops it. moving the tagging to when we add all the encap headers in vxlan_encap avoids this issue. --- sys/net/if_vxlan.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/sys/net/if_vxlan.c b/sys/net/if_vxlan.c index c8d3bc48cd6..f057fa21c8f 100644 --- a/sys/net/if_vxlan.c +++ b/sys/net/if_vxlan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vxlan.c,v 1.89 2022/02/21 05:19:07 dlg Exp $ */ +/* $OpenBSD: if_vxlan.c,v 1.90 2022/02/26 04:46:34 dlg Exp $ */ /* * Copyright (c) 2021 David Gwynne @@ -324,6 +324,8 @@ vxlan_encap(struct vxlan_softc *sc, struct mbuf *m, struct mbuf *(ip_encap)(struct vxlan_softc *sc, struct mbuf *, const union vxlan_addr *, uint8_t)) { + struct ifnet *ifp = &sc->sc_ac.ac_if; + struct m_tag *mtag; struct mbuf *m0; union vxlan_addr gateway; const union vxlan_addr *endpoint; @@ -388,6 +390,13 @@ vxlan_encap(struct vxlan_softc *sc, struct mbuf *m, SET(m->m_pkthdr.csum_flags, M_UDP_CSUM_OUT); + mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); + if (mtag == NULL) + goto drop; + + *(int *)(mtag + 1) = ifp->if_index; + m_tag_prepend(m, mtag); + prio = sc->sc_txhprio; if (prio == IF_HDRPRIO_PACKET) prio = m->m_pkthdr.pf.prio; @@ -465,30 +474,16 @@ vxlan_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { struct m_tag *mtag; - int error = 0; mtag = NULL; while ((mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) != NULL) { - if (memcmp((caddr_t)(mtag + 1), &ifp->if_index, - sizeof(ifp->if_index)) == 0) { - error = EIO; - goto drop; + if (*(int *)(mtag + 1) == ifp->if_index) { + m_freem(m); + return (EIO); } } - mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); - if (mtag == NULL) { - error = ENOBUFS; - goto drop; - } - memcpy((caddr_t)(mtag + 1), &ifp->if_index, sizeof(ifp->if_index)); - m_tag_prepend(m, mtag); - return (ether_output(ifp, m, dst, rt)); - -drop: - m_freem(m); - return (error); } static int -- 2.20.1