18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (C) 2006-2020 B.A.T.M.A.N. contributors: 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Simon Wunderlich, Marek Lindner 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include "bitarray.h" 88c2ecf20Sopenharmony_ci#include "main.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "log.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* shift the packet array by n places. */ 158c2ecf20Sopenharmony_cistatic void batadv_bitmap_shift_left(unsigned long *seq_bits, s32 n) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci if (n <= 0 || n >= BATADV_TQ_LOCAL_WINDOW_SIZE) 188c2ecf20Sopenharmony_ci return; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci bitmap_shift_left(seq_bits, seq_bits, n, BATADV_TQ_LOCAL_WINDOW_SIZE); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/** 248c2ecf20Sopenharmony_ci * batadv_bit_get_packet() - receive and process one packet within the sequence 258c2ecf20Sopenharmony_ci * number window 268c2ecf20Sopenharmony_ci * @priv: the bat priv with all the soft interface information 278c2ecf20Sopenharmony_ci * @seq_bits: pointer to the sequence number receive packet 288c2ecf20Sopenharmony_ci * @seq_num_diff: difference between the current/received sequence number and 298c2ecf20Sopenharmony_ci * the last sequence number 308c2ecf20Sopenharmony_ci * @set_mark: whether this packet should be marked in seq_bits 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * Return: true if the window was moved (either new or very old), 338c2ecf20Sopenharmony_ci * false if the window was not moved/shifted. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_cibool batadv_bit_get_packet(void *priv, unsigned long *seq_bits, 368c2ecf20Sopenharmony_ci s32 seq_num_diff, int set_mark) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci struct batadv_priv *bat_priv = priv; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* sequence number is slightly older. We already got a sequence number 418c2ecf20Sopenharmony_ci * higher than this one, so we just mark it. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci if (seq_num_diff <= 0 && seq_num_diff > -BATADV_TQ_LOCAL_WINDOW_SIZE) { 448c2ecf20Sopenharmony_ci if (set_mark) 458c2ecf20Sopenharmony_ci batadv_set_bit(seq_bits, -seq_num_diff); 468c2ecf20Sopenharmony_ci return false; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci /* sequence number is slightly newer, so we shift the window and 508c2ecf20Sopenharmony_ci * set the mark if required 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci if (seq_num_diff > 0 && seq_num_diff < BATADV_TQ_LOCAL_WINDOW_SIZE) { 538c2ecf20Sopenharmony_ci batadv_bitmap_shift_left(seq_bits, seq_num_diff); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (set_mark) 568c2ecf20Sopenharmony_ci batadv_set_bit(seq_bits, 0); 578c2ecf20Sopenharmony_ci return true; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* sequence number is much newer, probably missed a lot of packets */ 618c2ecf20Sopenharmony_ci if (seq_num_diff >= BATADV_TQ_LOCAL_WINDOW_SIZE && 628c2ecf20Sopenharmony_ci seq_num_diff < BATADV_EXPECTED_SEQNO_RANGE) { 638c2ecf20Sopenharmony_ci batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 648c2ecf20Sopenharmony_ci "We missed a lot of packets (%i) !\n", 658c2ecf20Sopenharmony_ci seq_num_diff - 1); 668c2ecf20Sopenharmony_ci bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); 678c2ecf20Sopenharmony_ci if (set_mark) 688c2ecf20Sopenharmony_ci batadv_set_bit(seq_bits, 0); 698c2ecf20Sopenharmony_ci return true; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* received a much older packet. The other host either restarted 738c2ecf20Sopenharmony_ci * or the old packet got delayed somewhere in the network. The 748c2ecf20Sopenharmony_ci * packet should be dropped without calling this function if the 758c2ecf20Sopenharmony_ci * seqno window is protected. 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE 788c2ecf20Sopenharmony_ci * or 798c2ecf20Sopenharmony_ci * seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 828c2ecf20Sopenharmony_ci "Other host probably restarted!\n"); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); 858c2ecf20Sopenharmony_ci if (set_mark) 868c2ecf20Sopenharmony_ci batadv_set_bit(seq_bits, 0); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci return true; 898c2ecf20Sopenharmony_ci} 90