|
@@ -304,6 +304,38 @@ update_hna:
|
|
|
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)
|
|
@@ -311,31 +343,41 @@ static char count_real_packets(struct ethhdr *ethhdr,
|
|
|
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;
|
|
@@ -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) &&
|
|
@@ -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 */
|
|
@@ -908,7 +953,7 @@ 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))) {
|
|
@@ -916,14 +961,20 @@ int recv_bcast_packet(struct sk_buff *skb)
|
|
|
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);
|
|
|
|