diff options
author | Antonio Quartulli <ordex@autistici.org> | 2011-04-26 18:22:00 -0400 |
---|---|---|
committer | Sven Eckelmann <sven@narfation.org> | 2011-06-20 05:37:35 -0400 |
commit | 2265c141086474bbae55a5bb3afa1ebb78ccaa7c (patch) | |
tree | f932bcdfa2ff8a6a2b442252e7167b90363bfa4d /net/batman-adv/gateway_client.c | |
parent | c6bda689c2c94788e1e567463ce861d1f135857f (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.c | 136 |
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 | ||
98 | void gw_deselect(struct bat_priv *bat_priv) | 99 | void 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 | ||
103 | void gw_election(struct bat_priv *bat_priv) | 104 | static 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 | |||
170 | next: | ||
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)) | 178 | void 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 | ||
208 | unlock: | 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 | |||
210 | out: | 230 | out: |
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 | ||
215 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) | 239 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) |