FAILED: patch "[PATCH] batman-adv: iv: recover OGM scheduling after forward packet" failed to apply to 6.6-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x aa3153bd139a6c48667dcd02608d3b2c80bff02c
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026052854-encode-overfeed-1870@gregkh' --subject-prefix 'PATCH 6.6.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From aa3153bd139a6c48667dcd02608d3b2c80bff02c Mon Sep 17 00:00:00 2001
From: Sven Eckelmann <[email protected]>
Date: Fri, 15 May 2026 22:00:40 +0200
Subject: [PATCH] batman-adv: iv: recover OGM scheduling after forward packet
error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When batadv_iv_ogm_schedule_buff() fails to allocate and queue a forward packet for OGM transmission, the work item that drives periodic OGM scheduling is never re-armed. This silently halts transmission of the node's own OGMs on the affected interface — only OGMs from other peers continue to be aggregated and forwarded.
Fix this by tracking whether batadv_iv_ogm_queue_add() (and transitively batadv_iv_ogm_aggregate_new()) successfully scheduled a forward packet. When scheduling fails, batadv_iv_ogm_schedule_buff() falls back to queuing a dedicated recovery work item (reschedule_work) that fires after one originator interval and calls batadv_iv_ogm_schedule() again.
net/batman-adv/bat_iv_ogm.c +57 -19
@@ -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,8 @@ 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);
@@ -818,11 +830,8 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface) ogm_buff_len, BATADV_OGM_HLEN);if (ret <0 ) { -/* OGMs must be queued even when the buffer allocation for -* TVLVs failed. just fall back to the non-TVLV version -*/ - ret =0 ; - *ogm_buff_len =BATADV_OGM_HLEN ; + reschedule = true; + goto out; } tvlv_len = ret;
@@ -844,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; }
@@ -857,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); }
@@ -880,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
@@ -2272,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); }
net/batman-adv/types.h +3 -0
@@ -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; };
Sven Eckelmann
maintainerPATCH 1/1 batman-adv: iv: recover OGM scheduling after forward packet error
commit aa3153bd139a6c48667dcd02608d3b2c80bff02c upstream.
When batadv_iv_ogm_schedule_buff() fails to allocate and queue a forward packet for OGM transmission, the work item that drives periodic OGM scheduling is never re-armed. This silently halts transmission of the node's own OGMs on the affected interface — only OGMs from other peers continue to be aggregated and forwarded.
Fix this by tracking whether batadv_iv_ogm_queue_add() (and transitively batadv_iv_ogm_aggregate_new()) successfully scheduled a forward packet. When scheduling fails, batadv_iv_ogm_schedule_buff() falls back to queuing a dedicated recovery work item (reschedule_work) that fires after one originator interval and calls batadv_iv_ogm_schedule() again.
--- net/batman-adv/bat_iv_ogm.c | 76 +++++++++++++++++++++++++++---------- net/batman-adv/types.h | 3 ++ 2 files changed, 60 insertions(+), 19 deletions(-)
net/batman-adv/bat_iv_ogm.c +57 -19
@@ -223,6 +223,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)
@@ -527,8 +529,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,
@@ -552,13 +556,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 ;
@@ -580,6 +584,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 */
@@ -609,8 +615,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,
@@ -662,14 +670,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; } }
@@ -781,6 +791,8 @@ 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);
@@ -809,11 +821,8 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface) ogm_buff_len, BATADV_OGM_HLEN);if (ret <0 ) { -/* OGMs must be queued even when the buffer allocation for -* TVLVs failed. just fall back to the non-TVLV version -*/ - ret =0 ; - *ogm_buff_len =BATADV_OGM_HLEN ; + reschedule = true; + goto out; } tvlv_len = ret;
@@ -835,8 +844,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; }
@@ -851,15 +863,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); }
@@ -874,6 +899,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
@@ -2277,6 +2313,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); }
net/batman-adv/types.h +3 -0
@@ -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; };
Signature · 1 line
2.47.3