2
* Copyright (C) 2006 B.A.T.M.A.N. contributors:
3
* Simon Wunderlich, Axel Neumann, Marek Lindner
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of version 2 of the GNU General Public
6
* License as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program; if not, write to the Free Software
15
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
#include <stdio.h> /* printf() */
30
void bit_init( TYPE_OF_WORD *seq_bits ) {
34
for (i=0; i< NUM_WORDS; i++)
39
/* returns true if corresponding bit in given seq_bits indicates so and curr_seqno is within range of last_seqno */
40
uint8_t get_bit_status( TYPE_OF_WORD *seq_bits, uint16_t last_seqno, uint16_t curr_seqno ) {
42
int16_t diff, word_offset, word_num;
44
diff= last_seqno- curr_seqno;
45
if ( diff < 0 || diff >= SEQ_RANGE ) {
50
word_offset= ( last_seqno - curr_seqno ) % WORD_BIT_SIZE; /* which position in the selected word */
51
word_num = ( last_seqno - curr_seqno ) / WORD_BIT_SIZE; /* which word */
53
if ( seq_bits[word_num] & (1<<word_offset) ) /* get position status */
62
/* print the packet array, for debugging purposes */
63
static char bit_string[130];
64
char* bit_print( TYPE_OF_WORD *seq_bits ) {
67
// printf("the last %d packets, we got %d:\n", SEQ_RANGE, bit_packet_count(seq_bits));
68
for ( i=0; i<NUM_WORDS; i++ ) {
69
for ( j=0; j<WORD_BIT_SIZE; j++) {
70
bit_string[k++] = ((seq_bits[i]>>j)%2 ? '1':'0'); /* print the j position */
71
if( ++b == SEQ_RANGE ) {
78
// debug_output( 4, "%s\n", bit_string);
83
/* turn corresponding bit on, so we can remember that we got the packet */
84
void bit_mark( TYPE_OF_WORD *seq_bits, int32_t n ) {
85
int32_t word_offset,word_num;
87
if ( n<0 || n >= SEQ_RANGE ) { /* if too old, just drop it */
88
// printf("got old packet, dropping\n");
92
// printf("mark bit %d\n", n);
94
word_offset= n%WORD_BIT_SIZE; /* which position in the selected word */
95
word_num = n/WORD_BIT_SIZE; /* which word */
97
seq_bits[word_num]|= 1<<word_offset; /* turn the position on */
100
/* shift the packet array p by n places. */
101
void bit_shift( TYPE_OF_WORD *seq_bits, int32_t n ) {
102
int32_t word_offset, word_num;
105
// bit_print( seq_bits );
108
word_offset= n%WORD_BIT_SIZE; /* shift how much inside each word */
109
word_num = n/WORD_BIT_SIZE; /* shift over how much (full) words */
111
for ( i=NUM_WORDS-1; i>word_num; i-- ) {
112
/* going from old to new, so we can't overwrite the data we copy from. *
113
* left is high, right is low: FEDC BA98 7654 3210
116
* ^^^^ = from, vvvvv =to, we'd have word_num==1 and
117
* word_offset==WORD_BIT_SIZE/2 ????? in this example. (=24 bits)
119
* our desired output would be: 9876 5432 1000 0000
123
(seq_bits[i - word_num] << word_offset) +
124
/* take the lower port from the left half, shift it left to its final position */
125
(seq_bits[i - word_num - 1] >> (WORD_BIT_SIZE-word_offset));
126
/* and the upper part of the right half and shift it left to it's position */
127
/* for our example that would be: word[0] = 9800 + 0076 = 9876 */
129
/* now for our last word, i==word_num, we only have the it's "left" half. that's the 1000 word in
132
seq_bits[i]= (seq_bits[i - word_num] << word_offset);
134
/* pad the rest with 0, if there is anything */
140
// bit_print( seq_bits );
144
/* receive and process one packet, returns 1 if received seq_num is considered new, 0 if old */
145
char bit_get_packet( TYPE_OF_WORD *seq_bits, int16_t seq_num_diff, int8_t set_mark ) {
149
if ( ( seq_num_diff < 0 ) && ( seq_num_diff >= -SEQ_RANGE ) ) { /* we already got a sequence number higher than this one, so we just mark it. this should wrap around the integer just fine */
152
bit_mark( seq_bits, -seq_num_diff );
158
if ( ( seq_num_diff > SEQ_RANGE ) || ( seq_num_diff < -SEQ_RANGE ) ) { /* it seems we missed a lot of packets or the other host restarted */
160
if ( seq_num_diff > SEQ_RANGE )
161
debug_output( 4, "It seems we missed a lot of packets (%i) !\n", seq_num_diff-1 );
163
if ( -seq_num_diff > SEQ_RANGE )
164
debug_output( 4, "Other host probably restarted !\n" );
166
for (i=0; i<NUM_WORDS; i++)
170
seq_bits[0] = 1; /* we only have the latest packet */
174
bit_shift(seq_bits, seq_num_diff);
177
bit_mark(seq_bits, 0);
185
/* count the hamming weight, how many good packets did we receive? just count the 1's ... */
186
int bit_packet_count( TYPE_OF_WORD *seq_bits ) {
191
for (i=0; i<NUM_WORDS; i++) {
197
word &= word-1; /* see http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan */