Commit 3ea00443 authored by David S. Miller's avatar David S. Miller

Merge tag 'batadv-next-for-davem-20160701' of git://git.open-mesh.org/linux-merge

Simon Wunderlich says:

====================
This feature patchset includes the following changes:

 - two patches with minimal clean up work by Antonio Quartulli and
   Simon Wunderlich

 - eight patches of B.A.T.M.A.N. V, API and documentation clean
   up work, by Antonio Quartulli and Marek Lindner

 - Andrew Lunn fixed the skb priority adoption when forwarding
   fragmented packets (two patches)

 - Multicast optimization support is now enabled for bridges which
   comes with some protocol updates, by Linus Luessing
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ca9354a1 4e3e823b
What: /sys/class/net/<iface>/batman-adv/throughput_override
Date: Feb 2014
Contact: Antonio Quartulli <antonio@meshcoding.com>
description:
Defines the throughput value to be used by B.A.T.M.A.N. V
when estimating the link throughput using this interface.
If the value is set to 0 then batman-adv will try to
estimate the throughput by itself.
What: /sys/class/net/<iface>/batman-adv/elp_interval
Date: Feb 2014
Contact: Linus Lüssing <linus.luessing@web.de>
Description:
Defines the interval in milliseconds in which batman
sends its probing packets for link quality measurements.
emits probing packets for neighbor sensing (ELP).
What: /sys/class/net/<iface>/batman-adv/iface_status
Date: May 2010
......@@ -28,3 +19,12 @@ Description:
The /sys/class/net/<iface>/batman-adv/mesh_iface file
displays the batman mesh interface this <iface>
currently is associated with.
What: /sys/class/net/<iface>/batman-adv/throughput_override
Date: Feb 2014
Contact: Antonio Quartulli <a@unstable.cc>
description:
Defines the throughput value to be used by B.A.T.M.A.N. V
when estimating the link throughput using this interface.
If the value is set to 0 then batman-adv will try to
estimate the throughput by itself.
......@@ -66,7 +66,7 @@ config BATMAN_ADV_NC
config BATMAN_ADV_MCAST
bool "Multicast optimisation"
depends on BATMAN_ADV
depends on BATMAN_ADV && INET && !(BRIDGE=m && BATMAN_ADV=y)
default n
help
This option enables the multicast optimisation which aims to
......
......@@ -18,13 +18,14 @@
#ifndef _NET_BATMAN_ADV_BAT_ALGO_H_
#define _NET_BATMAN_ADV_BAT_ALGO_H_
struct batadv_priv;
#include "main.h"
int batadv_iv_init(void);
#ifdef CONFIG_BATMAN_ADV_BATMAN_V
int batadv_v_init(void);
void batadv_v_hardif_init(struct batadv_hard_iface *hardif);
int batadv_v_mesh_init(struct batadv_priv *bat_priv);
void batadv_v_mesh_free(struct batadv_priv *bat_priv);
......@@ -35,6 +36,10 @@ static inline int batadv_v_init(void)
return 0;
}
static inline void batadv_v_hardif_init(struct batadv_hard_iface *hardif)
{
}
static inline int batadv_v_mesh_init(struct batadv_priv *bat_priv)
{
return 0;
......
......@@ -30,6 +30,7 @@
#include <linux/if_ether.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/kref.h>
#include <linux/lockdep.h>
......@@ -58,6 +59,8 @@
#include "send.h"
#include "translation-table.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
......@@ -336,7 +339,8 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
{
struct batadv_neigh_node *neigh_node;
neigh_node = batadv_neigh_node_new(orig_node, hard_iface, neigh_addr);
neigh_node = batadv_neigh_node_get_or_create(orig_node,
hard_iface, neigh_addr);
if (!neigh_node)
goto out;
......@@ -730,7 +734,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
/* start timer for this packet */
INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
batadv_send_outstanding_bat_ogm_packet);
batadv_iv_send_outstanding_bat_ogm_packet);
queue_delayed_work(batadv_event_workqueue,
&forw_packet_aggr->delayed_work,
send_time - jiffies);
......@@ -937,6 +941,19 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
u16 tvlv_len = 0;
unsigned long send_time;
if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) ||
(hard_iface->if_status == BATADV_IF_TO_BE_REMOVED))
return;
/* the interface gets activated here to avoid race conditions between
* the moment of activating the interface in
* hardif_activate_interface() where the originator mac is set and
* outdated packets (especially uninitialized mac addresses) in the
* packet queue
*/
if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED)
hard_iface->if_status = BATADV_IF_ACTIVE;
primary_if = batadv_primary_if_get_selected(bat_priv);
if (hard_iface == primary_if) {
......@@ -1778,6 +1795,45 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
batadv_orig_node_put(orig_node);
}
static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work)
{
struct delayed_work *delayed_work;
struct batadv_forw_packet *forw_packet;
struct batadv_priv *bat_priv;
delayed_work = to_delayed_work(work);
forw_packet = container_of(delayed_work, struct batadv_forw_packet,
delayed_work);
bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
hlist_del(&forw_packet->list);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
goto out;
batadv_iv_ogm_emit(forw_packet);
/* we have to have at least one packet in the queue to determine the
* queues wake up time unless we are shutting down.
*
* only re-schedule if this is the "original" copy, e.g. the OGM of the
* primary interface should only be rescheduled once per period, but
* this function will be called for the forw_packet instances of the
* other secondary interfaces as well.
*/
if (forw_packet->own &&
forw_packet->if_incoming == forw_packet->if_outgoing)
batadv_iv_ogm_schedule(forw_packet->if_incoming);
out:
/* don't count own packet */
if (!forw_packet->own)
atomic_inc(&bat_priv->batman_queue_left);
batadv_forw_packet_free(forw_packet);
}
static int batadv_iv_ogm_receive(struct sk_buff *skb,
struct batadv_hard_iface *if_incoming)
{
......@@ -1794,7 +1850,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
/* did we receive a B.A.T.M.A.N. IV OGM packet on an interface
* that does not have B.A.T.M.A.N. IV enabled ?
*/
if (bat_priv->bat_algo_ops->bat_ogm_emit != batadv_iv_ogm_emit)
if (bat_priv->bat_algo_ops->bat_iface_enable !=
batadv_iv_ogm_iface_enable)
return NET_RX_DROP;
batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX);
......@@ -2052,14 +2109,19 @@ batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1,
return ret;
}
static void batadv_iv_iface_activate(struct batadv_hard_iface *hard_iface)
{
/* begin scheduling originator messages on that interface */
batadv_iv_ogm_schedule(hard_iface);
}
static struct batadv_algo_ops batadv_batman_iv __read_mostly = {
.name = "BATMAN_IV",
.bat_iface_activate = batadv_iv_iface_activate,
.bat_iface_enable = batadv_iv_ogm_iface_enable,
.bat_iface_disable = batadv_iv_ogm_iface_disable,
.bat_iface_update_mac = batadv_iv_ogm_iface_update_mac,
.bat_primary_iface_set = batadv_iv_ogm_primary_iface_set,
.bat_ogm_schedule = batadv_iv_ogm_schedule,
.bat_ogm_emit = batadv_iv_ogm_emit,
.bat_neigh_cmp = batadv_iv_ogm_neigh_cmp,
.bat_neigh_is_similar_or_better = batadv_iv_ogm_neigh_is_sob,
.bat_neigh_print = batadv_iv_neigh_print,
......
......@@ -70,11 +70,6 @@ static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
if (ret < 0)
batadv_v_elp_iface_disable(hard_iface);
/* enable link throughput auto-detection by setting the throughput
* override to zero
*/
atomic_set(&hard_iface->bat_v.throughput_override, 0);
return ret;
}
......@@ -119,14 +114,6 @@ batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
batadv_v_elp_throughput_metric_update);
}
static void batadv_v_ogm_schedule(struct batadv_hard_iface *hard_iface)
{
}
static void batadv_v_ogm_emit(struct batadv_forw_packet *forw_packet)
{
}
/**
* batadv_v_orig_print_neigh - print neighbors for the originator table
* @orig_node: the orig_node for which the neighbors are printed
......@@ -340,14 +327,26 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = {
.bat_iface_update_mac = batadv_v_iface_update_mac,
.bat_primary_iface_set = batadv_v_primary_iface_set,
.bat_hardif_neigh_init = batadv_v_hardif_neigh_init,
.bat_ogm_emit = batadv_v_ogm_emit,
.bat_ogm_schedule = batadv_v_ogm_schedule,
.bat_orig_print = batadv_v_orig_print,
.bat_neigh_cmp = batadv_v_neigh_cmp,
.bat_neigh_is_similar_or_better = batadv_v_neigh_is_sob,
.bat_neigh_print = batadv_v_neigh_print,
};
/**
* batadv_v_hardif_init - initialize the algorithm specific fields in the
* hard-interface object
* @hard_iface: the hard-interface to initialize
*/
void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface)
{
/* enable link throughput auto-detection by setting the throughput
* override to zero
*/
atomic_set(&hard_iface->bat_v.throughput_override, 0);
atomic_set(&hard_iface->bat_v.elp_interval, 500);
}
/**
* batadv_v_mesh_init - initialize the B.A.T.M.A.N. V private resources for a
* mesh
......
......@@ -344,7 +344,6 @@ int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
/* randomize initial seqno to avoid collision */
get_random_bytes(&random_seqno, sizeof(random_seqno));
atomic_set(&hard_iface->bat_v.elp_seqno, random_seqno);
atomic_set(&hard_iface->bat_v.elp_interval, 500);
/* assume full-duplex by default */
hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
......@@ -443,7 +442,8 @@ static void batadv_v_elp_neigh_update(struct batadv_priv *bat_priv,
if (!orig_neigh)
return;
neigh = batadv_neigh_node_new(orig_neigh, if_incoming, neigh_addr);
neigh = batadv_neigh_node_get_or_create(orig_neigh,
if_incoming, neigh_addr);
if (!neigh)
goto orig_free;
......
......@@ -683,7 +683,7 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
if (!orig_node)
return;
neigh_node = batadv_neigh_node_new(orig_node, if_incoming,
neigh_node = batadv_neigh_node_get_or_create(orig_node, if_incoming,
ethhdr->h_source);
if (!neigh_node)
goto out;
......
......@@ -48,6 +48,7 @@
#include "distributed-arp-table.h"
#include "gateway_client.h"
#include "icmp_socket.h"
#include "multicast.h"
#include "network-coding.h"
#include "originator.h"
#include "translation-table.h"
......@@ -363,6 +364,22 @@ static int batadv_nc_nodes_open(struct inode *inode, struct file *file)
}
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
/**
* batadv_mcast_flags_open - prepare file handler for reads from mcast_flags
* @inode: inode which was opened
* @file: file handle to be initialized
*
* Return: 0 on success or negative error number in case of failure
*/
static int batadv_mcast_flags_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
return single_open(file, batadv_mcast_flags_seq_print_text, net_dev);
}
#endif
#define BATADV_DEBUGINFO(_name, _mode, _open) \
struct batadv_debuginfo batadv_debuginfo_##_name = { \
.attr = { \
......@@ -407,6 +424,9 @@ static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
#ifdef CONFIG_BATMAN_ADV_NC
static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
static BATADV_DEBUGINFO(mcast_flags, S_IRUGO, batadv_mcast_flags_open);
#endif
static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
&batadv_debuginfo_neighbors,
......@@ -423,6 +443,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
&batadv_debuginfo_transtable_local,
#ifdef CONFIG_BATMAN_ADV_NC
&batadv_debuginfo_nc_nodes,
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
&batadv_debuginfo_mcast_flags,
#endif
NULL,
};
......
......@@ -27,7 +27,6 @@
#include <linux/kernel.h>
#include <linux/lockdep.h>
#include <linux/netdevice.h>
#include <linux/pkt_sched.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
......@@ -414,7 +413,7 @@ static struct sk_buff *batadv_frag_create(struct sk_buff *skb,
if (!skb_fragment)
goto err;
skb->priority = TC_PRIO_CONTROL;
skb_fragment->priority = skb->priority;
/* Eat the last mtu-bytes of the skb */
skb_reserve(skb_fragment, header_size + ETH_HLEN);
......@@ -473,6 +472,15 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
frag_header.reserved = 0;
frag_header.no = 0;
frag_header.total_size = htons(skb->len);
/* skb->priority values from 256->263 are magic values to
* directly indicate a specific 802.1d priority. This is used
* to allow 802.1d priority to be passed directly in from VLAN
* tags, etc.
*/
if (skb->priority >= 256 && skb->priority <= 263)
frag_header.priority = skb->priority - 256;
ether_addr_copy(frag_header.orig, primary_if->net_dev->dev_addr);
ether_addr_copy(frag_header.dest, orig_node->orig);
......
......@@ -192,7 +192,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
tq_avg = router_ifinfo->bat_iv.tq_avg;
switch (atomic_read(&bat_priv->gw_sel_class)) {
switch (atomic_read(&bat_priv->gw.sel_class)) {
case 1: /* fast connection */
tmp_gw_factor = tq_avg * tq_avg;
tmp_gw_factor *= gw_node->bandwidth_down;
......@@ -255,7 +255,7 @@ void batadv_gw_check_client_stop(struct batadv_priv *bat_priv)
{
struct batadv_gw_node *curr_gw;
if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT)
if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT)
return;
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
......@@ -283,7 +283,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
struct batadv_neigh_ifinfo *router_ifinfo = NULL;
char gw_addr[18] = { '\0' };
if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT)
if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT)
goto out;
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
......@@ -402,8 +402,8 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
/* if the routing class is greater than 3 the value tells us how much
* greater the TQ value of the new gateway must be
*/
if ((atomic_read(&bat_priv->gw_sel_class) > 3) &&
(orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class)))
if ((atomic_read(&bat_priv->gw.sel_class) > 3) &&
(orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw.sel_class)))
goto out;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
......@@ -638,8 +638,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
goto out;
seq_printf(seq,
" %-12s (%s/%i) %17s [%10s]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
"Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF",
" Gateway (#/255) Nexthop [outgoingIF]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
BATADV_SOURCE_VERSION, primary_if->net_dev->name,
primary_if->net_dev->dev_addr, net_dev->name);
......@@ -821,7 +820,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
if (!gw_node)
goto out;
switch (atomic_read(&bat_priv->gw_mode)) {
switch (atomic_read(&bat_priv->gw.mode)) {
case BATADV_GW_MODE_SERVER:
/* If we are a GW then we are our best GW. We can artificially
* set the tq towards ourself as the maximum value
......
......@@ -144,7 +144,7 @@ void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv)
u32 down, up;
char gw_mode;
gw_mode = atomic_read(&bat_priv->gw_mode);
gw_mode = atomic_read(&bat_priv->gw.mode);
switch (gw_mode) {
case BATADV_GW_MODE_OFF:
......@@ -241,8 +241,8 @@ static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
/* restart gateway selection if fast or late switching was enabled */
if ((gateway.bandwidth_down != 0) &&
(atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) &&
(atomic_read(&bat_priv->gw_sel_class) > 2))
(atomic_read(&bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT) &&
(atomic_read(&bat_priv->gw.sel_class) > 2))
batadv_gw_check_election(bat_priv, orig);
}
......
......@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include "bat_algo.h"
#include "bridge_loop_avoidance.h"
#include "debugfs.h"
#include "distributed-arp-table.h"
......@@ -553,9 +554,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
batadv_hardif_recalc_extra_skbroom(soft_iface);
/* begin scheduling originator messages on that interface */
batadv_schedule_bat_ogm(hard_iface);
out:
return 0;
......@@ -686,6 +684,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
if (batadv_is_wifi_netdev(net_dev))
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
batadv_v_hardif_init(hard_iface);
/* extra reference for return */
kref_init(&hard_iface->refcount);
kref_get(&hard_iface->refcount);
......
......@@ -569,8 +569,6 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops)
!bat_algo_ops->bat_iface_disable ||
!bat_algo_ops->bat_iface_update_mac ||
!bat_algo_ops->bat_primary_iface_set ||
!bat_algo_ops->bat_ogm_schedule ||
!bat_algo_ops->bat_ogm_emit ||
!bat_algo_ops->bat_neigh_cmp ||
!bat_algo_ops->bat_neigh_is_similar_or_better) {
pr_info("Routing algo '%s' does not implement required ops\n",
......
......@@ -24,7 +24,7 @@
#define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION
#define BATADV_SOURCE_VERSION "2016.2"
#define BATADV_SOURCE_VERSION "2016.3"
#endif
/* B.A.T.M.A.N. parameters */
......@@ -231,6 +231,7 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr);
* @BATADV_DBG_BLA: bridge loop avoidance messages
* @BATADV_DBG_DAT: ARP snooping and DAT related messages
* @BATADV_DBG_NC: network coding related messages
* @BATADV_DBG_MCAST: multicast related messages
* @BATADV_DBG_ALL: the union of all the above log levels
*/
enum batadv_dbg_level {
......@@ -240,7 +241,8 @@ enum batadv_dbg_level {
BATADV_DBG_BLA = BIT(3),
BATADV_DBG_DAT = BIT(4),
BATADV_DBG_NC = BIT(5),
BATADV_DBG_ALL = 63,
BATADV_DBG_MCAST = BIT(6),
BATADV_DBG_ALL = 127,
};
#ifdef CONFIG_BATMAN_ADV_DEBUG
......
This diff is collapsed.
......@@ -20,6 +20,7 @@
#include "main.h"
struct seq_file;
struct sk_buff;
/**
......@@ -46,6 +47,8 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
void batadv_mcast_init(struct batadv_priv *bat_priv);
int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset);
void batadv_mcast_free(struct batadv_priv *bat_priv);
void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node);
......
......@@ -251,10 +251,8 @@ static void batadv_neigh_node_release(struct kref *ref)
struct hlist_node *node_tmp;
struct batadv_neigh_node *neigh_node;
struct batadv_neigh_ifinfo *neigh_ifinfo;
struct batadv_algo_ops *bao;
neigh_node = container_of(ref, struct batadv_neigh_node, refcount);
bao = neigh_node->orig_node->bat_priv->bat_algo_ops;
hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
&neigh_node->ifinfo_list, list) {
......@@ -263,9 +261,6 @@ static void batadv_neigh_node_release(struct kref *ref)
batadv_hardif_neigh_put(neigh_node->hardif_neigh);
if (bao->bat_neigh_free)
bao->bat_neigh_free(neigh_node);
batadv_hardif_put(neigh_node->if_incoming);
kfree_rcu(neigh_node, rcu);
......@@ -602,17 +597,17 @@ batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface,
}
/**
* batadv_neigh_node_new - create and init a new neigh_node object
* batadv_neigh_node_create - create a neigh node object
* @orig_node: originator object representing the neighbour
* @hard_iface: the interface where the neighbour is connected to
* @neigh_addr: the mac address of the neighbour interface
*
* Allocates a new neigh_node object and initialises all the generic fields.
*
* Return: neighbor when found. Othwerwise NULL
* Return: the neighbour node if found or created or NULL otherwise.
*/
struct batadv_neigh_node *
batadv_neigh_node_new(struct batadv_orig_node *orig_node,
static struct batadv_neigh_node *
batadv_neigh_node_create(struct batadv_orig_node *orig_node,
struct batadv_hard_iface *hard_iface,
const u8 *neigh_addr)
{
......@@ -666,6 +661,29 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
return neigh_node;
}
/**
* batadv_neigh_node_get_or_create - retrieve or create a neigh node object
* @orig_node: originator object representing the neighbour
* @hard_iface: the interface where the neighbour is connected to
* @neigh_addr: the mac address of the neighbour interface
*
* Return: the neighbour node if found or created or NULL otherwise.
*/
struct batadv_neigh_node *
batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node,
struct batadv_hard_iface *hard_iface,
const u8 *neigh_addr)
{
struct batadv_neigh_node *neigh_node = NULL;
/* first check without locking to avoid the overhead */
neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
if (neigh_node)
return neigh_node;
return batadv_neigh_node_create(orig_node, hard_iface, neigh_addr);
}
/**
* batadv_hardif_neigh_seq_print_text - print the single hop neighbour list
* @seq: neighbour table seq_file struct
......
......@@ -46,7 +46,7 @@ batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface,
void
batadv_hardif_neigh_put(struct batadv_hardif_neigh_node *hardif_neigh);
struct batadv_neigh_node *
batadv_neigh_node_new(struct batadv_orig_node *orig_node,
batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node,
struct batadv_hard_iface *hard_iface,
const u8 *neigh_addr);
void batadv_neigh_node_put(struct batadv_neigh_node *neigh_node);
......
......@@ -420,6 +420,7 @@ struct batadv_unicast_4addr_packet {
* @dest: final destination used when routing fragments
* @orig: originator of the fragment used when merging the packet
* @no: fragment number within this sequence
* @priority: priority of frame, from ToS IP precedence or 802.1p
* @reserved: reserved byte for alignment
* @seqno: sequence identification
* @total_size: size of the merged packet
......@@ -430,9 +431,11 @@ struct batadv_frag_packet {
u8 ttl;
#if defined(__BIG_ENDIAN_BITFIELD)
u8 no:4;
u8 reserved:4;
u8 priority:3;
u8 reserved:1;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
u8 reserved:4;
u8 reserved:1;
u8 priority:3;
u8 no:4;
#else
#error "unknown bitfield endianness"
......
......@@ -1007,6 +1007,8 @@ int batadv_recv_frag_packet(struct sk_buff *skb,
if (!orig_node_src)
goto out;
skb->priority = frag_packet->priority + 256;
/* Route the fragment if it is not for us and too big to be merged. */
if (!batadv_is_my_mac(bat_priv, frag_packet->dest) &&
batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) {
......
......@@ -428,27 +428,7 @@ int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb,
orig_node, vid);
}
void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) ||
(hard_iface->if_status == BATADV_IF_TO_BE_REMOVED))
return;
/* the interface gets activated here to avoid race conditions between
* the moment of activating the interface in
* hardif_activate_interface() where the originator mac is set and
* outdated packets (especially uninitialized mac addresses) in the
* packet queue
*/
if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED)
hard_iface->if_status = BATADV_IF_ACTIVE;
bat_priv->bat_algo_ops->bat_ogm_schedule(hard_iface);
}
static void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet)
void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet)
{
kfree_skb(forw_packet->skb);
if (forw_packet->if_incoming)
......@@ -604,45 +584,6 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
atomic_inc(&bat_priv->bcast_queue_left);
}
void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work)
{
struct delayed_work *delayed_work;
struct batadv_forw_packet *forw_packet;
struct batadv_priv *bat_priv;
delayed_work = to_delayed_work(work);
forw_packet = container_of(delayed_work, struct batadv_forw_packet,
delayed_work);
bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
hlist_del(&forw_packet->list);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
goto out;
bat_priv->bat_algo_ops->bat_ogm_emit(forw_packet);
/* we have to have at least one packet in the queue to determine the
* queues wake up time unless we are shutting down.
*
* only re-schedule if this is the "original" copy, e.g. the OGM of the
* primary interface should only be rescheduled once per period, but
* this function will be called for the forw_packet instances of the
* other secondary interfaces as well.
*/
if (forw_packet->own &&
forw_packet->if_incoming == forw_packet->if_outgoing)
batadv_schedule_bat_ogm(forw_packet->if_incoming);
out:
/* don't count own packet */
if (!forw_packet->own)
atomic_inc(&bat_priv->batman_queue_left);
batadv_forw_packet_free(forw_packet);
}
void
batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
const struct batadv_hard_iface *hard_iface)
......
......@@ -26,8 +26,8 @@
#include "packet.h"
struct sk_buff;
struct work_struct;
void batadv_forw_packet_free(struct batadv_forw_packet *forw_packet);
int batadv_send_skb_to_orig(struct sk_buff *skb,
struct batadv_orig_node *orig_node,
struct batadv_hard_iface *recv_if);
......@@ -38,11 +38,9 @@ int batadv_send_broadcast_skb(struct sk_buff *skb,
struct batadv_hard_iface *hard_iface);
int batadv_send_unicast_skb(struct sk_buff *skb,
struct batadv_neigh_node *neigh_node);
void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface);
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
const struct sk_buff *skb,
unsigned long delay);
void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work);
void
batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
const struct batadv_hard_iface *hard_iface);
......
......@@ -255,7 +255,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
goto dropped;
gw_mode = atomic_read(&bat_priv->gw_mode);
gw_mode = atomic_read(&bat_priv->gw.mode);
if (is_multicast_ether_addr(ethhdr->h_dest)) {
/* if gw mode is off, broadcast every packet */
if (gw_mode == BATADV_GW_MODE_OFF) {
......@@ -808,6 +808,10 @@ static int batadv_softif_init_late(struct net_device *dev)
atomic_set(&bat_priv->distributed_arp_table, 1);
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
bat_priv->mcast.querier_ipv4.exists = false;
bat_priv->mcast.querier_ipv4.shadowing = false;
bat_priv->mcast.querier_ipv6.exists = false;
bat_priv->mcast.querier_ipv6.shadowing = false;
bat_priv->mcast.flags = BATADV_NO_FLAGS;
atomic_set(&bat_priv->multicast_mode, 1);
atomic_set(&bat_priv->mcast.num_disabled, 0);
......@@ -815,8 +819,8 @@ static int batadv_softif_init_late(struct net_device *dev)
atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0);
atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0);
#endif
atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
atomic_set(&bat_priv->gw_sel_class, 20);
atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF);
atomic_set(&bat_priv->gw.sel_class, 20);
atomic_set(&bat_priv->gw.bandwidth_down, 100);
atomic_set(&bat_priv->gw.bandwidth_up, 20);
atomic_set(&bat_priv->orig_interval, 1000);
......
......@@ -389,12 +389,12 @@ static int batadv_store_uint_attr(const char *buff, size_t count,
return count;
}
static inline ssize_t
__batadv_store_uint_attr(const char *buff, size_t count,
static ssize_t __batadv_store_uint_attr(const char *buff, size_t count,
int min, int max,
void (*post_func)(struct net_device *),
const struct attribute *attr,
atomic_t *attr_store, struct net_device *net_dev)
atomic_t *attr_store,
struct net_device *net_dev)
{
int ret;
......@@ -427,7 +427,7 @@ static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr,
struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
int bytes_written;
switch (atomic_read(&bat_priv->gw_mode)) {
switch (atomic_read(&bat_priv->gw.mode)) {
case BATADV_GW_MODE_CLIENT:
bytes_written = sprintf(buff, "%s\n",
BATADV_GW_MODE_CLIENT_NAME);
......@@ -476,10 +476,10 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj,
return -EINVAL;
}
if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp)
if (atomic_read(&bat_priv->gw.mode) == gw_mode_tmp)
return count;
switch (atomic_read(&bat_priv->gw_mode)) {
switch (atomic_read(&bat_priv->gw.mode)) {
case BATADV_GW_MODE_CLIENT:
curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME;
break;
......@@ -508,7 +508,7 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj,
* state
*/
batadv_gw_check_client_stop(bat_priv);
atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
atomic_set(&bat_priv->gw.mode, (unsigned int)gw_mode_tmp);
batadv_gw_tvlv_container_update(bat_priv);
return count;
}
......@@ -624,7 +624,7 @@ BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, S_IRUGO | S_IWUSR,
2 * BATADV_JITTER, INT_MAX, NULL);
BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0,
BATADV_TQ_MAX_VALUE, NULL);
BATADV_ATTR_SIF_UINT(gw_sel_class, gw_sel_class, S_IRUGO | S_IWUSR, 1,
BATADV_ATTR_SIF_UINT(gw_sel_class, gw.sel_class, S_IRUGO | S_IWUSR, 1,
BATADV_TQ_MAX_VALUE, batadv_post_gw_reselect);
static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
batadv_store_gw_bwidth);
......
......@@ -996,7 +996,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
struct batadv_tt_local_entry *tt_local;
struct batadv_hard_iface *primary_if;
struct hlist_head *head;
unsigned short vid;
u32 i;
int last_seen_secs;
int last_seen_msecs;
......@@ -1023,7 +1022,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
tt_local = container_of(tt_common_entry,
struct batadv_tt_local_entry,
common);
vid = tt_common_entry->vid;
last_seen_jiffies = jiffies - tt_local->last_seen;
last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
last_seen_secs = last_seen_msecs / 1000;
......
......@@ -707,6 +707,8 @@ struct batadv_priv_debug_log {
* @list: list of available gateway nodes
* @list_lock: lock protecting gw_list & curr_gw
* @curr_gw: pointer to currently selected gateway node
* @mode: gateway operation: off, client or server (see batadv_gw_modes)
* @sel_class: gateway selection class (applies if gw_mode client)
* @bandwidth_down: advertised uplink download bandwidth (if gw_mode server)
* @bandwidth_up: advertised uplink upload bandwidth (if gw_mode server)
* @reselect: bool indicating a gateway re-selection is in progress
......@@ -715,6 +717,8 @@ struct batadv_priv_gw {
struct hlist_head list;
spinlock_t list_lock; /* protects gw_list & curr_gw */
struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */
atomic_t mode;
atomic_t sel_class;
atomic_t bandwidth_down;
atomic_t bandwidth_up;
atomic_t reselect;
......@@ -750,6 +754,17 @@ struct batadv_priv_dat {
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
/**
* struct batadv_mcast_querier_state - IGMP/MLD querier state when bridged
* @exists: whether a querier exists in the mesh
* @shadowing: if a querier exists, whether it is potentially shadowing
* multicast listeners (i.e. querier is behind our own bridge segment)
*/
struct batadv_mcast_querier_state {
bool exists;
bool shadowing;
};
/**
* struct batadv_priv_mcast - per mesh interface mcast data
* @mla_list: list of multicast addresses we are currently announcing via TT
......@@ -757,8 +772,11 @@ struct batadv_priv_dat {
* multicast traffic
* @want_all_ipv4_list: a list of orig_nodes wanting all IPv4 multicast traffic
* @want_all_ipv6_list: a list of orig_nodes wanting all IPv6 multicast traffic
* @querier_ipv4: the current state of an IGMP querier in the mesh
* @querier_ipv6: the current state of an MLD querier in the mesh
* @flags: the flags we have last sent in our mcast tvlv
* @enabled: whether the multicast tvlv is currently enabled
* @bridged: whether the soft interface has a bridge on top
* @num_disabled: number of nodes that have no mcast tvlv
* @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic
* @num_want_all_ipv4: counter for items in want_all_ipv4_list
......@@ -771,8 +789,11 @@ struct batadv_priv_mcast {
struct hlist_head want_all_unsnoopables_list;
struct hlist_head want_all_ipv4_list;
struct hlist_head want_all_ipv6_list;
struct batadv_mcast_querier_state querier_ipv4;
struct batadv_mcast_querier_state querier_ipv6;
u8 flags;
bool enabled;
bool bridged;
atomic_t num_disabled;
atomic_t num_want_all_unsnoopables;
atomic_t num_want_all_ipv4;
......@@ -865,8 +886,6 @@ struct batadv_priv_bat_v {
* enabled
* @multicast_mode: Enable or disable multicast optimizations on this node's
* sender/originating side
* @gw_mode: gateway operation: off, client or server (see batadv_gw_modes)
* @gw_sel_class: gateway selection class (applies if gw_mode client)
* @orig_interval: OGM broadcast interval in milliseconds
* @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop
* @log_level: configured log level (see batadv_dbg_level)
......@@ -922,8 +941,6 @@ struct batadv_priv {
#ifdef CONFIG_BATMAN_ADV_MCAST
atomic_t multicast_mode;
#endif
atomic_t gw_mode;
atomic_t gw_sel_class;
atomic_t orig_interval;
atomic_t hop_penalty;
#ifdef CONFIG_BATMAN_ADV_DEBUG
......@@ -1271,8 +1288,6 @@ struct batadv_forw_packet {
* @bat_iface_update_mac: (re-)init mac addresses of the protocol information
* belonging to this hard-interface
* @bat_primary_iface_set: called when primary interface is selected / changed
* @bat_ogm_schedule: prepare a new outgoing OGM for the send queue
* @bat_ogm_emit: send scheduled OGM
* @bat_hardif_neigh_init: called on creation of single hop entry
* @bat_neigh_cmp: compare the metrics of two neighbors for their respective
* outgoing interfaces
......@@ -1280,8 +1295,6 @@ struct batadv_forw_packet {
* better than neigh2 for their respective outgoing interface from the metric
* prospective
* @bat_neigh_print: print the single hop neighbor list (optional)
* @bat_neigh_free: free the resources allocated by the routing algorithm for a
* neigh_node object
* @bat_orig_print: print the originator table (optional)
* @bat_orig_free: free the resources allocated by the routing algorithm for an
* orig_node object
......@@ -1298,8 +1311,6 @@ struct batadv_algo_ops {
void (*bat_iface_disable)(struct batadv_hard_iface *hard_iface);
void (*bat_iface_update_mac)(struct batadv_hard_iface *hard_iface);
void (*bat_primary_iface_set)(struct batadv_hard_iface *hard_iface);
void (*bat_ogm_schedule)(struct batadv_hard_iface *hard_iface);
void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet);
/* neigh_node handling API */
void (*bat_hardif_neigh_init)(struct batadv_hardif_neigh_node *neigh);
int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1,
......@@ -1312,7 +1323,6 @@ struct batadv_algo_ops {
struct batadv_neigh_node *neigh2,
struct batadv_hard_iface *if_outgoing2);
void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq);
void (*bat_neigh_free)(struct batadv_neigh_node *neigh);
/* orig_node handling API */
void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq,
struct batadv_hard_iface *hard_iface);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment