diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index 62b855a8292b..0a13aa503745 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -96,6 +96,11 @@ #define BATADV_TP_PLEN (BATADV_TP_PACKET_LEN - ETH_HLEN - \ sizeof(struct batadv_unicast_packet)) +/** + * BATADV_TP_MAX_UNACKED - maximum number of packets a receiver didn't yet ack + */ +#define BATADV_TP_MAX_UNACKED 100 + static u8 batadv_tp_prerandom[4096] __read_mostly; /** @@ -1212,6 +1217,7 @@ static void batadv_tp_receiver_shutdown(struct timer_list *t) list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) { list_del(&un->list); kfree(un); + tp_vars->unacked_count--; } spin_unlock_bh(&tp_vars->unacked_lock); @@ -1324,6 +1330,7 @@ static bool batadv_tp_handle_out_of_order(struct batadv_tp_vars *tp_vars, /* 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); + tp_vars->unacked_count++; goto out; } @@ -1354,12 +1361,24 @@ static bool batadv_tp_handle_out_of_order(struct batadv_tp_vars *tp_vars, */ list_add(&new->list, &un->list); added = true; + tp_vars->unacked_count++; break; } /* received packet with smallest seqno out of order; add it to front */ - if (!added) + if (!added) { list_add(&new->list, &tp_vars->unacked_list); + tp_vars->unacked_count++; + } + + /* remove the last (biggest) unacked seqno when list is too large */ + if (tp_vars->unacked_count > BATADV_TP_MAX_UNACKED) { + un = list_last_entry(&tp_vars->unacked_list, + struct batadv_tp_unacked, list); + list_del(&un->list); + kfree(un); + tp_vars->unacked_count--; + } out: spin_unlock_bh(&tp_vars->unacked_lock); @@ -1396,6 +1415,7 @@ static void batadv_tp_ack_unordered(struct batadv_tp_vars *tp_vars) list_del(&un->list); kfree(un); + tp_vars->unacked_count--; } spin_unlock_bh(&tp_vars->unacked_lock); } @@ -1445,6 +1465,7 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv, spin_lock_init(&tp_vars->unacked_lock); INIT_LIST_HEAD(&tp_vars->unacked_list); + tp_vars->unacked_count = 0; kref_get(&tp_vars->refcount); timer_setup(&tp_vars->timer, batadv_tp_receiver_shutdown, 0); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 67feea66b8bb..45447c5aa114 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1450,6 +1450,9 @@ struct batadv_tp_vars { /** @unacked_lock: protect unacked_list */ spinlock_t unacked_lock; + /** @unacked_count: number of unacked entries */ + size_t unacked_count; + /** @last_recv_time: time time (jiffies) a msg was received */ unsigned long last_recv_time;