* 2) if the session is in Congestion Avoidance, the CWND has to be
* increased by MSS * MSS / CWND for every unique received ACK
*/
-static void batadv_tp_update_cwnd(struct batadv_tp_vars *tp_vars, u32 mss)
+static void batadv_tp_update_cwnd(struct batadv_tp_sender *tp_vars, u32 mss)
{
spin_lock_bh(&tp_vars->cwnd_lock);
* @tp_vars: the private data of the current TP meter session
* @new_rtt: new roundtrip time in msec
*/
-static void batadv_tp_update_rto(struct batadv_tp_vars *tp_vars,
+static void batadv_tp_update_rto(struct batadv_tp_sender *tp_vars,
u32 new_rtt)
{
long m = new_rtt;
}
/**
- * batadv_tp_list_find() - find a tp_vars object in the global list
+ * batadv_tp_list_find_sender() - find a sender tp_vars object in the global list
* @bat_priv: the bat priv with all the mesh interface information
* @dst: the other endpoint MAC address to look for
- * @role: role of the session
*
* Look for a tp_vars object matching dst as end_point and return it after
* having increment the refcounter. Return NULL is not found
*
* Return: matching tp_vars or NULL when no tp_vars with @dst was found
*/
-static struct batadv_tp_vars *batadv_tp_list_find(struct batadv_priv *bat_priv,
- const u8 *dst,
- enum batadv_tp_meter_role role)
+static struct batadv_tp_sender *
+batadv_tp_list_find_sender(struct batadv_priv *bat_priv, const u8 *dst)
{
- struct batadv_tp_vars *pos, *tp_vars = NULL;
+ struct batadv_tp_sender *pos, *tp_vars = NULL;
rcu_read_lock();
- hlist_for_each_entry_rcu(pos, &bat_priv->tp_list, list) {
- if (!batadv_compare_eth(pos->other_end, dst))
- continue;
-
- if (pos->role != role)
+ hlist_for_each_entry_rcu(pos, &bat_priv->tp_sender_list, common.list) {
+ if (!batadv_compare_eth(pos->common.other_end, dst))
continue;
/* most of the time this function is invoked during the normal
* process..it makes sens to pay more when the session is
* finished and to speed the process up during the measurement
*/
- if (unlikely(!kref_get_unless_zero(&pos->refcount)))
+ if (unlikely(!kref_get_unless_zero(&pos->common.refcount)))
continue;
tp_vars = pos;
static bool batadv_tp_list_active(struct batadv_priv *bat_priv, const u8 *dst)
__must_hold(&bat_priv->tp_list_lock)
{
- struct batadv_tp_vars *tp_vars;
+ struct batadv_tp_receiver *tp_receiver;
+ struct batadv_tp_sender *tp_sender;
+
+ hlist_for_each_entry_rcu(tp_sender, &bat_priv->tp_sender_list, common.list) {
+ if (batadv_compare_eth(tp_sender->common.other_end, dst))
+ return true;
+ }
- hlist_for_each_entry_rcu(tp_vars, &bat_priv->tp_list, list) {
- if (batadv_compare_eth(tp_vars->other_end, dst))
+ hlist_for_each_entry_rcu(tp_receiver, &bat_priv->tp_receiver_list, common.list) {
+ if (batadv_compare_eth(tp_receiver->common.other_end, dst))
return true;
}
}
/**
- * batadv_tp_list_find_session() - find tp_vars session object in the global
- * list
+ * batadv_tp_list_find_sender_session() - find tp_vars sender session
+ * object in the global list
* @bat_priv: the bat priv with all the mesh interface information
* @dst: the other endpoint MAC address to look for
* @session: session identifier
- * @role: role of the session
*
* Look for a tp_vars object matching dst as end_point, session as tp meter
* session and return it after having increment the refcounter. Return NULL
*
* Return: matching tp_vars or NULL when no tp_vars was found
*/
-static struct batadv_tp_vars *
-batadv_tp_list_find_session(struct batadv_priv *bat_priv, const u8 *dst,
- const u8 *session, enum batadv_tp_meter_role role)
+static struct batadv_tp_sender *
+batadv_tp_list_find_sender_session(struct batadv_priv *bat_priv, const u8 *dst,
+ const u8 *session)
{
- struct batadv_tp_vars *pos, *tp_vars = NULL;
+ struct batadv_tp_sender *pos, *tp_vars = NULL;
rcu_read_lock();
- hlist_for_each_entry_rcu(pos, &bat_priv->tp_list, list) {
- if (!batadv_compare_eth(pos->other_end, dst))
+ hlist_for_each_entry_rcu(pos, &bat_priv->tp_sender_list, common.list) {
+ if (!batadv_compare_eth(pos->common.other_end, dst))
continue;
- if (memcmp(pos->session, session, sizeof(pos->session)) != 0)
- continue;
-
- if (pos->role != role)
+ if (memcmp(pos->common.session, session, sizeof(pos->common.session)) != 0)
continue;
/* most of the time this function is invoked during the normal
* process..it makes sense to pay more when the session is
* finished and to speed the process up during the measurement
*/
- if (unlikely(!kref_get_unless_zero(&pos->refcount)))
+ if (unlikely(!kref_get_unless_zero(&pos->common.refcount)))
continue;
tp_vars = pos;
}
/**
- * batadv_tp_vars_release() - release batadv_tp_vars from lists and queue for
- * free after rcu grace period
+ * batadv_tp_vars_common_release() - release batadv_tp_vars_common from lists
+ * and queue for free after rcu grace period
* @ref: kref pointer of the batadv_tp_vars
*/
-static void batadv_tp_vars_release(struct kref *ref)
+static void batadv_tp_vars_common_release(struct kref *ref)
{
- struct batadv_tp_vars *tp_vars;
+ struct batadv_tp_vars_common *tp_vars;
struct batadv_tp_unacked *un, *safe;
- tp_vars = container_of(ref, struct batadv_tp_vars, refcount);
+ tp_vars = container_of(ref, struct batadv_tp_vars_common, refcount);
/* lock should not be needed because this object is now out of any
* context!
}
/**
- * batadv_tp_vars_put() - decrement the batadv_tp_vars refcounter and possibly
- * release it
+ * batadv_tp_sender_put() - decrement the batadv_tp_sender
+ * refcounter and possibly release it
* @tp_vars: the private data of the current TP meter session to be free'd
*/
-static void batadv_tp_vars_put(struct batadv_tp_vars *tp_vars)
+static void batadv_tp_sender_put(struct batadv_tp_sender *tp_vars)
{
if (!tp_vars)
return;
- kref_put(&tp_vars->refcount, batadv_tp_vars_release);
+ kref_put(&tp_vars->common.refcount, batadv_tp_vars_common_release);
}
/**
- * batadv_tp_list_detach() - remove tp session from mesh session list once
+ * batadv_tp_list_detach() - remove tp receiver session from mesh session list once
* @tp_vars: the private data of the current TP meter session
+ *
+ * Return: whether tp_vars was detached from list and reference must be freed
*/
-static void batadv_tp_list_detach(struct batadv_tp_vars *tp_vars)
+static bool batadv_tp_list_detach(struct batadv_tp_vars_common *tp_vars)
{
bool detached = false;
spin_unlock_bh(&tp_vars->bat_priv->tp_list_lock);
if (!detached)
- return;
+ return false;
atomic_dec(&tp_vars->bat_priv->tp_num);
- /* drop list reference */
- batadv_tp_vars_put(tp_vars);
+ return true;
}
/**
* batadv_tp_sender_cleanup() - cleanup sender data and drop and timer
* @tp_vars: the private data of the current TP meter session to cleanup
*/
-static void batadv_tp_sender_cleanup(struct batadv_tp_vars *tp_vars)
+static void batadv_tp_sender_cleanup(struct batadv_tp_sender *tp_vars)
{
cancel_delayed_work_sync(&tp_vars->finish_work);
- batadv_tp_list_detach(tp_vars);
+ if (batadv_tp_list_detach(&tp_vars->common))
+ batadv_tp_sender_put(tp_vars);
/* kill the timer and remove its reference */
- timer_shutdown_sync(&tp_vars->timer);
- batadv_tp_vars_put(tp_vars);
+ timer_shutdown_sync(&tp_vars->common.timer);
+ batadv_tp_sender_put(tp_vars);
}
/**
* @tp_vars: the private data of the current TP meter session
*/
static void batadv_tp_sender_end(struct batadv_priv *bat_priv,
- struct batadv_tp_vars *tp_vars)
+ struct batadv_tp_sender *tp_vars)
{
enum batadv_tp_meter_reason reason;
u32 session_cookie;
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
"Test towards %pM finished..shutting down (reason=%d)\n",
- tp_vars->other_end, reason);
+ tp_vars->common.other_end, reason);
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
"Last timing stats: SRTT=%ums RTTVAR=%ums RTO=%ums\n",
"Final values: cwnd=%u ss_threshold=%u\n",
tp_vars->cwnd, tp_vars->ss_threshold);
- session_cookie = batadv_tp_session_cookie(tp_vars->session,
+ session_cookie = batadv_tp_session_cookie(tp_vars->common.session,
tp_vars->icmp_uid);
batadv_tp_batctl_notify(reason,
- tp_vars->other_end,
+ tp_vars->common.other_end,
bat_priv,
tp_vars->start_time,
atomic64_read(&tp_vars->tot_sent),
* @tp_vars: the private data of the current TP meter session
* @reason: reason for tp meter session stop
*/
-static void batadv_tp_sender_shutdown(struct batadv_tp_vars *tp_vars,
+static void batadv_tp_sender_shutdown(struct batadv_tp_sender *tp_vars,
enum batadv_tp_meter_reason reason)
{
atomic_cmpxchg(&tp_vars->send_result, 0, reason);
*
* Return: whether stop reason was found
*/
-static bool batadv_tp_sender_stopped(struct batadv_tp_vars *tp_vars)
+static bool batadv_tp_sender_stopped(struct batadv_tp_sender *tp_vars)
{
return atomic_read(&tp_vars->send_result) != 0;
}
static void batadv_tp_sender_finish(struct work_struct *work)
{
struct delayed_work *delayed_work;
- struct batadv_tp_vars *tp_vars;
+ struct batadv_tp_sender *tp_vars;
delayed_work = to_delayed_work(work);
- tp_vars = container_of(delayed_work, struct batadv_tp_vars,
+ tp_vars = container_of(delayed_work, struct batadv_tp_sender,
finish_work);
batadv_tp_sender_shutdown(tp_vars, BATADV_TP_REASON_COMPLETE);
*
* Reschedule the timer using tp_vars->rto as delay
*/
-static void batadv_tp_reset_sender_timer(struct batadv_tp_vars *tp_vars)
+static void batadv_tp_reset_sender_timer(struct batadv_tp_sender *tp_vars)
{
/* most of the time this function is invoked while normal packet
* reception...
/* timer ref will be dropped in batadv_tp_sender_cleanup */
return;
- mod_timer(&tp_vars->timer, jiffies + msecs_to_jiffies(tp_vars->rto));
+ mod_timer(&tp_vars->common.timer, jiffies + msecs_to_jiffies(tp_vars->rto));
}
/**
*/
static void batadv_tp_sender_timeout(struct timer_list *t)
{
- struct batadv_tp_vars *tp_vars = timer_container_of(tp_vars, t, timer);
- struct batadv_priv *bat_priv = tp_vars->bat_priv;
+ struct batadv_tp_sender *tp_vars = timer_container_of(tp_vars, t, common.timer);
+ struct batadv_priv *bat_priv = tp_vars->common.bat_priv;
if (batadv_tp_sender_stopped(tp_vars))
return;
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
"Meter: RTO fired during test towards %pM! cwnd=%u new ss_thr=%u, resetting last_sent to %u\n",
- tp_vars->other_end, tp_vars->cwnd, tp_vars->ss_threshold,
+ tp_vars->common.other_end, tp_vars->cwnd, tp_vars->ss_threshold,
atomic_read(&tp_vars->last_acked));
tp_vars->cwnd = BATADV_TP_PLEN * 3;
* @buf: Buffer to fill with bytes
* @nbytes: amount of pseudorandom bytes
*/
-static void batadv_tp_fill_prerandom(struct batadv_tp_vars *tp_vars,
+static void batadv_tp_fill_prerandom(struct batadv_tp_sender *tp_vars,
u8 *buf, size_t nbytes)
{
u32 local_offset;
* 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,
+static int batadv_tp_send_msg(struct batadv_tp_sender *tp_vars, const u8 *src,
struct batadv_orig_node *orig_node,
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;
const struct batadv_icmp_tp_packet *icmp;
- struct batadv_tp_vars *tp_vars;
+ struct batadv_tp_sender *tp_vars;
const unsigned char *dev_addr;
size_t packet_len, mss;
u32 rtt, recv_ack, cwnd;
icmp = (struct batadv_icmp_tp_packet *)skb->data;
/* find the tp_vars */
- tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
- icmp->session, BATADV_TP_SENDER);
+ tp_vars = batadv_tp_list_find_sender_session(bat_priv, icmp->orig,
+ icmp->session);
if (unlikely(!tp_vars))
return;
out:
batadv_hardif_put(primary_if);
batadv_orig_node_put(orig_node);
- batadv_tp_vars_put(tp_vars);
+ batadv_tp_sender_put(tp_vars);
}
/**
*
* Return: true when congestion window is not full, false otherwise
*/
-static bool batadv_tp_avail(struct batadv_tp_vars *tp_vars,
+static bool batadv_tp_avail(struct batadv_tp_sender *tp_vars,
size_t payload_len)
{
u32 last_sent = READ_ONCE(tp_vars->last_sent);
* remaining jiffies (at least 1) if the condition evaluated to true before
* the timeout elapsed, or -ERESTARTSYS if it was interrupted by a signal.
*/
-static int batadv_tp_wait_available(struct batadv_tp_vars *tp_vars, size_t plen)
+static int batadv_tp_wait_available(struct batadv_tp_sender *tp_vars, size_t plen)
{
int ret;
*/
static int batadv_tp_send(void *arg)
{
- struct batadv_tp_vars *tp_vars = arg;
- struct batadv_priv *bat_priv = tp_vars->bat_priv;
+ struct batadv_tp_sender *tp_vars = arg;
+ struct batadv_priv *bat_priv = tp_vars->common.bat_priv;
struct batadv_hard_iface *primary_if = NULL;
struct batadv_orig_node *orig_node = NULL;
size_t payload_len, packet_len;
int err = 0;
- if (unlikely(tp_vars->role != BATADV_TP_SENDER)) {
- err = BATADV_TP_REASON_DST_UNREACHABLE;
- batadv_tp_sender_shutdown(tp_vars, err);
- goto out;
- }
-
- orig_node = batadv_orig_hash_find(bat_priv, tp_vars->other_end);
+ orig_node = batadv_orig_hash_find(bat_priv, tp_vars->common.other_end);
if (unlikely(!orig_node)) {
err = BATADV_TP_REASON_DST_UNREACHABLE;
batadv_tp_sender_shutdown(tp_vars, err);
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,
+ tp_vars->common.session, tp_vars->icmp_uid,
jiffies_to_msecs(jiffies));
/* something went wrong during the preparation/transmission */
batadv_tp_sender_cleanup(tp_vars);
complete(&tp_vars->finished);
- batadv_tp_vars_put(tp_vars);
+ batadv_tp_sender_put(tp_vars);
return 0;
}
* 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_kthread(struct batadv_tp_sender *tp_vars)
{
struct task_struct *kthread;
- struct batadv_priv *bat_priv = tp_vars->bat_priv;
+ struct batadv_priv *bat_priv = tp_vars->common.bat_priv;
u32 session_cookie;
- kref_get(&tp_vars->refcount);
+ kref_get(&tp_vars->common.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,
+ session_cookie = batadv_tp_session_cookie(tp_vars->common.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,
+ tp_vars->common.other_end,
bat_priv, session_cookie);
/* drop reserved reference for kthread */
- batadv_tp_vars_put(tp_vars);
+ batadv_tp_sender_put(tp_vars);
/* cleanup of failed tp meter variables */
batadv_tp_sender_cleanup(tp_vars);
void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
u32 test_length, u32 *cookie)
{
- struct batadv_tp_vars *tp_vars;
+ struct batadv_tp_sender *tp_vars;
u8 session_id[2];
u8 icmp_uid;
u32 session_cookie;
}
/* initialize tp_vars */
- ether_addr_copy(tp_vars->other_end, dst);
- kref_init(&tp_vars->refcount);
- tp_vars->role = BATADV_TP_SENDER;
+ ether_addr_copy(tp_vars->common.other_end, dst);
+ kref_init(&tp_vars->common.refcount);
atomic_set(&tp_vars->send_result, 0);
- memcpy(tp_vars->session, session_id, sizeof(session_id));
+ memcpy(tp_vars->common.session, session_id, sizeof(session_id));
tp_vars->icmp_uid = icmp_uid;
tp_vars->last_sent = BATADV_TP_FIRST_SEQ;
atomic64_set(&tp_vars->tot_sent, 0);
- kref_get(&tp_vars->refcount);
- timer_setup(&tp_vars->timer, batadv_tp_sender_timeout, 0);
+ kref_get(&tp_vars->common.refcount);
+ timer_setup(&tp_vars->common.timer, batadv_tp_sender_timeout, 0);
- tp_vars->bat_priv = bat_priv;
+ tp_vars->common.bat_priv = bat_priv;
tp_vars->start_time = jiffies;
init_waitqueue_head(&tp_vars->more_bytes);
init_completion(&tp_vars->finished);
- spin_lock_init(&tp_vars->unacked_lock);
- INIT_LIST_HEAD(&tp_vars->unacked_list);
+ spin_lock_init(&tp_vars->common.unacked_lock);
+ INIT_LIST_HEAD(&tp_vars->common.unacked_list);
spin_lock_init(&tp_vars->cwnd_lock);
/* init work item for finished tp tests */
INIT_DELAYED_WORK(&tp_vars->finish_work, batadv_tp_sender_finish);
- kref_get(&tp_vars->refcount);
- hlist_add_head_rcu(&tp_vars->list, &bat_priv->tp_list);
+ kref_get(&tp_vars->common.refcount);
+ hlist_add_head_rcu(&tp_vars->common.list, &bat_priv->tp_sender_list);
spin_unlock_bh(&bat_priv->tp_list_lock);
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
batadv_tp_start_kthread(tp_vars);
/* don't return reference to new tp_vars */
- batadv_tp_vars_put(tp_vars);
+ batadv_tp_sender_put(tp_vars);
}
/**
u8 return_value)
{
struct batadv_orig_node *orig_node;
- struct batadv_tp_vars *tp_vars;
+ struct batadv_tp_sender *tp_vars;
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
"Meter: stopping test towards %pM\n", dst);
if (!orig_node)
return;
- tp_vars = batadv_tp_list_find(bat_priv, orig_node->orig, BATADV_TP_SENDER);
+ tp_vars = batadv_tp_list_find_sender(bat_priv, orig_node->orig);
if (!tp_vars) {
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
"Meter: trying to interrupt an already over connection\n");
}
batadv_tp_sender_shutdown(tp_vars, return_value);
- batadv_tp_vars_put(tp_vars);
+ batadv_tp_sender_put(tp_vars);
out_put_orig_node:
batadv_orig_node_put(orig_node);
}
+/**
+ * batadv_tp_list_find_receiver_session() - find tp_vars receiver session
+ * object in the global list
+ * @bat_priv: the bat priv with all the mesh interface information
+ * @dst: the other endpoint MAC address to look for
+ * @session: session identifier
+ *
+ * Look for a tp_vars object matching dst as end_point, session as tp meter
+ * session and return it after having increment the refcounter. Return NULL
+ * is not found
+ *
+ * Return: matching tp_vars or NULL when no tp_vars was found
+ */
+static struct batadv_tp_receiver *
+batadv_tp_list_find_receiver_session(struct batadv_priv *bat_priv, const u8 *dst,
+ const u8 *session)
+{
+ struct batadv_tp_receiver *pos, *tp_vars = NULL;
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(pos, &bat_priv->tp_receiver_list, common.list) {
+ if (!batadv_compare_eth(pos->common.other_end, dst))
+ continue;
+
+ if (memcmp(pos->common.session, session, sizeof(pos->common.session)) != 0)
+ continue;
+
+ /* most of the time this function is invoked during the normal
+ * process..it makes sense to pay more when the session is
+ * finished and to speed the process up during the measurement
+ */
+ if (unlikely(!kref_get_unless_zero(&pos->common.refcount)))
+ continue;
+
+ tp_vars = pos;
+ break;
+ }
+ rcu_read_unlock();
+
+ return tp_vars;
+}
+
+/**
+ * batadv_tp_receiver_put() - decrement the batadv_tp_receiver
+ * refcounter and possibly release it
+ * @tp_vars: the private data of the current TP meter session to be free'd
+ */
+static void batadv_tp_receiver_put(struct batadv_tp_receiver *tp_vars)
+{
+ if (!tp_vars)
+ return;
+
+ kref_put(&tp_vars->common.refcount, batadv_tp_vars_common_release);
+}
+
/**
* batadv_tp_reset_receiver_timer() - reset the receiver shutdown timer
* @tp_vars: the private data of the current TP meter session
*
* start the receiver shutdown timer or reset it if already started
*/
-static void batadv_tp_reset_receiver_timer(struct batadv_tp_vars *tp_vars)
+static void batadv_tp_reset_receiver_timer(struct batadv_tp_receiver *tp_vars)
{
- mod_timer(&tp_vars->timer,
+ mod_timer(&tp_vars->common.timer,
jiffies + msecs_to_jiffies(BATADV_TP_RECV_TIMEOUT));
}
*/
static void batadv_tp_receiver_shutdown(struct timer_list *t)
{
- struct batadv_tp_vars *tp_vars = timer_container_of(tp_vars, t, timer);
+ struct batadv_tp_receiver *tp_vars = timer_container_of(tp_vars, t, common.timer);
struct batadv_tp_unacked *un, *safe;
struct batadv_priv *bat_priv;
- bat_priv = tp_vars->bat_priv;
+ bat_priv = tp_vars->common.bat_priv;
/* if there is recent activity rearm the timer */
if (!batadv_has_timed_out(tp_vars->last_recv_time,
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
"Shutting down for inactivity (more than %dms) from %pM\n",
- BATADV_TP_RECV_TIMEOUT, tp_vars->other_end);
+ BATADV_TP_RECV_TIMEOUT, tp_vars->common.other_end);
- batadv_tp_list_detach(tp_vars);
+ if (batadv_tp_list_detach(&tp_vars->common))
+ batadv_tp_receiver_put(tp_vars);
- spin_lock_bh(&tp_vars->unacked_lock);
- list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) {
+ spin_lock_bh(&tp_vars->common.unacked_lock);
+ list_for_each_entry_safe(un, safe, &tp_vars->common.unacked_list, list) {
list_del(&un->list);
kfree(un);
}
- spin_unlock_bh(&tp_vars->unacked_lock);
+ spin_unlock_bh(&tp_vars->common.unacked_lock);
/* drop reference of timer */
if (WARN_ON(atomic_xchg(&tp_vars->receiving, 0) != 1))
return;
- batadv_tp_vars_put(tp_vars);
+ batadv_tp_receiver_put(tp_vars);
}
/**
*
* Return: true if the packed has been successfully processed, false otherwise
*/
-static bool batadv_tp_handle_out_of_order(struct batadv_tp_vars *tp_vars,
+static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars,
const struct sk_buff *skb)
{
const struct batadv_icmp_tp_packet *icmp;
payload_len = skb->len - sizeof(struct batadv_unicast_packet);
new->len = payload_len;
- spin_lock_bh(&tp_vars->unacked_lock);
+ spin_lock_bh(&tp_vars->common.unacked_lock);
/* if the list is empty immediately attach this new object */
- if (list_empty(&tp_vars->unacked_list)) {
- list_add(&new->list, &tp_vars->unacked_list);
+ if (list_empty(&tp_vars->common.unacked_list)) {
+ list_add(&new->list, &tp_vars->common.unacked_list);
goto out;
}
* the last received packet (the one being processed now) has a bigger
* seqno than all the others already stored.
*/
- list_for_each_entry_reverse(un, &tp_vars->unacked_list, list) {
+ list_for_each_entry_reverse(un, &tp_vars->common.unacked_list, list) {
/* check for duplicates */
if (new->seqno == un->seqno) {
if (new->len > un->len)
/* received packet with smallest seqno out of order; add it to front */
if (!added)
- list_add(&new->list, &tp_vars->unacked_list);
+ list_add(&new->list, &tp_vars->common.unacked_list);
out:
- spin_unlock_bh(&tp_vars->unacked_lock);
+ spin_unlock_bh(&tp_vars->common.unacked_lock);
return true;
}
* without gaps
* @tp_vars: the private data of the current TP meter session
*/
-static void batadv_tp_ack_unordered(struct batadv_tp_vars *tp_vars)
+static void batadv_tp_ack_unordered(struct batadv_tp_receiver *tp_vars)
{
struct batadv_tp_unacked *un, *safe;
u32 to_ack;
/* go through the unacked packet list and possibly ACK them as
* well
*/
- spin_lock_bh(&tp_vars->unacked_lock);
- list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) {
+ spin_lock_bh(&tp_vars->common.unacked_lock);
+ list_for_each_entry_safe(un, safe, &tp_vars->common.unacked_list, list) {
/* the list is ordered, therefore it is possible to stop as soon
* there is a gap between the last acked seqno and the seqno of
* the packet under inspection
list_del(&un->list);
kfree(un);
}
- spin_unlock_bh(&tp_vars->unacked_lock);
+ spin_unlock_bh(&tp_vars->common.unacked_lock);
}
/**
*
* Return: corresponding tp_vars or NULL on errors
*/
-static struct batadv_tp_vars *
+static struct batadv_tp_receiver *
batadv_tp_init_recv(struct batadv_priv *bat_priv,
const struct batadv_icmp_tp_packet *icmp)
{
- struct batadv_tp_vars *tp_vars = NULL;
+ struct batadv_tp_receiver *tp_vars = NULL;
spin_lock_bh(&bat_priv->tp_list_lock);
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
goto out_unlock;
- tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
- icmp->session, BATADV_TP_RECEIVER);
+ tp_vars = batadv_tp_list_find_receiver_session(bat_priv, icmp->orig,
+ icmp->session);
if (tp_vars)
goto out_unlock;
goto out_unlock;
}
- ether_addr_copy(tp_vars->other_end, icmp->orig);
- tp_vars->role = BATADV_TP_RECEIVER;
+ ether_addr_copy(tp_vars->common.other_end, icmp->orig);
atomic_set(&tp_vars->receiving, 1);
- memcpy(tp_vars->session, icmp->session, sizeof(tp_vars->session));
+ memcpy(tp_vars->common.session, icmp->session, sizeof(tp_vars->common.session));
tp_vars->last_recv = BATADV_TP_FIRST_SEQ;
- tp_vars->bat_priv = bat_priv;
- kref_init(&tp_vars->refcount);
+ tp_vars->common.bat_priv = bat_priv;
+ kref_init(&tp_vars->common.refcount);
- spin_lock_init(&tp_vars->unacked_lock);
- INIT_LIST_HEAD(&tp_vars->unacked_list);
+ spin_lock_init(&tp_vars->common.unacked_lock);
+ INIT_LIST_HEAD(&tp_vars->common.unacked_list);
- kref_get(&tp_vars->refcount);
- timer_setup(&tp_vars->timer, batadv_tp_receiver_shutdown, 0);
+ kref_get(&tp_vars->common.refcount);
+ timer_setup(&tp_vars->common.timer, batadv_tp_receiver_shutdown, 0);
- kref_get(&tp_vars->refcount);
- hlist_add_head_rcu(&tp_vars->list, &bat_priv->tp_list);
+ kref_get(&tp_vars->common.refcount);
+ hlist_add_head_rcu(&tp_vars->common.list, &bat_priv->tp_receiver_list);
batadv_tp_reset_receiver_timer(tp_vars);
const struct sk_buff *skb)
{
const struct batadv_icmp_tp_packet *icmp;
- struct batadv_tp_vars *tp_vars;
+ struct batadv_tp_receiver *tp_vars;
size_t packet_size;
u32 seqno;
goto out;
}
} else {
- tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
- icmp->session, BATADV_TP_RECEIVER);
+ tp_vars = batadv_tp_list_find_receiver_session(bat_priv, icmp->orig,
+ icmp->session);
if (!tp_vars) {
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
"Unexpected packet from %pM!\n",
batadv_tp_send_ack(bat_priv, icmp->orig, tp_vars->last_recv,
icmp->timestamp, icmp->session, icmp->uid);
out:
- batadv_tp_vars_put(tp_vars);
+ batadv_tp_receiver_put(tp_vars);
}
/**
*/
void batadv_tp_stop_all(struct batadv_priv *bat_priv)
{
- struct batadv_tp_vars *tp_vars[BATADV_TP_MAX_NUM];
- struct batadv_tp_vars *tp_var;
- size_t count = 0;
+ struct batadv_tp_receiver *tp_receivers[BATADV_TP_MAX_NUM];
+ struct batadv_tp_sender *tp_senders[BATADV_TP_MAX_NUM];
+ struct batadv_tp_receiver *tp_receiver;
+ struct batadv_tp_sender *tp_sender;
+ size_t receiver_count = 0;
+ size_t sender_count = 0;
size_t i;
spin_lock_bh(&bat_priv->tp_list_lock);
- hlist_for_each_entry(tp_var, &bat_priv->tp_list, list) {
- if (WARN_ON_ONCE(count >= BATADV_TP_MAX_NUM))
+ hlist_for_each_entry(tp_receiver, &bat_priv->tp_receiver_list, common.list) {
+ if (WARN_ON_ONCE(receiver_count >= BATADV_TP_MAX_NUM))
break;
- if (!kref_get_unless_zero(&tp_var->refcount))
+ if (!kref_get_unless_zero(&tp_receiver->common.refcount))
continue;
- tp_vars[count++] = tp_var;
+ tp_receivers[receiver_count++] = tp_receiver;
+ }
+
+ hlist_for_each_entry(tp_sender, &bat_priv->tp_sender_list, common.list) {
+ if (WARN_ON_ONCE(sender_count >= BATADV_TP_MAX_NUM))
+ break;
+
+ if (!kref_get_unless_zero(&tp_sender->common.refcount))
+ continue;
+
+ tp_senders[sender_count++] = tp_sender;
}
spin_unlock_bh(&bat_priv->tp_list_lock);
- for (i = 0; i < count; i++) {
- tp_var = tp_vars[i];
+ for (i = 0; i < receiver_count; i++) {
+ tp_receiver = tp_receivers[i];
- switch (tp_var->role) {
- case BATADV_TP_SENDER:
- batadv_tp_sender_shutdown(tp_var,
- BATADV_TP_REASON_CANCEL);
- wake_up(&tp_var->more_bytes);
- wait_for_completion(&tp_var->finished);
- break;
- case BATADV_TP_RECEIVER:
- batadv_tp_list_detach(tp_var);
- timer_shutdown_sync(&tp_var->timer);
+ if (batadv_tp_list_detach(&tp_receiver->common))
+ batadv_tp_receiver_put(tp_receiver);
- if (atomic_xchg(&tp_var->receiving, 0) != 1)
- break;
+ timer_shutdown_sync(&tp_receiver->common.timer);
- batadv_tp_vars_put(tp_var);
- break;
- }
+ if (atomic_xchg(&tp_receiver->receiving, 0) != 0)
+ batadv_tp_receiver_put(tp_receiver);
+
+ batadv_tp_receiver_put(tp_receiver);
+ }
+
+ for (i = 0; i < sender_count; i++) {
+ tp_sender = tp_senders[i];
+
+ batadv_tp_sender_shutdown(tp_sender, BATADV_TP_REASON_CANCEL);
+ wake_up(&tp_sender->more_bytes);
+ wait_for_completion(&tp_sender->finished);
- batadv_tp_vars_put(tp_var);
+ batadv_tp_sender_put(tp_sender);
}
synchronize_net();