linux/net/batman-adv/bat_iv_ogm.c

// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) B.A.T.M.A.N. contributors:
 *
 * Marek Lindner, Simon Wunderlich
 */

#include "bat_iv_ogm.h"
#include "main.h"

#include <linux/atomic.h>
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/cache.h>
#include <linux/container_of.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
#include <linux/gfp.h>
#include <linux/if_ether.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/netlink.h>
#include <linux/pkt_sched.h>
#include <linux/printk.h>
#include <linux/random.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include <net/genetlink.h>
#include <net/netlink.h>
#include <uapi/linux/batadv_packet.h>
#include <uapi/linux/batman_adv.h>

#include "bat_algo.h"
#include "bitarray.h"
#include "gateway_client.h"
#include "hard-interface.h"
#include "hash.h"
#include "log.h"
#include "netlink.h"
#include "network-coding.h"
#include "originator.h"
#include "routing.h"
#include "send.h"
#include "translation-table.h"
#include "tvlv.h"

static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work);

/**
 * enum batadv_dup_status - duplicate status
 */
enum batadv_dup_status {};

/**
 * batadv_ring_buffer_set() - update the ring buffer with the given value
 * @lq_recv: pointer to the ring buffer
 * @lq_index: index to store the value at
 * @value: value to store in the ring buffer
 */
static void batadv_ring_buffer_set(u8 lq_recv[], u8 *lq_index, u8 value)
{}

/**
 * batadv_ring_buffer_avg() - compute the average of all non-zero values stored
 * in the given ring buffer
 * @lq_recv: pointer to the ring buffer
 *
 * Return: computed average value.
 */
static u8 batadv_ring_buffer_avg(const u8 lq_recv[])
{}

/**
 * batadv_iv_ogm_orig_get() - retrieve or create (if does not exist) an
 *  originator
 * @bat_priv: the bat priv with all the soft interface information
 * @addr: mac address of the originator
 *
 * Return: the originator object corresponding to the passed mac address or NULL
 * on failure.
 * If the object does not exist, it is created and initialised.
 */
static struct batadv_orig_node *
batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr)
{}

static struct batadv_neigh_node *
batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
			const u8 *neigh_addr,
			struct batadv_orig_node *orig_node,
			struct batadv_orig_node *orig_neigh)
{}

static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
{}

static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
{}

static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
{}

static void
batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
{}

/* when do we schedule our own ogm to be sent */
static unsigned long
batadv_iv_ogm_emit_send_time(const struct batadv_priv *bat_priv)
{}

/* when do we schedule a ogm packet to be sent */
static unsigned long batadv_iv_ogm_fwd_send_time(void)
{}

/* apply hop penalty for a normal link */
static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
{}

/**
 * batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached
 * @buff_pos: current position in the skb
 * @packet_len: total length of the skb
 * @ogm_packet: potential OGM in buffer
 *
 * Return: true if there is enough space for another OGM, false otherwise.
 */
static bool
batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
			  const struct batadv_ogm_packet *ogm_packet)
{}

/* send a batman ogm to a given interface */
static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
				     struct batadv_hard_iface *hard_iface)
{}

/* send a batman ogm packet */
static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
{}

/**
 * batadv_iv_ogm_can_aggregate() - find out if an OGM can be aggregated on an
 *  existing forward packet
 * @new_bat_ogm_packet: OGM packet to be aggregated
 * @bat_priv: the bat priv with all the soft interface information
 * @packet_len: (total) length of the OGM
 * @send_time: timestamp (jiffies) when the packet is to be sent
 * @directlink: true if this is a direct link packet
 * @if_incoming: interface where the packet was received
 * @if_outgoing: interface for which the retransmission should be considered
 * @forw_packet: the forwarded packet which should be checked
 *
 * Return: true if new_packet can be aggregated with forw_packet
 */
