|
|
|
|
@@ -28,6 +28,7 @@
|
|
|
|
|
#include <linux/net.h>
|
|
|
|
|
#include <linux/netdevice.h>
|
|
|
|
|
#include <linux/netlink.h>
|
|
|
|
|
#include <linux/overflow.h>
|
|
|
|
|
#include <linux/rculist.h>
|
|
|
|
|
#include <linux/rcupdate.h>
|
|
|
|
|
#include <linux/skbuff.h>
|
|
|
|
|
@@ -208,20 +209,6 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
|
|
|
|
|
return tt_global_entry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* batadv_tt_local_entry_free_rcu() - free the tt_local_entry
|
|
|
|
|
* @rcu: rcu pointer of the tt_local_entry
|
|
|
|
|
*/
|
|
|
|
|
static void batadv_tt_local_entry_free_rcu(struct rcu_head *rcu)
|
|
|
|
|
{
|
|
|
|
|
struct batadv_tt_local_entry *tt_local_entry;
|
|
|
|
|
|
|
|
|
|
tt_local_entry = container_of(rcu, struct batadv_tt_local_entry,
|
|
|
|
|
common.rcu);
|
|
|
|
|
|
|
|
|
|
kmem_cache_free(batadv_tl_cache, tt_local_entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* batadv_tt_local_entry_release() - release tt_local_entry from lists and queue
|
|
|
|
|
* for free after rcu grace period
|
|
|
|
|
@@ -236,7 +223,7 @@ static void batadv_tt_local_entry_release(struct kref *ref)
|
|
|
|
|
|
|
|
|
|
batadv_softif_vlan_put(tt_local_entry->vlan);
|
|
|
|
|
|
|
|
|
|
call_rcu(&tt_local_entry->common.rcu, batadv_tt_local_entry_free_rcu);
|
|
|
|
|
kfree_rcu(tt_local_entry, common.rcu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -254,20 +241,6 @@ batadv_tt_local_entry_put(struct batadv_tt_local_entry *tt_local_entry)
|
|
|
|
|
batadv_tt_local_entry_release);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* batadv_tt_global_entry_free_rcu() - free the tt_global_entry
|
|
|
|
|
* @rcu: rcu pointer of the tt_global_entry
|
|
|
|
|
*/
|
|
|
|
|
static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
|
|
|
|
|
{
|
|
|
|
|
struct batadv_tt_global_entry *tt_global_entry;
|
|
|
|
|
|
|
|
|
|
tt_global_entry = container_of(rcu, struct batadv_tt_global_entry,
|
|
|
|
|
common.rcu);
|
|
|
|
|
|
|
|
|
|
kmem_cache_free(batadv_tg_cache, tt_global_entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* batadv_tt_global_entry_release() - release tt_global_entry from lists and
|
|
|
|
|
* queue for free after rcu grace period
|
|
|
|
|
@@ -282,7 +255,7 @@ void batadv_tt_global_entry_release(struct kref *ref)
|
|
|
|
|
|
|
|
|
|
batadv_tt_global_del_orig_list(tt_global_entry);
|
|
|
|
|
|
|
|
|
|
call_rcu(&tt_global_entry->common.rcu, batadv_tt_global_entry_free_rcu);
|
|
|
|
|
kfree_rcu(tt_global_entry, common.rcu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -407,19 +380,6 @@ static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node,
|
|
|
|
|
batadv_tt_global_size_mod(orig_node, vid, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* batadv_tt_orig_list_entry_free_rcu() - free the orig_entry
|
|
|
|
|
* @rcu: rcu pointer of the orig_entry
|
|
|
|
|
*/
|
|
|
|
|
static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
|
|
|
|
|
{
|
|
|
|
|
struct batadv_tt_orig_list_entry *orig_entry;
|
|
|
|
|
|
|
|
|
|
orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
|
|
|
|
|
|
|
|
|
|
kmem_cache_free(batadv_tt_orig_cache, orig_entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* batadv_tt_orig_list_entry_release() - release tt orig entry from lists and
|
|
|
|
|
* queue for free after rcu grace period
|
|
|
|
|
@@ -433,7 +393,7 @@ static void batadv_tt_orig_list_entry_release(struct kref *ref)
|
|
|
|
|
refcount);
|
|
|
|
|
|
|
|
|
|
batadv_orig_node_put(orig_entry->orig_node);
|
|
|
|
|
call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
|
|
|
|
|
kfree_rcu(orig_entry, rcu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -856,8 +816,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
|
|
|
|
|
num_entries += atomic_read(&vlan->tt.num_entries);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
change_offset = sizeof(**tt_data);
|
|
|
|
|
change_offset += num_vlan * sizeof(*tt_vlan);
|
|
|
|
|
change_offset = struct_size(*tt_data, vlan_data, num_vlan);
|
|
|
|
|
|
|
|
|
|
/* if tt_len is negative, allocate the space needed by the full table */
|
|
|
|
|
if (*tt_len < 0)
|
|
|
|
|
@@ -876,7 +835,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
|
|
|
|
|
(*tt_data)->ttvn = atomic_read(&orig_node->last_ttvn);
|
|
|
|
|
(*tt_data)->num_vlan = htons(num_vlan);
|
|
|
|
|
|
|
|
|
|
tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
|
|
|
|
|
tt_vlan = (*tt_data)->vlan_data;
|
|
|
|
|
hlist_for_each_entry(vlan, &orig_node->vlan_list, list) {
|
|
|
|
|
tt_vlan->vid = htons(vlan->vid);
|
|
|
|
|
tt_vlan->crc = htonl(vlan->tt.crc);
|
|
|
|
|
@@ -936,8 +895,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
|
|
|
|
|
total_entries += vlan_entries;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
change_offset = sizeof(**tt_data);
|
|
|
|
|
change_offset += num_vlan * sizeof(*tt_vlan);
|
|
|
|
|
change_offset = struct_size(*tt_data, vlan_data, num_vlan);
|
|
|
|
|
|
|
|
|
|
/* if tt_len is negative, allocate the space needed by the full table */
|
|
|
|
|
if (*tt_len < 0)
|
|
|
|
|
@@ -956,7 +914,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
|
|
|
|
|
(*tt_data)->ttvn = atomic_read(&bat_priv->tt.vn);
|
|
|
|
|
(*tt_data)->num_vlan = htons(num_vlan);
|
|
|
|
|
|
|
|
|
|
tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
|
|
|
|
|
tt_vlan = (*tt_data)->vlan_data;
|
|
|
|
|
hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) {
|
|
|
|
|
vlan_entries = atomic_read(&vlan->tt.num_entries);
|
|
|
|
|
if (vlan_entries < 1)
|
|
|
|
|
@@ -2916,7 +2874,6 @@ static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
|
|
|
|
|
{
|
|
|
|
|
struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
|
|
|
|
|
struct batadv_tt_req_node *tt_req_node = NULL;
|
|
|
|
|
struct batadv_tvlv_tt_vlan_data *tt_vlan_req;
|
|
|
|
|
struct batadv_hard_iface *primary_if;
|
|
|
|
|
bool ret = false;
|
|
|
|
|
int i, size;
|
|
|
|
|
@@ -2932,7 +2889,7 @@ static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
|
|
|
|
|
if (!tt_req_node)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
size = sizeof(*tvlv_tt_data) + sizeof(*tt_vlan_req) * num_vlan;
|
|
|
|
|
size = struct_size(tvlv_tt_data, vlan_data, num_vlan);
|
|
|
|
|
tvlv_tt_data = kzalloc(size, GFP_ATOMIC);
|
|
|
|
|
if (!tvlv_tt_data)
|
|
|
|
|
goto out;
|
|
|
|
|
@@ -2944,12 +2901,10 @@ static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
|
|
|
|
|
/* send all the CRCs within the request. This is needed by intermediate
|
|
|
|
|
* nodes to ensure they have the correct table before replying
|
|
|
|
|
*/
|
|
|
|
|
tt_vlan_req = (struct batadv_tvlv_tt_vlan_data *)(tvlv_tt_data + 1);
|
|
|
|
|
for (i = 0; i < num_vlan; i++) {
|
|
|
|
|
tt_vlan_req->vid = tt_vlan->vid;
|
|
|
|
|
tt_vlan_req->crc = tt_vlan->crc;
|
|
|
|
|
tvlv_tt_data->vlan_data[i].vid = tt_vlan->vid;
|
|
|
|
|
tvlv_tt_data->vlan_data[i].crc = tt_vlan->crc;
|
|
|
|
|
|
|
|
|
|
tt_vlan_req++;
|
|
|
|
|
tt_vlan++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3001,7 +2956,6 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
|
|
|
|
|
struct batadv_orig_node *res_dst_orig_node = NULL;
|
|
|
|
|
struct batadv_tvlv_tt_change *tt_change;
|
|
|
|
|
struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
|
|
|
|
|
struct batadv_tvlv_tt_vlan_data *tt_vlan;
|
|
|
|
|
bool ret = false, full_table;
|
|
|
|
|
u8 orig_ttvn, req_ttvn;
|
|
|
|
|
u16 tvlv_len;
|
|
|
|
|
@@ -3024,10 +2978,9 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
|
|
|
|
|
orig_ttvn = (u8)atomic_read(&req_dst_orig_node->last_ttvn);
|
|
|
|
|
req_ttvn = tt_data->ttvn;
|
|
|
|
|
|
|
|
|
|
tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
|
|
|
|
|
/* this node doesn't have the requested data */
|
|
|
|
|
if (orig_ttvn != req_ttvn ||
|
|
|
|
|
!batadv_tt_global_check_crc(req_dst_orig_node, tt_vlan,
|
|
|
|
|
!batadv_tt_global_check_crc(req_dst_orig_node, tt_data->vlan_data,
|
|
|
|
|
ntohs(tt_data->num_vlan)))
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
@@ -3370,7 +3323,6 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
|
|
|
|
|
struct batadv_orig_node *orig_node = NULL;
|
|
|
|
|
struct batadv_tvlv_tt_change *tt_change;
|
|
|
|
|
u8 *tvlv_ptr = (u8 *)tt_data;
|
|
|
|
|
u16 change_offset;
|
|
|
|
|
|
|
|
|
|
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
|
|
|
|
"Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
|
|
|
|
|
@@ -3383,10 +3335,7 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
|
|
|
|
|
|
|
|
|
|
spin_lock_bh(&orig_node->tt_lock);
|
|
|
|
|
|
|
|
|
|
change_offset = sizeof(struct batadv_tvlv_tt_vlan_data);
|
|
|
|
|
change_offset *= ntohs(tt_data->num_vlan);
|
|
|
|
|
change_offset += sizeof(*tt_data);
|
|
|
|
|
tvlv_ptr += change_offset;
|
|
|
|
|
tvlv_ptr += struct_size(tt_data, vlan_data, ntohs(tt_data->num_vlan));
|
|
|
|
|
|
|
|
|
|
tt_change = (struct batadv_tvlv_tt_change *)tvlv_ptr;
|
|
|
|
|
if (tt_data->flags & BATADV_TT_FULL_TABLE) {
|
|
|
|
|
@@ -3985,10 +3934,10 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
|
|
|
|
|
u8 flags, void *tvlv_value,
|
|
|
|
|
u16 tvlv_value_len)
|
|
|
|
|
{
|
|
|
|
|
struct batadv_tvlv_tt_vlan_data *tt_vlan;
|
|
|
|
|
struct batadv_tvlv_tt_change *tt_change;
|
|
|
|
|
struct batadv_tvlv_tt_data *tt_data;
|
|
|
|
|
u16 num_entries, num_vlan;
|
|
|
|
|
size_t flex_size;
|
|
|
|
|
|
|
|
|
|
if (tvlv_value_len < sizeof(*tt_data))
|
|
|
|
|
return;
|
|
|
|
|
@@ -3998,17 +3947,18 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
|
|
|
|
|
|
|
|
|
|
num_vlan = ntohs(tt_data->num_vlan);
|
|
|
|
|
|
|
|
|
|
if (tvlv_value_len < sizeof(*tt_vlan) * num_vlan)
|
|
|
|
|
flex_size = flex_array_size(tt_data, vlan_data, num_vlan);
|
|
|
|
|
if (tvlv_value_len < flex_size)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
|
|
|
|
|
tt_change = (struct batadv_tvlv_tt_change *)(tt_vlan + num_vlan);
|
|
|
|
|
tvlv_value_len -= sizeof(*tt_vlan) * num_vlan;
|
|
|
|
|
tt_change = (struct batadv_tvlv_tt_change *)((void *)tt_data
|
|
|
|
|
+ flex_size);
|
|
|
|
|
tvlv_value_len -= flex_size;
|
|
|
|
|
|
|
|
|
|
num_entries = batadv_tt_entries(tvlv_value_len);
|
|
|
|
|
|
|
|
|
|
batadv_tt_update_orig(bat_priv, orig, tt_vlan, num_vlan, tt_change,
|
|
|
|
|
num_entries, tt_data->ttvn);
|
|
|
|
|
batadv_tt_update_orig(bat_priv, orig, tt_data->vlan_data, num_vlan,
|
|
|
|
|
tt_change, num_entries, tt_data->ttvn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -4039,8 +3989,8 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
|
|
|
|
|
tt_data = tvlv_value;
|
|
|
|
|
tvlv_value_len -= sizeof(*tt_data);
|
|
|
|
|
|
|
|
|
|
tt_vlan_len = sizeof(struct batadv_tvlv_tt_vlan_data);
|
|
|
|
|
tt_vlan_len *= ntohs(tt_data->num_vlan);
|
|
|
|
|
tt_vlan_len = flex_array_size(tt_data, vlan_data,
|
|
|
|
|
ntohs(tt_data->num_vlan));
|
|
|
|
|
|
|
|
|
|
if (tvlv_value_len < tt_vlan_len)
|
|
|
|
|
return NET_RX_SUCCESS;
|
|
|
|
|
|