mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
Here are batman-adv bugfixes, all by by Sven Eckelmann.
- fix batadv_skb_is_frag() kernel-doc - BATMAN V: stop OGMv2 on disabled interface - BATMAN IV: abort OGM send on tvlv append failure - BATMAN IV: reject oversized TVLV packets - tp_meter: fix race condition in send error reporting - tp_meter: avoid role confusion in tp_list - mcast: fix use-after-free in orig_node RCU release - BATMAN IV: recover OGM scheduling after forward packet error - bla: fix report_work leak on backbone_gw purge - bla: avoid double decrement of bla.num_requests - bla: avoid NULL-ptr deref for claim via dropped interface -----BEGIN PGP SIGNATURE----- iQJKBAABCgA0FiEE1ilQI7G+y+fdhnrfoSvjmEKSnqEFAmoNoHkWHHN3QHNpbW9u d3VuZGVybGljaC5kZQAKCRChK+OYQpKeoaFZD/4yN7deqhkVKj039EVNxoOOVOSi T0kQCOG6h20UiJX6j2l6QuoXF6vwBGDPFZfwCMKSMWXFhbuhzl8L0oEvZ+p6goho FyPgAWkWRcopPnSiJTQcFXVVtkku7EkPO2MjMLUEkU8YEKGfnBSWHUBr9+Mw0OUV rmrkRQcl7/BpWX++fM0U/qUFfKi8VuIPgQubPyC602/iInseNvx6Ju0abRJeTCF6 YM4IugyxKoHCwHbnR2jNwl1PfaI7FyLF/ZCvi/2NpAfwnjcykBlMYoEj46Qh3dTD 05ZIAHlgHAfMDHuW87rema6aYT0nCpSwtBaM4YE2/vim4hxRot6AN/ho/4JFHzHW GHCuhw3NxADeUJZBefGy4QEtGPIP/Odz4WcVTr/29TnOTKEAG2rsI4mwLoM4ogp/ Wa0tlZWUZNHEsjPHSkEWqnR+X/+J8Q9W/RUP85gthVpMKvHyMf7YC2JBXlJ2QvmF HzmCjYLv83X4pftutf6R/EAy8MedJTSCoCzJGitIDd5qW3EG3yYBgz6ep4DD/4Hp 4qWP3gdUbcPnL5mw3SOWYXhOKFQnOs68h5QsSRdEp4LYj0FExC6EZagRZUU7fGOu W5r7vsN6j83sBuZd5rQRIs1XNSm5RlUAfJAsWawKLI96l2xSuIrtmJq3zP/kc4cH q4Lc88OyebVE5t8/yA== =0Yhf -----END PGP SIGNATURE----- Merge tag 'batadv-net-pullrequest-20260520' of https://git.open-mesh.org/batadv Simon Wunderlich says: ==================== Here are batman-adv bugfixes, all by by Sven Eckelmann. - fix batadv_skb_is_frag() kernel-doc - BATMAN V: stop OGMv2 on disabled interface - BATMAN IV: abort OGM send on tvlv append failure - BATMAN IV: reject oversized TVLV packets - tp_meter: fix race condition in send error reporting - tp_meter: avoid role confusion in tp_list - mcast: fix use-after-free in orig_node RCU release - BATMAN IV: recover OGM scheduling after forward packet error - bla: fix report_work leak on backbone_gw purge - bla: avoid double decrement of bla.num_requests - bla: avoid NULL-ptr deref for claim via dropped interface * tag 'batadv-net-pullrequest-20260520' of https://git.open-mesh.org/batadv: batman-adv: bla: avoid NULL-ptr deref for claim via dropped interface batman-adv: bla: avoid double decrement of bla.num_requests batman-adv: bla: fix report_work leak on backbone_gw purge batman-adv: iv: recover OGM scheduling after forward packet error batman-adv: mcast: fix use-after-free in orig_node RCU release batman-adv: tp_meter: avoid role confusion in tp_list batman-adv: tp_meter: fix race condition in send error reporting batman-adv: tvlv: reject oversized TVLV packets batman-adv: tvlv: abort OGM send on tvlv append failure batman-adv: v: stop OGMv2 on disabled interface batman-adv: fix batadv_skb_is_frag() kernel-doc ==================== Link: https://patch.msgid.link/20260520115422.53552-1-sw@simonwunderlich.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
42734af663
|
|
@ -224,6 +224,8 @@ static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
|
|||
hard_iface->bat_iv.ogm_buff = NULL;
|
||||
|
||||
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
|
||||
cancel_delayed_work_sync(&hard_iface->bat_iv.reschedule_work);
|
||||
}
|
||||
|
||||
static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
|
||||
|
|
@ -536,8 +538,10 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
|
|||
* @if_incoming: interface where the packet was received
|
||||
* @if_outgoing: interface for which the retransmission should be considered
|
||||
* @own_packet: true if it is a self-generated ogm
|
||||
*
|
||||
* Return: whether forward packet was scheduled
|
||||
*/
|
||||
static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
||||
static bool batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
||||
int packet_len, unsigned long send_time,
|
||||
bool direct_link,
|
||||
struct batadv_hard_iface *if_incoming,
|
||||
|
|
@ -561,13 +565,13 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
|||
|
||||
skb = netdev_alloc_skb_ip_align(NULL, skb_size);
|
||||
if (!skb)
|
||||
return;
|
||||
return false;
|
||||
|
||||
forw_packet_aggr = batadv_forw_packet_alloc(if_incoming, if_outgoing,
|
||||
queue_left, bat_priv, skb);
|
||||
if (!forw_packet_aggr) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
forw_packet_aggr->skb->priority = TC_PRIO_CONTROL;
|
||||
|
|
@ -590,6 +594,8 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
|||
batadv_iv_send_outstanding_bat_ogm_packet);
|
||||
|
||||
batadv_forw_packet_ogmv1_queue(bat_priv, forw_packet_aggr, send_time);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* aggregate a new packet into the existing ogm packet */
|
||||
|
|
@ -617,8 +623,10 @@ static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr,
|
|||
* @if_outgoing: interface for which the retransmission should be considered
|
||||
* @own_packet: true if it is a self-generated ogm
|
||||
* @send_time: timestamp (jiffies) when the packet is to be sent
|
||||
*
|
||||
* Return: whether forward packet was scheduled
|
||||
*/
|
||||
static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
|
||||
static bool batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
|
||||
unsigned char *packet_buff,
|
||||
int packet_len,
|
||||
struct batadv_hard_iface *if_incoming,
|
||||
|
|
@ -670,14 +678,16 @@ static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
|
|||
if (!own_packet && atomic_read(&bat_priv->aggregated_ogms))
|
||||
send_time += max_aggregation_jiffies;
|
||||
|
||||
batadv_iv_ogm_aggregate_new(packet_buff, packet_len,
|
||||
send_time, direct_link,
|
||||
if_incoming, if_outgoing,
|
||||
own_packet);
|
||||
return batadv_iv_ogm_aggregate_new(packet_buff, packet_len,
|
||||
send_time, direct_link,
|
||||
if_incoming, if_outgoing,
|
||||
own_packet);
|
||||
} else {
|
||||
batadv_iv_ogm_aggregate(forw_packet_aggr, packet_buff,
|
||||
packet_len, direct_link);
|
||||
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -790,6 +800,9 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
|
|||
u32 seqno;
|
||||
u16 tvlv_len = 0;
|
||||
unsigned long send_time;
|
||||
bool reschedule = false;
|
||||
bool scheduled;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
|
||||
|
|
@ -813,9 +826,15 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
|
|||
* appended as it may alter the tt tvlv container
|
||||
*/
|
||||
batadv_tt_local_commit_changes(bat_priv);
|
||||
tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff,
|
||||
ogm_buff_len,
|
||||
BATADV_OGM_HLEN);
|
||||
ret = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff,
|
||||
ogm_buff_len,
|
||||
BATADV_OGM_HLEN);
|
||||
if (ret < 0) {
|
||||
reschedule = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tvlv_len = ret;
|
||||
}
|
||||
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
|
||||
|
|
@ -834,8 +853,11 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
|
|||
/* OGMs from secondary interfaces are only scheduled on their
|
||||
* respective interfaces.
|
||||
*/
|
||||
batadv_iv_ogm_queue_add(bat_priv, *ogm_buff, *ogm_buff_len,
|
||||
hard_iface, hard_iface, 1, send_time);
|
||||
scheduled = batadv_iv_ogm_queue_add(bat_priv, *ogm_buff, *ogm_buff_len,
|
||||
hard_iface, hard_iface, 1, send_time);
|
||||
if (!scheduled)
|
||||
reschedule = true;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -847,15 +869,28 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
|
|||
if (!kref_get_unless_zero(&tmp_hard_iface->refcount))
|
||||
continue;
|
||||
|
||||
batadv_iv_ogm_queue_add(bat_priv, *ogm_buff,
|
||||
*ogm_buff_len, hard_iface,
|
||||
tmp_hard_iface, 1, send_time);
|
||||
|
||||
scheduled = batadv_iv_ogm_queue_add(bat_priv, *ogm_buff,
|
||||
*ogm_buff_len, hard_iface,
|
||||
tmp_hard_iface, 1, send_time);
|
||||
batadv_hardif_put(tmp_hard_iface);
|
||||
|
||||
if (!scheduled && tmp_hard_iface == hard_iface)
|
||||
reschedule = true;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
out:
|
||||
if (reschedule) {
|
||||
/* there was a failure scheduling the own forward packet.
|
||||
* as result, the batadv_iv_send_outstanding_bat_ogm_packet()
|
||||
* work item is no longer scheduled. it is therefore necessary
|
||||
* to reschedule it manually
|
||||
*/
|
||||
queue_delayed_work(batadv_event_workqueue,
|
||||
&hard_iface->bat_iv.reschedule_work,
|
||||
msecs_to_jiffies(atomic_read(&bat_priv->orig_interval)));
|
||||
}
|
||||
|
||||
batadv_hardif_put(primary_if);
|
||||
}
|
||||
|
||||
|
|
@ -870,6 +905,17 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
|||
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
}
|
||||
|
||||
static void batadv_iv_ogm_reschedule(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work = to_delayed_work(work);
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
|
||||
hard_iface = container_of(delayed_work,
|
||||
struct batadv_hard_iface,
|
||||
bat_iv.reschedule_work);
|
||||
batadv_iv_ogm_schedule(hard_iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_orig_ifinfo_sum() - Get bcast_own sum for originator over interface
|
||||
* @orig_node: originator which reproadcasted the OGMs directly
|
||||
|
|
@ -2262,6 +2308,8 @@ batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1,
|
|||
|
||||
static void batadv_iv_iface_enabled(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
INIT_DELAYED_WORK(&hard_iface->bat_iv.reschedule_work, batadv_iv_ogm_reschedule);
|
||||
|
||||
/* begin scheduling originator messages on that interface */
|
||||
batadv_iv_ogm_schedule(hard_iface);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,14 +113,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 sk_buff *skb,
|
||||
static void batadv_v_ogm_send_to_if(struct batadv_priv *bat_priv,
|
||||
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;
|
||||
|
|
@ -187,6 +187,7 @@ 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
|
||||
|
|
@ -196,7 +197,8 @@ 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_hard_iface *hard_iface)
|
||||
static void batadv_v_ogm_aggr_send(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
unsigned int aggr_len = hard_iface->bat_v.aggr_len;
|
||||
struct sk_buff *skb_aggr;
|
||||
|
|
@ -226,27 +228,32 @@ static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface)
|
|||
consume_skb(skb);
|
||||
}
|
||||
|
||||
batadv_v_ogm_send_to_if(skb_aggr, hard_iface);
|
||||
batadv_v_ogm_send_to_if(bat_priv, 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 sk_buff *skb,
|
||||
static void batadv_v_ogm_queue_on_if(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb,
|
||||
struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
if (hard_iface->mesh_iface != bat_priv->mesh_iface) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!atomic_read(&bat_priv->aggregated_ogms)) {
|
||||
batadv_v_ogm_send_to_if(skb, hard_iface);
|
||||
batadv_v_ogm_send_to_if(bat_priv, skb, hard_iface);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
|
||||
if (!batadv_v_ogm_queue_left(skb, hard_iface))
|
||||
batadv_v_ogm_aggr_send(hard_iface);
|
||||
batadv_v_ogm_aggr_send(bat_priv, hard_iface);
|
||||
|
||||
hard_iface->bat_v.aggr_len += batadv_v_ogm_len(skb);
|
||||
__skb_queue_tail(&hard_iface->bat_v.aggr_list, skb);
|
||||
|
|
@ -262,10 +269,10 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
|
|||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_ogm2_packet *ogm_packet;
|
||||
struct sk_buff *skb, *skb_tmp;
|
||||
unsigned char *ogm_buff;
|
||||
unsigned char **ogm_buff;
|
||||
struct list_head *iter;
|
||||
int ogm_buff_len;
|
||||
u16 tvlv_len = 0;
|
||||
int *ogm_buff_len;
|
||||
u16 tvlv_len;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex);
|
||||
|
|
@ -273,25 +280,27 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
|
|||
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
|
||||
goto out;
|
||||
|
||||
ogm_buff = bat_priv->bat_v.ogm_buff;
|
||||
ogm_buff_len = bat_priv->bat_v.ogm_buff_len;
|
||||
ogm_buff = &bat_priv->bat_v.ogm_buff;
|
||||
ogm_buff_len = &bat_priv->bat_v.ogm_buff_len;
|
||||
|
||||
/* tt changes have to be committed before the tvlv data is
|
||||
* appended as it may alter the tt tvlv container
|
||||
*/
|
||||
batadv_tt_local_commit_changes(bat_priv);
|
||||
tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, &ogm_buff,
|
||||
&ogm_buff_len,
|
||||
BATADV_OGM2_HLEN);
|
||||
ret = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff,
|
||||
ogm_buff_len,
|
||||
BATADV_OGM2_HLEN);
|
||||
if (ret < 0)
|
||||
goto reschedule;
|
||||
|
||||
bat_priv->bat_v.ogm_buff = ogm_buff;
|
||||
bat_priv->bat_v.ogm_buff_len = ogm_buff_len;
|
||||
tvlv_len = ret;
|
||||
|
||||
skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + ogm_buff_len);
|
||||
skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + *ogm_buff_len);
|
||||
if (!skb)
|
||||
goto reschedule;
|
||||
|
||||
skb_reserve(skb, ETH_HLEN);
|
||||
skb_put_data(skb, ogm_buff, ogm_buff_len);
|
||||
skb_put_data(skb, *ogm_buff, *ogm_buff_len);
|
||||
|
||||
ogm_packet = (struct batadv_ogm2_packet *)skb->data;
|
||||
ogm_packet->seqno = htonl(atomic_read(&bat_priv->bat_v.ogm_seqno));
|
||||
|
|
@ -343,7 +352,7 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
|
|||
break;
|
||||
}
|
||||
|
||||
batadv_v_ogm_queue_on_if(skb_tmp, hard_iface);
|
||||
batadv_v_ogm_queue_on_if(bat_priv, skb_tmp, hard_iface);
|
||||
batadv_hardif_put(hard_iface);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
|
@ -383,12 +392,14 @@ 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(hard_iface);
|
||||
batadv_v_ogm_aggr_send(bat_priv, hard_iface);
|
||||
spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock);
|
||||
|
||||
batadv_v_ogm_start_queue_timer(hard_iface);
|
||||
|
|
@ -578,7 +589,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(skb, if_outgoing);
|
||||
batadv_v_ogm_queue_on_if(bat_priv, skb, if_outgoing);
|
||||
|
||||
out:
|
||||
batadv_orig_ifinfo_put(orig_ifinfo);
|
||||
|
|
|
|||
|
|
@ -356,12 +356,14 @@ 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 = primary_if->mesh_iface;
|
||||
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,
|
||||
primary_if->mesh_iface,
|
||||
mesh_iface,
|
||||
/* IP SRC: 0.0.0.0 */
|
||||
zeroip,
|
||||
/* Ethernet DST: Broadcast */
|
||||
|
|
@ -514,8 +516,8 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
|
|||
entry->crc = BATADV_BLA_CRC_INIT;
|
||||
entry->bat_priv = bat_priv;
|
||||
spin_lock_init(&entry->crc_lock);
|
||||
atomic_set(&entry->request_sent, 0);
|
||||
atomic_set(&entry->wait_periods, 0);
|
||||
entry->state = BATADV_BLA_BACKBONE_GW_SYNCED;
|
||||
entry->wait_periods = 0;
|
||||
ether_addr_copy(entry->orig, orig);
|
||||
INIT_WORK(&entry->report_work, batadv_bla_loopdetect_report);
|
||||
kref_init(&entry->refcount);
|
||||
|
|
@ -544,9 +546,13 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
|
|||
batadv_bla_send_announce(bat_priv, entry);
|
||||
|
||||
/* this will be decreased in the worker thread */
|
||||
atomic_inc(&entry->request_sent);
|
||||
atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS);
|
||||
atomic_inc(&bat_priv->bla.num_requests);
|
||||
spin_lock_bh(&bat_priv->bla.num_requests_lock);
|
||||
if (entry->state == BATADV_BLA_BACKBONE_GW_SYNCED) {
|
||||
entry->state = BATADV_BLA_BACKBONE_GW_UNSYNCED;
|
||||
entry->wait_periods = BATADV_BLA_WAIT_PERIODS;
|
||||
atomic_inc(&bat_priv->bla.num_requests);
|
||||
}
|
||||
spin_unlock_bh(&bat_priv->bla.num_requests_lock);
|
||||
}
|
||||
|
||||
return entry;
|
||||
|
|
@ -649,10 +655,12 @@ static void batadv_bla_send_request(struct batadv_bla_backbone_gw *backbone_gw)
|
|||
backbone_gw->vid, BATADV_CLAIM_TYPE_REQUEST);
|
||||
|
||||
/* no local broadcasts should be sent or received, for now. */
|
||||
if (!atomic_read(&backbone_gw->request_sent)) {
|
||||
spin_lock_bh(&backbone_gw->bat_priv->bla.num_requests_lock);
|
||||
if (backbone_gw->state == BATADV_BLA_BACKBONE_GW_SYNCED) {
|
||||
backbone_gw->state = BATADV_BLA_BACKBONE_GW_UNSYNCED;
|
||||
atomic_inc(&backbone_gw->bat_priv->bla.num_requests);
|
||||
atomic_set(&backbone_gw->request_sent, 1);
|
||||
}
|
||||
spin_unlock_bh(&backbone_gw->bat_priv->bla.num_requests_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -873,10 +881,12 @@ static bool batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
|
|||
/* if we have sent a request and the crc was OK,
|
||||
* we can allow traffic again.
|
||||
*/
|
||||
if (atomic_read(&backbone_gw->request_sent)) {
|
||||
spin_lock_bh(&bat_priv->bla.num_requests_lock);
|
||||
if (backbone_gw->state == BATADV_BLA_BACKBONE_GW_UNSYNCED) {
|
||||
backbone_gw->state = BATADV_BLA_BACKBONE_GW_SYNCED;
|
||||
atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
|
||||
atomic_set(&backbone_gw->request_sent, 0);
|
||||
}
|
||||
spin_unlock_bh(&bat_priv->bla.num_requests_lock);
|
||||
}
|
||||
|
||||
batadv_backbone_gw_put(backbone_gw);
|
||||
|
|
@ -1224,6 +1234,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
|
|||
struct hlist_head *head;
|
||||
struct batadv_hashtable *hash;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
bool purged;
|
||||
int i;
|
||||
|
||||
hash = bat_priv->bla.backbone_hash;
|
||||
|
|
@ -1234,30 +1245,49 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
|
|||
head = &hash->table[i];
|
||||
list_lock = &hash->list_locks[i];
|
||||
|
||||
spin_lock_bh(list_lock);
|
||||
hlist_for_each_entry_safe(backbone_gw, node_tmp,
|
||||
head, hash_entry) {
|
||||
if (now)
|
||||
goto purge_now;
|
||||
if (!batadv_has_timed_out(backbone_gw->lasttime,
|
||||
BATADV_BLA_BACKBONE_TIMEOUT))
|
||||
continue;
|
||||
do {
|
||||
purged = false;
|
||||
|
||||
batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
|
||||
"%s(): backbone gw %pM timed out\n",
|
||||
__func__, backbone_gw->orig);
|
||||
spin_lock_bh(list_lock);
|
||||
hlist_for_each_entry_safe(backbone_gw, node_tmp,
|
||||
head, hash_entry) {
|
||||
if (now)
|
||||
goto purge_now;
|
||||
if (!batadv_has_timed_out(backbone_gw->lasttime,
|
||||
BATADV_BLA_BACKBONE_TIMEOUT))
|
||||
continue;
|
||||
|
||||
batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
|
||||
"%s(): backbone gw %pM timed out\n",
|
||||
__func__, backbone_gw->orig);
|
||||
|
||||
purge_now:
|
||||
/* don't wait for the pending request anymore */
|
||||
if (atomic_read(&backbone_gw->request_sent))
|
||||
atomic_dec(&bat_priv->bla.num_requests);
|
||||
purged = true;
|
||||
|
||||
batadv_bla_del_backbone_claims(backbone_gw);
|
||||
/* don't wait for the pending request anymore */
|
||||
spin_lock_bh(&bat_priv->bla.num_requests_lock);
|
||||
if (backbone_gw->state == BATADV_BLA_BACKBONE_GW_UNSYNCED)
|
||||
atomic_dec(&bat_priv->bla.num_requests);
|
||||
|
||||
hlist_del_rcu(&backbone_gw->hash_entry);
|
||||
batadv_backbone_gw_put(backbone_gw);
|
||||
}
|
||||
spin_unlock_bh(list_lock);
|
||||
backbone_gw->state = BATADV_BLA_BACKBONE_GW_STOPPED;
|
||||
spin_unlock_bh(&bat_priv->bla.num_requests_lock);
|
||||
|
||||
batadv_bla_del_backbone_claims(backbone_gw);
|
||||
|
||||
hlist_del_rcu(&backbone_gw->hash_entry);
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(list_lock);
|
||||
|
||||
if (purged) {
|
||||
/* reference for pending report_work */
|
||||
if (cancel_work_sync(&backbone_gw->report_work))
|
||||
batadv_backbone_gw_put(backbone_gw);
|
||||
|
||||
/* reference for hash_entry */
|
||||
batadv_backbone_gw_put(backbone_gw);
|
||||
}
|
||||
} while (purged);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1492,7 +1522,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)
|
|||
batadv_bla_send_loopdetect(bat_priv,
|
||||
backbone_gw);
|
||||
|
||||
/* request_sent is only set after creation to avoid
|
||||
/* state is only set to unsynced after creation to avoid
|
||||
* problems when we are not yet known as backbone gw
|
||||
* in the backbone.
|
||||
*
|
||||
|
|
@ -1501,14 +1531,21 @@ static void batadv_bla_periodic_work(struct work_struct *work)
|
|||
* some grace time.
|
||||
*/
|
||||
|
||||
if (atomic_read(&backbone_gw->request_sent) == 0)
|
||||
continue;
|
||||
spin_lock_bh(&bat_priv->bla.num_requests_lock);
|
||||
if (backbone_gw->state != BATADV_BLA_BACKBONE_GW_UNSYNCED)
|
||||
goto unlock_next;
|
||||
|
||||
if (!atomic_dec_and_test(&backbone_gw->wait_periods))
|
||||
continue;
|
||||
if (backbone_gw->wait_periods > 0)
|
||||
backbone_gw->wait_periods--;
|
||||
|
||||
if (backbone_gw->wait_periods > 0)
|
||||
goto unlock_next;
|
||||
|
||||
backbone_gw->state = BATADV_BLA_BACKBONE_GW_SYNCED;
|
||||
atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
|
||||
atomic_set(&backbone_gw->request_sent, 0);
|
||||
|
||||
unlock_next:
|
||||
spin_unlock_bh(&bat_priv->bla.num_requests_lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -305,10 +305,10 @@ batadv_frag_merge_packets(struct hlist_head *chain)
|
|||
}
|
||||
|
||||
/**
|
||||
* batadv_skb_is_frag() - check if newly merged skb is gain a unicast packet
|
||||
* batadv_skb_is_frag() - check if newly merged skb contains unicast fragment
|
||||
* @skb: newly merged skb
|
||||
*
|
||||
* Return: if newly skb is of type BATADV_UNICAST_FRAG
|
||||
* Return: if newly merged skb is of type BATADV_UNICAST_FRAG
|
||||
*/
|
||||
static bool batadv_skb_is_frag(struct sk_buff *skb)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -787,6 +787,7 @@ static int batadv_meshif_init_late(struct net_device *dev)
|
|||
atomic_set(&bat_priv->tt.ogm_append_cnt, 0);
|
||||
#ifdef CONFIG_BATMAN_ADV_BLA
|
||||
atomic_set(&bat_priv->bla.num_requests, 0);
|
||||
spin_lock_init(&bat_priv->bla.num_requests_lock);
|
||||
#endif
|
||||
atomic_set(&bat_priv->tp_num, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -835,8 +835,6 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
|
|||
|
||||
orig_node = container_of(rcu, struct batadv_orig_node, rcu);
|
||||
|
||||
batadv_mcast_purge_orig(orig_node);
|
||||
|
||||
batadv_frag_purge_orig(orig_node, NULL);
|
||||
|
||||
kfree(orig_node->tt_buff);
|
||||
|
|
@ -887,6 +885,8 @@ void batadv_orig_node_release(struct kref *ref)
|
|||
}
|
||||
spin_unlock_bh(&orig_node->vlan_list_lock);
|
||||
|
||||
batadv_mcast_purge_orig(orig_node);
|
||||
|
||||
call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ static void batadv_tp_batctl_error_notify(enum batadv_tp_meter_reason reason,
|
|||
* batadv_tp_list_find() - find a 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
|
||||
|
|
@ -262,7 +263,8 @@ static void batadv_tp_batctl_error_notify(enum batadv_tp_meter_reason reason,
|
|||
* 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)
|
||||
const u8 *dst,
|
||||
enum batadv_tp_meter_role role)
|
||||
{
|
||||
struct batadv_tp_vars *pos, *tp_vars = NULL;
|
||||
|
||||
|
|
@ -271,6 +273,9 @@ static struct batadv_tp_vars *batadv_tp_list_find(struct batadv_priv *bat_priv,
|
|||
if (!batadv_compare_eth(pos->other_end, dst))
|
||||
continue;
|
||||
|
||||
if (pos->role != role)
|
||||
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
|
||||
|
|
@ -286,12 +291,33 @@ static struct batadv_tp_vars *batadv_tp_list_find(struct batadv_priv *bat_priv,
|
|||
return tp_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tp_list_active() - check if session from/to destination is ongoing
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @dst: the other endpoint MAC address to look for
|
||||
*
|
||||
* Return: if matching session with @dst was found
|
||||
*/
|
||||
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;
|
||||
|
||||
hlist_for_each_entry_rcu(tp_vars, &bat_priv->tp_list, list) {
|
||||
if (batadv_compare_eth(tp_vars->other_end, dst))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tp_list_find_session() - find tp_vars 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
|
||||
|
|
@ -301,7 +327,7 @@ static struct batadv_tp_vars *batadv_tp_list_find(struct batadv_priv *bat_priv,
|
|||
*/
|
||||
static struct batadv_tp_vars *
|
||||
batadv_tp_list_find_session(struct batadv_priv *bat_priv, const u8 *dst,
|
||||
const u8 *session)
|
||||
const u8 *session, enum batadv_tp_meter_role role)
|
||||
{
|
||||
struct batadv_tp_vars *pos, *tp_vars = NULL;
|
||||
|
||||
|
|
@ -313,6 +339,9 @@ batadv_tp_list_find_session(struct batadv_priv *bat_priv, const u8 *dst,
|
|||
if (memcmp(pos->session, session, sizeof(pos->session)) != 0)
|
||||
continue;
|
||||
|
||||
if (pos->role != role)
|
||||
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
|
||||
|
|
@ -413,11 +442,14 @@ static void batadv_tp_sender_cleanup(struct batadv_tp_vars *tp_vars)
|
|||
static void batadv_tp_sender_end(struct batadv_priv *bat_priv,
|
||||
struct batadv_tp_vars *tp_vars)
|
||||
{
|
||||
enum batadv_tp_meter_reason reason;
|
||||
u32 session_cookie;
|
||||
|
||||
reason = atomic_read(&tp_vars->send_result);
|
||||
|
||||
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
|
||||
"Test towards %pM finished..shutting down (reason=%d)\n",
|
||||
tp_vars->other_end, tp_vars->reason);
|
||||
tp_vars->other_end, reason);
|
||||
|
||||
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
|
||||
"Last timing stats: SRTT=%ums RTTVAR=%ums RTO=%ums\n",
|
||||
|
|
@ -430,7 +462,7 @@ static void batadv_tp_sender_end(struct batadv_priv *bat_priv,
|
|||
session_cookie = batadv_tp_session_cookie(tp_vars->session,
|
||||
tp_vars->icmp_uid);
|
||||
|
||||
batadv_tp_batctl_notify(tp_vars->reason,
|
||||
batadv_tp_batctl_notify(reason,
|
||||
tp_vars->other_end,
|
||||
bat_priv,
|
||||
tp_vars->start_time,
|
||||
|
|
@ -446,10 +478,18 @@ static void batadv_tp_sender_end(struct batadv_priv *bat_priv,
|
|||
static void batadv_tp_sender_shutdown(struct batadv_tp_vars *tp_vars,
|
||||
enum batadv_tp_meter_reason reason)
|
||||
{
|
||||
if (atomic_xchg(&tp_vars->sending, 0) != 1)
|
||||
return;
|
||||
atomic_cmpxchg(&tp_vars->send_result, 0, reason);
|
||||
}
|
||||
|
||||
tp_vars->reason = reason;
|
||||
/**
|
||||
* batadv_tp_sender_stopped() - check if tp session was stopped with reason
|
||||
* @tp_vars: the private data of the current TP meter session
|
||||
*
|
||||
* Return: whether stop reason was found
|
||||
*/
|
||||
static bool batadv_tp_sender_stopped(struct batadv_tp_vars *tp_vars)
|
||||
{
|
||||
return atomic_read(&tp_vars->send_result) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -479,7 +519,7 @@ static void batadv_tp_reset_sender_timer(struct batadv_tp_vars *tp_vars)
|
|||
/* most of the time this function is invoked while normal packet
|
||||
* reception...
|
||||
*/
|
||||
if (unlikely(atomic_read(&tp_vars->sending) == 0))
|
||||
if (unlikely(batadv_tp_sender_stopped(tp_vars)))
|
||||
/* timer ref will be dropped in batadv_tp_sender_cleanup */
|
||||
return;
|
||||
|
||||
|
|
@ -499,7 +539,7 @@ 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;
|
||||
|
||||
if (atomic_read(&tp_vars->sending) == 0)
|
||||
if (batadv_tp_sender_stopped(tp_vars))
|
||||
return;
|
||||
|
||||
/* if the user waited long enough...shutdown the test */
|
||||
|
|
@ -654,14 +694,11 @@ static void batadv_tp_recv_ack(struct batadv_priv *bat_priv,
|
|||
|
||||
/* find the tp_vars */
|
||||
tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
|
||||
icmp->session);
|
||||
icmp->session, BATADV_TP_SENDER);
|
||||
if (unlikely(!tp_vars))
|
||||
return;
|
||||
|
||||
if (unlikely(tp_vars->role != BATADV_TP_SENDER))
|
||||
goto out;
|
||||
|
||||
if (unlikely(atomic_read(&tp_vars->sending) == 0))
|
||||
if (unlikely(batadv_tp_sender_stopped(tp_vars)))
|
||||
goto out;
|
||||
|
||||
/* old ACK? silently drop it.. */
|
||||
|
|
@ -827,21 +864,21 @@ static int batadv_tp_send(void *arg)
|
|||
|
||||
if (unlikely(tp_vars->role != BATADV_TP_SENDER)) {
|
||||
err = BATADV_TP_REASON_DST_UNREACHABLE;
|
||||
tp_vars->reason = err;
|
||||
batadv_tp_sender_shutdown(tp_vars, err);
|
||||
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;
|
||||
batadv_tp_sender_shutdown(tp_vars, 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;
|
||||
batadv_tp_sender_shutdown(tp_vars, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -860,7 +897,7 @@ static int batadv_tp_send(void *arg)
|
|||
queue_delayed_work(batadv_event_workqueue, &tp_vars->finish_work,
|
||||
msecs_to_jiffies(tp_vars->test_length));
|
||||
|
||||
while (atomic_read(&tp_vars->sending) != 0) {
|
||||
while (!batadv_tp_sender_stopped(tp_vars)) {
|
||||
if (unlikely(!batadv_tp_avail(tp_vars, payload_len))) {
|
||||
batadv_tp_wait_available(tp_vars, payload_len);
|
||||
continue;
|
||||
|
|
@ -883,8 +920,7 @@ static int batadv_tp_send(void *arg)
|
|||
"Meter: %s() cannot send packets (%d)\n",
|
||||
__func__, err);
|
||||
/* ensure nobody else tries to stop the thread now */
|
||||
if (atomic_xchg(&tp_vars->sending, 0) == 1)
|
||||
tp_vars->reason = err;
|
||||
batadv_tp_sender_shutdown(tp_vars, err);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -970,10 +1006,8 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
|
|||
return;
|
||||
}
|
||||
|
||||
tp_vars = batadv_tp_list_find(bat_priv, dst);
|
||||
if (tp_vars) {
|
||||
if (batadv_tp_list_active(bat_priv, dst)) {
|
||||
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,
|
||||
|
|
@ -1006,7 +1040,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;
|
||||
atomic_set(&tp_vars->sending, 1);
|
||||
atomic_set(&tp_vars->send_result, 0);
|
||||
memcpy(tp_vars->session, session_id, sizeof(session_id));
|
||||
tp_vars->icmp_uid = icmp_uid;
|
||||
|
||||
|
|
@ -1094,18 +1128,14 @@ void batadv_tp_stop(struct batadv_priv *bat_priv, const u8 *dst,
|
|||
if (!orig_node)
|
||||
return;
|
||||
|
||||
tp_vars = batadv_tp_list_find(bat_priv, orig_node->orig);
|
||||
tp_vars = batadv_tp_list_find(bat_priv, orig_node->orig, BATADV_TP_SENDER);
|
||||
if (!tp_vars) {
|
||||
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
|
||||
"Meter: trying to interrupt an already over connection\n");
|
||||
goto out_put_orig_node;
|
||||
}
|
||||
|
||||
if (unlikely(tp_vars->role != BATADV_TP_SENDER))
|
||||
goto out_put_tp_vars;
|
||||
|
||||
batadv_tp_sender_shutdown(tp_vars, return_value);
|
||||
out_put_tp_vars:
|
||||
batadv_tp_vars_put(tp_vars);
|
||||
out_put_orig_node:
|
||||
batadv_orig_node_put(orig_node);
|
||||
|
|
@ -1361,7 +1391,7 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv,
|
|||
goto out_unlock;
|
||||
|
||||
tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
|
||||
icmp->session);
|
||||
icmp->session, BATADV_TP_RECEIVER);
|
||||
if (tp_vars)
|
||||
goto out_unlock;
|
||||
|
||||
|
|
@ -1432,7 +1462,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv,
|
|||
}
|
||||
} else {
|
||||
tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
|
||||
icmp->session);
|
||||
icmp->session, BATADV_TP_RECEIVER);
|
||||
if (!tp_vars) {
|
||||
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
|
||||
"Unexpected packet from %pM!\n",
|
||||
|
|
@ -1441,13 +1471,6 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv,
|
|||
}
|
||||
}
|
||||
|
||||
if (unlikely(tp_vars->role != BATADV_TP_RECEIVER)) {
|
||||
batadv_dbg(BATADV_DBG_TP_METER, bat_priv,
|
||||
"Meter: dropping packet: not expected (role=%u)\n",
|
||||
tp_vars->role);
|
||||
goto out;
|
||||
}
|
||||
|
||||
tp_vars->last_recv_time = jiffies;
|
||||
|
||||
/* if the packet is a duplicate, it may be the case that an ACK has been
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@
|
|||
|
||||
#include <linux/byteorder/generic.h>
|
||||
#include <linux/container_of.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
|
@ -159,10 +161,10 @@ batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version)
|
|||
*
|
||||
* Return: size of all currently registered tvlv containers in bytes.
|
||||
*/
|
||||
static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
|
||||
static size_t batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_tvlv_container *tvlv;
|
||||
u16 tvlv_len = 0;
|
||||
size_t tvlv_len = 0;
|
||||
|
||||
lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
|
||||
|
||||
|
|
@ -306,26 +308,35 @@ static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff,
|
|||
* The ogm packet might be enlarged or shrunk depending on the current size
|
||||
* and the size of the to-be-appended tvlv containers.
|
||||
*
|
||||
* Return: size of all appended tvlv containers in bytes.
|
||||
* Return: size of all appended tvlv containers in bytes (max U16_MAX), negative
|
||||
* if operation failed
|
||||
*/
|
||||
u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
|
||||
int batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
|
||||
unsigned char **packet_buff,
|
||||
int *packet_buff_len, int packet_min_len)
|
||||
{
|
||||
struct batadv_tvlv_container *tvlv;
|
||||
struct batadv_tvlv_hdr *tvlv_hdr;
|
||||
u16 tvlv_value_len;
|
||||
size_t tvlv_value_len;
|
||||
void *tvlv_value;
|
||||
int tvlv_len_ret;
|
||||
bool ret;
|
||||
|
||||
spin_lock_bh(&bat_priv->tvlv.container_list_lock);
|
||||
tvlv_value_len = batadv_tvlv_container_list_size(bat_priv);
|
||||
if (tvlv_value_len > U16_MAX) {
|
||||
tvlv_len_ret = -E2BIG;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = batadv_tvlv_realloc_packet_buff(packet_buff, packet_buff_len,
|
||||
packet_min_len, tvlv_value_len);
|
||||
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
tvlv_len_ret = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
|
||||
tvlv_len_ret = tvlv_value_len;
|
||||
|
||||
if (!tvlv_value_len)
|
||||
goto end;
|
||||
|
|
@ -344,7 +355,8 @@ u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
|
|||
|
||||
end:
|
||||
spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
|
||||
return tvlv_value_len;
|
||||
|
||||
return tvlv_len_ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
|
||||
u8 type, u8 version,
|
||||
void *tvlv_value, u16 tvlv_value_len);
|
||||
u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
|
||||
int batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
|
||||
unsigned char **packet_buff,
|
||||
int *packet_buff_len, int packet_min_len);
|
||||
void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
|
||||
|
|
|
|||
|
|
@ -83,6 +83,9 @@ struct batadv_hard_iface_bat_iv {
|
|||
/** @ogm_seqno: OGM sequence number - used to identify each OGM */
|
||||
atomic_t ogm_seqno;
|
||||
|
||||
/** @reschedule_work: recover OGM schedule after schedule error */
|
||||
struct delayed_work reschedule_work;
|
||||
|
||||
/** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
|
||||
struct mutex ogm_buff_mutex;
|
||||
};
|
||||
|
|
@ -1023,6 +1026,12 @@ struct batadv_priv_bla {
|
|||
/** @num_requests: number of bla requests in flight */
|
||||
atomic_t num_requests;
|
||||
|
||||
/**
|
||||
* @num_requests_lock: locks update num_requests +
|
||||
* batadv_backbone_gw::state + batadv_backbone_gw::wait_periods update
|
||||
*/
|
||||
spinlock_t num_requests_lock;
|
||||
|
||||
/**
|
||||
* @claim_hash: hash table containing mesh nodes this host has claimed
|
||||
*/
|
||||
|
|
@ -1320,15 +1329,15 @@ struct batadv_tp_vars {
|
|||
/** @role: receiver/sender modi */
|
||||
enum batadv_tp_meter_role role;
|
||||
|
||||
/** @sending: sending binary semaphore: 1 if sending, 0 is not */
|
||||
atomic_t sending;
|
||||
/**
|
||||
* @send_result: 0 when sending is ongoing and otherwise
|
||||
* enum batadv_tp_meter_reason
|
||||
*/
|
||||
atomic_t send_result;
|
||||
|
||||
/** @receiving: receiving binary semaphore: 1 if receiving, 0 is not */
|
||||
atomic_t receiving;
|
||||
|
||||
/** @reason: reason for a stopped session */
|
||||
enum batadv_tp_meter_reason reason;
|
||||
|
||||
/** @finish_work: work item for the finishing procedure */
|
||||
struct delayed_work finish_work;
|
||||
|
||||
|
|
@ -1669,6 +1678,27 @@ struct batadv_priv {
|
|||
|
||||
#ifdef CONFIG_BATMAN_ADV_BLA
|
||||
|
||||
enum batadv_bla_backbone_gw_state {
|
||||
/**
|
||||
* @BATADV_BLA_BACKBONE_GW_STOPPED: backbone gw is being removed
|
||||
* and it must not longer work on requests
|
||||
*/
|
||||
BATADV_BLA_BACKBONE_GW_STOPPED,
|
||||
|
||||
/**
|
||||
* @BATADV_BLA_BACKBONE_GW_UNSYNCED: backbone was detected out
|
||||
* of sync and a request was send. No traffic is forwarded until the
|
||||
* situation is resolved
|
||||
*/
|
||||
BATADV_BLA_BACKBONE_GW_UNSYNCED,
|
||||
|
||||
/**
|
||||
* @BATADV_BLA_BACKBONE_GW_SYNCED: backbone is consider to be in
|
||||
* sync. traffic can be forwarded
|
||||
*/
|
||||
BATADV_BLA_BACKBONE_GW_SYNCED,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct batadv_bla_backbone_gw - batman-adv gateway bridged into the LAN
|
||||
*/
|
||||
|
|
@ -1694,16 +1724,12 @@ struct batadv_bla_backbone_gw {
|
|||
/**
|
||||
* @wait_periods: grace time for bridge forward delays and bla group
|
||||
* forming at bootup phase - no bcast traffic is formwared until it has
|
||||
* elapsed
|
||||
* elapsed. Must only be access with num_requests_lock.
|
||||
*/
|
||||
atomic_t wait_periods;
|
||||
u8 wait_periods;
|
||||
|
||||
/**
|
||||
* @request_sent: if this bool is set to true we are out of sync with
|
||||
* this backbone gateway - no bcast traffic is formwared until the
|
||||
* situation was resolved
|
||||
*/
|
||||
atomic_t request_sent;
|
||||
/** @state: sync state. Must only be access with num_requests_lock. */
|
||||
enum batadv_bla_backbone_gw_state state;
|
||||
|
||||
/** @crc: crc16 checksum over all claims */
|
||||
u16 crc;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user