Release 4.11 net/batman-adv/bat_iv_ogm.c
/* Copyright (C) 2007-2017 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#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/errno.h>
#include <linux/etherdevice.h>
#include <linux/fs.h>
#include <linux/if_ether.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/lockdep.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/seq_file.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/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 "packet.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
* @BATADV_NO_DUP: the packet is no duplicate
* @BATADV_ORIG_DUP: OGM is a duplicate in the originator (but not for the
* neighbor)
* @BATADV_NEIGH_DUP: OGM is a duplicate for the neighbor
* @BATADV_PROTECTED: originator is currently protected (after reboot)
*/
enum batadv_dup_status {
BATADV_NO_DUP = 0,
BATADV_ORIG_DUP,
BATADV_NEIGH_DUP,
BATADV_PROTECTED,
};
/**
* 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)
{
lq_recv[*lq_index] = value;
*lq_index = (*lq_index + 1) % BATADV_TQ_GLOBAL_WINDOW_SIZE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Antonio Quartulli | 34 | 91.89% | 1 | 50.00% |
Sven Eckelmann | 3 | 8.11% | 1 | 50.00% |
Total | 37 | 100.00% | 2 | 100.00% |
/**
* 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[])
{
const u8 *ptr;
u16 count = 0;
u16 i = 0;
u16 sum = 0;
ptr = lq_recv;
while (i < BATADV_TQ_GLOBAL_WINDOW_SIZE) {
if (*ptr != 0) {
count++;
sum += *ptr;
}
i++;
ptr++;
}
if (count == 0)
return 0;
return (u8)(sum / count);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Antonio Quartulli | 76 | 89.41% | 1 | 33.33% |
Sven Eckelmann | 7 | 8.24% | 1 | 33.33% |
Markus Pargmann | 2 | 2.35% | 1 | 33.33% |
Total | 85 | 100.00% | 3 | 100.00% |
/**
* batadv_iv_ogm_orig_free - free the private resources allocated for this
* orig_node
* @orig_node: the orig_node for which the resources have to be free'd
*/
static void batadv_iv_ogm_orig_free(struct batadv_orig_node *orig_node)
{
kfree(orig_node->bat_iv.bcast_own);
kfree(orig_node->bat_iv.bcast_own_sum);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Antonio Quartulli | 29 | 100.00% | 1 | 100.00% |
Total | 29 | 100.00% | 1 | 100.00% |
/**
* batadv_iv_ogm_orig_add_if - change the private structures of the orig_node to
* include the new hard-interface
* @orig_node: the orig_node that has to be changed
* @max_if_num: the current amount of interfaces
*
* Return: 0 on success, a negative error code otherwise.
*/
static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node,
int max_if_num)
{
void *data_ptr;
size_t old_size;
int ret = -ENOMEM;
spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
old_size = (max_if_num - 1) * sizeof(unsigned long) * BATADV_NUM_WORDS;
data_ptr = kmalloc_array(max_if_num,
BATADV_NUM_WORDS * sizeof(unsigned long),
GFP_ATOMIC);
if (!data_ptr)
goto unlock;
memcpy(data_ptr, orig_node->bat_iv.bcast_own, old_size);
kfree(orig_node->bat_iv.bcast_own);
orig_node->bat_iv.bcast_own = data_ptr;
data_ptr = kmalloc_array(max_if_num, sizeof(u8), GFP_ATOMIC);
if (!data_ptr)
goto unlock;
memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
(max_if_num - 1) * sizeof(u8));
kfree(orig_node->bat_iv.bcast_own_sum);
orig_node->bat_iv.bcast_own_sum = data_ptr;
ret = 0;
unlock:
spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Antonio Quartulli | 186 | 98.94% | 2 | 66.67% |
Sven Eckelmann | 2 | 1.06% | 1 | 33.33% |
Total | 188 | 100.00% | 3 | 100.00% |
/**
* batadv_iv_ogm_drop_bcast_own_entry - drop section of bcast_own
* @orig_node: the orig_node that has to be changed
* @max_if_num: the current amount of interfaces
* @del_if_num: the index of the interface being removed
*/
static void
batadv_iv_ogm_drop_bcast_own_entry(struct batadv_orig_node *orig_node,
int max_if_num, int del_if_num)
{
size_t chunk_size;
size_t if_offset;
void *data_ptr;
lockdep_assert_held(&orig_node->bat_iv.ogm_cnt_lock);
chunk_size = sizeof(unsigned long) * BATADV_NUM_WORDS;
data_ptr = kmalloc_array(max_if_num, chunk_size, GFP_ATOMIC);
if (!data_ptr)
/* use old buffer when new one could not be allocated */
data_ptr = orig_node->bat_iv.bcast_own;
/* copy first part */
memmove(data_ptr, orig_node->bat_iv.bcast_own, del_if_num * chunk_size);
/* copy second part */
if_offset = (del_if_num + 1) * chunk_size;
memmove((char *)data_ptr + del_if_num * chunk_size,
(uint8_t *)orig_node->bat_iv.bcast_own + if_offset,
(max_if_num - del_if_num) * chunk_size);
/* bcast_own was shrunk down in new buffer; free old one */
if (orig_node->bat_iv.bcast_own != data_ptr) {
kfree(orig_node->bat_iv.bcast_own);
orig_node->bat_iv.bcast_own = data_ptr;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Antonio Quartulli | 115 | 70.99% | 2 | 50.00% |
Sven Eckelmann | 47 | 29.01% | 2 | 50.00% |
Total | 162 | 100.00% | 4 | 100.00% |
/**
* batadv_iv_ogm_drop_bcast_own_sum_entry - drop section of bcast_own_sum
* @orig_node: the orig_node that has to be changed
* @max_if_num: the current amount of interfaces
* @del_if_num: the index of the interface being removed
*/
static void
batadv_iv_ogm_drop_bcast_own_sum_entry(struct batadv_orig_node *orig_node,
int max_if_num, int del_if_num)
{
size_t if_offset;
void *data_ptr;
lockdep_assert_held(&orig_node->bat_iv.ogm_cnt_lock);
data_ptr = kmalloc_array(max_if_num, sizeof(u8), GFP_ATOMIC);
if (!data_ptr)
/* use old buffer when new one could not be allocated */
data_ptr = orig_node->bat_iv.bcast_own_sum;
memmove(data_ptr, orig_node->bat_iv.bcast_own_sum,
del_if_num * sizeof(u8));
if_offset = (del_if_num + 1) * sizeof(u8);
memmove((char *)data_ptr + del_if_num * sizeof(u8),
orig_node->bat_iv.bcast_own_sum + if_offset,
(max_if_num - del_if_num) * sizeof(u8));
/* bcast_own_sum was shrunk down in new buffer; free old one */
if (orig_node->bat_iv.bcast_own_sum != data_ptr) {
kfree(orig_node->bat_iv.bcast_own_sum);
orig_node->bat_iv.bcast_own_sum = data_ptr;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Antonio Quartulli | 101 | 63.92% | 2 | 50.00% |
Sven Eckelmann | 57 | 36.08% | 2 | 50.00% |
Total | 158 | 100.00% | 4 | 100.00% |
/**
* batadv_iv_ogm_orig_del_if - change the private structures of the orig_node to
* exclude the removed interface
* @orig_node: the orig_node that has to be changed
* @max_if_num: the current amount of interfaces
* @del_if_num: the index of the interface being removed
*
* Return: 0 on success, a negative error code otherwise.
*/
static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node,
int max_if_num, int del_if_num)
{
spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
if (max_if_num == 0) {
kfree(orig_node->bat_iv.bcast_own);
kfree(orig_node->bat_iv.bcast_own_sum);
orig_node->bat_iv.bcast_own = NULL;
orig_node->bat_iv.bcast_own_sum = NULL;
} else {
batadv_iv_ogm_drop_bcast_own_entry(orig_node, max_if_num,
del_if_num);
batadv_iv_ogm_drop_bcast_own_sum_entry(orig_node, max_if_num,
del_if_num);
}
spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Sven Eckelmann | 88 | 85.44% | 1 | 50.00% |
Antonio Quartulli | 15 | 14.56% | 1 | 50.00% |
Total | 103 | 100.00% | 2 | 100.00% |
/**
* 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 exists it is created an initialised.
*/
static struct batadv_orig_node *
batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr)
{
struct batadv_orig_node *orig_node;
int size, hash_added;
orig_node = batadv_orig_hash_find(bat_priv, addr);
if (orig_node)
return orig_node;
orig_node = batadv_orig_node_new(bat_priv, addr);
if (!orig_node)
return NULL;
spin_lock_init(&orig_node->bat_iv.ogm_cnt_lock);
size = bat_priv->num_ifaces * sizeof(unsigned long) * BATADV_NUM_WORDS;
orig_node->bat_iv.bcast_own = kzalloc(size, GFP_ATOMIC);
if (!orig_node->bat_iv.bcast_own)
goto free_orig_node;
size = bat_priv->num_ifaces * sizeof(u8);
orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC);
if (!orig_node->bat_iv.bcast_own_sum)
goto free_orig_node;
kref_get(&orig_node->refcount);
hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
batadv_choose_orig, orig_node,
&orig_node->hash_entry);
if (hash_added != 0)
goto free_orig_node_hash;
return orig_node;
free_orig_node_hash:
batadv_orig_node_put(orig_node);
free_orig_node:
batadv_orig_node_put(orig_node);
return NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Antonio Quartulli | 183 | 90.15% | 2 | 33.33% |
Sven Eckelmann | 16 | 7.88% | 3 | 50.00% |
Simon Wunderlich | 4 | 1.97% | 1 | 16.67% |
Total | 203 | 100.00% | 6 | 100.00% |
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)
{
struct batadv_neigh_node *neigh_node;
neigh_node = batadv_neigh_node_get_or_create(orig_node,
hard_iface, neigh_addr);
if (!neigh_node)
goto out;
neigh_node->orig_node = orig_neigh;
out:
return neigh_node;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 49 | 77.78% | 3 | 37.50% |
Sven Eckelmann | 7 | 11.11% | 3 | 37.50% |
Simon Wunderlich | 6 | 9.52% | 1 | 12.50% |
Al Viro | 1 | 1.59% | 1 | 12.50% |
Total | 63 | 100.00% | 8 | 100.00% |
static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
{
struct batadv_ogm_packet *batadv_ogm_packet;
unsigned char *ogm_buff;
u32 random_seqno;
/* randomize initial seqno to avoid collision */
get_random_bytes(&random_seqno, sizeof(random_seqno));
atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
if (!ogm_buff)
return -ENOMEM;
hard_iface->bat_iv.ogm_buff = ogm_buff;
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
batadv_ogm_packet->packet_type = BATADV_IV_OGM;
batadv_ogm_packet->version = BATADV_COMPAT_VERSION;
batadv_ogm_packet->ttl = 2;
batadv_ogm_packet->flags = BATADV_NO_FLAGS;
batadv_ogm_packet->reserved = 0;
batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 109 | 81.34% | 6 | 40.00% |
Sven Eckelmann | 20 | 14.93% | 8 | 53.33% |
Markus Pargmann | 5 | 3.73% | 1 | 6.67% |
Total | 134 | 100.00% | 15 | 100.00% |
static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
{
kfree(hard_iface->bat_iv.ogm_buff);
hard_iface->bat_iv.ogm_buff = NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 26 | 92.86% | 2 | 50.00% |
Sven Eckelmann | 2 | 7.14% | 2 | 50.00% |
Total | 28 | 100.00% | 4 | 100.00% |
static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
{
struct batadv_ogm_packet *batadv_ogm_packet;
unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
ether_addr_copy(batadv_ogm_packet->orig,
hard_iface->net_dev->dev_addr);
ether_addr_copy(batadv_ogm_packet->prev_sender,
hard_iface->net_dev->dev_addr);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 52 | 83.87% | 4 | 50.00% |
Sven Eckelmann | 8 | 12.90% | 3 | 37.50% |
Antonio Quartulli | 2 | 3.23% | 1 | 12.50% |
Total | 62 | 100.00% | 8 | 100.00% |
static void
batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
{
struct batadv_ogm_packet *batadv_ogm_packet;
unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
batadv_ogm_packet->ttl = BATADV_TTL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 34 | 80.95% | 4 | 50.00% |
Sven Eckelmann | 8 | 19.05% | 4 | 50.00% |
Total | 42 | 100.00% | 8 | 100.00% |
/* 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)
{
unsigned int msecs;
msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER;
msecs += prandom_u32() % (2 * BATADV_JITTER);
return jiffies + msecs_to_jiffies(msecs);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 26 | 54.17% | 1 | 16.67% |
Sven Eckelmann | 20 | 41.67% | 3 | 50.00% |
Akinobu Mita | 2 | 4.17% | 2 | 33.33% |
Total | 48 | 100.00% | 6 | 100.00% |
/* when do we schedule a ogm packet to be sent */
static unsigned long batadv_iv_ogm_fwd_send_time(void)
{
return jiffies + msecs_to_jiffies(prandom_u32() % (BATADV_JITTER / 2));
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 21 | 87.50% | 1 | 25.00% |
Sven Eckelmann | 2 | 8.33% | 2 | 50.00% |
Akinobu Mita | 1 | 4.17% | 1 | 25.00% |
Total | 24 | 100.00% | 4 | 100.00% |
/* apply hop penalty for a normal link */
static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
{
int hop_penalty = atomic_read(&bat_priv->hop_penalty);
int new_tq;
new_tq = tq * (BATADV_TQ_MAX_VALUE - hop_penalty);
new_tq /= BATADV_TQ_MAX_VALUE;
return new_tq;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 29 | 63.04% | 1 | 20.00% |
Sven Eckelmann | 17 | 36.96% | 4 | 80.00% |
Total | 46 | 100.00% | 5 | 100.00% |
/**
* 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
* @tvlv_len: tvlv length of the previously considered OGM
*
* 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,
__be16 tvlv_len)
{
int next_buff_pos = 0;
next_buff_pos += buff_pos + BATADV_OGM_HLEN;
next_buff_pos += ntohs(tvlv_len);
return (next_buff_pos <= packet_len) &&
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 34 | 73.91% | 2 | 28.57% |
Sven Eckelmann | 11 | 23.91% | 4 | 57.14% |
Markus Pargmann | 1 | 2.17% | 1 | 14.29% |
Total | 46 | 100.00% | 7 | 100.00% |
/* 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)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
const char *fwd_str;
u8 packet_num;
s16 buff_pos;
struct batadv_ogm_packet *batadv_ogm_packet;
struct sk_buff *skb;
u8 *packet_pos;
if (hard_iface->if_status != BATADV_IF_ACTIVE)
return;
packet_num = 0;
buff_pos = 0;
packet_pos = forw_packet->skb->data;
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
/* adjust all flags and log packets */
while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
batadv_ogm_packet->tvlv_len)) {
/* we might have aggregated direct link packets with an
* ordinary base packet
*/
if (forw_packet->direct_link_flags & BIT(packet_num) &&
forw_packet->if_incoming == hard_iface)
batadv_ogm_packet->flags |= BATADV_DIRECTLINK;
else
batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK;
if (packet_num > 0 || !forw_packet->own)
fwd_str = "Forwarding";
else
fwd_str = "Sending own";
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s) on interface %s [%pM]\n",
fwd_str, (packet_num > 0 ? "aggregated " : ""),
batadv_ogm_packet->orig,
ntohl(batadv_ogm_packet->seqno),
batadv_ogm_packet->tq, batadv_ogm_packet->ttl,
((batadv_ogm_packet->flags & BATADV_DIRECTLINK) ?
"on" : "off"),
hard_iface->net_dev->name,
hard_iface->net_dev->dev_addr);
buff_pos += BATADV_OGM_HLEN;
buff_pos += ntohs(batadv_ogm_packet->tvlv_len);
packet_num++;
packet_pos = forw_packet->skb->data + buff_pos;
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
}
/* create clone because function is called more than once */
skb = skb_clone(forw_packet->skb, GFP_ATOMIC);
if (skb) {
batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_TX);
batadv_add_counter(bat_priv, BATADV_CNT_MGMT_TX_BYTES,
skb->len + ETH_HLEN);
batadv_send_broadcast_skb(skb, hard_iface);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 209 | 68.98% | 3 | 14.29% |
Sven Eckelmann | 72 | 23.76% | 15 | 71.43% |
Martin Hundeböll | 20 | 6.60% | 1 | 4.76% |
Markus Pargmann | 1 | 0.33% | 1 | 4.76% |
Antonio Quartulli | 1 | 0.33% | 1 | 4.76% |
Total | 303 | 100.00% | 21 | 100.00% |
/* send a batman ogm packet */
static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
{
struct net_device *soft_iface;
if (!forw_packet->if_incoming) {
pr_err("Error - can't forward packet: incoming iface not specified\n");
return;
}
soft_iface = forw_packet->if_incoming->soft_iface;
if (WARN_ON(!forw_packet->if_outgoing))
return;
if (WARN_ON(forw_packet->if_outgoing->soft_iface != soft_iface))
return;
if (forw_packet->if_incoming->if_status != BATADV_IF_ACTIVE)
return;
/* only for one specific outgoing interface */
batadv_iv_ogm_send_to_if(forw_packet, forw_packet->if_outgoing);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 55 | 64.71% | 2 | 28.57% |
Simon Wunderlich | 22 | 25.88% | 1 | 14.29% |
Linus Lüssing | 4 | 4.71% | 1 | 14.29% |
Sven Eckelmann | 4 | 4.71% | 3 | 42.86% |
Total | 85 | 100.00% | 7 | 100.00% |
/**
* 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)
{
struct batadv_ogm_packet *batadv_ogm_packet;
int aggregated_bytes = forw_packet->packet_len + packet_len;
struct batadv_hard_iface *primary_if = NULL;
bool res = false;
unsigned long aggregation_end_time;
batadv_ogm_packet = (struct batadv_ogm_packet *)forw_packet->skb->data;
aggregation_end_time = send_time;
aggregation_end_time += msecs_to_jiffies(BATADV_MAX_AGGREGATION_MS);
/* we can aggregate the current packet to this aggregated packet
* if:
*
* - the send time is within our MAX_AGGREGATION_MS time
* - the resulting packet wont be bigger than
* MAX_AGGREGATION_BYTES
* otherwise aggregation is not possible
*/
if (!time_before(send_time, forw_packet->send_time) ||
!time_after_eq(aggregation_end_time, forw_packet->send_time))
return false;
if (aggregated_bytes > BATADV_MAX_AGGREGATION_BYTES)
return false;
/* packet is not leaving on the same interface. */
if (forw_packet->if_outgoing != if_outgoing)
return false;
/* check aggregation compatibility
* -> direct link packets are broadcasted on
* their interface only
* -> aggregate packet if the current packet is
* a "global" packet as well as the base
* packet
*/
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
return false;
/* packets without direct link flag and high TTL
* are flooded through the net
*/
if (!directlink &&
!(batadv_ogm_packet->flags & BATADV_DIRECTLINK) &&
batadv_ogm_packet->ttl != 1 &&
/* own packets originating non-primary
* interfaces leave only that interface
*/
(!forw_packet->own ||
forw_packet->if_incoming == primary_if)) {
res = true;
goto out;
}
/* if the incoming packet is sent via this one
* interface only - we still can aggregate
*/
if (directlink &&
new_bat_ogm_packet->ttl == 1 &&
forw_packet->if_incoming == if_incoming &&
/* packets from direct neighbors or
* own secondary interface packets
* (= secondary interface packets in general)
*/
(batadv_ogm_packet->flags & BATADV_DIRECTLINK ||
(forw_packet->own &&
forw_packet->if_incoming != primary_if))) {
res = true;
goto out;
}
out:
if (primary_if)
batadv_hardif_put(primary_if);
return res;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 191 | 71.54% | 1 | 10.00% |
Sven Eckelmann | 36 | 13.48% | 7 | 70.00% |
Markus Pargmann | 34 | 12.73% | 1 | 10.00% |
Simon Wunderlich | 6 | 2.25% | 1 | 10.00% |
Total | 267 | 100.00% | 10 | 100.00% |
/**
* 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)
{
struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
struct batadv_forw_packet *forw_packet_aggr;
unsigned char *skb_buff;
unsigned int skb_size;
atomic_t *queue_left = own_packet ? NULL : &bat_priv->batman_queue_left;
forw_packet_aggr = batadv_forw_packet_alloc(if_incoming, if_outgoing,
queue_left, bat_priv);
if (!forw_packet_aggr)
return;
if (atomic_read(&bat_priv->aggregated_ogms) &&
packet_len < BATADV_MAX_AGGREGATION_BYTES)
skb_size = BATADV_MAX_AGGREGATION_BYTES;
else
skb_size = packet_len;
skb_size += ETH_HLEN;
forw_packet_aggr->skb = netdev_alloc_skb_ip_align(NULL, skb_size);
if (!forw_packet_aggr->skb) {
batadv_forw_packet_free(forw_packet_aggr, true);
return;
}
forw_packet_aggr->skb->priority = TC_PRIO_CONTROL;
skb_reserve(forw_packet_aggr->skb, ETH_HLEN);
skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
forw_packet_aggr->packet_len = packet_len;
memcpy(skb_buff, packet_buff, packet_len);
forw_packet_aggr->own = own_packet;
forw_packet_aggr->direct_link_flags = BATADV_NO_FLAGS;
forw_packet_aggr->send_time = send_time;
/* save packet direct link flag status */
if (direct_link)
forw_packet_aggr->direct_link_flags |= 1;
INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
batadv_iv_send_outstanding_bat_ogm_packet);
batadv_forw_packet_ogmv1_queue(bat_priv, forw_packet_aggr, send_time);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 172 | 71.97% | 1 | 7.69% |
Linus Lüssing | 26 | 10.88% | 2 | 15.38% |
Sven Eckelmann | 23 | 9.62% | 5 | 38.46% |
Simon Wunderlich | 13 | 5.44% | 2 | 15.38% |
Antonio Quartulli | 5 | 2.09% | 3 | 23.08% |
Total | 239 | 100.00% | 13 | 100.00% |
/* 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)
{
unsigned char *skb_buff;
unsigned long new_direct_link_flag;
skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
memcpy(skb_buff, packet_buff, packet_len);
forw_packet_aggr->packet_len += packet_len;
forw_packet_aggr->num_packets++;
/* save packet direct link flag status */
if (direct_link) {
new_direct_link_flag = BIT(forw_packet_aggr->num_packets);
forw_packet_aggr->direct_link_flags |= new_direct_link_flag;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Marek Lindner | 67 | 78.82% | 1 | 25.00% |
Sven Eckelmann | 18 | 21.18% | 3 | 75.00% |
Total | 85 | 100.00% | 4 | 100.00% |
/**
* 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)
{
/* _aggr -> pointer to the packet we want to aggregate with
* _pos -> pointer to the position in the queue
*/
struct batadv_forw_packet *forw_packet_aggr = NULL;
struct batadv_forw_packet *forw_packet_pos = NULL;
struct batadv_ogm_packet *batadv_ogm_packet;
bool direct_link;
unsigned long max_aggregation_jiffies;
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
direct_link = !!(batadv_ogm_packet->flags & BATADV_DIRECTLINK);
max_aggregation_jiffies = msecs_to_jiffies(BATADV_MAX_AGGREGATION_MS);
/* find position for the packet in the forward queue */
spin_lock_bh(&bat_priv->forw_bat_list_lock);
/* own packets are not to be aggregated */
if (atomic_read(&bat_priv->aggregated_ogms) && !own_packet) {
hlist_for_each_entry(forw_packet_pos,
&bat_priv->forw_bat_list, list) {
if (batadv_iv_ogm_can_aggregate(batadv_ogm_packet,
bat_priv, packet_len,
send_time, direct_link,
if_incoming,
if_outgoing,
forw_packet_pos)) {
forw_packet_aggr = forw_packet_pos;
break;
}
}
}
/* nothing to aggregate with - either aggregation disabled or no
* suitable aggregation packet found
*/
if (!forw_packet_aggr) {
/* the following section can run without the lock */
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
/* if we could not aggregate this packet with one of the others
* we hold it back for a while, so that it might be aggregated
* later on
*/
if (!own_packet && atomic_read(&bat_priv->aggregated_ogms))
send_time += max_aggregation_jiffies;
batadv_iv_ogm_aggregate_new(packet_buff, packet_len,
send_time, direct_link,
if_incoming, if_outgoing,