From mboxrd@z Thu Jan 1 00:00:00 1970 From: David L Stevens Subject: [PATCHv8 net-next 4/4] sunvnet: generate ICMP PTMUD messages for smaller port MTUs Date: Mon, 29 Sep 2014 15:54:34 -0400 Message-ID: <5429B8FA.90108@oracle.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Cc: netdev@vger.kernel.org, Sowmini Varadhan , Raghuram Kothahota To: David Miller Return-path: Received: from aserp1040.oracle.com ([141.146.126.69]:46734 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751996AbaI2TyB (ORCPT ); Mon, 29 Sep 2014 15:54:01 -0400 Sender: netdev-owner@vger.kernel.org List-ID: 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 --- drivers/net/ethernet/sun/sunvnet.c | 37 +++++++++++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-) diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index e1f954c..b4e5303 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -17,6 +17,13 @@ #include #include +#if IS_ENABLED(CONFIG_IPV6) +#include +#endif + +#include +#include + #include #include @@ -887,8 +894,36 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(!skb)) goto out_dropped; - if (skb->len > port->rmtu) + if (skb->len > port->rmtu) { + unsigned long localmtu = port->rmtu - ETH_HLEN; + + if (vio_version_after_eq(&port->vio, 1, 3)) + localmtu -= VLAN_HLEN; + + if (skb->protocol == htons(ETH_P_IP)) { + struct flowi4 fl4; + struct rtable *rt = NULL; + + memset(&fl4, 0, sizeof(fl4)); + fl4.flowi4_oif = dev->ifindex; + fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); + fl4.daddr = ip_hdr(skb)->daddr; + fl4.saddr = ip_hdr(skb)->saddr; + + rt = ip_route_output_key(dev_net(dev), &fl4); + if (!IS_ERR(rt)) { + skb_dst_set(skb, &rt->dst); + icmp_send(skb, ICMP_DEST_UNREACH, + ICMP_FRAG_NEEDED, + htonl(localmtu)); + } + } +#if IS_ENABLED(CONFIG_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, localmtu); +#endif goto out_dropped; + } spin_lock_irqsave(&port->vio.lock, flags); -- 1.7.1