public inbox for b.a.t.m.a.n@lists.open-mesh.org
 help / color / mirror / Atom feed
From: Simon Wunderlich <sw@simonwunderlich.de>
To: b.a.t.m.a.n@lists.open-mesh.org
Subject: Re: [B.A.T.M.A.N.] [PATCHv2 3/8] batman-adv: split out router from orig_node
Date: Tue, 5 Nov 2013 14:14:02 +0100	[thread overview]
Message-ID: <201311051414.02525.sw@simonwunderlich.de> (raw)
In-Reply-To: <20131105000342.GU15496@Linus-Debian>

Hey Linus,

again, all suggestions not commented are approved. Some comments inline (BTW, 
it would be enough if you just keep the hunk you comment and don't keep the 
whole patchset in the reply).

> > + * @if_incoming: the interface where this packet was receved
> > + * @if_outgoing: the interface for which the packet should be considered
> > + */
> > +static void
> > +batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int
> > ogm_offset, +				struct batadv_orig_node *orig_node,
> > +				struct batadv_hard_iface *if_incoming,
> > +				struct batadv_hard_iface *if_outgoing)
> > 
> >  {
> >  
> >  	struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
> > 
> > -	struct batadv_hard_iface *hard_iface;
> > -	struct batadv_orig_node *orig_neigh_node, *orig_node, *orig_node_tmp;
> > 
> >  	struct batadv_neigh_node *router = NULL, *router_router = NULL;
> > 
> > +	struct batadv_orig_node *orig_neigh_node, *orig_node_tmp;
> > +	struct batadv_orig_ifinfo *orig_ifinfo;
> > 
> >  	struct batadv_neigh_node *orig_neigh_router = NULL;
> >  	struct batadv_neigh_ifinfo *router_ifinfo = NULL;
> > 
> > -	int has_directlink_flag;
> > -	int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
> > -	int is_bidirect;
> > -	bool is_single_hop_neigh = false;
> > -	bool is_from_best_next_hop = false;
> > -	int sameseq, similar_ttl;
> > +	struct batadv_ogm_packet *ogm_packet;
> > 
> >  	enum batadv_dup_status dup_status;
> > 
> > -	uint32_t if_incoming_seqno;
> > +	bool is_from_best_next_hop = false;
> > +	bool is_single_hop_neigh = false;
> > +	bool sameseq, similar_ttl;
> > +	struct sk_buff *skb_priv;
> > +	struct ethhdr *ethhdr;
> > 
> >  	uint8_t *prev_sender;
> > 
> > +	int is_bidirect;
> > +
> > +	/* create a private copy of the skb, as some functions change tq 
value
> > +	 * and/or flags.
> > +	 */
> > +	skb_priv = skb_copy(skb, GFP_ATOMIC);
> > +	if (!skb_priv)
> > +		return;
> > +
> > +	ethhdr = eth_hdr(skb_priv);
> > +	ogm_packet = (struct batadv_ogm_packet *)(skb_priv->data + 
ogm_offset);
> > +
> > +	dup_status = batadv_iv_ogm_update_seqnos(ethhdr, ogm_packet,
> > +						 if_incoming, if_outgoing);
> 
> To avoid redundant code execution,
> move this if statement to the calling function maybe?
> 

No, this has to be called per outgoing interface.

> > +	if (batadv_compare_eth(ethhdr->h_source, ogm_packet->orig))
> > +		is_single_hop_neigh = true;
> > +
> > +	if (dup_status == BATADV_PROTECTED) {
> > +		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> > +			   "Drop packet: packet within seqno protection time 
(sender:
> > %pM)\n", +			   ethhdr->h_source);
> > +		goto out;
> > +	}
> > +
> 
> Move this if statement to the calling function maybe?
> 

... depends on dup_status.

> > +	if (ogm_packet->tq == 0) {
> > +		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> > +			   "Drop packet: originator packet with tq equal 0\n");
> > +		goto out;
> > +	}
> > +
> > +	router = batadv_orig_router_get(orig_node, if_outgoing);
> > +	if (router) {
> > +		orig_node_tmp = router->orig_node;
> > +		router_router = batadv_orig_router_get(router->orig_node,
> > +						       if_outgoing);
> > +		router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
> > +	}
> > +
> > +	if ((router_ifinfo && router_ifinfo->bat_iv.tq_avg != 0) &&
> > +	    (batadv_compare_eth(router->addr, ethhdr->h_source)))
> > +		is_from_best_next_hop = true;
> > +
> > +	prev_sender = ogm_packet->prev_sender;
> > +	/* avoid temporary routing loops */
> > +	if (router && router_router &&
> > +	    (batadv_compare_eth(router->addr, prev_sender)) &&
> > +	    !(batadv_compare_eth(ogm_packet->orig, prev_sender)) &&
> > +	    (batadv_compare_eth(router->addr, router_router->addr))) {
> > +		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> > +			   "Drop packet: ignoring all rebroadcast packets that 
may make me
> > loop (sender: %pM)\n", +			   ethhdr->h_source);
> > +		goto out;
> > +	}
> > +
> 
> Move this to ...
> 