static bool
batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
			    struct batadv_priv *bat_priv,
			    int packet_len, unsigned long send_time,
			    bool directlink,
			    const struct batadv_hard_iface *if_incoming,
			    const struct batadv_hard_iface *if_outgoing,
			    const struct batadv_forw_packet *forw_packet)
{}

/**
 * batadv_iv_ogm_aggregate_new() - create a new aggregated packet and add this
 *  packet to it.
 * @packet_buff: pointer to the OGM
 * @packet_len: (total) length of the OGM
 * @send_time: timestamp (jiffies) when the packet is to be sent
 * @direct_link: whether this OGM has direct link status
 * @if_incoming: interface where the packet was received
 * @if_outgoing: interface for which the retransmission should be considered
 * @own_packet: true if it is a self-generated ogm
 */
static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
					int packet_len, unsigned long send_time,
					bool direct_link,
					struct batadv_hard_iface *if_incoming,
					struct batadv_hard_iface *if_outgoing,
					int own_packet)
{}

/* aggregate a new packet into the existing ogm packet */
static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr,
				    const unsigned char *packet_buff,
				    int packet_len, bool direct_link)
{}

/**
 * batadv_iv_ogm_queue_add() - queue up an OGM for transmission
 * @bat_priv: the bat priv with all the soft interface information
 * @packet_buff: pointer to the OGM
 * @packet_len: (total) length of the OGM
 * @if_incoming: interface where the packet was received
 * @if_outgoing: interface for which the retransmission should be considered
 * @own_packet: true if it is a self-generated ogm
 * @send_time: timestamp (jiffies) when the packet is to be sent
 */
static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
				    unsigned char *packet_buff,
				    int packet_len,
				    struct batadv_hard_iface *if_incoming,
				    struct batadv_hard_iface *if_outgoing,
				    int own_packet, unsigned long send_time)
{}

static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
				  const struct ethhdr *ethhdr,
				  struct batadv_ogm_packet *batadv_ogm_packet,
				  bool is_single_hop_neigh,
				  bool is_from_best_next_hop,
				  struct batadv_hard_iface *if_incoming,
				  struct batadv_hard_iface *if_outgoing)
{}

/**
 * batadv_iv_ogm_slide_own_bcast_window() - bitshift own OGM broadcast windows
 *  for the given interface
 * @hard_iface: the interface for which the windows have to be shifted
 */
static void
batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
{}

/**
 * batadv_iv_ogm_schedule_buff() - schedule submission of hardif ogm buffer
 * @hard_iface: interface whose ogm buffer should be transmitted
 */
static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
{}

static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
{}

/**
 * batadv_iv_orig_ifinfo_sum() - Get bcast_own sum for originator over interface
 * @orig_node: originator which reproadcasted the OGMs directly
 * @if_outgoing: interface which transmitted the original OGM and received the
 *  direct rebroadcast
 *
 * Return: Number of replied (rebroadcasted) OGMs which were transmitted by
 *  an originator and directly (without intermediate hop) received by a specific
 *  interface
 */
static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
				    struct batadv_hard_iface *if_outgoing)
{}

/**
 * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
 *  originator
 * @bat_priv: the bat priv with all the soft interface information
 * @orig_node: the orig node who originally emitted the ogm packet
 * @orig_ifinfo: ifinfo for the outgoing interface of the orig_node
 * @ethhdr: Ethernet header of the OGM
 * @batadv_ogm_packet: the ogm packet
 * @if_incoming: interface where the packet was received
 * @if_outgoing: interface for which the retransmission should be considered
 * @dup_status: the duplicate status of this ogm packet.
 */
static void
batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
			  struct batadv_orig_node *orig_node,
			  struct batadv_orig_ifinfo *orig_ifinfo,
			  const struct ethhdr *ethhdr,
			  const struct batadv_ogm_packet *batadv_ogm_packet,
			  struct batadv_hard_iface *if_incoming,
			  struct batadv_hard_iface *if_outgoing,
			  enum batadv_dup_status dup_status)
{}

