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