mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
This cleanup patchset includes the following patches:
- drop hardif global list, by Nora Schiffer (2 patches)
- make hard_iface->mesh_iface immutable, by Sven Eckelmann
- further post-hardif global list cleanups,
by Nora Schiffer (3 patches)
- cleanups and simplifications depending on the hardif->mesh_iface
immutability guarantee, by Sven Eckelmann (3 patches)
- tvlv: extract tvlv header iterator, by Sven Eckelmann
- tp_meter: improve unacked list handling,
by Sven Eckelmann (5 patches)
-----BEGIN PGP SIGNATURE-----
iQJKBAABCgA0FiEE1ilQI7G+y+fdhnrfoSvjmEKSnqEFAmpDzOAWHHN3QHNpbW9u
d3VuZGVybGljaC5kZQAKCRChK+OYQpKeod9SD/wJfdheMNGfp4H+drVIsf4eusM6
xmdTR5we2dhvfllb4aPQsEQ9TUQgzYU7j8VfUkQ5G8cryqbR7/s5YSTivWY09CN5
ecqgRSOHRrzZGDmsfnXykKMzIhw/7JW7ytRXoH1OagwyN38byFy8df+W7EuWx9mn
oQv/Fxhej+zmq/wOyORgaUJO/35otEW2m95eepE292uPZw4Tyxfh1dYBufQhJCyU
XC0vSe77AcHN6JeiY9kVD8p6rlAU7ZM0inZx6ZdUPnbaYRSDri9wCFjQTGgogoXt
8uQPuTY4fcba7ljnKxG124xXghq5U18hJfPT6xi8oNTlCKm4MKKt8Z6YudDzGqXh
YRj/abFuTU8FxoOi0NnrZqFEL9lGDeHv7/j+BEKcpRLPc0DnMWwlgDRVUcPKGntE
5qA7c0+/2DPLOfohIvcR9cCikWozXDLDjzkkW19Jt3HAAaApr27V3NsKcV9TqYMj
DtmjSPR9H7sxGrCKJcfNVuE8bctVKKlF/uFLflBDKWq8XU+6Eth++C6ZKd1oCiKT
drvsV44UWK2mQHTBYs3XwlX7XW+6tvTlpImmv1sarBGdGUKQcKgzxtmImeYGtXHd
r6Yrc1Pqqe2SdnSOVEG3c3hxWKn1ckDNF7lC3y0lCFWYKP32FsLrfmHl7YtbnXWV
w8o7IrYlPGAJn4NhvQ==
=TykP
-----END PGP SIGNATURE-----
Merge tag 'batadv-next-pullrequest-20260630' of https://git.open-mesh.org/batadv
Simon Wunderlich says:
====================
This cleanup patchset includes the following patches:
- drop hardif global list, by Nora Schiffer (2 patches)
- make hard_iface->mesh_iface immutable, by Sven Eckelmann
- further post-hardif global list cleanups,
by Nora Schiffer (3 patches)
- cleanups and simplifications depending on the hardif->mesh_iface
immutability guarantee, by Sven Eckelmann (3 patches)
- tvlv: extract tvlv header iterator, by Sven Eckelmann
- tp_meter: improve unacked list handling,
by Sven Eckelmann (5 patches)
* tag 'batadv-next-pullrequest-20260630' of https://git.open-mesh.org/batadv:
batman-adv: tp_meter: delay allocation of unacked entry
batman-adv: tp_meter: adjust name of receiver lock
batman-adv: tp_meter: keep unacked list for receivers
batman-adv: tp_meter: combine adjacent/overlapping unacked entries
batman-adv: tp_meter: simplify unordered ack calculation
batman-adv: tvlv: extract tvlv header iterator
batman-adv: iv: drop migration check for batadv_hard_iface
Revert "batman-adv: v: stop OGMv2 on disabled interface"
batman-adv: drop NULL check for immutable hardif->mesh_iface
batman-adv: drop unneeded goto and initialization from batadv_hardif_disable_interface()
batman-adv: move hardif generation counter into batadv_priv
batman-adv: remove BATADV_IF_NOT_IN_USE hardif state
batman-adv: make hard_iface->mesh_iface immutable
batman-adv: remove global hardif list
batman-adv: create hardif only for netdevs that are part of a mesh
====================
Link: https://patch.msgid.link/
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
f07f1e3ded
|
|
@ -404,23 +404,14 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
|
|||
/* send a batman ogm packet */
|
||||
static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
|
||||
{
|
||||
struct net_device *mesh_iface;
|
||||
|
||||
if (!forw_packet->if_incoming) {
|
||||
pr_err("Error - can't forward packet: incoming iface not specified\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mesh_iface = forw_packet->if_incoming->mesh_iface;
|
||||
|
||||
if (WARN_ON(!forw_packet->if_outgoing))
|
||||
return;
|
||||
|
||||
if (forw_packet->if_outgoing->mesh_iface != mesh_iface) {
|
||||
pr_warn("%s: mesh interface switch for queued OGM\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (forw_packet->if_incoming->if_status != BATADV_IF_ACTIVE)
|
||||
return;
|
||||
|
||||
|
|
@ -910,8 +901,7 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
|
|||
|
||||
static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
|
||||
hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
|
||||
if (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
|
||||
return;
|
||||
|
||||
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
|
|
|
|||
|
|
@ -90,12 +90,6 @@ static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh,
|
|||
u32 throughput;
|
||||
int ret;
|
||||
|
||||
/* don't query throughput when no longer associated with any
|
||||
* batman-adv interface
|
||||
*/
|
||||
if (!mesh_iface)
|
||||
return false;
|
||||
|
||||
/* if the user specified a customised value for this interface, then
|
||||
* return it directly
|
||||
*/
|
||||
|
|
@ -311,8 +305,7 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
|
|||
goto out;
|
||||
|
||||
/* we are in the process of shutting this interface down */
|
||||
if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
|
||||
hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
|
||||
if (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
|
||||
goto out;
|
||||
|
||||
/* the interface was enabled but may not be ready yet */
|
||||
|
|
|
|||
|
|
@ -115,14 +115,14 @@ static void batadv_v_ogm_start_timer(struct batadv_priv *bat_priv)
|
|||
|
||||
/**
|
||||
* batadv_v_ogm_send_to_if() - send a batman ogm using a given interface
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @skb: the OGM to send
|
||||
* @hard_iface: the interface to use to send the OGM
|
||||
*/
|
||||
static void batadv_v_ogm_send_to_if(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb,
|
||||
static void batadv_v_ogm_send_to_if(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
|
||||
if (hard_iface->if_status != BATADV_IF_ACTIVE) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
|
|
@ -189,7 +189,6 @@ static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface)
|
|||
|
||||
/**
|
||||
* batadv_v_ogm_aggr_send() - flush & send aggregation queue
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @hard_iface: the interface with the aggregation queue to flush
|
||||
*
|
||||
* Aggregates all OGMv2 packets currently in the aggregation queue into a
|
||||
|
|
@ -199,8 +198,7 @@ static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface)
|
|||
*
|
||||
* Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
|
||||
*/
|
||||
static void batadv_v_ogm_aggr_send(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *hard_iface)
|
||||
static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
unsigned int aggr_len = hard_iface->bat_v.aggr_len;
|
||||
struct sk_buff *skb_aggr;
|
||||
|
|
@ -230,26 +228,21 @@ static void batadv_v_ogm_aggr_send(struct batadv_priv *bat_priv,
|
|||
consume_skb(skb);
|
||||
}
|
||||
|
||||
batadv_v_ogm_send_to_if(bat_priv, skb_aggr, hard_iface);
|
||||
batadv_v_ogm_send_to_if(skb_aggr, hard_iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_v_ogm_queue_on_if() - queue a batman ogm on a given interface
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @skb: the OGM to queue
|
||||
* @hard_iface: the interface to queue the OGM on
|
||||
*/
|
||||
static void batadv_v_ogm_queue_on_if(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb,
|
||||
static void batadv_v_ogm_queue_on_if(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
if (hard_iface->mesh_iface != bat_priv->mesh_iface) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
|
||||
if (!READ_ONCE(bat_priv->aggregated_ogms)) {
|
||||
batadv_v_ogm_send_to_if(bat_priv, skb, hard_iface);
|
||||
batadv_v_ogm_send_to_if(skb, hard_iface);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +253,7 @@ static void batadv_v_ogm_queue_on_if(struct batadv_priv *bat_priv,
|
|||
}
|
||||
|
||||
if (!batadv_v_ogm_queue_left(skb, hard_iface))
|
||||
batadv_v_ogm_aggr_send(bat_priv, hard_iface);
|
||||
batadv_v_ogm_aggr_send(hard_iface);
|
||||
|
||||
hard_iface->bat_v.aggr_len += batadv_v_ogm_len(skb);
|
||||
__skb_queue_tail(&hard_iface->bat_v.aggr_list, skb);
|
||||
|
|
@ -357,7 +350,7 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
|
|||
break;
|
||||
}
|
||||
|
||||
batadv_v_ogm_queue_on_if(bat_priv, skb_tmp, hard_iface);
|
||||
batadv_v_ogm_queue_on_if(skb_tmp, hard_iface);
|
||||
batadv_hardif_put(hard_iface);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
|
@ -397,14 +390,12 @@ void batadv_v_ogm_aggr_work(struct work_struct *work)
|
|||
{
|
||||
struct batadv_hard_iface_bat_v *batv;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
|
||||
batv = container_of(work, struct batadv_hard_iface_bat_v, aggr_wq.work);
|
||||
hard_iface = container_of(batv, struct batadv_hard_iface, bat_v);
|
||||
bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
|
||||
spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
|
||||
batadv_v_ogm_aggr_send(bat_priv, hard_iface);
|
||||
batadv_v_ogm_aggr_send(hard_iface);
|
||||
spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock);
|
||||
|
||||
batadv_v_ogm_start_queue_timer(hard_iface);
|
||||
|
|
@ -601,7 +592,7 @@ static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
|
|||
if_outgoing->net_dev->name, ntohl(ogm_forward->throughput),
|
||||
ogm_forward->ttl, if_incoming->net_dev->name);
|
||||
|
||||
batadv_v_ogm_queue_on_if(bat_priv, skb, if_outgoing);
|
||||
batadv_v_ogm_queue_on_if(skb, if_outgoing);
|
||||
|
||||
out:
|
||||
batadv_orig_ifinfo_put(orig_ifinfo);
|
||||
|
|
|
|||
|
|
@ -344,7 +344,6 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, const u8 *mac,
|
|||
struct sk_buff *skb;
|
||||
struct ethhdr *ethhdr;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct net_device *mesh_iface;
|
||||
u8 *hw_src;
|
||||
struct batadv_bla_claim_dst local_claim_dest;
|
||||
__be32 zeroip = 0;
|
||||
|
|
@ -357,14 +356,10 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, const u8 *mac,
|
|||
sizeof(local_claim_dest));
|
||||
local_claim_dest.type = claimtype;
|
||||
|
||||
mesh_iface = READ_ONCE(primary_if->mesh_iface);
|
||||
if (!mesh_iface)
|
||||
goto out;
|
||||
|
||||
skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
|
||||
/* IP DST: 0.0.0.0 */
|
||||
zeroip,
|
||||
mesh_iface,
|
||||
primary_if->mesh_iface,
|
||||
/* IP SRC: 0.0.0.0 */
|
||||
zeroip,
|
||||
/* Ethernet DST: Broadcast */
|
||||
|
|
@ -442,7 +437,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, const u8 *mac,
|
|||
}
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
skb->protocol = eth_type_trans(skb, mesh_iface);
|
||||
skb->protocol = eth_type_trans(skb, primary_if->mesh_iface);
|
||||
batadv_inc_counter(bat_priv, BATADV_CNT_RX);
|
||||
batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
|
||||
skb->len + ETH_HLEN);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ void batadv_hardif_release(struct kref *ref)
|
|||
struct batadv_hard_iface *hard_iface;
|
||||
|
||||
hard_iface = container_of(ref, struct batadv_hard_iface, refcount);
|
||||
netdev_put(hard_iface->mesh_iface, &hard_iface->meshif_dev_tracker);
|
||||
netdev_put(hard_iface->net_dev, &hard_iface->dev_tracker);
|
||||
|
||||
kfree_rcu(hard_iface, rcu);
|
||||
|
|
@ -75,21 +76,21 @@ void batadv_hardif_release(struct kref *ref)
|
|||
* Return: batadv_hard_iface of net_dev (with increased refcnt), NULL on errors
|
||||
*/
|
||||
struct batadv_hard_iface *
|
||||
batadv_hardif_get_by_netdev(const struct net_device *net_dev)
|
||||
batadv_hardif_get_by_netdev(struct net_device *net_dev)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct net_device *mesh_iface;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
|
||||
if (hard_iface->net_dev == net_dev &&
|
||||
kref_get_unless_zero(&hard_iface->refcount))
|
||||
goto out;
|
||||
}
|
||||
ASSERT_RTNL();
|
||||
|
||||
hard_iface = NULL;
|
||||
mesh_iface = netdev_master_upper_dev_get(net_dev);
|
||||
if (!mesh_iface || !batadv_meshif_is_valid(mesh_iface))
|
||||
return NULL;
|
||||
|
||||
hard_iface = netdev_lower_dev_get_private(mesh_iface, net_dev);
|
||||
if (!kref_get_unless_zero(&hard_iface->refcount))
|
||||
return NULL;
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return hard_iface;
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +246,7 @@ struct net_device *__batadv_get_real_netdev(struct net_device *netdev)
|
|||
}
|
||||
|
||||
hard_iface = batadv_hardif_get_by_netdev(netdev);
|
||||
if (!hard_iface || !hard_iface->mesh_iface)
|
||||
if (!hard_iface)
|
||||
goto out;
|
||||
|
||||
net = dev_net(hard_iface->mesh_iface);
|
||||
|
|
@ -539,16 +540,10 @@ static void batadv_check_known_mac_addr(const struct batadv_hard_iface *hard_ifa
|
|||
const struct batadv_hard_iface *tmp_hard_iface;
|
||||
struct list_head *iter;
|
||||
|
||||
if (!mesh_iface)
|
||||
return;
|
||||
|
||||
netdev_for_each_lower_private(mesh_iface, tmp_hard_iface, iter) {
|
||||
if (tmp_hard_iface == hard_iface)
|
||||
continue;
|
||||
|
||||
if (tmp_hard_iface->if_status == BATADV_IF_NOT_IN_USE)
|
||||
continue;
|
||||
|
||||
if (!batadv_compare_eth(tmp_hard_iface->net_dev->dev_addr,
|
||||
hard_iface->net_dev->dev_addr))
|
||||
continue;
|
||||
|
|
@ -574,9 +569,6 @@ static void batadv_hardif_recalc_extra_skbroom(struct net_device *mesh_iface)
|
|||
|
||||
rcu_read_lock();
|
||||
netdev_for_each_lower_private_rcu(mesh_iface, hard_iface, iter) {
|
||||
if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
|
||||
continue;
|
||||
|
||||
lower_header_len = max_t(unsigned short, lower_header_len,
|
||||
hard_iface->net_dev->hard_header_len);
|
||||
|
||||
|
|
@ -723,38 +715,63 @@ batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface)
|
|||
}
|
||||
|
||||
/**
|
||||
* batadv_hardif_enable_interface() - Enslave hard interface to mesh interface
|
||||
* @hard_iface: hard interface to add to mesh interface
|
||||
* batadv_hardif_enable_interface() - Enslave interface to mesh interface
|
||||
* @net_dev: netdev struct of the interface to add to mesh interface
|
||||
* @mesh_iface: netdev struct of the mesh interface
|
||||
*
|
||||
* Return: 0 on success or negative error number in case of failure
|
||||
*/
|
||||
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
||||
int batadv_hardif_enable_interface(struct net_device *net_dev,
|
||||
struct net_device *mesh_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv;
|
||||
__be16 ethertype = htons(ETH_P_BATMAN);
|
||||
int max_header_len = batadv_max_header_len();
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
unsigned int required_mtu;
|
||||
unsigned int hardif_mtu;
|
||||
bool fragmentation;
|
||||
int ret;
|
||||
|
||||
hardif_mtu = READ_ONCE(hard_iface->net_dev->mtu);
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (!batadv_is_valid_iface(net_dev))
|
||||
return -EINVAL;
|
||||
|
||||
hardif_mtu = READ_ONCE(net_dev->mtu);
|
||||
required_mtu = READ_ONCE(mesh_iface->mtu) + max_header_len;
|
||||
|
||||
if (hardif_mtu < ETH_MIN_MTU + max_header_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
|
||||
goto out;
|
||||
hard_iface = kzalloc_obj(*hard_iface, GFP_ATOMIC);
|
||||
if (!hard_iface)
|
||||
return -ENOMEM;
|
||||
|
||||
kref_get(&hard_iface->refcount);
|
||||
netdev_hold(net_dev, &hard_iface->dev_tracker, GFP_ATOMIC);
|
||||
hard_iface->net_dev = net_dev;
|
||||
|
||||
hard_iface->if_status = BATADV_IF_INACTIVE;
|
||||
|
||||
INIT_HLIST_HEAD(&hard_iface->neigh_list);
|
||||
|
||||
mutex_init(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
spin_lock_init(&hard_iface->neigh_list_lock);
|
||||
kref_init(&hard_iface->refcount);
|
||||
|
||||
hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
|
||||
if (batadv_is_wifi_hardif(hard_iface))
|
||||
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
|
||||
|
||||
WRITE_ONCE(hard_iface->hop_penalty, 0);
|
||||
|
||||
batadv_v_hardif_init(hard_iface);
|
||||
|
||||
netdev_hold(mesh_iface, &hard_iface->meshif_dev_tracker, GFP_ATOMIC);
|
||||
hard_iface->mesh_iface = mesh_iface;
|
||||
bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
|
||||
bat_priv->hardif_generation++;
|
||||
ret = netdev_master_upper_dev_link(hard_iface->net_dev,
|
||||
mesh_iface, hard_iface, NULL, NULL);
|
||||
if (ret)
|
||||
|
|
@ -764,9 +781,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|||
if (ret < 0)
|
||||
goto err_upper;
|
||||
|
||||
hard_iface->if_status = BATADV_IF_INACTIVE;
|
||||
|
||||
kref_get(&hard_iface->refcount);
|
||||
hard_iface->batman_adv_ptype.type = ethertype;
|
||||
hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv;
|
||||
hard_iface->batman_adv_ptype.dev = hard_iface->net_dev;
|
||||
|
|
@ -802,14 +816,11 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|||
if (bat_priv->algo_ops->iface.enabled)
|
||||
bat_priv->algo_ops->iface.enabled(hard_iface);
|
||||
|
||||
out:
|
||||
return 0;
|
||||
|
||||
err_upper:
|
||||
netdev_upper_dev_unlink(hard_iface->net_dev, mesh_iface);
|
||||
err_dev:
|
||||
hard_iface->mesh_iface = NULL;
|
||||
netdev_put(mesh_iface, &hard_iface->meshif_dev_tracker);
|
||||
batadv_hardif_put(hard_iface);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -821,17 +832,18 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
|||
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
batadv_hardif_deactivate_interface(hard_iface);
|
||||
|
||||
if (hard_iface->if_status != BATADV_IF_INACTIVE)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
batadv_info(hard_iface->mesh_iface, "Removing interface: %s\n",
|
||||
hard_iface->net_dev->name);
|
||||
dev_remove_pack(&hard_iface->batman_adv_ptype);
|
||||
batadv_hardif_put(hard_iface);
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (hard_iface == primary_if) {
|
||||
|
|
@ -842,15 +854,16 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface)
|
|||
|
||||
batadv_hardif_put(new_if);
|
||||
}
|
||||
batadv_hardif_put(primary_if);
|
||||
|
||||
bat_priv->algo_ops->iface.disable(hard_iface);
|
||||
hard_iface->if_status = BATADV_IF_NOT_IN_USE;
|
||||
hard_iface->if_status = BATADV_IF_TO_BE_REMOVED;
|
||||
|
||||
/* delete all references to this hard_iface */
|
||||
batadv_purge_orig_ref(bat_priv);
|
||||
batadv_purge_outstanding_packets(bat_priv, hard_iface);
|
||||
netdev_put(hard_iface->mesh_iface, &hard_iface->meshif_dev_tracker);
|
||||
|
||||
bat_priv->hardif_generation++;
|
||||
netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->mesh_iface);
|
||||
batadv_hardif_recalc_extra_skbroom(hard_iface->mesh_iface);
|
||||
|
||||
|
|
@ -858,67 +871,6 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface)
|
|||
if (list_empty(&hard_iface->mesh_iface->adj_list.lower))
|
||||
batadv_gw_check_client_stop(bat_priv);
|
||||
|
||||
hard_iface->mesh_iface = NULL;
|
||||
batadv_hardif_put(hard_iface);
|
||||
|
||||
out:
|
||||
batadv_hardif_put(primary_if);
|
||||
}
|
||||
|
||||
static struct batadv_hard_iface *
|
||||
batadv_hardif_add_interface(struct net_device *net_dev)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (!batadv_is_valid_iface(net_dev))
|
||||
return NULL;
|
||||
|
||||
hard_iface = kzalloc_obj(*hard_iface, GFP_ATOMIC);
|
||||
if (!hard_iface)
|
||||
return NULL;
|
||||
|
||||
netdev_hold(net_dev, &hard_iface->dev_tracker, GFP_ATOMIC);
|
||||
hard_iface->net_dev = net_dev;
|
||||
|
||||
hard_iface->mesh_iface = NULL;
|
||||
hard_iface->if_status = BATADV_IF_NOT_IN_USE;
|
||||
|
||||
INIT_LIST_HEAD(&hard_iface->list);
|
||||
INIT_HLIST_HEAD(&hard_iface->neigh_list);
|
||||
|
||||
mutex_init(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
spin_lock_init(&hard_iface->neigh_list_lock);
|
||||
kref_init(&hard_iface->refcount);
|
||||
|
||||
hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
|
||||
if (batadv_is_wifi_hardif(hard_iface))
|
||||
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
|
||||
|
||||
WRITE_ONCE(hard_iface->hop_penalty, 0);
|
||||
|
||||
batadv_v_hardif_init(hard_iface);
|
||||
|
||||
kref_get(&hard_iface->refcount);
|
||||
list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
|
||||
batadv_hardif_generation++;
|
||||
|
||||
return hard_iface;
|
||||
}
|
||||
|
||||
static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
/* first deactivate interface */
|
||||
if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
|
||||
batadv_hardif_disable_interface(hard_iface);
|
||||
|
||||
if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
|
||||
return;
|
||||
|
||||
hard_iface->if_status = BATADV_IF_TO_BE_REMOVED;
|
||||
batadv_hardif_put(hard_iface);
|
||||
}
|
||||
|
||||
|
|
@ -1082,10 +1034,6 @@ static int batadv_hard_if_event(struct notifier_block *this,
|
|||
batadv_wifi_net_device_event(event, net_dev);
|
||||
|
||||
hard_iface = batadv_hardif_get_by_netdev(net_dev);
|
||||
if (!hard_iface && (event == NETDEV_REGISTER ||
|
||||
event == NETDEV_POST_TYPE_CHANGE))
|
||||
hard_iface = batadv_hardif_add_interface(net_dev);
|
||||
|
||||
if (!hard_iface)
|
||||
goto out;
|
||||
|
||||
|
|
@ -1099,19 +1047,12 @@ static int batadv_hard_if_event(struct notifier_block *this,
|
|||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
case NETDEV_PRE_TYPE_CHANGE:
|
||||
list_del_rcu(&hard_iface->list);
|
||||
batadv_hardif_generation++;
|
||||
|
||||
batadv_hardif_remove_interface(hard_iface);
|
||||
batadv_hardif_disable_interface(hard_iface);
|
||||
break;
|
||||
case NETDEV_CHANGEMTU:
|
||||
if (hard_iface->mesh_iface)
|
||||
batadv_update_min_mtu(hard_iface->mesh_iface);
|
||||
batadv_update_min_mtu(hard_iface->mesh_iface);
|
||||
break;
|
||||
case NETDEV_CHANGEADDR:
|
||||
if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
|
||||
goto hardif_put;
|
||||
|
||||
batadv_check_known_mac_addr(hard_iface);
|
||||
|
||||
bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
|
|
|
|||
|
|
@ -21,12 +21,6 @@
|
|||
* enum batadv_hard_if_state - State of a hard interface
|
||||
*/
|
||||
enum batadv_hard_if_state {
|
||||
/**
|
||||
* @BATADV_IF_NOT_IN_USE: interface is not used as slave interface of a
|
||||
* batman-adv mesh interface
|
||||
*/
|
||||
BATADV_IF_NOT_IN_USE,
|
||||
|
||||
/**
|
||||
* @BATADV_IF_TO_BE_REMOVED: interface will be removed from mesh
|
||||
* interface
|
||||
|
|
@ -74,8 +68,8 @@ u32 batadv_netdev_get_wifi_flags(struct net_device *net_dev);
|
|||
u32 batadv_hardif_get_wifi_flags(struct batadv_hard_iface *hard_iface);
|
||||
bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface);
|
||||
struct batadv_hard_iface*
|
||||
batadv_hardif_get_by_netdev(const struct net_device *net_dev);
|
||||
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
|
||||
batadv_hardif_get_by_netdev(struct net_device *net_dev);
|
||||
int batadv_hardif_enable_interface(struct net_device *net_dev,
|
||||
struct net_device *mesh_iface);
|
||||
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface);
|
||||
int batadv_hardif_min_mtu(struct net_device *mesh_iface);
|
||||
|
|
|
|||
|
|
@ -59,11 +59,6 @@
|
|||
#include "tp_meter.h"
|
||||
#include "translation-table.h"
|
||||
|
||||
/* List manipulations on hardif_list have to be rtnl_lock()'ed,
|
||||
* list traversals just rcu-locked
|
||||
*/
|
||||
struct list_head batadv_hardif_list;
|
||||
unsigned int batadv_hardif_generation;
|
||||
static int (*batadv_rx_handler[256])(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if);
|
||||
|
||||
|
|
@ -95,7 +90,6 @@ static int __init batadv_init(void)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
INIT_LIST_HEAD(&batadv_hardif_list);
|
||||
batadv_algo_init();
|
||||
|
||||
batadv_recv_handler_init();
|
||||
|
|
@ -450,9 +444,6 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
|||
if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb)))
|
||||
goto err_free;
|
||||
|
||||
if (!hard_iface->mesh_iface)
|
||||
goto err_free;
|
||||
|
||||
bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
|
||||
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
|
||||
|
|
|
|||
|
|
@ -226,9 +226,6 @@ static inline int batadv_print_vid(unsigned short vid)
|
|||
return -1;
|
||||
}
|
||||
|
||||
extern struct list_head batadv_hardif_list;
|
||||
extern unsigned int batadv_hardif_generation;
|
||||
|
||||
extern struct workqueue_struct *batadv_event_workqueue;
|
||||
|
||||
int batadv_mesh_init(struct net_device *mesh_iface);
|
||||
|
|
|
|||
|
|
@ -836,18 +836,7 @@ static int batadv_meshif_slave_add(struct net_device *dev,
|
|||
struct net_device *slave_dev,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
int ret = -EINVAL;
|
||||
|
||||
hard_iface = batadv_hardif_get_by_netdev(slave_dev);
|
||||
if (!hard_iface || hard_iface->mesh_iface)
|
||||
goto out;
|
||||
|
||||
ret = batadv_hardif_enable_interface(hard_iface, dev);
|
||||
|
||||
out:
|
||||
batadv_hardif_put(hard_iface);
|
||||
return ret;
|
||||
return batadv_hardif_enable_interface(slave_dev, dev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -968,7 +968,7 @@ batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb)
|
|||
bat_priv = netdev_priv(mesh_iface);
|
||||
|
||||
rtnl_lock();
|
||||
cb->seq = batadv_hardif_generation << 1 | 1;
|
||||
cb->seq = bat_priv->hardif_generation << 1 | 1;
|
||||
|
||||
netdev_for_each_lower_private(mesh_iface, hard_iface, iter) {
|
||||
if (i++ < skip)
|
||||
|
|
@ -1211,7 +1211,9 @@ batadv_netlink_get_hardif_from_ifindex(struct batadv_priv *bat_priv,
|
|||
if (!hard_dev)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
rtnl_lock();
|
||||
hard_iface = batadv_hardif_get_by_netdev(hard_dev);
|
||||
rtnl_unlock();
|
||||
if (!hard_iface)
|
||||
goto err_put_harddev;
|
||||
|
||||
|
|
|
|||
|
|
@ -1033,7 +1033,6 @@ batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv,
|
|||
|
||||
/* don't purge if the interface is not (going) down */
|
||||
if (if_outgoing->if_status != BATADV_IF_INACTIVE &&
|
||||
if_outgoing->if_status != BATADV_IF_NOT_IN_USE &&
|
||||
if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)
|
||||
continue;
|
||||
|
||||
|
|
@ -1077,7 +1076,6 @@ batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv,
|
|||
|
||||
/* don't purge if the interface is not (going) down */
|
||||
if (if_outgoing->if_status != BATADV_IF_INACTIVE &&
|
||||
if_outgoing->if_status != BATADV_IF_NOT_IN_USE &&
|
||||
if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)
|
||||
continue;
|
||||
|
||||
|
|
@ -1127,10 +1125,8 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
|
|||
|
||||
if (batadv_has_timed_out(last_seen, BATADV_PURGE_TIMEOUT) ||
|
||||
if_incoming->if_status == BATADV_IF_INACTIVE ||
|
||||
if_incoming->if_status == BATADV_IF_NOT_IN_USE ||
|
||||
if_incoming->if_status == BATADV_IF_TO_BE_REMOVED) {
|
||||
if (if_incoming->if_status == BATADV_IF_INACTIVE ||
|
||||
if_incoming->if_status == BATADV_IF_NOT_IN_USE ||
|
||||
if_incoming->if_status == BATADV_IF_TO_BE_REMOVED)
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"neighbor purge: originator %pM, neighbor: %pM, iface: %s\n",
|
||||
|
|
|
|||
|
|
@ -358,28 +358,16 @@ batadv_tp_list_find_sender_session(struct batadv_priv *bat_priv, const u8 *dst,
|
|||
}
|
||||
|
||||
/**
|
||||
* batadv_tp_vars_common_release() - release batadv_tp_vars_common from lists
|
||||
* batadv_tp_sender_release() - release batadv_tp_sender
|
||||
* and queue for free after rcu grace period
|
||||
* @ref: kref pointer of the batadv_tp_vars_common
|
||||
* @ref: kref pointer of the batadv_tp_sender
|
||||
*/
|
||||
static void batadv_tp_vars_common_release(struct kref *ref)
|
||||
static void batadv_tp_sender_release(struct kref *ref)
|
||||
{
|
||||
struct batadv_tp_vars_common *tp_vars;
|
||||
struct batadv_tp_unacked *un, *safe;
|
||||
struct batadv_tp_sender *tp_vars;
|
||||
|
||||
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!
|
||||
*/
|
||||
spin_lock_bh(&tp_vars->unacked_lock);
|
||||
list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) {
|
||||
list_del(&un->list);
|
||||
kfree(un);
|
||||
}
|
||||
spin_unlock_bh(&tp_vars->unacked_lock);
|
||||
|
||||
kfree_rcu(tp_vars, rcu);
|
||||
tp_vars = container_of(ref, struct batadv_tp_sender, common.refcount);
|
||||
kfree_rcu(tp_vars, common.rcu);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -392,7 +380,7 @@ static void batadv_tp_sender_put(struct batadv_tp_sender *tp_vars)
|
|||
if (!tp_vars)
|
||||
return;
|
||||
|
||||
kref_put(&tp_vars->common.refcount, batadv_tp_vars_common_release);
|
||||
kref_put(&tp_vars->common.refcount, batadv_tp_sender_release);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1145,9 +1133,6 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
|
|||
init_waitqueue_head(&tp_vars->more_bytes);
|
||||
init_completion(&tp_vars->finished);
|
||||
|
||||
spin_lock_init(&tp_vars->common.unacked_lock);
|
||||
INIT_LIST_HEAD(&tp_vars->common.unacked_list);
|
||||
|
||||
spin_lock_init(&tp_vars->cc_lock);
|
||||
|
||||
tp_vars->prerandom_offset = 0;
|
||||
|
|
@ -1251,6 +1236,33 @@ batadv_tp_list_find_receiver_session(struct batadv_priv *bat_priv, const u8 *dst
|
|||
return tp_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tp_receiver_release() - release batadv_tp_receiver
|
||||
* and queue for free after rcu grace period
|
||||
* @ref: kref pointer of the batadv_tp_receiver
|
||||
*/
|
||||
static void batadv_tp_receiver_release(struct kref *ref)
|
||||
{
|
||||
struct batadv_tp_receiver *tp_vars;
|
||||
struct batadv_tp_unacked *safe;
|
||||
struct batadv_tp_unacked *un;
|
||||
|
||||
tp_vars = container_of(ref, struct batadv_tp_receiver, common.refcount);
|
||||
|
||||
/* lock should not be needed because this object is now out of any
|
||||
* context!
|
||||
*/
|
||||
spin_lock_bh(&tp_vars->ack_seqno_lock);
|
||||
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->ack_seqno_lock);
|
||||
|
||||
kfree_rcu(tp_vars, common.rcu);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tp_receiver_put() - decrement the batadv_tp_receiver
|
||||
* refcounter and possibly release it
|
||||
|
|
@ -1261,7 +1273,7 @@ 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);
|
||||
kref_put(&tp_vars->common.refcount, batadv_tp_receiver_release);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1304,13 +1316,13 @@ static void batadv_tp_receiver_shutdown(struct timer_list *t)
|
|||
if (batadv_tp_list_detach(&tp_vars->common))
|
||||
batadv_tp_receiver_put(tp_vars);
|
||||
|
||||
spin_lock_bh(&tp_vars->common.unacked_lock);
|
||||
list_for_each_entry_safe(un, safe, &tp_vars->common.unacked_list, list) {
|
||||
spin_lock_bh(&tp_vars->ack_seqno_lock);
|
||||
list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) {
|
||||
list_del(&un->list);
|
||||
kfree(un);
|
||||
tp_vars->common.unacked_count--;
|
||||
tp_vars->unacked_count--;
|
||||
}
|
||||
spin_unlock_bh(&tp_vars->common.unacked_lock);
|
||||
spin_unlock_bh(&tp_vars->ack_seqno_lock);
|
||||
|
||||
/* drop reference of timer */
|
||||
if (WARN_ON(atomic_xchg(&tp_vars->receiving, 0) != 1))
|
||||
|
|
@ -1403,69 +1415,106 @@ static int batadv_tp_send_ack(struct batadv_priv *bat_priv, const u8 *dst,
|
|||
*/
|
||||
static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars,
|
||||
u32 seqno, u32 payload_len)
|
||||
__must_hold(&tp_vars->common.unacked_lock)
|
||||
__must_hold(&tp_vars->ack_seqno_lock)
|
||||
{
|
||||
struct batadv_tp_unacked *un, *new;
|
||||
bool added = false;
|
||||
struct list_head *pos = &tp_vars->unacked_list;
|
||||
struct batadv_tp_unacked *new = NULL;
|
||||
u32 end_seqno = seqno + payload_len;
|
||||
struct batadv_tp_unacked *safe;
|
||||
struct batadv_tp_unacked *un;
|
||||
|
||||
new = kmalloc_obj(*new, GFP_ATOMIC);
|
||||
if (unlikely(!new))
|
||||
return false;
|
||||
|
||||
new->seqno = seqno;
|
||||
new->len = payload_len;
|
||||
|
||||
/* if the list is empty immediately attach this new object */
|
||||
if (list_empty(&tp_vars->common.unacked_list)) {
|
||||
list_add(&new->list, &tp_vars->common.unacked_list);
|
||||
tp_vars->common.unacked_count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* otherwise loop over the list and either drop the packet because this
|
||||
* is a duplicate or store it at the right position.
|
||||
/* loop over the list to find either an existing entry which the new
|
||||
* seqno range can be merged with or the position at which a new entry
|
||||
* has to be inserted.
|
||||
*
|
||||
* The iteration is done in the reverse way because it is likely that
|
||||
* 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->common.unacked_list, list) {
|
||||
/* check for duplicates */
|
||||
if (new->seqno == un->seqno) {
|
||||
if (new->len > un->len)
|
||||
un->len = new->len;
|
||||
kfree(new);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* look for the right position */
|
||||
if (batadv_seq_before(new->seqno, un->seqno))
|
||||
list_for_each_entry_reverse(un, &tp_vars->unacked_list, list) {
|
||||
/* look for the right position - an un which is smaller */
|
||||
if (batadv_seq_before(seqno, un->seqno))
|
||||
continue;
|
||||
|
||||
/* as soon as an entry having a bigger seqno is found, the new
|
||||
* one is attached _after_ it. In this way the list is kept in
|
||||
* ascending order
|
||||
/* smaller/equal seqno was found but they might be directly
|
||||
* after another or overlapping. keep only a single entry
|
||||
*
|
||||
* It is already known that:
|
||||
*
|
||||
* un->seqno <= seqno
|
||||
*
|
||||
* When establishing that:
|
||||
*
|
||||
* seqno <= un->seqno + un->len
|
||||
*
|
||||
* Then it is not necessary to add a new entry because the
|
||||
* smaller/equal seqno of un might already contain the new
|
||||
* received packet or we only add new data directly after
|
||||
* the end of un. The latter can be identified using:
|
||||
*
|
||||
* un->seqno + un->len <= end_seqno
|
||||
*/
|
||||
list_add(&new->list, &un->list);
|
||||
added = true;
|
||||
tp_vars->common.unacked_count++;
|
||||
if (!batadv_seq_before(un->seqno + un->len, seqno)) {
|
||||
/* new data directly after un? */
|
||||
if (!batadv_seq_before(end_seqno, un->seqno + un->len))
|
||||
un->len = end_seqno - un->seqno;
|
||||
|
||||
/* un now represents both old un + new range and has to
|
||||
* be used to check if the gap to the next seqno range
|
||||
* was closed
|
||||
*/
|
||||
new = un;
|
||||
} else {
|
||||
/* as soon as an entry having a smaller seqno is found,
|
||||
* the new one is attached _after_ it. In this way the
|
||||
* list is kept in ascending order
|
||||
*/
|
||||
pos = &un->list;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* received packet with smallest seqno out of order; add it to front */
|
||||
if (!added) {
|
||||
list_add(&new->list, &tp_vars->common.unacked_list);
|
||||
tp_vars->common.unacked_count++;
|
||||
/* no entry to merge with was found; insert a new one after the entry
|
||||
* with the next smaller seqno (or at the front of the list when the
|
||||
* new seqno is the smallest or the list is empty)
|
||||
*/
|
||||
if (!new) {
|
||||
new = kmalloc_obj(*new, GFP_ATOMIC);
|
||||
if (unlikely(!new))
|
||||
return false;
|
||||
|
||||
new->seqno = seqno;
|
||||
new->len = payload_len;
|
||||
|
||||
list_add(&new->list, pos);
|
||||
tp_vars->unacked_count++;
|
||||
}
|
||||
|
||||
/* check if new filled the gap to the next list entries */
|
||||
un = new;
|
||||
list_for_each_entry_safe_continue(un, safe, &tp_vars->unacked_list, list) {
|
||||
if (batadv_seq_before(end_seqno, un->seqno))
|
||||
break;
|
||||
|
||||
/* next entry is overlapping or adjacent - combine both */
|
||||
if (batadv_seq_before(end_seqno, un->seqno + un->len)) {
|
||||
end_seqno = un->seqno + un->len;
|
||||
new->len = end_seqno - new->seqno;
|
||||
}
|
||||
|
||||
list_del(&un->list);
|
||||
kfree(un);
|
||||
tp_vars->unacked_count--;
|
||||
}
|
||||
|
||||
/* remove the last (biggest) unacked seqno when list is too large */
|
||||
if (tp_vars->common.unacked_count > BATADV_TP_MAX_UNACKED) {
|
||||
un = list_last_entry(&tp_vars->common.unacked_list,
|
||||
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->common.unacked_count--;
|
||||
tp_vars->unacked_count--;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -1477,7 +1526,7 @@ static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars,
|
|||
* @tp_vars: the private data of the current TP meter session
|
||||
*/
|
||||
static void batadv_tp_ack_unordered(struct batadv_tp_receiver *tp_vars)
|
||||
__must_hold(&tp_vars->common.unacked_lock)
|
||||
__must_hold(&tp_vars->ack_seqno_lock)
|
||||
{
|
||||
struct batadv_tp_unacked *un, *safe;
|
||||
u32 to_ack;
|
||||
|
|
@ -1485,7 +1534,7 @@ static void batadv_tp_ack_unordered(struct batadv_tp_receiver *tp_vars)
|
|||
/* go through the unacked packet list and possibly ACK them as
|
||||
* well
|
||||
*/
|
||||
list_for_each_entry_safe(un, safe, &tp_vars->common.unacked_list, list) {
|
||||
list_for_each_entry_safe(un, safe, &tp_vars->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
|
||||
|
|
@ -1493,14 +1542,14 @@ static void batadv_tp_ack_unordered(struct batadv_tp_receiver *tp_vars)
|
|||
if (batadv_seq_before(tp_vars->last_recv, un->seqno))
|
||||
break;
|
||||
|
||||
to_ack = un->seqno + un->len - tp_vars->last_recv;
|
||||
to_ack = un->seqno + un->len;
|
||||
|
||||
if (batadv_seq_before(tp_vars->last_recv, un->seqno + un->len))
|
||||
tp_vars->last_recv += to_ack;
|
||||
if (batadv_seq_before(tp_vars->last_recv, to_ack))
|
||||
tp_vars->last_recv = to_ack;
|
||||
|
||||
list_del(&un->list);
|
||||
kfree(un);
|
||||
tp_vars->common.unacked_count--;
|
||||
tp_vars->unacked_count--;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1547,9 +1596,9 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv,
|
|||
tp_vars->common.bat_priv = bat_priv;
|
||||
kref_init(&tp_vars->common.refcount);
|
||||
|
||||
spin_lock_init(&tp_vars->common.unacked_lock);
|
||||
INIT_LIST_HEAD(&tp_vars->common.unacked_list);
|
||||
tp_vars->common.unacked_count = 0;
|
||||
spin_lock_init(&tp_vars->ack_seqno_lock);
|
||||
INIT_LIST_HEAD(&tp_vars->unacked_list);
|
||||
tp_vars->unacked_count = 0;
|
||||
|
||||
kref_get(&tp_vars->common.refcount);
|
||||
timer_setup(&tp_vars->common.timer, batadv_tp_receiver_shutdown, 0);
|
||||
|
|
@ -1609,7 +1658,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv,
|
|||
WRITE_ONCE(tp_vars->last_recv_time, jiffies);
|
||||
}
|
||||
|
||||
spin_lock_bh(&tp_vars->common.unacked_lock);
|
||||
spin_lock_bh(&tp_vars->ack_seqno_lock);
|
||||
|
||||
/* if the packet is a duplicate, it may be the case that an ACK has been
|
||||
* lost. Resend the ACK
|
||||
|
|
@ -1625,7 +1674,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv,
|
|||
* not been enqueued correctly
|
||||
*/
|
||||
if (!batadv_tp_handle_out_of_order(tp_vars, seqno, payload_len)) {
|
||||
spin_unlock_bh(&tp_vars->common.unacked_lock);
|
||||
spin_unlock_bh(&tp_vars->ack_seqno_lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1641,7 +1690,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv,
|
|||
|
||||
send_ack:
|
||||
to_ack = tp_vars->last_recv;
|
||||
spin_unlock_bh(&tp_vars->common.unacked_lock);
|
||||
spin_unlock_bh(&tp_vars->ack_seqno_lock);
|
||||
|
||||
/* send the ACK. If the received packet was out of order, the ACK that
|
||||
* is going to be sent is a duplicate (the sender will count them and
|
||||
|
|
|
|||
|
|
@ -442,6 +442,54 @@ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
|
|||
return NET_RX_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tvlv_hdr_next() - move a tvlv buffer cursor to the next container
|
||||
* @tvlv_value: cursor into the tvlv buffer, advanced past the returned
|
||||
* container's content on success
|
||||
* @tvlv_value_len: remaining length of the tvlv buffer, reduced by the returned
|
||||
* container's size on success
|
||||
*
|
||||
* Parses a single container header at the current cursor position and, if a
|
||||
* complete container is available, advances the cursor and remaining length
|
||||
* past it. The returned header stays valid; its content is located at
|
||||
* (returned header + 1) and is ntohs(hdr->len) bytes long.
|
||||
*
|
||||
* Return: pointer to the next tvlv container header, or NULL if no further
|
||||
* complete container is present in the buffer.
|
||||
*/
|
||||
static struct batadv_tvlv_hdr *batadv_tvlv_hdr_next(void **tvlv_value, u16 *tvlv_value_len)
|
||||
{
|
||||
struct batadv_tvlv_hdr *tvlv_hdr;
|
||||
u16 tvlv_value_cont_len;
|
||||
void *tvlv_value_cont;
|
||||
u16 tvlv_len;
|
||||
|
||||
tvlv_value_cont = *tvlv_value;
|
||||
tvlv_len = *tvlv_value_len;
|
||||
|
||||
if (tvlv_len < sizeof(*tvlv_hdr))
|
||||
return NULL;
|
||||
|
||||
tvlv_hdr = tvlv_value_cont;
|
||||
tvlv_value_cont_len = ntohs(tvlv_hdr->len);
|
||||
tvlv_value_cont = tvlv_hdr + 1;
|
||||
tvlv_len -= sizeof(*tvlv_hdr);
|
||||
|
||||
if (tvlv_value_cont_len > tvlv_len)
|
||||
return NULL;
|
||||
|
||||
/* the next tvlv header is accessed assuming (at least) 2-byte
|
||||
* alignment, so it must start at an even offset.
|
||||
*/
|
||||
if (tvlv_value_cont_len & 1)
|
||||
return NULL;
|
||||
|
||||
*tvlv_value = (u8 *)tvlv_value_cont + tvlv_value_cont_len;
|
||||
*tvlv_value_len = tvlv_len - tvlv_value_cont_len;
|
||||
|
||||
return tvlv_hdr;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tvlv_containers_contain() - check if a tvlv buffer holds a container
|
||||
* @tvlv_value: tvlv content
|
||||
|
|
@ -457,28 +505,10 @@ static bool batadv_tvlv_containers_contain(void *tvlv_value,
|
|||
u8 version)
|
||||
{
|
||||
struct batadv_tvlv_hdr *tvlv_hdr;
|
||||
u16 tvlv_value_cont_len;
|
||||
|
||||
while (tvlv_value_len >= sizeof(*tvlv_hdr)) {
|
||||
tvlv_hdr = tvlv_value;
|
||||
tvlv_value_cont_len = ntohs(tvlv_hdr->len);
|
||||
tvlv_value = tvlv_hdr + 1;
|
||||
tvlv_value_len -= sizeof(*tvlv_hdr);
|
||||
|
||||
if (tvlv_value_cont_len > tvlv_value_len)
|
||||
break;
|
||||
|
||||
/* the next tvlv header is accessed assuming (at least) 2-byte
|
||||
* alignment, so it must start at an even offset.
|
||||
*/
|
||||
if (tvlv_value_cont_len & 1)
|
||||
break;
|
||||
|
||||
while ((tvlv_hdr = batadv_tvlv_hdr_next(&tvlv_value, &tvlv_value_len))) {
|
||||
if (tvlv_hdr->type == type && tvlv_hdr->version == version)
|
||||
return true;
|
||||
|
||||
tvlv_value = (u8 *)tvlv_value + tvlv_value_cont_len;
|
||||
tvlv_value_len -= tvlv_value_cont_len;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -511,20 +541,8 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
|
|||
u8 cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND;
|
||||
int ret = NET_RX_SUCCESS;
|
||||
|
||||
while (tvlv_value_len >= sizeof(*tvlv_hdr)) {
|
||||
tvlv_hdr = tvlv_value;
|
||||
while ((tvlv_hdr = batadv_tvlv_hdr_next(&tvlv_value, &tvlv_value_len))) {
|
||||
tvlv_value_cont_len = ntohs(tvlv_hdr->len);
|
||||
tvlv_value = tvlv_hdr + 1;
|
||||
tvlv_value_len -= sizeof(*tvlv_hdr);
|
||||
|
||||
if (tvlv_value_cont_len > tvlv_value_len)
|
||||
break;
|
||||
|
||||
/* the next tvlv header is accessed assuming (at least) 2-byte
|
||||
* alignment, so it must start at an even offset.
|
||||
*/
|
||||
if (tvlv_value_cont_len & 1)
|
||||
break;
|
||||
|
||||
tvlv_handler = batadv_tvlv_handler_get(bat_priv,
|
||||
tvlv_hdr->type,
|
||||
|
|
@ -532,11 +550,9 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
|
|||
|
||||
ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler,
|
||||
packet_type, orig_node, skb,
|
||||
tvlv_value,
|
||||
tvlv_hdr + 1,
|
||||
tvlv_value_cont_len);
|
||||
batadv_tvlv_handler_put(tvlv_handler);
|
||||
tvlv_value = (u8 *)tvlv_value + tvlv_value_cont_len;
|
||||
tvlv_value_len -= tvlv_value_cont_len;
|
||||
}
|
||||
|
||||
if (packet_type != BATADV_IV_OGM &&
|
||||
|
|
|
|||
|
|
@ -214,9 +214,6 @@ struct batadv_wifi_net_device_state {
|
|||
* struct batadv_hard_iface - network device known to batman-adv
|
||||
*/
|
||||
struct batadv_hard_iface {
|
||||
/** @list: list node for batadv_hardif_list */
|
||||
struct list_head list;
|
||||
|
||||
/** @if_status: status of the interface for batman-adv */
|
||||
char if_status;
|
||||
|
||||
|
|
@ -1335,9 +1332,9 @@ struct batadv_tp_unacked {
|
|||
u32 seqno;
|
||||
|
||||
/** @len: length of the packet */
|
||||
u16 len;
|
||||
u32 len;
|
||||
|
||||
/** @list: list node for &batadv_tp_vars_common.unacked_list */
|
||||
/** @list: list node for &batadv_tp_receiver.unacked_list */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
|
@ -1360,15 +1357,6 @@ struct batadv_tp_vars_common {
|
|||
/** @session: TP session identifier */
|
||||
u8 session[2];
|
||||
|
||||
/** @unacked_list: list of unacked packets (meta-info only) */
|
||||
struct list_head unacked_list;
|
||||
|
||||
/** @unacked_lock: protect unacked_list + &batadv_tp_receiver.last_recv */
|
||||
spinlock_t unacked_lock;
|
||||
|
||||
/** @unacked_count: number of unacked entries */
|
||||
size_t unacked_count;
|
||||
|
||||
/** @refcount: number of context where the object is used */
|
||||
struct kref refcount;
|
||||
|
||||
|
|
@ -1482,6 +1470,15 @@ struct batadv_tp_receiver {
|
|||
|
||||
/** @last_recv_time: time (jiffies) a msg was received */
|
||||
unsigned long last_recv_time;
|
||||
|
||||
/** @unacked_list: list of unacked packets (meta-info only) */
|
||||
struct list_head unacked_list;
|
||||
|
||||
/** @ack_seqno_lock: protect unacked_list + &batadv_tp_receiver.last_recv */
|
||||
spinlock_t ack_seqno_lock;
|
||||
|
||||
/** @unacked_count: number of unacked entries */
|
||||
size_t unacked_count;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1679,6 +1676,9 @@ struct batadv_priv {
|
|||
/** @tp_num: number of currently active tp sessions */
|
||||
atomic_t tp_num;
|
||||
|
||||
/** @hardif_generation: generation counter added to netlink hardif dumps */
|
||||
unsigned int hardif_generation;
|
||||
|
||||
/** @orig_work: work queue callback item for orig node purging */
|
||||
struct delayed_work orig_work;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user