Skip to content

Commit dc22482

Browse files
Toshiaki Makitaborkmann
authored andcommitted
veth: Avoid drops by oversized packets when XDP is enabled
Oversized packets including GSO packets can be dropped if XDP is enabled on receiver side, so don't send such packets from peer. Drop TSO and SCTP fragmentation features so that veth devices themselves segment packets with XDP enabled. Also cap MTU accordingly. v4: - Don't auto-adjust MTU but cap max MTU. Signed-off-by: Toshiaki Makita <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 948d4f2 commit dc22482

File tree

1 file changed

+45
-2
lines changed

1 file changed

+45
-2
lines changed

drivers/net/veth.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,23 @@ static int veth_get_iflink(const struct net_device *dev)
543543
return iflink;
544544
}
545545

546+
static netdev_features_t veth_fix_features(struct net_device *dev,
547+
netdev_features_t features)
548+
{
549+
struct veth_priv *priv = netdev_priv(dev);
550+
struct net_device *peer;
551+
552+
peer = rtnl_dereference(priv->peer);
553+
if (peer) {
554+
struct veth_priv *peer_priv = netdev_priv(peer);
555+
556+
if (peer_priv->_xdp_prog)
557+
features &= ~NETIF_F_GSO_SOFTWARE;
558+
}
559+
560+
return features;
561+
}
562+
546563
static void veth_set_rx_headroom(struct net_device *dev, int new_hr)
547564
{
548565
struct veth_priv *peer_priv, *priv = netdev_priv(dev);
@@ -572,6 +589,7 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
572589
struct veth_priv *priv = netdev_priv(dev);
573590
struct bpf_prog *old_prog;
574591
struct net_device *peer;
592+
unsigned int max_mtu;
575593
int err;
576594

577595
old_prog = priv->_xdp_prog;
@@ -585,21 +603,45 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
585603
goto err;
586604
}
587605

606+
max_mtu = PAGE_SIZE - VETH_XDP_HEADROOM -
607+
peer->hard_header_len -
608+
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
609+
if (peer->mtu > max_mtu) {
610+
NL_SET_ERR_MSG_MOD(extack, "Peer MTU is too large to set XDP");
611+
err = -ERANGE;
612+
goto err;
613+
}
614+
588615
if (dev->flags & IFF_UP) {
589616
err = veth_enable_xdp(dev);
590617
if (err) {
591618
NL_SET_ERR_MSG_MOD(extack, "Setup for XDP failed");
592619
goto err;
593620
}
594621
}
622+
623+
if (!old_prog) {
624+
peer->hw_features &= ~NETIF_F_GSO_SOFTWARE;
625+
peer->max_mtu = max_mtu;
626+
}
595627
}
596628

597629
if (old_prog) {
598-
if (!prog && dev->flags & IFF_UP)
599-
veth_disable_xdp(dev);
630+
if (!prog) {
631+
if (dev->flags & IFF_UP)
632+
veth_disable_xdp(dev);
633+
634+
if (peer) {
635+
peer->hw_features |= NETIF_F_GSO_SOFTWARE;
636+
peer->max_mtu = ETH_MAX_MTU;
637+
}
638+
}
600639
bpf_prog_put(old_prog);
601640
}
602641

642+
if ((!!old_prog ^ !!prog) && peer)
643+
netdev_update_features(peer);
644+
603645
return 0;
604646
err:
605647
priv->_xdp_prog = old_prog;
@@ -644,6 +686,7 @@ static const struct net_device_ops veth_netdev_ops = {
644686
.ndo_poll_controller = veth_poll_controller,
645687
#endif
646688
.ndo_get_iflink = veth_get_iflink,
689+
.ndo_fix_features = veth_fix_features,
647690
.ndo_features_check = passthru_features_check,
648691
.ndo_set_rx_headroom = veth_set_rx_headroom,
649692
.ndo_bpf = veth_xdp,

0 commit comments

Comments
 (0)