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:
Jakub Kicinski
2026-08-12 18:51:40 -07:00
31 changed files with 1555 additions and 548 deletions

View File

@@ -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;
};
/**

View File

@@ -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';

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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)
{
}

View File

@@ -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)

View File

@@ -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 ?

View File

@@ -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)

View File

@@ -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))

View File

@@ -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;

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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

View File

@@ -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))

View File

@@ -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;

View File

@@ -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];

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;
}
/**

View File

@@ -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 *

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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)

View File

@@ -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