162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (C) B.A.T.M.A.N. contributors: 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Simon Wunderlich, Marek Lindner 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include "bitarray.h" 862306a36Sopenharmony_ci#include "main.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/bitmap.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "log.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* shift the packet array by n places. */ 1562306a36Sopenharmony_cistatic void batadv_bitmap_shift_left(unsigned long *seq_bits, s32 n) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci if (n <= 0 || n >= BATADV_TQ_LOCAL_WINDOW_SIZE) 1862306a36Sopenharmony_ci return; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci bitmap_shift_left(seq_bits, seq_bits, n, BATADV_TQ_LOCAL_WINDOW_SIZE); 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/** 2462306a36Sopenharmony_ci * batadv_bit_get_packet() - receive and process one packet within the sequence 2562306a36Sopenharmony_ci * number window 2662306a36Sopenharmony_ci * @priv: the bat priv with all the soft interface information 2762306a36Sopenharmony_ci * @seq_bits: pointer to the sequence number receive packet 2862306a36Sopenharmony_ci * @seq_num_diff: difference between the current/received sequence number and 2962306a36Sopenharmony_ci * the last sequence number 3062306a36Sopenharmony_ci * @set_mark: whether this packet should be marked in seq_bits 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * Return: true if the window was moved (either new or very old), 3362306a36Sopenharmony_ci * false if the window was not moved/shifted. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_cibool batadv_bit_get_packet(void *priv, unsigned long *seq_bits, 3662306a36Sopenharmony_ci s32 seq_num_diff, int set_mark) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci struct batadv_priv *bat_priv = priv; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* sequence number is slightly older. We already got a sequence number 4162306a36Sopenharmony_ci * higher than this one, so we just mark it. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci if (seq_num_diff <= 0 && seq_num_diff > -BATADV_TQ_LOCAL_WINDOW_SIZE) { 4462306a36Sopenharmony_ci if (set_mark) 4562306a36Sopenharmony_ci batadv_set_bit(seq_bits, -seq_num_diff); 4662306a36Sopenharmony_ci return false; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci /* sequence number is slightly newer, so we shift the window and 5062306a36Sopenharmony_ci * set the mark if required 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_ci if (seq_num_diff > 0 && seq_num_diff < BATADV_TQ_LOCAL_WINDOW_SIZE) { 5362306a36Sopenharmony_ci batadv_bitmap_shift_left(seq_bits, seq_num_diff); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci if (set_mark) 5662306a36Sopenharmony_ci batadv_set_bit(seq_bits, 0); 5762306a36Sopenharmony_ci return true; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci /* sequence number is much newer, probably missed a lot of packets */ 6162306a36Sopenharmony_ci if (seq_num_diff >= BATADV_TQ_LOCAL_WINDOW_SIZE && 6262306a36Sopenharmony_ci seq_num_diff < BATADV_EXPECTED_SEQNO_RANGE) { 6362306a36Sopenharmony_ci batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 6462306a36Sopenharmony_ci "We missed a lot of packets (%i) !\n", 6562306a36Sopenharmony_ci seq_num_diff - 1); 6662306a36Sopenharmony_ci bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); 6762306a36Sopenharmony_ci if (set_mark) 6862306a36Sopenharmony_ci batadv_set_bit(seq_bits, 0); 6962306a36Sopenharmony_ci return true; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* received a much older packet. The other host either restarted 7362306a36Sopenharmony_ci * or the old packet got delayed somewhere in the network. The 7462306a36Sopenharmony_ci * packet should be dropped without calling this function if the 7562306a36Sopenharmony_ci * seqno window is protected. 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE 7862306a36Sopenharmony_ci * or 7962306a36Sopenharmony_ci * seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 8262306a36Sopenharmony_ci "Other host probably restarted!\n"); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); 8562306a36Sopenharmony_ci if (set_mark) 8662306a36Sopenharmony_ci batadv_set_bit(seq_bits, 0); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci return true; 8962306a36Sopenharmony_ci} 90