From patchwork Tue Jan 9 22:54:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Stokes, Ian" X-Patchwork-Id: 857822 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zGSBv20bjz9sBW for ; Wed, 10 Jan 2018 09:54:46 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 7623E5AC; Tue, 9 Jan 2018 22:54:30 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id BFE75FAB for ; Tue, 9 Jan 2018 22:54:29 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 20D5EE3 for ; Tue, 9 Jan 2018 22:54:29 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 09 Jan 2018 14:54:28 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,337,1511856000"; d="scan'208";a="19683642" Received: from sivswdev01.ir.intel.com (HELO localhost.localdomain) ([10.237.217.45]) by fmsmga004.fm.intel.com with ESMTP; 09 Jan 2018 14:54:27 -0800 From: Ian Stokes To: dev@openvswitch.org Date: Tue, 9 Jan 2018 22:54:25 +0000 Message-Id: <1515538465-15626-1-git-send-email-ian.stokes@intel.com> X-Mailer: git-send-email 1.7.0.7 X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [RFC PATCH v1 1/1] netdev-dpdk: Fix requested MTU size validation. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This commit replaces MTU_TO_FRAME_LEN(mtu) with MTU_TO_MAX_FRAME_LEN(mtu) when validating if an MTU will exceed NETDEV_DPDK_MAX_PKT_LEN in netdev_dpdk_set_mtu(). When setting an MTU we first check if the requested MTU frame size will exceed the maximum packet frame size supported in netdev_dpdk_set_mtu(). The MTU frame length is calculated as MTU + ETHER_HEADER + ETHER_CRC. The MTU for the device will be set at a later stage in dpdk_ethdev_init() using rte_ethdev_set_mtu(mtu). However when using rte_ethdev_set_mtu(mtu) the calculation used to check that the MTU does not exceed the max frame length for that device varies between DPDK device drivers. For example ixgbe driver calculates MTU frame length as mtu + ETHER_HDR_LEN + ETHER_CRC_LEN i40e driver calculates it as ETHER_HDR_LEN + ETHER_CRC_LEN + I40E_VLAN_TAG_SIZE * 2 em driver calculates it as mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + VLAN_TAG_SIZE Currently it is possible to set an MTU for a netdev_dpdk device that exceeds the upper limit MTU for that devices DPDK driver. This leads to a segfault. This is because the MTU frame length comparison as is, does not take into account the addition of the vlan tag overhead expected in the drivers. The netdev_dpdk_set_mtu() call will incorrectly succeed but the subsequent dpdk_ethdev_init() will fail before before queues have be created for DPDK device. This coupled with assumptions regarding reconfiguration requirements for the netdev will lead to a segfault when the rxq is polled for this device. A simple way to avoid this is by using MTU_TO_MAX_FRAME_LEN(mtu) when validating a requested MTU in netdev_dpdk_set_mtu() to account for vlan overhead required by some devices in MTU frame length. Note: this fix is a work around, a better approach would be if DPDK devices could report the maximum MTU value that can be requested on a per device basis. This capability however is not currently available. A downside of this patch is that the MTU upper limit will be reduced by 8 bytes for DPDK devices that do not need to account for vlan tags in MTU frame length driver calculations e.g. ixgbe devices upper MTU limit is reduced from the ovs point of view from 9710 to 9702. As this patch is RFC it has limited testing to i40e and ixgbe devices. If acceptable to the community documentation will also have to be updated under limitations I expect. CC: Mark Kavanagh Fixes: 0072e931 ("netdev-dpdk: add support for jumbo frames") Signed-off-by: Ian Stokes --- lib/netdev-dpdk.c | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-) diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index 364f545..4da5292 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -1999,7 +1999,16 @@ netdev_dpdk_set_mtu(struct netdev *netdev, int mtu) { struct netdev_dpdk *dev = netdev_dpdk_cast(netdev); - if (MTU_TO_FRAME_LEN(mtu) > NETDEV_DPDK_MAX_PKT_LEN + /* XXX: We need to ensure the requested MTU frame length does not + * surpass the NETDEV_DPDK_MAX_PKT_LEN. DPDK device drivers differ + * in how the MTU frame length is calculated when rte_ethdev_set_mtu(mtu) + * is called e.g. i40e and em drivers include vlan tags as part of the + * MTU frame length. As such we should use MTU_TO_MAX_FRAME_LEN(mtu) + * for comparison here to avoid a failure later with rte_ethdev_set_mtu(). + * This approach should be used until DPDK provides a method to retrieve + * maximum MTU frame length for a given device. + */ + if (MTU_TO_MAX_FRAME_LEN(mtu) > NETDEV_DPDK_MAX_PKT_LEN || mtu < ETHER_MIN_MTU) { VLOG_WARN("%s: unsupported MTU %d\n", dev->up.name, mtu); return EINVAL;