Commit a2b78e9b2cac897c7fb843922d49b2571dd84a76

Authored by David L Stevens
Committed by David S. Miller
1 parent 42db672dca

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