/**
 * batadv_iv_ogm_calc_tq() - calculate tq for current received ogm packet
 * @orig_node: the orig node who originally emitted the ogm packet
 * @orig_neigh_node: the orig node struct of the neighbor who sent the packet
 * @batadv_ogm_packet: the ogm packet
 * @if_incoming: interface where the packet was received
 * @if_outgoing: interface for which the retransmission should be considered
 *
 * Return: true if the link can be considered bidirectional, false otherwise
 */
static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
				  struct batadv_orig_node *orig_neigh_node,
				  struct batadv_ogm_packet *batadv_ogm_packet,
				  struct batadv_hard_iface *if_incoming,
				  struct batadv_hard_iface *if_outgoing)
{}

/**
 * batadv_iv_ogm_update_seqnos() -  process a batman packet for all interfaces,
 *  adjust the sequence number and find out whether it is a duplicate
 * @ethhdr: ethernet header of the packet
 * @batadv_ogm_packet: OGM packet to be considered
 * @if_incoming: interface on which the OGM packet was received
 * @if_outgoing: interface for which the retransmission should be considered
 *
 * Return: duplicate status as enum batadv_dup_status
 */
static enum batadv_dup_status
batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
			    const struct batadv_ogm_packet *batadv_ogm_packet,
			    const struct batadv_hard_iface *if_incoming,
			    struct batadv_hard_iface *if_outgoing)
{}

/**
 * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
 *  interface
 * @skb: the skb containing the OGM
 * @ogm_offset: offset from skb->data to start of ogm header
 * @orig_node: the (cached) orig node for the originator of this OGM
 * @if_incoming: the interface where this packet was received
 * @if_outgoing: the interface for which the packet should be considered
 */
static void
batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
				struct batadv_orig_node *orig_node,
				struct batadv_hard_iface *if_incoming,
				struct batadv_hard_iface *if_outgoing)
{}

/**
 * batadv_iv_ogm_process_reply() - Check OGM for direct reply and process it
 * @ogm_packet: rebroadcast OGM packet to process
 * @if_incoming: the interface where this packet was received
 * @orig_node: originator which reproadcasted the OGMs
 * @if_incoming_seqno: OGM sequence number when rebroadcast was received
 */
static void batadv_iv_ogm_process_reply(struct batadv_ogm_packet *ogm_packet,
					struct batadv_hard_iface *if_incoming,
					struct batadv_orig_node *orig_node,
					u32 if_incoming_seqno)
{}

/**
 * batadv_iv_ogm_process() - process an incoming batman iv OGM
 * @skb: the skb containing the OGM
 * @ogm_offset: offset to the OGM which should be processed (for aggregates)
 * @if_incoming: the interface where this packet was received
 */
static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
				  struct batadv_hard_iface *if_incoming)
{}

static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work)
{}

static int batadv_iv_ogm_receive(struct sk_buff *skb,
				 struct batadv_hard_iface *if_incoming)
{}

/**
 * batadv_iv_ogm_neigh_get_tq_avg() - Get the TQ average for a neighbour on a
 *  given outgoing interface.
 * @neigh_node: Neighbour of interest
 * @if_outgoing: Outgoing interface of interest
 * @tq_avg: Pointer of where to store the TQ average
 *
 * Return: False if no average TQ available, otherwise true.
 */
static bool
batadv_iv_ogm_neigh_get_tq_avg(struct batadv_neigh_node *neigh_node,
			       struct batadv_hard_iface *if_outgoing,
			       u8 *tq_avg)
{}

/**
 * batadv_iv_ogm_orig_dump_subentry() - Dump an originator subentry into a
 *  message
 * @msg: Netlink message to dump into
 * @portid: Port making netlink request
 * @seq: Sequence number of netlink message
 * @bat_priv: The bat priv with all the soft interface information
 * @if_outgoing: Limit dump to entries with this outgoing interface
 * @orig_node: Originator to dump
 * @neigh_node: Single hops neighbour
 * @best: Is the best originator
 *
 * Return: Error code, or 0 on success
 */
