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_ogm.c (33561B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (C) B.A.T.M.A.N. contributors:
      3 *
      4 * Antonio Quartulli
      5 */
      6
      7#include "bat_v_ogm.h"
      8#include "main.h"
      9
     10#include <linux/atomic.h>
     11#include <linux/byteorder/generic.h>
     12#include <linux/container_of.h>
     13#include <linux/errno.h>
     14#include <linux/etherdevice.h>
     15#include <linux/gfp.h>
     16#include <linux/if_ether.h>
     17#include <linux/jiffies.h>
     18#include <linux/kref.h>
     19#include <linux/list.h>
     20#include <linux/lockdep.h>
     21#include <linux/minmax.h>
     22#include <linux/mutex.h>
     23#include <linux/netdevice.h>
     24#include <linux/prandom.h>
     25#include <linux/random.h>
     26#include <linux/rculist.h>
     27#include <linux/rcupdate.h>
     28#include <linux/skbuff.h>
     29#include <linux/slab.h>
     30#include <linux/spinlock.h>
     31#include <linux/stddef.h>
     32#include <linux/string.h>
     33#include <linux/types.h>
     34#include <linux/workqueue.h>
     35#include <uapi/linux/batadv_packet.h>
     36
     37#include "bat_algo.h"
     38#include "hard-interface.h"
     39#include "hash.h"
     40#include "log.h"
     41#include "originator.h"
     42#include "routing.h"
     43#include "send.h"
     44#include "translation-table.h"
     45#include "tvlv.h"
     46
     47/**
     48 * batadv_v_ogm_orig_get() - retrieve and possibly create an originator node
     49 * @bat_priv: the bat priv with all the soft interface information
     50 * @addr: the address of the originator
     51 *
     52 * Return: the orig_node corresponding to the specified address. If such an
     53 * object does not exist, it is allocated here. In case of allocation failure
     54 * returns NULL.
     55 */
     56struct batadv_orig_node *batadv_v_ogm_orig_get(struct batadv_priv *bat_priv,
     57					       const u8 *addr)
     58{
     59	struct batadv_orig_node *orig_node;
     60	int hash_added;
     61
     62	orig_node = batadv_orig_hash_find(bat_priv, addr);
     63	if (orig_node)
     64		return orig_node;
     65
     66	orig_node = batadv_orig_node_new(bat_priv, addr);
     67	if (!orig_node)
     68		return NULL;
     69
     70	kref_get(&orig_node->refcount);
     71	hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
     72				     batadv_choose_orig, orig_node,
     73				     &orig_node->hash_entry);
     74	if (hash_added != 0) {
     75		/* remove refcnt for newly created orig_node and hash entry */
     76		batadv_orig_node_put(orig_node);
     77		batadv_orig_node_put(orig_node);
     78		orig_node = NULL;
     79	}
     80
     81	return orig_node;
     82}
     83
     84/**
     85 * batadv_v_ogm_start_queue_timer() - restart the OGM aggregation timer
     86 * @hard_iface: the interface to use to send the OGM
     87 */
     88static void batadv_v_ogm_start_queue_timer(struct batadv_hard_iface *hard_iface)
     89{
     90	unsigned int msecs = BATADV_MAX_AGGREGATION_MS * 1000;
     91
     92	/* msecs * [0.9, 1.1] */
     93	msecs += prandom_u32_max(msecs / 5) - (msecs / 10);
     94	queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.aggr_wq,
     95			   msecs_to_jiffies(msecs / 1000));
     96}
     97
     98/**
     99 * batadv_v_ogm_start_timer() - restart the OGM sending timer
    100 * @bat_priv: the bat priv with all the soft interface information
    101 */
    102static void batadv_v_ogm_start_timer(struct batadv_priv *bat_priv)
    103{
    104	unsigned long msecs;
    105	/* this function may be invoked in different contexts (ogm rescheduling
    106	 * or hard_iface activation), but the work timer should not be reset
    107	 */
    108	if (delayed_work_pending(&bat_priv->bat_v.ogm_wq))
    109		return;
    110
    111	msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER;
    112	msecs += prandom_u32_max(2 * BATADV_JITTER);
    113	queue_delayed_work(batadv_event_workqueue, &bat_priv->bat_v.ogm_wq,
    114			   msecs_to_jiffies(msecs));
    115}
    116
    117/**
    118 * batadv_v_ogm_send_to_if() - send a batman ogm using a given interface
    119 * @skb: the OGM to send
    120 * @hard_iface: the interface to use to send the OGM
    121 */
    122static void batadv_v_ogm_send_to_if(struct sk_buff *skb,
    123				    struct batadv_hard_iface *hard_iface)
    124{
    125	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
    126
    127	if (hard_iface->if_status != BATADV_IF_ACTIVE)
    128		return;
    129
    130	batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_TX);
    131	batadv_add_counter(bat_priv, BATADV_CNT_MGMT_TX_BYTES,
    132			   skb->len + ETH_HLEN);
    133
    134	batadv_send_broadcast_skb(skb, hard_iface);
    135}
    136
    137/**
    138 * batadv_v_ogm_len() - OGMv2 packet length
    139 * @skb: the OGM to check
    140 *
    141 * Return: Length of the given OGMv2 packet, including tvlv length, excluding
    142 * ethernet header length.
    143 */
    144static unsigned int batadv_v_ogm_len(struct sk_buff *skb)
    145{
    146	struct batadv_ogm2_packet *ogm_packet;
    147
    148	ogm_packet = (struct batadv_ogm2_packet *)skb->data;
    149	return BATADV_OGM2_HLEN + ntohs(ogm_packet->tvlv_len);
    150}
    151
    152/**
    153 * batadv_v_ogm_queue_left() - check if given OGM still fits aggregation queue
    154 * @skb: the OGM to check
    155 * @hard_iface: the interface to use to send the OGM
    156 *
    157 * Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
    158 *
    159 * Return: True, if the given OGMv2 packet still fits, false otherwise.
    160 */
    161static bool batadv_v_ogm_queue_left(struct sk_buff *skb,
    162				    struct batadv_hard_iface *hard_iface)
    163{
    164	unsigned int max = min_t(unsigned int, hard_iface->net_dev->mtu,
    165				 BATADV_MAX_AGGREGATION_BYTES);
    166	unsigned int ogm_len = batadv_v_ogm_len(skb);
    167
    168	lockdep_assert_held(&hard_iface->bat_v.aggr_list.lock);
    169
    170	return hard_iface->bat_v.aggr_len + ogm_len <= max;
    171}
    172
    173/**
    174 * batadv_v_ogm_aggr_list_free - free all elements in an aggregation queue
    175 * @hard_iface: the interface holding the aggregation queue
    176 *
    177 * Empties the OGMv2 aggregation queue and frees all the skbs it contains.
    178 *
    179 * Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
    180 */
    181static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface)
    182{
    183	lockdep_assert_held(&hard_iface->bat_v.aggr_list.lock);
    184
    185	__skb_queue_purge(&hard_iface->bat_v.aggr_list);
    186	hard_iface->bat_v.aggr_len = 0;
    187}
    188
    189/**
    190 * batadv_v_ogm_aggr_send() - flush & send aggregation queue
    191 * @hard_iface: the interface with the aggregation queue to flush
    192 *
    193 * Aggregates all OGMv2 packets currently in the aggregation queue into a
    194 * single OGMv2 packet and transmits this aggregate.
    195 *
    196 * The aggregation queue is empty after this call.
    197 *
    198 * Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
    199 */
    200static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface)
    201{
    202	unsigned int aggr_len = hard_iface->bat_v.aggr_len;
    203	struct sk_buff *skb_aggr;
    204	unsigned int ogm_len;
    205	struct sk_buff *skb;
    206
    207	lockdep_assert_held(&hard_iface->bat_v.aggr_list.lock);
    208
    209	if (!aggr_len)
    210		return;
    211
    212	skb_aggr = dev_alloc_skb(aggr_len + ETH_HLEN + NET_IP_ALIGN);
    213	if (!skb_aggr) {
    214		batadv_v_ogm_aggr_list_free(hard_iface);
    215		return;
    216	}
    217
    218	skb_reserve(skb_aggr, ETH_HLEN + NET_IP_ALIGN);
    219	skb_reset_network_header(skb_aggr);
    220
    221	while ((skb = __skb_dequeue(&hard_iface->bat_v.aggr_list))) {
    222		hard_iface->bat_v.aggr_len -= batadv_v_ogm_len(skb);
    223
    224		ogm_len = batadv_v_ogm_len(skb);
    225		skb_put_data(skb_aggr, skb->data, ogm_len);
    226
    227		consume_skb(skb);
    228	}
    229
    230	batadv_v_ogm_send_to_if(skb_aggr, hard_iface);
    231}
    232
    233/**
    234 * batadv_v_ogm_queue_on_if() - queue a batman ogm on a given interface
    235 * @skb: the OGM to queue
    236 * @hard_iface: the interface to queue the OGM on
    237 */
    238static void batadv_v_ogm_queue_on_if(struct sk_buff *skb,
    239				     struct batadv_hard_iface *hard_iface)
    240{
    241	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
    242
    243	if (!atomic_read(&bat_priv->aggregated_ogms)) {
    244		batadv_v_ogm_send_to_if(skb, hard_iface);
    245		return;
    246	}
    247
    248	spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
    249	if (!batadv_v_ogm_queue_left(skb, hard_iface))
    250		batadv_v_ogm_aggr_send(hard_iface);
    251
    252	hard_iface->bat_v.aggr_len += batadv_v_ogm_len(skb);
    253	__skb_queue_tail(&hard_iface->bat_v.aggr_list, skb);
    254	spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock);
    255}
    256
    257/**
    258 * batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM
    259 * @bat_priv: the bat priv with all the soft interface information
    260 */
    261static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv)
    262{
    263	struct batadv_hard_iface *hard_iface;
    264	struct batadv_ogm2_packet *ogm_packet;
    265	struct sk_buff *skb, *skb_tmp;
    266	unsigned char *ogm_buff;
    267	int ogm_buff_len;
    268	u16 tvlv_len = 0;
    269	int ret;
    270
    271	lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex);
    272
    273	if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
    274		goto out;
    275
    276	ogm_buff = bat_priv->bat_v.ogm_buff;
    277	ogm_buff_len = bat_priv->bat_v.ogm_buff_len;
    278	/* tt changes have to be committed before the tvlv data is
    279	 * appended as it may alter the tt tvlv container
    280	 */
    281	batadv_tt_local_commit_changes(bat_priv);
    282	tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, &ogm_buff,
    283						    &ogm_buff_len,
    284						    BATADV_OGM2_HLEN);
    285
    286	bat_priv->bat_v.ogm_buff = ogm_buff;
    287	bat_priv->bat_v.ogm_buff_len = ogm_buff_len;
    288
    289	skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + ogm_buff_len);
    290	if (!skb)
    291		goto reschedule;
    292
    293	skb_reserve(skb, ETH_HLEN);
    294	skb_put_data(skb, ogm_buff, ogm_buff_len);
    295
    296	ogm_packet = (struct batadv_ogm2_packet *)skb->data;
    297	ogm_packet->seqno = htonl(atomic_read(&bat_priv->bat_v.ogm_seqno));
    298	atomic_inc(&bat_priv->bat_v.ogm_seqno);
    299	ogm_packet->tvlv_len = htons(tvlv_len);
    300
    301	/* broadcast on every interface */
    302	rcu_read_lock();
    303	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
    304		if (hard_iface->soft_iface != bat_priv->soft_iface)
    305			continue;
    306
    307		if (!kref_get_unless_zero(&hard_iface->refcount))
    308			continue;
    309
    310		ret = batadv_hardif_no_broadcast(hard_iface, NULL, NULL);
    311		if (ret) {
    312			char *type;
    313
    314			switch (ret) {
    315			case BATADV_HARDIF_BCAST_NORECIPIENT:
    316				type = "no neighbor";
    317				break;
    318			case BATADV_HARDIF_BCAST_DUPFWD:
    319				type = "single neighbor is source";
    320				break;
    321			case BATADV_HARDIF_BCAST_DUPORIG:
    322				type = "single neighbor is originator";
    323				break;
    324			default:
    325				type = "unknown";
    326			}
    327
    328			batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "OGM2 from ourselves on %s suppressed: %s\n",
    329				   hard_iface->net_dev->name, type);
    330
    331			batadv_hardif_put(hard_iface);
    332			continue;
    333		}
    334
    335		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    336			   "Sending own OGM2 packet (originator %pM, seqno %u, throughput %u, TTL %d) on interface %s [%pM]\n",
    337			   ogm_packet->orig, ntohl(ogm_packet->seqno),
    338			   ntohl(ogm_packet->throughput), ogm_packet->ttl,
    339			   hard_iface->net_dev->name,
    340			   hard_iface->net_dev->dev_addr);
    341
    342		/* this skb gets consumed by batadv_v_ogm_send_to_if() */
    343		skb_tmp = skb_clone(skb, GFP_ATOMIC);
    344		if (!skb_tmp) {
    345			batadv_hardif_put(hard_iface);
    346			break;
    347		}
    348
    349		batadv_v_ogm_queue_on_if(skb_tmp, hard_iface);
    350		batadv_hardif_put(hard_iface);
    351	}
    352	rcu_read_unlock();
    353
    354	consume_skb(skb);
    355
    356reschedule:
    357	batadv_v_ogm_start_timer(bat_priv);
    358out:
    359	return;
    360}
    361
    362/**
    363 * batadv_v_ogm_send() - periodic worker broadcasting the own OGM
    364 * @work: work queue item
    365 */
    366static void batadv_v_ogm_send(struct work_struct *work)
    367{
    368	struct batadv_priv_bat_v *bat_v;
    369	struct batadv_priv *bat_priv;
    370
    371	bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
    372	bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
    373
    374	mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
    375	batadv_v_ogm_send_softif(bat_priv);
    376	mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
    377}
    378
    379/**
    380 * batadv_v_ogm_aggr_work() - OGM queue periodic task per interface
    381 * @work: work queue item
    382 *
    383 * Emits aggregated OGM messages in regular intervals.
    384 */
    385void batadv_v_ogm_aggr_work(struct work_struct *work)
    386{
    387	struct batadv_hard_iface_bat_v *batv;
    388	struct batadv_hard_iface *hard_iface;
    389
    390	batv = container_of(work, struct batadv_hard_iface_bat_v, aggr_wq.work);
    391	hard_iface = container_of(batv, struct batadv_hard_iface, bat_v);
    392
    393	spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
    394	batadv_v_ogm_aggr_send(hard_iface);
    395	spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock);
    396
    397	batadv_v_ogm_start_queue_timer(hard_iface);
    398}
    399
    400/**
    401 * batadv_v_ogm_iface_enable() - prepare an interface for B.A.T.M.A.N. V
    402 * @hard_iface: the interface to prepare
    403 *
    404 * Takes care of scheduling its own OGM sending routine for this interface.
    405 *
    406 * Return: 0 on success or a negative error code otherwise
    407 */
    408int batadv_v_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
    409{
    410	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
    411
    412	batadv_v_ogm_start_queue_timer(hard_iface);
    413	batadv_v_ogm_start_timer(bat_priv);
    414
    415	return 0;
    416}
    417
    418/**
    419 * batadv_v_ogm_iface_disable() - release OGM interface private resources
    420 * @hard_iface: interface for which the resources have to be released
    421 */
    422void batadv_v_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
    423{
    424	cancel_delayed_work_sync(&hard_iface->bat_v.aggr_wq);
    425
    426	spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
    427	batadv_v_ogm_aggr_list_free(hard_iface);
    428	spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock);
    429}
    430
    431/**
    432 * batadv_v_ogm_primary_iface_set() - set a new primary interface
    433 * @primary_iface: the new primary interface
    434 */
    435void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
    436{
    437	struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface);
    438	struct batadv_ogm2_packet *ogm_packet;
    439
    440	mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
    441	if (!bat_priv->bat_v.ogm_buff)
    442		goto unlock;
    443
    444	ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff;
    445	ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
    446
    447unlock:
    448	mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
    449}
    450
    451/**
    452 * batadv_v_forward_penalty() - apply a penalty to the throughput metric
    453 *  forwarded with B.A.T.M.A.N. V OGMs
    454 * @bat_priv: the bat priv with all the soft interface information
    455 * @if_incoming: the interface where the OGM has been received
    456 * @if_outgoing: the interface where the OGM has to be forwarded to
    457 * @throughput: the current throughput
    458 *
    459 * Apply a penalty on the current throughput metric value based on the
    460 * characteristic of the interface where the OGM has been received.
    461 *
    462 * Initially the per hardif hop penalty is applied to the throughput. After
    463 * that the return value is then computed as follows:
    464 * - throughput * 50%          if the incoming and outgoing interface are the
    465 *                             same WiFi interface and the throughput is above
    466 *                             1MBit/s
    467 * - throughput                if the outgoing interface is the default
    468 *                             interface (i.e. this OGM is processed for the
    469 *                             internal table and not forwarded)
    470 * - throughput * node hop penalty  otherwise
    471 *
    472 * Return: the penalised throughput metric.
    473 */
    474static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
    475				    struct batadv_hard_iface *if_incoming,
    476				    struct batadv_hard_iface *if_outgoing,
    477				    u32 throughput)
    478{
    479	int if_hop_penalty = atomic_read(&if_incoming->hop_penalty);
    480	int hop_penalty = atomic_read(&bat_priv->hop_penalty);
    481	int hop_penalty_max = BATADV_TQ_MAX_VALUE;
    482
    483	/* Apply per hardif hop penalty */
    484	throughput = throughput * (hop_penalty_max - if_hop_penalty) /
    485		     hop_penalty_max;
    486
    487	/* Don't apply hop penalty in default originator table. */
    488	if (if_outgoing == BATADV_IF_DEFAULT)
    489		return throughput;
    490
    491	/* Forwarding on the same WiFi interface cuts the throughput in half
    492	 * due to the store & forward characteristics of WIFI.
    493	 * Very low throughput values are the exception.
    494	 */
    495	if (throughput > 10 &&
    496	    if_incoming == if_outgoing &&
    497	    !(if_incoming->bat_v.flags & BATADV_FULL_DUPLEX))
    498		return throughput / 2;
    499
    500	/* hop penalty of 255 equals 100% */
    501	return throughput * (hop_penalty_max - hop_penalty) / hop_penalty_max;
    502}
    503
    504/**
    505 * batadv_v_ogm_forward() - check conditions and forward an OGM to the given
    506 *  outgoing interface
    507 * @bat_priv: the bat priv with all the soft interface information
    508 * @ogm_received: previously received OGM to be forwarded
    509 * @orig_node: the originator which has been updated
    510 * @neigh_node: the neigh_node through with the OGM has been received
    511 * @if_incoming: the interface on which this OGM was received on
    512 * @if_outgoing: the interface to which the OGM has to be forwarded to
    513 *
    514 * Forward an OGM to an interface after having altered the throughput metric and
    515 * the TTL value contained in it. The original OGM isn't modified.
    516 */
    517static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
    518				 const struct batadv_ogm2_packet *ogm_received,
    519				 struct batadv_orig_node *orig_node,
    520				 struct batadv_neigh_node *neigh_node,
    521				 struct batadv_hard_iface *if_incoming,
    522				 struct batadv_hard_iface *if_outgoing)
    523{
    524	struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
    525	struct batadv_orig_ifinfo *orig_ifinfo = NULL;
    526	struct batadv_neigh_node *router = NULL;
    527	struct batadv_ogm2_packet *ogm_forward;
    528	unsigned char *skb_buff;
    529	struct sk_buff *skb;
    530	size_t packet_len;
    531	u16 tvlv_len;
    532
    533	/* only forward for specific interfaces, not for the default one. */
    534	if (if_outgoing == BATADV_IF_DEFAULT)
    535		goto out;
    536
    537	orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
    538	if (!orig_ifinfo)
    539		goto out;
    540
    541	/* acquire possibly updated router */
    542	router = batadv_orig_router_get(orig_node, if_outgoing);
    543
    544	/* strict rule: forward packets coming from the best next hop only */
    545	if (neigh_node != router)
    546		goto out;
    547
    548	/* don't forward the same seqno twice on one interface */
    549	if (orig_ifinfo->last_seqno_forwarded == ntohl(ogm_received->seqno))
    550		goto out;
    551
    552	orig_ifinfo->last_seqno_forwarded = ntohl(ogm_received->seqno);
    553
    554	if (ogm_received->ttl <= 1) {
    555		batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
    556		goto out;
    557	}
    558
    559	neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
    560	if (!neigh_ifinfo)
    561		goto out;
    562
    563	tvlv_len = ntohs(ogm_received->tvlv_len);
    564
    565	packet_len = BATADV_OGM2_HLEN + tvlv_len;
    566	skb = netdev_alloc_skb_ip_align(if_outgoing->net_dev,
    567					ETH_HLEN + packet_len);
    568	if (!skb)
    569		goto out;
    570
    571	skb_reserve(skb, ETH_HLEN);
    572	skb_buff = skb_put_data(skb, ogm_received, packet_len);
    573
    574	/* apply forward penalty */
    575	ogm_forward = (struct batadv_ogm2_packet *)skb_buff;
    576	ogm_forward->throughput = htonl(neigh_ifinfo->bat_v.throughput);
    577	ogm_forward->ttl--;
    578
    579	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    580		   "Forwarding OGM2 packet on %s: throughput %u, ttl %u, received via %s\n",
    581		   if_outgoing->net_dev->name, ntohl(ogm_forward->throughput),
    582		   ogm_forward->ttl, if_incoming->net_dev->name);
    583
    584	batadv_v_ogm_queue_on_if(skb, if_outgoing);
    585
    586out:
    587	batadv_orig_ifinfo_put(orig_ifinfo);
    588	batadv_neigh_node_put(router);
    589	batadv_neigh_ifinfo_put(neigh_ifinfo);
    590}
    591
    592/**
    593 * batadv_v_ogm_metric_update() - update route metric based on OGM
    594 * @bat_priv: the bat priv with all the soft interface information
    595 * @ogm2: OGM2 structure
    596 * @orig_node: Originator structure for which the OGM has been received
    597 * @neigh_node: the neigh_node through with the OGM has been received
    598 * @if_incoming: the interface where this packet was received
    599 * @if_outgoing: the interface for which the packet should be considered
    600 *
    601 * Return:
    602 *  1  if the OGM is new,
    603 *  0  if it is not new but valid,
    604 *  <0 on error (e.g. old OGM)
    605 */
    606static int batadv_v_ogm_metric_update(struct batadv_priv *bat_priv,
    607				      const struct batadv_ogm2_packet *ogm2,
    608				      struct batadv_orig_node *orig_node,
    609				      struct batadv_neigh_node *neigh_node,
    610				      struct batadv_hard_iface *if_incoming,
    611				      struct batadv_hard_iface *if_outgoing)
    612{
    613	struct batadv_orig_ifinfo *orig_ifinfo;
    614	struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
    615	bool protection_started = false;
    616	int ret = -EINVAL;
    617	u32 path_throughput;
    618	s32 seq_diff;
    619
    620	orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
    621	if (!orig_ifinfo)
    622		goto out;
    623
    624	seq_diff = ntohl(ogm2->seqno) - orig_ifinfo->last_real_seqno;
    625
    626	if (!hlist_empty(&orig_node->neigh_list) &&
    627	    batadv_window_protected(bat_priv, seq_diff,
    628				    BATADV_OGM_MAX_AGE,
    629				    &orig_ifinfo->batman_seqno_reset,
    630				    &protection_started)) {
    631		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    632			   "Drop packet: packet within window protection time from %pM\n",
    633			   ogm2->orig);
    634		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    635			   "Last reset: %ld, %ld\n",
    636			   orig_ifinfo->batman_seqno_reset, jiffies);
    637		goto out;
    638	}
    639
    640	/* drop packets with old seqnos, however accept the first packet after
    641	 * a host has been rebooted.
    642	 */
    643	if (seq_diff < 0 && !protection_started)
    644		goto out;
    645
    646	neigh_node->last_seen = jiffies;
    647
    648	orig_node->last_seen = jiffies;
    649
    650	orig_ifinfo->last_real_seqno = ntohl(ogm2->seqno);
    651	orig_ifinfo->last_ttl = ogm2->ttl;
    652
    653	neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing);
    654	if (!neigh_ifinfo)
    655		goto out;
    656
    657	path_throughput = batadv_v_forward_penalty(bat_priv, if_incoming,
    658						   if_outgoing,
    659						   ntohl(ogm2->throughput));
    660	neigh_ifinfo->bat_v.throughput = path_throughput;
    661	neigh_ifinfo->bat_v.last_seqno = ntohl(ogm2->seqno);
    662	neigh_ifinfo->last_ttl = ogm2->ttl;
    663
    664	if (seq_diff > 0 || protection_started)
    665		ret = 1;
    666	else
    667		ret = 0;
    668out:
    669	batadv_orig_ifinfo_put(orig_ifinfo);
    670	batadv_neigh_ifinfo_put(neigh_ifinfo);
    671
    672	return ret;
    673}
    674
    675/**
    676 * batadv_v_ogm_route_update() - update routes based on OGM
    677 * @bat_priv: the bat priv with all the soft interface information
    678 * @ethhdr: the Ethernet header of the OGM2
    679 * @ogm2: OGM2 structure
    680 * @orig_node: Originator structure for which the OGM has been received
    681 * @neigh_node: the neigh_node through with the OGM has been received
    682 * @if_incoming: the interface where this packet was received
    683 * @if_outgoing: the interface for which the packet should be considered
    684 *
    685 * Return: true if the packet should be forwarded, false otherwise
    686 */
    687static bool batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
    688				      const struct ethhdr *ethhdr,
    689				      const struct batadv_ogm2_packet *ogm2,
    690				      struct batadv_orig_node *orig_node,
    691				      struct batadv_neigh_node *neigh_node,
    692				      struct batadv_hard_iface *if_incoming,
    693				      struct batadv_hard_iface *if_outgoing)
    694{
    695	struct batadv_neigh_node *router = NULL;
    696	struct batadv_orig_node *orig_neigh_node;
    697	struct batadv_neigh_node *orig_neigh_router = NULL;
    698	struct batadv_neigh_ifinfo *router_ifinfo = NULL, *neigh_ifinfo = NULL;
    699	u32 router_throughput, neigh_throughput;
    700	u32 router_last_seqno;
    701	u32 neigh_last_seqno;
    702	s32 neigh_seq_diff;
    703	bool forward = false;
    704
    705	orig_neigh_node = batadv_v_ogm_orig_get(bat_priv, ethhdr->h_source);
    706	if (!orig_neigh_node)
    707		goto out;
    708
    709	orig_neigh_router = batadv_orig_router_get(orig_neigh_node,
    710						   if_outgoing);
    711
    712	/* drop packet if sender is not a direct neighbor and if we
    713	 * don't route towards it
    714	 */
    715	router = batadv_orig_router_get(orig_node, if_outgoing);
    716	if (router && router->orig_node != orig_node && !orig_neigh_router) {
    717		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    718			   "Drop packet: OGM via unknown neighbor!\n");
    719		goto out;
    720	}
    721
    722	/* Mark the OGM to be considered for forwarding, and update routes
    723	 * if needed.
    724	 */
    725	forward = true;
    726
    727	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    728		   "Searching and updating originator entry of received packet\n");
    729
    730	/* if this neighbor already is our next hop there is nothing
    731	 * to change
    732	 */
    733	if (router == neigh_node)
    734		goto out;
    735
    736	/* don't consider neighbours with worse throughput.
    737	 * also switch route if this seqno is BATADV_V_MAX_ORIGDIFF newer than
    738	 * the last received seqno from our best next hop.
    739	 */
    740	if (router) {
    741		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
    742		neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
    743
    744		/* if these are not allocated, something is wrong. */
    745		if (!router_ifinfo || !neigh_ifinfo)
    746			goto out;
    747
    748		neigh_last_seqno = neigh_ifinfo->bat_v.last_seqno;
    749		router_last_seqno = router_ifinfo->bat_v.last_seqno;
    750		neigh_seq_diff = neigh_last_seqno - router_last_seqno;
    751		router_throughput = router_ifinfo->bat_v.throughput;
    752		neigh_throughput = neigh_ifinfo->bat_v.throughput;
    753
    754		if (neigh_seq_diff < BATADV_OGM_MAX_ORIGDIFF &&
    755		    router_throughput >= neigh_throughput)
    756			goto out;
    757	}
    758
    759	batadv_update_route(bat_priv, orig_node, if_outgoing, neigh_node);
    760out:
    761	batadv_neigh_node_put(router);
    762	batadv_neigh_node_put(orig_neigh_router);
    763	batadv_orig_node_put(orig_neigh_node);
    764	batadv_neigh_ifinfo_put(router_ifinfo);
    765	batadv_neigh_ifinfo_put(neigh_ifinfo);
    766
    767	return forward;
    768}
    769
    770/**
    771 * batadv_v_ogm_process_per_outif() - process a batman v OGM for an outgoing if
    772 * @bat_priv: the bat priv with all the soft interface information
    773 * @ethhdr: the Ethernet header of the OGM2
    774 * @ogm2: OGM2 structure
    775 * @orig_node: Originator structure for which the OGM has been received
    776 * @neigh_node: the neigh_node through with the OGM has been received
    777 * @if_incoming: the interface where this packet was received
    778 * @if_outgoing: the interface for which the packet should be considered
    779 */
    780static void
    781batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
    782			       const struct ethhdr *ethhdr,
    783			       const struct batadv_ogm2_packet *ogm2,
    784			       struct batadv_orig_node *orig_node,
    785			       struct batadv_neigh_node *neigh_node,
    786			       struct batadv_hard_iface *if_incoming,
    787			       struct batadv_hard_iface *if_outgoing)
    788{
    789	int seqno_age;
    790	bool forward;
    791
    792	/* first, update the metric with according sanity checks */
    793	seqno_age = batadv_v_ogm_metric_update(bat_priv, ogm2, orig_node,
    794					       neigh_node, if_incoming,
    795					       if_outgoing);
    796
    797	/* outdated sequence numbers are to be discarded */
    798	if (seqno_age < 0)
    799		return;
    800
    801	/* only unknown & newer OGMs contain TVLVs we are interested in */
    802	if (seqno_age > 0 && if_outgoing == BATADV_IF_DEFAULT)
    803		batadv_tvlv_containers_process(bat_priv, true, orig_node,
    804					       NULL, NULL,
    805					       (unsigned char *)(ogm2 + 1),
    806					       ntohs(ogm2->tvlv_len));
    807
    808	/* if the metric update went through, update routes if needed */
    809	forward = batadv_v_ogm_route_update(bat_priv, ethhdr, ogm2, orig_node,
    810					    neigh_node, if_incoming,
    811					    if_outgoing);
    812
    813	/* if the routes have been processed correctly, check and forward */
    814	if (forward)
    815		batadv_v_ogm_forward(bat_priv, ogm2, orig_node, neigh_node,
    816				     if_incoming, if_outgoing);
    817}
    818
    819/**
    820 * batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated
    821 * @buff_pos: current position in the skb
    822 * @packet_len: total length of the skb
    823 * @ogm2_packet: potential OGM2 in buffer
    824 *
    825 * Return: true if there is enough space for another OGM, false otherwise.
    826 */
    827static bool
    828batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
    829			 const struct batadv_ogm2_packet *ogm2_packet)
    830{
    831	int next_buff_pos = 0;
    832
    833	/* check if there is enough space for the header */
    834	next_buff_pos += buff_pos + sizeof(*ogm2_packet);
    835	if (next_buff_pos > packet_len)
    836		return false;
    837
    838	/* check if there is enough space for the optional TVLV */
    839	next_buff_pos += ntohs(ogm2_packet->tvlv_len);
    840
    841	return (next_buff_pos <= packet_len) &&
    842	       (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
    843}
    844
    845/**
    846 * batadv_v_ogm_process() - process an incoming batman v OGM
    847 * @skb: the skb containing the OGM
    848 * @ogm_offset: offset to the OGM which should be processed (for aggregates)
    849 * @if_incoming: the interface where this packet was received
    850 */
    851static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
    852				 struct batadv_hard_iface *if_incoming)
    853{
    854	struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
    855	struct ethhdr *ethhdr;
    856	struct batadv_orig_node *orig_node = NULL;
    857	struct batadv_hardif_neigh_node *hardif_neigh = NULL;
    858	struct batadv_neigh_node *neigh_node = NULL;
    859	struct batadv_hard_iface *hard_iface;
    860	struct batadv_ogm2_packet *ogm_packet;
    861	u32 ogm_throughput, link_throughput, path_throughput;
    862	int ret;
    863
    864	ethhdr = eth_hdr(skb);
    865	ogm_packet = (struct batadv_ogm2_packet *)(skb->data + ogm_offset);
    866
    867	ogm_throughput = ntohl(ogm_packet->throughput);
    868
    869	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    870		   "Received OGM2 packet via NB: %pM, IF: %s [%pM] (from OG: %pM, seqno %u, throughput %u, TTL %u, V %u, tvlv_len %u)\n",
    871		   ethhdr->h_source, if_incoming->net_dev->name,
    872		   if_incoming->net_dev->dev_addr, ogm_packet->orig,
    873		   ntohl(ogm_packet->seqno), ogm_throughput, ogm_packet->ttl,
    874		   ogm_packet->version, ntohs(ogm_packet->tvlv_len));
    875
    876	if (batadv_is_my_mac(bat_priv, ogm_packet->orig)) {
    877		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    878			   "Drop packet: originator packet from ourself\n");
    879		return;
    880	}
    881
    882	/* If the throughput metric is 0, immediately drop the packet. No need
    883	 * to create orig_node / neigh_node for an unusable route.
    884	 */
    885	if (ogm_throughput == 0) {
    886		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    887			   "Drop packet: originator packet with throughput metric of 0\n");
    888		return;
    889	}
    890
    891	/* require ELP packets be to received from this neighbor first */
    892	hardif_neigh = batadv_hardif_neigh_get(if_incoming, ethhdr->h_source);
    893	if (!hardif_neigh) {
    894		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
    895			   "Drop packet: OGM via unknown neighbor!\n");
    896		goto out;
    897	}
    898
    899	orig_node = batadv_v_ogm_orig_get(bat_priv, ogm_packet->orig);
    900	if (!orig_node)
    901		goto out;
    902
    903	neigh_node = batadv_neigh_node_get_or_create(orig_node, if_incoming,
    904						     ethhdr->h_source);
    905	if (!neigh_node)
    906		goto out;
    907
    908	/* Update the received throughput metric to match the link
    909	 * characteristic:
    910	 *  - If this OGM traveled one hop so far (emitted by single hop
    911	 *    neighbor) the path throughput metric equals the link throughput.
    912	 *  - For OGMs traversing more than hop the path throughput metric is
    913	 *    the smaller of the path throughput and the link throughput.
    914	 */
    915	link_throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
    916	path_throughput = min_t(u32, link_throughput, ogm_throughput);
    917	ogm_packet->throughput = htonl(path_throughput);
    918
    919	batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet, orig_node,
    920				       neigh_node, if_incoming,
    921				       BATADV_IF_DEFAULT);
    922
    923	rcu_read_lock();
    924	list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
    925		if (hard_iface->if_status != BATADV_IF_ACTIVE)
    926			continue;
    927
    928		if (hard_iface->soft_iface != bat_priv->soft_iface)
    929			continue;
    930
    931		if (!kref_get_unless_zero(&hard_iface->refcount))
    932			continue;
    933
    934		ret = batadv_hardif_no_broadcast(hard_iface,
    935						 ogm_packet->orig,
    936						 hardif_neigh->orig);
    937
    938		if (ret) {
    939			char *type;
    940
    941			switch (ret) {
    942			case BATADV_HARDIF_BCAST_NORECIPIENT:
    943				type = "no neighbor";
    944				break;
    945			case BATADV_HARDIF_BCAST_DUPFWD:
    946				type = "single neighbor is source";
    947				break;
    948			case BATADV_HARDIF_BCAST_DUPORIG:
    949				type = "single neighbor is originator";
    950				break;
    951			default:
    952				type = "unknown";
    953			}
    954
    955			batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "OGM2 packet from %pM on %s suppressed: %s\n",
    956				   ogm_packet->orig, hard_iface->net_dev->name,
    957				   type);
    958
    959			batadv_hardif_put(hard_iface);
    960			continue;
    961		}
    962
    963		batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet,
    964					       orig_node, neigh_node,
    965					       if_incoming, hard_iface);
    966
    967		batadv_hardif_put(hard_iface);
    968	}
    969	rcu_read_unlock();
    970out:
    971	batadv_orig_node_put(orig_node);
    972	batadv_neigh_node_put(neigh_node);
    973	batadv_hardif_neigh_put(hardif_neigh);
    974}
    975
    976/**
    977 * batadv_v_ogm_packet_recv() - OGM2 receiving handler
    978 * @skb: the received OGM
    979 * @if_incoming: the interface where this OGM has been received
    980 *
    981 * Return: NET_RX_SUCCESS and consume the skb on success or returns NET_RX_DROP
    982 * (without freeing the skb) on failure
    983 */
    984int batadv_v_ogm_packet_recv(struct sk_buff *skb,
    985			     struct batadv_hard_iface *if_incoming)
    986{
    987	struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
    988	struct batadv_ogm2_packet *ogm_packet;
    989	struct ethhdr *ethhdr = eth_hdr(skb);
    990	int ogm_offset;
    991	u8 *packet_pos;
    992	int ret = NET_RX_DROP;
    993
    994	/* did we receive a OGM2 packet on an interface that does not have
    995	 * B.A.T.M.A.N. V enabled ?
    996	 */
    997	if (strcmp(bat_priv->algo_ops->name, "BATMAN_V") != 0)
    998		goto free_skb;
    999
   1000	if (!batadv_check_management_packet(skb, if_incoming, BATADV_OGM2_HLEN))
   1001		goto free_skb;
   1002
   1003	if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
   1004		goto free_skb;
   1005
   1006	batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX);
   1007	batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES,
   1008			   skb->len + ETH_HLEN);
   1009
   1010	ogm_offset = 0;
   1011	ogm_packet = (struct batadv_ogm2_packet *)skb->data;
   1012
   1013	while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
   1014					ogm_packet)) {
   1015		batadv_v_ogm_process(skb, ogm_offset, if_incoming);
   1016
   1017		ogm_offset += BATADV_OGM2_HLEN;
   1018		ogm_offset += ntohs(ogm_packet->tvlv_len);
   1019
   1020		packet_pos = skb->data + ogm_offset;
   1021		ogm_packet = (struct batadv_ogm2_packet *)packet_pos;
   1022	}
   1023
   1024	ret = NET_RX_SUCCESS;
   1025
   1026free_skb:
   1027	if (ret == NET_RX_SUCCESS)
   1028		consume_skb(skb);
   1029	else
   1030		kfree_skb(skb);
   1031
   1032	return ret;
   1033}
   1034
   1035/**
   1036 * batadv_v_ogm_init() - initialise the OGM2 engine
   1037 * @bat_priv: the bat priv with all the soft interface information
   1038 *
   1039 * Return: 0 on success or a negative error code in case of failure
   1040 */
   1041int batadv_v_ogm_init(struct batadv_priv *bat_priv)
   1042{
   1043	struct batadv_ogm2_packet *ogm_packet;
   1044	unsigned char *ogm_buff;
   1045	u32 random_seqno;
   1046
   1047	bat_priv->bat_v.ogm_buff_len = BATADV_OGM2_HLEN;
   1048	ogm_buff = kzalloc(bat_priv->bat_v.ogm_buff_len, GFP_ATOMIC);
   1049	if (!ogm_buff)
   1050		return -ENOMEM;
   1051
   1052	bat_priv->bat_v.ogm_buff = ogm_buff;
   1053	ogm_packet = (struct batadv_ogm2_packet *)ogm_buff;
   1054	ogm_packet->packet_type = BATADV_OGM2;
   1055	ogm_packet->version = BATADV_COMPAT_VERSION;
   1056	ogm_packet->ttl = BATADV_TTL;
   1057	ogm_packet->flags = BATADV_NO_FLAGS;
   1058	ogm_packet->throughput = htonl(BATADV_THROUGHPUT_MAX_VALUE);
   1059
   1060	/* randomize initial seqno to avoid collision */
   1061	get_random_bytes(&random_seqno, sizeof(random_seqno));
   1062	atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno);
   1063	INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send);
   1064
   1065	mutex_init(&bat_priv->bat_v.ogm_buff_mutex);
   1066
   1067	return 0;
   1068}
   1069
   1070/**
   1071 * batadv_v_ogm_free() - free OGM private resources
   1072 * @bat_priv: the bat priv with all the soft interface information
   1073 */
   1074void batadv_v_ogm_free(struct batadv_priv *bat_priv)
   1075{
   1076	cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq);
   1077
   1078	mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
   1079
   1080	kfree(bat_priv->bat_v.ogm_buff);
   1081	bat_priv->bat_v.ogm_buff = NULL;
   1082	bat_priv->bat_v.ogm_buff_len = 0;
   1083
   1084	mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
   1085}