History

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.

Linus Lüssing committed 6 years ago

Commit 3bda14d1 parent bccb48c6 files · +40 −13Browse files

Unified · Split

6 files
  1. include/uapi/linux/batman_adv.h +2 −1
  2. net/batman-adv/bat_iv_ogm.c +9 −8
  3. net/batman-adv/bat_v_ogm.c +10 −3
  4. net/batman-adv/hard-interface.c +2 −0
  5. net/batman-adv/netlink.c +11 −1
  6. net/batman-adv/types.h +6 −0
include/uapi/linux/batman_adv.h+2−1
@@ -427,7 +427,8 @@ enum batadv_nl_attrs { · 426 unmodified lines
427427
428428 /**
429429 * @BATADV_ATTR_HOP_PENALTY: defines the penalty which will be applied
430− * to an originator message's tq-field on every hop.
430+ * to an originator message's tq-field on every hop and/or per
431+ * hard interface
431432 */
432433 BATADV_ATTR_HOP_PENALTY,
433434
net/batman-adv/bat_iv_ogm.c+9−8
@@ -1075,10 +1075,10 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, · 1074 unmodified lines
10751075 struct batadv_neigh_ifinfo *neigh_ifinfo;
10761076 u8 total_count;
10771077 u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own;
1078+ unsigned int tq_iface_hop_penalty = BATADV_TQ_MAX_VALUE;
10781079 unsigned int neigh_rq_inv_cube, neigh_rq_max_cube;
10791080 unsigned int tq_asym_penalty, inv_asym_penalty;
10801081 unsigned int combined_tq;
1081− unsigned int tq_iface_penalty;
10821082 bool ret = false;
10831083
10841084 /* find corresponding one hop neighbor */
@@ -1157,31 +1157,32 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, · 72 unmodified lines
11571157 inv_asym_penalty = BATADV_TQ_MAX_VALUE * neigh_rq_inv_cube;
11581158 inv_asym_penalty /= neigh_rq_max_cube;
11591159 tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty;
1160+ tq_iface_hop_penalty -= atomic_read(&if_incoming->hop_penalty);
11601161
11611162 /* penalize if the OGM is forwarded on the same interface. WiFi
11621163 * interfaces and other half duplex devices suffer from throughput
11631164 * drops as they can't send and receive at the same time.
11641165 */
1165− tq_iface_penalty = BATADV_TQ_MAX_VALUE;
11661166 if (if_outgoing && if_incoming == if_outgoing &&
11671167 batadv_is_wifi_hardif(if_outgoing))
1168− tq_iface_penalty = batadv_hop_penalty(BATADV_TQ_MAX_VALUE,
1169− bat_priv);
1168+ tq_iface_hop_penalty = batadv_hop_penalty(tq_iface_hop_penalty,
1169+ bat_priv);
11701170
11711171 combined_tq = batadv_ogm_packet->tq *
11721172 tq_own *
11731173 tq_asym_penalty *
1174− tq_iface_penalty;
1174+ tq_iface_hop_penalty;
11751175 combined_tq /= BATADV_TQ_MAX_VALUE *
11761176 BATADV_TQ_MAX_VALUE *
11771177 BATADV_TQ_MAX_VALUE;
11781178 batadv_ogm_packet->tq = combined_tq;
11791179
11801180 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1181− "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",
1181+ "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",
11821182 orig_node->orig, orig_neigh_node->orig, total_count,
1183− neigh_rq_count, tq_own, tq_asym_penalty, tq_iface_penalty,
1184− batadv_ogm_packet->tq, if_incoming->net_dev->name,
1183+ neigh_rq_count, tq_own, tq_asym_penalty,
1184+ tq_iface_hop_penalty, batadv_ogm_packet->tq,
1185+ if_incoming->net_dev->name,
11851186 if_outgoing ? if_outgoing->net_dev->name : "DEFAULT");
11861187
11871188 /* if link has the minimum required transmission quality
net/batman-adv/bat_v_ogm.c+10−3
@@ -455,15 +455,17 @@ unlock: · 454 unmodified lines
455455 * @throughput: the current throughput
456456 *
457457 * Apply a penalty on the current throughput metric value based on the
458− * characteristic of the interface where the OGM has been received. The return
459− * value is computed as follows:
458+ * characteristic of the interface where the OGM has been received.
459+ *
460+ * Initially the per hardif hop penalty is applied to the throughput. After
461+ * that the return value is then computed as follows:
460462 * - throughput * 50% if the incoming and outgoing interface are the
461463 * same WiFi interface and the throughput is above
462464 * 1MBit/s
463465 * - throughput if the outgoing interface is the default
464466 * interface (i.e. this OGM is processed for the
465467 * internal table and not forwarded)
466− * - throughput * hop penalty otherwise
468+ * - throughput * node hop penalty otherwise
467469 *
468470 * Return: the penalised throughput metric.
469471 */
@@ -472,9 +474,14 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv, · 2 unmodified lines
472474 struct batadv_hard_iface *if_outgoing,
473475 u32 throughput)
474476 {
477+ int if_hop_penalty = atomic_read(&if_incoming->hop_penalty);
475478 int hop_penalty = atomic_read(&bat_priv->hop_penalty);
476479 int hop_penalty_max = BATADV_TQ_MAX_VALUE;
477480
481+ /* Apply per hardif hop penalty */
482+ throughput = throughput * (hop_penalty_max - if_hop_penalty) /
483+ hop_penalty_max;
484+
478485 /* Don't apply hop penalty in default originator table. */
479486 if (if_outgoing == BATADV_IF_DEFAULT)
480487 return throughput;
net/batman-adv/hard-interface.c+2−0
@@ -939,6 +939,8 @@ batadv_hardif_add_interface(struct net_device *net_dev) · 938 unmodified lines
939939 if (batadv_is_wifi_hardif(hard_iface))
940940 hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
941941
942+ atomic_set(&hard_iface->hop_penalty, 0);
943+
942944 batadv_v_hardif_init(hard_iface);
943945
944946 batadv_check_known_mac_addr(hard_iface->net_dev);
net/batman-adv/netlink.c+11−1
@@ -826,6 +826,10 @@ static int batadv_netlink_hardif_fill(struct sk_buff *msg, · 825 unmodified lines
826826 goto nla_put_failure;
827827 }
828828
829+ if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
830+ atomic_read(&hard_iface->hop_penalty)))
831+ goto nla_put_failure;
832+
829833 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
830834 if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL,
831835 atomic_read(&hard_iface->bat_v.elp_interval)))
@@ -920,9 +924,15 @@ static int batadv_netlink_set_hardif(struct sk_buff *skb, · 88 unmodified lines
920924 {
921925 struct batadv_hard_iface *hard_iface = info->user_ptr[1];
922926 struct batadv_priv *bat_priv = info->user_ptr[0];
927+ struct nlattr *attr;
928+
929+ if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
930+ attr = info->attrs[BATADV_ATTR_HOP_PENALTY];
931+
932+ atomic_set(&hard_iface->hop_penalty, nla_get_u8(attr));
933+ }
923934
924935 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
925− struct nlattr *attr;
926936
927937 if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) {
928938 attr = info->attrs[BATADV_ATTR_ELP_INTERVAL];
net/batman-adv/types.h+6−0
@@ -208,6 +208,12 @@ struct batadv_hard_iface { · 207 unmodified lines
208208 /** @rcu: struct used for freeing in an RCU-safe manner */
209209 struct rcu_head rcu;
210210
211+ /**
212+ * @hop_penalty: penalty which will be applied to the tq-field
213+ * of an OGM received via this interface
214+ */
215+ atomic_t hop_penalty;
216+
211217 /** @bat_iv: per hard-interface B.A.T.M.A.N. IV data */
212218 struct batadv_hard_iface_bat_iv bat_iv;
213219