@@ -948,16 +948,25 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
948
948
int tt_diff_len , tt_change_len = 0 ;
949
949
int tt_diff_entries_num = 0 ;
950
950
int tt_diff_entries_count = 0 ;
951
+ bool drop_changes = false;
952
+ size_t tt_extra_len = 0 ;
951
953
u16 tvlv_len ;
952
954
953
955
tt_diff_entries_num = atomic_read (& bat_priv -> tt .local_changes );
954
956
tt_diff_len = batadv_tt_len (tt_diff_entries_num );
955
957
956
958
/* 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.
958
964
*/
959
- if (tt_diff_len > bat_priv -> soft_iface -> mtu )
965
+ if (tt_diff_len > bat_priv -> soft_iface -> mtu ) {
960
966
tt_diff_len = 0 ;
967
+ tt_diff_entries_num = 0 ;
968
+ drop_changes = true;
969
+ }
961
970
962
971
tvlv_len = batadv_tt_prepare_tvlv_local_data (bat_priv , & tt_data ,
963
972
& tt_change , & tt_diff_len );
@@ -966,7 +975,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
966
975
967
976
tt_data -> flags = BATADV_TT_OGM_DIFF ;
968
977
969
- if (tt_diff_len == 0 )
978
+ if (! drop_changes && tt_diff_len == 0 )
970
979
goto container_register ;
971
980
972
981
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)
985
994
}
986
995
spin_unlock_bh (& bat_priv -> tt .changes_list_lock );
987
996
997
+ tt_extra_len = batadv_tt_len (tt_diff_entries_num -
998
+ tt_diff_entries_count );
999
+
988
1000
/* Keep the buffer for possible tt_request */
989
1001
spin_lock_bh (& bat_priv -> tt .last_changeset_lock );
990
1002
kfree (bat_priv -> tt .last_changeset );
@@ -993,6 +1005,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
993
1005
tt_change_len = batadv_tt_len (tt_diff_entries_count );
994
1006
/* check whether this new OGM has no changes due to size problems */
995
1007
if (tt_diff_entries_count > 0 ) {
1008
+ tt_diff_len -= tt_extra_len ;
996
1009
/* if kmalloc() fails we will reply with the full table
997
1010
* instead of providing the diff
998
1011
*/
@@ -1005,6 +1018,8 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
1005
1018
}
1006
1019
spin_unlock_bh (& bat_priv -> tt .last_changeset_lock );
1007
1020
1021
+ /* Remove extra packet space for OGM */
1022
+ tvlv_len -= tt_extra_len ;
1008
1023
container_register :
1009
1024
batadv_tvlv_container_register (bat_priv , BATADV_TVLV_TT , 1 , tt_data ,
1010
1025
tvlv_len );
@@ -2705,14 +2720,16 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
2705
2720
*
2706
2721
* Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
2707
2722
* is not provided then this becomes a no-op.
2723
+ *
2724
+ * Return: Remaining unused length in tvlv_buff.
2708
2725
*/
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 )
2716
2733
{
2717
2734
struct batadv_tt_common_entry * tt_common_entry ;
2718
2735
struct batadv_tvlv_tt_change * tt_change ;
@@ -2726,7 +2743,7 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
2726
2743
tt_change = tvlv_buff ;
2727
2744
2728
2745
if (!valid_cb )
2729
- return ;
2746
+ return tt_len ;
2730
2747
2731
2748
rcu_read_lock ();
2732
2749
for (i = 0 ; i < hash -> size ; i ++ ) {
@@ -2752,6 +2769,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
2752
2769
}
2753
2770
}
2754
2771
rcu_read_unlock ();
2772
+
2773
+ return batadv_tt_len (tt_tot - tt_num_entries );
2755
2774
}
2756
2775
2757
2776
/**
@@ -3022,10 +3041,11 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
3022
3041
goto out ;
3023
3042
3024
3043
/* 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 );
3029
3049
}
3030
3050
3031
3051
/* 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,
3149
3169
goto out ;
3150
3170
3151
3171
/* 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 );
3155
3177
}
3156
3178
3157
3179
tvlv_tt_data -> flags = BATADV_TT_RESPONSE ;
0 commit comments