1 /* Copyright (C) 2013-2016 B.A.T.M.A.N. contributors: 2 * 3 * Linus Lüssing, Marek Lindner 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of version 2 of the GNU General Public 7 * License as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "bat_algo.h" 19 #include "main.h" 20 21 #include <linux/atomic.h> 22 #include <linux/bug.h> 23 #include <linux/cache.h> 24 #include <linux/init.h> 25 #include <linux/jiffies.h> 26 #include <linux/netdevice.h> 27 #include <linux/rculist.h> 28 #include <linux/rcupdate.h> 29 #include <linux/seq_file.h> 30 #include <linux/stddef.h> 31 #include <linux/types.h> 32 #include <linux/workqueue.h> 33 34 #include "bat_v_elp.h" 35 #include "bat_v_ogm.h" 36 #include "hard-interface.h" 37 #include "hash.h" 38 #include "originator.h" 39 #include "packet.h" 40 41 static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface) 42 { 43 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 44 struct batadv_hard_iface *primary_if; 45 46 primary_if = batadv_primary_if_get_selected(bat_priv); 47 48 if (primary_if) { 49 batadv_v_elp_iface_activate(primary_if, hard_iface); 50 batadv_hardif_put(primary_if); 51 } 52 53 /* B.A.T.M.A.N. V does not use any queuing mechanism, therefore it can 54 * set the interface as ACTIVE right away, without any risk of race 55 * condition 56 */ 57 if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED) 58 hard_iface->if_status = BATADV_IF_ACTIVE; 59 } 60 61 static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface) 62 { 63 int ret; 64 65 ret = batadv_v_elp_iface_enable(hard_iface); 66 if (ret < 0) 67 return ret; 68 69 ret = batadv_v_ogm_iface_enable(hard_iface); 70 if (ret < 0) 71 batadv_v_elp_iface_disable(hard_iface); 72 73 /* enable link throughput auto-detection by setting the throughput 74 * override to zero 75 */ 76 atomic_set(&hard_iface->bat_v.throughput_override, 0); 77 78 return ret; 79 } 80 81 static void batadv_v_iface_disable(struct batadv_hard_iface *hard_iface) 82 { 83 batadv_v_elp_iface_disable(hard_iface); 84 } 85 86 static void batadv_v_primary_iface_set(struct batadv_hard_iface *hard_iface) 87 { 88 batadv_v_elp_primary_iface_set(hard_iface); 89 batadv_v_ogm_primary_iface_set(hard_iface); 90 } 91 92 /** 93 * batadv_v_iface_update_mac - react to hard-interface MAC address change 94 * @hard_iface: the modified interface 95 * 96 * If the modified interface is the primary one, update the originator 97 * address in the ELP and OGM messages to reflect the new MAC address. 98 */ 99 static void batadv_v_iface_update_mac(struct batadv_hard_iface *hard_iface) 100 { 101 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 102 struct batadv_hard_iface *primary_if; 103 104 primary_if = batadv_primary_if_get_selected(bat_priv); 105 if (primary_if != hard_iface) 106 goto out; 107 108 batadv_v_primary_iface_set(hard_iface); 109 out: 110 if (primary_if) 111 batadv_hardif_put(primary_if); 112 } 113 114 static void 115 batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh) 116 { 117 ewma_throughput_init(&hardif_neigh->bat_v.throughput); 118 INIT_WORK(&hardif_neigh->bat_v.metric_work, 119 batadv_v_elp_throughput_metric_update); 120 } 121 122 static void batadv_v_ogm_schedule(struct batadv_hard_iface *hard_iface) 123 { 124 } 125 126 static void batadv_v_ogm_emit(struct batadv_forw_packet *forw_packet) 127 { 128 } 129 130 /** 131 * batadv_v_orig_print_neigh - print neighbors for the originator table 132 * @orig_node: the orig_node for which the neighbors are printed 133 * @if_outgoing: outgoing interface for these entries 134 * @seq: debugfs table seq_file struct 135 * 136 * Must be called while holding an rcu lock. 137 */ 138 static void 139 batadv_v_orig_print_neigh(struct batadv_orig_node *orig_node, 140 struct batadv_hard_iface *if_outgoing, 141 struct seq_file *seq) 142 { 143 struct batadv_neigh_node *neigh_node; 144 struct batadv_neigh_ifinfo *n_ifinfo; 145 146 hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) { 147 n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing); 148 if (!n_ifinfo) 149 continue; 150 151 seq_printf(seq, " %pM (%9u.%1u)", 152 neigh_node->addr, 153 n_ifinfo->bat_v.throughput / 10, 154 n_ifinfo->bat_v.throughput % 10); 155 156 batadv_neigh_ifinfo_put(n_ifinfo); 157 } 158 } 159 160 /** 161 * batadv_v_hardif_neigh_print - print a single ELP neighbour node 162 * @seq: neighbour table seq_file struct 163 * @hardif_neigh: hardif neighbour information 164 */ 165 static void 166 batadv_v_hardif_neigh_print(struct seq_file *seq, 167 struct batadv_hardif_neigh_node *hardif_neigh) 168 { 169 int last_secs, last_msecs; 170 u32 throughput; 171 172 last_secs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) / 1000; 173 last_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) % 1000; 174 throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput); 175 176 seq_printf(seq, "%pM %4i.%03is (%9u.%1u) [%10s]\n", 177 hardif_neigh->addr, last_secs, last_msecs, throughput / 10, 178 throughput % 10, hardif_neigh->if_incoming->net_dev->name); 179 } 180 181 /** 182 * batadv_v_neigh_print - print the single hop neighbour list 183 * @bat_priv: the bat priv with all the soft interface information 184 * @seq: neighbour table seq_file struct 185 */ 186 static void batadv_v_neigh_print(struct batadv_priv *bat_priv, 187 struct seq_file *seq) 188 { 189 struct net_device *net_dev = (struct net_device *)seq->private; 190 struct batadv_hardif_neigh_node *hardif_neigh; 191 struct batadv_hard_iface *hard_iface; 192 int batman_count = 0; 193 194 seq_puts(seq, 195 " Neighbor last-seen ( throughput) [ IF]\n"); 196 197 rcu_read_lock(); 198 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { 199 if (hard_iface->soft_iface != net_dev) 200 continue; 201 202 hlist_for_each_entry_rcu(hardif_neigh, 203 &hard_iface->neigh_list, list) { 204 batadv_v_hardif_neigh_print(seq, hardif_neigh); 205 batman_count++; 206 } 207 } 208 rcu_read_unlock(); 209 210 if (batman_count == 0) 211 seq_puts(seq, "No batman nodes in range ...\n"); 212 } 213 214 /** 215 * batadv_v_orig_print - print the originator table 216 * @bat_priv: the bat priv with all the soft interface information 217 * @seq: debugfs table seq_file struct 218 * @if_outgoing: the outgoing interface for which this should be printed 219 */ 220 static void batadv_v_orig_print(struct batadv_priv *bat_priv, 221 struct seq_file *seq, 222 struct batadv_hard_iface *if_outgoing) 223 { 224 struct batadv_neigh_node *neigh_node; 225 struct batadv_hashtable *hash = bat_priv->orig_hash; 226 int last_seen_msecs, last_seen_secs; 227 struct batadv_orig_node *orig_node; 228 struct batadv_neigh_ifinfo *n_ifinfo; 229 unsigned long last_seen_jiffies; 230 struct hlist_head *head; 231 int batman_count = 0; 232 u32 i; 233 234 seq_puts(seq, 235 " Originator last-seen ( throughput) Nexthop [outgoingIF]: Potential nexthops ...\n"); 236 237 for (i = 0; i < hash->size; i++) { 238 head = &hash->table[i]; 239 240 rcu_read_lock(); 241 hlist_for_each_entry_rcu(orig_node, head, hash_entry) { 242 neigh_node = batadv_orig_router_get(orig_node, 243 if_outgoing); 244 if (!neigh_node) 245 continue; 246 247 n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, 248 if_outgoing); 249 if (!n_ifinfo) 250 goto next; 251 252 last_seen_jiffies = jiffies - orig_node->last_seen; 253 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); 254 last_seen_secs = last_seen_msecs / 1000; 255 last_seen_msecs = last_seen_msecs % 1000; 256 257 seq_printf(seq, "%pM %4i.%03is (%9u.%1u) %pM [%10s]:", 258 orig_node->orig, last_seen_secs, 259 last_seen_msecs, 260 n_ifinfo->bat_v.throughput / 10, 261 n_ifinfo->bat_v.throughput % 10, 262 neigh_node->addr, 263 neigh_node->if_incoming->net_dev->name); 264 265 batadv_v_orig_print_neigh(orig_node, if_outgoing, seq); 266 seq_puts(seq, "\n"); 267 batman_count++; 268 269 next: 270 batadv_neigh_node_put(neigh_node); 271 if (n_ifinfo) 272 batadv_neigh_ifinfo_put(n_ifinfo); 273 } 274 rcu_read_unlock(); 275 } 276 277 if (batman_count == 0) 278 seq_puts(seq, "No batman nodes in range ...\n"); 279 } 280 281 static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1, 282 struct batadv_hard_iface *if_outgoing1, 283 struct batadv_neigh_node *neigh2, 284 struct batadv_hard_iface *if_outgoing2) 285 { 286 struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2; 287 int ret = 0; 288 289 ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); 290 if (WARN_ON(!ifinfo1)) 291 goto err_ifinfo1; 292 293 ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); 294 if (WARN_ON(!ifinfo2)) 295 goto err_ifinfo2; 296 297 ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput; 298 299 batadv_neigh_ifinfo_put(ifinfo2); 300 err_ifinfo2: 301 batadv_neigh_ifinfo_put(ifinfo1); 302 err_ifinfo1: 303 return ret; 304 } 305 306 static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1, 307 struct batadv_hard_iface *if_outgoing1, 308 struct batadv_neigh_node *neigh2, 309 struct batadv_hard_iface *if_outgoing2) 310 { 311 struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2; 312 u32 threshold; 313 bool ret = false; 314 315 ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1); 316 if (WARN_ON(!ifinfo1)) 317 goto err_ifinfo1; 318 319 ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2); 320 if (WARN_ON(!ifinfo2)) 321 goto err_ifinfo2; 322 323 threshold = ifinfo1->bat_v.throughput / 4; 324 threshold = ifinfo1->bat_v.throughput - threshold; 325 326 ret = ifinfo2->bat_v.throughput > threshold; 327 328 batadv_neigh_ifinfo_put(ifinfo2); 329 err_ifinfo2: 330 batadv_neigh_ifinfo_put(ifinfo1); 331 err_ifinfo1: 332 return ret; 333 } 334 335 static struct batadv_algo_ops batadv_batman_v __read_mostly = { 336 .name = "BATMAN_V", 337 .bat_iface_activate = batadv_v_iface_activate, 338 .bat_iface_enable = batadv_v_iface_enable, 339 .bat_iface_disable = batadv_v_iface_disable, 340 .bat_iface_update_mac = batadv_v_iface_update_mac, 341 .bat_primary_iface_set = batadv_v_primary_iface_set, 342 .bat_hardif_neigh_init = batadv_v_hardif_neigh_init, 343 .bat_ogm_emit = batadv_v_ogm_emit, 344 .bat_ogm_schedule = batadv_v_ogm_schedule, 345 .bat_orig_print = batadv_v_orig_print, 346 .bat_neigh_cmp = batadv_v_neigh_cmp, 347 .bat_neigh_is_similar_or_better = batadv_v_neigh_is_sob, 348 .bat_neigh_print = batadv_v_neigh_print, 349 }; 350 351 /** 352 * batadv_v_mesh_init - initialize the B.A.T.M.A.N. V private resources for a 353 * mesh 354 * @bat_priv: the object representing the mesh interface to initialise 355 * 356 * Return: 0 on success or a negative error code otherwise 357 */ 358 int batadv_v_mesh_init(struct batadv_priv *bat_priv) 359 { 360 return batadv_v_ogm_init(bat_priv); 361 } 362 363 /** 364 * batadv_v_mesh_free - free the B.A.T.M.A.N. V private resources for a mesh 365 * @bat_priv: the object representing the mesh interface to free 366 */ 367 void batadv_v_mesh_free(struct batadv_priv *bat_priv) 368 { 369 batadv_v_ogm_free(bat_priv); 370 } 371 372 /** 373 * batadv_v_init - B.A.T.M.A.N. V initialization function 374 * 375 * Description: Takes care of initializing all the subcomponents. 376 * It is invoked upon module load only. 377 * 378 * Return: 0 on success or a negative error code otherwise 379 */ 380 int __init batadv_v_init(void) 381 { 382 int ret; 383 384 /* B.A.T.M.A.N. V echo location protocol packet */ 385 ret = batadv_recv_handler_register(BATADV_ELP, 386 batadv_v_elp_packet_recv); 387 if (ret < 0) 388 return ret; 389 390 ret = batadv_recv_handler_register(BATADV_OGM2, 391 batadv_v_ogm_packet_recv); 392 if (ret < 0) 393 goto elp_unregister; 394 395 ret = batadv_algo_register(&batadv_batman_v); 396 if (ret < 0) 397 goto ogm_unregister; 398 399 return ret; 400 401 ogm_unregister: 402 batadv_recv_handler_unregister(BATADV_OGM2); 403 404 elp_unregister: 405 batadv_recv_handler_unregister(BATADV_ELP); 406 407 return ret; 408 } 409