aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Lüssing <linus.luessing@web.de>2011-03-14 18:43:27 -0400
committerSven Eckelmann <sven@narfation.org>2011-04-17 15:11:00 -0400
commit551586292b39da6e4fbfbb5b96b57b68decfdab9 (patch)
tree7d9260d487a9c29fb3c50e0174986d1399aab1be
parent0ce790e7d736cedc563e1fb4e998babf5a4dbc3d (diff)
batman-adv: Move bonding / iface alternating router search to own functions
This decreases the size of find_router() by outsourcing the router search for the bonding and interface alternating modes to their own sub functions. This shall make it easier to keep track of the correct refcounting later. Signed-off-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Sven Eckelmann <sven@narfation.org>
-rw-r--r--net/batman-adv/routing.c180
1 files changed, 105 insertions, 75 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index c172f5d0e05a..f212abe745bc 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -1092,6 +1092,106 @@ out:
1092 return ret; 1092 return ret;
1093} 1093}
1094 1094
1095/* In the bonding case, send the packets in a round
1096 * robin fashion over the remaining interfaces.
1097 *
1098 * This method rotates the bonding list and increases the
1099 * returned router's refcount. */
1100static struct neigh_node *find_bond_router(struct orig_node *primary_orig,
1101 struct hard_iface *recv_if)
1102{
1103 struct neigh_node *tmp_neigh_node;
1104 struct neigh_node *router = NULL, *first_candidate = NULL;
1105
1106 rcu_read_lock();
1107 list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list,
1108 bonding_list) {
1109 if (!first_candidate)
1110 first_candidate = tmp_neigh_node;
1111
1112 /* recv_if == NULL on the first node. */
1113 if (tmp_neigh_node->if_incoming == recv_if)
1114 continue;
1115
1116 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
1117 continue;
1118
1119 router = tmp_neigh_node;
1120 break;
1121 }
1122
1123 /* use the first candidate if nothing was found. */
1124 if (!router && first_candidate &&
1125 atomic_inc_not_zero(&first_candidate->refcount))
1126 router = first_candidate;
1127
1128 if (!router)
1129 goto out;
1130
1131 /* selected should point to the next element
1132 * after the current router */
1133 spin_lock_bh(&primary_orig->neigh_list_lock);
1134 /* this is a list_move(), which unfortunately
1135 * does not exist as rcu version */
1136 list_del_rcu(&primary_orig->bond_list);
1137 list_add_rcu(&primary_orig->bond_list,
1138 &router->bonding_list);
1139 spin_unlock_bh(&primary_orig->neigh_list_lock);
1140
1141out:
1142 rcu_read_unlock();
1143 return router;
1144}
1145
1146/* Interface Alternating: Use the best of the
1147 * remaining candidates which are not using
1148 * this interface.
1149 *
1150 * Increases the returned router's refcount */
1151static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig,
1152 struct hard_iface *recv_if)
1153{
1154 struct neigh_node *tmp_neigh_node;
1155 struct neigh_node *router = NULL, *first_candidate = NULL;
1156
1157 rcu_read_lock();
1158 list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list,
1159 bonding_list) {
1160 if (!first_candidate)
1161 first_candidate = tmp_neigh_node;
1162
1163 /* recv_if == NULL on the first node. */
1164 if (tmp_neigh_node->if_incoming == recv_if)
1165 continue;
1166
1167 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
1168 continue;
1169
1170 /* if we don't have a router yet
1171 * or this one is better, choose it. */
1172 if ((!router) ||
1173 (tmp_neigh_node->tq_avg > router->tq_avg)) {
1174 /* decrement refcount of
1175 * previously selected router */
1176 if (router)
1177 neigh_node_free_ref(router);
1178
1179 router = tmp_neigh_node;
1180 atomic_inc_not_zero(&router->refcount);
1181 }
1182
1183 neigh_node_free_ref(tmp_neigh_node);
1184 }
1185
1186 /* use the first candidate if nothing was found. */
1187 if (!router && first_candidate &&
1188 atomic_inc_not_zero(&first_candidate->refcount))
1189 router = first_candidate;
1190
1191 rcu_read_unlock();
1192 return router;
1193}
1194
1095/* find a suitable router for this originator, and use 1195/* find a suitable router for this originator, and use
1096 * bonding if possible. increases the found neighbors 1196 * bonding if possible. increases the found neighbors
1097 * refcount.*/ 1197 * refcount.*/
@@ -1101,7 +1201,7 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
1101{ 1201{
1102 struct orig_node *primary_orig_node; 1202 struct orig_node *primary_orig_node;
1103 struct orig_node *router_orig; 1203 struct orig_node *router_orig;
1104 struct neigh_node *router, *first_candidate, *tmp_neigh_node; 1204 struct neigh_node *router;
1105 static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; 1205 static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
1106 int bonding_enabled; 1206 int bonding_enabled;
1107 1207
@@ -1157,82 +1257,12 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
1157 * in. */ 1257 * in. */
1158 1258
1159 neigh_node_free_ref(router); 1259 neigh_node_free_ref(router);
1160 first_candidate = NULL;
1161 router = NULL;
1162
1163 if (bonding_enabled) {
1164 /* in the bonding case, send the packets in a round
1165 * robin fashion over the remaining interfaces. */
1166
1167 list_for_each_entry_rcu(tmp_neigh_node,
1168 &primary_orig_node->bond_list, bonding_list) {
1169 if (!first_candidate)
1170 first_candidate = tmp_neigh_node;
1171 /* recv_if == NULL on the first node. */
1172 if (tmp_neigh_node->if_incoming != recv_if &&
1173 atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
1174 router = tmp_neigh_node;
1175 break;
1176 }
1177 }
1178
1179 /* use the first candidate if nothing was found. */
1180 if (!router && first_candidate &&
1181 atomic_inc_not_zero(&first_candidate->refcount))
1182 router = first_candidate;
1183 1260
1184 if (!router) { 1261 if (bonding_enabled)
1185 rcu_read_unlock(); 1262 router = find_bond_router(primary_orig_node, recv_if);
1186 return NULL; 1263 else
1187 } 1264 router = find_ifalter_router(primary_orig_node, recv_if);
1188
1189 /* selected should point to the next element
1190 * after the current router */
1191 spin_lock_bh(&primary_orig_node->neigh_list_lock);
1192 /* this is a list_move(), which unfortunately
1193 * does not exist as rcu version */
1194 list_del_rcu(&primary_orig_node->bond_list);
1195 list_add_rcu(&primary_orig_node->bond_list,
1196 &router->bonding_list);
1197 spin_unlock_bh(&primary_orig_node->neigh_list_lock);
1198
1199 } else {
1200 /* if bonding is disabled, use the best of the
1201 * remaining candidates which are not using
1202 * this interface. */
1203 list_for_each_entry_rcu(tmp_neigh_node,
1204 &primary_orig_node->bond_list, bonding_list) {
1205 if (!first_candidate)
1206 first_candidate = tmp_neigh_node;
1207
1208 /* recv_if == NULL on the first node. */
1209 if (tmp_neigh_node->if_incoming == recv_if)
1210 continue;
1211
1212 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
1213 continue;
1214
1215 /* if we don't have a router yet
1216 * or this one is better, choose it. */
1217 if ((!router) ||
1218 (tmp_neigh_node->tq_avg > router->tq_avg)) {
1219 /* decrement refcount of
1220 * previously selected router */
1221 if (router)
1222 neigh_node_free_ref(router);
1223
1224 router = tmp_neigh_node;
1225 atomic_inc_not_zero(&router->refcount);
1226 }
1227
1228 neigh_node_free_ref(tmp_neigh_node);
1229 }
1230 1265
1231 /* use the first candidate if nothing was found. */
1232 if (!router && first_candidate &&
1233 atomic_inc_not_zero(&first_candidate->refcount))
1234 router = first_candidate;
1235 }
1236return_router: 1266return_router:
1237 rcu_read_unlock(); 1267 rcu_read_unlock();
1238 return router; 1268 return router;