29 #include <linux/ipv6.h>
30 #include <linux/udp.h>
31 #include <linux/if_vlan.h>
36 #define BATADV_DHCP_OPTIONS_OFFSET 240
37 #define BATADV_DHCP_REQUEST 3
39 static void batadv_gw_node_free_ref(
struct batadv_gw_node *gw_node)
46 batadv_gw_get_selected_gw_node(
struct batadv_priv *bat_priv)
69 gw_node = batadv_gw_get_selected_gw_node(bat_priv);
85 batadv_gw_node_free_ref(gw_node);
89 static void batadv_gw_select(
struct batadv_priv *bat_priv,
94 spin_lock_bh(&bat_priv->
gw.list_lock);
103 batadv_gw_node_free_ref(curr_gw_node);
105 spin_unlock_bh(&bat_priv->
gw.list_lock);
114 batadv_gw_get_best_gw_node(
struct batadv_priv *bat_priv)
119 uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
130 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->
gw.list,
list) {
149 tmp_gw_factor = tq_avg * tq_avg * down * 100 * 100;
150 tmp_gw_factor /= gw_divisor;
152 if ((tmp_gw_factor > max_gw_factor) ||
153 ((tmp_gw_factor == max_gw_factor) &&
154 (tq_avg > max_tq))) {
156 batadv_gw_node_free_ref(curr_gw);
169 if (tq_avg > max_tq) {
171 batadv_gw_node_free_ref(curr_gw);
181 if (tmp_gw_factor > max_gw_factor)
182 max_gw_factor = tmp_gw_factor;
184 batadv_gw_node_free_ref(gw_node);
198 char gw_addr[18] = {
'\0' };
208 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
213 next_gw = batadv_gw_get_best_gw_node(bat_priv);
215 if (curr_gw == next_gw)
219 sprintf(gw_addr,
"%pM", next_gw->orig_node->orig);
228 if ((curr_gw) && (!next_gw)) {
230 "Removing selected gateway - no gateway in range\n");
233 }
else if ((!curr_gw) && (next_gw)) {
235 "Adding route to gateway %pM (gw_flags: %i, tq: %i)\n",
236 next_gw->orig_node->orig,
237 next_gw->orig_node->gw_flags, router->
tq_avg);
242 "Changing route to gateway %pM (gw_flags: %i, tq: %i)\n",
243 next_gw->orig_node->orig,
244 next_gw->orig_node->gw_flags, router->
tq_avg);
249 batadv_gw_select(bat_priv, next_gw);
253 batadv_gw_node_free_ref(curr_gw);
255 batadv_gw_node_free_ref(next_gw);
265 uint8_t gw_tq_avg, orig_tq_avg;
276 if (curr_gw_orig == orig_node)
283 gw_tq_avg = router_gw->
tq_avg;
284 orig_tq_avg = router_orig->tq_avg;
287 if (orig_tq_avg < gw_tq_avg)
298 "Restarting gateway selection: better gateway found (tq curr: %i, tq new: %i)\n",
299 gw_tq_avg, orig_tq_avg);
314 static void batadv_gw_node_add(
struct batadv_priv *bat_priv,
321 gw_node = kzalloc(
sizeof(*gw_node),
GFP_ATOMIC);
325 INIT_HLIST_NODE(&gw_node->
list);
329 spin_lock_bh(&bat_priv->
gw.list_lock);
330 hlist_add_head_rcu(&gw_node->
list, &bat_priv->
gw.list);
331 spin_unlock_bh(&bat_priv->
gw.list_lock);
335 "Found new gateway %pM -> gw_class: %i - %i%s/%i%s\n",
336 orig_node->
orig, new_gwflags,
337 (down > 2048 ? down / 1024 : down),
338 (down > 2048 ?
"MBit" :
"KBit"),
339 (up > 2048 ? up / 1024 : up),
340 (up > 2048 ?
"MBit" :
"KBit"));
355 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
358 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->
gw.list,
list) {
363 "Gateway class of originator %pM changed from %i to %i\n",
372 "Gateway %pM removed from gateway list\n",
375 if (gw_node == curr_gw)
385 batadv_gw_node_add(bat_priv, orig_node, new_gwflags);
394 batadv_gw_node_free_ref(curr_gw);
410 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
412 spin_lock_bh(&bat_priv->
gw.list_lock);
415 &bat_priv->
gw.list,
list) {
421 if (curr_gw == gw_node)
424 hlist_del_rcu(&gw_node->
list);
425 batadv_gw_node_free_ref(gw_node);
428 spin_unlock_bh(&bat_priv->
gw.list_lock);
435 batadv_gw_node_free_ref(curr_gw);
439 static int batadv_write_buffer_text(
struct batadv_priv *bat_priv,
453 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
455 ret =
seq_printf(seq,
"%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n",
456 (curr_gw == gw_node ?
"=>" :
" "),
461 (down > 2048 ? down / 1024 : down),
462 (down > 2048 ?
"MBit" :
"KBit"),
463 (up > 2048 ? up / 1024 : up),
464 (up > 2048 ?
"MBit" :
"KBit"));
468 batadv_gw_node_free_ref(curr_gw);
476 struct batadv_priv *bat_priv = netdev_priv(net_dev);
480 int gw_count = 0, ret = 0;
482 primary_if = batadv_primary_if_get_selected(bat_priv);
485 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
492 "BATMAN mesh %s disabled - primary interface not active\n",
498 " %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
504 hlist_for_each_entry_rcu(gw_node, node, &bat_priv->
gw.list,
list) {
509 if (batadv_write_buffer_text(bat_priv, seq, gw_node) < 0)
517 seq_printf(seq,
"No gateways in range ...\n");
521 batadv_hardif_free_ref(primary_if);
531 if (skb_linearize(skb) < 0)
534 pkt_len = skb_headlen(skb);
540 pkt_len -= header_len + BATADV_DHCP_OPTIONS_OFFSET + 1;
547 while (*p != 255 && !ret) {
561 }
else if (*p == 0) {
575 if (pkt_len < 1 + (*p))
593 if (!pskb_may_pull(skb, *header_len +
ETH_HLEN))
595 ethhdr = (
struct ethhdr *)skb->
data;
600 if (!pskb_may_pull(skb, *header_len +
VLAN_HLEN))
609 if (!pskb_may_pull(skb, *header_len +
sizeof(*iphdr)))
611 iphdr = (
struct iphdr *)(skb->
data + *header_len);
612 *header_len += iphdr->ihl * 4;
620 if (!pskb_may_pull(skb, *header_len +
sizeof(*ipv6hdr)))
622 ipv6hdr = (
struct ipv6hdr *)(skb->
data + *header_len);
623 *header_len +=
sizeof(*ipv6hdr);
634 if (!pskb_may_pull(skb, *header_len +
sizeof(*udphdr)))
636 udphdr = (
struct udphdr *)(skb->
data + *header_len);
637 *header_len +=
sizeof(*udphdr);
657 bool ret, out_of_range =
false;
658 unsigned int header_len = 0;
673 ret = batadv_is_type_dhcprequest(skb, header_len);
685 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
702 curr_tq_avg = neigh_curr->
tq_avg;
720 batadv_gw_node_free_ref(curr_gw);