VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46238

CVE-2026-46238

Description

In the Linux kernel, the following vulnerability has been resolved:

batman-adv: stop caching unowned originator pointers in BAT IV

BAT IV keeps the last-hop neighbor address in each neigh_node, but some paths also cache an originator pointer derived from a temporary lookup. That pointer is not owned by the neigh_node and may no longer refer to a live originator entry after purge handling runs.

Stop storing the auxiliary originator pointer in the BAT IV neighbor state. When BAT IV needs the neighbor originator data, resolve it from the stored neighbor address and drop the reference again after use.

[sven: avoid bonding logic for outgoing OGM]

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In the Linux kernel's batman-adv BAT IV routing, a dangling originator pointer cached in neigh_node can be used after free, potentially leading to a use-after-free condition.

Vulnerability

In the Linux kernel's batman-adv module, the BAT IV routing algorithm caches an auxiliary originator pointer in each neigh_node structure derived from a temporary lookup. This pointer is not owned by the neigh_node and may no longer refer to a live originator entry after purge handling runs, leading to a use-after-free vulnerability when the cached pointer is accessed. The issue affects all kernel versions using batman-adv with BAT IV enabled. No specific version range is provided in the available references.

Exploitation

An attacker with network access to a mesh network running BAT IV could trigger the vulnerability by causing a sequence of events where the cached originator pointer is used after the originator entry has been purged. The precise conditions require the attacker to be able to send crafted mesh traffic that causes the stale pointer to be dereferenced. No authentication is required, but the attacker must be able to participate in the mesh network.

Impact

Successful exploitation could result in a use-after-free condition, potentially leading to memory corruption, kernel crash (denial of service), or in theory, privilege escalation. The impact is limited to systems running the batman-adv kernel module with BAT IV enabled.

Mitigation

The fix is included in the Linux kernel stable branch as commit 67bceeb22207f1f5a402973a3a0809e5f2698f38 [1]. The commit removes the caching of the unowned originator pointer and instead resolves the originator data on demand, dropping the reference after use. No workarounds are available if a patched kernel cannot be deployed; the only mitigation is to disable the batman-adv module or switch to a different routing algorithm if supported.

AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

3

Patches

10
6e20700f8c52

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 98984296989e11..748188d3b878b2 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -172,19 +172,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -900,6 +893,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -969,17 +987,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1031,10 +1041,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1100,7 +1109,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1296,6 +1304,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1366,8 +1400,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 98984296989e11..748188d3b878b2 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -172,19 +172,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -900,6 +893,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -969,17 +987,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1031,10 +1041,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1100,7 +1109,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1296,6 +1304,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1366,8 +1400,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
f03e85835329

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
09dc0d1a1222

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
67bceeb22207

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
aafcbaf1159e

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 98984296989e11..748188d3b878b2 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -172,19 +172,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -900,6 +893,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -969,17 +987,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1031,10 +1041,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1100,7 +1109,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1296,6 +1304,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1366,8 +1400,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 98984296989e11..748188d3b878b2 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -172,19 +172,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -900,6 +893,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -969,17 +987,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1031,10 +1041,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1100,7 +1109,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1296,6 +1304,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1366,8 +1400,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
aafcbaf1159e

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 98984296989e11..748188d3b878b2 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -172,19 +172,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -900,6 +893,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -969,17 +987,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1031,10 +1041,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1100,7 +1109,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1296,6 +1304,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1366,8 +1400,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 98984296989e11..748188d3b878b2 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -172,19 +172,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -900,6 +893,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -969,17 +987,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1031,10 +1041,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1100,7 +1109,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1296,6 +1304,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1366,8 +1400,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
67bceeb22207

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
6e20700f8c52

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 98984296989e11..748188d3b878b2 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -172,19 +172,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -900,6 +893,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -969,17 +987,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1031,10 +1041,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1100,7 +1109,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1296,6 +1304,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1366,8 +1400,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 98984296989e11..748188d3b878b2 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -172,19 +172,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -900,6 +893,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -969,17 +987,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1031,10 +1041,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1100,7 +1109,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1296,6 +1304,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1366,8 +1400,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
f03e85835329

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
09dc0d1a1222

batman-adv: stop caching unowned originator pointers in BAT IV

