aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-03-29 09:03:07 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-03-31 11:38:26 +0000
commitbaacf701372bfeb3927c6b9e0b85d6eff198c6a3 (patch)
tree86d251406f7f8f96b463b042996948f29d4a214f
parente243367b644562c9410b39f8d78dafdb7e785d85 (diff)
downloadsrc-baacf701372bfeb3927c6b9e0b85d6eff198c6a3.tar.gz
src-baacf701372bfeb3927c6b9e0b85d6eff198c6a3.zip
vxlan: correct interface MTU when using hw offloads
Otherwise it breaks when offloading like checksum or TSO are used, because second (encapsulated) ip_output() processing passes fragments of the encapsulated packet down to the hardware interface. Diagnosed by: hselasky Reviewed by: np Sponsored by: Nvidia Networking / Mellanox Technologies MFC after: 1 week Differential revision: https://reviews.freebsd.org/D29501
-rw-r--r--share/man/man4/vxlan.415
-rw-r--r--sys/net/if_vxlan.c17
2 files changed, 28 insertions, 4 deletions
diff --git a/share/man/man4/vxlan.4 b/share/man/man4/vxlan.4
index 1848897d97c9..99f3411c02d2 100644
--- a/share/man/man4/vxlan.4
+++ b/share/man/man4/vxlan.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 17, 2020
+.Dd March 30, 2021
.Dt VXLAN 4
.Os
.Sh NAME
@@ -175,13 +175,24 @@ The
.Nm
specification recommends the physical network MTU be configured
to use jumbo frames to accommodate the encapsulated frame size.
+.Pp
+By default, the
+.Nm
+driver sets its MTU to usual ethernet MTU of 1500 bytes, reduced by
+the size of vxlan headers prepended to the encapsulated packets.
+.Pp
Alternatively, the
.Xr ifconfig 8
.Cm mtu
-command may be used to reduce the MTU size on the
+command may be used to set the fixed MTU size on the
.Nm
interface to allow the encapsulated frame to fit in the
current MTU of the physical network.
+If the
+.Cm mtu
+command was used, system no longer adjust the
+.Nm
+interface MTU on routing or address changes.
.Sh HARDWARE
The
.Nm
diff --git a/sys/net/if_vxlan.c b/sys/net/if_vxlan.c
index 0d69244ce64b..f56ec23540a7 100644
--- a/sys/net/if_vxlan.c
+++ b/sys/net/if_vxlan.c
@@ -171,6 +171,7 @@ struct vxlan_softc {
#define VXLAN_FLAG_INIT 0x0001
#define VXLAN_FLAG_TEARDOWN 0x0002
#define VXLAN_FLAG_LEARN 0x0004
+#define VXLAN_FLAG_USER_MTU 0x0008
uint32_t vxl_port_hash_key;
uint16_t vxl_min_port;
@@ -1620,6 +1621,8 @@ vxlan_setup_interface_hdrlen(struct vxlan_softc *sc)
{
struct ifnet *ifp;
+ VXLAN_LOCK_WASSERT(sc);
+
ifp = sc->vxl_ifp;
ifp->if_hdrlen = ETHER_HDR_LEN + sizeof(struct vxlanudphdr);
@@ -1627,6 +1630,9 @@ vxlan_setup_interface_hdrlen(struct vxlan_softc *sc)
ifp->if_hdrlen += sizeof(struct ip);
else if (VXLAN_SOCKADDR_IS_IPV6(&sc->vxl_dst_addr) != 0)
ifp->if_hdrlen += sizeof(struct ip6_hdr);
+
+ if ((sc->vxl_flags & VXLAN_FLAG_USER_MTU) == 0)
+ ifp->if_mtu = ETHERMTU - ifp->if_hdrlen;
}
static int
@@ -2354,10 +2360,14 @@ vxlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
case SIOCSIFMTU:
- if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > VXLAN_MAX_MTU)
+ if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > VXLAN_MAX_MTU) {
error = EINVAL;
- else
+ } else {
+ VXLAN_WLOCK(sc);
ifp->if_mtu = ifr->ifr_mtu;
+ sc->vxl_flags |= VXLAN_FLAG_USER_MTU;
+ VXLAN_WUNLOCK(sc);
+ }
break;
case SIOCSIFCAP:
@@ -3211,7 +3221,10 @@ vxlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
ether_ifattach(ifp, sc->vxl_hwaddr.octet);
ifp->if_baudrate = 0;
+
+ VXLAN_WLOCK(sc);
vxlan_setup_interface_hdrlen(sc);
+ VXLAN_WUNLOCK(sc);
return (0);