@@ -948,16 +948,25 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
948948 int tt_diff_len , tt_change_len = 0 ;
949949 int tt_diff_entries_num = 0 ;
950950 int tt_diff_entries_count = 0 ;
951+ bool drop_changes = false;
952+ size_t tt_extra_len = 0 ;
951953 u16 tvlv_len ;
952954
953955 tt_diff_entries_num = atomic_read (& bat_priv -> tt .local_changes );
954956 tt_diff_len = batadv_tt_len (tt_diff_entries_num );
955957
956958 /* if we have too many changes for one packet don't send any
957- * and wait for the tt table request which will be fragmented
959+ * and wait for the tt table request so we can reply with the full
960+ * (fragmented) table.
961+ *
962+ * The local change history should still be cleaned up so the next
963+ * TT round can start again with a clean state.
958964 */
959- if (tt_diff_len > bat_priv -> soft_iface -> mtu )
965+ if (tt_diff_len > bat_priv -> soft_iface -> mtu ) {
960966 tt_diff_len = 0 ;
967+ tt_diff_entries_num = 0 ;
968+ drop_changes = true;
969+ }
961970
962971 tvlv_len = batadv_tt_prepare_tvlv_local_data (bat_priv , & tt_data ,
963972 & tt_change , & tt_diff_len );
@@ -966,7 +975,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
966975
967976 tt_data -> flags = BATADV_TT_OGM_DIFF ;
968977
969- if (tt_diff_len == 0 )
978+ if (! drop_changes && tt_diff_len == 0 )
970979 goto container_register ;
971980
972981 spin_lock_bh (& bat_priv -> tt .changes_list_lock );
@@ -985,6 +994,9 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
985994 }
986995 spin_unlock_bh (& bat_priv -> tt .changes_list_lock );
987996
997+ tt_extra_len = batadv_tt_len (tt_diff_entries_num -
998+ tt_diff_entries_count );
999+
9881000 /* Keep the buffer for possible tt_request */
9891001 spin_lock_bh (& bat_priv -> tt .last_changeset_lock );
9901002 kfree (bat_priv -> tt .last_changeset );
@@ -993,6 +1005,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
9931005 tt_change_len = batadv_tt_len (tt_diff_entries_count );
9941006 /* check whether this new OGM has no changes due to size problems */
9951007 if (tt_diff_entries_count > 0 ) {
1008+ tt_diff_len -= tt_extra_len ;
9961009 /* if kmalloc() fails we will reply with the full table
9971010 * instead of providing the diff
9981011 */
@@ -1005,6 +1018,8 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
10051018 }
10061019 spin_unlock_bh (& bat_priv -> tt .last_changeset_lock );
10071020
1021+ /* Remove extra packet space for OGM */
1022+ tvlv_len -= tt_extra_len ;
10081023container_register :
10091024 batadv_tvlv_container_register (bat_priv , BATADV_TVLV_TT , 1 , tt_data ,
10101025 tvlv_len );
@@ -2705,14 +2720,16 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
27052720 *
27062721 * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
27072722 * is not provided then this becomes a no-op.
2723+ *
2724+ * Return: Remaining unused length in tvlv_buff.
27082725 */
2709- static void batadv_tt_tvlv_generate (struct batadv_priv * bat_priv ,
2710- struct batadv_hashtable * hash ,
2711- void * tvlv_buff , u16 tt_len ,
2712- bool (* valid_cb )(const void * ,
2713- const void * ,
2714- u8 * flags ),
2715- void * cb_data )
2726+ static u16 batadv_tt_tvlv_generate (struct batadv_priv * bat_priv ,
2727+ struct batadv_hashtable * hash ,
2728+ void * tvlv_buff , u16 tt_len ,
2729+ bool (* valid_cb )(const void * ,
2730+ const void * ,
2731+ u8 * flags ),
2732+ void * cb_data )
27162733{
27172734 struct batadv_tt_common_entry * tt_common_entry ;
27182735 struct batadv_tvlv_tt_change * tt_change ;
@@ -2726,7 +2743,7 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
27262743 tt_change = tvlv_buff ;
27272744
27282745 if (!valid_cb )
2729- return ;
2746+ return tt_len ;
27302747
27312748 rcu_read_lock ();
27322749 for (i = 0 ; i < hash -> size ; i ++ ) {
@@ -2752,6 +2769,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
27522769 }
27532770 }
27542771 rcu_read_unlock ();
2772+
2773+ return batadv_tt_len (tt_tot - tt_num_entries );
27552774}
27562775
27572776/**
@@ -3022,10 +3041,11 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
30223041 goto out ;
30233042
30243043 /* fill the rest of the tvlv with the real TT entries */
3025- batadv_tt_tvlv_generate (bat_priv , bat_priv -> tt .global_hash ,
3026- tt_change , tt_len ,
3027- batadv_tt_global_valid ,
3028- req_dst_orig_node );
3044+ tvlv_len -= batadv_tt_tvlv_generate (bat_priv ,
3045+ bat_priv -> tt .global_hash ,
3046+ tt_change , tt_len ,
3047+ batadv_tt_global_valid ,
3048+ req_dst_orig_node );
30293049 }
30303050
30313051 /* Don't send the response, if larger than fragmented packet. */
@@ -3149,9 +3169,11 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
31493169 goto out ;
31503170
31513171 /* fill the rest of the tvlv with the real TT entries */
3152- batadv_tt_tvlv_generate (bat_priv , bat_priv -> tt .local_hash ,
3153- tt_change , tt_len ,
3154- batadv_tt_local_valid , NULL );
3172+ tvlv_len -= batadv_tt_tvlv_generate (bat_priv ,
3173+ bat_priv -> tt .local_hash ,
3174+ tt_change , tt_len ,
3175+ batadv_tt_local_valid ,
3176+ NULL );
31553177 }
31563178
31573179 tvlv_tt_data -> flags = BATADV_TT_RESPONSE ;
0 commit comments