static int
batadv_iv_ogm_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
				 struct batadv_priv *bat_priv,
				 struct batadv_hard_iface *if_outgoing,
				 struct batadv_orig_node *orig_node,
				 struct batadv_neigh_node *neigh_node,
				 bool best)
{}

/**
 * batadv_iv_ogm_orig_dump_entry() - Dump an originator entry into a message
 * @msg: Netlink message to dump into
 * @portid: Port making netlink request
 * @seq: Sequence number of netlink message
 * @bat_priv: The bat priv with all the soft interface information
 * @if_outgoing: Limit dump to entries with this outgoing interface
 * @orig_node: Originator to dump
 * @sub_s: Number of sub entries to skip
 *
 * This function assumes the caller holds rcu_read_lock().
 *
 * Return: Error code, or 0 on success
 */
static int
batadv_iv_ogm_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
			      struct batadv_priv *bat_priv,
			      struct batadv_hard_iface *if_outgoing,
			      struct batadv_orig_node *orig_node, int *sub_s)
{}

/**
 * batadv_iv_ogm_orig_dump_bucket() - Dump an originator bucket into a
 *  message
 * @msg: Netlink message to dump into
 * @portid: Port making netlink request
 * @seq: Sequence number of netlink message
 * @bat_priv: The bat priv with all the soft interface information
 * @if_outgoing: Limit dump to entries with this outgoing interface
 * @head: Bucket to be dumped
 * @idx_s: Number of entries to be skipped
 * @sub: Number of sub entries to be skipped
 *
 * Return: Error code, or 0 on success
 */
static int
batadv_iv_ogm_orig_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
			       struct batadv_priv *bat_priv,
			       struct batadv_hard_iface *if_outgoing,
			       struct hlist_head *head, int *idx_s, int *sub)
{}

/**
 * batadv_iv_ogm_orig_dump() - Dump the originators into a message
 * @msg: Netlink message to dump into
 * @cb: Control block containing additional options
 * @bat_priv: The bat priv with all the soft interface information
 * @if_outgoing: Limit dump to entries with this outgoing interface
 */
static void
batadv_iv_ogm_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
			struct batadv_priv *bat_priv,
			struct batadv_hard_iface *if_outgoing)
{}

/**
 * batadv_iv_ogm_neigh_diff() - calculate tq difference of two neighbors
 * @neigh1: the first neighbor object of the comparison
 * @if_outgoing1: outgoing interface for the first neighbor
 * @neigh2: the second neighbor object of the comparison
 * @if_outgoing2: outgoing interface for the second neighbor
 * @diff: pointer to integer receiving the calculated difference
 *
 * The content of *@diff is only valid when this function returns true.
 * It is less, equal to or greater than 0 if the metric via neigh1 is lower,
 * the same as or higher than the metric via neigh2
 *
 * Return: true when the difference could be calculated, false otherwise
 */
static bool batadv_iv_ogm_neigh_diff(struct batadv_neigh_node *neigh1,
				     struct batadv_hard_iface *if_outgoing1,
				     struct batadv_neigh_node *neigh2,
				     struct batadv_hard_iface *if_outgoing2,
				     int *diff)
{}

/**
 * batadv_iv_ogm_neigh_dump_neigh() - Dump a neighbour into a netlink message
 * @msg: Netlink message to dump into
 * @portid: Port making netlink request
 * @seq: Sequence number of netlink message
 * @hardif_neigh: Neighbour to be dumped
 *
 * Return: Error code, or 0 on success
 */
static int
batadv_iv_ogm_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
			       struct batadv_hardif_neigh_node *hardif_neigh)
{}

