|
@@ -233,73 +233,6 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
|
|
|
ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * batadv_v_ogm_orig_update - update the originator status based on the received
|
|
|
- * OGM
|
|
|
- * @bat_priv: the bat priv with all the soft interface information
|
|
|
- * @orig_node: the originator to update
|
|
|
- * @neigh_node: the neighbour the OGM has been received from (to update)
|
|
|
- * @ogm2: the received OGM
|
|
|
- * @if_outgoing: the interface where this OGM is going to be forwarded through
|
|
|
- */
|
|
|
-static void
|
|
|
-batadv_v_ogm_orig_update(struct batadv_priv *bat_priv,
|
|
|
- struct batadv_orig_node *orig_node,
|
|
|
- struct batadv_neigh_node *neigh_node,
|
|
|
- const struct batadv_ogm2_packet *ogm2,
|
|
|
- struct batadv_hard_iface *if_outgoing)
|
|
|
-{
|
|
|
- struct batadv_neigh_ifinfo *router_ifinfo = NULL, *neigh_ifinfo = NULL;
|
|
|
- struct batadv_neigh_node *router = NULL;
|
|
|
- s32 neigh_seq_diff;
|
|
|
- u32 neigh_last_seqno;
|
|
|
- u32 router_last_seqno;
|
|
|
- u32 router_throughput, neigh_throughput;
|
|
|
-
|
|
|
- batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
|
|
- "Searching and updating originator entry of received packet\n");
|
|
|
-
|
|
|
- /* if this neighbor already is our next hop there is nothing
|
|
|
- * to change
|
|
|
- */
|
|
|
- router = batadv_orig_router_get(orig_node, if_outgoing);
|
|
|
- if (router == neigh_node)
|
|
|
- goto out;
|
|
|
-
|
|
|
- /* don't consider neighbours with worse throughput.
|
|
|
- * also switch route if this seqno is BATADV_V_MAX_ORIGDIFF newer than
|
|
|
- * the last received seqno from our best next hop.
|
|
|
- */
|
|
|
- if (router) {
|
|
|
- router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
|
|
|
- neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
|
|
|
-
|
|
|
- /* if these are not allocated, something is wrong. */
|
|
|
- if (!router_ifinfo || !neigh_ifinfo)
|
|
|
- goto out;
|
|
|
-
|
|
|
- neigh_last_seqno = neigh_ifinfo->bat_v.last_seqno;
|
|
|
- router_last_seqno = router_ifinfo->bat_v.last_seqno;
|
|
|
- neigh_seq_diff = neigh_last_seqno - router_last_seqno;
|
|
|
- router_throughput = router_ifinfo->bat_v.throughput;
|
|
|
- neigh_throughput = neigh_ifinfo->bat_v.throughput;
|
|
|
-
|
|
|
- if ((neigh_seq_diff < BATADV_OGM_MAX_ORIGDIFF) &&
|
|
|
- (router_throughput >= neigh_throughput))
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- batadv_update_route(bat_priv, orig_node, if_outgoing, neigh_node);
|
|
|
-
|
|
|
-out:
|
|
|
- if (router_ifinfo)
|
|
|
- batadv_neigh_ifinfo_put(router_ifinfo);
|
|
|
- if (neigh_ifinfo)
|
|
|
- batadv_neigh_ifinfo_put(neigh_ifinfo);
|
|
|
- if (router)
|
|
|
- batadv_neigh_node_put(router);
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* batadv_v_forward_penalty - apply a penalty to the throughput metric forwarded
|
|
|
* with B.A.T.M.A.N. V OGMs
|
|
@@ -347,10 +280,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
|
|
|
* @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_outgoing: the interface to which the OGM has to be forwarded to
|
|
|
*
|
|
@@ -359,28 +294,57 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
|
|
|
*/
|
|
|
static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
|
|
|
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_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;
|
|
|
unsigned char *skb_buff;
|
|
|
struct sk_buff *skb;
|
|
|
size_t packet_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) {
|
|
|
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);
|
|
|
|
|
|
packet_len = BATADV_OGM2_HLEN + tvlv_len;
|
|
|
skb = netdev_alloc_skb_ip_align(if_outgoing->net_dev,
|
|
|
ETH_HLEN + packet_len);
|
|
|
if (!skb)
|
|
|
- return;
|
|
|
+ goto out;
|
|
|
|
|
|
skb_reserve(skb, ETH_HLEN);
|
|
|
skb_buff = skb_put(skb, packet_len);
|
|
@@ -388,15 +352,23 @@ static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
|
|
|
|
|
|
/* apply forward penalty */
|
|
|
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--;
|
|
|
|
|
|
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
|
|
"Forwarding OGM2 packet on %s: throughput %u, ttl %u, received via %s\n",
|
|
|
- if_outgoing->net_dev->name, throughput, ogm_forward->ttl,
|
|
|
- if_incoming->net_dev->name);
|
|
|
+ if_outgoing->net_dev->name, ntohl(ogm_forward->throughput),
|
|
|
+ ogm_forward->ttl, if_incoming->net_dev->name);
|
|
|
|
|
|
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 +465,10 @@ out:
|
|
|
* @neigh_node: the neigh_node through with the OGM has been received
|
|
|
* @if_incoming: the interface where this packet was received
|
|
|
* @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 batadv_ogm2_packet *ogm2,
|
|
|
struct batadv_orig_node *orig_node,
|
|
@@ -503,14 +477,14 @@ static void batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
|
|
|
struct batadv_hard_iface *if_outgoing)
|
|
|
{
|
|
|
struct batadv_neigh_node *router = NULL;
|
|
|
- struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
|
|
|
struct batadv_orig_node *orig_neigh_node = NULL;
|
|
|
- struct batadv_orig_ifinfo *orig_ifinfo = NULL;
|
|
|
struct batadv_neigh_node *orig_neigh_router = NULL;
|
|
|
-
|
|
|
- neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
|
|
|
- if (!neigh_ifinfo)
|
|
|
- goto out;
|
|
|
+ struct batadv_neigh_ifinfo *router_ifinfo = NULL, *neigh_ifinfo = NULL;
|
|
|
+ u32 router_throughput, neigh_throughput;
|
|
|
+ u32 router_last_seqno;
|
|
|
+ u32 neigh_last_seqno;
|
|
|
+ s32 neigh_seq_diff;
|
|
|
+ bool forward = false;
|
|
|
|
|
|
orig_neigh_node = batadv_v_ogm_orig_get(bat_priv, ethhdr->h_source);
|
|
|
if (!orig_neigh_node)
|
|
@@ -529,47 +503,57 @@ static void batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- if (router)
|
|
|
- batadv_neigh_node_put(router);
|
|
|
+ /* Mark the OGM to be considered for forwarding, and update routes
|
|
|
+ * if needed.
|
|
|
+ */
|
|
|
+ forward = true;
|
|
|
|
|
|
- /* 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,
|
|
|
- if_outgoing);
|
|
|
+ batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
|
|
+ "Searching and updating originator entry of received packet\n");
|
|
|
|
|
|
- orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
|
|
|
- if (!orig_ifinfo)
|
|
|
+ /* if this neighbor already is our next hop there is nothing
|
|
|
+ * to change
|
|
|
+ */
|
|
|
+ if (router == neigh_node)
|
|
|
goto out;
|
|
|
|
|
|
- /* don't forward the same seqno twice on one interface */
|
|
|
- if (orig_ifinfo->last_seqno_forwarded == ntohl(ogm2->seqno))
|
|
|
- goto out;
|
|
|
+ /* don't consider neighbours with worse throughput.
|
|
|
+ * also switch route if this seqno is BATADV_V_MAX_ORIGDIFF newer than
|
|
|
+ * the last received seqno from our best next hop.
|
|
|
+ */
|
|
|
+ if (router) {
|
|
|
+ router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
|
|
|
+ neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
|
|
|
|
|
|
- /* acquire possibly updated router */
|
|
|
- router = batadv_orig_router_get(orig_node, if_outgoing);
|
|
|
+ /* if these are not allocated, something is wrong. */
|
|
|
+ if (!router_ifinfo || !neigh_ifinfo)
|
|
|
+ goto out;
|
|
|
|
|
|
- /* strict rule: forward packets coming from the best next hop only */
|
|
|
- if (neigh_node != router)
|
|
|
- goto out;
|
|
|
+ neigh_last_seqno = neigh_ifinfo->bat_v.last_seqno;
|
|
|
+ router_last_seqno = router_ifinfo->bat_v.last_seqno;
|
|
|
+ neigh_seq_diff = neigh_last_seqno - router_last_seqno;
|
|
|
+ router_throughput = router_ifinfo->bat_v.throughput;
|
|
|
+ neigh_throughput = neigh_ifinfo->bat_v.throughput;
|
|
|
|
|
|
- /* 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);
|
|
|
+ if ((neigh_seq_diff < BATADV_OGM_MAX_ORIGDIFF) &&
|
|
|
+ (router_throughput >= neigh_throughput))
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
+ batadv_update_route(bat_priv, orig_node, if_outgoing, neigh_node);
|
|
|
out:
|
|
|
- if (orig_ifinfo)
|
|
|
- batadv_orig_ifinfo_put(orig_ifinfo);
|
|
|
if (router)
|
|
|
batadv_neigh_node_put(router);
|
|
|
if (orig_neigh_router)
|
|
|
batadv_neigh_node_put(orig_neigh_router);
|
|
|
if (orig_neigh_node)
|
|
|
batadv_orig_node_put(orig_neigh_node);
|
|
|
+ if (router_ifinfo)
|
|
|
+ batadv_neigh_ifinfo_put(router_ifinfo);
|
|
|
if (neigh_ifinfo)
|
|
|
batadv_neigh_ifinfo_put(neigh_ifinfo);
|
|
|
+
|
|
|
+ return forward;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -592,6 +576,7 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
|
|
|
struct batadv_hard_iface *if_outgoing)
|
|
|
{
|
|
|
int seqno_age;
|
|
|
+ bool forward;
|
|
|
|
|
|
/* first, update the metric with according sanity checks */
|
|
|
seqno_age = batadv_v_ogm_metric_update(bat_priv, ogm2, orig_node,
|
|
@@ -610,8 +595,14 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
|
|
|
ntohs(ogm2->tvlv_len));
|
|
|
|
|
|
/* if the metric update went through, update routes if needed */
|
|
|
- batadv_v_ogm_route_update(bat_priv, ethhdr, ogm2, orig_node,
|
|
|
- neigh_node, if_incoming, if_outgoing);
|
|
|
+ forward = batadv_v_ogm_route_update(bat_priv, ethhdr, ogm2, orig_node,
|
|
|
+ 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);
|
|
|
}
|
|
|
|
|
|
/**
|