/* don't query throughput when no longer associated with any *batman-advinterface
*/ if (!mesh_iface) returnfalse;
/* if the user specified a customised value for this interface, then *returnitdirectly
*/
throughput = atomic_read(&hard_iface->bat_v.throughput_override); if (throughput != 0) {
*pthroughput = throughput; returntrue;
}
/* if this is a wireless device, then ask its throughput through *cfg80211API
*/ 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);
if (!ret) { /* free the TID stats immediately */
cfg80211_sinfo_release_content(&sinfo);
}
dev_put(real_netdev); if (ret == -ENOENT) { /* Node is not associated anymore! It would be *possibletodeletethisneighbor.Fornowset *thethroughputmetricto0.
*/
*pthroughput = 0; returntrue;
} if (ret) goto default_throughput;
/* try to estimate the expected throughput based on reported tx *rates
*/ if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
*pthroughput = cfg80211_calculate_bitrate(&sinfo.txrate) / 3; returntrue;
}
goto default_throughput;
}
/* only use rtnl_trylock because the elp worker will be cancelled while *therntl_lockisheld.thecancel_delayed_work_sync()wouldotherwise *waitforeverwhentheelpwork_itemwasstartedanditisthenalso *tryingtortnl_lock
*/ if (!rtnl_trylock()) returnfalse;
/* if not a wifi interface, check if this device provides data via *ethtool(e.g.anEthernetadapter)
*/
ret = __ethtool_get_link_ksettings(hard_iface->net_dev, &link_settings);
rtnl_unlock(); if (ret == 0) { /* link characteristics might change over time */ if (link_settings.base.duplex == DUPLEX_FULL)
hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX; else
hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
default_throughput: if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) {
batadv_info(mesh_iface, "WiFi driver or ethtool info does not provide information about link speeds on interface %s, therefore defaulting to hardcoded throughput values of %u.%1u Mbps. Consider overriding the throughput manually or checking your driver.\n",
hard_iface->net_dev->name,
BATADV_THROUGHPUT_DEFAULT_VALUE / 10,
BATADV_THROUGHPUT_DEFAULT_VALUE % 10);
hard_iface->bat_v.flags |= BATADV_WARNING_DEFAULT;
}
/* if none of the above cases apply, return the base_throughput */
*pthroughput = BATADV_THROUGHPUT_DEFAULT_VALUE; returntrue;
}
/* this probing routine is for Wifi neighbours only */ if (!batadv_is_wifi_hardif(hard_iface)) returntrue;
/* probe the neighbor only if no unicast packets have been sent *toitinthelast100milliseconds:thisistheratecontrol *algorithmsamplinginterval(minstrel).Inthisway,ifnot *enoughtraffichasbeensenttotheneighbor,batman-advcan *generate2probepacketsandpushtheRCalgorithmtoperform *thesampling
*/
last_tx_diff = jiffies_to_msecs(jiffies - neigh->bat_v.last_unicast_tx); if (last_tx_diff <= BATADV_ELP_PROBE_MAX_TX_DIFF) returntrue;
for (i = 0; i < BATADV_ELP_PROBES_PER_NODE; i++) {
elp_skb_len = hard_iface->bat_v.elp_skb->len;
skb = skb_copy_expand(hard_iface->bat_v.elp_skb, 0,
probe_len - elp_skb_len,
GFP_ATOMIC); if (!skb) returnfalse;
/* Tell the skb to get as big as the allocated space (we want *thepackettobeexactlyofthatsizetomakethelink *throughputestimationeffective.
*/
skb_put_zero(skb, probe_len - hard_iface->bat_v.elp_skb->len);
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "Sending unicast (probe) ELP packet on interface %s to %pM\n",
hard_iface->net_dev->name, neigh->addr);
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) goto out;
/* we are in the process of shutting this interface down */ if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
hard_iface->if_status == BATADV_IF_TO_BE_REMOVED) goto out;
/* the interface was enabled but may not be ready yet */ if (hard_iface->if_status != BATADV_IF_ACTIVE) goto restart_timer;
skb = skb_copy(hard_iface->bat_v.elp_skb, GFP_ATOMIC); if (!skb) goto restart_timer;
/* The throughput metric is updated on each sent packet. This way, if a *nodeisdeadandnolongersendspackets,batman-advisstillableto *reacttimelytoitsdeath. * *Thethroughputmetricisupdatedbyfollowingthesesteps: *1)ifthehard_ifaceiswifi=>sendanumberofunicastELPsfor *probing/samplingtoeachneighbor *2)updatethethroughputmetricvalueofeachneighbor(notethatthe *valueretrievedinthisstepmightbe100msoldbecausethe *probingpacketsatpoint1)couldstillbeintheHWqueue)
*/
rcu_read_lock();
hlist_for_each_entry_rcu(hardif_neigh, &hard_iface->neigh_list, list) { if (!batadv_v_elp_wifi_neigh_probe(hardif_neigh)) /* if something goes wrong while probing, better to stop *sendingpacketsimmediatelyandreschedulethetask
*/ break;
if (!kref_get_unless_zero(&hardif_neigh->refcount)) continue;
/* Reading the estimated throughput from cfg80211 is a task that *maysleepandthatisnotallowedinanrcuprotected *context.Thereforeaddittometric_queueandprocessit *outsidercuprotectedcontext.
*/
metric_entry = kzalloc(sizeof(*metric_entry), GFP_ATOMIC); if (!metric_entry) {
batadv_hardif_neigh_put(hardif_neigh); continue;
}
/* update orig field of every elp iface belonging to this mesh */
rcu_read_lock();
netdev_for_each_lower_private_rcu(primary_iface->mesh_iface, hard_iface, iter)
batadv_v_elp_iface_activate(primary_iface, hard_iface);
rcu_read_unlock();
}
res = batadv_check_management_packet(skb, if_incoming, BATADV_ELP_HLEN); if (!res) goto free_skb;
ethhdr = eth_hdr(skb); if (batadv_is_my_mac(bat_priv, ethhdr->h_source)) goto free_skb;
/* did we receive a B.A.T.M.A.N. V ELP packet on an interface *thatdoesnothaveB.A.T.M.A.N.VELPenabled?
*/ if (strcmp(bat_priv->algo_ops->name, "BATMAN_V") != 0) goto free_skb;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.