1
0
Fork 0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-01-24 17:23:25 -05:00

batman-adv: move and restructure batadv_v_ogm_forward

To match our code better to the protocol description of B.A.T.M.A.N. V,
move batadv_v_ogm_forward() out into batadv_v_ogm_process_per_outif()
and move all checks directly deciding whether the OGM should be
forwarded into batadv_v_ogm_forward().

Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: Antonio Quartulli <a@unstable.cc>
This commit is contained in:
Simon Wunderlich 2016-02-01 15:21:37 +01:00 committed by Antonio Quartulli
parent 121bdca0d4
commit efcc9d3069

View file

@ -347,10 +347,12 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
} }
/** /**
* batadv_v_ogm_forward - forward an OGM to the given outgoing interface * batadv_v_ogm_forward - check conditions and forward an OGM to the given
* outgoing interface
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
* @ogm_received: previously received OGM to be forwarded * @ogm_received: previously received OGM to be forwarded
* @throughput: throughput to announce, may vary per outgoing interface * @orig_node: the originator which has been updated
* @neigh_node: the neigh_node through with the OGM has been received
* @if_incoming: the interface on which this OGM was received on * @if_incoming: the interface on which this OGM was received on
* @if_outgoing: the interface to which the OGM has to be forwarded to * @if_outgoing: the interface to which the OGM has to be forwarded to
* *
@ -359,28 +361,57 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
*/ */
static void batadv_v_ogm_forward(struct batadv_priv *bat_priv, static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
const struct batadv_ogm2_packet *ogm_received, const struct batadv_ogm2_packet *ogm_received,
u32 throughput, struct batadv_orig_node *orig_node,
struct batadv_neigh_node *neigh_node,
struct batadv_hard_iface *if_incoming, struct batadv_hard_iface *if_incoming,
struct batadv_hard_iface *if_outgoing) struct batadv_hard_iface *if_outgoing)
{ {
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
struct batadv_orig_ifinfo *orig_ifinfo = NULL;
struct batadv_neigh_node *router = NULL;
struct batadv_ogm2_packet *ogm_forward; struct batadv_ogm2_packet *ogm_forward;
unsigned char *skb_buff; unsigned char *skb_buff;
struct sk_buff *skb; struct sk_buff *skb;
size_t packet_len; size_t packet_len;
u16 tvlv_len; u16 tvlv_len;
/* only forward for specific interfaces, not for the default one. */
if (if_outgoing == BATADV_IF_DEFAULT)
goto out;
orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
if (!orig_ifinfo)
goto out;
/* acquire possibly updated router */
router = batadv_orig_router_get(orig_node, if_outgoing);
/* strict rule: forward packets coming from the best next hop only */
if (neigh_node != router)
goto out;
/* don't forward the same seqno twice on one interface */
if (orig_ifinfo->last_seqno_forwarded == ntohl(ogm_received->seqno))
goto out;
orig_ifinfo->last_seqno_forwarded = ntohl(ogm_received->seqno);
if (ogm_received->ttl <= 1) { if (ogm_received->ttl <= 1) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n"); batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
return; goto out;
} }
neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
if (!neigh_ifinfo)
goto out;
tvlv_len = ntohs(ogm_received->tvlv_len); tvlv_len = ntohs(ogm_received->tvlv_len);
packet_len = BATADV_OGM2_HLEN + tvlv_len; packet_len = BATADV_OGM2_HLEN + tvlv_len;
skb = netdev_alloc_skb_ip_align(if_outgoing->net_dev, skb = netdev_alloc_skb_ip_align(if_outgoing->net_dev,
ETH_HLEN + packet_len); ETH_HLEN + packet_len);
if (!skb) if (!skb)
return; goto out;
skb_reserve(skb, ETH_HLEN); skb_reserve(skb, ETH_HLEN);
skb_buff = skb_put(skb, packet_len); skb_buff = skb_put(skb, packet_len);
@ -388,15 +419,23 @@ static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
/* apply forward penalty */ /* apply forward penalty */
ogm_forward = (struct batadv_ogm2_packet *)skb_buff; ogm_forward = (struct batadv_ogm2_packet *)skb_buff;
ogm_forward->throughput = htonl(throughput); ogm_forward->throughput = htonl(neigh_ifinfo->bat_v.throughput);
ogm_forward->ttl--; ogm_forward->ttl--;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Forwarding OGM2 packet on %s: throughput %u, ttl %u, received via %s\n", "Forwarding OGM2 packet on %s: throughput %u, ttl %u, received via %s\n",
if_outgoing->net_dev->name, throughput, ogm_forward->ttl, if_outgoing->net_dev->name, ntohl(ogm_forward->throughput),
if_incoming->net_dev->name); ogm_forward->ttl, if_incoming->net_dev->name);
batadv_v_ogm_send_to_if(skb, if_outgoing); batadv_v_ogm_send_to_if(skb, if_outgoing);
out:
if (orig_ifinfo)
batadv_orig_ifinfo_put(orig_ifinfo);
if (router)
batadv_neigh_node_put(router);
if (neigh_ifinfo)
batadv_neigh_ifinfo_put(neigh_ifinfo);
} }
/** /**
@ -493,8 +532,10 @@ out:
* @neigh_node: the neigh_node through with the OGM has been received * @neigh_node: the neigh_node through with the OGM has been received
* @if_incoming: the interface where this packet was received * @if_incoming: the interface where this packet was received
* @if_outgoing: the interface for which the packet should be considered * @if_outgoing: the interface for which the packet should be considered
*
* Return: true if the packet should be forwarded, false otherwise
*/ */
static void batadv_v_ogm_route_update(struct batadv_priv *bat_priv, static bool batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
const struct ethhdr *ethhdr, const struct ethhdr *ethhdr,
const struct batadv_ogm2_packet *ogm2, const struct batadv_ogm2_packet *ogm2,
struct batadv_orig_node *orig_node, struct batadv_orig_node *orig_node,
@ -503,14 +544,9 @@ static void batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_outgoing) struct batadv_hard_iface *if_outgoing)
{ {
struct batadv_neigh_node *router = NULL; struct batadv_neigh_node *router = NULL;
struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
struct batadv_orig_node *orig_neigh_node = NULL; struct batadv_orig_node *orig_neigh_node = NULL;
struct batadv_orig_ifinfo *orig_ifinfo = NULL;
struct batadv_neigh_node *orig_neigh_router = NULL; struct batadv_neigh_node *orig_neigh_router = NULL;
bool forward = false;
neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
if (!neigh_ifinfo)
goto out;
orig_neigh_node = batadv_v_ogm_orig_get(bat_priv, ethhdr->h_source); orig_neigh_node = batadv_v_ogm_orig_get(bat_priv, ethhdr->h_source);
if (!orig_neigh_node) if (!orig_neigh_node)
@ -529,47 +565,20 @@ static void batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
goto out; goto out;
} }
if (router)
batadv_neigh_node_put(router);
/* Update routes, and check if the OGM is from the best next hop */ /* Update routes, and check if the OGM is from the best next hop */
batadv_v_ogm_orig_update(bat_priv, orig_node, neigh_node, ogm2, batadv_v_ogm_orig_update(bat_priv, orig_node, neigh_node, ogm2,
if_outgoing); if_outgoing);
orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing); forward = true;
if (!orig_ifinfo)
goto out;
/* don't forward the same seqno twice on one interface */
if (orig_ifinfo->last_seqno_forwarded == ntohl(ogm2->seqno))
goto out;
/* acquire possibly updated router */
router = batadv_orig_router_get(orig_node, if_outgoing);
/* strict rule: forward packets coming from the best next hop only */
if (neigh_node != router)
goto out;
/* only forward for specific interface, not for the default one. */
if (if_outgoing != BATADV_IF_DEFAULT) {
orig_ifinfo->last_seqno_forwarded = ntohl(ogm2->seqno);
batadv_v_ogm_forward(bat_priv, ogm2,
neigh_ifinfo->bat_v.throughput,
if_incoming, if_outgoing);
}
out: out:
if (orig_ifinfo)
batadv_orig_ifinfo_put(orig_ifinfo);
if (router) if (router)
batadv_neigh_node_put(router); batadv_neigh_node_put(router);
if (orig_neigh_router) if (orig_neigh_router)
batadv_neigh_node_put(orig_neigh_router); batadv_neigh_node_put(orig_neigh_router);
if (orig_neigh_node) if (orig_neigh_node)
batadv_orig_node_put(orig_neigh_node); batadv_orig_node_put(orig_neigh_node);
if (neigh_ifinfo)
batadv_neigh_ifinfo_put(neigh_ifinfo); return forward;
} }
/** /**
@ -592,6 +601,7 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_outgoing) struct batadv_hard_iface *if_outgoing)
{ {
int seqno_age; int seqno_age;
bool forward;
/* first, update the metric with according sanity checks */ /* first, update the metric with according sanity checks */
seqno_age = batadv_v_ogm_metric_update(bat_priv, ogm2, orig_node, seqno_age = batadv_v_ogm_metric_update(bat_priv, ogm2, orig_node,
@ -610,8 +620,14 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
ntohs(ogm2->tvlv_len)); ntohs(ogm2->tvlv_len));
/* if the metric update went through, update routes if needed */ /* if the metric update went through, update routes if needed */
batadv_v_ogm_route_update(bat_priv, ethhdr, ogm2, orig_node, forward = batadv_v_ogm_route_update(bat_priv, ethhdr, ogm2, orig_node,
neigh_node, if_incoming, if_outgoing); neigh_node, if_incoming,
if_outgoing);
/* if the routes have been processed correctly, check and forward */
if (forward)
batadv_v_ogm_forward(bat_priv, ogm2, orig_node, neigh_node,
if_incoming, if_outgoing);
} }
/** /**