Blame view

kernel/linux-imx6_3.14.28/net/batman-adv/bitarray.c 2.77 KB
6b13f685e   김민수   BSP 최초 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  /* Copyright (C) 2006-2014 B.A.T.M.A.N. contributors:
   *
   * Simon Wunderlich, Marek Lindner
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of version 2 of the GNU General Public
   * License as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, see <http://www.gnu.org/licenses/>.
   */
  
  #include "main.h"
  #include "bitarray.h"
  
  #include <linux/bitops.h>
  
  /* shift the packet array by n places. */
  static void batadv_bitmap_shift_left(unsigned long *seq_bits, int32_t n)
  {
  	if (n <= 0 || n >= BATADV_TQ_LOCAL_WINDOW_SIZE)
  		return;
  
  	bitmap_shift_left(seq_bits, seq_bits, n, BATADV_TQ_LOCAL_WINDOW_SIZE);
  }
  
  
  /* receive and process one packet within the sequence number window.
   *
   * returns:
   *  1 if the window was moved (either new or very old)
   *  0 if the window was not moved/shifted.
   */
  int batadv_bit_get_packet(void *priv, unsigned long *seq_bits,
  			  int32_t seq_num_diff, int set_mark)
  {
  	struct batadv_priv *bat_priv = priv;
  
  	/* sequence number is slightly older. We already got a sequence number
  	 * higher than this one, so we just mark it.
  	 */
  	if (seq_num_diff <= 0 && seq_num_diff > -BATADV_TQ_LOCAL_WINDOW_SIZE) {
  		if (set_mark)
  			batadv_set_bit(seq_bits, -seq_num_diff);
  		return 0;
  	}
  
  	/* sequence number is slightly newer, so we shift the window and
  	 * set the mark if required
  	 */
  	if (seq_num_diff > 0 && seq_num_diff < BATADV_TQ_LOCAL_WINDOW_SIZE) {
  		batadv_bitmap_shift_left(seq_bits, seq_num_diff);
  
  		if (set_mark)
  			batadv_set_bit(seq_bits, 0);
  		return 1;
  	}
  
  	/* sequence number is much newer, probably missed a lot of packets */
  	if (seq_num_diff >= BATADV_TQ_LOCAL_WINDOW_SIZE &&
  	    seq_num_diff < BATADV_EXPECTED_SEQNO_RANGE) {
  		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  			   "We missed a lot of packets (%i) !
  ",
  			   seq_num_diff - 1);
  		bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
  		if (set_mark)
  			batadv_set_bit(seq_bits, 0);
  		return 1;
  	}
  
  	/* received a much older packet. The other host either restarted
  	 * or the old packet got delayed somewhere in the network. The
  	 * packet should be dropped without calling this function if the
  	 * seqno window is protected.
  	 *
  	 * seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE
  	 * or
  	 * seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE
  	 */
  	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  		   "Other host probably restarted!
  ");
  
  	bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
  	if (set_mark)
  		batadv_set_bit(seq_bits, 0);
  
  	return 1;
  }