@@ -84,6 +84,14 @@ enum batadv_iv_flags {
BATADV_DIRECTLINK = 1UL << 2,
};
+/**
+ * enum batadv_v_flags - flags used in B.A.T.M.A.N. V OGM2 packets
+ * @BATADV_V_HALF_DUPLEX: Half Duplex penalty should be applied to throughput
+ */
+enum batadv_v_flags {
+ BATADV_V_HALF_DUPLEX = 1UL << 0,
+};
+
/**
* enum batadv_icmp_packettype - ICMP message types
* @BATADV_ECHO_REPLY: success reply to BATADV_ECHO_REQUEST
@@ -474,12 +474,14 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_incoming,
struct batadv_hard_iface *if_outgoing,
- u32 throughput)
+ u32 throughput, bool *half_duplex)
{
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;
+ *half_duplex = false;
+
/* Apply per hardif hop penalty */
throughput = throughput * (hop_penalty_max - if_hop_penalty) /
hop_penalty_max;
@@ -494,8 +496,10 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
*/
if (throughput > 10 &&
if_incoming == if_outgoing &&
- !(if_incoming->bat_v.flags & BATADV_FULL_DUPLEX))
+ !(if_incoming->bat_v.flags & BATADV_FULL_DUPLEX)) {
+ *half_duplex = true;
return throughput / 2;
+ }
/* hop penalty of 255 equals 100% */
return throughput * (hop_penalty_max - hop_penalty) / hop_penalty_max;
@@ -573,6 +577,9 @@ static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
/* apply forward penalty */
ogm_forward = (struct batadv_ogm2_packet *)skb_buff;
+ ogm_forward->flags &= ~BATADV_V_HALF_DUPLEX;
+ if (neigh_ifinfo->bat_v.half_duplex)
+ ogm_forward->flags |= BATADV_V_HALF_DUPLEX;
ogm_forward->throughput = htonl(neigh_ifinfo->bat_v.throughput);
ogm_forward->ttl--;
@@ -615,6 +622,7 @@ static int batadv_v_ogm_metric_update(struct batadv_priv *bat_priv,
bool protection_started = false;
int ret = -EINVAL;
u32 path_throughput;
+ bool half_duplex;
s32 seq_diff;
orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
@@ -656,10 +664,12 @@ static int batadv_v_ogm_metric_update(struct batadv_priv *bat_priv,
path_throughput = batadv_v_forward_penalty(bat_priv, if_incoming,
if_outgoing,
- ntohl(ogm2->throughput));
+ ntohl(ogm2->throughput),
+ &half_duplex);
neigh_ifinfo->bat_v.throughput = path_throughput;
neigh_ifinfo->bat_v.last_seqno = ntohl(ogm2->seqno);
neigh_ifinfo->last_ttl = ogm2->ttl;
+ neigh_ifinfo->bat_v.half_duplex = half_duplex;
if (seq_diff > 0 || protection_started)
ret = 1;
@@ -842,6 +852,26 @@ batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
}
+/**
+ * batadv_v_get_throughput() - Compute path throughput from received OGM
+ * @ogm: OGM2 packet received
+ * @neigh: Neighbour OGM packet has been received from
+ * @return: Estimated path throughput
+ */
+static u32 batadv_v_get_throughput(struct batadv_ogm2_packet *ogm,
+ struct batadv_hardif_neigh_node *neigh)
+{
+ u32 oth, lth;
+
+ oth = ntohl(ogm->throughput);
+ lth = ewma_throughput_read(&neigh->bat_v.throughput);
+
+ if ((ogm->flags & BATADV_V_HALF_DUPLEX) && lth > 10)
+ lth /= 2;
+
+ return min_t(u32, lth, oth);
+}
+
/**
* batadv_v_ogm_process() - process an incoming batman v OGM
* @skb: the skb containing the OGM
@@ -858,7 +888,7 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
struct batadv_neigh_node *neigh_node = NULL;
struct batadv_hard_iface *hard_iface;
struct batadv_ogm2_packet *ogm_packet;
- u32 ogm_throughput, link_throughput, path_throughput;
+ u32 ogm_throughput, path_throughput;
int ret;
ethhdr = eth_hdr(skb);
@@ -911,9 +941,9 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
* neighbor) the path throughput metric equals the link throughput.
* - For OGMs traversing more than hop the path throughput metric is
* the smaller of the path throughput and the link throughput.
+ * - Also apply Half Duplex interfaces penalty
*/
- link_throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
- path_throughput = min_t(u32, link_throughput, ogm_throughput);
+ path_throughput = batadv_v_get_throughput(ogm_packet, hardif_neigh);
ogm_packet->throughput = htonl(path_throughput);
batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet, orig_node,
@@ -708,6 +708,9 @@ struct batadv_neigh_ifinfo_bat_v {
/** @last_seqno: last sequence number known for this neighbor */
u32 last_seqno;
+
+ /** @half_duplex: throughput should suffer half duplex penalty */
+ bool half_duplex;
};
/**