aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/gateway_client.c
diff options
context:
space:
mode:
authorAntonio Quartulli <ordex@autistici.org>2011-04-26 18:22:00 -0400
committerSven Eckelmann <sven@narfation.org>2011-06-20 05:37:35 -0400
commit2265c141086474bbae55a5bb3afa1ebb78ccaa7c (patch)
treef932bcdfa2ff8a6a2b442252e7167b90363bfa4d /net/batman-adv/gateway_client.c
parentc6bda689c2c94788e1e567463ce861d1f135857f (diff)
batman-adv: gateway election code refactoring
The gateway election mechanism has been a little revised. Now the gw_election is trigered by an atomic_t flag (gw_reselect) which is set to 1 in case of election needed, avoding to set curr_gw to NULL. Signed-off-by: Antonio Quartulli <ordex@autistici.org> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Sven Eckelmann <sven@narfation.org>
Diffstat (limited to 'net/batman-adv/gateway_client.c')
-rw-r--r--net/batman-adv/gateway_client.c136
1 files changed, 80 insertions, 56 deletions
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 7248de2e66dc..0350c0cd690e 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -20,6 +20,7 @@
20 */ 20 */
21 21
22#include "main.h" 22#include "main.h"
23#include "bat_sysfs.h"
23#include "gateway_client.h" 24#include "gateway_client.h"
24#include "gateway_common.h" 25#include "gateway_common.h"
25#include "hard-interface.h" 26#include "hard-interface.h"
@@ -97,40 +98,19 @@ static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node)
97 98
98void gw_deselect(struct bat_priv *bat_priv) 99void gw_deselect(struct bat_priv *bat_priv)
99{ 100{
100 gw_select(bat_priv, NULL); 101 atomic_set(&bat_priv->gw_reselect, 1);
101} 102}
102 103
103void gw_election(struct bat_priv *bat_priv) 104static struct gw_node *gw_get_best_gw_node(struct bat_priv *bat_priv)
104{ 105{
105 struct hlist_node *node;
106 struct gw_node *gw_node, *curr_gw = NULL, *curr_gw_tmp = NULL;
107 struct neigh_node *router; 106 struct neigh_node *router;
108 uint8_t max_tq = 0; 107 struct hlist_node *node;
108 struct gw_node *gw_node, *curr_gw = NULL;
109 uint32_t max_gw_factor = 0, tmp_gw_factor = 0; 109 uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
110 uint8_t max_tq = 0;
110 int down, up; 111 int down, up;
111 112
112 /**
113 * The batman daemon checks here if we already passed a full originator
114 * cycle in order to make sure we don't choose the first gateway we
115 * hear about. This check is based on the daemon's uptime which we
116 * don't have.
117 **/
118 if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
119 return;
120
121 curr_gw = gw_get_selected_gw_node(bat_priv);
122 if (curr_gw)
123 goto out;
124
125 rcu_read_lock(); 113 rcu_read_lock();
126 if (hlist_empty(&bat_priv->gw_list)) {
127 bat_dbg(DBG_BATMAN, bat_priv,
128 "Removing selected gateway - "
129 "no gateway in range\n");
130 gw_deselect(bat_priv);
131 goto unlock;
132 }
133
134 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { 114 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
135 if (gw_node->deleted) 115 if (gw_node->deleted)
136 continue; 116 continue;
@@ -139,6 +119,9 @@ void gw_election(struct bat_priv *bat_priv)
139 if (!router) 119 if (!router)
140 continue; 120 continue;
141 121
122 if (!atomic_inc_not_zero(&gw_node->refcount))
123 goto next;
124
142 switch (atomic_read(&bat_priv->gw_sel_class)) { 125 switch (atomic_read(&bat_priv->gw_sel_class)) {
143 case 1: /* fast connection */ 126 case 1: /* fast connection */
144 gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, 127 gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags,
@@ -151,8 +134,12 @@ void gw_election(struct bat_priv *bat_priv)
151 134
152 if ((tmp_gw_factor > max_gw_factor) || 135 if ((tmp_gw_factor > max_gw_factor) ||
153 ((tmp_gw_factor == max_gw_factor) && 136 ((tmp_gw_factor == max_gw_factor) &&
154 (router->tq_avg > max_tq))) 137 (router->tq_avg > max_tq))) {
155 curr_gw_tmp = gw_node; 138 if (curr_gw)
139 gw_node_free_ref(curr_gw);
140 curr_gw = gw_node;
141 atomic_inc(&curr_gw->refcount);
142 }
156 break; 143 break;
157 144
158 default: /** 145 default: /**
@@ -163,8 +150,12 @@ void gw_election(struct bat_priv *bat_priv)
163 * soon as a better gateway appears which has 150 * soon as a better gateway appears which has
164 * $routing_class more tq points) 151 * $routing_class more tq points)
165 **/ 152 **/
166 if (router->tq_avg > max_tq) 153 if (router->tq_avg > max_tq) {
167 curr_gw_tmp = gw_node; 154 if (curr_gw)
155 gw_node_free_ref(curr_gw);
156 curr_gw = gw_node;
157 atomic_inc(&curr_gw->refcount);
158 }
168 break; 159 break;
169 } 160 }
170 161
@@ -174,42 +165,75 @@ void gw_election(struct bat_priv *bat_priv)
174 if (tmp_gw_factor > max_gw_factor) 165 if (tmp_gw_factor > max_gw_factor)
175 max_gw_factor = tmp_gw_factor; 166 max_gw_factor = tmp_gw_factor;
176 167
168 gw_node_free_ref(gw_node);
169
170next:
177 neigh_node_free_ref(router); 171 neigh_node_free_ref(router);
178 } 172 }
173 rcu_read_unlock();
179 174
180 if (curr_gw != curr_gw_tmp) { 175 return curr_gw;
181 router = orig_node_get_router(curr_gw_tmp->orig_node); 176}
182 if (!router)
183 goto unlock;
184 177
185 if ((curr_gw) && (!curr_gw_tmp)) 178void gw_election(struct bat_priv *bat_priv)
186 bat_dbg(DBG_BATMAN, bat_priv, 179{
187 "Removing selected gateway - " 180 struct gw_node *curr_gw = NULL, *next_gw = NULL;
188 "no gateway in range\n"); 181 struct neigh_node *router = NULL;
189 else if ((!curr_gw) && (curr_gw_tmp))
190 bat_dbg(DBG_BATMAN, bat_priv,
191 "Adding route to gateway %pM "
192 "(gw_flags: %i, tq: %i)\n",
193 curr_gw_tmp->orig_node->orig,
194 curr_gw_tmp->orig_node->gw_flags,
195 router->tq_avg);
196 else
197 bat_dbg(DBG_BATMAN, bat_priv,
198 "Changing route to gateway %pM "
199 "(gw_flags: %i, tq: %i)\n",
200 curr_gw_tmp->orig_node->orig,
201 curr_gw_tmp->orig_node->gw_flags,
202 router->tq_avg);
203 182
204 neigh_node_free_ref(router); 183 /**
205 gw_select(bat_priv, curr_gw_tmp); 184 * The batman daemon checks here if we already passed a full originator
185 * cycle in order to make sure we don't choose the first gateway we
186 * hear about. This check is based on the daemon's uptime which we
187 * don't have.
188 **/
189 if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
190 goto out;
191
192 if (!atomic_dec_not_zero(&bat_priv->gw_reselect))
193 goto out;
194
195 curr_gw = gw_get_selected_gw_node(bat_priv);
196
197 next_gw = gw_get_best_gw_node(bat_priv);
198
199 if (curr_gw == next_gw)
200 goto out;
201
202 if (next_gw) {
203 router = orig_node_get_router(next_gw->orig_node);
204 if (!router) {
205 gw_deselect(bat_priv);
206 goto out;
207 }
206 } 208 }
207 209
208unlock: 210 if ((curr_gw) && (!next_gw)) {
209 rcu_read_unlock(); 211 bat_dbg(DBG_BATMAN, bat_priv,
212 "Removing selected gateway - no gateway in range\n");
213 } else if ((!curr_gw) && (next_gw)) {
214 bat_dbg(DBG_BATMAN, bat_priv,
215 "Adding route to gateway %pM (gw_flags: %i, tq: %i)\n",
216 next_gw->orig_node->orig,
217 next_gw->orig_node->gw_flags,
218 router->tq_avg);
219 } else {
220 bat_dbg(DBG_BATMAN, bat_priv,
221 "Changing route to gateway %pM "
222 "(gw_flags: %i, tq: %i)\n",
223 next_gw->orig_node->orig,
224 next_gw->orig_node->gw_flags,
225 router->tq_avg);
226 }
227
228 gw_select(bat_priv, next_gw);
229
210out: 230out:
211 if (curr_gw) 231 if (curr_gw)
212 gw_node_free_ref(curr_gw); 232 gw_node_free_ref(curr_gw);
233 if (next_gw)
234 gw_node_free_ref(next_gw);
235 if (router)
236 neigh_node_free_ref(router);
213} 237}
214 238
215void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) 239void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)