From patchwork Sun Mar 6 13:25:16 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nicolas_de_Peslo=C3=BCan?= X-Patchwork-Id: 85578 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id A0296B70EC for ; Mon, 7 Mar 2011 00:25:42 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752781Ab1CFNZi (ORCPT ); Sun, 6 Mar 2011 08:25:38 -0500 Received: from smtp6-g21.free.fr ([212.27.42.6]:57059 "EHLO smtp6-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752518Ab1CFNZh (ORCPT ); Sun, 6 Mar 2011 08:25:37 -0500 Received: from localhost.localdomain (unknown [88.175.177.37]) by smtp6-g21.free.fr (Postfix) with ESMTP id A2DD482384; Sun, 6 Mar 2011 14:25:28 +0100 (CET) From: =?UTF-8?q?Nicolas=20de=20Peslo=C3=BCan?= To: netdev@vger.kernel.org Cc: davem@davemloft.net, shemminger@vyatta.com, eric.dumazet@gmail.com, kaber@trash.net, fubar@us.ibm.com, andy@greyhouse.net, =?UTF-8?q?Nicolas=20de=20Peslo=C3=BCan?= Subject: [PATCH net-next-2.6] net: harmonize the call to ptype_all and ptype_base handlers. Date: Sun, 6 Mar 2011 14:25:16 +0100 Message-Id: <1299417916-14198-1-git-send-email-nicolas.2p.debian@free.fr> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <4D738751.6050209@gmail.com> References: <4D738751.6050209@gmail.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Until now, ptype_all and ptype_base delivery in __netif_receive_skb() is inconsistent. - For ptype_all, we deliver to every device crossed while walking the rx_handler path (inside the another_round loop), and there is no way to stop wildcard delivery (no exact match logic). - For ptype_base, we deliver to the lowest device (orig_dev) and to the highest (skb->dev) and we can ask for exact match delivery. This patch try and fix this, by: 1/ Doing exact match delivery for both ptype_all and ptype_base, while walking the rx_handler path. 2/ Doing wildcard match delivery at the end of __netif_receive_skb(), if not asked to do exact match delivery only. Signed-off-by: Nicolas de Pesloüan --- This apply on top of the last batch of patch from Jiri Pirko. --- net/core/dev.c | 32 ++++++++++++++++++++++++-------- 1 files changed, 24 insertions(+), 8 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index c71bd18..a368223 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3117,8 +3117,6 @@ static int __netif_receive_skb(struct sk_buff *skb) { struct packet_type *ptype, *pt_prev; rx_handler_func_t *rx_handler; - struct net_device *orig_dev; - struct net_device *null_or_dev; bool deliver_exact = false; int ret = NET_RX_DROP; __be16 type; @@ -3134,7 +3132,6 @@ static int __netif_receive_skb(struct sk_buff *skb) if (!skb->skb_iif) skb->skb_iif = skb->dev->ifindex; - orig_dev = skb->dev; skb_reset_network_header(skb); skb_reset_transport_header(skb); @@ -3156,7 +3153,17 @@ another_round: #endif list_for_each_entry_rcu(ptype, &ptype_all, list) { - if (!ptype->dev || ptype->dev == skb->dev) { + if (ptype->dev == skb->dev) { + if (pt_prev) + ret = deliver_skb(skb, pt_prev); + pt_prev = ptype; + } + } + + type = skb->protocol; + list_for_each_entry_rcu(ptype, + &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { + if (ptype->type == type && ptype->dev == skb->dev) { if (pt_prev) ret = deliver_skb(skb, pt_prev); pt_prev = ptype; @@ -3205,20 +3212,29 @@ ncls: vlan_on_bond_hook(skb); /* deliver only exact match when indicated */ - null_or_dev = deliver_exact ? skb->dev : NULL; + if (deliver_exact) + goto skip_wildcard_delivery; + + list_for_each_entry_rcu(ptype, &ptype_all, list) { + if (!ptype->dev) { + if (pt_prev) + ret = deliver_skb(skb, pt_prev); + pt_prev = ptype; + } + } type = skb->protocol; list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { - if (ptype->type == type && - (ptype->dev == null_or_dev || ptype->dev == skb->dev || - ptype->dev == orig_dev)) { + if (ptype->type == type && !ptype->dev) { if (pt_prev) ret = deliver_skb(skb, pt_prev); pt_prev = ptype; } } +skip_wildcard_delivery: + if (pt_prev) { ret = pt_prev->func(skb, skb->dev, pt_prev); } else {