Commit a2b78e9b2cac897c7fb843922d49b2571dd84a76
Committed by
David S. Miller
1 parent
42db672dca
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
sunvnet: generate ICMP PTMUD messages for smaller port MTUs
This patch sends ICMP and ICMPv6 messages for Path MTU Discovery when a remote port MTU is smaller than the device MTU. This allows mixing newer VIO protocol devices that support MTU negotiation with older devices that do not on the same vswitch. It also allows Linux-Linux LDOMs to use 64K-1 data packets even though Solaris vswitch is limited to <16K MTU. Signed-off-by: David L Stevens <david.stevens@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 36 additions and 1 deletions Side-by-side Diff
drivers/net/ethernet/sun/sunvnet.c
... | ... | @@ -17,6 +17,13 @@ |
17 | 17 | #include <linux/mutex.h> |
18 | 18 | #include <linux/if_vlan.h> |
19 | 19 | |
20 | +#if IS_ENABLED(CONFIG_IPV6) | |
21 | +#include <linux/icmpv6.h> | |
22 | +#endif | |
23 | + | |
24 | +#include <net/icmp.h> | |
25 | +#include <net/route.h> | |
26 | + | |
20 | 27 | #include <asm/vio.h> |
21 | 28 | #include <asm/ldc.h> |
22 | 29 | |
23 | 30 | |
... | ... | @@ -913,8 +920,36 @@ |
913 | 920 | if (unlikely(!skb)) |
914 | 921 | goto out_dropped; |
915 | 922 | |
916 | - if (skb->len > port->rmtu) | |
923 | + if (skb->len > port->rmtu) { | |
924 | + unsigned long localmtu = port->rmtu - ETH_HLEN; | |
925 | + | |
926 | + if (vio_version_after_eq(&port->vio, 1, 3)) | |
927 | + localmtu -= VLAN_HLEN; | |
928 | + | |
929 | + if (skb->protocol == htons(ETH_P_IP)) { | |
930 | + struct flowi4 fl4; | |
931 | + struct rtable *rt = NULL; | |
932 | + | |
933 | + memset(&fl4, 0, sizeof(fl4)); | |
934 | + fl4.flowi4_oif = dev->ifindex; | |
935 | + fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); | |
936 | + fl4.daddr = ip_hdr(skb)->daddr; | |
937 | + fl4.saddr = ip_hdr(skb)->saddr; | |
938 | + | |
939 | + rt = ip_route_output_key(dev_net(dev), &fl4); | |
940 | + if (!IS_ERR(rt)) { | |
941 | + skb_dst_set(skb, &rt->dst); | |
942 | + icmp_send(skb, ICMP_DEST_UNREACH, | |
943 | + ICMP_FRAG_NEEDED, | |
944 | + htonl(localmtu)); | |
945 | + } | |
946 | + } | |
947 | +#if IS_ENABLED(CONFIG_IPV6) | |
948 | + else if (skb->protocol == htons(ETH_P_IPV6)) | |
949 | + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, localmtu); | |
950 | +#endif | |
917 | 951 | goto out_dropped; |
952 | + } | |
918 | 953 | |
919 | 954 | spin_lock_irqsave(&port->vio.lock, flags); |
920 | 955 |