diff options
Diffstat (limited to 'net/batman-adv/bat_v_elp.c')
-rw-r--r-- | net/batman-adv/bat_v_elp.c | 71 |
1 files changed, 41 insertions, 30 deletions
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c index ee08540ce503..f2fb2f05b6bf 100644 --- a/net/batman-adv/bat_v_elp.c +++ b/net/batman-adv/bat_v_elp.c @@ -75,6 +75,7 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) { struct batadv_hard_iface *hard_iface = neigh->if_incoming; struct ethtool_link_ksettings link_settings; + struct net_device *real_netdev; struct station_info sinfo; u32 throughput; int ret; @@ -89,23 +90,27 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh) /* if this is a wireless device, then ask its throughput through * cfg80211 API */ - if (batadv_is_wifi_netdev(hard_iface->net_dev)) { - if (hard_iface->net_dev->ieee80211_ptr) { - ret = cfg80211_get_station(hard_iface->net_dev, - neigh->addr, &sinfo); - if (ret == -ENOENT) { - /* Node is not associated anymore! It would be - * possible to delete this neighbor. For now set - * the throughput metric to 0. - */ - return 0; - } - if (!ret) - return sinfo.expected_throughput / 100; + if (batadv_is_wifi_hardif(hard_iface)) { + if (!batadv_is_cfg80211_hardif(hard_iface)) + /* unsupported WiFi driver version */ + goto default_throughput; + + real_netdev = batadv_get_real_netdev(hard_iface->net_dev); + if (!real_netdev) + goto default_throughput; + + ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo); + + dev_put(real_netdev); + if (ret == -ENOENT) { + /* Node is not associated anymore! It would be + * possible to delete this neighbor. For now set + * the throughput metric to 0. + */ + return 0; } - - /* unsupported WiFi driver version */ - goto default_throughput; + if (!ret) + return sinfo.expected_throughput / 100; } /* if not a wifi interface, check if this device provides data via @@ -187,7 +192,7 @@ batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh) int elp_skb_len; /* this probing routine is for Wifi neighbours only */ - if (!batadv_is_wifi_netdev(hard_iface->net_dev)) + if (!batadv_is_wifi_hardif(hard_iface)) return true; /* probe the neighbor only if no unicast packets have been sent @@ -352,7 +357,7 @@ int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface) /* warn the user (again) if there is no throughput data is available */ hard_iface->bat_v.flags &= ~BATADV_WARNING_DEFAULT; - if (batadv_is_wifi_netdev(hard_iface->net_dev)) + if (batadv_is_wifi_hardif(hard_iface)) hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX; INIT_DELAYED_WORK(&hard_iface->bat_v.elp_wq, @@ -492,20 +497,21 @@ int batadv_v_elp_packet_recv(struct sk_buff *skb, struct batadv_elp_packet *elp_packet; struct batadv_hard_iface *primary_if; struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); - bool ret; + bool res; + int ret = NET_RX_DROP; - ret = batadv_check_management_packet(skb, if_incoming, BATADV_ELP_HLEN); - if (!ret) - return NET_RX_DROP; + res = batadv_check_management_packet(skb, if_incoming, BATADV_ELP_HLEN); + if (!res) + goto free_skb; if (batadv_is_my_mac(bat_priv, ethhdr->h_source)) - return NET_RX_DROP; + goto free_skb; /* did we receive a B.A.T.M.A.N. V ELP packet on an interface * that does not have B.A.T.M.A.N. V ELP enabled ? */ if (strcmp(bat_priv->algo_ops->name, "BATMAN_V") != 0) - return NET_RX_DROP; + goto free_skb; elp_packet = (struct batadv_elp_packet *)skb->data; @@ -516,14 +522,19 @@ int batadv_v_elp_packet_recv(struct sk_buff *skb, primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) - goto out; + goto free_skb; batadv_v_elp_neigh_update(bat_priv, ethhdr->h_source, if_incoming, elp_packet); -out: - if (primary_if) - batadv_hardif_put(primary_if); - consume_skb(skb); - return NET_RX_SUCCESS; + ret = NET_RX_SUCCESS; + batadv_hardif_put(primary_if); + +free_skb: + if (ret == NET_RX_SUCCESS) + consume_skb(skb); + else + kfree_skb(skb); + + return ret; } |