cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bat_v_elp.c (16881B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (C) B.A.T.M.A.N. contributors:
      3 *
      4 * Linus Lüssing, Marek Lindner
      5 */
      6
      7#include "bat_v_elp.h"
      8#include "main.h"
      9
     10#include <linux/atomic.h>
     11#include <linux/bitops.h>
     12#include <linux/byteorder/generic.h>
     13#include <linux/container_of.h>
     14#include <linux/errno.h>
     15#include <linux/etherdevice.h>
     16#include <linux/ethtool.h>
     17#include <linux/gfp.h>
     18#include <linux/if_ether.h>
     19#include <linux/jiffies.h>
     20#include <linux/kref.h>
     21#include <linux/minmax.h>
     22#include <linux/netdevice.h>
     23#include <linux/nl80211.h>
     24#include <linux/prandom.h>
     25#include <linux/random.h>
     26#include <linux/rculist.h>
     27#include <linux/rcupdate.h>
     28#include <linux/rtnetlink.h>
     29#include <linux/skbuff.h>
     30#include <linux/stddef.h>
     31#include <linux/string.h>
     32#include <linux/types.h>
     33#include <linux/workqueue.h>
     34#include <net/cfg80211.h>
     35#include <uapi/linux/batadv_packet.h>
     36
     37#include "bat_algo.h"
     38#include "bat_v_ogm.h"
     39#include "hard-interface.h"
     40#include "log.h"
     41#include "originator.h"
     42#include "routing.h"
     43#include "send.h"
     44
     45/**
     46 * batadv_v_elp_start_timer() - restart timer for ELP periodic work
     47 * @hard_iface: the interface for which the timer has to be reset
     48 */
     49static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
     50{
     51	unsigned int msecs;
     52
     53	msecs = atomic_read(&hard_iface->bat_v.elp_interval) - BATADV_JITTER;
     54	msecs += prandom_u32_max(2 * BATADV_JITTER);
     55
     56	queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.elp_wq,
     57			   msecs_to_jiffies(msecs));
     58}
     59
     60/**
     61 * batadv_v_elp_get_throughput() - get the throughput towards a neighbour
     62 * @neigh: the neighbour for which the throughput has to be obtained
     63 *
     64 * Return: The throughput towards the given neighbour in multiples of 100kpbs
     65 *         (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
     66 */
     67static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
     68{
     69	struct batadv_hard_iface *hard_iface = neigh->if_incoming;
     70	struct ethtool_link_ksettings link_settings;
     71	struct net_device *real_netdev;
     72	struct station_info sinfo;
     73	u32 throughput;
     74	int ret;
     75
     76	/* if the user specified a customised value for this interface, then
     77	 * return it directly
     78	 */
     79	throughput =  atomic_read(&hard_iface->bat_v.throughput_override);
     80	if (throughput != 0)
     81		return throughput;
     82
     83	/* if this is a wireless device, then ask its throughput through
     84	 * cfg80211 API
     85	 */
     86	if (batadv_is_wifi_hardif(hard_iface)) {
     87		if (!batadv_is_cfg80211_hardif(hard_iface))
     88			/* unsupported WiFi driver version */
     89			goto default_throughput;
     90
     91		real_netdev = batadv_get_real_netdev(hard_iface->net_dev);
     92		if (!real_netdev)
     93			goto default_throughput;
     94
     95		ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo);
     96
     97		if (!ret) {
     98			/* free the TID stats immediately */
     99			cfg80211_sinfo_release_content(&sinfo);
    100		}
    101
    102		dev_put(real_netdev);
    103		if (ret == -ENOENT) {
    104			/* Node is not associated anymore! It would be
    105			 * possible to delete this neighbor. For now set
    106			 * the throughput metric to 0.
    107			 */
    108			return 0;
    109		}
    110		if (ret)
    111			goto default_throughput;
    112
    113		if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))
    114			return sinfo.expected_throughput / 100;
    115
    116		/* try to estimate the expected throughput based on reported tx
    117		 * rates
    118		 */
    119		if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))
    120			return cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
    121
    122		goto default_throughput;
    123	}
    124
    125	/* if not a wifi interface, check if this device provides data via
    126	 * ethtool (e.g. an Ethernet adapter)
    127	 */
    128	memset(&link_settings, 0, sizeof(link_settings));
    129	rtnl_lock();
    130	ret = __ethtool_get_link_ksettings(hard_iface->net_dev, &link_settings);
    131	rtnl_unlock();
    132	if (ret == 0) {
    133		/* link characteristics might change over time */
    134		if (link_settings.base.duplex == DUPLEX_FULL)
    135			hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
    136		else
    137			hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
    138
    139		throughput = link_settings.base.speed;
    140		if (throughput && throughput != SPEED_UNKNOWN)
    141			return throughput * 10;
    142	}
    143
    144default_throughput:
    145	if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) {
    146		batadv_info(hard_iface->soft_iface,
    147			    "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",
    148			    hard_iface->net_dev->name,
    149			    BATADV_THROUGHPUT_DEFAULT_VALUE / 10,
    150			    BATADV_THROUGHPUT_DEFAULT_VALUE % 10);
    151		hard_iface->bat_v.flags |= BATADV_WARNING_DEFAULT;
    152	}
    153
    154	/* if none of the above cases apply, return the base_throughput */
    155	return BATADV_THROUGHPUT_DEFAULT_VALUE;
    156}
    157
    158/**
    159 * batadv_v_elp_throughput_metric_update() - worker updating the throughput
    160 *  metric of a single hop neighbour
    161 * @work: the work queue item
    162 */
    163void batadv_v_elp_throughput_metric_update(struct work_struct *work)
    164{
    165	struct batadv_hardif_neigh_node_bat_v *neigh_bat_v;
    166	struct batadv_hardif_neigh_node *neigh;
    167
    168	neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
    169				   metric_work);
    170	neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
    171			     bat_v);
    172
    173	ewma_throughput_add(&neigh->bat_v.throughput,
    174			    batadv_v_elp_get_throughput(neigh));
    175
    176	/* decrement refcounter to balance increment performed before scheduling
    177	 * this task
    178	 */
    179	batadv_hardif_neigh_put(neigh);
    180}
    181
    182/**
    183 * batadv_v_elp_wifi_neigh_probe() - send link probing packets to a neighbour
    184 * @neigh: the neighbour to probe
    185 *
    186 * Sends a predefined number of unicast wifi packets to a given neighbour in
    187 * order to trigger the throughput estimation on this link by the RC algorithm.
    188 * Packets are sent only if there is not enough payload unicast traffic towards
    189 * this neighbour..
    190 *
    191 * Return: True on success and false in case of error during skb preparation.
    192 */
    193static bool
    194batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh)
    195{
    196	struct batadv_hard_iface *hard_iface = neigh->if_incoming;
    197	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
    198	unsigned long last_tx_diff;
    199	struct sk_buff *skb;
    200	int probe_len, i;
    201	int elp_skb_len;
    202
    203	/* this probing routine is for Wifi neighbours only */
    204	if (!batadv_is_wifi_hardif(hard_iface))
    205		return true;
    206
    207	/* probe the neighbor only if no unicast packets have been sent
    208	 * to it in the last 100 milliseconds: this is the rate control
    209	 * algorithm sampling interval (minstrel). In this way, if not
    210	 * enough traffic has been sent to the neighbor, batman-adv can
    211	 * generate 2 probe packets and push the RC algorithm to perform
    212	 * the sampling
    213	 */
    214	last_tx_diff = jiffies_to_msecs(jiffies - neigh->bat_v.last_unicast_tx);
    215	if (last_tx_diff <= BATADV_ELP_PROBE_MAX_TX_DIFF)
    216		return true;
    217
    218	probe_len = max_t(int, sizeof(struct batadv_elp_packet),
    219			  BATADV_ELP_MIN_PROBE_SIZE);
    220
    221	for (i = 0; i < BATADV_ELP_PROBES_PER_NODE; i++) {
    222		elp_skb_len = hard_iface->bat_v.elp_skb->len;
    223		skb = skb_copy_expand(hard_iface->bat_v.elp_skb, 0,
    224				      probe_len - elp_skb_len,
    225				      GFP_ATOMIC);
    226		if (!skb)
    227			return false;
    228
    229		/* Tell the skb to get as big as the allocated space (we want
    230		 * the packet to be exactly of that size to make the link
    231		 * throughput estimation effective.
    232		 */
    233		skb_put_zero(skb, probe_len - hard_iface->bat_v.elp_skb->len);
    234
    235		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    236			   "Sending unicast (probe) ELP packet on interface %s to %pM\n",
    237			   hard_iface->net_dev->name, neigh->addr);
    238
    239		batadv_send_skb_packet(skb, hard_iface, neigh->addr);
    240	}
    241
    242	return true;
    243}
    244
    245/**
    246 * batadv_v_elp_periodic_work() - ELP periodic task per interface
    247 * @work: work queue item
    248 *
    249 * Emits broadcast ELP messages in regular intervals.
    250 */
    251static void batadv_v_elp_periodic_work(struct work_struct *work)
    252{
    253	struct batadv_hardif_neigh_node *hardif_neigh;
    254	struct batadv_hard_iface *hard_iface;
    255	struct batadv_hard_iface_bat_v *bat_v;
    256	struct batadv_elp_packet *elp_packet;
    257	struct batadv_priv *bat_priv;
    258	struct sk_buff *skb;
    259	u32 elp_interval;
    260	bool ret;
    261
    262	bat_v = container_of(work, struct batadv_hard_iface_bat_v, elp_wq.work);
    263	hard_iface = container_of(bat_v, struct batadv_hard_iface, bat_v);
    264	bat_priv = netdev_priv(hard_iface->soft_iface);
    265
    266	if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
    267		goto out;
    268
    269	/* we are in the process of shutting this interface down */
    270	if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
    271	    hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
    272		goto out;
    273
    274	/* the interface was enabled but may not be ready yet */
    275	if (hard_iface->if_status != BATADV_IF_ACTIVE)
    276		goto restart_timer;
    277
    278	skb = skb_copy(hard_iface->bat_v.elp_skb, GFP_ATOMIC);
    279	if (!skb)
    280		goto restart_timer;
    281
    282	elp_packet = (struct batadv_elp_packet *)skb->data;
    283	elp_packet->seqno = htonl(atomic_read(&hard_iface->bat_v.elp_seqno));
    284	elp_interval = atomic_read(&hard_iface->bat_v.elp_interval);
    285	elp_packet->elp_interval = htonl(elp_interval);
    286
    287	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    288		   "Sending broadcast ELP packet on interface %s, seqno %u\n",
    289		   hard_iface->net_dev->name,
    290		   atomic_read(&hard_iface->bat_v.elp_seqno));
    291
    292	batadv_send_broadcast_skb(skb, hard_iface);
    293
    294	atomic_inc(&hard_iface->bat_v.elp_seqno);
    295
    296	/* The throughput metric is updated on each sent packet. This way, if a
    297	 * node is dead and no longer sends packets, batman-adv is still able to
    298	 * react timely to its death.
    299	 *
    300	 * The throughput metric is updated by following these steps:
    301	 * 1) if the hard_iface is wifi => send a number of unicast ELPs for
    302	 *    probing/sampling to each neighbor
    303	 * 2) update the throughput metric value of each neighbor (note that the
    304	 *    value retrieved in this step might be 100ms old because the
    305	 *    probing packets at point 1) could still be in the HW queue)
    306	 */
    307	rcu_read_lock();
    308	hlist_for_each_entry_rcu(hardif_neigh, &hard_iface->neigh_list, list) {
    309		if (!batadv_v_elp_wifi_neigh_probe(hardif_neigh))
    310			/* if something goes wrong while probing, better to stop
    311			 * sending packets immediately and reschedule the task
    312			 */
    313			break;
    314
    315		if (!kref_get_unless_zero(&hardif_neigh->refcount))
    316			continue;
    317
    318		/* Reading the estimated throughput from cfg80211 is a task that
    319		 * may sleep and that is not allowed in an rcu protected
    320		 * context. Therefore schedule a task for that.
    321		 */
    322		ret = queue_work(batadv_event_workqueue,
    323				 &hardif_neigh->bat_v.metric_work);
    324
    325		if (!ret)
    326			batadv_hardif_neigh_put(hardif_neigh);
    327	}
    328	rcu_read_unlock();
    329
    330restart_timer:
    331	batadv_v_elp_start_timer(hard_iface);
    332out:
    333	return;
    334}
    335
    336/**
    337 * batadv_v_elp_iface_enable() - setup the ELP interface private resources
    338 * @hard_iface: interface for which the data has to be prepared
    339 *
    340 * Return: 0 on success or a -ENOMEM in case of failure.
    341 */
    342int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
    343{
    344	static const size_t tvlv_padding = sizeof(__be32);
    345	struct batadv_elp_packet *elp_packet;
    346	unsigned char *elp_buff;
    347	u32 random_seqno;
    348	size_t size;
    349	int res = -ENOMEM;
    350
    351	size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN + tvlv_padding;
    352	hard_iface->bat_v.elp_skb = dev_alloc_skb(size);
    353	if (!hard_iface->bat_v.elp_skb)
    354		goto out;
    355
    356	skb_reserve(hard_iface->bat_v.elp_skb, ETH_HLEN + NET_IP_ALIGN);
    357	elp_buff = skb_put_zero(hard_iface->bat_v.elp_skb,
    358				BATADV_ELP_HLEN + tvlv_padding);
    359	elp_packet = (struct batadv_elp_packet *)elp_buff;
    360
    361	elp_packet->packet_type = BATADV_ELP;
    362	elp_packet->version = BATADV_COMPAT_VERSION;
    363
    364	/* randomize initial seqno to avoid collision */
    365	get_random_bytes(&random_seqno, sizeof(random_seqno));
    366	atomic_set(&hard_iface->bat_v.elp_seqno, random_seqno);
    367
    368	/* assume full-duplex by default */
    369	hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
    370
    371	/* warn the user (again) if there is no throughput data is available */
    372	hard_iface->bat_v.flags &= ~BATADV_WARNING_DEFAULT;
    373
    374	if (batadv_is_wifi_hardif(hard_iface))
    375		hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
    376
    377	INIT_DELAYED_WORK(&hard_iface->bat_v.elp_wq,
    378			  batadv_v_elp_periodic_work);
    379	batadv_v_elp_start_timer(hard_iface);
    380	res = 0;
    381
    382out:
    383	return res;
    384}
    385
    386/**
    387 * batadv_v_elp_iface_disable() - release ELP interface private resources
    388 * @hard_iface: interface for which the resources have to be released
    389 */
    390void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface)
    391{
    392	cancel_delayed_work_sync(&hard_iface->bat_v.elp_wq);
    393
    394	dev_kfree_skb(hard_iface->bat_v.elp_skb);
    395	hard_iface->bat_v.elp_skb = NULL;
    396}
    397
    398/**
    399 * batadv_v_elp_iface_activate() - update the ELP buffer belonging to the given
    400 *  hard-interface
    401 * @primary_iface: the new primary interface
    402 * @hard_iface: interface holding the to-be-updated buffer
    403 */
    404void batadv_v_elp_iface_activate(struct batadv_hard_iface *primary_iface,
    405				 struct batadv_hard_iface *hard_iface)
    406{
    407	struct batadv_elp_packet *elp_packet;
    408	struct sk_buff *skb;
    409
    410	if (!hard_iface->bat_v.elp_skb)
    411		return;
    412
    413	skb = hard_iface->bat_v.elp_skb;
    414	elp_packet = (struct batadv_elp_packet *)skb->data;
    415	ether_addr_copy(elp_packet->orig,
    416			primary_iface->net_dev->dev_addr);
    417}
    418
    419/**
    420 * batadv_v_elp_primary_iface_set() - change internal data to reflect the new
    421 *  primary interface
    422 * @primary_iface: the new primary interface
    423 */
    424void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface)
    425{
    426	struct batadv_hard_iface *hard_iface;
    427
    428	/* update orig field of every elp iface belonging to this mesh */
    429	rcu_read_lock();
    430	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
    431		if (primary_iface->soft_iface != hard_iface->soft_iface)
    432			continue;
    433
    434		batadv_v_elp_iface_activate(primary_iface, hard_iface);
    435	}
    436	rcu_read_unlock();
    437}
    438
    439/**
    440 * batadv_v_elp_neigh_update() - update an ELP neighbour node
    441 * @bat_priv: the bat priv with all the soft interface information
    442 * @neigh_addr: the neighbour interface address
    443 * @if_incoming: the interface the packet was received through
    444 * @elp_packet: the received ELP packet
    445 *
    446 * Updates the ELP neighbour node state with the data received within the new
    447 * ELP packet.
    448 */
    449static void batadv_v_elp_neigh_update(struct batadv_priv *bat_priv,
    450				      u8 *neigh_addr,
    451				      struct batadv_hard_iface *if_incoming,
    452				      struct batadv_elp_packet *elp_packet)
    453
    454{
    455	struct batadv_neigh_node *neigh;
    456	struct batadv_orig_node *orig_neigh;
    457	struct batadv_hardif_neigh_node *hardif_neigh;
    458	s32 seqno_diff;
    459	s32 elp_latest_seqno;
    460
    461	orig_neigh = batadv_v_ogm_orig_get(bat_priv, elp_packet->orig);
    462	if (!orig_neigh)
    463		return;
    464
    465	neigh = batadv_neigh_node_get_or_create(orig_neigh,
    466						if_incoming, neigh_addr);
    467	if (!neigh)
    468		goto orig_free;
    469
    470	hardif_neigh = batadv_hardif_neigh_get(if_incoming, neigh_addr);
    471	if (!hardif_neigh)
    472		goto neigh_free;
    473
    474	elp_latest_seqno = hardif_neigh->bat_v.elp_latest_seqno;
    475	seqno_diff = ntohl(elp_packet->seqno) - elp_latest_seqno;
    476
    477	/* known or older sequence numbers are ignored. However always adopt
    478	 * if the router seems to have been restarted.
    479	 */
    480	if (seqno_diff < 1 && seqno_diff > -BATADV_ELP_MAX_AGE)
    481		goto hardif_free;
    482
    483	neigh->last_seen = jiffies;
    484	hardif_neigh->last_seen = jiffies;
    485	hardif_neigh->bat_v.elp_latest_seqno = ntohl(elp_packet->seqno);
    486	hardif_neigh->bat_v.elp_interval = ntohl(elp_packet->elp_interval);
    487
    488hardif_free:
    489	batadv_hardif_neigh_put(hardif_neigh);
    490neigh_free:
    491	batadv_neigh_node_put(neigh);
    492orig_free:
    493	batadv_orig_node_put(orig_neigh);
    494}
    495
    496/**
    497 * batadv_v_elp_packet_recv() - main ELP packet handler
    498 * @skb: the received packet
    499 * @if_incoming: the interface this packet was received through
    500 *
    501 * Return: NET_RX_SUCCESS and consumes the skb if the packet was properly
    502 * processed or NET_RX_DROP in case of failure.
    503 */
    504int batadv_v_elp_packet_recv(struct sk_buff *skb,
    505			     struct batadv_hard_iface *if_incoming)
    506{
    507	struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
    508	struct batadv_elp_packet *elp_packet;
    509	struct batadv_hard_iface *primary_if;
    510	struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
    511	bool res;
    512	int ret = NET_RX_DROP;
    513
    514	res = batadv_check_management_packet(skb, if_incoming, BATADV_ELP_HLEN);
    515	if (!res)
    516		goto free_skb;
    517
    518	if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
    519		goto free_skb;
    520
    521	/* did we receive a B.A.T.M.A.N. V ELP packet on an interface
    522	 * that does not have B.A.T.M.A.N. V ELP enabled ?
    523	 */
    524	if (strcmp(bat_priv->algo_ops->name, "BATMAN_V") != 0)
    525		goto free_skb;
    526
    527	elp_packet = (struct batadv_elp_packet *)skb->data;
    528
    529	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    530		   "Received ELP packet from %pM seqno %u ORIG: %pM\n",
    531		   ethhdr->h_source, ntohl(elp_packet->seqno),
    532		   elp_packet->orig);
    533
    534	primary_if = batadv_primary_if_get_selected(bat_priv);
    535	if (!primary_if)
    536		goto free_skb;
    537
    538	batadv_v_elp_neigh_update(bat_priv, ethhdr->h_source, if_incoming,
    539				  elp_packet);
    540
    541	ret = NET_RX_SUCCESS;
    542	batadv_hardif_put(primary_if);
    543
    544free_skb:
    545	if (ret == NET_RX_SUCCESS)
    546		consume_skb(skb);
    547	else
    548		kfree_skb(skb);
    549
    550	return ret;
    551}