net/batman-adv/bat_v_elp.c

Source file repositories/reference/linux-study-clean/net/batman-adv/bat_v_elp.c

File Facts

System
Linux kernel
Corpus path
net/batman-adv/bat_v_elp.c
Extension
.c
Size
18463 bytes
Lines
608
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct batadv_v_metric_queue_entry {
	/** @hardif_neigh: hardif neighbor scheduled for metric update */
	struct batadv_hardif_neigh_node *hardif_neigh;

	/** @list: list node for metric_queue */
	struct list_head list;
};

/**
 * batadv_v_elp_start_timer() - restart timer for ELP periodic work
 * @hard_iface: the interface for which the timer has to be reset
 */
static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
{
	unsigned int msecs;

	msecs = READ_ONCE(hard_iface->bat_v.elp_interval) - BATADV_JITTER;
	msecs += get_random_u32_below(2 * BATADV_JITTER);

	queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.elp_wq,
			   msecs_to_jiffies(msecs));
}

/**
 * batadv_v_elp_get_throughput() - get the throughput towards a neighbour
 * @neigh: the neighbour for which the throughput has to be obtained
 * @pthroughput: calculated throughput towards the given neighbour in multiples
 *  of 100kpbs (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
 *
 * Return: true when value behind @pthroughput was set
 */
static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh,
					u32 *pthroughput)
{
	struct batadv_hard_iface *hard_iface = neigh->if_incoming;
	struct net_device *mesh_iface = hard_iface->mesh_iface;
	struct ethtool_link_ksettings link_settings;
	struct net_device *real_netdev;
	struct station_info sinfo;
	u32 wifi_flags;
	u32 throughput;
	int ret;

	/* don't query throughput when no longer associated with any
	 * batman-adv interface
	 */
	if (!mesh_iface)
		return false;

	/* if the user specified a customised value for this interface, then
	 * return it directly
	 */
	throughput =  READ_ONCE(hard_iface->bat_v.throughput_override);
	if (throughput != 0) {
		*pthroughput = throughput;
		return true;
	}

	/* if this is a wireless device, then ask its throughput through
	 * cfg80211 API
	 */
	wifi_flags = batadv_hardif_get_wifi_flags(hard_iface);
	if (batadv_is_wifi(wifi_flags)) {
		if (!batadv_is_cfg80211(wifi_flags))
			/* unsupported WiFi driver version */
			goto default_throughput;

		/* only use rtnl_trylock because the elp worker will be cancelled while
		 * the rntl_lock is held. the disable_delayed_work_sync() would otherwise
		 * wait forever when the elp work_item was started and it is then also
		 * trying to rtnl_lock
		 */
		if (!rtnl_trylock())
			return false;
		real_netdev = __batadv_get_real_netdev(hard_iface->net_dev);
		rtnl_unlock();
		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
			 * possible to delete this neighbor. For now set

Annotation

Implementation Notes