diff options
author | Linus Lüssing <linus.luessing@web.de> | 2011-03-14 18:43:27 -0400 |
---|---|---|
committer | Sven Eckelmann <sven@narfation.org> | 2011-04-17 15:11:00 -0400 |
commit | 551586292b39da6e4fbfbb5b96b57b68decfdab9 (patch) | |
tree | 7d9260d487a9c29fb3c50e0174986d1399aab1be | |
parent | 0ce790e7d736cedc563e1fb4e998babf5a4dbc3d (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.c | 180 |
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. */ | ||
1100 | static 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 | |||
1141 | out: | ||
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 */ | ||
1151 | static 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 | } | ||
1236 | return_router: | 1266 | return_router: |
1237 | rcu_read_unlock(); | 1267 | rcu_read_unlock(); |
1238 | return router; | 1268 | return router; |