Skip to content

Commit c1a800e

Browse files
sbrivio-rhdavem330
authored andcommitted
geneve: Support for PMTU discovery on directly bridged links
If the interface is a bridge or Open vSwitch port, and we can't forward a packet because it exceeds the local PMTU estimate, trigger an ICMP or ICMPv6 reply to the sender, using the same interface to forward it back. If metadata collection is enabled, set destination and source addresses for the flow as if we were receiving the packet, so that Open vSwitch can match the ICMP error against the existing association. v2: Use netif_is_any_bridge_port() (David Ahern) Signed-off-by: Stefano Brivio <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fc68c99 commit c1a800e

File tree

1 file changed

+51
-5
lines changed

1 file changed

+51
-5
lines changed

drivers/net/geneve.c

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -893,8 +893,31 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
893893
if (IS_ERR(rt))
894894
return PTR_ERR(rt);
895895

896-
skb_tunnel_check_pmtu(skb, &rt->dst,
897-
GENEVE_IPV4_HLEN + info->options_len, false);
896+
err = skb_tunnel_check_pmtu(skb, &rt->dst,
897+
GENEVE_IPV4_HLEN + info->options_len,
898+
netif_is_any_bridge_port(dev));
899+
if (err < 0) {
900+
dst_release(&rt->dst);
901+
return err;
902+
} else if (err) {
903+
struct ip_tunnel_info *info;
904+
905+
info = skb_tunnel_info(skb);
906+
if (info) {
907+
info->key.u.ipv4.dst = fl4.saddr;
908+
info->key.u.ipv4.src = fl4.daddr;
909+
}
910+
911+
if (!pskb_may_pull(skb, ETH_HLEN)) {
912+
dst_release(&rt->dst);
913+
return -EINVAL;
914+
}
915+
916+
skb->protocol = eth_type_trans(skb, geneve->dev);
917+
netif_rx(skb);
918+
dst_release(&rt->dst);
919+
return -EMSGSIZE;
920+
}
898921

899922
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
900923
if (geneve->cfg.collect_md) {
@@ -955,8 +978,30 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
955978
if (IS_ERR(dst))
956979
return PTR_ERR(dst);
957980

958-
skb_tunnel_check_pmtu(skb, dst, GENEVE_IPV6_HLEN + info->options_len,
959-
false);
981+
err = skb_tunnel_check_pmtu(skb, dst,
982+
GENEVE_IPV6_HLEN + info->options_len,
983+
netif_is_any_bridge_port(dev));
984+
if (err < 0) {
985+
dst_release(dst);
986+
return err;
987+
} else if (err) {
988+
struct ip_tunnel_info *info = skb_tunnel_info(skb);
989+
990+
if (info) {
991+
info->key.u.ipv6.dst = fl6.saddr;
992+
info->key.u.ipv6.src = fl6.daddr;
993+
}
994+
995+
if (!pskb_may_pull(skb, ETH_HLEN)) {
996+
dst_release(dst);
997+
return -EINVAL;
998+
}
999+
1000+
skb->protocol = eth_type_trans(skb, geneve->dev);
1001+
netif_rx(skb);
1002+
dst_release(dst);
1003+
return -EMSGSIZE;
1004+
}
9601005

9611006
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
9621007
if (geneve->cfg.collect_md) {
@@ -1013,7 +1058,8 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
10131058
if (likely(!err))
10141059
return NETDEV_TX_OK;
10151060

1016-
dev_kfree_skb(skb);
1061+
if (err != -EMSGSIZE)
1062+
dev_kfree_skb(skb);
10171063

10181064
if (err == -ELOOP)
10191065
dev->stats.collisions++;

0 commit comments

Comments
 (0)