Skip to content

Commit

Permalink
batman-adv: Introduce a configurable per interface hop penalty
Browse files Browse the repository at this point in the history
In some setups multiple hard interfaces with similar link qualities
or throughput values are available. But people have expressed the desire
to consider one of them as a backup only.

Some creative solutions are currently in use: Such people are
configuring multiple batman-adv mesh/soft interfaces, wire them
together with some veth pairs and then tune the hop penalty to achieve
an effect similar to a tunable per interface hop penalty.

This patch introduces a new, configurable, per hard interface hop penalty
to simplify such setups.

Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
  • Loading branch information
Linus Lüssing authored and Simon Wunderlich committed Jun 26, 2020
1 parent bccb48c commit 3bda14d
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 13 deletions.
3 changes: 2 additions & 1 deletion include/uapi/linux/batman_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,8 @@ enum batadv_nl_attrs {

/**
* @BATADV_ATTR_HOP_PENALTY: defines the penalty which will be applied
* to an originator message's tq-field on every hop.
* to an originator message's tq-field on every hop and/or per
* hard interface
*/
BATADV_ATTR_HOP_PENALTY,

Expand Down
17 changes: 9 additions & 8 deletions net/batman-adv/bat_iv_ogm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1075,10 +1075,10 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
struct batadv_neigh_ifinfo *neigh_ifinfo;
u8 total_count;
u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own;
unsigned int tq_iface_hop_penalty = BATADV_TQ_MAX_VALUE;
unsigned int neigh_rq_inv_cube, neigh_rq_max_cube;
unsigned int tq_asym_penalty, inv_asym_penalty;
unsigned int combined_tq;
unsigned int tq_iface_penalty;
bool ret = false;

/* find corresponding one hop neighbor */
Expand Down Expand Up @@ -1157,31 +1157,32 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
inv_asym_penalty = BATADV_TQ_MAX_VALUE * neigh_rq_inv_cube;
inv_asym_penalty /= neigh_rq_max_cube;
tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty;
tq_iface_hop_penalty -= atomic_read(&if_incoming->hop_penalty);

/* penalize if the OGM is forwarded on the same interface. WiFi
* interfaces and other half duplex devices suffer from throughput
* drops as they can't send and receive at the same time.
*/
tq_iface_penalty = BATADV_TQ_MAX_VALUE;
if (if_outgoing && if_incoming == if_outgoing &&
batadv_is_wifi_hardif(if_outgoing))
tq_iface_penalty = batadv_hop_penalty(BATADV_TQ_MAX_VALUE,
bat_priv);
tq_iface_hop_penalty = batadv_hop_penalty(tq_iface_hop_penalty,
bat_priv);

combined_tq = batadv_ogm_packet->tq *
tq_own *
tq_asym_penalty *
tq_iface_penalty;
tq_iface_hop_penalty;
combined_tq /= BATADV_TQ_MAX_VALUE *
BATADV_TQ_MAX_VALUE *
BATADV_TQ_MAX_VALUE;
batadv_ogm_packet->tq = combined_tq;

batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"bidirectional: orig = %pM neigh = %pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, iface_penalty: %3i, total tq: %3i, if_incoming = %s, if_outgoing = %s\n",
"bidirectional: orig = %pM neigh = %pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, iface_hop_penalty: %3i, total tq: %3i, if_incoming = %s, if_outgoing = %s\n",
orig_node->orig, orig_neigh_node->orig, total_count,
neigh_rq_count, tq_own, tq_asym_penalty, tq_iface_penalty,
batadv_ogm_packet->tq, if_incoming->net_dev->name,
neigh_rq_count, tq_own, tq_asym_penalty,
tq_iface_hop_penalty, batadv_ogm_packet->tq,
if_incoming->net_dev->name,
if_outgoing ? if_outgoing->net_dev->name : "DEFAULT");

/* if link has the minimum required transmission quality
Expand Down
13 changes: 10 additions & 3 deletions net/batman-adv/bat_v_ogm.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,15 +455,17 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
* @throughput: the current throughput
*
* Apply a penalty on the current throughput metric value based on the
* characteristic of the interface where the OGM has been received. The return
* value is computed as follows:
* characteristic of the interface where the OGM has been received.
*
* Initially the per hardif hop penalty is applied to the throughput. After
* that the return value is then computed as follows:
* - throughput * 50% if the incoming and outgoing interface are the
* same WiFi interface and the throughput is above
* 1MBit/s
* - throughput if the outgoing interface is the default
* interface (i.e. this OGM is processed for the
* internal table and not forwarded)
* - throughput * hop penalty otherwise
* - throughput * node hop penalty otherwise
*
* Return: the penalised throughput metric.
*/
Expand All @@ -472,9 +474,14 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_outgoing,
u32 throughput)
{
int if_hop_penalty = atomic_read(&if_incoming->hop_penalty);
int hop_penalty = atomic_read(&bat_priv->hop_penalty);
int hop_penalty_max = BATADV_TQ_MAX_VALUE;

/* Apply per hardif hop penalty */
throughput = throughput * (hop_penalty_max - if_hop_penalty) /
hop_penalty_max;

/* Don't apply hop penalty in default originator table. */
if (if_outgoing == BATADV_IF_DEFAULT)
return throughput;
Expand Down
2 changes: 2 additions & 0 deletions net/batman-adv/hard-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
if (batadv_is_wifi_hardif(hard_iface))
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;

atomic_set(&hard_iface->hop_penalty, 0);

batadv_v_hardif_init(hard_iface);

batadv_check_known_mac_addr(hard_iface->net_dev);
Expand Down
12 changes: 11 additions & 1 deletion net/batman-adv/netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,10 @@ static int batadv_netlink_hardif_fill(struct sk_buff *msg,
goto nla_put_failure;
}

if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
atomic_read(&hard_iface->hop_penalty)))
goto nla_put_failure;

#ifdef CONFIG_BATMAN_ADV_BATMAN_V
if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL,
atomic_read(&hard_iface->bat_v.elp_interval)))
Expand Down Expand Up @@ -920,9 +924,15 @@ static int batadv_netlink_set_hardif(struct sk_buff *skb,
{
struct batadv_hard_iface *hard_iface = info->user_ptr[1];
struct batadv_priv *bat_priv = info->user_ptr[0];
struct nlattr *attr;

if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
attr = info->attrs[BATADV_ATTR_HOP_PENALTY];

atomic_set(&hard_iface->hop_penalty, nla_get_u8(attr));
}

#ifdef CONFIG_BATMAN_ADV_BATMAN_V
struct nlattr *attr;

if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) {
attr = info->attrs[BATADV_ATTR_ELP_INTERVAL];
Expand Down
6 changes: 6 additions & 0 deletions net/batman-adv/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ struct batadv_hard_iface {
/** @rcu: struct used for freeing in an RCU-safe manner */
struct rcu_head rcu;

/**
* @hop_penalty: penalty which will be applied to the tq-field
* of an OGM received via this interface
*/
atomic_t hop_penalty;

/** @bat_iv: per hard-interface B.A.T.M.A.N. IV data */
struct batadv_hard_iface_bat_iv bat_iv;

Expand Down

0 comments on commit 3bda14d

Please sign in to comment.