mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 13:23:02 -04:00
Merge tag 'batadv-next-pullrequest-20260805' of https://git.open-mesh.org/batadv
Simon Wunderlich says: ==================== This cleanup patchset includes the following patches: - dat: drop non-4addr backwards compatibility, by Sven Eckelmann - tvlv: handle negative tvlv processing return codes, by Sven Eckelmann - improve kernel-doc, add comments and warnings, by Sven Eckelmann (3 patches) - coding style: split declarations, reverse x-mas tree, by Sven Eckelmann (2 patches) - handle errors in batadv_init(), by Minhong He - correct NET_RX_* NET_XMIT_* confusion, by Sven Eckelmann - remove negative returns for batadv_send_skb_unicast, by Sven Eckelmann * tag 'batadv-next-pullrequest-20260805' of https://git.open-mesh.org/batadv: batman-adv: remove negative returns for batadv_send_skb_unicast batman-adv: correct NET_RX_* NET_XMIT_* confusion batman-adv: handle errors in batadv_init() batman-adv: switch var declarations to reverse x-mas tree order batman-adv: split multiple declarations per line batman-adv: annotate functions which may reallocate the skbuff batman-adv: fix kernel-doc for functions holding skb ownership batman-adv: add missing kernel-doc comments batman-adv: tvlv: handle negative tvlv processing return codes batman-adv: dat: drop non-4addr backwards compatibility ==================== Link: https://patch.msgid.link/20260805143200.722098-1-sw@simonwunderlich.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -192,13 +192,19 @@ enum batadv_tvlv_type {
|
||||
};
|
||||
|
||||
#pragma pack(2)
|
||||
/* the destination hardware field in the ARP frame is used to
|
||||
* transport the claim type and the group id
|
||||
/**
|
||||
* struct batadv_bla_claim_dst - layout of the destination MAC of a BLA claim
|
||||
* frame
|
||||
* @magic: fixed magic prefix (FF:43:05) identifying claim frames
|
||||
* @type: claim frame type, see &enum batadv_bla_claimframe
|
||||
* @group: group identifier of the announcing backbone gateway
|
||||
*
|
||||
* used in the destination hardware field of the ARP frame
|
||||
*/
|
||||
struct batadv_bla_claim_dst {
|
||||
__u8 magic[3]; /* FF:43:05 */
|
||||
__u8 type; /* bla_claimframe */
|
||||
__be16 group; /* group id */
|
||||
__u8 magic[3];
|
||||
__u8 type;
|
||||
__be16 group;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,7 +42,8 @@ void batadv_algo_init(void)
|
||||
*/
|
||||
struct batadv_algo_ops *batadv_algo_get(const char *name)
|
||||
{
|
||||
struct batadv_algo_ops *bat_algo_ops = NULL, *bat_algo_ops_tmp;
|
||||
struct batadv_algo_ops *bat_algo_ops = NULL;
|
||||
struct batadv_algo_ops *bat_algo_ops_tmp;
|
||||
|
||||
hlist_for_each_entry(bat_algo_ops_tmp, &batadv_algo_list, list) {
|
||||
if (strcmp(bat_algo_ops_tmp->name, name) != 0)
|
||||
@@ -116,12 +117,23 @@ int batadv_algo_select(struct batadv_priv *bat_priv, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_param_set_ra() - Validate and store routing_algo module parameter
|
||||
* @val: new value for the routing_algo module parameter
|
||||
* @kp: kernel parameter description used to store the value
|
||||
*
|
||||
* Check that the requested algorithm is known to batman-adv and then store
|
||||
* the name as the new default routing algorithm.
|
||||
*
|
||||
* Return: 0 on success or negative error number in case of failure
|
||||
*/
|
||||
static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
struct batadv_algo_ops *bat_algo_ops;
|
||||
char *algo_name = (char *)val;
|
||||
size_t name_len = strlen(algo_name);
|
||||
size_t name_len;
|
||||
|
||||
name_len = strlen(algo_name);
|
||||
if (name_len > 0 && algo_name[name_len - 1] == '\n')
|
||||
algo_name[name_len - 1] = '\0';
|
||||
|
||||
|
||||
@@ -106,8 +106,8 @@ static u8 batadv_ring_buffer_avg(const u8 lq_recv[])
|
||||
{
|
||||
const u8 *ptr;
|
||||
u16 count = 0;
|
||||
u16 i = 0;
|
||||
u16 sum = 0;
|
||||
u16 i = 0;
|
||||
|
||||
ptr = lq_recv;
|
||||
|
||||
@@ -171,6 +171,14 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_ogm_neigh_new() - retrieve or create a B.A.T.M.A.N. IV neighbour
|
||||
* @hard_iface: the interface where the neighbour is connected to
|
||||
* @neigh_addr: the mac address of the neighbour
|
||||
* @orig_node: originator object representing the neighbour
|
||||
*
|
||||
* Return: pointer to the neigh_node or NULL in case of failure
|
||||
*/
|
||||
static struct batadv_neigh_node *
|
||||
batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
|
||||
const u8 *neigh_addr,
|
||||
@@ -183,6 +191,14 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
|
||||
return neigh_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_ogm_iface_enable() - prepare an interface for B.A.T.M.A.N. IV
|
||||
* @hard_iface: the interface to prepare
|
||||
*
|
||||
* Allocate and prepare the per-interface OGM buffer
|
||||
*
|
||||
* Return: 0 on success or negative error number in case of failure
|
||||
*/
|
||||
static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
@@ -220,6 +236,14 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_ogm_iface_disable() - release B.A.T.M.A.N. IV resources of an
|
||||
* interface
|
||||
* @hard_iface: the interface which is shutting down
|
||||
*
|
||||
* Free the per-interface OGM buffer and cancel a possibly pending OGM
|
||||
* rescheduling work.
|
||||
*/
|
||||
static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
@@ -233,6 +257,11 @@ static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
|
||||
disable_delayed_work_sync(&hard_iface->bat_iv.reschedule_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_ogm_iface_update_mac() - update the originator MAC stored in the
|
||||
* per-interface OGM buffer
|
||||
* @hard_iface: the interface for which the OGM buffer should be updated
|
||||
*/
|
||||
static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
@@ -254,6 +283,14 @@ static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
|
||||
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_ogm_primary_iface_set() - apply primary interface state to
|
||||
* a batadv_hard_iface
|
||||
* @hard_iface: interface which just became the primary
|
||||
*
|
||||
* The primary interface uses the full TTL for its own OGMs, so adjust the TTL
|
||||
* stored in the OGM template buffer accordingly.
|
||||
*/
|
||||
static void
|
||||
batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
@@ -273,7 +310,17 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
|
||||
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
}
|
||||
|
||||
/* when do we schedule our own ogm to be sent */
|
||||
/**
|
||||
* batadv_iv_ogm_emit_send_time() - calculate the jiffies when an own OGM
|
||||
* should be sent next
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* The next emission point is the configured orig_interval randomised by
|
||||
* +/- BATADV_JITTER milliseconds to reduce chance of potential collisions
|
||||
* between neighbours.
|
||||
*
|
||||
* Return: jiffies value when the next OGM should be transmitted
|
||||
*/
|
||||
static unsigned long
|
||||
batadv_iv_ogm_emit_send_time(const struct batadv_priv *bat_priv)
|
||||
{
|
||||
@@ -285,13 +332,24 @@ batadv_iv_ogm_emit_send_time(const struct batadv_priv *bat_priv)
|
||||
return jiffies + msecs_to_jiffies(msecs);
|
||||
}
|
||||
|
||||
/* when do we schedule a ogm packet to be sent */
|
||||
/**
|
||||
* batadv_iv_ogm_fwd_send_time() - calculate the jiffies when a forwarded OGM
|
||||
* should be sent next
|
||||
*
|
||||
* Return: jiffies value at which a forwarded OGM should be transmitted
|
||||
*/
|
||||
static unsigned long batadv_iv_ogm_fwd_send_time(void)
|
||||
{
|
||||
return jiffies + msecs_to_jiffies(get_random_u32_below(BATADV_JITTER / 2));
|
||||
}
|
||||
|
||||
/* apply hop penalty for a normal link */
|
||||
/**
|
||||
* batadv_hop_penalty() - apply the configured hop penalty to a TQ value
|
||||
* @tq: input TQ value to be reduced
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* Return: the TQ value after the hop penalty has been applied
|
||||
*/
|
||||
static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
|
||||
{
|
||||
int hop_penalty = READ_ONCE(bat_priv->hop_penalty);
|
||||
@@ -337,17 +395,25 @@ batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
|
||||
return next_buff_pos <= packet_len;
|
||||
}
|
||||
|
||||
/* send a batman ogm to a given interface */
|
||||
/**
|
||||
* batadv_iv_ogm_send_to_if() - send a batman OGM to a given interface
|
||||
* @forw_packet: forward packet containing the OGM(s) to be transmitted
|
||||
* @hard_iface: interface to send the OGM out on
|
||||
*
|
||||
* Update the direct link flags of each aggregated OGM for the outgoing
|
||||
* interface, log the transmission and finally hand a clone of the skb to the
|
||||
* lower layer for broadcast.
|
||||
*/
|
||||
static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
|
||||
struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
const char *fwd_str;
|
||||
u8 packet_num;
|
||||
int buff_pos;
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
const char *fwd_str;
|
||||
struct sk_buff *skb;
|
||||
u8 *packet_pos;
|
||||
u8 packet_num;
|
||||
int buff_pos;
|
||||
|
||||
if (hard_iface->if_status != BATADV_IF_ACTIVE)
|
||||
return;
|
||||
@@ -401,7 +467,13 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
|
||||
}
|
||||
}
|
||||
|
||||
/* send a batman ogm packet */
|
||||
/**
|
||||
* batadv_iv_ogm_emit() - emit an (aggregated) OGM packet
|
||||
* @forw_packet: forward packet which should be emitted
|
||||
*
|
||||
* The @forw_packet will be emitted but not consumed. When the interface is
|
||||
* no longer active, the transmission will be skipped.
|
||||
*/
|
||||
static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
|
||||
{
|
||||
if (!forw_packet->if_incoming) {
|
||||
@@ -442,13 +514,13 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
|
||||
const struct batadv_hard_iface *if_outgoing,
|
||||
const struct batadv_forw_packet *forw_packet)
|
||||
{
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
unsigned int aggregated_bytes = forw_packet->packet_len + packet_len;
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
u8 packet_num = forw_packet->num_packets;
|
||||
bool res = false;
|
||||
unsigned long aggregation_end_time;
|
||||
unsigned int max_bytes;
|
||||
bool res = false;
|
||||
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)forw_packet->skb->data;
|
||||
aggregation_end_time = send_time;
|
||||
@@ -555,10 +627,10 @@ static bool batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface);
|
||||
struct batadv_forw_packet *forw_packet_aggr;
|
||||
struct sk_buff *skb;
|
||||
unsigned char *skb_buff;
|
||||
unsigned int skb_size;
|
||||
atomic_t *queue_left = own_packet ? NULL : &bat_priv->batman_queue_left;
|
||||
atomic_t *queue_left;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (READ_ONCE(bat_priv->aggregated_ogms))
|
||||
skb_size = max_t(unsigned int, BATADV_MAX_AGGREGATION_BYTES,
|
||||
@@ -572,6 +644,7 @@ static bool batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
||||
if (!skb)
|
||||
return false;
|
||||
|
||||
queue_left = own_packet ? NULL : &bat_priv->batman_queue_left;
|
||||
forw_packet_aggr = batadv_forw_packet_alloc(if_incoming, if_outgoing,
|
||||
queue_left, bat_priv, skb);
|
||||
if (!forw_packet_aggr) {
|
||||
@@ -603,7 +676,14 @@ static bool batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* aggregate a new packet into the existing ogm packet */
|
||||
/**
|
||||
* batadv_iv_ogm_aggregate() - append an OGM to an existing aggregated forward
|
||||
* packet
|
||||
* @forw_packet_aggr: aggregated forward packet to extend
|
||||
* @packet_buff: pointer to the OGM to append
|
||||
* @packet_len: length of the OGM to append
|
||||
* @direct_link: true if @packet_buff was received as a direct link OGM
|
||||
*/
|
||||
static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr,
|
||||
const unsigned char *packet_buff,
|
||||
int packet_len, bool direct_link)
|
||||
@@ -644,9 +724,9 @@ static bool batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
|
||||
struct batadv_forw_packet *forw_packet_aggr = NULL;
|
||||
struct batadv_forw_packet *forw_packet_pos = NULL;
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
bool direct_link;
|
||||
unsigned long max_aggregation_jiffies;
|
||||
bool aggregated_ogms;
|
||||
bool direct_link;
|
||||
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
|
||||
direct_link = !!(batadv_ogm_packet->flags & BATADV_DIRECTLINK);
|
||||
@@ -699,6 +779,21 @@ static bool batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_ogm_forward() - rebroadcast a received OGM
|
||||
* @orig_node: originator that sent the OGM
|
||||
* @ethhdr: ethernet header of the OGM packet
|
||||
* @batadv_ogm_packet: OGM packet to be forwarded
|
||||
* @is_single_hop_neigh: true if the OGM was received via a one-hop neighbour
|
||||
* @is_from_best_next_hop: true if the sender is the currently selected best
|
||||
* next hop towards @orig_node
|
||||
* @if_incoming: interface where the packet was received
|
||||
* @if_outgoing: interface for which the retransmission should be considered
|
||||
*
|
||||
* Decrement the TTL, apply the hop penalty and queue the OGM for
|
||||
* retransmission. OGMs that do not arrive over the best next hop are only
|
||||
* forwarded for link-quality measurement reasons (and marked accordingly).
|
||||
*/
|
||||
static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
|
||||
const struct ethhdr *ethhdr,
|
||||
struct batadv_ogm_packet *batadv_ogm_packet,
|
||||
@@ -762,9 +857,9 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
struct batadv_hashtable *hash = bat_priv->orig_hash;
|
||||
struct hlist_head *head;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct hlist_head *head;
|
||||
unsigned long *word;
|
||||
u32 i;
|
||||
u8 *w;
|
||||
@@ -802,13 +897,14 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
struct batadv_ogm_buf *ogm_buff = &hard_iface->bat_iv.ogm_buff;
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
struct batadv_hard_iface *primary_if, *tmp_hard_iface;
|
||||
struct list_head *iter;
|
||||
u32 seqno;
|
||||
u16 tvlv_len = 0;
|
||||
struct batadv_hard_iface *tmp_hard_iface;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
unsigned long send_time;
|
||||
bool reschedule = false;
|
||||
struct list_head *iter;
|
||||
u16 tvlv_len = 0;
|
||||
bool scheduled;
|
||||
u32 seqno;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
@@ -899,6 +995,13 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
|
||||
batadv_hardif_put(primary_if);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_ogm_schedule() - schedule the next OGM transmission on an
|
||||
* interface
|
||||
* @hard_iface: interface for which the next OGM should be scheduled
|
||||
*
|
||||
* Take the OGM buffer mutex and prepare the next OGM for transmission.
|
||||
*/
|
||||
static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
if (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
|
||||
@@ -909,6 +1012,13 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
||||
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_ogm_reschedule() - work-queue helper to rerun batadv_iv_ogm_schedule()
|
||||
* @work: work item embedded in the hard interface
|
||||
*
|
||||
* Invoked from the per-interface reschedule_work delayed work when the
|
||||
* previous attempt to enqueue the own OGM failed.
|
||||
*/
|
||||
static void batadv_iv_ogm_reschedule(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work = to_delayed_work(work);
|
||||
@@ -996,13 +1106,14 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *if_outgoing,
|
||||
enum batadv_dup_status dup_status)
|
||||
{
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
|
||||
struct batadv_neigh_ifinfo *router_ifinfo = NULL;
|
||||
struct batadv_neigh_node *neigh_node = NULL;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
|
||||
struct batadv_neigh_node *tmp_neigh_node = NULL;
|
||||
struct batadv_neigh_node *neigh_node = NULL;
|
||||
struct batadv_neigh_node *router = NULL;
|
||||
u8 sum_orig, sum_neigh;
|
||||
u8 *neigh_addr;
|
||||
u8 sum_neigh;
|
||||
u8 sum_orig;
|
||||
u8 tq_avg;
|
||||
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
@@ -1133,15 +1244,21 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface);
|
||||
struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo;
|
||||
u8 total_count;
|
||||
u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own;
|
||||
unsigned int tq_iface_hop_penalty = BATADV_TQ_MAX_VALUE;
|
||||
unsigned int neigh_rq_inv_cube, neigh_rq_max_cube;
|
||||
unsigned int tq_asym_penalty, inv_asym_penalty;
|
||||
struct batadv_neigh_node *neigh_node = NULL;
|
||||
struct batadv_neigh_node *tmp_neigh_node;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo;
|
||||
unsigned int neigh_rq_inv_cube;
|
||||
unsigned int neigh_rq_max_cube;
|
||||
unsigned int inv_asym_penalty;
|
||||
unsigned int tq_asym_penalty;
|
||||
unsigned int combined_tq;
|
||||
u8 neigh_rq_count;
|
||||
u8 orig_eq_count;
|
||||
bool ret = false;
|
||||
u8 neigh_rq_inv;
|
||||
u8 total_count;
|
||||
u8 tq_own;
|
||||
|
||||
/* find corresponding one hop neighbor */
|
||||
rcu_read_lock();
|
||||
@@ -1274,19 +1391,19 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface);
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct batadv_orig_ifinfo *orig_ifinfo = NULL;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo;
|
||||
bool is_dup;
|
||||
s32 seq_diff;
|
||||
bool need_update = false;
|
||||
int set_mark;
|
||||
enum batadv_dup_status ret = BATADV_NO_DUP;
|
||||
u32 seqno = ntohl(batadv_ogm_packet->seqno);
|
||||
u8 *neigh_addr;
|
||||
u8 packet_count;
|
||||
enum batadv_dup_status ret = BATADV_NO_DUP;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
struct batadv_orig_node *orig_node;
|
||||
bool need_update = false;
|
||||
unsigned long *bitmap;
|
||||
u8 packet_count;
|
||||
u8 *neigh_addr;
|
||||
s32 seq_diff;
|
||||
int set_mark;
|
||||
bool is_dup;
|
||||
|
||||
orig_node = batadv_iv_ogm_orig_get(bat_priv, batadv_ogm_packet->orig);
|
||||
if (!orig_node)
|
||||
@@ -1403,21 +1520,22 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface);
|
||||
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
|
||||
struct batadv_neigh_node *router = NULL;
|
||||
struct batadv_neigh_node *router_router = NULL;
|
||||
struct batadv_orig_node *orig_neigh_node;
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
struct batadv_neigh_node *orig_neigh_router = NULL;
|
||||
struct batadv_neigh_ifinfo *router_ifinfo = NULL;
|
||||
struct batadv_neigh_node *router_router = NULL;
|
||||
struct batadv_orig_node *orig_neigh_node;
|
||||
struct batadv_neigh_node *router = NULL;
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
struct batadv_ogm_packet *ogm_packet;
|
||||
enum batadv_dup_status dup_status;
|
||||
bool is_from_best_next_hop = false;
|
||||
enum batadv_dup_status dup_status;
|
||||
bool is_single_hop_neigh = false;
|
||||
bool sameseq, similar_ttl;
|
||||
struct sk_buff *skb_priv;
|
||||
struct ethhdr *ethhdr;
|
||||
u8 *prev_sender;
|
||||
bool similar_ttl;
|
||||
bool is_bidirect;
|
||||
u8 *prev_sender;
|
||||
bool sameseq;
|
||||
|
||||
/* create a private copy of the skb, as some functions change tq value
|
||||
* and/or flags.
|
||||
@@ -1639,16 +1757,17 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
|
||||
struct batadv_hard_iface *if_incoming)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface);
|
||||
struct batadv_orig_node *orig_neigh_node, *orig_node;
|
||||
struct batadv_orig_node *orig_neigh_node;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_ogm_packet *ogm_packet;
|
||||
u32 if_incoming_seqno;
|
||||
bool has_directlink_flag;
|
||||
struct ethhdr *ethhdr;
|
||||
struct batadv_orig_node *orig_node;
|
||||
bool is_my_oldorig = false;
|
||||
bool has_directlink_flag;
|
||||
bool is_my_addr = false;
|
||||
bool is_my_orig = false;
|
||||
struct list_head *iter;
|
||||
u32 if_incoming_seqno;
|
||||
struct ethhdr *ethhdr;
|
||||
|
||||
ogm_packet = (struct batadv_ogm_packet *)(skb->data + ogm_offset);
|
||||
ethhdr = eth_hdr(skb);
|
||||
@@ -1765,10 +1884,18 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
|
||||
batadv_orig_node_put(orig_node);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_send_outstanding_bat_ogm_packet() - work-queue helper to emit a
|
||||
* queued forward packet
|
||||
* @work: work item embedded in the forward packet
|
||||
*
|
||||
* Emit the queued OGM forward packet and, for own primary-interface packets,
|
||||
* schedule the next periodic OGM. The forward packet is freed afterwards.
|
||||
*/
|
||||
static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work;
|
||||
struct batadv_forw_packet *forw_packet;
|
||||
struct delayed_work *delayed_work;
|
||||
struct batadv_priv *bat_priv;
|
||||
bool dropped = false;
|
||||
|
||||
@@ -1803,15 +1930,26 @@ static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work)
|
||||
batadv_forw_packet_free(forw_packet, dropped);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_ogm_receive() - receive a B.A.T.M.A.N. IV OGM packet
|
||||
* @skb: skb containing the OGM packet
|
||||
* @if_incoming: interface where the packet was received
|
||||
*
|
||||
* Validate the packet, then split the aggregated OGM packet into individual
|
||||
* OGMs and hand each of them to batadv_iv_ogm_process(). Ownership of @skb is
|
||||
* always taken over by this function.
|
||||
*
|
||||
* Return: NET_RX_SUCCESS or NET_RX_DROP
|
||||
*/
|
||||
static int batadv_iv_ogm_receive(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *if_incoming)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface);
|
||||
struct batadv_ogm_packet *ogm_packet;
|
||||
int ret = NET_RX_DROP;
|
||||
u8 *packet_pos;
|
||||
int ogm_offset;
|
||||
bool res;
|
||||
int ret = NET_RX_DROP;
|
||||
|
||||
res = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
|
||||
if (!res)
|
||||
@@ -1901,9 +2039,9 @@ batadv_iv_ogm_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
struct batadv_neigh_node *neigh_node,
|
||||
bool best)
|
||||
{
|
||||
unsigned int last_seen_msecs;
|
||||
void *hdr;
|
||||
u8 tq_avg;
|
||||
unsigned int last_seen_msecs;
|
||||
|
||||
last_seen_msecs = jiffies_to_msecs(jiffies - orig_node->last_seen);
|
||||
|
||||
@@ -1965,9 +2103,9 @@ batadv_iv_ogm_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
{
|
||||
struct batadv_neigh_node *neigh_node_best;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
u8 tq_avg_best;
|
||||
int sub = 0;
|
||||
bool best;
|
||||
u8 tq_avg_best;
|
||||
|
||||
neigh_node_best = batadv_orig_router_get(orig_node, if_outgoing);
|
||||
if (!neigh_node_best)
|
||||
@@ -2060,11 +2198,11 @@ batadv_iv_ogm_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_hashtable *hash = bat_priv->orig_hash;
|
||||
struct hlist_head *head;
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
int bucket = cb->args[0];
|
||||
struct hlist_head *head;
|
||||
int idx = cb->args[1];
|
||||
int sub = cb->args[2];
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
|
||||
while (bucket < hash->size) {
|
||||
head = &hash->table[bucket];
|
||||
@@ -2103,9 +2241,11 @@ static bool batadv_iv_ogm_neigh_diff(struct batadv_neigh_node *neigh1,
|
||||
struct batadv_hard_iface *if_outgoing2,
|
||||
int *diff)
|
||||
{
|
||||
struct batadv_neigh_ifinfo *neigh1_ifinfo, *neigh2_ifinfo;
|
||||
u8 tq1, tq2;
|
||||
struct batadv_neigh_ifinfo *neigh1_ifinfo;
|
||||
struct batadv_neigh_ifinfo *neigh2_ifinfo;
|
||||
bool ret = true;
|
||||
u8 tq1;
|
||||
u8 tq2;
|
||||
|
||||
neigh1_ifinfo = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
|
||||
neigh2_ifinfo = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
|
||||
@@ -2139,8 +2279,8 @@ static int
|
||||
batadv_iv_ogm_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
struct batadv_hardif_neigh_node *hardif_neigh)
|
||||
{
|
||||
void *hdr;
|
||||
unsigned int last_seen_msecs;
|
||||
void *hdr;
|
||||
|
||||
last_seen_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen);
|
||||
|
||||
@@ -2218,12 +2358,12 @@ batadv_iv_ogm_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *single_hardif)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct list_head *iter;
|
||||
int i_hardif = 0;
|
||||
int i_hardif_s = cb->args[0];
|
||||
int idx = cb->args[1];
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
int i_hardif_s = cb->args[0];
|
||||
struct list_head *iter;
|
||||
int idx = cb->args[1];
|
||||
int i_hardif = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
if (single_hardif) {
|
||||
@@ -2310,6 +2450,12 @@ batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_iface_enabled() - notification handler for activated interfaces
|
||||
* @hard_iface: interface that was just activated
|
||||
*
|
||||
* Set up the per-interface reschedule work and start sending periodic OGMs.
|
||||
*/
|
||||
static void batadv_iv_iface_enabled(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
INIT_DELAYED_WORK(&hard_iface->bat_iv.reschedule_work, batadv_iv_ogm_reschedule);
|
||||
@@ -2328,17 +2474,26 @@ static void batadv_iv_init_sel_class(struct batadv_priv *bat_priv)
|
||||
WRITE_ONCE(bat_priv->gw.sel_class, 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_gw_get_best_gw_node() - retrieve the best gateway node based on
|
||||
* the B.A.T.M.A.N. IV metric and the configured GW selection class
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* Return: gateway node with the highest score for the current selection class,
|
||||
* or NULL if no eligible gateway exists.
|
||||
*/
|
||||
static struct batadv_gw_node *
|
||||
batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_neigh_node *router;
|
||||
struct batadv_neigh_ifinfo *router_ifinfo;
|
||||
struct batadv_gw_node *gw_node, *curr_gw = NULL;
|
||||
struct batadv_gw_node *curr_gw = NULL;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct batadv_neigh_node *router;
|
||||
struct batadv_gw_node *gw_node;
|
||||
u64 max_gw_factor = 0;
|
||||
u64 tmp_gw_factor = 0;
|
||||
u8 max_tq = 0;
|
||||
u8 tq_avg;
|
||||
struct batadv_orig_node *orig_node;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
|
||||
@@ -2405,6 +2560,19 @@ batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
|
||||
return curr_gw;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_gw_is_eligible() - check whether a new gateway should replace the
|
||||
* currently selected one
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @curr_gw_orig: originator of the currently selected gateway
|
||||
* @orig_node: originator of the gateway candidate
|
||||
*
|
||||
* Compare the TQ values of @curr_gw_orig and @orig_node, taking the configured
|
||||
* gateway selection class into account.
|
||||
*
|
||||
* Return: true if @orig_node should take over as the active gateway, false
|
||||
* otherwise
|
||||
*/
|
||||
static bool batadv_iv_gw_is_eligible(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *curr_gw_orig,
|
||||
struct batadv_orig_node *orig_node)
|
||||
@@ -2412,10 +2580,11 @@ static bool batadv_iv_gw_is_eligible(struct batadv_priv *bat_priv,
|
||||
struct batadv_neigh_ifinfo *router_orig_ifinfo = NULL;
|
||||
struct batadv_neigh_ifinfo *router_gw_ifinfo = NULL;
|
||||
u32 sel_class = READ_ONCE(bat_priv->gw.sel_class);
|
||||
struct batadv_neigh_node *router_gw = NULL;
|
||||
struct batadv_neigh_node *router_orig = NULL;
|
||||
u8 gw_tq_avg, orig_tq_avg;
|
||||
struct batadv_neigh_node *router_gw = NULL;
|
||||
bool ret = false;
|
||||
u8 orig_tq_avg;
|
||||
u8 gw_tq_avg;
|
||||
|
||||
/* dynamic re-election is performed only on fast or late switch */
|
||||
if (sel_class <= 2)
|
||||
@@ -2486,8 +2655,8 @@ static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid,
|
||||
struct batadv_gw_node *gw_node)
|
||||
{
|
||||
struct batadv_neigh_ifinfo *router_ifinfo = NULL;
|
||||
struct batadv_neigh_node *router;
|
||||
struct batadv_gw_node *curr_gw = NULL;
|
||||
struct batadv_neigh_node *router;
|
||||
int ret = 0;
|
||||
void *hdr;
|
||||
|
||||
@@ -2633,3 +2802,11 @@ int __init batadv_iv_init(void)
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_iv_deinit() - B.A.T.M.A.N. IV deinitialization function
|
||||
*/
|
||||
void batadv_iv_deinit(void)
|
||||
{
|
||||
batadv_recv_handler_unregister(BATADV_IV_OGM);
|
||||
}
|
||||
|
||||
@@ -10,5 +10,6 @@
|
||||
#include "main.h"
|
||||
|
||||
int batadv_iv_init(void);
|
||||
void batadv_iv_deinit(void);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_BAT_IV_OGM_H_ */
|
||||
|
||||
@@ -41,6 +41,13 @@
|
||||
#include "netlink.h"
|
||||
#include "originator.h"
|
||||
|
||||
/**
|
||||
* batadv_v_iface_activate() - finalise the activation of a hard interface
|
||||
* @hard_iface: interface to activate
|
||||
*
|
||||
* Reuse the currently selected primary interface to seed the ELP packet.
|
||||
* Immediately activate the interface.
|
||||
*/
|
||||
static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
@@ -61,6 +68,16 @@ static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface)
|
||||
hard_iface->if_status = BATADV_IF_ACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_v_iface_enable() - enable the B.A.T.M.A.N. V protocol on an
|
||||
* interface
|
||||
* @hard_iface: interface to enable
|
||||
*
|
||||
* Enable the ELP and OGM components for @hard_iface. On error, the partially
|
||||
* enabled state is rolled back before returning.
|
||||
*
|
||||
* Return: 0 on success or negative error number in case of failure
|
||||
*/
|
||||
static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
int ret;
|
||||
@@ -76,12 +93,21 @@ static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_v_iface_disable() - disable the B.A.T.M.A.N. V protocol on an
|
||||
* interface
|
||||
* @hard_iface: interface to disable
|
||||
*/
|
||||
static void batadv_v_iface_disable(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
batadv_v_ogm_iface_disable(hard_iface);
|
||||
batadv_v_elp_iface_disable(hard_iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_v_primary_iface_set() - apply primary interface state
|
||||
* @hard_iface: interface which just became the primary
|
||||
*/
|
||||
static void batadv_v_primary_iface_set(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
batadv_v_elp_primary_iface_set(hard_iface);
|
||||
@@ -109,6 +135,11 @@ static void batadv_v_iface_update_mac(struct batadv_hard_iface *hard_iface)
|
||||
batadv_hardif_put(primary_if);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_v_hardif_neigh_init() - initialise the B.A.T.M.A.N. V state of a
|
||||
* hard interface neighbour
|
||||
* @hardif_neigh: hard interface neighbour to initialise
|
||||
*/
|
||||
static void
|
||||
batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
|
||||
{
|
||||
@@ -128,9 +159,9 @@ static int
|
||||
batadv_v_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
struct batadv_hardif_neigh_node *hardif_neigh)
|
||||
{
|
||||
void *hdr;
|
||||
unsigned int last_seen_msecs;
|
||||
u32 throughput;
|
||||
void *hdr;
|
||||
|
||||
last_seen_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen);
|
||||
throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
|
||||
@@ -211,12 +242,12 @@ batadv_v_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *single_hardif)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct list_head *iter;
|
||||
int i_hardif = 0;
|
||||
int i_hardif_s = cb->args[0];
|
||||
int idx = cb->args[1];
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
int i_hardif_s = cb->args[0];
|
||||
struct list_head *iter;
|
||||
int idx = cb->args[1];
|
||||
int i_hardif = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
if (single_hardif) {
|
||||
@@ -421,11 +452,11 @@ batadv_v_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_hashtable *hash = bat_priv->orig_hash;
|
||||
struct hlist_head *head;
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
int bucket = cb->args[0];
|
||||
struct hlist_head *head;
|
||||
int idx = cb->args[1];
|
||||
int sub = cb->args[2];
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
|
||||
while (bucket < hash->size) {
|
||||
head = &hash->table[bucket];
|
||||
@@ -444,12 +475,23 @@ batadv_v_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
cb->args[2] = sub;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_v_neigh_cmp() - compare two B.A.T.M.A.N. V neighbours by throughput
|
||||
* @neigh1: first neighbour to compare
|
||||
* @if_outgoing1: outgoing interface to use for @neigh1
|
||||
* @neigh2: second neighbour to compare
|
||||
* @if_outgoing2: outgoing interface to use for @neigh2
|
||||
*
|
||||
* Return: a positive value if @neigh1 is better, a negative value if @neigh2
|
||||
* is better and 0 if both have equal throughput
|
||||
*/
|
||||
static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
|
||||
struct batadv_hard_iface *if_outgoing1,
|
||||
struct batadv_neigh_node *neigh2,
|
||||
struct batadv_hard_iface *if_outgoing2)
|
||||
{
|
||||
struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
|
||||
struct batadv_neigh_ifinfo *ifinfo1;
|
||||
struct batadv_neigh_ifinfo *ifinfo2;
|
||||
int ret = 0;
|
||||
|
||||
ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
|
||||
@@ -469,14 +511,26 @@ static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_v_neigh_is_sob() - check whether two B.A.T.M.A.N. V neighbours have
|
||||
* a similar or better throughput
|
||||
* @neigh1: first neighbour to compare
|
||||
* @if_outgoing1: outgoing interface to use for @neigh1
|
||||
* @neigh2: second neighbour to compare
|
||||
* @if_outgoing2: outgoing interface to use for @neigh2
|
||||
*
|
||||
* Return: true if the throughput of @neigh2 is at least 3/4 of the
|
||||
* @neigh1 throughput
|
||||
*/
|
||||
static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
|
||||
struct batadv_hard_iface *if_outgoing1,
|
||||
struct batadv_neigh_node *neigh2,
|
||||
struct batadv_hard_iface *if_outgoing2)
|
||||
{
|
||||
struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
|
||||
u32 threshold;
|
||||
struct batadv_neigh_ifinfo *ifinfo1;
|
||||
struct batadv_neigh_ifinfo *ifinfo2;
|
||||
bool ret = false;
|
||||
u32 threshold;
|
||||
|
||||
ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
|
||||
if (!ifinfo1)
|
||||
@@ -558,8 +612,10 @@ static int batadv_v_gw_throughput_get(struct batadv_gw_node *gw_node, u32 *bw)
|
||||
static struct batadv_gw_node *
|
||||
batadv_v_gw_get_best_gw_node(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_gw_node *gw_node, *curr_gw = NULL;
|
||||
u32 max_bw = 0, bw;
|
||||
struct batadv_gw_node *curr_gw = NULL;
|
||||
struct batadv_gw_node *gw_node;
|
||||
u32 max_bw = 0;
|
||||
u32 bw;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
|
||||
@@ -598,9 +654,12 @@ static bool batadv_v_gw_is_eligible(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *curr_gw_orig,
|
||||
struct batadv_orig_node *orig_node)
|
||||
{
|
||||
struct batadv_gw_node *curr_gw, *orig_gw = NULL;
|
||||
u32 gw_throughput, orig_throughput, threshold;
|
||||
struct batadv_gw_node *orig_gw = NULL;
|
||||
struct batadv_gw_node *curr_gw;
|
||||
u32 orig_throughput;
|
||||
u32 gw_throughput;
|
||||
bool ret = false;
|
||||
u32 threshold;
|
||||
|
||||
threshold = READ_ONCE(bat_priv->gw.sel_class);
|
||||
|
||||
@@ -656,8 +715,8 @@ static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid,
|
||||
struct batadv_gw_node *gw_node)
|
||||
{
|
||||
struct batadv_neigh_ifinfo *router_ifinfo = NULL;
|
||||
struct batadv_neigh_node *router;
|
||||
struct batadv_gw_node *curr_gw = NULL;
|
||||
struct batadv_neigh_node *router;
|
||||
int ret = 0;
|
||||
void *hdr;
|
||||
|
||||
@@ -888,3 +947,12 @@ int __init batadv_v_init(void)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_v_deinit() - B.A.T.M.A.N. V deinitialization function
|
||||
*/
|
||||
void batadv_v_deinit(void)
|
||||
{
|
||||
batadv_recv_handler_unregister(BATADV_OGM2);
|
||||
batadv_recv_handler_unregister(BATADV_ELP);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#ifdef CONFIG_BATMAN_ADV_BATMAN_V
|
||||
|
||||
int batadv_v_init(void);
|
||||
void batadv_v_deinit(void);
|
||||
void batadv_v_hardif_init(struct batadv_hard_iface *hardif);
|
||||
int batadv_v_mesh_init(struct batadv_priv *bat_priv);
|
||||
void batadv_v_mesh_free(struct batadv_priv *bat_priv);
|
||||
@@ -23,6 +24,10 @@ static inline int batadv_v_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void batadv_v_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void batadv_v_hardif_init(struct batadv_hard_iface *hardif)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -230,11 +230,14 @@ static bool
|
||||
batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface = neigh->if_incoming;
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
struct batadv_priv *bat_priv;
|
||||
unsigned long last_tx_diff;
|
||||
struct sk_buff *skb;
|
||||
int probe_len, i;
|
||||
int elp_skb_len;
|
||||
int probe_len;
|
||||
int i;
|
||||
|
||||
bat_priv = netdev_priv(hard_iface->mesh_iface);
|
||||
|
||||
/* this probing routine is for Wifi neighbours only */
|
||||
if (!batadv_is_wifi_hardif(hard_iface))
|
||||
@@ -289,8 +292,8 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
|
||||
struct batadv_v_metric_queue_entry *metric_entry;
|
||||
struct batadv_v_metric_queue_entry *metric_safe;
|
||||
struct batadv_hardif_neigh_node *hardif_neigh;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_hard_iface_bat_v *bat_v;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_elp_packet *elp_packet;
|
||||
struct list_head metric_queue;
|
||||
struct batadv_priv *bat_priv;
|
||||
@@ -395,9 +398,9 @@ int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
|
||||
static const size_t tvlv_padding = sizeof(__be32);
|
||||
struct batadv_elp_packet *elp_packet;
|
||||
unsigned char *elp_buff;
|
||||
int res = -ENOMEM;
|
||||
u32 random_seqno;
|
||||
size_t size;
|
||||
int res = -ENOMEM;
|
||||
|
||||
size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN + tvlv_padding;
|
||||
hard_iface->bat_v.elp_skb = dev_alloc_skb(size);
|
||||
@@ -500,11 +503,11 @@ static void batadv_v_elp_neigh_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_elp_packet *elp_packet)
|
||||
|
||||
{
|
||||
struct batadv_neigh_node *neigh;
|
||||
struct batadv_orig_node *orig_neigh;
|
||||
struct batadv_hardif_neigh_node *hardif_neigh;
|
||||
s32 seqno_diff;
|
||||
struct batadv_orig_node *orig_neigh;
|
||||
struct batadv_neigh_node *neigh;
|
||||
s32 elp_latest_seqno;
|
||||
s32 seqno_diff;
|
||||
|
||||
orig_neigh = batadv_v_ogm_orig_get(bat_priv, elp_packet->orig);
|
||||
if (!orig_neigh)
|
||||
@@ -556,8 +559,8 @@ int batadv_v_elp_packet_recv(struct sk_buff *skb,
|
||||
struct batadv_elp_packet *elp_packet;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct ethhdr *ethhdr;
|
||||
bool res;
|
||||
int ret = NET_RX_DROP;
|
||||
bool res;
|
||||
|
||||
res = batadv_check_management_packet(skb, if_incoming, BATADV_ELP_HLEN);
|
||||
if (!res)
|
||||
|
||||
@@ -101,6 +101,7 @@ static void batadv_v_ogm_start_queue_timer(struct batadv_hard_iface *hard_iface)
|
||||
static void batadv_v_ogm_start_timer(struct batadv_priv *bat_priv)
|
||||
{
|
||||
unsigned long msecs;
|
||||
|
||||
/* this function may be invoked in different contexts (ogm rescheduling
|
||||
* or hard_iface activation), but the work timer should not be reset
|
||||
*/
|
||||
@@ -268,11 +269,12 @@ static void batadv_v_ogm_queue_on_if(struct sk_buff *skb,
|
||||
*/
|
||||
static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_ogm2_packet *ogm_packet;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_ogm_buf *ogm_buff;
|
||||
struct sk_buff *skb, *skb_tmp;
|
||||
struct sk_buff *skb_tmp;
|
||||
struct list_head *iter;
|
||||
struct sk_buff *skb;
|
||||
u16 tvlv_len;
|
||||
int ret;
|
||||
|
||||
@@ -621,11 +623,11 @@ static int batadv_v_ogm_metric_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *if_incoming,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
bool protection_started = false;
|
||||
int ret = -EINVAL;
|
||||
u32 path_throughput;
|
||||
int ret = -EINVAL;
|
||||
s32 seq_diff;
|
||||
|
||||
orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
|
||||
@@ -703,15 +705,17 @@ static bool batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *if_incoming,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_neigh_node *router = NULL;
|
||||
struct batadv_orig_node *orig_neigh_node;
|
||||
struct batadv_neigh_node *orig_neigh_router = NULL;
|
||||
struct batadv_neigh_ifinfo *router_ifinfo = NULL, *neigh_ifinfo = NULL;
|
||||
u32 router_throughput, neigh_throughput;
|
||||
struct batadv_neigh_ifinfo *router_ifinfo = NULL;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
|
||||
struct batadv_orig_node *orig_neigh_node;
|
||||
struct batadv_neigh_node *router = NULL;
|
||||
u32 router_throughput;
|
||||
u32 router_last_seqno;
|
||||
u32 neigh_throughput;
|
||||
u32 neigh_last_seqno;
|
||||
s32 neigh_seq_diff;
|
||||
bool forward = false;
|
||||
s32 neigh_seq_diff;
|
||||
|
||||
orig_neigh_node = batadv_v_ogm_orig_get(bat_priv, ethhdr->h_source);
|
||||
if (!orig_neigh_node)
|
||||
@@ -871,14 +875,16 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
|
||||
struct batadv_hard_iface *if_incoming)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface);
|
||||
struct ethhdr *ethhdr;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
|
||||
struct batadv_neigh_node *neigh_node = NULL;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_ogm2_packet *ogm_packet;
|
||||
u32 ogm_throughput, link_throughput, path_throughput;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct list_head *iter;
|
||||
struct ethhdr *ethhdr;
|
||||
u32 link_throughput;
|
||||
u32 path_throughput;
|
||||
u32 ogm_throughput;
|
||||
int ret;
|
||||
|
||||
ethhdr = eth_hdr(skb);
|
||||
@@ -1004,9 +1010,9 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
|
||||
struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface);
|
||||
struct batadv_ogm2_packet *ogm_packet;
|
||||
struct ethhdr *ethhdr;
|
||||
int ret = NET_RX_DROP;
|
||||
int ogm_offset;
|
||||
u8 *packet_pos;
|
||||
int ret = NET_RX_DROP;
|
||||
|
||||
/* did we receive a OGM2 packet on an interface that does not have
|
||||
* B.A.T.M.A.N. V enabled ?
|
||||
|
||||
@@ -11,7 +11,14 @@
|
||||
|
||||
#include "log.h"
|
||||
|
||||
/* shift the packet array by n places. */
|
||||
/**
|
||||
* batadv_bitmap_shift_left() - shift the sequence number bitmap left
|
||||
* @seq_bits: the sequence number bitmap to shift
|
||||
* @n: number of positions to shift left
|
||||
*
|
||||
* Shift @seq_bits by @n positions. No-op if @n is not within the bounds of
|
||||
* the bitmap.
|
||||
*/
|
||||
static void batadv_bitmap_shift_left(unsigned long *seq_bits, s32 n)
|
||||
{
|
||||
if (n <= 0 || n >= BATADV_TQ_LOCAL_WINDOW_SIZE)
|
||||
|
||||
@@ -177,8 +177,8 @@ static void batadv_backbone_gw_put(struct batadv_bla_backbone_gw *backbone_gw)
|
||||
*/
|
||||
static void batadv_claim_release(struct kref *ref)
|
||||
{
|
||||
struct batadv_bla_claim *claim;
|
||||
struct batadv_bla_backbone_gw *old_backbone_gw;
|
||||
struct batadv_bla_claim *claim;
|
||||
|
||||
claim = container_of(ref, struct batadv_bla_claim, refcount);
|
||||
|
||||
@@ -220,9 +220,9 @@ batadv_claim_hash_find(struct batadv_priv *bat_priv,
|
||||
struct batadv_bla_claim *data)
|
||||
{
|
||||
struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
|
||||
struct hlist_head *head;
|
||||
struct batadv_bla_claim *claim;
|
||||
struct batadv_bla_claim *claim_tmp = NULL;
|
||||
struct batadv_bla_claim *claim;
|
||||
struct hlist_head *head;
|
||||
int index;
|
||||
|
||||
if (!hash)
|
||||
@@ -260,9 +260,10 @@ batadv_backbone_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
|
||||
struct hlist_head *head;
|
||||
struct batadv_bla_backbone_gw search_entry, *backbone_gw;
|
||||
struct batadv_bla_backbone_gw *backbone_gw_tmp = NULL;
|
||||
struct batadv_bla_backbone_gw search_entry;
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct hlist_head *head;
|
||||
int index;
|
||||
|
||||
if (!hash)
|
||||
@@ -298,12 +299,12 @@ batadv_backbone_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
|
||||
static void
|
||||
batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw)
|
||||
{
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
struct batadv_bla_claim *claim;
|
||||
struct batadv_hashtable *hash;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
struct batadv_bla_claim *claim;
|
||||
int i;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
|
||||
hash = backbone_gw->bat_priv->bla.claim_hash;
|
||||
if (!hash)
|
||||
@@ -341,12 +342,12 @@ batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw)
|
||||
static void batadv_bla_send_claim(struct batadv_priv *bat_priv, const u8 *mac,
|
||||
unsigned short vid, int claimtype)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct ethhdr *ethhdr;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
u8 *hw_src;
|
||||
struct batadv_bla_claim_dst local_claim_dest;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct ethhdr *ethhdr;
|
||||
struct sk_buff *skb;
|
||||
__be32 zeroip = 0;
|
||||
u8 *hw_src;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if)
|
||||
@@ -593,10 +594,10 @@ static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct hlist_head *head;
|
||||
struct batadv_hashtable *hash;
|
||||
struct batadv_bla_claim *claim;
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct batadv_bla_claim *claim;
|
||||
struct batadv_hashtable *hash;
|
||||
struct hlist_head *head;
|
||||
int i;
|
||||
|
||||
batadv_dbg(BATADV_DBG_BLA, bat_priv,
|
||||
@@ -692,8 +693,8 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
|
||||
struct batadv_bla_backbone_gw *backbone_gw)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *old_backbone_gw;
|
||||
struct batadv_bla_claim *claim;
|
||||
struct batadv_bla_claim search_claim;
|
||||
struct batadv_bla_claim *claim;
|
||||
bool remove_crc = false;
|
||||
int hash_added;
|
||||
|
||||
@@ -800,9 +801,10 @@ batadv_bla_claim_get_backbone_gw(struct batadv_bla_claim *claim)
|
||||
static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
|
||||
const u8 *mac, const unsigned short vid)
|
||||
{
|
||||
struct batadv_bla_claim search_claim, *claim;
|
||||
struct batadv_bla_claim *claim_removed_entry;
|
||||
struct hlist_node *claim_removed_node;
|
||||
struct batadv_bla_claim search_claim;
|
||||
struct batadv_bla_claim *claim;
|
||||
|
||||
ether_addr_copy(search_claim.addr, mac);
|
||||
search_claim.vid = vid;
|
||||
@@ -842,7 +844,8 @@ static bool batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
|
||||
u8 *backbone_addr, unsigned short vid)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
u16 backbone_crc, crc;
|
||||
u16 backbone_crc;
|
||||
u16 crc;
|
||||
|
||||
if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
|
||||
return false;
|
||||
@@ -1019,9 +1022,10 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv,
|
||||
u8 *hw_src, u8 *hw_dst,
|
||||
struct ethhdr *ethhdr)
|
||||
{
|
||||
u8 *backbone_addr;
|
||||
struct batadv_bla_claim_dst *bla_dst_own;
|
||||
struct batadv_bla_claim_dst *bla_dst;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
|
||||
u8 *backbone_addr;
|
||||
|
||||
bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
|
||||
bla_dst_own = &bat_priv->bla.claim_dest;
|
||||
@@ -1078,6 +1082,11 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv,
|
||||
* @primary_if: the primary hard interface of this batman mesh interface
|
||||
* @skb: the frame to be checked
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* batadv_get_vid()/... Any pointer into the skb data (e.g. obtained
|
||||
* from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true if it was a claim frame, otherwise return false to
|
||||
* tell the callee that it can use the frame on its own.
|
||||
*/
|
||||
@@ -1085,15 +1094,18 @@ static bool batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
|
||||
u8 *hw_src, *hw_dst;
|
||||
struct vlan_hdr *vhdr, vhdr_buf;
|
||||
struct batadv_bla_claim_dst *bla_dst_own;
|
||||
struct batadv_bla_claim_dst *bla_dst;
|
||||
struct vlan_hdr vhdr_buf;
|
||||
struct vlan_hdr *vhdr;
|
||||
struct ethhdr *ethhdr;
|
||||
struct arphdr *arphdr;
|
||||
unsigned short vid;
|
||||
int vlan_depth = 0;
|
||||
__be16 proto;
|
||||
int headlen;
|
||||
u8 *hw_src;
|
||||
u8 *hw_dst;
|
||||
int ret;
|
||||
|
||||
vid = batadv_get_vid(skb, 0);
|
||||
@@ -1225,11 +1237,11 @@ static bool batadv_bla_process_claim(struct batadv_priv *bat_priv,
|
||||
*/
|
||||
static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
|
||||
{
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct batadv_hashtable *hash;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
struct batadv_hashtable *hash;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
bool purged;
|
||||
int i;
|
||||
|
||||
@@ -1302,8 +1314,8 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct batadv_bla_claim *claim;
|
||||
struct hlist_head *head;
|
||||
struct batadv_hashtable *hash;
|
||||
struct hlist_head *head;
|
||||
int i;
|
||||
|
||||
hash = bat_priv->bla.claim_hash;
|
||||
@@ -1365,8 +1377,8 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *oldif)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct hlist_head *head;
|
||||
struct batadv_hashtable *hash;
|
||||
struct hlist_head *head;
|
||||
__be16 group;
|
||||
int i;
|
||||
|
||||
@@ -1459,14 +1471,14 @@ void batadv_bla_status_update(struct net_device *net_dev)
|
||||
*/
|
||||
static void batadv_bla_periodic_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work;
|
||||
struct batadv_priv *bat_priv;
|
||||
struct batadv_priv_bla *priv_bla;
|
||||
struct hlist_head *head;
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct batadv_hashtable *hash;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct delayed_work *delayed_work;
|
||||
struct batadv_priv_bla *priv_bla;
|
||||
struct batadv_hashtable *hash;
|
||||
struct batadv_priv *bat_priv;
|
||||
bool send_loopdetect = false;
|
||||
struct hlist_head *head;
|
||||
int i;
|
||||
|
||||
delayed_work = to_delayed_work(work);
|
||||
@@ -1568,11 +1580,11 @@ static struct lock_class_key batadv_backbone_hash_lock_class_key;
|
||||
*/
|
||||
int batadv_bla_init(struct batadv_priv *bat_priv)
|
||||
{
|
||||
int i;
|
||||
u8 claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
|
||||
struct batadv_hard_iface *primary_if;
|
||||
u16 crc;
|
||||
unsigned long entrytime;
|
||||
u16 crc;
|
||||
int i;
|
||||
|
||||
spin_lock_init(&bat_priv->bla.bcast_duplist_lock);
|
||||
|
||||
@@ -1651,8 +1663,9 @@ static bool batadv_bla_check_duplist(struct batadv_priv *bat_priv,
|
||||
struct batadv_bcast_duplist_entry *entry;
|
||||
bool ret = false;
|
||||
int payload_len;
|
||||
int i, curr;
|
||||
int curr;
|
||||
u32 crc;
|
||||
int i;
|
||||
|
||||
/* calculate the crc ... */
|
||||
payload_len = skb->len - payload_offset;
|
||||
@@ -1774,8 +1787,8 @@ bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
|
||||
struct hlist_head *head;
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct hlist_head *head;
|
||||
int i;
|
||||
|
||||
if (!READ_ONCE(bat_priv->bridge_loop_avoidance))
|
||||
@@ -1807,6 +1820,11 @@ bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig,
|
||||
* @orig_node: the orig_node of the frame
|
||||
* @hdr_size: maximum length of the frame
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* pskb_may_pull()/batadv_get_vid()/... Any pointer into the skb data (e.g.
|
||||
* obtained from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true if the orig_node is also a gateway on the mesh interface,
|
||||
* otherwise it returns false.
|
||||
*/
|
||||
@@ -1936,9 +1954,10 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid, int packet_type)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct ethhdr *ethhdr;
|
||||
struct batadv_bla_claim search_claim, *claim = NULL;
|
||||
struct batadv_bla_claim *claim = NULL;
|
||||
struct batadv_bla_claim search_claim;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct ethhdr *ethhdr;
|
||||
bool own_claim;
|
||||
bool ret;
|
||||
|
||||
@@ -2061,7 +2080,10 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
*
|
||||
* in these cases, the skb is further handled by this function.
|
||||
*
|
||||
* This call might reallocate skb data.
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* batadv_bla_process_claim()/... Any pointer into the skb data (e.g.
|
||||
* obtained from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true if handled, otherwise it returns false and the caller shall
|
||||
* further process the skb.
|
||||
@@ -2069,10 +2091,11 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct ethhdr *ethhdr;
|
||||
struct batadv_bla_claim search_claim, *claim = NULL;
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct batadv_bla_claim *claim = NULL;
|
||||
struct batadv_bla_claim search_claim;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct ethhdr *ethhdr;
|
||||
bool client_roamed;
|
||||
bool ret = false;
|
||||
|
||||
@@ -2173,10 +2196,10 @@ batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid,
|
||||
{
|
||||
const u8 *primary_addr = primary_if->net_dev->dev_addr;
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
int ret = -EINVAL;
|
||||
u16 backbone_crc;
|
||||
bool is_own;
|
||||
void *hdr;
|
||||
int ret = -EINVAL;
|
||||
|
||||
hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
|
||||
&batadv_netlink_family, NLM_F_MULTI,
|
||||
@@ -2335,11 +2358,11 @@ batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid,
|
||||
struct batadv_bla_backbone_gw *backbone_gw)
|
||||
{
|
||||
const u8 *primary_addr = primary_if->net_dev->dev_addr;
|
||||
int ret = -EINVAL;
|
||||
u16 backbone_crc;
|
||||
bool is_own;
|
||||
int msecs;
|
||||
void *hdr;
|
||||
int ret = -EINVAL;
|
||||
|
||||
hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
|
||||
&batadv_netlink_family, NLM_F_MULTI,
|
||||
@@ -2494,10 +2517,10 @@ int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
bool batadv_bla_check_claim(struct batadv_priv *bat_priv,
|
||||
u8 *addr, unsigned short vid)
|
||||
{
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct batadv_bla_claim search_claim;
|
||||
struct batadv_bla_claim *claim = NULL;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_bla_backbone_gw *backbone_gw;
|
||||
struct batadv_bla_claim *claim = NULL;
|
||||
struct batadv_bla_claim search_claim;
|
||||
bool ret = true;
|
||||
|
||||
if (!READ_ONCE(bat_priv->bridge_loop_avoidance))
|
||||
|
||||
@@ -50,27 +50,65 @@
|
||||
#include "translation-table.h"
|
||||
#include "tvlv.h"
|
||||
|
||||
/**
|
||||
* enum batadv_bootpop - BOOTP/DHCP message op codes
|
||||
*/
|
||||
enum batadv_bootpop {
|
||||
/** @BATADV_BOOTREPLY: server-to-client reply */
|
||||
BATADV_BOOTREPLY = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum batadv_boothtype - BOOTP/DHCP hardware address types
|
||||
*/
|
||||
enum batadv_boothtype {
|
||||
/** @BATADV_HTYPE_ETHERNET: Ethernet (10Mb) */
|
||||
BATADV_HTYPE_ETHERNET = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum batadv_dhcpoptioncode - DHCP option codes relevant for batman-adv DAT
|
||||
*/
|
||||
enum batadv_dhcpoptioncode {
|
||||
/** @BATADV_DHCP_OPT_PAD: pad option */
|
||||
BATADV_DHCP_OPT_PAD = 0,
|
||||
|
||||
/** @BATADV_DHCP_OPT_MSG_TYPE: DHCP message type option */
|
||||
BATADV_DHCP_OPT_MSG_TYPE = 53,
|
||||
|
||||
/** @BATADV_DHCP_OPT_END: end of options marker */
|
||||
BATADV_DHCP_OPT_END = 255,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum batadv_dhcptype - DHCP message types relevant for batman-adv DAT
|
||||
*/
|
||||
enum batadv_dhcptype {
|
||||
/** @BATADV_DHCPACK: DHCPACK message */
|
||||
BATADV_DHCPACK = 5,
|
||||
};
|
||||
|
||||
/* { 99, 130, 83, 99 } */
|
||||
#define BATADV_DHCP_MAGIC 1669485411
|
||||
|
||||
/**
|
||||
* struct batadv_dhcp_packet - BOOTP/DHCP packet header
|
||||
* @op: message op code / message type
|
||||
* @htype: hardware address type
|
||||
* @hlen: hardware address length
|
||||
* @hops: number of relay hops
|
||||
* @xid: transaction identifier
|
||||
* @secs: seconds elapsed since client started trying to boot
|
||||
* @flags: BOOTP/DHCP flags
|
||||
* @ciaddr: client IP address
|
||||
* @yiaddr: "your" (client) IP address as assigned by the server
|
||||
* @siaddr: IP address of next server to use in bootstrap
|
||||
* @giaddr: relay agent IP address
|
||||
* @chaddr: client hardware address
|
||||
* @sname: optional server host name
|
||||
* @file: boot file name
|
||||
* @magic: BOOTP/DHCP magic cookie identifying the start of options
|
||||
*/
|
||||
struct batadv_dhcp_packet {
|
||||
__u8 op;
|
||||
__u8 htype;
|
||||
@@ -90,6 +128,34 @@ struct batadv_dhcp_packet {
|
||||
/* __u8 options[]; */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct batadv_dhcp_header - minimal BOOTP/DHCP packet header
|
||||
*/
|
||||
struct batadv_dhcp_header {
|
||||
/** @op: message op code / message type */
|
||||
__u8 op;
|
||||
|
||||
/** @htype: hardware address type */
|
||||
__u8 htype;
|
||||
|
||||
/** @hlen: hardware address length */
|
||||
__u8 hlen;
|
||||
|
||||
/** @hops: number of relay hops */
|
||||
__u8 hops;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct batadv_dhcp_option_header - BOOTP/DHCP option header
|
||||
*/
|
||||
struct batadv_dhcp_option_header {
|
||||
/** @type: type of option */
|
||||
__u8 type;
|
||||
|
||||
/** @len: length of option */
|
||||
__u8 len;
|
||||
};
|
||||
|
||||
#define BATADV_DHCP_YIADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->yiaddr)
|
||||
#define BATADV_DHCP_CHADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr)
|
||||
|
||||
@@ -288,9 +354,9 @@ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
|
||||
*/
|
||||
static u32 batadv_hash_dat(const void *data, u32 size)
|
||||
{
|
||||
u32 hash = 0;
|
||||
const struct batadv_dat_entry *dat = data;
|
||||
const unsigned char *key;
|
||||
u32 hash = 0;
|
||||
__be16 vid;
|
||||
u32 i;
|
||||
|
||||
@@ -329,9 +395,11 @@ static struct batadv_dat_entry *
|
||||
batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct hlist_head *head;
|
||||
struct batadv_dat_entry to_find, *dat_entry, *dat_entry_tmp = NULL;
|
||||
struct batadv_hashtable *hash = bat_priv->dat.hash;
|
||||
struct batadv_dat_entry *dat_entry_tmp = NULL;
|
||||
struct batadv_dat_entry *dat_entry;
|
||||
struct batadv_dat_entry to_find;
|
||||
struct hlist_head *head;
|
||||
u32 index;
|
||||
|
||||
if (!hash)
|
||||
@@ -432,7 +500,8 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
struct batadv_unicast_4addr_packet *unicast_4addr_packet;
|
||||
struct batadv_bcast_packet *bcast_pkt;
|
||||
u8 *orig_addr;
|
||||
__be32 ip_src, ip_dst;
|
||||
__be32 ip_src;
|
||||
__be32 ip_dst;
|
||||
|
||||
if (msg)
|
||||
batadv_dbg(BATADV_DBG_DAT, bat_priv, "%s\n", msg);
|
||||
@@ -567,10 +636,11 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
|
||||
int select, batadv_dat_addr_t ip_key,
|
||||
batadv_dat_addr_t *last_max)
|
||||
{
|
||||
batadv_dat_addr_t max = 0;
|
||||
batadv_dat_addr_t tmp_max = 0;
|
||||
struct batadv_orig_node *orig_node, *max_orig_node = NULL;
|
||||
struct batadv_hashtable *hash = bat_priv->orig_hash;
|
||||
struct batadv_orig_node *max_orig_node = NULL;
|
||||
struct batadv_orig_node *orig_node;
|
||||
batadv_dat_addr_t tmp_max = 0;
|
||||
batadv_dat_addr_t max = 0;
|
||||
struct hlist_head *head;
|
||||
int i;
|
||||
|
||||
@@ -634,10 +704,11 @@ static struct batadv_dat_candidate *
|
||||
batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst,
|
||||
unsigned short vid)
|
||||
{
|
||||
int select;
|
||||
batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
|
||||
batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX;
|
||||
struct batadv_dat_candidate *res;
|
||||
struct batadv_dat_entry dat;
|
||||
batadv_dat_addr_t ip_key;
|
||||
int select;
|
||||
|
||||
if (!bat_priv->orig_hash)
|
||||
return NULL;
|
||||
@@ -680,12 +751,12 @@ static bool batadv_dat_forward_data(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, __be32 ip,
|
||||
unsigned short vid, int packet_subtype)
|
||||
{
|
||||
int i;
|
||||
struct batadv_neigh_node *neigh_node = NULL;
|
||||
struct batadv_dat_candidate *cand;
|
||||
struct sk_buff *tmp_skb;
|
||||
bool ret = false;
|
||||
int send_status;
|
||||
struct batadv_neigh_node *neigh_node = NULL;
|
||||
struct sk_buff *tmp_skb;
|
||||
struct batadv_dat_candidate *cand;
|
||||
int i;
|
||||
|
||||
cand = batadv_dat_select_candidates(bat_priv, ip, vid);
|
||||
if (!cand)
|
||||
@@ -993,6 +1064,11 @@ int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
* @skb: packet to analyse
|
||||
* @hdr_size: size of the possible header before the ARP packet in the skb
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* pskb_may_pull()/... Any pointer into the skb data (e.g. obtained from skb->data
|
||||
* or eth_hdr()) before this call must be considered invalid afterwards and has
|
||||
* to be reacquired.
|
||||
*
|
||||
* Return: the ARP type if the skb contains a valid ARP packet, 0 otherwise.
|
||||
*/
|
||||
static u16 batadv_arp_get_type(struct batadv_priv *bat_priv,
|
||||
@@ -1000,9 +1076,11 @@ static u16 batadv_arp_get_type(struct batadv_priv *bat_priv,
|
||||
{
|
||||
struct arphdr *arphdr;
|
||||
struct ethhdr *ethhdr;
|
||||
__be32 ip_src, ip_dst;
|
||||
u8 *hw_src, *hw_dst;
|
||||
__be32 ip_src;
|
||||
__be32 ip_dst;
|
||||
u16 type = 0;
|
||||
u8 *hw_src;
|
||||
u8 *hw_dst;
|
||||
|
||||
/* pull the ethernet header */
|
||||
if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN)))
|
||||
@@ -1069,6 +1147,11 @@ static u16 batadv_arp_get_type(struct batadv_priv *bat_priv,
|
||||
* The caller must ensure that at least @hdr_size + ETH_HLEN bytes are
|
||||
* accessible after skb->data.
|
||||
*
|
||||
* Warning: This function calls batadv_get_vid() and may therefore reallocate
|
||||
* the skb data buffer. Any pointer into the skb data (e.g. obtained from
|
||||
* skb->data or eth_hdr()) before this call must be considered invalid
|
||||
* afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: If the packet embedded in the skb is vlan tagged this function
|
||||
* returns the VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS
|
||||
* is returned.
|
||||
@@ -1131,6 +1214,11 @@ batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src,
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @skb: packet to check
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* batadv_dat_get_vid()/.... Any pointer into the skb data (e.g. obtained
|
||||
* from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true if the message has been sent to the dht candidates, false
|
||||
* otherwise. In case of a positive return value the message has to be enqueued
|
||||
* to permit the fallback.
|
||||
@@ -1138,15 +1226,16 @@ batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src,
|
||||
bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u16 type = 0;
|
||||
__be32 ip_dst, ip_src;
|
||||
u8 *hw_src;
|
||||
bool ret = false;
|
||||
struct net_device *mesh_iface = bat_priv->mesh_iface;
|
||||
struct batadv_dat_entry *dat_entry = NULL;
|
||||
struct sk_buff *skb_new;
|
||||
struct net_device *mesh_iface = bat_priv->mesh_iface;
|
||||
int hdr_size = 0;
|
||||
unsigned short vid;
|
||||
bool ret = false;
|
||||
int hdr_size = 0;
|
||||
__be32 ip_dst;
|
||||
__be32 ip_src;
|
||||
u16 type = 0;
|
||||
u8 *hw_src;
|
||||
|
||||
if (!READ_ONCE(bat_priv->distributed_arp_table))
|
||||
goto out;
|
||||
@@ -1233,18 +1322,24 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
|
||||
* @skb: packet to check
|
||||
* @hdr_size: size of the encapsulation header
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* batadv_dat_get_vid()/... Any pointer into the skb data (e.g. obtained
|
||||
* from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true if the request has been answered, false otherwise.
|
||||
*/
|
||||
bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, int hdr_size)
|
||||
{
|
||||
u16 type;
|
||||
__be32 ip_src, ip_dst;
|
||||
u8 *hw_src;
|
||||
struct sk_buff *skb_new;
|
||||
struct batadv_dat_entry *dat_entry = NULL;
|
||||
bool ret = false;
|
||||
struct sk_buff *skb_new;
|
||||
unsigned short vid;
|
||||
bool ret = false;
|
||||
__be32 ip_src;
|
||||
__be32 ip_dst;
|
||||
u8 *hw_src;
|
||||
u16 type;
|
||||
int err;
|
||||
|
||||
if (!READ_ONCE(bat_priv->distributed_arp_table))
|
||||
@@ -1277,17 +1372,9 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
|
||||
if (!skb_new)
|
||||
goto out;
|
||||
|
||||
/* To preserve backwards compatibility, the node has choose the outgoing
|
||||
* format based on the incoming request packet type. The assumption is
|
||||
* that a node not using the 4addr packet format doesn't support it.
|
||||
*/
|
||||
if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
|
||||
err = batadv_send_skb_via_tt_4addr(bat_priv, skb_new,
|
||||
BATADV_P_DAT_CACHE_REPLY,
|
||||
NULL, vid);
|
||||
else
|
||||
err = batadv_send_skb_via_tt(bat_priv, skb_new, NULL, vid);
|
||||
|
||||
err = batadv_send_skb_via_tt_4addr(bat_priv, skb_new,
|
||||
BATADV_P_DAT_CACHE_REPLY,
|
||||
NULL, vid);
|
||||
if (err != NET_XMIT_DROP) {
|
||||
batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX);
|
||||
ret = true;
|
||||
@@ -1303,15 +1390,22 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
|
||||
* batadv_dat_snoop_outgoing_arp_reply() - snoop the ARP reply and fill the DHT
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @skb: packet to check
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* batadv_dat_get_vid()/... Any pointer into the skb data (e.g. obtained
|
||||
* from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*/
|
||||
void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u16 type;
|
||||
__be32 ip_src, ip_dst;
|
||||
u8 *hw_src, *hw_dst;
|
||||
int hdr_size = 0;
|
||||
unsigned short vid;
|
||||
int hdr_size = 0;
|
||||
__be32 ip_src;
|
||||
__be32 ip_dst;
|
||||
u8 *hw_src;
|
||||
u8 *hw_dst;
|
||||
u16 type;
|
||||
|
||||
if (!READ_ONCE(bat_priv->distributed_arp_table))
|
||||
return;
|
||||
@@ -1352,6 +1446,11 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
|
||||
* @skb: packet to check
|
||||
* @hdr_size: size of the encapsulation header
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* batadv_dat_get_vid()/... Any pointer into the skb data (e.g. obtained
|
||||
* from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true if the packet was snooped and consumed by DAT. False if the
|
||||
* packet has to be delivered to the interface
|
||||
*/
|
||||
@@ -1359,11 +1458,13 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, int hdr_size)
|
||||
{
|
||||
struct batadv_dat_entry *dat_entry = NULL;
|
||||
u16 type;
|
||||
__be32 ip_src, ip_dst;
|
||||
u8 *hw_src, *hw_dst;
|
||||
bool dropped = false;
|
||||
unsigned short vid;
|
||||
__be32 ip_src;
|
||||
__be32 ip_dst;
|
||||
u8 *hw_src;
|
||||
u8 *hw_dst;
|
||||
u16 type;
|
||||
|
||||
if (!READ_ONCE(bat_priv->distributed_arp_table))
|
||||
goto out;
|
||||
@@ -1454,8 +1555,10 @@ static bool
|
||||
batadv_dat_check_dhcp_ipudp(struct sk_buff *skb, __be32 *ip_src)
|
||||
{
|
||||
unsigned int offset = skb_network_offset(skb);
|
||||
struct udphdr *udphdr, _udphdr;
|
||||
struct iphdr *iphdr, _iphdr;
|
||||
struct udphdr *udphdr;
|
||||
struct udphdr _udphdr;
|
||||
struct iphdr *iphdr;
|
||||
struct iphdr _iphdr;
|
||||
|
||||
iphdr = skb_header_pointer(skb, offset, sizeof(_iphdr), &_iphdr);
|
||||
if (!iphdr || iphdr->version != 4 || iphdr->ihl * 4 < sizeof(_iphdr))
|
||||
@@ -1493,14 +1596,11 @@ batadv_dat_check_dhcp_ipudp(struct sk_buff *skb, __be32 *ip_src)
|
||||
static int
|
||||
batadv_dat_check_dhcp(struct sk_buff *skb, __be16 proto, __be32 *ip_src)
|
||||
{
|
||||
__be32 *magic, _magic;
|
||||
struct batadv_dhcp_header *dhcp_h;
|
||||
struct batadv_dhcp_header _dhcp_h;
|
||||
unsigned int offset;
|
||||
struct {
|
||||
__u8 op;
|
||||
__u8 htype;
|
||||
__u8 hlen;
|
||||
__u8 hops;
|
||||
} *dhcp_h, _dhcp_h;
|
||||
__be32 *magic;
|
||||
__be32 _magic;
|
||||
|
||||
if (proto != htons(ETH_P_IP))
|
||||
return -EINVAL;
|
||||
@@ -1541,11 +1641,10 @@ batadv_dat_check_dhcp(struct sk_buff *skb, __be16 proto, __be32 *ip_src)
|
||||
static int batadv_dat_get_dhcp_message_type(struct sk_buff *skb)
|
||||
{
|
||||
unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr);
|
||||
u8 *type, _type;
|
||||
struct {
|
||||
u8 type;
|
||||
u8 len;
|
||||
} *tl, _tl;
|
||||
struct batadv_dhcp_option_header *tl;
|
||||
struct batadv_dhcp_option_header _tl;
|
||||
u8 *type;
|
||||
u8 _type;
|
||||
|
||||
offset += sizeof(struct batadv_dhcp_packet);
|
||||
|
||||
@@ -1737,7 +1836,8 @@ void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv,
|
||||
unsigned short vid)
|
||||
{
|
||||
u8 chaddr[BATADV_DHCP_CHADDR_LEN];
|
||||
__be32 ip_src, yiaddr;
|
||||
__be32 ip_src;
|
||||
__be32 yiaddr;
|
||||
|
||||
if (!READ_ONCE(bat_priv->distributed_arp_table))
|
||||
return;
|
||||
@@ -1758,15 +1858,21 @@ void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv,
|
||||
* This function first checks whether the given skb is a valid DHCPACK. If
|
||||
* so then its source MAC and IP as well as its DHCP Client Hardware Address
|
||||
* field and DHCP Your IP Address field are added to the local DAT cache.
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* pskb_may_pull()/batadv_dat_get_vid()/... Any pointer into the skb data
|
||||
* (e.g.obtained from skb->data or eth_hdr()) before this call must be
|
||||
* considered invalid afterwards and has to be reacquired.
|
||||
*/
|
||||
void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, int hdr_size)
|
||||
{
|
||||
u8 chaddr[BATADV_DHCP_CHADDR_LEN];
|
||||
struct ethhdr *ethhdr;
|
||||
__be32 ip_src, yiaddr;
|
||||
unsigned short vid;
|
||||
int hdr_size_tmp;
|
||||
__be32 ip_src;
|
||||
__be32 yiaddr;
|
||||
__be16 proto;
|
||||
u8 *hw_src;
|
||||
|
||||
@@ -1805,17 +1911,22 @@ void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv,
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @forw_packet: the broadcast packet
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* batadv_dat_get_vid()/... Any pointer into the skb data (e.g. obtained
|
||||
* from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true if the node can drop the packet, false otherwise.
|
||||
*/
|
||||
bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
|
||||
struct batadv_forw_packet *forw_packet)
|
||||
{
|
||||
u16 type;
|
||||
__be32 ip_dst;
|
||||
struct batadv_dat_entry *dat_entry = NULL;
|
||||
bool ret = false;
|
||||
int hdr_size = sizeof(struct batadv_bcast_packet);
|
||||
struct batadv_dat_entry *dat_entry = NULL;
|
||||
unsigned short vid;
|
||||
bool ret = false;
|
||||
__be32 ip_dst;
|
||||
u16 type;
|
||||
|
||||
if (!READ_ONCE(bat_priv->distributed_arp_table))
|
||||
goto out;
|
||||
|
||||
@@ -139,15 +139,17 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
|
||||
struct sk_buff *skb,
|
||||
struct hlist_head *chain_out)
|
||||
{
|
||||
struct batadv_frag_table_entry *chain;
|
||||
struct batadv_frag_list_entry *frag_entry_new = NULL, *frag_entry_curr;
|
||||
struct batadv_frag_list_entry *frag_entry_last = NULL;
|
||||
struct batadv_frag_list_entry *frag_entry_new = NULL;
|
||||
u16 hdr_size = sizeof(struct batadv_frag_packet);
|
||||
struct batadv_frag_list_entry *frag_entry_curr;
|
||||
struct batadv_frag_packet *frag_packet;
|
||||
u8 bucket;
|
||||
u16 seqno, hdr_size = sizeof(struct batadv_frag_packet);
|
||||
struct batadv_frag_table_entry *chain;
|
||||
bool overflow = false;
|
||||
bool ret = false;
|
||||
size_t data_len;
|
||||
u8 bucket;
|
||||
u16 seqno;
|
||||
|
||||
/* Linearize packet to avoid linearizing 16 packets in a row when doing
|
||||
* the later merge. Non-linear merge should be added to remove this
|
||||
@@ -258,11 +260,12 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
|
||||
static struct sk_buff *
|
||||
batadv_frag_merge_packets(struct hlist_head *chain)
|
||||
{
|
||||
struct batadv_frag_packet *packet;
|
||||
int hdr_size = sizeof(struct batadv_frag_packet);
|
||||
struct batadv_frag_list_entry *entry;
|
||||
struct batadv_frag_packet *packet;
|
||||
struct sk_buff *skb_out;
|
||||
int size, hdr_size = sizeof(struct batadv_frag_packet);
|
||||
bool dropped = false;
|
||||
int size;
|
||||
|
||||
/* Remove first entry, as this is the destination for the rest of the
|
||||
* fragments.
|
||||
@@ -348,8 +351,8 @@ static bool batadv_skb_is_frag(struct sk_buff *skb)
|
||||
bool batadv_frag_skb_buffer(struct sk_buff **skb,
|
||||
struct batadv_orig_node *orig_node_src)
|
||||
{
|
||||
struct sk_buff *skb_out = NULL;
|
||||
struct hlist_head head = HLIST_HEAD_INIT;
|
||||
struct sk_buff *skb_out = NULL;
|
||||
bool ret = false;
|
||||
|
||||
/* Add packet to buffer and table entry if merge is possible. */
|
||||
@@ -403,8 +406,8 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
|
||||
struct batadv_priv *bat_priv = netdev_priv(recv_if->mesh_iface);
|
||||
struct batadv_neigh_node *neigh_node = NULL;
|
||||
struct batadv_frag_packet *packet;
|
||||
u16 total_size;
|
||||
bool ret = false;
|
||||
u16 total_size;
|
||||
|
||||
packet = (struct batadv_frag_packet *)skb->data;
|
||||
|
||||
@@ -468,10 +471,11 @@ static struct sk_buff *batadv_frag_create(struct net_device *net_dev,
|
||||
{
|
||||
unsigned int ll_reserved = LL_RESERVED_SPACE(net_dev);
|
||||
unsigned int tailroom = net_dev->needed_tailroom;
|
||||
struct sk_buff *skb_fragment;
|
||||
unsigned int header_size = sizeof(*frag_head);
|
||||
unsigned int mtu = fragment_size + header_size;
|
||||
struct sk_buff *skb_fragment;
|
||||
unsigned int mtu;
|
||||
|
||||
mtu = fragment_size + header_size;
|
||||
skb_fragment = dev_alloc_skb(ll_reserved + mtu + tailroom);
|
||||
if (!skb_fragment)
|
||||
goto err;
|
||||
@@ -503,15 +507,18 @@ int batadv_frag_send_packet(struct sk_buff *skb,
|
||||
struct batadv_neigh_node *neigh_node)
|
||||
{
|
||||
struct net_device *net_dev = neigh_node->if_incoming->net_dev;
|
||||
struct batadv_priv *bat_priv;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_frag_packet frag_header;
|
||||
struct sk_buff *skb_fragment;
|
||||
unsigned int mtu = net_dev->mtu;
|
||||
unsigned int header_size = sizeof(frag_header);
|
||||
unsigned int max_fragment_size, num_fragments;
|
||||
unsigned int max_fragment_size;
|
||||
struct batadv_priv *bat_priv;
|
||||
struct sk_buff *skb_fragment;
|
||||
unsigned int num_fragments;
|
||||
unsigned int header_size;
|
||||
int ret;
|
||||
|
||||
header_size = sizeof(frag_header);
|
||||
|
||||
/* To avoid merge and refragmentation at next-hops we never send
|
||||
* fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
|
||||
*/
|
||||
|
||||
@@ -103,8 +103,8 @@ batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv)
|
||||
struct batadv_orig_node *
|
||||
batadv_gw_get_selected_orig(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_gw_node *gw_node;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_gw_node *gw_node;
|
||||
|
||||
gw_node = batadv_gw_get_selected_gw_node(bat_priv);
|
||||
if (!gw_node)
|
||||
@@ -125,6 +125,14 @@ batadv_gw_get_selected_orig(struct batadv_priv *bat_priv)
|
||||
return orig_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_gw_select() - select a new currently active gateway
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @new_gw_node: gateway node to be set as the current gateway, may be NULL
|
||||
*
|
||||
* Atomically replace the currently active gateway with @new_gw_node and drop
|
||||
* the reference to the previous one.
|
||||
*/
|
||||
static void batadv_gw_select(struct batadv_priv *bat_priv,
|
||||
struct batadv_gw_node *new_gw_node)
|
||||
{
|
||||
@@ -197,10 +205,10 @@ void batadv_gw_check_client_stop(struct batadv_priv *bat_priv)
|
||||
*/
|
||||
void batadv_gw_election(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_neigh_ifinfo *router_ifinfo = NULL;
|
||||
struct batadv_neigh_node *router = NULL;
|
||||
struct batadv_gw_node *curr_gw = NULL;
|
||||
struct batadv_gw_node *next_gw = NULL;
|
||||
struct batadv_neigh_node *router = NULL;
|
||||
struct batadv_neigh_ifinfo *router_ifinfo = NULL;
|
||||
char gw_addr[18] = { '\0' };
|
||||
|
||||
if (READ_ONCE(bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT)
|
||||
@@ -370,7 +378,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
|
||||
struct batadv_gw_node *batadv_gw_node_get(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node)
|
||||
{
|
||||
struct batadv_gw_node *gw_node_tmp, *gw_node = NULL;
|
||||
struct batadv_gw_node *gw_node = NULL;
|
||||
struct batadv_gw_node *gw_node_tmp;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.gateway_list,
|
||||
@@ -400,7 +409,8 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
struct batadv_tvlv_gateway_data *gateway)
|
||||
{
|
||||
struct batadv_gw_node *gw_node, *curr_gw = NULL;
|
||||
struct batadv_gw_node *curr_gw = NULL;
|
||||
struct batadv_gw_node *gw_node;
|
||||
|
||||
spin_lock_bh(&bat_priv->gw.list_lock);
|
||||
gw_node = batadv_gw_node_get(bat_priv, orig_node);
|
||||
@@ -545,7 +555,10 @@ int batadv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
* @chaddr: buffer where the client address will be stored. Valid
|
||||
* only if the function returns BATADV_DHCP_TO_CLIENT
|
||||
*
|
||||
* This function may re-allocate the data buffer of the skb passed as argument.
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* pskb_may_pull()/... Any pointer into the skb data (e.g.
|
||||
* obtained from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return:
|
||||
* - BATADV_DHCP_NO if the packet is not a dhcp message or if there was an error
|
||||
@@ -558,11 +571,11 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len,
|
||||
u8 *chaddr)
|
||||
{
|
||||
enum batadv_dhcp_recipient ret = BATADV_DHCP_NO;
|
||||
struct ethhdr *ethhdr;
|
||||
struct iphdr *iphdr;
|
||||
struct ipv6hdr *ipv6hdr;
|
||||
struct udphdr *udphdr;
|
||||
struct vlan_ethhdr *vhdr;
|
||||
struct ipv6hdr *ipv6hdr;
|
||||
struct ethhdr *ethhdr;
|
||||
struct udphdr *udphdr;
|
||||
struct iphdr *iphdr;
|
||||
int chaddr_offset;
|
||||
__be16 proto;
|
||||
u8 *p;
|
||||
@@ -669,7 +682,11 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len,
|
||||
* server. Due to topology changes it may be the case that the GW server
|
||||
* previously selected is not the best one anymore.
|
||||
*
|
||||
* This call might reallocate skb data.
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* batadv_get_vid()/... Any pointer into the skb data (e.g. obtained
|
||||
* from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Must be invoked only when the DHCP packet is going TO a DHCP SERVER.
|
||||
*
|
||||
* Return: true if the packet destination is unicast and it is not the best gw,
|
||||
@@ -678,16 +695,17 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len,
|
||||
bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct batadv_orig_node *orig_dst_node = NULL;
|
||||
struct batadv_neigh_node *neigh_curr = NULL;
|
||||
struct batadv_neigh_node *neigh_old = NULL;
|
||||
struct batadv_orig_node *orig_dst_node = NULL;
|
||||
struct batadv_neigh_ifinfo *curr_ifinfo;
|
||||
struct batadv_neigh_ifinfo *old_ifinfo;
|
||||
struct batadv_gw_node *gw_node = NULL;
|
||||
struct batadv_gw_node *curr_gw = NULL;
|
||||
struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo;
|
||||
struct ethhdr *ethhdr;
|
||||
bool out_of_range = false;
|
||||
u8 curr_tq_avg;
|
||||
struct ethhdr *ethhdr;
|
||||
unsigned short vid;
|
||||
u8 curr_tq_avg;
|
||||
|
||||
vid = batadv_get_vid(skb, 0);
|
||||
ethhdr = (struct ethhdr *)skb->data;
|
||||
|
||||
@@ -26,7 +26,8 @@ void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_tvlv_gateway_data gw;
|
||||
enum batadv_gw_modes gw_mode;
|
||||
u32 down, up;
|
||||
u32 down;
|
||||
u32 up;
|
||||
|
||||
gw_mode = READ_ONCE(bat_priv->gw.mode);
|
||||
|
||||
@@ -59,7 +60,8 @@ static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
|
||||
u8 flags,
|
||||
void *tvlv_value, u16 tvlv_value_len)
|
||||
{
|
||||
struct batadv_tvlv_gateway_data gateway, *gateway_ptr;
|
||||
struct batadv_tvlv_gateway_data *gateway_ptr;
|
||||
struct batadv_tvlv_gateway_data gateway;
|
||||
|
||||
/* only fetch the tvlv value if the handler wasn't called via the
|
||||
* CIFNOTFND flag and if there is data to fetch
|
||||
|
||||
@@ -197,6 +197,17 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_is_valid_iface() - check whether a net_device can be used as a hard
|
||||
* interface
|
||||
* @net_dev: the net_device to check
|
||||
*
|
||||
* Refuse loopback devices, non-Ethernet devices, devices with a non-Ethernet
|
||||
* address length and any device that is already part of a batman-adv mesh
|
||||
* interface stack.
|
||||
*
|
||||
* Return: true if @net_dev can be used as a hard interface, false otherwise
|
||||
*/
|
||||
static bool batadv_is_valid_iface(const struct net_device *net_dev)
|
||||
{
|
||||
if (net_dev->flags & IFF_LOOPBACK)
|
||||
@@ -339,8 +350,8 @@ static bool batadv_is_cfg80211_netdev(struct net_device *net_device)
|
||||
*/
|
||||
static u32 batadv_wifi_flags_evaluate(struct net_device *net_device)
|
||||
{
|
||||
u32 wifi_flags = 0;
|
||||
struct net_device *real_netdev;
|
||||
u32 wifi_flags = 0;
|
||||
|
||||
if (batadv_is_wext_netdev(net_device))
|
||||
wifi_flags |= BATADV_HARDIF_WIFI_WEXT_DIRECT;
|
||||
@@ -434,8 +445,8 @@ int batadv_hardif_no_broadcast(struct batadv_hard_iface *if_outgoing,
|
||||
u8 *orig_addr, u8 *orig_neigh)
|
||||
{
|
||||
struct batadv_hardif_neigh_node *hardif_neigh;
|
||||
struct hlist_node *first;
|
||||
int ret = BATADV_HARDIF_BCAST_OK;
|
||||
struct hlist_node *first;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@@ -467,6 +478,14 @@ int batadv_hardif_no_broadcast(struct batadv_hard_iface *if_outgoing,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_hardif_get_active() - retrieve an active hard interface for a mesh
|
||||
* interface
|
||||
* @mesh_iface: mesh interface to search
|
||||
*
|
||||
* Return: first hard interface in BATADV_IF_ACTIVE state attached to
|
||||
* @mesh_iface, or NULL if none is active.
|
||||
*/
|
||||
static struct batadv_hard_iface *
|
||||
batadv_hardif_get_active(struct net_device *mesh_iface)
|
||||
{
|
||||
@@ -487,6 +506,15 @@ batadv_hardif_get_active(struct net_device *mesh_iface)
|
||||
return hard_iface;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_primary_if_update_addr() - propagate the new primary interface MAC
|
||||
* address to all dependent components
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @oldif: previously used primary interface, or NULL if none
|
||||
*
|
||||
* Inform DAT and BLA that the originator address has changed so they can
|
||||
* adjust their state accordingly.
|
||||
*/
|
||||
static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *oldif)
|
||||
{
|
||||
@@ -502,6 +530,15 @@ static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
|
||||
batadv_hardif_put(primary_if);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_primary_if_select() - select the new primary interface
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @new_hard_iface: new primary interface, may be NULL
|
||||
*
|
||||
* Replace the currently selected primary interface with @new_hard_iface,
|
||||
* invoke the algorithm-specific primary_set hook and update the originator
|
||||
* MAC address.
|
||||
*/
|
||||
static void batadv_primary_if_select(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *new_hard_iface)
|
||||
{
|
||||
@@ -525,6 +562,13 @@ static void batadv_primary_if_select(struct batadv_priv *bat_priv,
|
||||
batadv_hardif_put(curr_hard_iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_hardif_is_iface_up() - check whether the underlying net_device of a
|
||||
* hard interface is up
|
||||
* @hard_iface: the hard interface to check
|
||||
*
|
||||
* Return: true if the underlying net_device has the IFF_UP flag set
|
||||
*/
|
||||
static bool
|
||||
batadv_hardif_is_iface_up(const struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
@@ -534,6 +578,15 @@ batadv_hardif_is_iface_up(const struct batadv_hard_iface *hard_iface)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_check_known_mac_addr() - warn about duplicate hard interface MAC
|
||||
* addresses
|
||||
* @hard_iface: hard interface that was just added or had its MAC changed
|
||||
*
|
||||
* Iterate over all hard interfaces of the same mesh interface and emit a
|
||||
* warning if another in-use interface shares the same MAC address as
|
||||
* @hard_iface.
|
||||
*/
|
||||
static void batadv_check_known_mac_addr(const struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct net_device *mesh_iface = hard_iface->mesh_iface;
|
||||
@@ -666,11 +719,20 @@ void batadv_update_min_mtu(struct net_device *mesh_iface)
|
||||
batadv_tt_local_resize_to_mtu(mesh_iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_hardif_activate_interface() - move a hard interface to the active
|
||||
* state
|
||||
* @hard_iface: the interface that has come up
|
||||
*
|
||||
* Activate an interface, select it as the primary interface if no
|
||||
* primary is currently active and invoke the algorithm-specific
|
||||
* activate hook.
|
||||
*/
|
||||
static void
|
||||
batadv_hardif_activate_interface(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_priv *bat_priv;
|
||||
|
||||
if (hard_iface->if_status != BATADV_IF_INACTIVE)
|
||||
goto out;
|
||||
@@ -699,6 +761,14 @@ batadv_hardif_activate_interface(struct batadv_hard_iface *hard_iface)
|
||||
batadv_hardif_put(primary_if);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_hardif_deactivate_interface() - move a hard interface to the
|
||||
* inactive state
|
||||
* @hard_iface: the interface that went down
|
||||
*
|
||||
* Demote @hard_iface to BATADV_IF_INACTIVE and recalculate the mesh minimum
|
||||
* MTU based on the remaining active interfaces.
|
||||
*/
|
||||
static void
|
||||
batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
@@ -724,10 +794,10 @@ batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface)
|
||||
int batadv_hardif_enable_interface(struct net_device *net_dev,
|
||||
struct net_device *mesh_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv;
|
||||
__be16 ethertype = htons(ETH_P_BATMAN);
|
||||
int max_header_len = batadv_max_header_len();
|
||||
__be16 ethertype = htons(ETH_P_BATMAN);
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
unsigned int required_mtu;
|
||||
unsigned int hardif_mtu;
|
||||
bool fragmentation;
|
||||
@@ -1020,12 +1090,24 @@ static void batadv_wifi_net_device_event(unsigned long event,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_hard_if_event() - netdevice notifier callback for hard interfaces
|
||||
* @this: notifier block (unused)
|
||||
* @event: the NETDEV_* event to handle
|
||||
* @ptr: notifier info pointing to the affected net_device
|
||||
*
|
||||
* Dispatch netdevice events that affect potential or existing hard
|
||||
* interfaces. Mesh interfaces are handled separately by
|
||||
* batadv_hard_if_event_meshif().
|
||||
*
|
||||
* Return: NOTIFY_DONE
|
||||
*/
|
||||
static int batadv_hard_if_event(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
|
||||
if (batadv_meshif_is_valid(net_dev))
|
||||
|
||||
@@ -11,7 +11,10 @@
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* clears the hash */
|
||||
/**
|
||||
* batadv_hash_init() - clear all buckets of a hashtable
|
||||
* @hash: hashtable to clear
|
||||
*/
|
||||
static void batadv_hash_init(struct batadv_hashtable *hash)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
@@ -18,21 +18,35 @@
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* callback to a compare function. should compare 2 element data for their
|
||||
* keys
|
||||
/**
|
||||
* typedef batadv_hashdata_compare_cb - hash element comparison callback
|
||||
* @node: hlist node of the element currently stored in the bucket
|
||||
* @key: opaque payload to compare @node's key against
|
||||
*
|
||||
* Return: true if same and false if not same
|
||||
* Compare hash element by its keys.
|
||||
*
|
||||
* Return: true if both elements are considered equal, false otherwise.
|
||||
*/
|
||||
typedef bool (*batadv_hashdata_compare_cb)(const struct hlist_node *,
|
||||
const void *);
|
||||
typedef bool (*batadv_hashdata_compare_cb)(const struct hlist_node *node,
|
||||
const void *key);
|
||||
|
||||
/* the hashfunction
|
||||
/**
|
||||
* typedef batadv_hashdata_choose_cb - hash bucket selection callback
|
||||
* @key: opaque payload whose key selects the bucket
|
||||
* @size: number of buckets in the hash table
|
||||
*
|
||||
* Return: an index based on the key in the data of the first argument and the
|
||||
* size the second
|
||||
* Return: bucket index derived from the key in @key and the table @size.
|
||||
*/
|
||||
typedef u32 (*batadv_hashdata_choose_cb)(const void *, u32);
|
||||
typedef void (*batadv_hashdata_free_cb)(struct hlist_node *, void *);
|
||||
typedef u32 (*batadv_hashdata_choose_cb)(const void *key, u32 size);
|
||||
|
||||
/**
|
||||
* typedef batadv_hashdata_free_cb - hash element free callback
|
||||
* @node: hlist node of the element being removed
|
||||
* @arg: opaque caller-supplied argument forwarded from the caller
|
||||
*
|
||||
* Release a previously inserted hash element.
|
||||
*/
|
||||
typedef void (*batadv_hashdata_free_cb)(struct hlist_node *node, void *arg);
|
||||
|
||||
/**
|
||||
* struct batadv_hashtable - Wrapper of simple hlist based hashtable
|
||||
@@ -78,11 +92,11 @@ static inline int batadv_hash_add(struct batadv_hashtable *hash,
|
||||
const void *data,
|
||||
struct hlist_node *data_node)
|
||||
{
|
||||
u32 index;
|
||||
int ret = -1;
|
||||
spinlock_t *list_lock; /* spinlock to protect write access */
|
||||
struct hlist_head *head;
|
||||
struct hlist_node *node;
|
||||
spinlock_t *list_lock; /* spinlock to protect write access */
|
||||
int ret = -1;
|
||||
u32 index;
|
||||
|
||||
if (!hash)
|
||||
goto out;
|
||||
@@ -131,10 +145,10 @@ static inline void *batadv_hash_remove(struct batadv_hashtable *hash,
|
||||
batadv_hashdata_choose_cb choose,
|
||||
void *data)
|
||||
{
|
||||
u32 index;
|
||||
struct hlist_node *node;
|
||||
struct hlist_head *head;
|
||||
void *data_save = NULL;
|
||||
u32 index;
|
||||
|
||||
index = choose(data, hash->size);
|
||||
head = &hash->table[index];
|
||||
|
||||
@@ -117,8 +117,12 @@ static inline void _batadv_dbg(int type __always_unused,
|
||||
*/
|
||||
#define batadv_info(net_dev, fmt, arg...) \
|
||||
do { \
|
||||
struct net_device *_netdev = (net_dev); \
|
||||
struct batadv_priv *_batpriv = netdev_priv(_netdev); \
|
||||
struct batadv_priv *_batpriv; \
|
||||
struct net_device *_netdev; \
|
||||
\
|
||||
_netdev = (net_dev); \
|
||||
_batpriv = netdev_priv(_netdev); \
|
||||
\
|
||||
batadv_dbg(BATADV_DBG_ALL, _batpriv, fmt, ## arg); \
|
||||
pr_info("%s: " fmt, _netdev->name, ## arg); \
|
||||
} while (0)
|
||||
@@ -131,8 +135,12 @@ static inline void _batadv_dbg(int type __always_unused,
|
||||
*/
|
||||
#define batadv_err(net_dev, fmt, arg...) \
|
||||
do { \
|
||||
struct net_device *_netdev = (net_dev); \
|
||||
struct batadv_priv *_batpriv = netdev_priv(_netdev); \
|
||||
struct batadv_priv *_batpriv; \
|
||||
struct net_device *_netdev; \
|
||||
\
|
||||
_netdev = (net_dev); \
|
||||
_batpriv = netdev_priv(_netdev); \
|
||||
\
|
||||
batadv_dbg(BATADV_DBG_ALL, _batpriv, fmt, ## arg); \
|
||||
pr_err("%s: " fmt, _netdev->name, ## arg); \
|
||||
} while (0)
|
||||
|
||||
@@ -82,6 +82,14 @@ static char *batadv_uev_type_str[] = {
|
||||
"bla",
|
||||
};
|
||||
|
||||
/**
|
||||
* batadv_init() - batman-adv module init function
|
||||
*
|
||||
* Initialise the global state used by all mesh interfaces, register the
|
||||
* netdevice notifier and the netlink/rtnl family.
|
||||
*
|
||||
* Return: 0 on success or negative error number in case of failure
|
||||
*/
|
||||
static int __init batadv_init(void)
|
||||
{
|
||||
int ret;
|
||||
@@ -94,40 +102,69 @@ static int __init batadv_init(void)
|
||||
|
||||
batadv_recv_handler_init();
|
||||
|
||||
batadv_v_init();
|
||||
batadv_iv_init();
|
||||
ret = batadv_v_init();
|
||||
if (ret < 0)
|
||||
goto err_tt;
|
||||
|
||||
ret = batadv_iv_init();
|
||||
if (ret < 0)
|
||||
goto err_v;
|
||||
|
||||
batadv_tp_meter_init();
|
||||
|
||||
ret = batadv_wifi_net_devices_init();
|
||||
if (ret < 0)
|
||||
goto err_iv;
|
||||
|
||||
batadv_event_workqueue = create_singlethread_workqueue("bat_events");
|
||||
if (!batadv_event_workqueue) {
|
||||
ret = -ENOMEM;
|
||||
goto err_create_wq;
|
||||
goto err_wifi;
|
||||
}
|
||||
|
||||
ret = batadv_wifi_net_devices_init();
|
||||
ret = register_netdevice_notifier(&batadv_hard_if_notifier);
|
||||
if (ret < 0)
|
||||
goto err_init_wifi;
|
||||
goto err_wq;
|
||||
|
||||
register_netdevice_notifier(&batadv_hard_if_notifier);
|
||||
rtnl_link_register(&batadv_link_ops);
|
||||
batadv_netlink_register();
|
||||
ret = rtnl_link_register(&batadv_link_ops);
|
||||
if (ret < 0)
|
||||
goto err_notifier;
|
||||
|
||||
ret = batadv_netlink_register();
|
||||
if (ret < 0)
|
||||
goto err_rtnl;
|
||||
|
||||
pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n",
|
||||
init_utsname()->release, BATADV_COMPAT_VERSION);
|
||||
|
||||
return 0;
|
||||
|
||||
err_init_wifi:
|
||||
err_rtnl:
|
||||
rtnl_link_unregister(&batadv_link_ops);
|
||||
err_notifier:
|
||||
unregister_netdevice_notifier(&batadv_hard_if_notifier);
|
||||
err_wq:
|
||||
destroy_workqueue(batadv_event_workqueue);
|
||||
batadv_event_workqueue = NULL;
|
||||
rcu_barrier();
|
||||
|
||||
err_create_wq:
|
||||
err_wifi:
|
||||
batadv_wifi_net_devices_deinit();
|
||||
err_iv:
|
||||
batadv_iv_deinit();
|
||||
err_v:
|
||||
batadv_v_deinit();
|
||||
err_tt:
|
||||
batadv_tt_cache_destroy();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_exit() - batman-adv module exit function
|
||||
*
|
||||
* Unregister the netdevice notifier and tear down all global state allocated
|
||||
* by batadv_init().
|
||||
*/
|
||||
static void __exit batadv_exit(void)
|
||||
{
|
||||
batadv_netlink_unregister();
|
||||
@@ -354,10 +391,14 @@ int batadv_max_header_len(void)
|
||||
*/
|
||||
void batadv_skb_set_priority(struct sk_buff *skb, int offset)
|
||||
{
|
||||
struct iphdr ip_hdr_tmp, *ip_hdr;
|
||||
struct ipv6hdr ip6_hdr_tmp, *ip6_hdr;
|
||||
struct ethhdr ethhdr_tmp, *ethhdr;
|
||||
struct vlan_ethhdr *vhdr, vhdr_tmp;
|
||||
struct vlan_ethhdr vhdr_tmp;
|
||||
struct ipv6hdr ip6_hdr_tmp;
|
||||
struct ethhdr ethhdr_tmp;
|
||||
struct vlan_ethhdr *vhdr;
|
||||
struct iphdr ip_hdr_tmp;
|
||||
struct ipv6hdr *ip6_hdr;
|
||||
struct ethhdr *ethhdr;
|
||||
struct iphdr *ip_hdr;
|
||||
u32 prio;
|
||||
|
||||
/* already set, do nothing */
|
||||
@@ -398,6 +439,17 @@ void batadv_skb_set_priority(struct sk_buff *skb, int offset)
|
||||
skb->priority = prio + 256;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_recv_unhandled_packet() - default RX handler for unsupported packet
|
||||
* types
|
||||
* @skb: incoming packet
|
||||
* @recv_if: interface on which the packet was received (unused)
|
||||
*
|
||||
* Drop incoming packets whose packet_type has no dedicated RX handler
|
||||
* registered.
|
||||
*
|
||||
* Return: NET_RX_DROP
|
||||
*/
|
||||
static int batadv_recv_unhandled_packet(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
{
|
||||
@@ -406,10 +458,6 @@ static int batadv_recv_unhandled_packet(struct sk_buff *skb,
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
/* incoming packets with the batman ethertype received on any active hard
|
||||
* interface
|
||||
*/
|
||||
|
||||
/**
|
||||
* batadv_batman_skb_recv() - Handle incoming message from an hard interface
|
||||
* @skb: the received packet
|
||||
@@ -423,9 +471,9 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *ptype,
|
||||
struct net_device *orig_dev)
|
||||
{
|
||||
struct batadv_priv *bat_priv;
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
u8 idx;
|
||||
|
||||
hard_iface = container_of(ptype, struct batadv_hard_iface,
|
||||
@@ -492,6 +540,13 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_recv_handler_init() - initialise the RX handler dispatch table
|
||||
*
|
||||
* Initialise all entries of the RX handler table as either "unhandled" or with
|
||||
* protocol indepentend handlers, and perform compile-time size sanity checks on
|
||||
* all on-wire packet structs.
|
||||
*/
|
||||
static void batadv_recv_handler_init(void)
|
||||
{
|
||||
int i;
|
||||
@@ -582,6 +637,11 @@ void batadv_recv_handler_unregister(u8 packet_type)
|
||||
* The caller must ensure that at least @header_len + ETH_HLEN bytes are
|
||||
* accessible after skb->data.
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* pskb_may_pull()/... Any pointer into the skb data (e.g. obtained from skb->data
|
||||
* or eth_hdr()) before this call must be considered invalid afterwards and has
|
||||
* to be reacquired.
|
||||
*
|
||||
* Return: VID with the BATADV_VLAN_HAS_TAG flag when the packet embedded in the
|
||||
* skb is vlan tagged. Otherwise BATADV_NO_FLAGS.
|
||||
*/
|
||||
@@ -650,9 +710,9 @@ bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid)
|
||||
int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
|
||||
enum batadv_uev_action action, const char *data)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
struct kobject *bat_kobj;
|
||||
char *uevent_env[4] = { NULL, NULL, NULL, NULL };
|
||||
struct kobject *bat_kobj;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
bat_kobj = &bat_priv->mesh_iface->dev.kobj;
|
||||
|
||||
|
||||
@@ -57,6 +57,11 @@
|
||||
* @skb: packet buffer which should be modified
|
||||
* @len: number of bytes to add
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* skb_cow_head()/... Any pointer into the skb data (e.g. obtained
|
||||
* from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: 0 on success or negative error number in case of failure
|
||||
*/
|
||||
int batadv_skb_head_push(struct sk_buff *skb, unsigned int len)
|
||||
@@ -87,7 +92,8 @@ int batadv_skb_head_push(struct sk_buff *skb, unsigned int len)
|
||||
*/
|
||||
static u64 batadv_sum_counter(struct batadv_priv *bat_priv, size_t idx)
|
||||
{
|
||||
u64 *counters, sum = 0;
|
||||
u64 *counters;
|
||||
u64 sum = 0;
|
||||
int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
@@ -98,6 +104,15 @@ static u64 batadv_sum_counter(struct batadv_priv *bat_priv, size_t idx)
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_interface_stats() - return netdev stats for a mesh interface
|
||||
* @dev: the mesh interface to query
|
||||
*
|
||||
* Aggregate the per-CPU traffic counters into the standard netdev stats
|
||||
* structure.
|
||||
*
|
||||
* Return: pointer to the populated net_device_stats structure
|
||||
*/
|
||||
static struct net_device_stats *batadv_interface_stats(struct net_device *dev)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(dev);
|
||||
@@ -111,6 +126,18 @@ static struct net_device_stats *batadv_interface_stats(struct net_device *dev)
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_interface_set_mac_addr() - change the MAC address of a mesh
|
||||
* interface
|
||||
* @dev: the mesh interface to modify
|
||||
* @p: pointer to a struct sockaddr holding the new MAC address
|
||||
*
|
||||
* Replace the MAC address of the mesh interface. If the mesh is already
|
||||
* active, also update the local translation table entries for all configured
|
||||
* VLANs so that the new MAC is announced and the old one is removed.
|
||||
*
|
||||
* Return: 0 on success or negative error number in case of failure
|
||||
*/
|
||||
static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(dev);
|
||||
@@ -140,6 +167,16 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_interface_change_mtu() - change the MTU of a mesh interface
|
||||
* @dev: the mesh interface to modify
|
||||
* @new_mtu: requested new MTU value
|
||||
*
|
||||
* Validate that @new_mtu fits within the range supported by the configured
|
||||
* hard interfaces and remember it as the user-configured MTU.
|
||||
*
|
||||
* Return: 0 on success or -EINVAL if @new_mtu is out of range
|
||||
*/
|
||||
static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(dev);
|
||||
@@ -166,31 +203,39 @@ static void batadv_interface_set_rx_mode(struct net_device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_interface_tx() - transmit a frame on a mesh interface
|
||||
* @skb: the frame to send
|
||||
* @mesh_iface: the mesh interface the frame was queued on
|
||||
*
|
||||
* Return: NETDEV_TX_OK on success
|
||||
*/
|
||||
static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
|
||||
struct net_device *mesh_iface)
|
||||
{
|
||||
struct ethhdr *ethhdr;
|
||||
static const u8 ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
static const u8 stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x00};
|
||||
struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
|
||||
enum batadv_dhcp_recipient dhcp_rcp = BATADV_DHCP_NO;
|
||||
enum batadv_forw_mode forw_mode = BATADV_FORW_BCAST;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_bcast_packet *bcast_packet;
|
||||
static const u8 stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
|
||||
0x00, 0x00};
|
||||
static const u8 ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00};
|
||||
enum batadv_dhcp_recipient dhcp_rcp = BATADV_DHCP_NO;
|
||||
u8 *dst_hint = NULL, chaddr[ETH_ALEN];
|
||||
struct vlan_ethhdr *vhdr;
|
||||
unsigned int header_len = 0;
|
||||
int data_len = skb->len, ret;
|
||||
unsigned long brd_delay = 0;
|
||||
bool do_bcast = false, client_added;
|
||||
unsigned short vid;
|
||||
u32 seqno;
|
||||
int gw_mode;
|
||||
enum batadv_forw_mode forw_mode = BATADV_FORW_BCAST;
|
||||
int mcast_is_routable = 0;
|
||||
int network_offset = ETH_HLEN;
|
||||
unsigned int header_len = 0;
|
||||
unsigned long brd_delay = 0;
|
||||
int mcast_is_routable = 0;
|
||||
struct vlan_ethhdr *vhdr;
|
||||
int data_len = skb->len;
|
||||
struct ethhdr *ethhdr;
|
||||
bool do_bcast = false;
|
||||
u8 *dst_hint = NULL;
|
||||
u8 chaddr[ETH_ALEN];
|
||||
unsigned short vid;
|
||||
bool client_added;
|
||||
__be16 proto;
|
||||
int gw_mode;
|
||||
u32 seqno;
|
||||
int ret;
|
||||
|
||||
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
|
||||
goto dropped;
|
||||
@@ -408,8 +453,8 @@ void batadv_interface_rx(struct net_device *mesh_iface,
|
||||
struct sk_buff *skb, int hdr_size,
|
||||
struct batadv_orig_node *orig_node)
|
||||
{
|
||||
struct batadv_bcast_packet *batadv_bcast_packet;
|
||||
struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
|
||||
struct batadv_bcast_packet *batadv_bcast_packet;
|
||||
struct vlan_ethhdr *vhdr;
|
||||
struct ethhdr *ethhdr;
|
||||
unsigned short vid;
|
||||
@@ -523,7 +568,8 @@ void batadv_meshif_vlan_release(struct kref *ref)
|
||||
struct batadv_meshif_vlan *batadv_meshif_vlan_get(struct batadv_priv *bat_priv,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_meshif_vlan *vlan_tmp, *vlan = NULL;
|
||||
struct batadv_meshif_vlan *vlan = NULL;
|
||||
struct batadv_meshif_vlan *vlan_tmp;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->meshif_vlan_list, list) {
|
||||
@@ -741,10 +787,10 @@ static void batadv_set_lockdep_class(struct net_device *dev)
|
||||
*/
|
||||
static int batadv_meshif_init_late(struct net_device *dev)
|
||||
{
|
||||
size_t cnt_len = sizeof(u64) * BATADV_CNT_NUM;
|
||||
struct batadv_priv *bat_priv;
|
||||
u32 random_seqno;
|
||||
int ret;
|
||||
size_t cnt_len = sizeof(u64) * BATADV_CNT_NUM;
|
||||
|
||||
batadv_set_lockdep_class(dev);
|
||||
|
||||
@@ -883,6 +929,11 @@ static const struct net_device_ops batadv_netdev_ops = {
|
||||
.ndo_del_slave = batadv_meshif_slave_del,
|
||||
};
|
||||
|
||||
/**
|
||||
* batadv_get_drvinfo() - ethtool driver info handler for mesh interfaces
|
||||
* @dev: the mesh interface (unused)
|
||||
* @info: ethtool_drvinfo struct to populate
|
||||
*/
|
||||
static void batadv_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
@@ -943,6 +994,12 @@ static const struct {
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* batadv_get_strings() - ethtool string handler for mesh interfaces
|
||||
* @dev: the mesh interface (unused)
|
||||
* @stringset: ethtool string set to retrieve
|
||||
* @data: buffer to copy the requested string set into
|
||||
*/
|
||||
static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data)
|
||||
{
|
||||
if (stringset == ETH_SS_STATS)
|
||||
@@ -950,6 +1007,12 @@ static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data)
|
||||
sizeof(batadv_counters_strings));
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_get_ethtool_stats() - ethtool stats handler for mesh interfaces
|
||||
* @dev: the mesh interface to query
|
||||
* @stats: ethtool_stats struct (unused)
|
||||
* @data: destination array for the gathered counter values
|
||||
*/
|
||||
static void batadv_get_ethtool_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
@@ -960,6 +1023,14 @@ static void batadv_get_ethtool_stats(struct net_device *dev,
|
||||
data[i] = batadv_sum_counter(bat_priv, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_get_sset_count() - ethtool stringset size handler for mesh interfaces
|
||||
* @dev: the mesh interface (unused)
|
||||
* @stringset: ethtool string set to query
|
||||
*
|
||||
* Return: number of entries in @stringset or -EOPNOTSUPP if @stringset is not
|
||||
* supported
|
||||
*/
|
||||
static int batadv_get_sset_count(struct net_device *dev, int stringset)
|
||||
{
|
||||
if (stringset == ETH_SS_STATS)
|
||||
|
||||
@@ -274,8 +274,9 @@ static struct batadv_mcast_mla_flags
|
||||
batadv_mcast_mla_flags_get(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct net_device *dev = bat_priv->mesh_iface;
|
||||
struct batadv_mcast_querier_state *qr4, *qr6;
|
||||
struct batadv_mcast_mla_flags mla_flags;
|
||||
struct batadv_mcast_querier_state *qr4;
|
||||
struct batadv_mcast_querier_state *qr6;
|
||||
struct net_device *bridge;
|
||||
|
||||
bridge = batadv_mcast_get_bridge(dev);
|
||||
@@ -521,7 +522,8 @@ batadv_mcast_mla_meshif_get(struct net_device *dev,
|
||||
struct batadv_mcast_mla_flags *flags)
|
||||
{
|
||||
struct net_device *bridge = batadv_mcast_get_bridge(dev);
|
||||
int ret4, ret6 = 0;
|
||||
int ret6 = 0;
|
||||
int ret4;
|
||||
|
||||
if (bridge)
|
||||
dev = bridge;
|
||||
@@ -585,10 +587,11 @@ static int batadv_mcast_mla_bridge_get(struct net_device *dev,
|
||||
struct batadv_mcast_mla_flags *flags)
|
||||
{
|
||||
struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list);
|
||||
struct br_ip_list *br_ip_entry, *tmp;
|
||||
u8 tvlv_flags = flags->tvlv_flags;
|
||||
struct br_ip_list *br_ip_entry;
|
||||
struct batadv_hw_addr *new;
|
||||
u8 mcast_addr[ETH_ALEN];
|
||||
struct br_ip_list *tmp;
|
||||
int ret;
|
||||
|
||||
/* we don't need to detect these devices/listeners, the IGMP/MLD
|
||||
@@ -935,8 +938,8 @@ static void __batadv_mcast_mla_update(struct batadv_priv *bat_priv)
|
||||
*/
|
||||
static void batadv_mcast_mla_update(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work;
|
||||
struct batadv_priv_mcast *priv_mcast;
|
||||
struct delayed_work *delayed_work;
|
||||
struct batadv_priv *bat_priv;
|
||||
|
||||
delayed_work = to_delayed_work(work);
|
||||
@@ -951,7 +954,10 @@ static void batadv_mcast_mla_update(struct work_struct *work)
|
||||
* batadv_mcast_is_report_ipv4() - check for IGMP reports
|
||||
* @skb: the ethernet frame destined for the mesh
|
||||
*
|
||||
* This call might reallocate skb data.
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* ip_mc_check_igmp()/... Any pointer into the skb data (e.g.
|
||||
* obtained from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Checks whether the given frame is a valid IGMP report.
|
||||
*
|
||||
@@ -1017,7 +1023,10 @@ static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv,
|
||||
* batadv_mcast_is_report_ipv6() - check for MLD reports
|
||||
* @skb: the ethernet frame destined for the mesh
|
||||
*
|
||||
* This call might reallocate skb data.
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* ipv6_mc_check_mld()/... Any pointer into the skb data (e.g.
|
||||
* obtained from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Checks whether the given frame is a valid MLD report.
|
||||
*
|
||||
@@ -1223,10 +1232,14 @@ enum batadv_forw_mode
|
||||
batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid, int *is_routable)
|
||||
{
|
||||
int ret, tt_count, ip_count, unsnoop_count, total_count;
|
||||
bool is_unsnoopable = false;
|
||||
struct ethhdr *ethhdr;
|
||||
int unsnoop_count;
|
||||
int rtr_count = 0;
|
||||
int total_count;
|
||||
int tt_count;
|
||||
int ip_count;
|
||||
int ret;
|
||||
|
||||
ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable,
|
||||
is_routable);
|
||||
@@ -1301,13 +1314,11 @@ static int
|
||||
batadv_mcast_forw_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid)
|
||||
{
|
||||
int ret = NET_XMIT_SUCCESS;
|
||||
struct sk_buff *newskb;
|
||||
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
|
||||
struct batadv_tt_global_entry *tt_global;
|
||||
const u8 *addr = eth_hdr(skb)->h_dest;
|
||||
int ret = NET_XMIT_SUCCESS;
|
||||
struct sk_buff *newskb;
|
||||
|
||||
tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
|
||||
if (!tt_global)
|
||||
@@ -1602,8 +1613,8 @@ static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig,
|
||||
u8 mcast_flags)
|
||||
{
|
||||
struct hlist_node *node = &orig->mcast_want_all_unsnoopables_node;
|
||||
struct hlist_head *head = &bat_priv->mcast.want_all_unsnoopables_list;
|
||||
struct hlist_node *node = &orig->mcast_want_all_unsnoopables_node;
|
||||
|
||||
lockdep_assert_held(&orig->mcast_handler_lock);
|
||||
|
||||
@@ -1647,8 +1658,8 @@ static void batadv_mcast_want_ipv4_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig,
|
||||
u8 mcast_flags)
|
||||
{
|
||||
struct hlist_node *node = &orig->mcast_want_all_ipv4_node;
|
||||
struct hlist_head *head = &bat_priv->mcast.want_all_ipv4_list;
|
||||
struct hlist_node *node = &orig->mcast_want_all_ipv4_node;
|
||||
|
||||
lockdep_assert_held(&orig->mcast_handler_lock);
|
||||
|
||||
@@ -1692,8 +1703,8 @@ static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig,
|
||||
u8 mcast_flags)
|
||||
{
|
||||
struct hlist_node *node = &orig->mcast_want_all_ipv6_node;
|
||||
struct hlist_head *head = &bat_priv->mcast.want_all_ipv6_list;
|
||||
struct hlist_node *node = &orig->mcast_want_all_ipv6_node;
|
||||
|
||||
lockdep_assert_held(&orig->mcast_handler_lock);
|
||||
|
||||
@@ -1737,8 +1748,8 @@ static void batadv_mcast_want_rtr4_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig,
|
||||
u8 mcast_flags)
|
||||
{
|
||||
struct hlist_node *node = &orig->mcast_want_all_rtr4_node;
|
||||
struct hlist_head *head = &bat_priv->mcast.want_all_rtr4_list;
|
||||
struct hlist_node *node = &orig->mcast_want_all_rtr4_node;
|
||||
|
||||
lockdep_assert_held(&orig->mcast_handler_lock);
|
||||
|
||||
@@ -1782,8 +1793,8 @@ static void batadv_mcast_want_rtr6_update(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig,
|
||||
u8 mcast_flags)
|
||||
{
|
||||
struct hlist_node *node = &orig->mcast_want_all_rtr6_node;
|
||||
struct hlist_head *head = &bat_priv->mcast.want_all_rtr6_list;
|
||||
struct hlist_node *node = &orig->mcast_want_all_rtr6_node;
|
||||
|
||||
lockdep_assert_held(&orig->mcast_handler_lock);
|
||||
|
||||
|
||||
@@ -195,8 +195,8 @@ static int batadv_mcast_forw_push_dests_list(struct batadv_priv *bat_priv,
|
||||
unsigned short *num_dests,
|
||||
unsigned short *tvlv_len)
|
||||
{
|
||||
struct hlist_node *node;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct hlist_node *node;
|
||||
|
||||
rcu_read_lock();
|
||||
__hlist_for_each_rcu(node, head) {
|
||||
@@ -232,12 +232,9 @@ batadv_mcast_forw_push_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short *tvlv_len)
|
||||
{
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
|
||||
struct batadv_tt_global_entry *tt_global;
|
||||
const u8 *addr = eth_hdr(skb)->h_dest;
|
||||
|
||||
/* ok */
|
||||
int ret = true;
|
||||
int ret = true; /* ok */
|
||||
|
||||
tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
|
||||
if (!tt_global)
|
||||
@@ -368,7 +365,8 @@ static void batadv_mcast_forw_scrape(struct sk_buff *skb,
|
||||
unsigned short offset,
|
||||
unsigned short len)
|
||||
{
|
||||
char *to, *from;
|
||||
char *from;
|
||||
char *to;
|
||||
|
||||
SKB_LINEAR_ASSERT(skb);
|
||||
|
||||
@@ -411,7 +409,8 @@ static bool batadv_mcast_forw_push_insert_padding(struct sk_buff *skb,
|
||||
unsigned short *tvlv_len)
|
||||
{
|
||||
unsigned short offset = *tvlv_len;
|
||||
char *to, *from = skb->data;
|
||||
char *from = skb->data;
|
||||
char *to;
|
||||
|
||||
to = batadv_mcast_forw_push_padding(skb, tvlv_len);
|
||||
if (!to)
|
||||
@@ -933,8 +932,9 @@ static int batadv_mcast_forw_packet(struct batadv_priv *bat_priv,
|
||||
unsigned int tvlv_len;
|
||||
unsigned long offset;
|
||||
bool xmitted = false;
|
||||
u8 *dest, *next_dest;
|
||||
u8 *next_dest;
|
||||
u16 num_dests;
|
||||
u8 *dest;
|
||||
int ret;
|
||||
|
||||
/* (at least) TVLV part needs to be linearized */
|
||||
@@ -1080,6 +1080,11 @@ unsigned int batadv_mcast_forw_packet_hdrlen(unsigned int num_dests)
|
||||
* Tries to expand an skb's headroom so that its head to tail is 1298
|
||||
* bytes (minimum IPv6 MTU + vlan ethernet header size) large.
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* skb_cow()/skb_linearize()/... Any pointer into the skb data (e.g.
|
||||
* obtained from skb->data or eth_hdr()) before this call must be
|
||||
* considered invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: -EINVAL if the given skb's length is too large or -ENOMEM on memory
|
||||
* allocation failure. Otherwise, on success, zero is returned.
|
||||
*/
|
||||
@@ -1120,6 +1125,11 @@ static int batadv_mcast_forw_expand_head(struct batadv_priv *bat_priv,
|
||||
* that signaled interest in it, that is either via the translation table or the
|
||||
* according want-all flags, is attached accordingly.
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* batadv_mcast_forw_expand_head()/... Any pointer into the skb data (e.g.
|
||||
* obtained from skb->data or eth_hdr()) before this call must be
|
||||
* considered invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true on success, false otherwise.
|
||||
*/
|
||||
bool batadv_mcast_forw_push(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
|
||||
@@ -52,9 +52,15 @@
|
||||
|
||||
struct genl_family batadv_netlink_family;
|
||||
|
||||
/* multicast groups */
|
||||
/**
|
||||
* enum batadv_netlink_multicast_groups - batman-adv generic netlink multicast
|
||||
* groups
|
||||
*/
|
||||
enum batadv_netlink_multicast_groups {
|
||||
/** @BATADV_NL_MCGRP_CONFIG: configuration change notifications */
|
||||
BATADV_NL_MCGRP_CONFIG,
|
||||
|
||||
/** @BATADV_NL_MCGRP_TPMETER: throughput meter result notifications */
|
||||
BATADV_NL_MCGRP_TPMETER,
|
||||
};
|
||||
|
||||
@@ -746,8 +752,8 @@ static int
|
||||
batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct batadv_priv *bat_priv = info->user_ptr[0];
|
||||
u8 *dst;
|
||||
int ret = 0;
|
||||
u8 *dst;
|
||||
|
||||
if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS])
|
||||
return -EINVAL;
|
||||
@@ -953,10 +959,10 @@ static int batadv_netlink_set_hardif(struct sk_buff *skb,
|
||||
static int
|
||||
batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
{
|
||||
struct net_device *mesh_iface;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct net_device *mesh_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
int skip = cb->args[0];
|
||||
struct list_head *iter;
|
||||
int i = 0;
|
||||
@@ -1550,14 +1556,18 @@ struct genl_family batadv_netlink_family __ro_after_init = {
|
||||
|
||||
/**
|
||||
* batadv_netlink_register() - register batadv genl netlink family
|
||||
*
|
||||
* Return: 0 on success or negative error number in case of failure
|
||||
*/
|
||||
void __init batadv_netlink_register(void)
|
||||
int __init batadv_netlink_register(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = genl_register_family(&batadv_netlink_family);
|
||||
if (ret)
|
||||
pr_warn("unable to register netlink family\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
void batadv_netlink_register(void);
|
||||
int batadv_netlink_register(void);
|
||||
void batadv_netlink_unregister(void);
|
||||
struct net_device *batadv_netlink_get_meshif(struct netlink_callback *cb);
|
||||
struct batadv_hard_iface *
|
||||
|
||||
@@ -53,8 +53,9 @@ struct batadv_orig_node *
|
||||
batadv_orig_hash_find(struct batadv_priv *bat_priv, const void *data)
|
||||
{
|
||||
struct batadv_hashtable *hash = bat_priv->orig_hash;
|
||||
struct batadv_orig_node *orig_node_tmp = NULL;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct hlist_head *head;
|
||||
struct batadv_orig_node *orig_node, *orig_node_tmp = NULL;
|
||||
int index;
|
||||
|
||||
if (!hash)
|
||||
@@ -108,7 +109,8 @@ struct batadv_orig_node_vlan *
|
||||
batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_orig_node_vlan *vlan = NULL, *tmp;
|
||||
struct batadv_orig_node_vlan *vlan = NULL;
|
||||
struct batadv_orig_node_vlan *tmp;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) {
|
||||
@@ -282,9 +284,9 @@ void batadv_hardif_neigh_release(struct kref *ref)
|
||||
*/
|
||||
void batadv_neigh_node_release(struct kref *ref)
|
||||
{
|
||||
struct hlist_node *node_tmp;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
struct hlist_node *node_tmp;
|
||||
|
||||
neigh_node = container_of(ref, struct batadv_neigh_node, refcount);
|
||||
|
||||
@@ -314,8 +316,8 @@ struct batadv_neigh_node *
|
||||
batadv_orig_router_get(struct batadv_orig_node *orig_node,
|
||||
const struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
struct batadv_neigh_node *router = NULL;
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(orig_ifinfo, &orig_node->ifinfo_list, list) {
|
||||
@@ -373,7 +375,8 @@ struct batadv_orig_ifinfo *
|
||||
batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_orig_ifinfo *tmp, *orig_ifinfo = NULL;
|
||||
struct batadv_orig_ifinfo *orig_ifinfo = NULL;
|
||||
struct batadv_orig_ifinfo *tmp;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(tmp, &orig_node->ifinfo_list,
|
||||
@@ -451,8 +454,8 @@ struct batadv_neigh_ifinfo *
|
||||
batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL,
|
||||
*tmp_neigh_ifinfo;
|
||||
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
|
||||
struct batadv_neigh_ifinfo *tmp_neigh_ifinfo;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(tmp_neigh_ifinfo, &neigh->ifinfo_list,
|
||||
@@ -530,7 +533,8 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
|
||||
const struct batadv_hard_iface *hard_iface,
|
||||
const u8 *addr)
|
||||
{
|
||||
struct batadv_neigh_node *tmp_neigh_node, *res = NULL;
|
||||
struct batadv_neigh_node *tmp_neigh_node;
|
||||
struct batadv_neigh_node *res = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) {
|
||||
@@ -634,7 +638,8 @@ struct batadv_hardif_neigh_node *
|
||||
batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface,
|
||||
const u8 *neigh_addr)
|
||||
{
|
||||
struct batadv_hardif_neigh_node *tmp_hardif_neigh, *hardif_neigh = NULL;
|
||||
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
|
||||
struct batadv_hardif_neigh_node *tmp_hardif_neigh;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(tmp_hardif_neigh,
|
||||
@@ -668,8 +673,8 @@ batadv_neigh_node_create(struct batadv_orig_node *orig_node,
|
||||
struct batadv_hard_iface *hard_iface,
|
||||
const u8 *neigh_addr)
|
||||
{
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
|
||||
spin_lock_bh(&orig_node->neigh_list_lock);
|
||||
|
||||
@@ -753,7 +758,8 @@ batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node,
|
||||
*/
|
||||
int batadv_hardif_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
{
|
||||
struct batadv_hard_iface *primary_if, *hard_iface;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct net_device *mesh_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
int ret;
|
||||
@@ -850,12 +856,12 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
|
||||
*/
|
||||
void batadv_orig_node_release(struct kref *ref)
|
||||
{
|
||||
struct hlist_node *node_tmp;
|
||||
struct batadv_orig_ifinfo *last_candidate;
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct batadv_orig_ifinfo *orig_ifinfo;
|
||||
struct batadv_orig_node_vlan *vlan;
|
||||
struct batadv_orig_ifinfo *last_candidate;
|
||||
struct hlist_node *node_tmp;
|
||||
|
||||
orig_node = container_of(ref, struct batadv_orig_node, refcount);
|
||||
|
||||
@@ -898,11 +904,11 @@ void batadv_orig_node_release(struct kref *ref)
|
||||
*/
|
||||
void batadv_originator_free(struct batadv_priv *bat_priv)
|
||||
{
|
||||
spinlock_t *list_lock; /* spinlock to protect write access */
|
||||
struct batadv_hashtable *hash = bat_priv->orig_hash;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
spinlock_t *list_lock; /* spinlock to protect write access */
|
||||
struct batadv_orig_node *orig_node;
|
||||
u32 i;
|
||||
|
||||
if (!hash)
|
||||
@@ -1109,11 +1115,11 @@ static bool
|
||||
batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node)
|
||||
{
|
||||
struct hlist_node *node_tmp;
|
||||
struct batadv_hard_iface *if_incoming;
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
struct hlist_node *node_tmp;
|
||||
bool neigh_purged = false;
|
||||
unsigned long last_seen;
|
||||
struct batadv_hard_iface *if_incoming;
|
||||
|
||||
spin_lock_bh(&orig_node->neigh_list_lock);
|
||||
|
||||
@@ -1167,8 +1173,9 @@ batadv_find_best_neighbor(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
struct batadv_hard_iface *if_outgoing)
|
||||
{
|
||||
struct batadv_neigh_node *best = NULL, *neigh;
|
||||
struct batadv_algo_ops *bao = bat_priv->algo_ops;
|
||||
struct batadv_neigh_node *best = NULL;
|
||||
struct batadv_neigh_node *neigh;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(neigh, &orig_node->neigh_list, list) {
|
||||
@@ -1203,8 +1210,9 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
|
||||
{
|
||||
struct batadv_neigh_node *best_neigh_node;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
bool changed_ifinfo, changed_neigh;
|
||||
struct list_head *iter;
|
||||
bool changed_ifinfo;
|
||||
bool changed_neigh;
|
||||
|
||||
if (batadv_has_timed_out(orig_node->last_seen,
|
||||
2 * BATADV_PURGE_TIMEOUT)) {
|
||||
@@ -1256,11 +1264,11 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
|
||||
*/
|
||||
void batadv_purge_orig_ref(struct batadv_priv *bat_priv)
|
||||
{
|
||||
spinlock_t *list_lock; /* spinlock to protect write access */
|
||||
struct batadv_hashtable *hash = bat_priv->orig_hash;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
spinlock_t *list_lock; /* spinlock to protect write access */
|
||||
struct batadv_orig_node *orig_node;
|
||||
u32 i;
|
||||
|
||||
if (!hash)
|
||||
@@ -1295,6 +1303,13 @@ void batadv_purge_orig_ref(struct batadv_priv *bat_priv)
|
||||
batadv_gw_election(bat_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_purge_orig() - periodic worker to purge stale originator entries
|
||||
* @work: delayed work embedded in the bat_priv
|
||||
*
|
||||
* Invoke batadv_purge_orig_ref() to drop stale originators and reschedule the
|
||||
* next run after BATADV_ORIG_WORK_PERIOD milliseconds.
|
||||
*/
|
||||
static void batadv_purge_orig(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work;
|
||||
@@ -1318,7 +1333,8 @@ static void batadv_purge_orig(struct work_struct *work)
|
||||
*/
|
||||
int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
{
|
||||
struct batadv_hard_iface *primary_if, *hard_iface;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct net_device *mesh_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
int ret;
|
||||
|
||||
@@ -172,6 +172,11 @@ bool batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
|
||||
* @hard_iface: incoming hard interface
|
||||
* @header_len: minimal header length of packet type
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* skb_cow()/skb_linearize()/... Any pointer into the skb data (e.g.
|
||||
* obtained from skb->data or eth_hdr()) before this call must be
|
||||
* considered invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true when management preconditions are met, false otherwise
|
||||
*/
|
||||
bool batadv_check_management_packet(struct sk_buff *skb,
|
||||
@@ -263,8 +268,7 @@ static bool batadv_skb_decrement_ttl(struct sk_buff *skb)
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @skb: icmp packet to process
|
||||
*
|
||||
* Return: NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
|
||||
* otherwise.
|
||||
* Return: NET_RX_SUCCESS on success or NET_RX_DROP in case of failure
|
||||
*/
|
||||
static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb)
|
||||
@@ -272,7 +276,8 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_icmp_header *icmph;
|
||||
int res, ret = NET_RX_DROP;
|
||||
int ret = NET_RX_DROP;
|
||||
int res;
|
||||
|
||||
icmph = (struct batadv_icmp_header *)skb->data;
|
||||
|
||||
@@ -328,13 +333,24 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_recv_icmp_ttl_exceeded() - handle an ICMP packet that hit TTL 0
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @skb: ICMP packet whose TTL has expired
|
||||
*
|
||||
* For traceroute-style ICMP echo requests, send a TTL exceeded reply back to
|
||||
* the source. Other ICMP types are simply dropped.
|
||||
*
|
||||
* Return: NET_RX_SUCCESS if the reply was queued, NET_RX_DROP otherwise
|
||||
*/
|
||||
static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_icmp_packet *icmp_packet;
|
||||
int res, ret = NET_RX_DROP;
|
||||
int ret = NET_RX_DROP;
|
||||
int res;
|
||||
|
||||
icmp_packet = (struct batadv_icmp_packet *)skb->data;
|
||||
|
||||
@@ -366,8 +382,8 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
|
||||
icmp_packet->ttl = BATADV_TTL;
|
||||
|
||||
res = batadv_send_skb_to_orig(skb, orig_node, NULL);
|
||||
if (res == NET_RX_SUCCESS)
|
||||
ret = NET_XMIT_SUCCESS;
|
||||
if (res == NET_XMIT_SUCCESS)
|
||||
ret = NET_RX_SUCCESS;
|
||||
|
||||
/* skb was consumed */
|
||||
skb = NULL;
|
||||
@@ -392,12 +408,13 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(recv_if->mesh_iface);
|
||||
struct batadv_icmp_header *icmph;
|
||||
struct batadv_icmp_packet_rr *icmp_packet_rr;
|
||||
struct ethhdr *ethhdr;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
int hdr_size = sizeof(struct batadv_icmp_header);
|
||||
int res, ret = NET_RX_DROP;
|
||||
struct batadv_icmp_packet_rr *icmp_packet_rr;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_icmp_header *icmph;
|
||||
struct ethhdr *ethhdr;
|
||||
int ret = NET_RX_DROP;
|
||||
int res;
|
||||
|
||||
/* drop packet if it has not necessary minimum size */
|
||||
if (unlikely(!pskb_may_pull(skb, hdr_size)))
|
||||
@@ -576,15 +593,17 @@ batadv_find_router(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
{
|
||||
struct batadv_algo_ops *bao = bat_priv->algo_ops;
|
||||
struct batadv_neigh_node *first_candidate_router = NULL;
|
||||
struct batadv_neigh_node *next_candidate_router = NULL;
|
||||
struct batadv_neigh_node *router, *cand_router = NULL;
|
||||
struct batadv_neigh_node *last_cand_router = NULL;
|
||||
struct batadv_orig_ifinfo *cand, *first_candidate = NULL;
|
||||
struct batadv_orig_ifinfo *first_candidate = NULL;
|
||||
struct batadv_algo_ops *bao = bat_priv->algo_ops;
|
||||
struct batadv_orig_ifinfo *next_candidate = NULL;
|
||||
struct batadv_neigh_node *cand_router = NULL;
|
||||
struct batadv_orig_ifinfo *last_candidate;
|
||||
bool last_candidate_found = false;
|
||||
struct batadv_neigh_node *router;
|
||||
struct batadv_orig_ifinfo *cand;
|
||||
|
||||
if (!orig_node)
|
||||
return NULL;
|
||||
@@ -706,15 +725,29 @@ batadv_find_router(struct batadv_priv *bat_priv,
|
||||
return router;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_route_unicast_packet() - forward a unicast packet towards its
|
||||
* destination originator
|
||||
* @skb: the received unicast packet
|
||||
* @recv_if: interface on which the packet was received
|
||||
*
|
||||
* Decrement the TTL, look up the originator for the destination address and
|
||||
* hand the packet over to batadv_send_skb_to_orig() for transmission. Drop
|
||||
* the packet when the TTL is exhausted or no route exists.
|
||||
*
|
||||
* Return: NET_RX_SUCCESS if the packet was forwarded, NET_RX_DROP otherwise
|
||||
*/
|
||||
static int batadv_route_unicast_packet(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(recv_if->mesh_iface);
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_unicast_packet *unicast_packet;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct ethhdr *ethhdr = eth_hdr(skb);
|
||||
int res, hdr_len, ret = NET_RX_DROP;
|
||||
int ret = NET_RX_DROP;
|
||||
unsigned int len;
|
||||
int hdr_len;
|
||||
int res;
|
||||
|
||||
unicast_packet = (struct batadv_unicast_packet *)skb->data;
|
||||
|
||||
@@ -797,10 +830,10 @@ batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
struct batadv_unicast_packet *unicast_packet,
|
||||
u8 *dst_addr, unsigned short vid)
|
||||
{
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
bool ret = false;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
const u8 *orig_addr;
|
||||
bool ret = false;
|
||||
u8 orig_ttvn;
|
||||
|
||||
if (batadv_is_my_client(bat_priv, dst_addr, vid)) {
|
||||
@@ -836,16 +869,31 @@ batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_check_unicast_ttvn() - check and adjust the TTVN of a unicast packet
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @skb: the unicast packet to check
|
||||
* @hdr_len: length of the unicast header preceding the payload
|
||||
*
|
||||
* Warning: This function may reallocate the skb data buffer via
|
||||
* pskb_may_pull()/batadv_get_vid()/... Any pointer into the skb data (e.g.
|
||||
* obtained from skb->data or eth_hdr()) before this call must be considered
|
||||
* invalid afterwards and has to be reacquired.
|
||||
*
|
||||
* Return: true if the packet may be processed further, false if has to be
|
||||
* dropped by the caller
|
||||
*/
|
||||
static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, int hdr_len)
|
||||
{
|
||||
struct batadv_unicast_packet *unicast_packet;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct batadv_orig_node *orig_node;
|
||||
u8 curr_ttvn, old_ttvn;
|
||||
struct ethhdr *ethhdr;
|
||||
unsigned short vid;
|
||||
int is_old_ttvn;
|
||||
u8 curr_ttvn;
|
||||
u8 old_ttvn;
|
||||
|
||||
/* check if there is enough data before accessing it */
|
||||
if (!pskb_may_pull(skb, hdr_len + ETH_HLEN))
|
||||
@@ -955,15 +1003,15 @@ static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
* @skb: unicast tvlv packet to process
|
||||
* @recv_if: pointer to interface this packet was received on
|
||||
*
|
||||
* Return: NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
|
||||
* otherwise.
|
||||
* Return: NET_RX_SUCCESS on success or NET_RX_DROP in case of failure
|
||||
*/
|
||||
int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
{
|
||||
struct batadv_unicast_packet *unicast_packet;
|
||||
struct batadv_priv *bat_priv = netdev_priv(recv_if->mesh_iface);
|
||||
int check, hdr_size = sizeof(*unicast_packet);
|
||||
struct batadv_unicast_packet *unicast_packet;
|
||||
int hdr_size = sizeof(*unicast_packet);
|
||||
int check;
|
||||
|
||||
check = batadv_check_unicast_packet(bat_priv, skb, hdr_size);
|
||||
if (check < 0)
|
||||
@@ -992,14 +1040,18 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(recv_if->mesh_iface);
|
||||
struct batadv_unicast_packet *unicast_packet;
|
||||
struct batadv_unicast_4addr_packet *unicast_4addr_packet;
|
||||
u8 *orig_addr, *orig_addr_gw;
|
||||
struct batadv_orig_node *orig_node = NULL, *orig_node_gw = NULL;
|
||||
int check, hdr_size = sizeof(*unicast_packet);
|
||||
struct batadv_unicast_packet *unicast_packet;
|
||||
struct batadv_orig_node *orig_node_gw = NULL;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
int hdr_size = sizeof(*unicast_packet);
|
||||
enum batadv_subtype subtype;
|
||||
int ret = NET_RX_DROP;
|
||||
bool is4addr, is_gw;
|
||||
u8 *orig_addr_gw;
|
||||
u8 *orig_addr;
|
||||
bool is4addr;
|
||||
bool is_gw;
|
||||
int check;
|
||||
|
||||
unicast_packet = (struct batadv_unicast_packet *)skb->data;
|
||||
is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR;
|
||||
@@ -1089,18 +1141,17 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
|
||||
* @skb: unicast tvlv packet to process
|
||||
* @recv_if: pointer to interface this packet was received on
|
||||
*
|
||||
* Return: NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
|
||||
* otherwise.
|
||||
* Return: NET_RX_SUCCESS on success or NET_RX_DROP in case of failure
|
||||
*/
|
||||
int batadv_recv_unicast_tvlv(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(recv_if->mesh_iface);
|
||||
struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
|
||||
unsigned char *tvlv_buff;
|
||||
u16 tvlv_buff_len;
|
||||
int hdr_size = sizeof(*unicast_tvlv_packet);
|
||||
unsigned char *tvlv_buff;
|
||||
int ret = NET_RX_DROP;
|
||||
u16 tvlv_buff_len;
|
||||
|
||||
if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
|
||||
goto free_skb;
|
||||
@@ -1146,7 +1197,7 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb,
|
||||
* the assembled packet will exceed our MTU; 2) Buffer fragment, if we still
|
||||
* lack further fragments; 3) Merge fragments, if we have all needed parts.
|
||||
*
|
||||
* Return: NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise.
|
||||
* Return: NET_RX_SUCCESS on success or NET_RX_DROP in case of failure
|
||||
*/
|
||||
int batadv_recv_frag_packet(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
@@ -1215,8 +1266,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
|
||||
struct batadv_priv *bat_priv = netdev_priv(recv_if->mesh_iface);
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_bcast_packet *bcast_packet;
|
||||
struct ethhdr *ethhdr;
|
||||
int hdr_size = sizeof(*bcast_packet);
|
||||
struct ethhdr *ethhdr;
|
||||
s32 seq_diff;
|
||||
u32 seqno;
|
||||
int ret;
|
||||
@@ -1334,7 +1385,9 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
|
||||
* contents of its TVLV forwards it and/or decapsulates it to hand it to the
|
||||
* mesh interface.
|
||||
*
|
||||
* Return: NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise.
|
||||
* Return: NET_RX_SUCCESS if the skb was locally received, NET_RX_DROP otherwise
|
||||
* or a negative errno code when the multicast tracker TVLV could not be
|
||||
* processed
|
||||
*/
|
||||
int batadv_recv_mcast_packet(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
|
||||
@@ -271,8 +271,8 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig,
|
||||
int packet_subtype)
|
||||
{
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct batadv_unicast_4addr_packet *uc_4addr_packet;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
bool ret = false;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
@@ -322,8 +322,9 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_unicast_packet *unicast_packet;
|
||||
struct ethhdr *ethhdr;
|
||||
int ret = NET_XMIT_DROP;
|
||||
struct ethhdr *ethhdr;
|
||||
int res;
|
||||
|
||||
if (!orig_node)
|
||||
goto out;
|
||||
@@ -360,7 +361,10 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
|
||||
if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid))
|
||||
unicast_packet->ttvn = unicast_packet->ttvn - 1;
|
||||
|
||||
ret = batadv_send_skb_to_orig(skb, orig_node, NULL);
|
||||
res = batadv_send_skb_to_orig(skb, orig_node, NULL);
|
||||
if (res == NET_XMIT_SUCCESS)
|
||||
ret = NET_XMIT_SUCCESS;
|
||||
|
||||
/* skb was consumed */
|
||||
skb = NULL;
|
||||
|
||||
@@ -394,7 +398,8 @@ int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv,
|
||||
{
|
||||
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
|
||||
struct batadv_orig_node *orig_node;
|
||||
u8 *src, *dst;
|
||||
u8 *src;
|
||||
u8 *dst;
|
||||
int ret;
|
||||
|
||||
src = ethhdr->h_source;
|
||||
|
||||
@@ -221,9 +221,9 @@ static void batadv_tp_batctl_notify(enum batadv_tp_meter_reason reason,
|
||||
unsigned long start_time, u64 total_sent,
|
||||
u32 cookie)
|
||||
{
|
||||
u32 total_bytes;
|
||||
u32 test_time;
|
||||
u8 result;
|
||||
u32 total_bytes;
|
||||
|
||||
if (!batadv_tp_is_error(reason)) {
|
||||
result = BATADV_TP_REASON_COMPLETE;
|
||||
@@ -267,7 +267,8 @@ static void batadv_tp_batctl_error_notify(enum batadv_tp_meter_reason reason,
|
||||
static struct batadv_tp_sender *
|
||||
batadv_tp_list_find_sender(struct batadv_priv *bat_priv, const u8 *dst)
|
||||
{
|
||||
struct batadv_tp_sender *pos, *tp_vars = NULL;
|
||||
struct batadv_tp_sender *tp_vars = NULL;
|
||||
struct batadv_tp_sender *pos;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(pos, &bat_priv->tp_sender_list, common.list) {
|
||||
@@ -332,7 +333,8 @@ static struct batadv_tp_sender *
|
||||
batadv_tp_list_find_sender_session(struct batadv_priv *bat_priv, const u8 *dst,
|
||||
const u8 *session)
|
||||
{
|
||||
struct batadv_tp_sender *pos, *tp_vars = NULL;
|
||||
struct batadv_tp_sender *tp_vars = NULL;
|
||||
struct batadv_tp_sender *pos;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(pos, &bat_priv->tp_sender_list, common.list) {
|
||||
@@ -578,8 +580,8 @@ static void batadv_tp_sender_timeout(struct timer_list *t)
|
||||
static void batadv_tp_fill_prerandom(struct batadv_tp_sender *tp_vars,
|
||||
u8 *buf, size_t nbytes)
|
||||
{
|
||||
u32 local_offset;
|
||||
size_t bytes_inbuf;
|
||||
u32 local_offset;
|
||||
size_t to_copy;
|
||||
size_t pos = 0;
|
||||
|
||||
@@ -625,9 +627,9 @@ static int batadv_tp_send_msg(struct batadv_tp_sender *tp_vars, const u8 *src,
|
||||
{
|
||||
struct batadv_icmp_tp_packet *icmp;
|
||||
struct sk_buff *skb;
|
||||
int r;
|
||||
u8 *data;
|
||||
size_t data_len;
|
||||
u8 *data;
|
||||
int r;
|
||||
|
||||
skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
|
||||
if (unlikely(!skb))
|
||||
@@ -864,7 +866,8 @@ static void batadv_tp_recv_ack(struct batadv_priv *bat_priv,
|
||||
static bool batadv_tp_avail(struct batadv_tp_sender *tp_vars,
|
||||
size_t payload_len)
|
||||
{
|
||||
u32 win_left, win_limit;
|
||||
u32 win_limit;
|
||||
u32 win_left;
|
||||
|
||||
spin_lock_bh(&tp_vars->cc_lock);
|
||||
|
||||
@@ -910,14 +913,16 @@ static int batadv_tp_wait_available(struct batadv_tp_sender *tp_vars, size_t ple
|
||||
*/
|
||||
static int batadv_tp_send(void *arg)
|
||||
{
|
||||
struct batadv_tp_sender *tp_vars = arg;
|
||||
struct batadv_priv *bat_priv = tp_vars->common.bat_priv;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
size_t payload_len, packet_len;
|
||||
struct batadv_tp_sender *tp_vars = arg;
|
||||
struct batadv_priv *bat_priv;
|
||||
size_t payload_len;
|
||||
size_t packet_len;
|
||||
u32 last_sent;
|
||||
int err = 0;
|
||||
|
||||
bat_priv = tp_vars->common.bat_priv;
|
||||
orig_node = batadv_orig_hash_find(bat_priv, tp_vars->common.other_end);
|
||||
if (unlikely(!orig_node)) {
|
||||
err = BATADV_TP_REASON_DST_UNREACHABLE;
|
||||
@@ -1005,8 +1010,8 @@ static int batadv_tp_send(void *arg)
|
||||
*/
|
||||
static void batadv_tp_start_kthread(struct batadv_tp_sender *tp_vars)
|
||||
{
|
||||
struct task_struct *kthread;
|
||||
struct batadv_priv *bat_priv = tp_vars->common.bat_priv;
|
||||
struct task_struct *kthread;
|
||||
u32 session_cookie;
|
||||
|
||||
kref_get(&tp_vars->common.refcount);
|
||||
@@ -1042,9 +1047,9 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
|
||||
u32 test_length, u32 *cookie)
|
||||
{
|
||||
struct batadv_tp_sender *tp_vars;
|
||||
u32 session_cookie;
|
||||
u8 session_id[2];
|
||||
u8 icmp_uid;
|
||||
u32 session_cookie;
|
||||
|
||||
get_random_bytes(session_id, sizeof(session_id));
|
||||
get_random_bytes(&icmp_uid, 1);
|
||||
@@ -1211,7 +1216,8 @@ static struct batadv_tp_receiver *
|
||||
batadv_tp_list_find_receiver_session(struct batadv_priv *bat_priv, const u8 *dst,
|
||||
const u8 *session)
|
||||
{
|
||||
struct batadv_tp_receiver *pos, *tp_vars = NULL;
|
||||
struct batadv_tp_receiver *tp_vars = NULL;
|
||||
struct batadv_tp_receiver *pos;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(pos, &bat_priv->tp_receiver_list, common.list) {
|
||||
@@ -1296,7 +1302,8 @@ static void batadv_tp_reset_receiver_timer(struct batadv_tp_receiver *tp_vars)
|
||||
static void batadv_tp_receiver_shutdown(struct timer_list *t)
|
||||
{
|
||||
struct batadv_tp_receiver *tp_vars = timer_container_of(tp_vars, t, common.timer);
|
||||
struct batadv_tp_unacked *un, *safe;
|
||||
struct batadv_tp_unacked *safe;
|
||||
struct batadv_tp_unacked *un;
|
||||
struct batadv_priv *bat_priv;
|
||||
|
||||
bat_priv = tp_vars->common.bat_priv;
|
||||
@@ -1351,7 +1358,8 @@ static int batadv_tp_send_ack(struct batadv_priv *bat_priv, const u8 *dst,
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct batadv_icmp_tp_packet *icmp;
|
||||
struct sk_buff *skb;
|
||||
int r, ret;
|
||||
int ret;
|
||||
int r;
|
||||
|
||||
orig_node = batadv_orig_hash_find(bat_priv, dst);
|
||||
if (unlikely(!orig_node)) {
|
||||
@@ -1528,7 +1536,8 @@ static bool batadv_tp_handle_out_of_order(struct batadv_tp_receiver *tp_vars,
|
||||
static void batadv_tp_ack_unordered(struct batadv_tp_receiver *tp_vars)
|
||||
__must_hold(&tp_vars->ack_seqno_lock)
|
||||
{
|
||||
struct batadv_tp_unacked *un, *safe;
|
||||
struct batadv_tp_unacked *safe;
|
||||
struct batadv_tp_unacked *un;
|
||||
u32 to_ack;
|
||||
|
||||
/* go through the unacked packet list and possibly ACK them as
|
||||
|
||||
@@ -128,8 +128,10 @@ static struct batadv_tt_common_entry *
|
||||
batadv_tt_hash_find(struct batadv_hashtable *hash, const u8 *addr,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_tt_common_entry *tt_tmp = NULL;
|
||||
struct batadv_tt_common_entry to_search;
|
||||
struct batadv_tt_common_entry *tt;
|
||||
struct hlist_head *head;
|
||||
struct batadv_tt_common_entry to_search, *tt, *tt_tmp = NULL;
|
||||
u32 index;
|
||||
|
||||
if (!hash)
|
||||
@@ -173,8 +175,8 @@ static struct batadv_tt_local_entry *
|
||||
batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
struct batadv_tt_local_entry *tt_local_entry = NULL;
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
|
||||
tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, addr,
|
||||
vid);
|
||||
@@ -198,8 +200,8 @@ struct batadv_tt_global_entry *
|
||||
batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
struct batadv_tt_global_entry *tt_global_entry = NULL;
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
|
||||
tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, addr,
|
||||
vid);
|
||||
@@ -421,10 +423,13 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
|
||||
struct batadv_tt_local_entry *tt_local_entry,
|
||||
u8 event_flags)
|
||||
{
|
||||
struct batadv_tt_change_node *tt_change_node, *entry, *safe;
|
||||
struct batadv_tt_common_entry *common = &tt_local_entry->common;
|
||||
struct batadv_tt_change_node *tt_change_node;
|
||||
u8 flags = common->flags | event_flags;
|
||||
bool del_op_requested, del_op_entry;
|
||||
struct batadv_tt_change_node *entry;
|
||||
struct batadv_tt_change_node *safe;
|
||||
bool del_op_requested;
|
||||
bool del_op_entry;
|
||||
size_t changes;
|
||||
|
||||
tt_change_node = kmem_cache_alloc(batadv_tt_change_cache, GFP_ATOMIC);
|
||||
@@ -514,9 +519,9 @@ static u16 batadv_tt_entries(u16 tt_len)
|
||||
*/
|
||||
static int batadv_tt_local_table_transmit_size(struct batadv_priv *bat_priv)
|
||||
{
|
||||
u16 num_vlan = 0;
|
||||
u16 tt_local_entries = 0;
|
||||
struct batadv_meshif_vlan *vlan;
|
||||
u16 tt_local_entries = 0;
|
||||
u16 num_vlan = 0;
|
||||
int hdr_size;
|
||||
|
||||
rcu_read_lock();
|
||||
@@ -535,6 +540,12 @@ static int batadv_tt_local_table_transmit_size(struct batadv_priv *bat_priv)
|
||||
return hdr_size + batadv_tt_len(tt_local_entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_local_init() - allocate and initialise the local translation table
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* Return: 0 on success or -ENOMEM in case of allocation failure
|
||||
*/
|
||||
static int batadv_tt_local_init(struct batadv_priv *bat_priv)
|
||||
{
|
||||
if (bat_priv->tt.local_hash)
|
||||
@@ -551,6 +562,15 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_global_free() - drop a global translation table entry
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @tt_global: the global TT entry to remove
|
||||
* @message: debug message explaining why the entry is being removed
|
||||
*
|
||||
* Remove @tt_global from the global TT hash and drop the reference held by
|
||||
* the hash.
|
||||
*/
|
||||
static void batadv_tt_global_free(struct batadv_priv *bat_priv,
|
||||
struct batadv_tt_global_entry *tt_global,
|
||||
const char *message)
|
||||
@@ -594,18 +614,20 @@ bool batadv_tt_local_add(struct net_device *mesh_iface, const u8 *addr,
|
||||
unsigned short vid, int ifindex, u32 mark)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
|
||||
struct batadv_tt_local_entry *tt_local;
|
||||
struct batadv_tt_global_entry *tt_global = NULL;
|
||||
struct net *net = dev_net(mesh_iface);
|
||||
struct batadv_meshif_vlan *vlan;
|
||||
struct net_device *in_dev = NULL;
|
||||
struct hlist_head *head;
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
int hash_added, table_size, packet_size_max;
|
||||
bool ret = false;
|
||||
struct batadv_tt_local_entry *tt_local;
|
||||
struct net *net = dev_net(mesh_iface);
|
||||
struct net_device *in_dev = NULL;
|
||||
struct batadv_meshif_vlan *vlan;
|
||||
bool roamed_back = false;
|
||||
bool iif_is_wifi = false;
|
||||
struct hlist_head *head;
|
||||
int packet_size_max;
|
||||
bool ret = false;
|
||||
u8 remote_flags;
|
||||
int hash_added;
|
||||
int table_size;
|
||||
u32 match_mark;
|
||||
|
||||
if (ifindex != BATADV_NULL_IFINDEX)
|
||||
@@ -987,14 +1009,16 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
|
||||
*/
|
||||
static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_tt_change_node *entry, *safe;
|
||||
struct batadv_tvlv_tt_data *tt_data;
|
||||
struct batadv_tvlv_tt_change *tt_change;
|
||||
int tt_diff_len, tt_change_len = 0;
|
||||
int tt_diff_entries_num = 0;
|
||||
struct batadv_tt_change_node *entry;
|
||||
struct batadv_tvlv_tt_data *tt_data;
|
||||
struct batadv_tt_change_node *safe;
|
||||
int tt_diff_entries_count = 0;
|
||||
int tt_diff_entries_num = 0;
|
||||
bool drop_changes = false;
|
||||
size_t tt_extra_len = 0;
|
||||
int tt_change_len = 0;
|
||||
int tt_diff_len;
|
||||
u16 tvlv_len;
|
||||
|
||||
tt_diff_entries_num = READ_ONCE(bat_priv->tt.local_changes);
|
||||
@@ -1087,10 +1111,10 @@ batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid,
|
||||
struct batadv_priv *bat_priv,
|
||||
struct batadv_tt_common_entry *common)
|
||||
{
|
||||
void *hdr;
|
||||
struct batadv_meshif_vlan *vlan;
|
||||
struct batadv_tt_local_entry *local;
|
||||
struct batadv_meshif_vlan *vlan;
|
||||
unsigned int last_seen_msecs;
|
||||
void *hdr;
|
||||
u32 crc;
|
||||
|
||||
local = container_of(common, struct batadv_tt_local_entry, common);
|
||||
@@ -1181,14 +1205,14 @@ batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid,
|
||||
*/
|
||||
int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
{
|
||||
struct net_device *mesh_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
struct net_device *mesh_iface;
|
||||
struct batadv_hashtable *hash;
|
||||
int ret;
|
||||
struct batadv_priv *bat_priv;
|
||||
int bucket = cb->args[0];
|
||||
int idx = cb->args[1];
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
int ret;
|
||||
|
||||
mesh_iface = batadv_netlink_get_meshif(cb);
|
||||
if (IS_ERR(mesh_iface))
|
||||
@@ -1224,6 +1248,17 @@ int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_local_set_pending() - mark a local TT entry as pending removal
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @tt_local_entry: local TT entry to mark
|
||||
* @flags: TT change flags to announce together with the pending removal
|
||||
* @message: debug message describing the reason for the change
|
||||
*
|
||||
* Schedule the TT change announcement and set BATADV_TT_CLIENT_PENDING on the
|
||||
* entry. The entry is kept in the local table until the next TTVN increment
|
||||
* so that a consistency-check response can still be answered.
|
||||
*/
|
||||
static void
|
||||
batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
|
||||
struct batadv_tt_local_entry *tt_local_entry,
|
||||
@@ -1259,8 +1294,9 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
|
||||
{
|
||||
struct batadv_tt_local_entry *tt_removed_entry;
|
||||
struct batadv_tt_local_entry *tt_local_entry;
|
||||
u16 flags, curr_flags = BATADV_NO_FLAGS;
|
||||
struct hlist_node *tt_removed_node;
|
||||
u16 curr_flags = BATADV_NO_FLAGS;
|
||||
u16 flags;
|
||||
|
||||
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
|
||||
if (!tt_local_entry)
|
||||
@@ -1319,8 +1355,8 @@ static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
|
||||
struct hlist_head *head,
|
||||
int timeout)
|
||||
{
|
||||
struct batadv_tt_local_entry *tt_local_entry;
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
struct batadv_tt_local_entry *tt_local_entry;
|
||||
struct hlist_node *node_tmp;
|
||||
|
||||
hlist_for_each_entry_safe(tt_common_entry, node_tmp, head,
|
||||
@@ -1352,9 +1388,9 @@ static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
|
||||
static void batadv_tt_local_purge(struct batadv_priv *bat_priv,
|
||||
int timeout)
|
||||
{
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
struct batadv_hashtable *hash = bat_priv->tt.local_hash;
|
||||
struct hlist_head *head;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < hash->size; i++) {
|
||||
@@ -1367,12 +1403,19 @@ static void batadv_tt_local_purge(struct batadv_priv *bat_priv,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_local_table_free() - release the local translation table
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* Drop every entry of the local TT hash, free their references and finally
|
||||
* release the hashtable itself.
|
||||
*/
|
||||
static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_hashtable *hash;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
struct batadv_tt_local_entry *tt_local;
|
||||
struct batadv_hashtable *hash;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
u32 i;
|
||||
@@ -1404,6 +1447,13 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
|
||||
bat_priv->tt.local_hash = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_global_init() - allocate and initialise the global translation
|
||||
* table
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* Return: 0 on success or -ENOMEM in case of allocation failure
|
||||
*/
|
||||
static int batadv_tt_global_init(struct batadv_priv *bat_priv)
|
||||
{
|
||||
if (bat_priv->tt.global_hash)
|
||||
@@ -1420,9 +1470,16 @@ static int batadv_tt_global_init(struct batadv_priv *bat_priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_changes_list_free() - drop all pending local TT changes
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* Discard every queued local TT change and reset the pending change counter.
|
||||
*/
|
||||
static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_tt_change_node *entry, *safe;
|
||||
struct batadv_tt_change_node *entry;
|
||||
struct batadv_tt_change_node *safe;
|
||||
|
||||
spin_lock_bh(&bat_priv->tt.changes_list_lock);
|
||||
|
||||
@@ -1451,7 +1508,8 @@ static struct batadv_tt_orig_list_entry *
|
||||
batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
|
||||
const struct batadv_orig_node *orig_node)
|
||||
{
|
||||
struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
|
||||
struct batadv_tt_orig_list_entry *orig_entry = NULL;
|
||||
struct batadv_tt_orig_list_entry *tmp_orig_entry;
|
||||
const struct hlist_head *head;
|
||||
|
||||
rcu_read_lock();
|
||||
@@ -1604,10 +1662,10 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
|
||||
{
|
||||
struct batadv_tt_global_entry *tt_global_entry;
|
||||
struct batadv_tt_local_entry *tt_local_entry;
|
||||
bool ret = false;
|
||||
int hash_added;
|
||||
struct batadv_tt_common_entry *common;
|
||||
bool ret = false;
|
||||
u16 local_flags;
|
||||
int hash_added;
|
||||
|
||||
/* ignore global entries from backbone nodes */
|
||||
if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid))
|
||||
@@ -1763,10 +1821,12 @@ static struct batadv_tt_orig_list_entry *
|
||||
batadv_transtable_best_orig(struct batadv_priv *bat_priv,
|
||||
struct batadv_tt_global_entry *tt_global_entry)
|
||||
{
|
||||
struct batadv_neigh_node *router, *best_router = NULL;
|
||||
struct batadv_tt_orig_list_entry *best_entry = NULL;
|
||||
struct batadv_algo_ops *bao = bat_priv->algo_ops;
|
||||
struct batadv_neigh_node *best_router = NULL;
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
struct batadv_neigh_node *router;
|
||||
struct hlist_head *head;
|
||||
struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
|
||||
|
||||
head = &tt_global_entry->orig_list;
|
||||
hlist_for_each_entry_rcu(orig_entry, head, list) {
|
||||
@@ -1812,9 +1872,9 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
bool best)
|
||||
{
|
||||
u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags;
|
||||
void *hdr;
|
||||
struct batadv_orig_node_vlan *vlan;
|
||||
u8 last_ttvn;
|
||||
void *hdr;
|
||||
u32 crc;
|
||||
|
||||
vlan = batadv_orig_node_vlan_get(orig->orig_node,
|
||||
@@ -1873,7 +1933,8 @@ batadv_tt_global_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
struct batadv_priv *bat_priv,
|
||||
struct batadv_tt_common_entry *common, int *sub_s)
|
||||
{
|
||||
struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
struct batadv_tt_orig_list_entry *best_entry;
|
||||
struct batadv_tt_global_entry *global;
|
||||
struct hlist_head *head;
|
||||
int sub = 0;
|
||||
@@ -1948,16 +2009,16 @@ batadv_tt_global_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
*/
|
||||
int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
{
|
||||
struct net_device *mesh_iface;
|
||||
struct batadv_priv *bat_priv;
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
struct net_device *mesh_iface;
|
||||
struct batadv_hashtable *hash;
|
||||
struct hlist_head *head;
|
||||
int ret;
|
||||
struct batadv_priv *bat_priv;
|
||||
int bucket = cb->args[0];
|
||||
struct hlist_head *head;
|
||||
int idx = cb->args[1];
|
||||
int sub = cb->args[2];
|
||||
int portid = NETLINK_CB(cb->skb).portid;
|
||||
int ret;
|
||||
|
||||
mesh_iface = batadv_netlink_get_meshif(cb);
|
||||
if (IS_ERR(mesh_iface))
|
||||
@@ -2024,13 +2085,17 @@ _batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
|
||||
batadv_tt_orig_list_entry_put(orig_entry);
|
||||
}
|
||||
|
||||
/* deletes the orig list of a tt_global_entry */
|
||||
/**
|
||||
* batadv_tt_global_del_orig_list() - drop every orig_list_entry of a global
|
||||
* TT entry
|
||||
* @tt_global_entry: the global TT entry to clear
|
||||
*/
|
||||
static void
|
||||
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
|
||||
{
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
struct hlist_head *head;
|
||||
struct hlist_node *safe;
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
|
||||
spin_lock_bh(&tt_global_entry->list_lock);
|
||||
head = &tt_global_entry->orig_list;
|
||||
@@ -2055,9 +2120,9 @@ batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
const char *message)
|
||||
{
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
struct hlist_head *head;
|
||||
struct hlist_node *safe;
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
unsigned short vid;
|
||||
|
||||
spin_lock_bh(&tt_global_entry->list_lock);
|
||||
@@ -2077,9 +2142,17 @@ batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv,
|
||||
spin_unlock_bh(&tt_global_entry->list_lock);
|
||||
}
|
||||
|
||||
/* If the client is to be deleted, we check if it is the last origantor entry
|
||||
* within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
|
||||
* timer, otherwise we simply remove the originator scheduled for deletion.
|
||||
/**
|
||||
* batadv_tt_global_del_roaming() - remove a roaming client from a global TT
|
||||
* entry
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @tt_global_entry: the global TT entry of the roaming client
|
||||
* @orig_node: the originator that the client has roamed away from
|
||||
* @message: debug message describing the reason for the change
|
||||
*
|
||||
* If @orig_node was the last announced source for the client, mark the entry
|
||||
* for roaming so it can be cleaned up after the roaming timer expires.
|
||||
* Otherwise simply remove the orig_node entry from the announcer list.
|
||||
*/
|
||||
static void
|
||||
batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
|
||||
@@ -2087,9 +2160,9 @@ batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
const char *message)
|
||||
{
|
||||
bool last_entry = true;
|
||||
struct hlist_head *head;
|
||||
struct batadv_tt_orig_list_entry *orig_entry;
|
||||
struct hlist_head *head;
|
||||
bool last_entry = true;
|
||||
|
||||
/* no local entry exists, case 1:
|
||||
* Check if this is the last one or if other entries exist.
|
||||
@@ -2133,8 +2206,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
|
||||
const unsigned char *addr, unsigned short vid,
|
||||
const char *message, bool roaming)
|
||||
{
|
||||
struct batadv_tt_global_entry *tt_global_entry;
|
||||
struct batadv_tt_local_entry *local_entry = NULL;
|
||||
struct batadv_tt_global_entry *tt_global_entry;
|
||||
|
||||
tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
|
||||
if (!tt_global_entry)
|
||||
@@ -2196,14 +2269,14 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
|
||||
s32 match_vid,
|
||||
const char *message)
|
||||
{
|
||||
struct batadv_tt_global_entry *tt_global;
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
u32 i;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
struct batadv_hashtable *hash = bat_priv->tt.global_hash;
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
struct batadv_tt_global_entry *tt_global;
|
||||
struct hlist_node *safe;
|
||||
struct hlist_head *head;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
unsigned short vid;
|
||||
u32 i;
|
||||
|
||||
if (!hash)
|
||||
return;
|
||||
@@ -2241,12 +2314,21 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
|
||||
clear_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_global_to_purge() - check whether a global TT entry has to be
|
||||
* purged
|
||||
* @tt_global: global TT entry under consideration
|
||||
* @msg: storage for a pointer to a human readable reason on return
|
||||
*
|
||||
* Return: true if the entry should be purged because its roaming or temporary
|
||||
* timer has elapsed; false otherwise
|
||||
*/
|
||||
static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
|
||||
char **msg)
|
||||
{
|
||||
bool purge = false;
|
||||
unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
|
||||
unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
|
||||
bool purge = false;
|
||||
|
||||
if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
|
||||
batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
|
||||
@@ -2263,16 +2345,23 @@ static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
|
||||
return purge;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_global_purge() - purge expired global translation table entries
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* Iterate over the global translation table and drop every entry that the
|
||||
* roaming or temporary timer has expired for.
|
||||
*/
|
||||
static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_hashtable *hash = bat_priv->tt.global_hash;
|
||||
struct hlist_head *head;
|
||||
struct hlist_node *node_tmp;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
u32 i;
|
||||
char *msg = NULL;
|
||||
struct batadv_hashtable *hash = bat_priv->tt.global_hash;
|
||||
struct batadv_tt_common_entry *tt_common;
|
||||
struct batadv_tt_global_entry *tt_global;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
char *msg = NULL;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < hash->size; i++) {
|
||||
head = &hash->table[i];
|
||||
@@ -2302,12 +2391,19 @@ static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_global_table_free() - release the global translation table
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* Drop every entry of the global TT hash, free their references and finally
|
||||
* release the hashtable itself.
|
||||
*/
|
||||
static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_hashtable *hash;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
struct batadv_tt_global_entry *tt_global;
|
||||
struct batadv_hashtable *hash;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
u32 i;
|
||||
@@ -2338,6 +2434,16 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
|
||||
bat_priv->tt.global_hash = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* _batadv_is_ap_isolated() - check whether two clients are AP-isolated from
|
||||
* each other
|
||||
* @tt_local_entry: local TT entry of the sending client
|
||||
* @tt_global_entry: global TT entry of the destination client
|
||||
*
|
||||
* Return: true if traffic between the two clients should be dropped because
|
||||
* either both are WiFi clients or both carry the ISOLATION flag; false
|
||||
* otherwise
|
||||
*/
|
||||
static bool
|
||||
_batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
|
||||
struct batadv_tt_global_entry *tt_global_entry)
|
||||
@@ -2373,10 +2479,10 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
|
||||
const u8 *addr,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_tt_local_entry *tt_local_entry = NULL;
|
||||
struct batadv_tt_global_entry *tt_global_entry = NULL;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_tt_local_entry *tt_local_entry = NULL;
|
||||
struct batadv_tt_orig_list_entry *best_entry;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
|
||||
if (src && batadv_vlan_ap_isola_get(bat_priv, vid)) {
|
||||
tt_local_entry = batadv_tt_local_hash_find(bat_priv, src, vid);
|
||||
@@ -2445,9 +2551,11 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv,
|
||||
struct batadv_tt_common_entry *tt_common;
|
||||
struct batadv_tt_global_entry *tt_global;
|
||||
struct hlist_head *head;
|
||||
u32 i, crc_tmp, crc = 0;
|
||||
u8 flags;
|
||||
__be16 tmp_vid;
|
||||
u32 crc_tmp;
|
||||
u32 crc = 0;
|
||||
u8 flags;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < hash->size; i++) {
|
||||
head = &hash->table[i];
|
||||
@@ -2523,9 +2631,11 @@ static u32 batadv_tt_local_crc(struct batadv_priv *bat_priv,
|
||||
struct batadv_hashtable *hash = bat_priv->tt.local_hash;
|
||||
struct batadv_tt_common_entry *tt_common;
|
||||
struct hlist_head *head;
|
||||
u32 i, crc_tmp, crc = 0;
|
||||
u8 flags;
|
||||
__be16 tmp_vid;
|
||||
u32 crc_tmp;
|
||||
u32 crc = 0;
|
||||
u8 flags;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < hash->size; i++) {
|
||||
head = &hash->table[i];
|
||||
@@ -2590,6 +2700,10 @@ static void batadv_tt_req_node_put(struct batadv_tt_req_node *tt_req_node)
|
||||
kref_put(&tt_req_node->refcount, batadv_tt_req_node_release);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_req_list_free() - drop all pending TT requests
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*/
|
||||
static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_tt_req_node *node;
|
||||
@@ -2605,6 +2719,18 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
|
||||
spin_unlock_bh(&bat_priv->tt.req_list_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_save_orig_buffer() - cache the latest TT TVLV payload of an
|
||||
* originator
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @orig_node: originator for which the buffer should be created
|
||||
* @tt_buff: pointer to the TT TVLV payload to cache
|
||||
* @tt_buff_len: length of @tt_buff in bytes
|
||||
*
|
||||
* Replace the previously cached TT payload of @orig_node with a copy of
|
||||
* @tt_buff. The buffer is left untouched when @tt_buff_len is 0 so that
|
||||
* empty OGM updates do not discard the previously cached data.
|
||||
*/
|
||||
static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
const void *tt_buff,
|
||||
@@ -2626,6 +2752,10 @@ static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
|
||||
spin_unlock_bh(&orig_node->tt_buff_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_req_purge() - drop timed-out TT requests
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*/
|
||||
static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_tt_req_node *node;
|
||||
@@ -2654,7 +2784,8 @@ static struct batadv_tt_req_node *
|
||||
batadv_tt_req_node_new(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node)
|
||||
{
|
||||
struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
|
||||
struct batadv_tt_req_node *tt_req_node = NULL;
|
||||
struct batadv_tt_req_node *tt_req_node_tmp;
|
||||
|
||||
spin_lock_bh(&bat_priv->tt.req_list_lock);
|
||||
hlist_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
|
||||
@@ -2763,7 +2894,8 @@ static u16 batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
|
||||
struct batadv_tt_common_entry *tt_common_entry;
|
||||
struct batadv_tvlv_tt_change *tt_change;
|
||||
struct hlist_head *head;
|
||||
u16 tt_tot, tt_num_entries = 0;
|
||||
u16 tt_num_entries = 0;
|
||||
u16 tt_tot;
|
||||
u8 flags;
|
||||
bool ret;
|
||||
u32 i;
|
||||
@@ -2817,8 +2949,9 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
|
||||
{
|
||||
struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
|
||||
struct batadv_orig_node_vlan *vlan;
|
||||
int i, orig_num_vlan;
|
||||
int orig_num_vlan;
|
||||
u32 crc;
|
||||
int i;
|
||||
|
||||
/* check if each received CRC matches the locally stored one */
|
||||
for (i = 0; i < num_vlan; i++) {
|
||||
@@ -2924,7 +3057,8 @@ static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
|
||||
struct batadv_tt_req_node *tt_req_node = NULL;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
bool ret = false;
|
||||
int i, size;
|
||||
int size;
|
||||
int i;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if)
|
||||
@@ -3000,13 +3134,15 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
|
||||
struct batadv_tvlv_tt_data *tt_data,
|
||||
u8 *req_src, u8 *req_dst)
|
||||
{
|
||||
struct batadv_orig_node *req_dst_orig_node;
|
||||
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;
|
||||
bool ret = false, full_table;
|
||||
u8 orig_ttvn, req_ttvn;
|
||||
struct batadv_orig_node *req_dst_orig_node;
|
||||
struct batadv_tvlv_tt_change *tt_change;
|
||||
bool ret = false;
|
||||
bool full_table;
|
||||
u8 orig_ttvn;
|
||||
u16 tvlv_len;
|
||||
u8 req_ttvn;
|
||||
s32 tt_len;
|
||||
|
||||
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
||||
@@ -3133,9 +3269,10 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
|
||||
struct batadv_hard_iface *primary_if = NULL;
|
||||
struct batadv_tvlv_tt_change *tt_change;
|
||||
struct batadv_orig_node *orig_node;
|
||||
u8 my_ttvn, req_ttvn;
|
||||
u16 tvlv_len;
|
||||
bool full_table;
|
||||
u16 tvlv_len;
|
||||
u8 req_ttvn;
|
||||
u8 my_ttvn;
|
||||
s32 tt_len;
|
||||
|
||||
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
||||
@@ -3253,13 +3390,25 @@ static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
|
||||
req_dst);
|
||||
}
|
||||
|
||||
/**
|
||||
* _batadv_tt_update_changes() - apply a list of TT changes to the global TT
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @orig_node: originator announcing the changes
|
||||
* @tt_change: array of TT change entries to apply
|
||||
* @tt_num_changes: number of entries in @tt_change
|
||||
* @ttvn: TTVN of @orig_node corresponding to @tt_change
|
||||
*
|
||||
* Walk @tt_change and add/remove the announced clients in the global TT.
|
||||
* Abort early without marking the @orig_node TT as initialized if adding
|
||||
* an entry fails, so that the next TT request can re-sync the full table.
|
||||
*/
|
||||
static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
struct batadv_tvlv_tt_change *tt_change,
|
||||
u16 tt_num_changes, u8 ttvn)
|
||||
{
|
||||
int i;
|
||||
int roams;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < tt_num_changes; i++) {
|
||||
if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) {
|
||||
@@ -3286,6 +3435,18 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
|
||||
set_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_fill_gtable() - replace the cached TT of an originator with a
|
||||
* full table response
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @tt_change: array of TT change entries describing the full table
|
||||
* @ttvn: TTVN announced together with the full table
|
||||
* @resp_src: MAC address of the responder
|
||||
* @num_entries: number of entries in @tt_change
|
||||
*
|
||||
* Drop the previously known global TT entries of @resp_src and replace them
|
||||
* with the entries from a freshly received full TT response.
|
||||
*/
|
||||
static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
|
||||
struct batadv_tvlv_tt_change *tt_change,
|
||||
u8 ttvn, u8 *resp_src,
|
||||
@@ -3316,6 +3477,15 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
|
||||
batadv_orig_node_put(orig_node);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_update_changes() - apply an incremental TT changeset to the
|
||||
* global TT
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
* @orig_node: originator announcing the changes
|
||||
* @tt_num_changes: number of entries in @tt_change
|
||||
* @ttvn: TTVN of @orig_node corresponding to @tt_change
|
||||
* @tt_change: array of TT change entries to apply
|
||||
*/
|
||||
static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
u16 tt_num_changes, u8 ttvn,
|
||||
@@ -3369,11 +3539,11 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
|
||||
struct batadv_tvlv_tt_data *tt_data,
|
||||
u8 *resp_src, u16 num_entries)
|
||||
{
|
||||
struct batadv_tt_req_node *node;
|
||||
struct hlist_node *safe;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_tvlv_tt_change *tt_change;
|
||||
struct batadv_tt_req_node *node;
|
||||
u8 *tvlv_ptr = (u8 *)tt_data;
|
||||
struct hlist_node *safe;
|
||||
|
||||
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
||||
"Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
|
||||
@@ -3416,9 +3586,14 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
|
||||
batadv_orig_node_put(orig_node);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_roam_list_free() - drop all entries from the roaming clients list
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*/
|
||||
static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_tt_roam_node *node, *safe;
|
||||
struct batadv_tt_roam_node *node;
|
||||
struct batadv_tt_roam_node *safe;
|
||||
|
||||
spin_lock_bh(&bat_priv->tt.roam_list_lock);
|
||||
|
||||
@@ -3430,9 +3605,14 @@ static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
|
||||
spin_unlock_bh(&bat_priv->tt.roam_list_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_roam_purge() - drop timed-out roaming clients
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*/
|
||||
static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
|
||||
{
|
||||
struct batadv_tt_roam_node *node, *safe;
|
||||
struct batadv_tt_roam_node *node;
|
||||
struct batadv_tt_roam_node *safe;
|
||||
|
||||
spin_lock_bh(&bat_priv->tt.roam_list_lock);
|
||||
list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
|
||||
@@ -3522,8 +3702,8 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, u8 *client,
|
||||
unsigned short vid,
|
||||
struct batadv_orig_node *orig_node)
|
||||
{
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct batadv_tvlv_roam_adv tvlv_roam;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if)
|
||||
@@ -3552,6 +3732,14 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, u8 *client,
|
||||
batadv_hardif_put(primary_if);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_tt_purge() - periodic worker to maintain the translation table
|
||||
* @work: delayed work embedded in the per-mesh-interface TT state
|
||||
*
|
||||
* Purge timed-out entries from the local and global TT, drop stale TT
|
||||
* requests and roaming clients, and reschedule the next run after
|
||||
* BATADV_TT_WORK_PERIOD milliseconds.
|
||||
*/
|
||||
static void batadv_tt_purge(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work;
|
||||
@@ -3638,15 +3826,22 @@ static void batadv_tt_local_set_flags(struct batadv_priv *bat_priv, u16 flags,
|
||||
}
|
||||
}
|
||||
|
||||
/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
|
||||
/**
|
||||
* batadv_tt_local_purge_pending_clients() - finalise removal of pending local
|
||||
* clients
|
||||
* @bat_priv: the bat priv with all the mesh interface information
|
||||
*
|
||||
* Iterate over the local TT and physically remove every entry that has been
|
||||
* marked as BATADV_TT_CLIENT_PENDING.
|
||||
*/
|
||||
static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
|
||||
{
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
struct batadv_hashtable *hash = bat_priv->tt.local_hash;
|
||||
struct batadv_tt_common_entry *tt_common;
|
||||
struct batadv_tt_local_entry *tt_local;
|
||||
struct hlist_node *node_tmp;
|
||||
struct hlist_head *head;
|
||||
spinlock_t *list_lock; /* protects write access to the hash lists */
|
||||
u32 i;
|
||||
|
||||
if (!hash)
|
||||
@@ -3736,8 +3931,8 @@ void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
|
||||
bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
|
||||
unsigned short vid)
|
||||
{
|
||||
struct batadv_tt_local_entry *tt_local_entry;
|
||||
struct batadv_tt_global_entry *tt_global_entry;
|
||||
struct batadv_tt_local_entry *tt_local_entry;
|
||||
struct batadv_meshif_vlan *vlan;
|
||||
bool ret = false;
|
||||
|
||||
@@ -3947,9 +4142,12 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
|
||||
void batadv_tt_local_resize_to_mtu(struct net_device *mesh_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
|
||||
int packet_size_max = READ_ONCE(bat_priv->packet_size_max);
|
||||
int table_size, timeout = BATADV_TT_LOCAL_TIMEOUT / 2;
|
||||
int timeout = BATADV_TT_LOCAL_TIMEOUT / 2;
|
||||
bool reduced = false;
|
||||
int packet_size_max;
|
||||
int table_size;
|
||||
|
||||
packet_size_max = READ_ONCE(bat_priv->packet_size_max);
|
||||
|
||||
spin_lock_bh(&bat_priv->tt.commit_lock);
|
||||
|
||||
@@ -3992,8 +4190,9 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
|
||||
{
|
||||
struct batadv_tvlv_tt_change *tt_change;
|
||||
struct batadv_tvlv_tt_data *tt_data;
|
||||
u16 num_entries, num_vlan;
|
||||
size_t tt_data_sz;
|
||||
u16 num_entries;
|
||||
u16 num_vlan;
|
||||
|
||||
if (tvlv_value_len < sizeof(*tt_data))
|
||||
return;
|
||||
@@ -4115,8 +4314,8 @@ static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
|
||||
void *tvlv_value,
|
||||
u16 tvlv_value_len)
|
||||
{
|
||||
struct batadv_tvlv_roam_adv *roaming_adv;
|
||||
struct batadv_orig_node *orig_node = NULL;
|
||||
struct batadv_tvlv_roam_adv *roaming_adv;
|
||||
|
||||
/* If this node is not the intended recipient of the
|
||||
* roaming advertisement the packet is forwarded
|
||||
@@ -4219,12 +4418,12 @@ bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
|
||||
*/
|
||||
int __init batadv_tt_cache_init(void)
|
||||
{
|
||||
size_t tl_size = sizeof(struct batadv_tt_local_entry);
|
||||
size_t tg_size = sizeof(struct batadv_tt_global_entry);
|
||||
size_t tt_orig_size = sizeof(struct batadv_tt_orig_list_entry);
|
||||
size_t tt_change_size = sizeof(struct batadv_tt_change_node);
|
||||
size_t tt_req_size = sizeof(struct batadv_tt_req_node);
|
||||
size_t tt_roam_size = sizeof(struct batadv_tt_roam_node);
|
||||
size_t tg_size = sizeof(struct batadv_tt_global_entry);
|
||||
size_t tt_req_size = sizeof(struct batadv_tt_req_node);
|
||||
size_t tl_size = sizeof(struct batadv_tt_local_entry);
|
||||
|
||||
batadv_tl_cache = kmem_cache_create("batadv_tl_cache", tl_size, 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
|
||||
@@ -72,7 +72,8 @@ static void batadv_tvlv_handler_put(struct batadv_tvlv_handler *tvlv_handler)
|
||||
static struct batadv_tvlv_handler *
|
||||
batadv_tvlv_handler_get(struct batadv_priv *bat_priv, u8 type, u8 version)
|
||||
{
|
||||
struct batadv_tvlv_handler *tvlv_handler_tmp, *tvlv_handler = NULL;
|
||||
struct batadv_tvlv_handler *tvlv_handler = NULL;
|
||||
struct batadv_tvlv_handler *tvlv_handler_tmp;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(tvlv_handler_tmp,
|
||||
@@ -134,7 +135,8 @@ static void batadv_tvlv_container_put(struct batadv_tvlv_container *tvlv)
|
||||
static struct batadv_tvlv_container *
|
||||
batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version)
|
||||
{
|
||||
struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL;
|
||||
struct batadv_tvlv_container *tvlv = NULL;
|
||||
struct batadv_tvlv_container *tvlv_tmp;
|
||||
|
||||
lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
|
||||
|
||||
@@ -236,7 +238,8 @@ void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
|
||||
u8 type, u8 version,
|
||||
void *tvlv_value, u16 tvlv_value_len)
|
||||
{
|
||||
struct batadv_tvlv_container *tvlv_old, *tvlv_new;
|
||||
struct batadv_tvlv_container *tvlv_old;
|
||||
struct batadv_tvlv_container *tvlv_new;
|
||||
|
||||
if (!tvlv_value)
|
||||
tvlv_value_len = 0;
|
||||
@@ -383,8 +386,9 @@ int batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
|
||||
* @tvlv_value: tvlv content
|
||||
* @tvlv_value_len: tvlv content length
|
||||
*
|
||||
* Return: success if the handler was not found or the return value of the
|
||||
* handler callback.
|
||||
* Return: NET_RX_SUCCESS if the handler was not found or the return value of
|
||||
* the handler callback. The latter is NET_RX_SUCCESS or NET_RX_DROP for the
|
||||
* unicast handler and additionally a negative errno code for the mcast handler.
|
||||
*/
|
||||
static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
|
||||
struct batadv_tvlv_handler *tvlv_handler,
|
||||
@@ -394,7 +398,8 @@ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
|
||||
u16 tvlv_value_len)
|
||||
{
|
||||
unsigned int tvlv_offset;
|
||||
u8 *src, *dst;
|
||||
u8 *src;
|
||||
u8 *dst;
|
||||
|
||||
if (!tvlv_handler)
|
||||
return NET_RX_SUCCESS;
|
||||
@@ -524,8 +529,9 @@ static bool batadv_tvlv_containers_contain(void *tvlv_value,
|
||||
* @tvlv_value: tvlv content
|
||||
* @tvlv_value_len: tvlv content length
|
||||
*
|
||||
* Return: success when processing an OGM or the return value of all called
|
||||
* handler callbacks.
|
||||
* Return: NET_RX_SUCCESS when processing an OGM or the combined return value of
|
||||
* all called handler callbacks. The latter is NET_RX_SUCCESS, NET_RX_DROP or,
|
||||
* for BATADV_MCAST packets, a negative errno code.
|
||||
*/
|
||||
int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
|
||||
u8 packet_type,
|
||||
@@ -533,13 +539,14 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb, void *tvlv_value,
|
||||
u16 tvlv_value_len)
|
||||
{
|
||||
u8 cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND;
|
||||
u16 tvlv_value_start_len = tvlv_value_len;
|
||||
struct batadv_tvlv_handler *tvlv_handler;
|
||||
void *tvlv_value_start = tvlv_value;
|
||||
struct batadv_tvlv_hdr *tvlv_hdr;
|
||||
u16 tvlv_value_cont_len;
|
||||
u8 cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND;
|
||||
int ret = NET_RX_SUCCESS;
|
||||
u16 tvlv_value_cont_len;
|
||||
int res;
|
||||
|
||||
while ((tvlv_hdr = batadv_tvlv_hdr_next(&tvlv_value, &tvlv_value_len))) {
|
||||
tvlv_value_cont_len = ntohs(tvlv_hdr->len);
|
||||
@@ -548,10 +555,13 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
|
||||
tvlv_hdr->type,
|
||||
tvlv_hdr->version);
|
||||
|
||||
ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler,
|
||||
packet_type, orig_node, skb,
|
||||
tvlv_hdr + 1,
|
||||
tvlv_value_cont_len);
|
||||
res = batadv_tvlv_call_handler(bat_priv, tvlv_handler,
|
||||
packet_type, orig_node, skb,
|
||||
tvlv_hdr + 1,
|
||||
tvlv_value_cont_len);
|
||||
if (ret == NET_RX_SUCCESS || res < 0)
|
||||
ret = res;
|
||||
|
||||
batadv_tvlv_handler_put(tvlv_handler);
|
||||
}
|
||||
|
||||
@@ -596,8 +606,8 @@ void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
|
||||
struct batadv_ogm_packet *batadv_ogm_packet,
|
||||
struct batadv_orig_node *orig_node)
|
||||
{
|
||||
void *tvlv_value;
|
||||
u16 tvlv_value_len;
|
||||
void *tvlv_value;
|
||||
|
||||
if (!batadv_ogm_packet)
|
||||
return;
|
||||
@@ -717,12 +727,12 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, const u8 *src,
|
||||
void *tvlv_value, u16 tvlv_value_len)
|
||||
{
|
||||
struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
|
||||
struct batadv_tvlv_hdr *tvlv_hdr;
|
||||
ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct sk_buff *skb;
|
||||
struct batadv_tvlv_hdr *tvlv_hdr;
|
||||
unsigned char *tvlv_buff;
|
||||
unsigned int tvlv_len;
|
||||
ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
|
||||
struct sk_buff *skb;
|
||||
|
||||
orig_node = batadv_orig_hash_find(bat_priv, dst);
|
||||
if (!orig_node)
|
||||
|
||||
@@ -1827,10 +1827,10 @@ struct batadv_bla_claim {
|
||||
/** @hash_entry: hlist node for &batadv_priv_bla.claim_hash */
|
||||
struct hlist_node hash_entry;
|
||||
|
||||
/** @refcount: number of contexts the object is used */
|
||||
/** @rcu: struct used for freeing in an RCU-safe manner */
|
||||
struct rcu_head rcu;
|
||||
|
||||
/** @rcu: struct used for freeing in an RCU-safe manner */
|
||||
/** @refcount: number of contexts the object is used */
|
||||
struct kref refcount;
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user