From patchwork Tue Sep 6 19:10:43 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Javier Cardona X-Patchwork-Id: 1126942 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p86JB0Kv008985 for ; Tue, 6 Sep 2011 19:11:00 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754534Ab1IFTK4 (ORCPT ); Tue, 6 Sep 2011 15:10:56 -0400 Received: from mail-yx0-f174.google.com ([209.85.213.174]:64964 "EHLO mail-yx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754108Ab1IFTK4 (ORCPT ); Tue, 6 Sep 2011 15:10:56 -0400 Received: by yxj19 with SMTP id 19so3227207yxj.19 for ; Tue, 06 Sep 2011 12:10:55 -0700 (PDT) Received: by 10.68.6.168 with SMTP id c8mr9839700pba.166.1315336254931; Tue, 06 Sep 2011 12:10:54 -0700 (PDT) Received: from localhost.localdomain (99-8-184-170.lightspeed.snfcca.sbcglobal.net. [99.8.184.170]) by mx.google.com with ESMTPS id f6sm2066120pbp.2.2011.09.06.12.10.52 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 06 Sep 2011 12:10:52 -0700 (PDT) From: Javier Cardona To: "John W. Linville" Cc: Javier Cardona , Thomas Pedersen , devel@lists.open80211s.org, Johannes Berg , linux-wireless@vger.kernel.org, jlopex@gmail.com Subject: [PATCH v3] mac80211: Defer tranmission of mesh path errors Date: Tue, 6 Sep 2011 12:10:43 -0700 Message-Id: <1315336244-23351-1-git-send-email-javier@cozybit.com> X-Mailer: git-send-email 1.7.6 In-Reply-To: <1314961190.3927.6.camel@jlt3.sipsolutions.net> References: <1314961190.3927.6.camel@jlt3.sipsolutions.net> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Tue, 06 Sep 2011 19:11:00 +0000 (UTC) Under failure conditions, the mesh stack sends PERR messages to the previous sender of the failed frame. This happens in the tx feedback path, in which the transmission queue lock may be taken. Avoid a deadlock by sending the path error via the pending queue. --- v3: - Comment on headroom size (Johannes) v2: - Prepare skb for deferred transmission (Johannes) - Reword comment (Johannes) Signed-off-by: Javier Cardona Reviewed-by: Johannes Berg net/mac80211/mesh_hwmp.c | 32 ++++++++++++++++++++++++++++++-- 1 files changed, 30 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index fd4f76a..63df0bc 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -8,6 +8,7 @@ */ #include +#include "wme.h" #include "mesh.h" #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG @@ -202,6 +203,27 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, return 0; } + +/* Headroom is not adjusted. Caller should ensure that skb has sufficient + * headroom in case the frame is encrypted. */ +static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + skb_set_mac_header(skb, 0); + skb_set_network_header(skb, 0); + skb_set_transport_header(skb, 0); + + /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ + skb_set_queue_mapping(skb, IEEE80211_AC_VO); + skb->priority = 7; + + info->control.vif = &sdata->vif; + ieee80211_set_qos_hdr(local, skb); +} + /** * mesh_send_path error - Sends a PERR mesh management frame * @@ -209,6 +231,10 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, * @target_sn: SN of the broken destination * @target_rcode: reason code for this PERR * @ra: node this frame is addressed to + * + * Note: This function may be called with driver locks taken that the driver + * also acquires in the TX path. To avoid a deadlock we don't transmit the + * frame directly but add it to the pending queue instead. */ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, __le16 target_rcode, const u8 *ra, @@ -222,7 +248,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, if (!skb) return -1; - skb_reserve(skb, local->hw.extra_tx_headroom); + skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom); /* 25 is the size of the common mgmt part (24) plus the size of the * common action part (1) */ @@ -263,7 +289,9 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, pos += 4; memcpy(pos, &target_rcode, 2); - ieee80211_tx_skb(sdata, skb); + /* see note in function header */ + prepare_frame_for_deferred_tx(sdata, skb); + ieee80211_add_pending_skb(local, skb); return 0; }