/**
 * batadv_iv_ogm_neigh_dump_hardif() - Dump the neighbours of a hard interface
 *  into a message
 * @msg: Netlink message to dump into
 * @portid: Port making netlink request
 * @seq: Sequence number of netlink message
 * @bat_priv: The bat priv with all the soft interface information
 * @hard_iface: Hard interface to dump the neighbours for
 * @idx_s: Number of entries to skip
 *
 * This function assumes the caller holds rcu_read_lock().
 *
 * Return: Error code, or 0 on success
 */
static int
batadv_iv_ogm_neigh_dump_hardif(struct sk_buff *msg, u32 portid, u32 seq,
				struct batadv_priv *bat_priv,
				struct batadv_hard_iface *hard_iface,
				int *idx_s)
{}

/**
 * batadv_iv_ogm_neigh_dump() - Dump the neighbours into a message
 * @msg: Netlink message to dump into
 * @cb: Control block containing additional options
 * @bat_priv: The bat priv with all the soft interface information
 * @single_hardif: Limit dump to this hard interface
 */
static void
batadv_iv_ogm_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
			 struct batadv_priv *bat_priv,
			 struct batadv_hard_iface *single_hardif)
{}

/**
 * batadv_iv_ogm_neigh_cmp() - compare the metrics of two neighbors
 * @neigh1: the first neighbor object of the comparison
 * @if_outgoing1: outgoing interface for the first neighbor
 * @neigh2: the second neighbor object of the comparison
 * @if_outgoing2: outgoing interface for the second neighbor
 *
 * Return: a value less, equal to or greater than 0 if the metric via neigh1 is
 * lower, the same as or higher than the metric via neigh2
 */
static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1,
				   struct batadv_hard_iface *if_outgoing1,
				   struct batadv_neigh_node *neigh2,
				   struct batadv_hard_iface *if_outgoing2)
{}

/**
 * batadv_iv_ogm_neigh_is_sob() - check if neigh1 is similarly good or better
 *  than neigh2 from the metric prospective
 * @neigh1: the first neighbor object of the comparison
 * @if_outgoing1: outgoing interface for the first neighbor
 * @neigh2: the second neighbor object of the comparison
 * @if_outgoing2: outgoing interface for the second neighbor
 *
 * Return: true if the metric via neigh1 is equally good or better than
 * the metric via neigh2, false otherwise.
 */
static bool
batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1,
			   struct batadv_hard_iface *if_outgoing1,
			   struct batadv_neigh_node *neigh2,
			   struct batadv_hard_iface *if_outgoing2)
{}

static void batadv_iv_iface_enabled(struct batadv_hard_iface *hard_iface)
{}

/**
 * batadv_iv_init_sel_class() - initialize GW selection class
 * @bat_priv: the bat priv with all the soft interface information
 */
static void batadv_iv_init_sel_class(struct batadv_priv *bat_priv)
{}

static struct batadv_gw_node *
batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
{}

static bool batadv_iv_gw_is_eligible(struct batadv_priv *bat_priv,
				     struct batadv_orig_node *curr_gw_orig,
				     struct batadv_orig_node *orig_node)
{}

/**
 * batadv_iv_gw_dump_entry() - Dump a gateway into a message
 * @msg: Netlink message to dump into
 * @portid: Port making netlink request
 * @cb: Control block containing additional options
 * @bat_priv: The bat priv with all the soft interface information
 * @gw_node: Gateway to be dumped
 *
 * Return: Error code, or 0 on success
 */
static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid,
				   struct netlink_callback *cb,
				   struct batadv_priv *bat_priv,
				   struct batadv_gw_node *gw_node)
{}

/**
 * batadv_iv_gw_dump() - Dump gateways into a message
 * @msg: Netlink message to dump into
 * @cb: Control block containing additional options
 * @bat_priv: The bat priv with all the soft interface information
 */
static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
			      struct batadv_priv *bat_priv)
{}

static struct batadv_algo_ops batadv_batman_iv __read_mostly =;

/**
 * batadv_iv_init() - B.A.T.M.A.N. IV initialization function
 *
 * Return: 0 on success or negative error number in case of failure
 */
int __init batadv_iv_init(void)
{}