Nope, this comes after the duplicate check/filling of the respective bitfields. 
As we can't move the dupstatus changing the order is not a good idea imho.

> > +	/* if sender is a direct neighbor the sender mac equals
> > +	 * originator mac
> > +	 */
> > +	if (is_single_hop_neigh)
> > +		orig_neigh_node = orig_node;
> > +	else
> > +		orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv,
> > +							 ethhdr->h_source);
> > +
> > +	if (!orig_neigh_node)
> > +		goto out;
> > +
> > +	/* Update nc_nodes of the originator */
> > +	batadv_nc_update_nc_node(bat_priv, orig_node, orig_neigh_node,
> > +				 ogm_packet, is_single_hop_neigh);
> 
> ... this to the calling function, maybe?
> 

Not sure here, but I'd rather not fiddle with network coding here.

To summarise here: I wanted to split the ogm_process function between the 
outif-independent part and the outif-dependent part while keeping the order of 
the processing as it was before - to not introduce new bugs here. Therefore I 
prefer to keep the order, even if some checks are done twice after the bitfield 
setting.

> > +
> > +	orig_neigh_router = batadv_orig_router_get(orig_neigh_node,
> > +						   if_outgoing);
> > +
> > +	/* drop packet if sender is not a direct neighbor and if we
> > +	 * don't route towards it
> > +	 */
> > +	if (!is_single_hop_neigh && (!orig_neigh_router)) {
> > +		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> > +			   "Drop packet: OGM via unknown neighbor!\n");
> > +		goto out_neigh;
> > +	}
> > +
> > +	is_bidirect = batadv_iv_ogm_calc_tq(orig_node, orig_neigh_node,
> > +					    ogm_packet, if_incoming,
> > +					    if_outgoing);
> > +
> > +	/* update ranking if it is not a duplicate or has the same
> > +	 * seqno and similar ttl as the non-duplicate
> > +	 */
> > +	orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
> > +	if (!orig_ifinfo)
> > +		goto out_neigh;
> > +
> > +	sameseq = orig_ifinfo->last_real_seqno == ntohl(ogm_packet->seqno);
> > +	similar_ttl = (orig_ifinfo->last_ttl - 3) <= ogm_packet->header.ttl;
> > +	if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
> > +			    (sameseq && similar_ttl))) {
> > +		batadv_iv_ogm_orig_update(bat_priv, orig_node,
> > +					  orig_ifinfo, ethhdr,
> > +					  ogm_packet, if_incoming,
> > +					  if_outgoing, dup_status);
> > +	}
> > +	batadv_orig_ifinfo_free_ref(orig_ifinfo);
> > +
> > +	/* is single hop (direct) neighbor */
> > +	if (is_single_hop_neigh) {
> > +		if ((ogm_packet->header.ttl <= 2) &&
> > +		    (if_incoming != if_outgoing)) {
> > +			batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> > +				   "Drop packet: OGM from secondary interface and 
wrong outgoing
> > interface\n"); +			goto out_neigh;
> > +		}
> 
> The check above, is this just an optimization independant of
> this patchset or is it somehow needed for the multi interface
> patchset? Maybe a comment could be added?
> 

Yeah this is required now as the function is called multiple times, I'll add a 
comment.

> > +		/* mark direct link on incoming interface */
> > +		batadv_iv_ogm_forward(orig_node, ethhdr, ogm_packet,
> > +				      is_single_hop_neigh,
> > +				      is_from_best_next_hop, if_incoming);
> 
> Hmm, okay, now we are forwarding OGMs on an interface multiple
> times. Though you are fixing this in "batman-adv: consider
> outgoing interface in OGM sending" I guess, this is still a
> regression here, isn't it?
> 

Well, yes, you are probably right. I'll add a check here to only schedule for 
the default interface and will remove in the next one again. The "consider 
outgoing interface" patch is not trivial so I wanted to keep it seperate.
> > +
> > +		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> > +			   "Forwarding packet: rebroadcast neighbor packet with 
direct link
> > flag\n"); +		goto out_neigh;
> > +	}
> > +
> > +	/* multihop originator */
> > +	if (!is_bidirect) {
> > +		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> > +			   "Drop packet: not received via bidirectional 
link\n");
> > +		goto out_neigh;
> > +	}
> > +
> > +	if (dup_status == BATADV_NEIGH_DUP) {
> > +		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> > +			   "Drop packet: duplicate packet received\n");
> > +		goto out_neigh;
> > +	}
> > +
> > +	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> > +		   "Forwarding packet: rebroadcast originator packet\n");
> > +	batadv_iv_ogm_forward(orig_node, ethhdr, ogm_packet,
> > +			      is_single_hop_neigh, is_from_best_next_hop,
> > +			      if_incoming);
> > +
> > +out_neigh:
> > +	if ((orig_neigh_node) && (!is_single_hop_neigh))
> > +		batadv_orig_node_free_ref(orig_neigh_node);
> > +out:
> > +	if (router)
> > +		batadv_neigh_node_free_ref(router);
> > +	if (router_router)
> > +		batadv_neigh_node_free_ref(router_router);
> > +	if (orig_neigh_router)
> > +		batadv_neigh_node_free_ref(orig_neigh_router);
> > +
> > +	kfree_skb(skb_priv);
> > +}
> 
> Although this is mostly just code moved around, maybe it would be
> a good idea to split it into several functions now? Would make it
> easier to debug and find potential regressions introduced by this
> patch later, wouldn't it?
> 
> Maybe batadv_iv_ogm_process() would benefit from some more splits,
> too?

