Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 197366
b: refs/heads/master
c: f94cee2
h: refs/heads/master
v: v3
  • Loading branch information
Simon Wunderlich authored and Greg Kroah-Hartman committed May 11, 2010
1 parent ae164ae commit 5a9b452
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 48 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b7bce588b3a6a058e00d9629c25cf170dede63fc
refs/heads/master: f94cee241099b31732460c255c6af24979ec778e
74 changes: 51 additions & 23 deletions trunk/drivers/staging/batman-adv/bitarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
int32_t word_offset, word_num;
int32_t i;

if (n <= 0)
if (n <= 0 || n >= TQ_LOCAL_WINDOW_SIZE)
return;

word_offset = n % WORD_BIT_SIZE;/* shift how much inside each word */
Expand Down Expand Up @@ -111,48 +111,76 @@ void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
seq_bits[i] = 0;
}

static void bit_reset_window(TYPE_OF_WORD *seq_bits)
{
int i;
for (i = 0; i < NUM_WORDS; i++)
seq_bits[i] = 0;
}


/* receive and process one packet, returns 1 if received seq_num is considered
* new, 0 if old */
/* 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.
*/
char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
int8_t set_mark)
{
int i;
/* sequence number is slightly older. We already got a sequence number
* higher than this one, so we just mark it. */

/* we already got a sequence number higher than this one, so we just
* mark it. this should wrap around the integer just fine */
if ((seq_num_diff < 0) && (seq_num_diff >= -TQ_LOCAL_WINDOW_SIZE)) {
if ((seq_num_diff <= 0) && (seq_num_diff > -TQ_LOCAL_WINDOW_SIZE)) {
if (set_mark)
bit_mark(seq_bits, -seq_num_diff);
return 0;
}

/* it seems we missed a lot of packets or the other host restarted */
if ((seq_num_diff > TQ_LOCAL_WINDOW_SIZE) ||
(seq_num_diff < -TQ_LOCAL_WINDOW_SIZE)) {
/* sequence number is slightly newer, so we shift the window and
* set the mark if required */

if (seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
bat_dbg(DBG_BATMAN,
"We missed a lot of packets (%i) !\n",
seq_num_diff-1);
if ((seq_num_diff > 0) && (seq_num_diff < TQ_LOCAL_WINDOW_SIZE)) {
bit_shift(seq_bits, seq_num_diff);

if (-seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
bat_dbg(DBG_BATMAN,
"Other host probably restarted !\n");
if (set_mark)
bit_mark(seq_bits, 0);
return 1;
}

for (i = 0; i < NUM_WORDS; i++)
seq_bits[i] = 0;
/* sequence number is much newer, probably missed a lot of packets */

if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff < EXPECTED_SEQNO_RANGE)) {
bat_dbg(DBG_BATMAN,
"We missed a lot of packets (%i) !\n",
seq_num_diff - 1);
bit_reset_window(seq_bits);
if (set_mark)
seq_bits[0] = 1; /* we only have the latest packet */
} else {
bit_shift(seq_bits, seq_num_diff);
bit_mark(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. */

if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {

bat_dbg(DBG_BATMAN,
"Other host probably restarted!\n");

bit_reset_window(seq_bits);
if (set_mark)
bit_mark(seq_bits, 0);

return 1;
}

return 1;
/* never reached */
return 0;
}

/* count the hamming weight, how many good packets did we receive? just count
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/staging/batman-adv/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
* forw_packet->direct_link_flags */
#define MAX_AGGREGATION_MS 100

#define RESET_PROTECTION_MS 30000
#define EXPECTED_SEQNO_RANGE 4096
/* don't reset again within 30 seconds */

#define MODULE_INACTIVE 0
#define MODULE_ACTIVE 1
#define MODULE_DEACTIVATING 2
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/staging/batman-adv/originator.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ struct orig_node *get_orig_node(uint8_t *addr)
memcpy(orig_node->orig, addr, ETH_ALEN);
orig_node->router = NULL;
orig_node->hna_buff = NULL;
orig_node->bcast_seqno_reset = jiffies - msecs_to_jiffies(RESET_PROTECTION_MS) - 1;
orig_node->batman_seqno_reset = jiffies - msecs_to_jiffies(RESET_PROTECTION_MS) - 1;

size = bat_priv->num_ifaces * sizeof(TYPE_OF_WORD) * NUM_WORDS;

Expand Down
99 changes: 75 additions & 24 deletions trunk/drivers/staging/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,38 +304,80 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
update_routes(orig_node, orig_node->router, hna_buff, tmp_hna_buff_len);
}

/* checks whether the host restarted and is in the protection time.
* returns:
* 0 if the packet is to be accepted
* 1 if the packet is to be ignored.
*/
static int window_protected(int16_t seq_num_diff,
unsigned long *last_reset)
{
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
if (time_after(jiffies, *last_reset +
msecs_to_jiffies(RESET_PROTECTION_MS))) {

*last_reset = jiffies;
bat_dbg(DBG_BATMAN,
"old packet received, start protection\n");

return 0;
} else
return 1;
}
return 0;
}

/* processes a batman packet for all interfaces, adjusts the sequence number and
* finds out whether it is a duplicate.
* returns:
* 1 the packet is a duplicate
* 0 the packet has not yet been received
* -1 the packet is old and has been received while the seqno window
* was protected. Caller should drop it.
*/
static char count_real_packets(struct ethhdr *ethhdr,
struct batman_packet *batman_packet,
struct batman_if *if_incoming)
{
struct orig_node *orig_node;
struct neigh_node *tmp_neigh_node;
char is_duplicate = 0;
uint16_t seq_diff;
int16_t seq_diff;
int need_update = 0;
int set_mark;

orig_node = get_orig_node(batman_packet->orig);
if (orig_node == NULL)
return 0;

seq_diff = batman_packet->seqno - orig_node->last_real_seqno;

/* signalize caller that the packet is to be dropped. */
if (window_protected(seq_diff, &orig_node->batman_seqno_reset))
return -1;

list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {

if (!is_duplicate)
is_duplicate =
get_bit_status(tmp_neigh_node->real_bits,
is_duplicate |= get_bit_status(tmp_neigh_node->real_bits,
orig_node->last_real_seqno,
batman_packet->seqno);
seq_diff = batman_packet->seqno - orig_node->last_real_seqno;

if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
(tmp_neigh_node->if_incoming == if_incoming))
bit_get_packet(tmp_neigh_node->real_bits, seq_diff, 1);
set_mark = 1;
else
bit_get_packet(tmp_neigh_node->real_bits, seq_diff, 0);
set_mark = 0;

/* if the window moved, set the update flag. */
need_update |= bit_get_packet(tmp_neigh_node->real_bits,
seq_diff, set_mark);

tmp_neigh_node->real_packet_count =
bit_packet_count(tmp_neigh_node->real_bits);
}

if (!is_duplicate) {
if (need_update) {
bat_dbg(DBG_BATMAN, "updating last_seqno: old %d, new %d\n",
orig_node->last_real_seqno, batman_packet->seqno);
orig_node->last_real_seqno = batman_packet->seqno;
Expand Down Expand Up @@ -453,24 +495,27 @@ void receive_bat_packet(struct ethhdr *ethhdr,
return;
}

if (batman_packet->tq == 0) {
count_real_packets(ethhdr, batman_packet, if_incoming);

bat_dbg(DBG_BATMAN, "Drop packet: originator packet with tq equal 0\n");
return;
}

if (is_my_oldorig) {
bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %pM)\n", ethhdr->h_source);
return;
}

is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);

orig_node = get_orig_node(batman_packet->orig);
if (orig_node == NULL)
return;

is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);

if (is_duplicate == -1) {
bat_dbg(DBG_BATMAN, "Drop packet: packet within seqno protection time (sender: %pM)\n", ethhdr->h_source);
return;
}

if (batman_packet->tq == 0) {
bat_dbg(DBG_BATMAN, "Drop packet: originator packet with tq equal 0\n");
return;
}

/* avoid temporary routing loops */
if ((orig_node->router) &&
(orig_node->router->orig_node->router) &&
Expand Down Expand Up @@ -866,13 +911,13 @@ int recv_unicast_packet(struct sk_buff *skb)
return ret;
}


int recv_bcast_packet(struct sk_buff *skb)
{
struct orig_node *orig_node;
struct bcast_packet *bcast_packet;
struct ethhdr *ethhdr;
int hdr_size = sizeof(struct bcast_packet);
int16_t seq_diff;
unsigned long flags;

/* drop packet if it has not necessary minimum size */
Expand Down Expand Up @@ -908,22 +953,28 @@ int recv_bcast_packet(struct sk_buff *skb)
return NET_RX_DROP;
}

/* check flood history */
/* check whether the packet is a duplicate */
if (get_bit_status(orig_node->bcast_bits,
orig_node->last_bcast_seqno,
ntohs(bcast_packet->seqno))) {
spin_unlock_irqrestore(&orig_hash_lock, flags);
return NET_RX_DROP;
}

/* mark broadcast in flood history */
if (bit_get_packet(orig_node->bcast_bits,
ntohs(bcast_packet->seqno) -
orig_node->last_bcast_seqno, 1))
seq_diff = ntohs(bcast_packet->seqno) - orig_node->last_bcast_seqno;

/* check whether the packet is old and the host just restarted. */
if (window_protected(seq_diff, &orig_node->bcast_seqno_reset)) {
spin_unlock_irqrestore(&orig_hash_lock, flags);
return NET_RX_DROP;
}

/* mark broadcast in flood history, update window position
* if required. */
if (bit_get_packet(orig_node->bcast_bits, seq_diff, 1))
orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno);

spin_unlock_irqrestore(&orig_hash_lock, flags);

/* rebroadcast packet */
add_bcast_packet_to_list(skb);

Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/staging/batman-adv/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ struct orig_node { /* structure for orig_list maintaining nodes of
uint8_t tq_own;
int tq_asym_penalty;
unsigned long last_valid; /* when last packet from this node was received */
unsigned long bcast_seqno_reset; /* time when the broadcast
seqno window was reset. */
unsigned long batman_seqno_reset;/* time when the batman seqno
window was reset. */
/* uint8_t gwflags; * flags related to gateway functions: gateway class */
uint8_t flags; /* for now only VIS_SERVER flag. */
unsigned char *hna_buff;
Expand Down

0 comments on commit 5a9b452

Please sign in to comment.