Merge branch 'master' of github.com:openwrt-routing/packages
[feed/routing.git] / batman-adv / patches / 0010-batman-adv-forward-late-OGMs-from-best-next-hop.patch
1 From 3d999e5116f44b47c742aa16d6382721c360a6d0 Mon Sep 17 00:00:00 2001
2 From: Simon Wunderlich <simon@open-mesh.com>
3 Date: Thu, 23 May 2013 13:07:42 +0200
4 Subject: [PATCH 10/10] batman-adv: forward late OGMs from best next hop
5
6 When a packet is received from another node first and later from the
7 best next hop, this packet is dropped. However the first OGM was sent
8 with the BATADV_NOT_BEST_NEXT_HOP flag and thus dropped by neighbors.
9 The late OGM from the best neighbor is then dropped because it is a
10 duplicate.
11
12 If this situation happens constantly, a node might end up not forwarding
13 the "valid" OGMs anymore, and nodes behind will starve from not getting
14 valid OGMs.
15
16 Fix this by refining the duplicate checking behaviour: The actions
17 should depend on whether it was a duplicate for a neighbor only or for
18 the originator. OGMs which are not duplicates for a specific neighbor
19 will now be considered in batadv_iv_ogm_forward(), but only actually
20 forwarded for the best next hop. Therefore, late OGMs from the best
21 next hop are forwarded now and not dropped as duplicates anymore.
22
23 Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
24 Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
25 ---
26 bat_iv_ogm.c | 86 +++++++++++++++++++++++++++++++++++++---------------------
27 1 file changed, 55 insertions(+), 31 deletions(-)
28
29 diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c
30 index 071f288..f680ee1 100644
31 --- a/bat_iv_ogm.c
32 +++ b/bat_iv_ogm.c
33 @@ -29,6 +29,21 @@
34 #include "bat_algo.h"
35 #include "network-coding.h"
36
37 +/**
38 + * batadv_dup_status - duplicate status
39 + * @BATADV_NO_DUP: the packet is a duplicate
40 + * @BATADV_ORIG_DUP: OGM is a duplicate in the originator (but not for the
41 + * neighbor)
42 + * @BATADV_NEIGH_DUP: OGM is a duplicate for the neighbor
43 + * @BATADV_PROTECTED: originator is currently protected (after reboot)
44 + */
45 +enum batadv_dup_status {
46 + BATADV_NO_DUP = 0,
47 + BATADV_ORIG_DUP,
48 + BATADV_NEIGH_DUP,
49 + BATADV_PROTECTED,
50 +};
51 +
52 static struct batadv_neigh_node *
53 batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
54 const uint8_t *neigh_addr,
55 @@ -650,7 +665,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
56 const struct batadv_ogm_packet *batadv_ogm_packet,
57 struct batadv_hard_iface *if_incoming,
58 const unsigned char *tt_buff,
59 - int is_duplicate)
60 + enum batadv_dup_status dup_status)
61 {
62 struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
63 struct batadv_neigh_node *router = NULL;
64 @@ -676,7 +691,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
65 continue;
66 }
67
68 - if (is_duplicate)
69 + if (dup_status != BATADV_NO_DUP)
70 continue;
71
72 spin_lock_bh(&tmp_neigh_node->lq_update_lock);
73 @@ -718,7 +733,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
74 neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv);
75 spin_unlock_bh(&neigh_node->lq_update_lock);
76
77 - if (!is_duplicate) {
78 + if (dup_status == BATADV_NO_DUP) {
79 orig_node->last_ttl = batadv_ogm_packet->header.ttl;
80 neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
81 }
82 @@ -902,15 +917,16 @@ out:
83 return ret;
84 }
85
86 -/* processes a batman packet for all interfaces, adjusts the sequence number and
87 - * finds out whether it is a duplicate.
88 - * returns:
89 - * 1 the packet is a duplicate
90 - * 0 the packet has not yet been received
91 - * -1 the packet is old and has been received while the seqno window
92 - * was protected. Caller should drop it.
93 +/**
94 + * batadv_iv_ogm_update_seqnos - process a batman packet for all interfaces,
95 + * adjust the sequence number and find out whether it is a duplicate
96 + * @ethhdr: ethernet header of the packet
97 + * @batadv_ogm_packet: OGM packet to be considered
98 + * @if_incoming: interface on which the OGM packet was received
99 + *
100 + * Returns duplicate status as enum batadv_dup_status
101 */
102 -static int
103 +static enum batadv_dup_status
104 batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
105 const struct batadv_ogm_packet *batadv_ogm_packet,
106 const struct batadv_hard_iface *if_incoming)
107 @@ -918,17 +934,18 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
108 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
109 struct batadv_orig_node *orig_node;
110 struct batadv_neigh_node *tmp_neigh_node;
111 - int is_duplicate = 0;
112 + int is_dup;
113 int32_t seq_diff;
114 int need_update = 0;
115 - int set_mark, ret = -1;
116 + int set_mark;
117 + enum batadv_dup_status ret = BATADV_NO_DUP;
118 uint32_t seqno = ntohl(batadv_ogm_packet->seqno);
119 uint8_t *neigh_addr;
120 uint8_t packet_count;
121
122 orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig);
123 if (!orig_node)
124 - return 0;
125 + return BATADV_NO_DUP;
126
127 spin_lock_bh(&orig_node->ogm_cnt_lock);
128 seq_diff = seqno - orig_node->last_real_seqno;
129 @@ -936,22 +953,29 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
130 /* signalize caller that the packet is to be dropped. */
131 if (!hlist_empty(&orig_node->neigh_list) &&
132 batadv_window_protected(bat_priv, seq_diff,
133 - &orig_node->batman_seqno_reset))
134 + &orig_node->batman_seqno_reset)) {
135 + ret = BATADV_PROTECTED;
136 goto out;
137 + }
138
139 rcu_read_lock();
140 hlist_for_each_entry_rcu(tmp_neigh_node,
141 &orig_node->neigh_list, list) {
142 - is_duplicate |= batadv_test_bit(tmp_neigh_node->real_bits,
143 - orig_node->last_real_seqno,
144 - seqno);
145 -
146 neigh_addr = tmp_neigh_node->addr;
147 + is_dup = batadv_test_bit(tmp_neigh_node->real_bits,
148 + orig_node->last_real_seqno,
149 + seqno);
150 +
151 if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
152 - tmp_neigh_node->if_incoming == if_incoming)
153 + tmp_neigh_node->if_incoming == if_incoming) {
154 set_mark = 1;
155 - else
156 + if (is_dup)
157 + ret = BATADV_NEIGH_DUP;
158 + } else {
159 set_mark = 0;
160 + if (is_dup && (ret != BATADV_NEIGH_DUP))
161 + ret = BATADV_ORIG_DUP;
162 + }
163
164 /* if the window moved, set the update flag. */
165 need_update |= batadv_bit_get_packet(bat_priv,
166 @@ -971,8 +995,6 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
167 orig_node->last_real_seqno = seqno;
168 }
169
170 - ret = is_duplicate;
171 -
172 out:
173 spin_unlock_bh(&orig_node->ogm_cnt_lock);
174 batadv_orig_node_free_ref(orig_node);
175 @@ -994,7 +1016,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
176 int is_broadcast = 0, is_bidirect;
177 bool is_single_hop_neigh = false;
178 bool is_from_best_next_hop = false;
179 - int is_duplicate, sameseq, simlar_ttl;
180 + int sameseq, similar_ttl;
181 + enum batadv_dup_status dup_status;
182 uint32_t if_incoming_seqno;
183 uint8_t *prev_sender;
184
185 @@ -1138,10 +1161,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
186 if (!orig_node)
187 return;
188
189 - is_duplicate = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
190 - if_incoming);
191 + dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
192 + if_incoming);
193
194 - if (is_duplicate == -1) {
195 + if (dup_status == BATADV_PROTECTED) {
196 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
197 "Drop packet: packet within seqno protection time (sender: %pM)\n",
198 ethhdr->h_source);
199 @@ -1211,11 +1234,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
200 * seqno and similar ttl as the non-duplicate
201 */
202 sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
203 - simlar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
204 - if (is_bidirect && (!is_duplicate || (sameseq && simlar_ttl)))
205 + similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
206 + if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
207 + (sameseq && similar_ttl)))
208 batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
209 batadv_ogm_packet, if_incoming,
210 - tt_buff, is_duplicate);
211 + tt_buff, dup_status);
212
213 /* is single hop (direct) neighbor */
214 if (is_single_hop_neigh) {
215 @@ -1236,7 +1260,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
216 goto out_neigh;
217 }
218
219 - if (is_duplicate) {
220 + if (dup_status == BATADV_NEIGH_DUP) {
221 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
222 "Drop packet: duplicate packet received\n");
223 goto out_neigh;
224 --
225 1.7.10.4
226