From patchwork Tue May 8 16:41:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Lindner X-Patchwork-Id: 17343 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 102CB823A2; Tue, 8 May 2018 19:17:54 +0200 (CEST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=5.148.176.60; helo=s2.neomailbox.net; envelope-from=mareklindner@neomailbox.ch; receiver= Received: from s2.neomailbox.net (s2.neomailbox.net [5.148.176.60]) by open-mesh.org (Postfix) with ESMTPS id EDFD1806A5 for ; Tue, 8 May 2018 19:17:52 +0200 (CEST) From: Marek Lindner To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 9 May 2018 00:41:25 +0800 Message-Id: <20180508164130.8633-2-mareklindner@neomailbox.ch> In-Reply-To: <20180508164130.8633-1-mareklindner@neomailbox.ch> References: <20180508164130.8633-1-mareklindner@neomailbox.ch> Subject: [B.A.T.M.A.N.] [RFC 1/6] batman-adv: tp_meter - prevent concurrent tp_meter sessions by using workqueue X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Cc: Antonio Quartulli Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" From: Antonio Quartulli To ensure that no more than one tp_meter session runs at the same time, use an ordered workqueue instead of spawning one kthread per session. Signed-off-by: Antonio Quartulli --- net/batman-adv/main.c | 10 ++++-- net/batman-adv/tp_meter.c | 73 ++++++++++++++++++--------------------- net/batman-adv/tp_meter.h | 3 +- net/batman-adv/types.h | 5 ++- 4 files changed, 48 insertions(+), 43 deletions(-) diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 69c0d85b..cd3f1924 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -91,6 +91,10 @@ static int __init batadv_init(void) if (ret < 0) return ret; + ret = batadv_tp_meter_init(); + if (ret < 0) + goto err_tp_meter; + INIT_LIST_HEAD(&batadv_hardif_list); batadv_algo_init(); @@ -99,7 +103,6 @@ static int __init batadv_init(void) batadv_v_init(); batadv_iv_init(); batadv_nc_init(); - batadv_tp_meter_init(); batadv_event_workqueue = create_singlethread_workqueue("bat_events"); if (!batadv_event_workqueue) @@ -118,9 +121,11 @@ static int __init batadv_init(void) return 0; err_create_wq: + batadv_tp_meter_destroy(); +err_tp_meter: batadv_tt_cache_destroy(); - return -ENOMEM; + return ret; } static void __exit batadv_exit(void) @@ -138,6 +143,7 @@ static void __exit batadv_exit(void) rcu_barrier(); batadv_tt_cache_destroy(); + batadv_tp_meter_destroy(); } /** diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index 11520de9..55e93abc 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -97,6 +96,9 @@ static u8 batadv_tp_prerandom[4096] __read_mostly; +/* ordered work queue */ +static struct workqueue_struct *batadv_tp_meter_queue; + /** * batadv_tp_session_cookie() - generate session cookie based on session ids * @session: TP session identifier @@ -812,15 +814,18 @@ static int batadv_tp_wait_available(struct batadv_tp_vars *tp_vars, size_t plen) * * Return: nothing, this function never returns */ -static int batadv_tp_send(void *arg) +static void batadv_tp_send(struct work_struct *work) { - struct batadv_tp_vars *tp_vars = arg; - struct batadv_priv *bat_priv = tp_vars->bat_priv; struct batadv_hard_iface *primary_if = NULL; struct batadv_orig_node *orig_node = NULL; + struct batadv_tp_vars *tp_vars; size_t payload_len, packet_len; + struct batadv_priv *bat_priv; int err = 0; + tp_vars = container_of(work, struct batadv_tp_vars, test_work); + bat_priv = tp_vars->bat_priv; + if (unlikely(tp_vars->role != BATADV_TP_SENDER)) { err = BATADV_TP_REASON_DST_UNREACHABLE; tp_vars->reason = err; @@ -901,40 +906,17 @@ static int batadv_tp_send(void *arg) batadv_tp_sender_cleanup(bat_priv, tp_vars); batadv_tp_vars_put(tp_vars); - - do_exit(0); } /** - * batadv_tp_start_kthread() - start new thread which manages the tp meter - * sender + * batadv_tp_start_work - start new thread which manages the tp meter sender * @tp_vars: the private data of the current TP meter session */ -static void batadv_tp_start_kthread(struct batadv_tp_vars *tp_vars) +static void batadv_tp_start_work(struct batadv_tp_vars *tp_vars) { - struct task_struct *kthread; - struct batadv_priv *bat_priv = tp_vars->bat_priv; - u32 session_cookie; - - kref_get(&tp_vars->refcount); - kthread = kthread_create(batadv_tp_send, tp_vars, "kbatadv_tp_meter"); - if (IS_ERR(kthread)) { - session_cookie = batadv_tp_session_cookie(tp_vars->session, - tp_vars->icmp_uid); - pr_err("batadv: cannot create tp meter kthread\n"); - batadv_tp_batctl_error_notify(BATADV_TP_REASON_MEMORY_ERROR, - tp_vars->other_end, - bat_priv, session_cookie); - - /* drop reserved reference for kthread */ - batadv_tp_vars_put(tp_vars); - - /* cleanup of failed tp meter variables */ - batadv_tp_sender_cleanup(bat_priv, tp_vars); - return; - } - - wake_up_process(kthread); + /* init work item that will actually execute the test and schedule it */ + INIT_WORK(&tp_vars->test_work, batadv_tp_send); + queue_work(batadv_tp_meter_queue, &tp_vars->test_work); } /** @@ -1053,13 +1035,10 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, /* init work item for finished tp tests */ INIT_DELAYED_WORK(&tp_vars->finish_work, batadv_tp_sender_finish); - /* start tp kthread. This way the write() call issued from userspace can - * happily return and avoid to block + /* schedule the tp worker. This way the write() call issued from + * userspace can happily return and avoid to block */ - batadv_tp_start_kthread(tp_vars); - - /* don't return reference to new tp_vars */ - batadv_tp_vars_put(tp_vars); + batadv_tp_start_work(tp_vars); } /** @@ -1499,7 +1478,23 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb) /** * batadv_tp_meter_init() - initialize global tp_meter structures */ -void __init batadv_tp_meter_init(void) +int __init batadv_tp_meter_init(void) { get_random_bytes(batadv_tp_prerandom, sizeof(batadv_tp_prerandom)); + + batadv_tp_meter_queue = alloc_ordered_workqueue("bat_tp_meter", 0); + if (!batadv_tp_meter_queue) + return -ENOMEM; + + return 0; +} + +/** + * batadv_tp_meter_destroy() - destroy tp meter memory allocations + */ +void batadv_tp_meter_destroy(void) +{ + flush_workqueue(batadv_tp_meter_queue); + destroy_workqueue(batadv_tp_meter_queue); + batadv_tp_meter_queue = NULL; } diff --git a/net/batman-adv/tp_meter.h b/net/batman-adv/tp_meter.h index 68e60097..ab0bde26 100644 --- a/net/batman-adv/tp_meter.h +++ b/net/batman-adv/tp_meter.h @@ -25,7 +25,8 @@ struct sk_buff; -void batadv_tp_meter_init(void); +int batadv_tp_meter_init(void); +void batadv_tp_meter_destroy(void); void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, u32 test_length, u32 *cookie); void batadv_tp_stop(struct batadv_priv *bat_priv, const u8 *dst, diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 360357f8..c4bc8221 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1354,7 +1354,10 @@ struct batadv_tp_vars { /** @finish_work: work item for the finishing procedure */ struct delayed_work finish_work; - /** @test_length: test length in milliseconds */ + /** @test_work: work item for the test process */ + struct work_struct test_work; + + /** @test_length: test length in milliseconds */ u32 test_length; /** @session: TP session identifier */ From patchwork Tue May 8 16:41:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Lindner X-Patchwork-Id: 17344 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 595D9823DE; Tue, 8 May 2018 19:22:58 +0200 (CEST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=5.148.176.60; helo=s2.neomailbox.net; envelope-from=mareklindner@neomailbox.ch; receiver= Received: from s2.neomailbox.net (s2.neomailbox.net [5.148.176.60]) by open-mesh.org (Postfix) with ESMTPS id 6386A80936 for ; Tue, 8 May 2018 19:22:56 +0200 (CEST) From: Marek Lindner To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 9 May 2018 00:41:26 +0800 Message-Id: <20180508164130.8633-3-mareklindner@neomailbox.ch> In-Reply-To: <20180508164130.8633-1-mareklindner@neomailbox.ch> References: <20180508164130.8633-1-mareklindner@neomailbox.ch> Subject: [B.A.T.M.A.N.] [RFC 2/6] batman-adv: tp_meter - don't check for existing session X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Cc: Antonio Quartulli Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" From: Antonio Quartulli Since the conversion from kthread to queue worker it is not possible to run more than one "sender" session at a time. For this reason, checking if another session to the same destination is already scheduled is not useful anymore. Remove such check and allow the user to enqueue a new session to a previously targeted node. Signed-off-by: Antonio Quartulli --- net/batman-adv/tp_meter.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index 55e93abc..d91d371d 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -939,21 +939,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, session_cookie = batadv_tp_session_cookie(session_id, icmp_uid); *cookie = session_cookie; - /* look for an already existing test towards this node */ - spin_lock_bh(&bat_priv->tp_list_lock); - tp_vars = batadv_tp_list_find(bat_priv, dst); - if (tp_vars) { - spin_unlock_bh(&bat_priv->tp_list_lock); - batadv_tp_vars_put(tp_vars); - batadv_dbg(BATADV_DBG_TP_METER, bat_priv, - "Meter: test to or from the same node already ongoing, aborting\n"); - batadv_tp_batctl_error_notify(BATADV_TP_REASON_ALREADY_ONGOING, - dst, bat_priv, session_cookie); - return; - } - if (!atomic_add_unless(&bat_priv->tp_num, 1, BATADV_TP_MAX_NUM)) { - spin_unlock_bh(&bat_priv->tp_list_lock); batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Meter: too many ongoing sessions, aborting (SEND)\n"); batadv_tp_batctl_error_notify(BATADV_TP_REASON_TOO_MANY, dst, @@ -963,7 +949,6 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, tp_vars = kmalloc(sizeof(*tp_vars), GFP_ATOMIC); if (!tp_vars) { - spin_unlock_bh(&bat_priv->tp_list_lock); batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Meter: %s cannot allocate list elements\n", __func__); @@ -1021,6 +1006,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, spin_lock_init(&tp_vars->prerandom_lock); kref_get(&tp_vars->refcount); + spin_lock_bh(&bat_priv->tp_list_lock); hlist_add_head_rcu(&tp_vars->list, &bat_priv->tp_list); spin_unlock_bh(&bat_priv->tp_list_lock); From patchwork Tue May 8 16:41:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Lindner X-Patchwork-Id: 17347 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 7FC3C8249D; Tue, 8 May 2018 19:30:43 +0200 (CEST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=5.148.176.60; helo=s2.neomailbox.net; envelope-from=mareklindner@neomailbox.ch; receiver= Received: from s2.neomailbox.net (s2.neomailbox.net [5.148.176.60]) by open-mesh.org (Postfix) with ESMTPS id 4423C808E3 for ; Tue, 8 May 2018 19:30:41 +0200 (CEST) From: Marek Lindner To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 9 May 2018 00:41:27 +0800 Message-Id: <20180508164130.8633-4-mareklindner@neomailbox.ch> In-Reply-To: <20180508164130.8633-1-mareklindner@neomailbox.ch> References: <20180508164130.8633-1-mareklindner@neomailbox.ch> Subject: [B.A.T.M.A.N.] [RFC 3/6] batman-adv: tp_meter - allow up to 10 queued sessions X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Cc: Marek Lindner Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" Signed-off-by: Marek Lindner --- net/batman-adv/main.h | 6 ++++-- net/batman-adv/tp_meter.c | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 8da3c933..89dfaf87 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -137,9 +137,11 @@ #define BATADV_NC_NODE_TIMEOUT 10000 /* Milliseconds */ /** - * BATADV_TP_MAX_NUM - maximum number of simultaneously active tp sessions + * BATADV_TP_MAX_NUM_QUEUE - maximum number of queued (outgoing) tp sessions + * BATADV_TP_MAX_NUM_RECV - maximum number of simultaneous receiving streams */ -#define BATADV_TP_MAX_NUM 5 +#define BATADV_TP_MAX_NUM_QUEUE 10 +#define BATADV_TP_MAX_NUM_RECV 1 /** * enum batadv_mesh_state - State of a soft interface diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index d91d371d..eb7862cd 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -939,7 +939,8 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, session_cookie = batadv_tp_session_cookie(session_id, icmp_uid); *cookie = session_cookie; - if (!atomic_add_unless(&bat_priv->tp_num, 1, BATADV_TP_MAX_NUM)) { + if (!atomic_add_unless(&bat_priv->tp_num, 1, BATADV_TP_MAX_NUM_QUEUE)) { + spin_unlock_bh(&bat_priv->tp_list_lock); batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Meter: too many ongoing sessions, aborting (SEND)\n"); batadv_tp_batctl_error_notify(BATADV_TP_REASON_TOO_MANY, dst, @@ -1316,7 +1317,7 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv, if (tp_vars) goto out_unlock; - if (!atomic_add_unless(&bat_priv->tp_num, 1, BATADV_TP_MAX_NUM)) { + if (!atomic_add_unless(&bat_priv->tp_num, 1, BATADV_TP_MAX_NUM_RECV)) { batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Meter: too many ongoing sessions, aborting (RECV)\n"); goto out_unlock; From patchwork Tue May 8 16:41:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Lindner X-Patchwork-Id: 17341 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 13B4A82102; Tue, 8 May 2018 19:02:21 +0200 (CEST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=5.148.176.60; helo=s2.neomailbox.net; envelope-from=mareklindner@neomailbox.ch; receiver= X-Greylist: delayed 1236 seconds by postgrey-1.36 at open-mesh.org; Tue, 08 May 2018 19:02:19 CEST Received: from s2.neomailbox.net (s2.neomailbox.net [5.148.176.60]) by open-mesh.org (Postfix) with ESMTPS id 1AAC580852 for ; Tue, 8 May 2018 19:02:18 +0200 (CEST) From: Marek Lindner To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 9 May 2018 00:41:28 +0800 Message-Id: <20180508164130.8633-5-mareklindner@neomailbox.ch> In-Reply-To: <20180508164130.8633-1-mareklindner@neomailbox.ch> References: <20180508164130.8633-1-mareklindner@neomailbox.ch> Subject: [B.A.T.M.A.N.] [RFC 4/6] batman-adv: tp_meter - add caller distinction X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Cc: Marek Lindner Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" The throughput meter can be called from user space as well as from the batman-adv kernel module itself. Add infrastructure to handle the different callers. Signed-off-by: Marek Lindner --- net/batman-adv/netlink.c | 2 +- net/batman-adv/tp_meter.c | 102 +++++++++++++++++++++----------------- net/batman-adv/tp_meter.h | 2 +- net/batman-adv/types.h | 15 +++++- 4 files changed, 72 insertions(+), 49 deletions(-) diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 0d9459b6..88bf6c6f 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -378,7 +378,7 @@ batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info) } bat_priv = netdev_priv(soft_iface); - batadv_tp_start(bat_priv, dst, test_length, &cookie); + batadv_tp_start(bat_priv, dst, test_length, &cookie, BATADV_TP_USERSPACE); ret = batadv_netlink_tp_meter_put(msg, cookie); diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index eb7862cd..f7bb45d3 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -215,50 +215,68 @@ static void batadv_tp_update_rto(struct batadv_tp_vars *tp_vars, } /** - * batadv_tp_batctl_notify() - send client status result to client - * @reason: reason for tp meter session stop - * @dst: destination of tp_meter session + * batadv_tp_caller_notify() - send tp meter status result to caller * @bat_priv: the bat priv with all the soft interface information - * @start_time: start of transmission in jiffies - * @total_sent: bytes acked to the receiver - * @cookie: cookie of tp_meter session + * @tp_vars: the private data of the current TP meter session + * @reason: reason for tp meter session stop */ -static void batadv_tp_batctl_notify(enum batadv_tp_meter_reason reason, - const u8 *dst, struct batadv_priv *bat_priv, - unsigned long start_time, u64 total_sent, - u32 cookie) +static void batadv_tp_caller_notify(struct batadv_priv *bat_priv, + struct batadv_tp_vars *tp_vars, + enum batadv_tp_meter_reason reason) { - u32 test_time; - u8 result; u32 total_bytes; + u32 test_time; + u32 cookie; + bool reason_is_error; - if (!batadv_tp_is_error(reason)) { - result = BATADV_TP_REASON_COMPLETE; - test_time = jiffies_to_msecs(jiffies - start_time); - total_bytes = total_sent; - } else { - result = reason; - test_time = 0; - total_bytes = 0; - } + reason_is_error = batadv_tp_is_error(reason); - batadv_netlink_tpmeter_notify(bat_priv, dst, result, test_time, - total_bytes, cookie); + switch (tp_vars->caller) { + case BATADV_TP_USERSPACE: + cookie = batadv_tp_session_cookie(tp_vars->session, tp_vars->icmp_uid); + + if (reason_is_error) { + batadv_netlink_tpmeter_notify(bat_priv, tp_vars->other_end, + reason, 0, 0, cookie); + return; + } + + test_time = jiffies_to_msecs(jiffies - tp_vars->start_time); + total_bytes = atomic64_read(&tp_vars->tot_sent); + batadv_netlink_tpmeter_notify(bat_priv, tp_vars->other_end, + BATADV_TP_REASON_COMPLETE, test_time, + total_bytes, cookie); + + break; + case BATADV_TP_ELP: + break; + default: + break; + } } /** - * batadv_tp_batctl_error_notify() - send client error result to client + * batadv_tp_caller_init_error() - report early tp meter errors to caller + * @bat_priv: the bat priv with all the soft interface information + * @caller: caller of tp meter session (user space or ELP) * @reason: reason for tp meter session stop * @dst: destination of tp_meter session - * @bat_priv: the bat priv with all the soft interface information * @cookie: cookie of tp_meter session */ -static void batadv_tp_batctl_error_notify(enum batadv_tp_meter_reason reason, - const u8 *dst, - struct batadv_priv *bat_priv, - u32 cookie) +static void batadv_tp_caller_init_error(struct batadv_priv *bat_priv, + enum batadv_tp_meter_caller caller, + enum batadv_tp_meter_reason reason, + const u8 *dst, u32 cookie) { - batadv_tp_batctl_notify(reason, dst, bat_priv, 0, 0, cookie); + switch (caller) { + case BATADV_TP_USERSPACE: + batadv_netlink_tpmeter_notify(bat_priv, dst, reason, 0, 0, cookie); + break; + case BATADV_TP_ELP: + break; + default: + break; + } } /** @@ -411,8 +429,6 @@ static void batadv_tp_sender_cleanup(struct batadv_priv *bat_priv, static void batadv_tp_sender_end(struct batadv_priv *bat_priv, struct batadv_tp_vars *tp_vars) { - u32 session_cookie; - batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Test towards %pM finished..shutting down (reason=%d)\n", tp_vars->other_end, tp_vars->reason); @@ -425,15 +441,7 @@ static void batadv_tp_sender_end(struct batadv_priv *bat_priv, "Final values: cwnd=%u ss_threshold=%u\n", tp_vars->cwnd, tp_vars->ss_threshold); - session_cookie = batadv_tp_session_cookie(tp_vars->session, - tp_vars->icmp_uid); - - batadv_tp_batctl_notify(tp_vars->reason, - tp_vars->other_end, - bat_priv, - tp_vars->start_time, - atomic64_read(&tp_vars->tot_sent), - session_cookie); + batadv_tp_caller_notify(bat_priv, tp_vars, tp_vars->reason); } /** @@ -925,9 +933,10 @@ static void batadv_tp_start_work(struct batadv_tp_vars *tp_vars) * @dst: the receiver MAC address * @test_length: test length in milliseconds * @cookie: session cookie + * @caller: caller of tp meter session (user space or ELP) */ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, - u32 test_length, u32 *cookie) + u32 test_length, u32 *cookie, enum batadv_tp_meter_caller caller) { struct batadv_tp_vars *tp_vars; u8 session_id[2]; @@ -943,8 +952,8 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, spin_unlock_bh(&bat_priv->tp_list_lock); batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Meter: too many ongoing sessions, aborting (SEND)\n"); - batadv_tp_batctl_error_notify(BATADV_TP_REASON_TOO_MANY, dst, - bat_priv, session_cookie); + batadv_tp_caller_init_error(bat_priv, caller, BATADV_TP_REASON_TOO_MANY, + dst, session_cookie); return; } @@ -953,8 +962,8 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Meter: %s cannot allocate list elements\n", __func__); - batadv_tp_batctl_error_notify(BATADV_TP_REASON_MEMORY_ERROR, - dst, bat_priv, session_cookie); + batadv_tp_caller_init_error(bat_priv, caller, BATADV_TP_REASON_MEMORY_ERROR, + dst, session_cookie); return; } @@ -962,6 +971,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, ether_addr_copy(tp_vars->other_end, dst); kref_init(&tp_vars->refcount); tp_vars->role = BATADV_TP_SENDER; + tp_vars->caller = caller; atomic_set(&tp_vars->sending, 1); memcpy(tp_vars->session, session_id, sizeof(session_id)); tp_vars->icmp_uid = icmp_uid; diff --git a/net/batman-adv/tp_meter.h b/net/batman-adv/tp_meter.h index ab0bde26..d844575d 100644 --- a/net/batman-adv/tp_meter.h +++ b/net/batman-adv/tp_meter.h @@ -28,7 +28,7 @@ struct sk_buff; int batadv_tp_meter_init(void); void batadv_tp_meter_destroy(void); void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, - u32 test_length, u32 *cookie); + u32 test_length, u32 *cookie, enum batadv_tp_meter_caller caller); void batadv_tp_stop(struct batadv_priv *bat_priv, const u8 *dst, u8 return_value); void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index c4bc8221..826b3b42 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1323,6 +1323,16 @@ enum batadv_tp_meter_role { BATADV_TP_SENDER }; +/** + * enum batadv_tp_meter_caller - initiator of the tp meter session + * @BATADV_TP_USERSPACE: initiated by user space + * @BATADV_TP_ELP: initiated by ELP + */ +enum batadv_tp_meter_caller { + BATADV_TP_USERSPACE, + BATADV_TP_ELP +}; + /** * struct batadv_tp_vars - tp meter private variables per session */ @@ -1345,7 +1355,10 @@ struct batadv_tp_vars { /** @role: receiver/sender modi */ enum batadv_tp_meter_role role; - /** @sending: sending binary semaphore: 1 if sending, 0 is not */ + /** @caller: caller of tp meter session (user space or ELP) */ + enum batadv_tp_meter_caller caller; + + /** @sending: sending binary semaphore: 1 if sending, 0 is not */ atomic_t sending; /** @reason: reason for a stopped session */ From patchwork Tue May 8 16:41:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Lindner X-Patchwork-Id: 17346 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 4C9E98249A; Tue, 8 May 2018 19:27:23 +0200 (CEST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=5.148.176.60; helo=s2.neomailbox.net; envelope-from=mareklindner@neomailbox.ch; receiver= Received: from s2.neomailbox.net (s2.neomailbox.net [5.148.176.60]) by open-mesh.org (Postfix) with ESMTPS id AB1498050D for ; Tue, 8 May 2018 19:27:21 +0200 (CEST) From: Marek Lindner To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 9 May 2018 00:41:29 +0800 Message-Id: <20180508164130.8633-6-mareklindner@neomailbox.ch> In-Reply-To: <20180508164130.8633-1-mareklindner@neomailbox.ch> References: <20180508164130.8633-1-mareklindner@neomailbox.ch> Subject: [B.A.T.M.A.N.] [RFC 5/6] batman-adv: to_meter - add option to perform one-hop test X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Cc: Antonio Quartulli Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" From: Antonio Quartulli A link test is a TP session ran over a specific one-hop link, rather than towards an originator in the mesh. Signed-off-by: Antonio Quartulli --- include/uapi/linux/batadv_packet.h | 1 + net/batman-adv/netlink.c | 3 +- net/batman-adv/routing.c | 5 +- net/batman-adv/tp_meter.c | 220 +++++++++++++++++++---------- net/batman-adv/tp_meter.h | 8 +- net/batman-adv/types.h | 3 + 6 files changed, 161 insertions(+), 79 deletions(-) diff --git a/include/uapi/linux/batadv_packet.h b/include/uapi/linux/batadv_packet.h index 894d8d2f..fc89ab6b 100644 --- a/include/uapi/linux/batadv_packet.h +++ b/include/uapi/linux/batadv_packet.h @@ -355,6 +355,7 @@ struct batadv_icmp_tp_packet { enum batadv_icmp_tp_subtype { BATADV_TP_MSG = 0, BATADV_TP_ACK, + BATADV_TP_MSG_LINK, }; #define BATADV_RR_LEN 16 diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 88bf6c6f..064020cc 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -378,7 +378,8 @@ batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info) } bat_priv = netdev_priv(soft_iface); - batadv_tp_start(bat_priv, dst, test_length, &cookie, BATADV_TP_USERSPACE); + batadv_tp_start(bat_priv, dst, NULL, test_length, &cookie, + BATADV_TP_USERSPACE); ret = batadv_netlink_tp_meter_put(msg, cookie); diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index cc3ed93a..2a2c1ffe 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -229,6 +229,7 @@ bool batadv_check_management_packet(struct sk_buff *skb, * otherwise. */ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, + struct batadv_hard_iface *recv_if, struct sk_buff *skb) { struct batadv_hard_iface *primary_if = NULL; @@ -281,7 +282,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, if (!pskb_may_pull(skb, sizeof(struct batadv_icmp_tp_packet))) goto out; - batadv_tp_meter_recv(bat_priv, skb); + batadv_tp_meter_recv(bat_priv, recv_if, skb); ret = NET_RX_SUCCESS; /* skb was consumed */ skb = NULL; @@ -418,7 +419,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb, /* packet for me */ if (batadv_is_my_mac(bat_priv, icmph->dst)) - return batadv_recv_my_icmp_packet(bat_priv, skb); + return batadv_recv_my_icmp_packet(bat_priv, recv_if, skb); /* TTL exceeded */ if (icmph->ttl < 2) diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index f7bb45d3..1526286b 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -378,6 +378,9 @@ static void batadv_tp_vars_release(struct kref *ref) } spin_unlock_bh(&tp_vars->unacked_lock); + if (tp_vars->hardif_neigh) + batadv_hardif_neigh_put(tp_vars->hardif_neigh); + kfree_rcu(tp_vars, rcu); } @@ -591,26 +594,57 @@ static void batadv_tp_fill_prerandom(struct batadv_tp_vars *tp_vars, * not reachable, BATADV_TP_REASON_MEMORY_ERROR if the packet couldn't be * allocated */ -static int batadv_tp_send_msg(struct batadv_tp_vars *tp_vars, const u8 *src, - struct batadv_orig_node *orig_node, - u32 seqno, size_t len, const u8 *session, - int uid, u32 timestamp) +static int batadv_tp_send_msg(struct batadv_priv *bat_priv, + struct batadv_tp_vars *tp_vars, u32 seqno, + size_t len, const u8 *session, int uid, + u32 timestamp) { + struct batadv_hard_iface *primary_if = NULL; + struct batadv_orig_node *orig_node = NULL; struct batadv_icmp_tp_packet *icmp; struct sk_buff *skb; - int r; - u8 *data; + int r, ret = 0; + u8 *data, *src, *dst, subtype; + struct net_device *netdev; size_t data_len; - skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); - if (unlikely(!skb)) - return BATADV_TP_REASON_MEMORY_ERROR; + /* link test */ + if (tp_vars->hardif_neigh) { + dst = tp_vars->hardif_neigh->addr; + src = tp_vars->hardif_neigh->if_incoming->net_dev->dev_addr; + subtype = BATADV_TP_MSG_LINK; + netdev = tp_vars->hardif_neigh->if_incoming->net_dev; + } else { + orig_node = batadv_orig_hash_find(bat_priv, tp_vars->other_end); + if (unlikely(!orig_node)) { + ret = BATADV_TP_REASON_DST_UNREACHABLE; + goto out; + } + + + primary_if = batadv_primary_if_get_selected(bat_priv); + if (unlikely(!primary_if)) { + ret = BATADV_TP_REASON_DST_UNREACHABLE; + goto out; + } + + dst = orig_node->orig; + src = primary_if->net_dev->dev_addr; + subtype = BATADV_TP_MSG; + netdev = NULL; + } + + skb = netdev_alloc_skb_ip_align(netdev, len + ETH_HLEN); + if (unlikely(!skb)) { + ret = BATADV_TP_REASON_MEMORY_ERROR; + goto out; + } skb_reserve(skb, ETH_HLEN); icmp = skb_put(skb, sizeof(*icmp)); /* fill the icmp header */ - ether_addr_copy(icmp->dst, orig_node->orig); + ether_addr_copy(icmp->dst, dst); ether_addr_copy(icmp->orig, src); icmp->version = BATADV_COMPAT_VERSION; icmp->packet_type = BATADV_ICMP; @@ -618,7 +652,7 @@ static int batadv_tp_send_msg(struct batadv_tp_vars *tp_vars, const u8 *src, icmp->msg_type = BATADV_TP; icmp->uid = uid; - icmp->subtype = BATADV_TP_MSG; + icmp->subtype = subtype; memcpy(icmp->session, session, sizeof(icmp->session)); icmp->seqno = htonl(seqno); icmp->timestamp = htonl(timestamp); @@ -627,11 +661,23 @@ static int batadv_tp_send_msg(struct batadv_tp_vars *tp_vars, const u8 *src, data = skb_put(skb, data_len); batadv_tp_fill_prerandom(tp_vars, data, data_len); - r = batadv_send_skb_to_orig(skb, orig_node, NULL); - if (r == NET_XMIT_SUCCESS) - return 0; + if (tp_vars->hardif_neigh) + r = batadv_send_skb_packet(skb, + tp_vars->hardif_neigh->if_incoming, + dst); + else + r = batadv_send_skb_to_orig(skb, orig_node, NULL); + + if (unlikely(r != NET_XMIT_SUCCESS)) + ret = BATADV_TP_REASON_CANT_SEND; - return BATADV_TP_REASON_CANT_SEND; +out: + if (likely(primary_if)) + batadv_hardif_put(primary_if); + if (likely(orig_node)) + batadv_orig_node_put(orig_node); + + return ret; } /** @@ -650,7 +696,6 @@ static void batadv_tp_recv_ack(struct batadv_priv *bat_priv, struct batadv_tp_vars *tp_vars; size_t packet_len, mss; u32 rtt, recv_ack, cwnd; - unsigned char *dev_addr; packet_len = BATADV_TP_PLEN; mss = BATADV_TP_PLEN; @@ -672,13 +717,11 @@ static void batadv_tp_recv_ack(struct batadv_priv *bat_priv, (u32)atomic_read(&tp_vars->last_acked))) goto out; - primary_if = batadv_primary_if_get_selected(bat_priv); - if (unlikely(!primary_if)) - goto out; - - orig_node = batadv_orig_hash_find(bat_priv, icmp->orig); - if (unlikely(!orig_node)) - goto out; + if (!tp_vars->hardif_neigh) { + primary_if = batadv_primary_if_get_selected(bat_priv); + if (unlikely(!primary_if)) + goto out; + } /* update RTO with the new sampled RTT, if any */ rtt = jiffies_to_msecs(jiffies) - ntohl(icmp->timestamp); @@ -700,8 +743,11 @@ static void batadv_tp_recv_ack(struct batadv_priv *bat_priv, goto out; /* if this is the third duplicate ACK do Fast Retransmit */ - batadv_tp_send_msg(tp_vars, primary_if->net_dev->dev_addr, - orig_node, recv_ack, packet_len, + + /* if we have a hardif_neigh, it means that this is a LINK test, + * therefore use the according function + */ + batadv_tp_send_msg(bat_priv, tp_vars, recv_ack, packet_len, icmp->session, icmp->uid, jiffies_to_msecs(jiffies)); @@ -738,9 +784,7 @@ static void batadv_tp_recv_ack(struct batadv_priv *bat_priv, * immediately as specified by NewReno (see * Section 3.2 of RFC6582 for details) */ - dev_addr = primary_if->net_dev->dev_addr; - batadv_tp_send_msg(tp_vars, dev_addr, - orig_node, recv_ack, + batadv_tp_send_msg(bat_priv, tp_vars, recv_ack, packet_len, icmp->session, icmp->uid, jiffies_to_msecs(jiffies)); @@ -824,8 +868,6 @@ static int batadv_tp_wait_available(struct batadv_tp_vars *tp_vars, size_t plen) */ static void batadv_tp_send(struct work_struct *work) { - struct batadv_hard_iface *primary_if = NULL; - struct batadv_orig_node *orig_node = NULL; struct batadv_tp_vars *tp_vars; size_t payload_len, packet_len; struct batadv_priv *bat_priv; @@ -840,20 +882,6 @@ static void batadv_tp_send(struct work_struct *work) goto out; } - orig_node = batadv_orig_hash_find(bat_priv, tp_vars->other_end); - if (unlikely(!orig_node)) { - err = BATADV_TP_REASON_DST_UNREACHABLE; - tp_vars->reason = err; - goto out; - } - - primary_if = batadv_primary_if_get_selected(bat_priv); - if (unlikely(!primary_if)) { - err = BATADV_TP_REASON_DST_UNREACHABLE; - tp_vars->reason = err; - goto out; - } - /* assume that all the hard_interfaces have a correctly * configured MTU, so use the soft_iface MTU as MSS. * This might not be true and in that case the fragmentation @@ -880,10 +908,9 @@ static void batadv_tp_send(struct work_struct *work) */ packet_len = payload_len + sizeof(struct batadv_unicast_packet); - err = batadv_tp_send_msg(tp_vars, primary_if->net_dev->dev_addr, - orig_node, tp_vars->last_sent, - packet_len, - tp_vars->session, tp_vars->icmp_uid, + err = batadv_tp_send_msg(bat_priv, tp_vars, tp_vars->last_sent, + packet_len, tp_vars->session, + tp_vars->icmp_uid, jiffies_to_msecs(jiffies)); /* something went wrong during the preparation/transmission */ @@ -905,11 +932,6 @@ static void batadv_tp_send(struct work_struct *work) } out: - if (likely(primary_if)) - batadv_hardif_put(primary_if); - if (likely(orig_node)) - batadv_orig_node_put(orig_node); - batadv_tp_sender_end(bat_priv, tp_vars); batadv_tp_sender_cleanup(bat_priv, tp_vars); @@ -936,17 +958,20 @@ static void batadv_tp_start_work(struct batadv_tp_vars *tp_vars) * @caller: caller of tp meter session (user space or ELP) */ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, + struct batadv_hardif_neigh_node *neigh, u32 test_length, u32 *cookie, enum batadv_tp_meter_caller caller) { struct batadv_tp_vars *tp_vars; u8 session_id[2]; u8 icmp_uid; - u32 session_cookie; + u32 session_cookie = 0; get_random_bytes(session_id, sizeof(session_id)); get_random_bytes(&icmp_uid, 1); - session_cookie = batadv_tp_session_cookie(session_id, icmp_uid); - *cookie = session_cookie; + if (cookie) { + session_cookie = batadv_tp_session_cookie(session_id, icmp_uid); + *cookie = session_cookie; + } if (!atomic_add_unless(&bat_priv->tp_num, 1, BATADV_TP_MAX_NUM_QUEUE)) { spin_unlock_bh(&bat_priv->tp_list_lock); @@ -969,6 +994,10 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, /* initialize tp_vars */ ether_addr_copy(tp_vars->other_end, dst); + if (neigh) { + kref_get(&neigh->refcount); + tp_vars->hardif_neigh = neigh; + } kref_init(&tp_vars->refcount); tp_vars->role = BATADV_TP_SENDER; tp_vars->caller = caller; @@ -1139,29 +1168,42 @@ static void batadv_tp_receiver_shutdown(struct timer_list *t) * Return: 0 on success, a positive integer representing the reason of the * failure otherwise */ -static int batadv_tp_send_ack(struct batadv_priv *bat_priv, const u8 *dst, +static int batadv_tp_send_ack(struct batadv_priv *bat_priv, + struct batadv_tp_vars *tp_vars, u32 seq, __be32 timestamp, const u8 *session, int socket_index) { struct batadv_hard_iface *primary_if = NULL; - struct batadv_orig_node *orig_node; + struct batadv_orig_node *orig_node = NULL; struct batadv_icmp_tp_packet *icmp; + struct net_device *netdev = NULL; struct sk_buff *skb; + u8 *src, *dst; int r, ret; - orig_node = batadv_orig_hash_find(bat_priv, dst); - if (unlikely(!orig_node)) { - ret = BATADV_TP_REASON_DST_UNREACHABLE; - goto out; - } + if (tp_vars->hardif_neigh) { + dst = tp_vars->hardif_neigh->addr; + src = tp_vars->hardif_neigh->if_incoming->net_dev->dev_addr; + netdev = tp_vars->hardif_neigh->if_incoming->net_dev; + } else { + orig_node = batadv_orig_hash_find(bat_priv, tp_vars->other_end); + if (unlikely(!orig_node)) { + ret = BATADV_TP_REASON_DST_UNREACHABLE; + goto out; + } - primary_if = batadv_primary_if_get_selected(bat_priv); - if (unlikely(!primary_if)) { - ret = BATADV_TP_REASON_DST_UNREACHABLE; - goto out; + primary_if = batadv_primary_if_get_selected(bat_priv); + if (unlikely(!primary_if)) { + ret = BATADV_TP_REASON_DST_UNREACHABLE; + goto out; + } + + dst = orig_node->orig; + src = primary_if->net_dev->dev_addr; + netdev = NULL; } - skb = netdev_alloc_skb_ip_align(NULL, sizeof(*icmp) + ETH_HLEN); + skb = netdev_alloc_skb_ip_align(netdev, sizeof(*icmp) + ETH_HLEN); if (unlikely(!skb)) { ret = BATADV_TP_REASON_MEMORY_ERROR; goto out; @@ -1183,7 +1225,13 @@ static int batadv_tp_send_ack(struct batadv_priv *bat_priv, const u8 *dst, icmp->timestamp = timestamp; /* send the ack */ - r = batadv_send_skb_to_orig(skb, orig_node, NULL); + if (tp_vars->hardif_neigh) + r = batadv_send_skb_packet(skb, + tp_vars->hardif_neigh->if_incoming, + dst); + else + r = batadv_send_skb_to_orig(skb, orig_node, NULL); + if (unlikely(r < 0) || r == NET_XMIT_DROP) { ret = BATADV_TP_REASON_DST_UNREACHABLE; goto out; @@ -1317,8 +1365,10 @@ static void batadv_tp_ack_unordered(struct batadv_tp_vars *tp_vars) */ static struct batadv_tp_vars * batadv_tp_init_recv(struct batadv_priv *bat_priv, + struct batadv_hard_iface *recv_if, const struct batadv_icmp_tp_packet *icmp) { + struct batadv_hardif_neigh_node *neigh = NULL; struct batadv_tp_vars *tp_vars; spin_lock_bh(&bat_priv->tp_list_lock); @@ -1333,15 +1383,30 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv, goto out_unlock; } + /* the sender is starting a LINK test, therefore we have retrieve its + * corresponding hardif_neigh_node that we'll use later to send ACKs + * back + */ + if (icmp->subtype == BATADV_TP_MSG_LINK) { + neigh = batadv_hardif_neigh_get(recv_if, icmp->orig); + if (!neigh) { + batadv_dbg(BATADV_DBG_TP_METER, bat_priv, + "Meter: %s() can't retrieve sender neigh object for %pM\n", + __func__, icmp->orig); + goto out_unlock; + } + } + tp_vars = kmalloc(sizeof(*tp_vars), GFP_ATOMIC); if (!tp_vars) - goto out_unlock; + goto err_neigh_put; ether_addr_copy(tp_vars->other_end, icmp->orig); tp_vars->role = BATADV_TP_RECEIVER; memcpy(tp_vars->session, icmp->session, sizeof(tp_vars->session)); tp_vars->last_recv = BATADV_TP_FIRST_SEQ; tp_vars->bat_priv = bat_priv; + tp_vars->hardif_neigh = neigh; kref_init(&tp_vars->refcount); spin_lock_init(&tp_vars->unacked_lock); @@ -1354,7 +1419,10 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv, timer_setup(&tp_vars->timer, batadv_tp_receiver_shutdown, 0); batadv_tp_reset_receiver_timer(tp_vars); + goto out_unlock; +err_neigh_put: + batadv_hardif_neigh_put(neigh); out_unlock: spin_unlock_bh(&bat_priv->tp_list_lock); @@ -1369,6 +1437,7 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv, * Process a received TP MSG packet */ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv, + struct batadv_hard_iface *recv_if, const struct sk_buff *skb) { const struct batadv_icmp_tp_packet *icmp; @@ -1383,7 +1452,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv, * first packet is lost, the tp meter does not work anymore! */ if (seqno == BATADV_TP_FIRST_SEQ) { - tp_vars = batadv_tp_init_recv(bat_priv, icmp); + tp_vars = batadv_tp_init_recv(bat_priv, recv_if, icmp); if (!tp_vars) { batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Meter: seqno != BATADV_TP_FIRST_SEQ cannot initiate connection\n"); @@ -1439,7 +1508,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv, * is going to be sent is a duplicate (the sender will count them and * possibly enter Fast Retransmit as soon as it has reached 3) */ - batadv_tp_send_ack(bat_priv, icmp->orig, tp_vars->last_recv, + batadv_tp_send_ack(bat_priv, tp_vars, tp_vars->last_recv, icmp->timestamp, icmp->session, icmp->uid); out: if (likely(tp_vars)) @@ -1451,7 +1520,9 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @skb: the buffer containing the received packet */ -void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb) +void batadv_tp_meter_recv(struct batadv_priv *bat_priv, + struct batadv_hard_iface *recv_if, + struct sk_buff *skb) { struct batadv_icmp_tp_packet *icmp; @@ -1459,7 +1530,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb) switch (icmp->subtype) { case BATADV_TP_MSG: - batadv_tp_recv_msg(bat_priv, skb); + case BATADV_TP_MSG_LINK: + batadv_tp_recv_msg(bat_priv, recv_if, skb); break; case BATADV_TP_ACK: batadv_tp_recv_ack(bat_priv, skb); diff --git a/net/batman-adv/tp_meter.h b/net/batman-adv/tp_meter.h index d844575d..3a1be483 100644 --- a/net/batman-adv/tp_meter.h +++ b/net/batman-adv/tp_meter.h @@ -28,9 +28,13 @@ struct sk_buff; int batadv_tp_meter_init(void); void batadv_tp_meter_destroy(void); void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, - u32 test_length, u32 *cookie, enum batadv_tp_meter_caller caller); + struct batadv_hardif_neigh_node *neigh, + u32 test_length, u32 *cookie, + enum batadv_tp_meter_caller caller); void batadv_tp_stop(struct batadv_priv *bat_priv, const u8 *dst, u8 return_value); -void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb); +void batadv_tp_meter_recv(struct batadv_priv *bat_priv, + struct batadv_hard_iface *recv_if, + struct sk_buff *skb); #endif /* _NET_BATMAN_ADV_TP_METER_H_ */ diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 826b3b42..98dccc6c 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1454,6 +1454,9 @@ struct batadv_tp_vars { /** @rcu: struct used for freeing in an RCU-safe manner */ struct rcu_head rcu; + + /** @neigh_node: in case of LINK test, represents the other-end */ + struct batadv_hardif_neigh_node *hardif_neigh; }; /** From patchwork Tue May 8 16:41:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Lindner X-Patchwork-Id: 17345 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 7AB368242B; Tue, 8 May 2018 19:26:45 +0200 (CEST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=5.148.176.60; helo=s2.neomailbox.net; envelope-from=mareklindner@neomailbox.ch; receiver= Received: from s2.neomailbox.net (s2.neomailbox.net [5.148.176.60]) by open-mesh.org (Postfix) with ESMTPS id 8EE5F8050D for ; Tue, 8 May 2018 19:26:43 +0200 (CEST) From: Marek Lindner To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 9 May 2018 00:41:30 +0800 Message-Id: <20180508164130.8633-7-mareklindner@neomailbox.ch> In-Reply-To: <20180508164130.8633-1-mareklindner@neomailbox.ch> References: <20180508164130.8633-1-mareklindner@neomailbox.ch> Subject: [B.A.T.M.A.N.] [RFC 6/6] batman-adv: ELP - use tp meter to estimate the throughput if otherwise not available X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Cc: Marek Lindner Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" Signed-off-by: Marek Lindner --- net/batman-adv/bat_v_elp.c | 62 ++++++++++++++++++++++++++++++++++++-- net/batman-adv/bat_v_elp.h | 19 ++++++++++++ net/batman-adv/main.h | 1 + net/batman-adv/tp_meter.c | 25 +++++++++++++-- net/batman-adv/types.h | 9 ++++++ 5 files changed, 111 insertions(+), 5 deletions(-) diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c index 28687493..028dc3ab 100644 --- a/net/batman-adv/bat_v_elp.c +++ b/net/batman-adv/bat_v_elp.c @@ -51,6 +51,7 @@ #include "originator.h" #include "routing.h" #include "send.h" +#include "tp_meter.h" /** * batadv_v_elp_start_timer() - restart timer for ELP periodic work @@ -67,6 +68,41 @@ static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface) msecs_to_jiffies(msecs)); } +/** + * batadv_v_elp_tp_start() - start a tp meter session for a neighbor + * @neigh: neighbor to run tp meter on + */ +static void batadv_v_elp_tp_start(struct batadv_hardif_neigh_node *neigh) +{ + struct batadv_hard_iface *hard_iface = neigh->if_incoming; + struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + + neigh->bat_v.tp_meter_running = true; + batadv_tp_start(bat_priv, neigh->addr, neigh, 10, NULL, BATADV_TP_ELP); +} + +/** + * batadv_v_elp_tp_fail() - handle tp meter session failure + * @neigh: neighbor to run tp meter on + */ +void batadv_v_elp_tp_fail(struct batadv_hardif_neigh_node *neigh) +{ + neigh->bat_v.tp_meter_running = false; +} + +/** + * batadv_v_elp_tp_finish() - post-process tp meter results + * @neigh: neighbor tp meter on + * @throughput: tp meter throughput result + */ +void batadv_v_elp_tp_finish(struct batadv_hardif_neigh_node *neigh, + u32 throughput) +{ + ewma_throughput_add(&neigh->bat_v.throughput, throughput); + neigh->bat_v.last_tp_meter_run = jiffies; + neigh->bat_v.tp_meter_running = false; +} + /** * batadv_v_elp_get_throughput() - get the throughput towards a neighbour * @neigh: the neighbour for which the throughput has to be obtained @@ -80,6 +116,7 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) struct ethtool_link_ksettings link_settings; struct net_device *real_netdev; struct station_info sinfo; + u32 last_tp_run_msecs; u32 throughput; int ret; @@ -112,10 +149,13 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) */ return 0; } + + /* unsupported WiFi driver */ if (ret) - goto default_throughput; + goto fallback_throughput; + if (!(sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))) - goto default_throughput; + goto fallback_throughput; return sinfo.expected_throughput / 100; } @@ -139,6 +179,24 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) return throughput * 10; } +fallback_throughput: + last_tp_run_msecs = jiffies_to_msecs(jiffies - neigh->bat_v.last_tp_meter_run); + + /* check the tp_meter_running flag before checking the timestamp to + * avoid a race condition where a new tp meter session is scheduled + * right after the previous tp meter session has completed + */ + if (!neigh->bat_v.tp_meter_running && + last_tp_run_msecs > BATADV_ELP_TP_RUN_INTERVAL) + batadv_v_elp_tp_start(neigh); + + /* discard too old tp test results */ + if (last_tp_run_msecs > 2 * BATADV_ELP_TP_RUN_INTERVAL) + neigh->bat_v.tp_meter_throughput = 0; + + if (!neigh->bat_v.tp_meter_throughput) + return neigh->bat_v.tp_meter_throughput; + default_throughput: if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) { batadv_info(hard_iface->soft_iface, diff --git a/net/batman-adv/bat_v_elp.h b/net/batman-adv/bat_v_elp.h index e8c7b7fd..d0605054 100644 --- a/net/batman-adv/bat_v_elp.h +++ b/net/batman-adv/bat_v_elp.h @@ -33,4 +33,23 @@ int batadv_v_elp_packet_recv(struct sk_buff *skb, struct batadv_hard_iface *if_incoming); void batadv_v_elp_throughput_metric_update(struct work_struct *work); +#ifdef CONFIG_BATMAN_ADV_BATMAN_V + +void batadv_v_elp_tp_fail(struct batadv_hardif_neigh_node *neigh); +void batadv_v_elp_tp_finish(struct batadv_hardif_neigh_node *neigh, + u32 throughput); + +#else + +static inline void batadv_v_elp_tp_fail(struct batadv_hardif_neigh_node *neigh) +{ +} + +static inline void +batadv_v_elp_tp_finish(struct batadv_hardif_neigh_node *neigh, u32 throughput) +{ +} + +#endif /* CONFIG_BATMAN_ADV_BATMAN_V */ + #endif /* _NET_BATMAN_ADV_BAT_V_ELP_H_ */ diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 89dfaf87..ed4ae913 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -69,6 +69,7 @@ #define BATADV_ELP_MIN_PROBE_SIZE 200 /* bytes */ #define BATADV_ELP_PROBE_MAX_TX_DIFF 100 /* milliseconds */ #define BATADV_ELP_MAX_AGE 64 +#define BATADV_ELP_TP_RUN_INTERVAL 60000 /* milliseconds */ #define BATADV_OGM_MAX_ORIGDIFF 5 #define BATADV_OGM_MAX_AGE 64 diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index 1526286b..e7a3c24e 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -56,6 +56,7 @@ #include "netlink.h" #include "originator.h" #include "send.h" +#include "bat_v_elp.h" /** * BATADV_TP_DEF_TEST_LENGTH - Default test length if not specified by the user @@ -225,6 +226,7 @@ static void batadv_tp_caller_notify(struct batadv_priv *bat_priv, enum batadv_tp_meter_reason reason) { u32 total_bytes; + u64 throughput; u32 test_time; u32 cookie; bool reason_is_error; @@ -249,6 +251,21 @@ static void batadv_tp_caller_notify(struct batadv_priv *bat_priv, break; case BATADV_TP_ELP: + if (reason_is_error) { + batadv_v_elp_tp_fail(tp_vars->hardif_neigh); + return; + } + + test_time = jiffies_to_msecs(jiffies - tp_vars->start_time); + total_bytes = atomic64_read(&tp_vars->tot_sent); + + /* The following calculation includes these steps: + * - convert bytes to bits + * - divide bits by the test length (msecs) + * - convert result from bits/ms to 0.1Mb/s (* 1024 * 10 / 1000) + */ + throughput = total_bytes * 8 >> ilog2(test_time) / 10; + batadv_v_elp_tp_finish(tp_vars->hardif_neigh, throughput); break; default: break; @@ -266,13 +283,15 @@ static void batadv_tp_caller_notify(struct batadv_priv *bat_priv, static void batadv_tp_caller_init_error(struct batadv_priv *bat_priv, enum batadv_tp_meter_caller caller, enum batadv_tp_meter_reason reason, - const u8 *dst, u32 cookie) + const u8 *dst, u32 cookie, + struct batadv_hardif_neigh_node *hardif_neigh) { switch (caller) { case BATADV_TP_USERSPACE: batadv_netlink_tpmeter_notify(bat_priv, dst, reason, 0, 0, cookie); break; case BATADV_TP_ELP: + batadv_v_elp_tp_fail(hardif_neigh); break; default: break; @@ -978,7 +997,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Meter: too many ongoing sessions, aborting (SEND)\n"); batadv_tp_caller_init_error(bat_priv, caller, BATADV_TP_REASON_TOO_MANY, - dst, session_cookie); + dst, session_cookie, neigh); return; } @@ -988,7 +1007,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, "Meter: %s cannot allocate list elements\n", __func__); batadv_tp_caller_init_error(bat_priv, caller, BATADV_TP_REASON_MEMORY_ERROR, - dst, session_cookie); + dst, session_cookie, neigh); return; } diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 98dccc6c..54fabcb1 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -583,6 +583,15 @@ struct batadv_hardif_neigh_node_bat_v { /** @metric_work: work queue callback item for metric update */ struct work_struct metric_work; + + /** @tp_meter_running: tp meter measurements towards this neighbor in progress */ + bool tp_meter_running; + + /** @last_tp_meter_run: timestamp of last tp meter measurement completion */ + unsigned long last_tp_meter_run; + + /** @tp_meter_throughput: throughput information measured by tp meter */ + unsigned long tp_meter_throughput; }; /**