1
0
Fork 0

batman-adv: Introduce a configurable per interface hop penalty

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>
zero-sugar-mainline-defconfig
Linus Lüssing 2020-06-01 22:35:22 +02:00 committed by Simon Wunderlich
parent bccb48c89f
commit 3bda14d09d
6 changed files with 40 additions and 13 deletions

View File

@ -427,7 +427,8 @@ enum batadv_nl_attrs {
/** /**
* @BATADV_ATTR_HOP_PENALTY: defines the penalty which will be applied * @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, BATADV_ATTR_HOP_PENALTY,

View File

@ -1075,10 +1075,10 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
struct batadv_neigh_ifinfo *neigh_ifinfo; struct batadv_neigh_ifinfo *neigh_ifinfo;
u8 total_count; u8 total_count;
u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own; 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 neigh_rq_inv_cube, neigh_rq_max_cube;
unsigned int tq_asym_penalty, inv_asym_penalty; unsigned int tq_asym_penalty, inv_asym_penalty;
unsigned int combined_tq; unsigned int combined_tq;
unsigned int tq_iface_penalty;
bool ret = false; bool ret = false;
/* find corresponding one hop neighbor */ /* find corresponding one hop neighbor */
@ -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 = BATADV_TQ_MAX_VALUE * neigh_rq_inv_cube;
inv_asym_penalty /= neigh_rq_max_cube; inv_asym_penalty /= neigh_rq_max_cube;
tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty; 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 /* penalize if the OGM is forwarded on the same interface. WiFi
* interfaces and other half duplex devices suffer from throughput * interfaces and other half duplex devices suffer from throughput
* drops as they can't send and receive at the same time. * 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 && if (if_outgoing && if_incoming == if_outgoing &&
batadv_is_wifi_hardif(if_outgoing)) batadv_is_wifi_hardif(if_outgoing))
tq_iface_penalty = batadv_hop_penalty(BATADV_TQ_MAX_VALUE, tq_iface_hop_penalty = batadv_hop_penalty(tq_iface_hop_penalty,
bat_priv); bat_priv);
combined_tq = batadv_ogm_packet->tq * combined_tq = batadv_ogm_packet->tq *
tq_own * tq_own *
tq_asym_penalty * tq_asym_penalty *
tq_iface_penalty; tq_iface_hop_penalty;
combined_tq /= BATADV_TQ_MAX_VALUE * combined_tq /= BATADV_TQ_MAX_VALUE *
BATADV_TQ_MAX_VALUE * BATADV_TQ_MAX_VALUE *
BATADV_TQ_MAX_VALUE; BATADV_TQ_MAX_VALUE;
batadv_ogm_packet->tq = combined_tq; batadv_ogm_packet->tq = combined_tq;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 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, orig_node->orig, orig_neigh_node->orig, total_count,
neigh_rq_count, tq_own, tq_asym_penalty, tq_iface_penalty, neigh_rq_count, tq_own, tq_asym_penalty,
batadv_ogm_packet->tq, if_incoming->net_dev->name, tq_iface_hop_penalty, batadv_ogm_packet->tq,
if_incoming->net_dev->name,
if_outgoing ? if_outgoing->net_dev->name : "DEFAULT"); if_outgoing ? if_outgoing->net_dev->name : "DEFAULT");
/* if link has the minimum required transmission quality /* if link has the minimum required transmission quality

View File

@ -455,15 +455,17 @@ unlock:
* @throughput: the current throughput * @throughput: the current throughput
* *
* Apply a penalty on the current throughput metric value based on the * Apply a penalty on the current throughput metric value based on the
* characteristic of the interface where the OGM has been received. The return * characteristic of the interface where the OGM has been received.
* value is computed as follows: *
* 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 * - throughput * 50% if the incoming and outgoing interface are the
* same WiFi interface and the throughput is above * same WiFi interface and the throughput is above
* 1MBit/s * 1MBit/s
* - throughput if the outgoing interface is the default * - throughput if the outgoing interface is the default
* interface (i.e. this OGM is processed for the * interface (i.e. this OGM is processed for the
* internal table and not forwarded) * internal table and not forwarded)
* - throughput * hop penalty otherwise * - throughput * node hop penalty otherwise
* *
* Return: the penalised throughput metric. * Return: the penalised throughput metric.
*/ */
@ -472,9 +474,14 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_outgoing, struct batadv_hard_iface *if_outgoing,
u32 throughput) u32 throughput)
{ {
int if_hop_penalty = atomic_read(&if_incoming->hop_penalty);
int hop_penalty = atomic_read(&bat_priv->hop_penalty); int hop_penalty = atomic_read(&bat_priv->hop_penalty);
int hop_penalty_max = BATADV_TQ_MAX_VALUE; 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. */ /* Don't apply hop penalty in default originator table. */
if (if_outgoing == BATADV_IF_DEFAULT) if (if_outgoing == BATADV_IF_DEFAULT)
return throughput; return throughput;

View File

@ -939,6 +939,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
if (batadv_is_wifi_hardif(hard_iface)) if (batadv_is_wifi_hardif(hard_iface))
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
atomic_set(&hard_iface->hop_penalty, 0);
batadv_v_hardif_init(hard_iface); batadv_v_hardif_init(hard_iface);
batadv_check_known_mac_addr(hard_iface->net_dev); batadv_check_known_mac_addr(hard_iface->net_dev);

View File

@ -826,6 +826,10 @@ static int batadv_netlink_hardif_fill(struct sk_buff *msg,
goto nla_put_failure; 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 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL, if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL,
atomic_read(&hard_iface->bat_v.elp_interval))) atomic_read(&hard_iface->bat_v.elp_interval)))
@ -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_hard_iface *hard_iface = info->user_ptr[1];
struct batadv_priv *bat_priv = info->user_ptr[0]; 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 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
struct nlattr *attr;
if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) { if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) {
attr = info->attrs[BATADV_ATTR_ELP_INTERVAL]; attr = info->attrs[BATADV_ATTR_ELP_INTERVAL];

View File

@ -208,6 +208,12 @@ struct batadv_hard_iface {
/** @rcu: struct used for freeing in an RCU-safe manner */ /** @rcu: struct used for freeing in an RCU-safe manner */
struct rcu_head rcu; 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 */ /** @bat_iv: per hard-interface B.A.T.M.A.N. IV data */
struct batadv_hard_iface_bat_iv bat_iv; struct batadv_hard_iface_bat_iv bat_iv;