17db7d9f3SSven Eckelmann // SPDX-License-Identifier: GPL-2.0
2*cfa55c6dSSven Eckelmann /* Copyright (C) B.A.T.M.A.N. contributors:
3c6c8fea2SSven Eckelmann *
4c6c8fea2SSven Eckelmann * Simon Wunderlich, Marek Lindner
5c6c8fea2SSven Eckelmann */
6c6c8fea2SSven Eckelmann
7c6c8fea2SSven Eckelmann #include "bitarray.h"
81e2c2a4fSSven Eckelmann #include "main.h"
9c6c8fea2SSven Eckelmann
101e2c2a4fSSven Eckelmann #include <linux/bitmap.h>
11c6c8fea2SSven Eckelmann
12ba412080SSven Eckelmann #include "log.h"
13ba412080SSven Eckelmann
14c6c8fea2SSven Eckelmann /* shift the packet array by n places. */
batadv_bitmap_shift_left(unsigned long * seq_bits,s32 n)156b5e971aSSven Eckelmann static void batadv_bitmap_shift_left(unsigned long *seq_bits, s32 n)
16c6c8fea2SSven Eckelmann {
1742d0b044SSven Eckelmann if (n <= 0 || n >= BATADV_TQ_LOCAL_WINDOW_SIZE)
18c6c8fea2SSven Eckelmann return;
19c6c8fea2SSven Eckelmann
2042d0b044SSven Eckelmann bitmap_shift_left(seq_bits, seq_bits, n, BATADV_TQ_LOCAL_WINDOW_SIZE);
21c6c8fea2SSven Eckelmann }
22c6c8fea2SSven Eckelmann
237afcbbefSSven Eckelmann /**
247e9a8c2cSSven Eckelmann * batadv_bit_get_packet() - receive and process one packet within the sequence
257afcbbefSSven Eckelmann * number window
267afcbbefSSven Eckelmann * @priv: the bat priv with all the soft interface information
277afcbbefSSven Eckelmann * @seq_bits: pointer to the sequence number receive packet
287afcbbefSSven Eckelmann * @seq_num_diff: difference between the current/received sequence number and
297afcbbefSSven Eckelmann * the last sequence number
307afcbbefSSven Eckelmann * @set_mark: whether this packet should be marked in seq_bits
31c6c8fea2SSven Eckelmann *
324b426b10SSven Eckelmann * Return: true if the window was moved (either new or very old),
334b426b10SSven Eckelmann * false if the window was not moved/shifted.
34c6c8fea2SSven Eckelmann */
batadv_bit_get_packet(void * priv,unsigned long * seq_bits,s32 seq_num_diff,int set_mark)354b426b10SSven Eckelmann bool batadv_bit_get_packet(void *priv, unsigned long *seq_bits,
364b426b10SSven Eckelmann s32 seq_num_diff, int set_mark)
37c6c8fea2SSven Eckelmann {
3856303d34SSven Eckelmann struct batadv_priv *bat_priv = priv;
39c6c8fea2SSven Eckelmann
40c6c8fea2SSven Eckelmann /* sequence number is slightly older. We already got a sequence number
419cfc7bd6SSven Eckelmann * higher than this one, so we just mark it.
429cfc7bd6SSven Eckelmann */
4342d0b044SSven Eckelmann if (seq_num_diff <= 0 && seq_num_diff > -BATADV_TQ_LOCAL_WINDOW_SIZE) {
44c6c8fea2SSven Eckelmann if (set_mark)
459b4a1159SSven Eckelmann batadv_set_bit(seq_bits, -seq_num_diff);
464b426b10SSven Eckelmann return false;
47c6c8fea2SSven Eckelmann }
48c6c8fea2SSven Eckelmann
49c6c8fea2SSven Eckelmann /* sequence number is slightly newer, so we shift the window and
509cfc7bd6SSven Eckelmann * set the mark if required
519cfc7bd6SSven Eckelmann */
5242d0b044SSven Eckelmann if (seq_num_diff > 0 && seq_num_diff < BATADV_TQ_LOCAL_WINDOW_SIZE) {
530f5f9322SSven Eckelmann batadv_bitmap_shift_left(seq_bits, seq_num_diff);
54c6c8fea2SSven Eckelmann
55c6c8fea2SSven Eckelmann if (set_mark)
569b4a1159SSven Eckelmann batadv_set_bit(seq_bits, 0);
574b426b10SSven Eckelmann return true;
58c6c8fea2SSven Eckelmann }
59c6c8fea2SSven Eckelmann
60c6c8fea2SSven Eckelmann /* sequence number is much newer, probably missed a lot of packets */
6142d0b044SSven Eckelmann if (seq_num_diff >= BATADV_TQ_LOCAL_WINDOW_SIZE &&
6242d0b044SSven Eckelmann seq_num_diff < BATADV_EXPECTED_SEQNO_RANGE) {
6339c75a51SSven Eckelmann batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
64c6c8fea2SSven Eckelmann "We missed a lot of packets (%i) !\n",
65c6c8fea2SSven Eckelmann seq_num_diff - 1);
6642d0b044SSven Eckelmann bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
67c6c8fea2SSven Eckelmann if (set_mark)
689b4a1159SSven Eckelmann batadv_set_bit(seq_bits, 0);
694b426b10SSven Eckelmann return true;
70c6c8fea2SSven Eckelmann }
71c6c8fea2SSven Eckelmann
72c6c8fea2SSven Eckelmann /* received a much older packet. The other host either restarted
73c6c8fea2SSven Eckelmann * or the old packet got delayed somewhere in the network. The
74c6c8fea2SSven Eckelmann * packet should be dropped without calling this function if the
759cfc7bd6SSven Eckelmann * seqno window is protected.
768e7c15d6SSven Eckelmann *
778e7c15d6SSven Eckelmann * seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE
788e7c15d6SSven Eckelmann * or
798e7c15d6SSven Eckelmann * seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE
809cfc7bd6SSven Eckelmann */
8139c75a51SSven Eckelmann batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
82c6c8fea2SSven Eckelmann "Other host probably restarted!\n");
83c6c8fea2SSven Eckelmann
8442d0b044SSven Eckelmann bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
85c6c8fea2SSven Eckelmann if (set_mark)
869b4a1159SSven Eckelmann batadv_set_bit(seq_bits, 0);
87c6c8fea2SSven Eckelmann
884b426b10SSven Eckelmann return true;
89c6c8fea2SSven Eckelmann }
90