2 files changed · +118 50
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/batman-adv/bat_iv_ogm.c+59 25 modified
    diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
    index 618d1889c04e75..74ef7dc2b2f981 100644
    --- a/net/batman-adv/bat_iv_ogm.c
    +++ b/net/batman-adv/bat_iv_ogm.c
    @@ -173,19 +173,12 @@ free_orig_node_hash:
     static struct batadv_neigh_node *
     batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
     			const u8 *neigh_addr,
    -			struct batadv_orig_node *orig_node,
    -			struct batadv_orig_node *orig_neigh)
    +			struct batadv_orig_node *orig_node)
     {
     	struct batadv_neigh_node *neigh_node;
     
     	neigh_node = batadv_neigh_node_get_or_create(orig_node,
     						     hard_iface, neigh_addr);
    -	if (!neigh_node)
    -		goto out;
    -
    -	neigh_node->orig_node = orig_neigh;
    -
    -out:
     	return neigh_node;
     }
     
    @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
     	return sum;
     }
     
    +/**
    + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @neigh_node: last-hop neighbor of an originator
    + *
    + * Return: Number of replied (rebroadcasted) OGMs for the originator currently
    + * announced by the neighbor. Returns 0 if the neighbor's originator entry is
    + * not available anymore.
    + */
    +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv,
    +					 const struct batadv_neigh_node *neigh_node)
    +{
    +	struct batadv_orig_node *orig_neigh;
    +	u8 sum;
    +
    +	orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr);
    +	if (!orig_neigh)
    +		return 0;
    +
    +	sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming);
    +	batadv_orig_node_put(orig_neigh);
    +
    +	return sum;
    +}
    +
     /**
      * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
      *  originator
    @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	}
     
     	if (!neigh_node) {
    -		struct batadv_orig_node *orig_tmp;
    -
    -		orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source);
    -		if (!orig_tmp)
    -			goto unlock;
    -
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     ethhdr->h_source,
    -						     orig_node, orig_tmp);
    -
    -		batadv_orig_node_put(orig_tmp);
    +						     orig_node);
     		if (!neigh_node)
     			goto unlock;
     	} else {
    @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
     	 */
     	if (router_ifinfo &&
     	    neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
    -		sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
    -						     router->if_incoming);
    -		sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
    -						      neigh_node->if_incoming);
    +		sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router);
    +		sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv,
    +							   neigh_node);
     		if (sum_orig >= sum_neigh)
     			goto out;
     	}
    @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
     	if (!neigh_node)
     		neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
     						     orig_neigh_node->orig,
    -						     orig_neigh_node,
     						     orig_neigh_node);
     
     	if (!neigh_node)
    @@ -1302,6 +1310,32 @@ out:
     	return ret;
     }
     
    +/**
    + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address
    + * @bat_priv: the bat priv with all the mesh interface information
    + * @orig_addr: the originator MAC address to search the best next hop router for
    + * @if_outgoing: the interface where the OGM should be sent to
    + *
    + * Return: A neighbor node which is the best router towards the given originator
    + * address. Bonding candidates are ignored.
    + */
    +static struct batadv_neigh_node *
    +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr,
    +			     struct batadv_hard_iface *if_outgoing)
    +{
    +	struct batadv_neigh_node *neigh_node;
    +	struct batadv_orig_node *orig_node;
    +
    +	orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
    +	if (!orig_node)
    +		return NULL;
    +
    +	neigh_node = batadv_orig_router_get(orig_node, if_outgoing);
    +	batadv_orig_node_put(orig_node);
    +
    +	return neigh_node;
    +}
    +
     /**
      * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing
      *  interface
    @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset,
     
     	router = batadv_orig_router_get(orig_node, if_outgoing);
     	if (router) {
    -		router_router = batadv_orig_router_get(router->orig_node,
    -						       if_outgoing);
    +		router_router = batadv_orig_to_direct_router(bat_priv,
    +							     router->addr,
    +							     if_outgoing);
     		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
     	}
     
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"The neigh_node stored a borrowed originator pointer without taking a reference, allowing a use-after-free when the originator entry is purged concurrently."

Attack vector

An attacker on the same mesh network can send crafted batman-adv OGMs (Originator Messages) to trigger the race condition. When the kernel processes an OGM, it temporarily looks up an `orig_node` and caches the pointer in a `neigh_node`. If a concurrent purge operation frees that originator entry before the cached pointer is used, the kernel dereferences freed memory. This can lead to a use-after-free crash or potentially arbitrary code execution. [patch_id=2897497]

Affected code

The vulnerability is in `net/batman-adv/bat_iv_ogm.c`. The `batadv_iv_ogm_neigh_new()` function stored a borrowed `orig_node` pointer in `neigh_node->orig_node` without taking a reference, and callers in `batadv_iv_ogm_orig_update()`, `batadv_iv_ogm_calc_tq()`, and `batadv_iv_ogm_process_per_outif()` later dereferenced this pointer (`router->orig_node`) after the originator entry could have been freed by purge handling. [patch_id=2897495] [patch_id=2897497]

What the fix does

The patch removes the `neigh_node->orig_node` field that was storing an unowned pointer. Instead of caching the pointer, the new helper `batadv_iv_ogm_neigh_ifinfo_sum()` performs a fresh `batadv_orig_hash_find()` using the neighbor's MAC address, calls `batadv_iv_orig_ifinfo_sum()`, and then drops the reference with `batadv_orig_node_put()`. Similarly, `batadv_orig_to_direct_router()` replaces the direct `router->orig_node` dereference by looking up the originator by address and releasing it after use. This ensures every originator pointer is properly reference-counted and cannot become dangling. [patch_id=2897495]

Preconditions

  • networkThe attacker must be a participant in the same batman-adv mesh network and able to send/receive OGMs.
  • configThe kernel must be running a version of batman-adv that caches the unowned originator pointer (introduced since commit c6c8fea29769).

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.