Apart from my personal laziness, the idea was to actually keep the code as 
much as it was as possible to make it easier to compare to the previous one. I 
think doing refactoring now would even complicate the review later.

> > @@ -1382,14 +1580,14 @@ static void batadv_iv_ogm_process(const struct
> > ethhdr *ethhdr,
> > 
> >  		 */
> >  		
> >  		if (has_directlink_flag &&
> >  		
> >  		    batadv_compare_eth(if_incoming->net_dev->dev_addr,
> > 
> > -				       batadv_ogm_packet->orig)) {
> > +				       ogm_packet->orig)) {
> > 
> >  			if_num = if_incoming->if_num;
> >  			offset = if_num * BATADV_NUM_WORDS;
> >  			
> >  			spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
> >  			word = &(orig_neigh_node->bat_iv.bcast_own[offset]);
> >  			bit_pos = if_incoming_seqno - 2;
> > 
> > -			bit_pos -= ntohl(batadv_ogm_packet->seqno);
> > +			bit_pos -= ntohl(ogm_packet->seqno);
> > 
> >  			batadv_set_bit(word, bit_pos);
> >  			weight = &orig_neigh_node->bat_iv.bcast_own_sum[if_num];
> >  			*weight = bitmap_weight(word,
> > 
> > @@ -1410,144 +1608,34 @@ static void batadv_iv_ogm_process(const struct
> > ethhdr *ethhdr,
> > 
> >  		return;
> >  	
> >  	}
> > 
> > -	if (batadv_ogm_packet->flags & BATADV_NOT_BEST_NEXT_HOP) {
> > +	if (ogm_packet->flags & BATADV_NOT_BEST_NEXT_HOP) {
> > 
> >  		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
> >  		
> >  			   "Drop packet: ignoring all packets not forwarded from the 
best
> >  			   next hop (sender: %pM)\n", ethhdr->h_source);
> >  		
> >  		return;
> >  	
> >  	}
> > 
> > -	orig_node = batadv_iv_ogm_orig_get(bat_priv, batadv_ogm_packet->orig);
> > +	orig_node = batadv_iv_ogm_orig_get(bat_priv, ogm_packet->orig);
> > 
> >  	if (!orig_node)
> >  	
> >  		return;
> > 
> > -	dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
> > -						 if_incoming,
> > -						 BATADV_IF_DEFAULT);
> > +	batadv_tvlv_ogm_receive(bat_priv, ogm_packet, orig_node);
> 
> Hmm, moving the tvlv_ogm processing upwards, in front of all the
> duplicate/protected/etc. checks seems like a notable, functional change.
> Though there don't seem to be any problems with the OGM TVLVs we
> are currently having as far as I can tell, maybe this change could
> be mentioned in the commit message though?

You are right ... I'll better keep it at the original place and just perform 
that for the default outgoing interface.

> > + * batadv_purge_orig_ifinfo - purge ifinfo entries from originator
> > + * @bat_priv: the bat priv with all the soft interface information
> > + * @orig_node: orig node which is to be checked
> > + *
> > + * Returns true if any ifinfo entry was purged, false otherwise.
> > + */
> > +static bool
> > +batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv,
> > +			 struct batadv_orig_node *orig_node)
> > +{
> > +	struct batadv_orig_ifinfo *orig_ifinfo;
> > +	struct batadv_hard_iface *if_outgoing;
> > +	struct hlist_node *node_tmp;
> > +	bool ifinfo_purged = false;
> > +
> > +	spin_lock_bh(&orig_node->neigh_list_lock);
> > +
> > +	/* for all neighbors towards this originator ... */
> > +	hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
> > +				  &orig_node->ifinfo_list, list) {
> > +		if_outgoing = orig_ifinfo->if_outgoing;
> > +		if (!if_outgoing)
> > +			continue;
> > +
> > +		if ((if_outgoing->if_status != BATADV_IF_INACTIVE) &&
> > +		    (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) &&
> > +		    (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED))
> > +			continue;
> > +
> 
> Hm, if we aren't purging them now, when are we going to do that
> instead? Later we can't because the orig_node and its ifinfo list is
> gone, can we?
> 

The purge function is there to remove obsolete ifinfos of the orig node, just 
as purge_orig_node checks and removes obsolete neighbors and other parts (or 
the whole orig node if it timed out).

I'll update the kerneldoc and will also add kerneldoc to 
batadv_purge_orig_node, this is not very clear.

Thanks,
    Simon

  reply	other threads:[~2013-11-05 13:14 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-30 14:01 [B.A.T.M.A.N.] [PATCHv2 0/8] add network wide multi interface optimization Simon Wunderlich
2013-10-30 14:01 ` [B.A.T.M.A.N.] [PATCHv2 1/8] batman-adv: remove bonding and interface alternating Simon Wunderlich
2013-10-30 14:01 ` [B.A.T.M.A.N.] [PATCHv2 2/8] batman-adv: split tq information in neigh_node struct Simon Wunderlich
2013-10-30 16:33   ` Marek Lindner
2013-11-01  5:53   ` Linus Lüssing
2013-11-05 11:16     ` Simon Wunderlich
2013-11-05  0:13   ` Linus Lüssing
2013-10-30 14:01 ` [B.A.T.M.A.N.] [PATCHv2 3/8] batman-adv: split out router from orig_node Simon Wunderlich
2013-11-05  0:03   ` Linus Lüssing
2013-11-05 13:14     ` Simon Wunderlich [this message]
2013-11-05  0:17   ` Linus Lüssing
2013-10-30 14:01 ` [B.A.T.M.A.N.] [PATCHv2 4/8] batman-adv: add WiFi penalty Simon Wunderlich
2013-10-30 14:01 ` [B.A.T.M.A.N.] [PATCHv2 5/8] batman-adv: consider outgoing interface in OGM sending Simon Wunderlich
2013-10-30 14:01 ` [B.A.T.M.A.N.] [PATCHv2 6/8] batman-adv: add bonding again Simon Wunderlich
2013-10-30 14:01 ` [B.A.T.M.A.N.] [PATCHv2 7/8] batman-adv: add debugfs structure for information per interface Simon Wunderlich
2013-10-30 14:01 ` [B.A.T.M.A.N.] [PATCHv2 8/8] batman-adv: add debugfs support to view multiif tables Simon Wunderlich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201311051414.02525.sw@simonwunderlich.de \
    --to=sw@simonwunderlich.de \
    --cc=b.a.t.m.a.n@lists.open-mesh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox