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.
Unified · Split
| @@ -427,7 +427,8 @@ enum batadv_nl_attrs { · 426 unmodified lines | |||
| 427 | 427 | ||
| 428 | /** | 428 | /** |
| 429 | * @BATADV_ATTR_HOP_PENALTY: defines the penalty which will be applied | 429 | * @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 | ||
| 431 | */ | 432 | */ |
| 432 | BATADV_ATTR_HOP_PENALTY, | 433 | BATADV_ATTR_HOP_PENALTY, |
| 433 | 434 | ||
| @@ -1075,10 +1075,10 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, · 1074 unmodified lines | |||
| 1075 | struct batadv_neigh_ifinfo *neigh_ifinfo; | 1075 | struct batadv_neigh_ifinfo *neigh_ifinfo; |
| 1076 | u8 total_count; | 1076 | u8 total_count; |
| 1077 | u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own; | 1077 | u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own; |
| 1078 | unsigned int tq_iface_hop_penalty = BATADV_TQ_MAX_VALUE; | ||
| 1078 | unsigned int neigh_rq_inv_cube, neigh_rq_max_cube; | 1079 | unsigned int neigh_rq_inv_cube, neigh_rq_max_cube; |
| 1079 | unsigned int tq_asym_penalty, inv_asym_penalty; | 1080 | unsigned int tq_asym_penalty, inv_asym_penalty; |
| 1080 | unsigned int combined_tq; | 1081 | unsigned int combined_tq; |
| 1081 | unsigned int tq_iface_penalty; | ||
| 1082 | bool ret = false; | 1082 | bool ret = false; |
| 1083 | 1083 | ||
| 1084 | /* find corresponding one hop neighbor */ | 1084 | /* 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 | |||
| 1157 | inv_asym_penalty = BATADV_TQ_MAX_VALUE * neigh_rq_inv_cube; | 1157 | inv_asym_penalty = BATADV_TQ_MAX_VALUE * neigh_rq_inv_cube; |
| 1158 | inv_asym_penalty /= neigh_rq_max_cube; | 1158 | inv_asym_penalty /= neigh_rq_max_cube; |
| 1159 | tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty; | 1159 | tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty; |
| 1160 | tq_iface_hop_penalty -= atomic_read(&if_incoming->hop_penalty); | ||
| 1160 | 1161 | ||
| 1161 | /* penalize if the OGM is forwarded on the same interface. WiFi | 1162 | /* penalize if the OGM is forwarded on the same interface. WiFi |
| 1162 | * interfaces and other half duplex devices suffer from throughput | 1163 | * interfaces and other half duplex devices suffer from throughput |
| 1163 | * drops as they can't send and receive at the same time. | 1164 | * drops as they can't send and receive at the same time. |
| 1164 | */ | 1165 | */ |
| 1165 | tq_iface_penalty = BATADV_TQ_MAX_VALUE; | ||
| 1166 | if (if_outgoing && if_incoming == if_outgoing && | 1166 | if (if_outgoing && if_incoming == if_outgoing && |
| 1167 | batadv_is_wifi_hardif(if_outgoing)) | 1167 | batadv_is_wifi_hardif(if_outgoing)) |
| 1168 | tq_iface_penalty = batadv_hop_penalty(BATADV_TQ_MAX_VALUE, | 1168 | tq_iface_hop_penalty = batadv_hop_penalty(tq_iface_hop_penalty, |
| 1169 | bat_priv); | 1169 | bat_priv); |
| 1170 | 1170 | ||
| 1171 | combined_tq = batadv_ogm_packet->tq * | 1171 | combined_tq = batadv_ogm_packet->tq * |
| 1172 | tq_own * | 1172 | tq_own * |
| 1173 | tq_asym_penalty * | 1173 | tq_asym_penalty * |
| 1174 | tq_iface_penalty; | 1174 | tq_iface_hop_penalty; |
| 1175 | combined_tq /= BATADV_TQ_MAX_VALUE * | 1175 | combined_tq /= BATADV_TQ_MAX_VALUE * |
| 1176 | BATADV_TQ_MAX_VALUE * | 1176 | BATADV_TQ_MAX_VALUE * |
| 1177 | BATADV_TQ_MAX_VALUE; | 1177 | BATADV_TQ_MAX_VALUE; |
| 1178 | batadv_ogm_packet->tq = combined_tq; | 1178 | batadv_ogm_packet->tq = combined_tq; |
| 1179 | 1179 | ||
| 1180 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1180 | 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", |
| 1182 | orig_node->orig, orig_neigh_node->orig, total_count, | 1182 | orig_node->orig, orig_neigh_node->orig, total_count, |
| 1183 | neigh_rq_count, tq_own, tq_asym_penalty, tq_iface_penalty, | 1183 | neigh_rq_count, tq_own, tq_asym_penalty, |
| 1184 | batadv_ogm_packet->tq, if_incoming->net_dev->name, | 1184 | tq_iface_hop_penalty, batadv_ogm_packet->tq, |
| 1185 | if_incoming->net_dev->name, | ||
| 1185 | if_outgoing ? if_outgoing->net_dev->name : "DEFAULT"); | 1186 | if_outgoing ? if_outgoing->net_dev->name : "DEFAULT"); |
| 1186 | 1187 | ||
| 1187 | /* if link has the minimum required transmission quality | 1188 | /* if link has the minimum required transmission quality |
| @@ -455,15 +455,17 @@ unlock: · 454 unmodified lines | |||
| 455 | * @throughput: the current throughput | 455 | * @throughput: the current throughput |
| 456 | * | 456 | * |
| 457 | * Apply a penalty on the current throughput metric value based on the | 457 | * 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 | 458 | * characteristic of the interface where the OGM has been received. |
| 459 | * value is computed as follows: | 459 | * |
| 460 | * Initially the per hardif hop penalty is applied to the throughput. After | ||
| 461 | * that the return value is then computed as follows: | ||
| 460 | * - throughput * 50% if the incoming and outgoing interface are the | 462 | * - throughput * 50% if the incoming and outgoing interface are the |
| 461 | * same WiFi interface and the throughput is above | 463 | * same WiFi interface and the throughput is above |
| 462 | * 1MBit/s | 464 | * 1MBit/s |
| 463 | * - throughput if the outgoing interface is the default | 465 | * - throughput if the outgoing interface is the default |
| 464 | * interface (i.e. this OGM is processed for the | 466 | * interface (i.e. this OGM is processed for the |
| 465 | * internal table and not forwarded) | 467 | * internal table and not forwarded) |
| 466 | * - throughput * hop penalty otherwise | 468 | * - throughput * node hop penalty otherwise |
| 467 | * | 469 | * |
| 468 | * Return: the penalised throughput metric. | 470 | * Return: the penalised throughput metric. |
| 469 | */ | 471 | */ |
| @@ -472,9 +474,14 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv, · 2 unmodified lines | |||
| 472 | struct batadv_hard_iface *if_outgoing, | 474 | struct batadv_hard_iface *if_outgoing, |
| 473 | u32 throughput) | 475 | u32 throughput) |
| 474 | { | 476 | { |
| 477 | int if_hop_penalty = atomic_read(&if_incoming->hop_penalty); | ||
| 475 | int hop_penalty = atomic_read(&bat_priv->hop_penalty); | 478 | int hop_penalty = atomic_read(&bat_priv->hop_penalty); |
| 476 | int hop_penalty_max = BATADV_TQ_MAX_VALUE; | 479 | int hop_penalty_max = BATADV_TQ_MAX_VALUE; |
| 477 | 480 | ||
| 481 | /* Apply per hardif hop penalty */ | ||
| 482 | throughput = throughput * (hop_penalty_max - if_hop_penalty) / | ||
| 483 | hop_penalty_max; | ||
| 484 | |||
| 478 | /* Don't apply hop penalty in default originator table. */ | 485 | /* Don't apply hop penalty in default originator table. */ |
| 479 | if (if_outgoing == BATADV_IF_DEFAULT) | 486 | if (if_outgoing == BATADV_IF_DEFAULT) |
| 480 | return throughput; | 487 | return throughput; |
| @@ -939,6 +939,8 @@ batadv_hardif_add_interface(struct net_device *net_dev) · 938 unmodified lines | |||
| 939 | if (batadv_is_wifi_hardif(hard_iface)) | 939 | if (batadv_is_wifi_hardif(hard_iface)) |
| 940 | hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; | 940 | hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; |
| 941 | 941 | ||
| 942 | atomic_set(&hard_iface->hop_penalty, 0); | ||
| 943 | |||
| 942 | batadv_v_hardif_init(hard_iface); | 944 | batadv_v_hardif_init(hard_iface); |
| 943 | 945 | ||
| 944 | batadv_check_known_mac_addr(hard_iface->net_dev); | 946 | batadv_check_known_mac_addr(hard_iface->net_dev); |
| @@ -826,6 +826,10 @@ static int batadv_netlink_hardif_fill(struct sk_buff *msg, · 825 unmodified lines | |||
| 826 | goto nla_put_failure; | 826 | goto nla_put_failure; |
| 827 | } | 827 | } |
| 828 | 828 | ||
| 829 | if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY, | ||
| 830 | atomic_read(&hard_iface->hop_penalty))) | ||
| 831 | goto nla_put_failure; | ||
| 832 | |||
| 829 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 833 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
| 830 | if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL, | 834 | if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL, |
| 831 | atomic_read(&hard_iface->bat_v.elp_interval))) | 835 | 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 | |||
| 920 | { | 924 | { |
| 921 | struct batadv_hard_iface *hard_iface = info->user_ptr[1]; | 925 | struct batadv_hard_iface *hard_iface = info->user_ptr[1]; |
| 922 | struct batadv_priv *bat_priv = info->user_ptr[0]; | 926 | 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 | } | ||
| 923 | 934 | ||
| 924 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 935 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
| 925 | struct nlattr *attr; | ||
| 926 | 936 | ||
| 927 | if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) { | 937 | if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) { |
| 928 | attr = info->attrs[BATADV_ATTR_ELP_INTERVAL]; | 938 | attr = info->attrs[BATADV_ATTR_ELP_INTERVAL]; |
| @@ -208,6 +208,12 @@ struct batadv_hard_iface { · 207 unmodified lines | |||
| 208 | /** @rcu: struct used for freeing in an RCU-safe manner */ | 208 | /** @rcu: struct used for freeing in an RCU-safe manner */ |
| 209 | struct rcu_head rcu; | 209 | struct rcu_head rcu; |
| 210 | 210 | ||
| 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 | |||
| 211 | /** @bat_iv: per hard-interface B.A.T.M.A.N. IV data */ | 217 | /** @bat_iv: per hard-interface B.A.T.M.A.N. IV data */ |
| 212 | struct batadv_hard_iface_bat_iv bat_iv; | 218 | struct batadv_hard_iface_bat_iv bat_iv; |
| 213 | 219 | ||