|
@@ -1079,8 +1079,9 @@ out:
|
|
|
return skb;
|
|
|
}
|
|
|
|
|
|
-int send_tt_request(struct bat_priv *bat_priv, struct orig_node *dst_orig_node,
|
|
|
- uint8_t ttvn, uint16_t tt_crc, bool full_table)
|
|
|
+static int send_tt_request(struct bat_priv *bat_priv,
|
|
|
+ struct orig_node *dst_orig_node,
|
|
|
+ uint8_t ttvn, uint16_t tt_crc, bool full_table)
|
|
|
{
|
|
|
struct sk_buff *skb = NULL;
|
|
|
struct tt_query_packet *tt_request;
|
|
@@ -1455,9 +1456,10 @@ out:
|
|
|
orig_node_free_ref(orig_node);
|
|
|
}
|
|
|
|
|
|
-void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
|
|
- uint16_t tt_num_changes, uint8_t ttvn,
|
|
|
- struct tt_change *tt_change)
|
|
|
+static void tt_update_changes(struct bat_priv *bat_priv,
|
|
|
+ struct orig_node *orig_node,
|
|
|
+ uint16_t tt_num_changes, uint8_t ttvn,
|
|
|
+ struct tt_change *tt_change)
|
|
|
{
|
|
|
_tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes,
|
|
|
ttvn);
|
|
@@ -1802,3 +1804,60 @@ out:
|
|
|
tt_local_entry_free_ref(tt_local_entry);
|
|
|
return ret;
|
|
|
}
|
|
|
+
|
|
|
+void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
|
|
+ const unsigned char *tt_buff, uint8_t tt_num_changes,
|
|
|
+ uint8_t ttvn, uint16_t tt_crc)
|
|
|
+{
|
|
|
+ uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
|
|
|
+ bool full_table = true;
|
|
|
+
|
|
|
+ /* the ttvn increased by one -> we can apply the attached changes */
|
|
|
+ if (ttvn - orig_ttvn == 1) {
|
|
|
+ /* the OGM could not contain the changes due to their size or
|
|
|
+ * because they have already been sent TT_OGM_APPEND_MAX times.
|
|
|
+ * In this case send a tt request */
|
|
|
+ if (!tt_num_changes) {
|
|
|
+ full_table = false;
|
|
|
+ goto request_table;
|
|
|
+ }
|
|
|
+
|
|
|
+ tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
|
|
|
+ (struct tt_change *)tt_buff);
|
|
|
+
|
|
|
+ /* Even if we received the precomputed crc with the OGM, we
|
|
|
+ * prefer to recompute it to spot any possible inconsistency
|
|
|
+ * in the global table */
|
|
|
+ orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
|
|
|
+
|
|
|
+ /* The ttvn alone is not enough to guarantee consistency
|
|
|
+ * because a single value could represent different states
|
|
|
+ * (due to the wrap around). Thus a node has to check whether
|
|
|
+ * the resulting table (after applying the changes) is still
|
|
|
+ * consistent or not. E.g. a node could disconnect while its
|
|
|
+ * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
|
|
|
+ * checking the CRC value is mandatory to detect the
|
|
|
+ * inconsistency */
|
|
|
+ if (orig_node->tt_crc != tt_crc)
|
|
|
+ goto request_table;
|
|
|
+
|
|
|
+ /* Roaming phase is over: tables are in sync again. I can
|
|
|
+ * unset the flag */
|
|
|
+ orig_node->tt_poss_change = false;
|
|
|
+ } else {
|
|
|
+ /* if we missed more than one change or our tables are not
|
|
|
+ * in sync anymore -> request fresh tt data */
|
|
|
+ if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
|
|
|
+request_table:
|
|
|
+ bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
|
|
|
+ "Need to retrieve the correct information "
|
|
|
+ "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
|
|
|
+ "%u num_changes: %u)\n", orig_node->orig, ttvn,
|
|
|
+ orig_ttvn, tt_crc, orig_node->tt_crc,
|
|
|
+ tt_num_changes);
|
|
|
+ send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
|
|
|
+ full_table);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|