@@ -492,6 +492,53 @@ out:
}
/**
+ * batadv_v_ogm_seq_tx - penalize router throughput
+ * @router_throughput: the router throughput to penalize
+ * @seq_diff: seqno diff between OGM and current router
+ */
+static u32 batadv_v_ogm_seq_tx(u32 router_throughput, u32 seq_diff)
+{
+ const u32 m = BATADV_OGM_MAX_ORIGDIFF;
+ const u32 r = router_throughput;
+ const u32 d = seq_diff;
+ u64 ret;
+
+ if (s <= 1)
+ return r;
+ else if (s >= d)
+ return 0;
+
+ /* f(x) = [ - 1/(m-1)^2 * (d-1)^2 + 1 ] * r */
+ ret = r * (m-1) * (m-1) - r * (d-1) * (d-1)
+ return (u32)(ret / ( (m-1) * (m-1) ));
+
+ /**
+ * For BATADV_OGM_MAX_ORIGDIFF == 5 equivalent to:
+ */
+ switch(seq_diff) {
+ case 0:
+ /* fallthrough */
+ case 1:
+ /* no penalty for seq-diff == 1 either,
+ * maybe the best route has just a little more
+ * latency
+ */
+ return router_throughput;
+ case 2:
+ /* 15/16 */
+ return 0.9375 * router_throughput;
+ case 3:
+ /* 3/4 */
+ return 0.75 * router_throughput;
+ case 4:
+ /* 7/16 */
+ return 0.4375 * router_throughput;
+ default:
+ return 0;
+ }
+}
+
+/**
* batadv_v_ogm_route_update - update routes based on OGM
* @bat_priv: the bat priv with all the soft interface information
* @ethhdr: the Ethernet header of the OGM2
@@ -570,8 +617,8 @@ static bool batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
router_throughput = router_ifinfo->bat_v.throughput;
neigh_throughput = neigh_ifinfo->bat_v.throughput;
- if ((neigh_seq_diff < BATADV_OGM_MAX_ORIGDIFF) &&
- (router_throughput >= neigh_throughput))
+ if (batadv_v_ogm_seq_tx(router_throughput, neigh_seq_diff)
+ >= neigh_throughput)
goto out;
}