Skip to content

Commit 1ae7e76

Browse files
ecsvgregkh
authored andcommitted
batman-adv: Fix out-of-order fragmentation support
[ Upstream commit d912426 ] batadv_frag_insert_packet was unable to handle out-of-order packets because it dropped them directly. This is caused by the way the fragmentation lists is checked for the correct place to insert a fragmentation entry. The fragmentation code keeps the fragments in lists. The fragmentation entries are kept in descending order of sequence number. The list is traversed and each entry is compared with the new fragment. If the current entry has a smaller sequence number than the new fragment then the new one has to be inserted before the current entry. This ensures that the list is still in descending order. An out-of-order packet with a smaller sequence number than all entries in the list still has to be added to the end of the list. The used hlist has no information about the last entry in the list inside hlist_head and thus the last entry has to be calculated differently. Currently the code assumes that the iterator variable of hlist_for_each_entry can be used for this purpose after the hlist_for_each_entry finished. This is obviously wrong because the iterator variable is always NULL when the list was completely traversed. Instead the information about the last entry has to be stored in a different variable. This problem was introduced in 610bfc6 ("batman-adv: Receive fragmented packets and merge"). Signed-off-by: Sven Eckelmann <[email protected]> Signed-off-by: Marek Lindner <[email protected]> Signed-off-by: Antonio Quartulli <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent b79cc87 commit 1ae7e76

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

net/batman-adv/fragmentation.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
128128
{
129129
struct batadv_frag_table_entry *chain;
130130
struct batadv_frag_list_entry *frag_entry_new = NULL, *frag_entry_curr;
131+
struct batadv_frag_list_entry *frag_entry_last = NULL;
131132
struct batadv_frag_packet *frag_packet;
132133
uint8_t bucket;
133134
uint16_t seqno, hdr_size = sizeof(struct batadv_frag_packet);
@@ -180,11 +181,14 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
180181
ret = true;
181182
goto out;
182183
}
184+
185+
/* store current entry because it could be the last in list */
186+
frag_entry_last = frag_entry_curr;
183187
}
184188

185-
/* Reached the end of the list, so insert after 'frag_entry_curr'. */
186-
if (likely(frag_entry_curr)) {
187-
hlist_add_after(&frag_entry_curr->list, &frag_entry_new->list);
189+
/* Reached the end of the list, so insert after 'frag_entry_last'. */
190+
if (likely(frag_entry_last)) {
191+
hlist_add_after(&frag_entry_last->list, &frag_entry_new->list);
188192
chain->size += skb->len - hdr_size;
189193
chain->timestamp = jiffies;
190194
ret = true;

0 commit comments

Comments
 (0)