netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ahmed Amamou <ahmed@gandi.net>
To: netdev@vger.kernel.org
Cc: William Dauchy <william@gandi.net>,
	Ahmed Amamou <ahmed@gandi.net>, Kamel Haddadou <kamel@gandi.net>
Subject: [PATCH RFC v2 19/21] net: rbridge: add rbr_multidest_fwd
Date: Tue,  1 Sep 2015 17:43:14 +0200	[thread overview]
Message-ID: <1441122196-11662-20-git-send-email-ahmed@gandi.net> (raw)
In-Reply-To: <1441122196-11662-1-git-send-email-ahmed@gandi.net>

For multidest trill frame use multiple unicast forward to all
adjacency on the distributed tree when called while encapsulating
original frame need to be freed as it was already flooded to all
local access port for recv function when using multdestination
forward, the original frame has to be saved in order to be
decapsulated locally

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>

Conflicts:
	net/bridge/rbr.c
---
 net/bridge/rbr.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 98 insertions(+), 2 deletions(-)

diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
index ab71e6b..23f3e1d 100644
--- a/net/bridge/rbr.c
+++ b/net/bridge/rbr.c
@@ -214,6 +214,100 @@ dest_fwd_fail:
 	kfree_skb(skb);
 }
 
+static int rbr_multidest_fwd(struct net_bridge_port *p,
+			     struct sk_buff *skb, u16 egressnick,
+			     u16 ingressnick, const u8 *saddr,
+			     u16 vid, bool free)
+{
+	struct rbr *rbr;
+	struct rbr_node *dest;
+	struct rbr_node *adj;
+	struct sk_buff *skb2;
+	u16 adjnicksaved = 0;
+	u16 adjnick;
+	bool nicksaved = false;
+	unsigned int i;
+
+	if (unlikely(!p)) {
+		pr_warn_ratelimited("rbr_multidest_fwd: port error\n");
+		goto multidest_fwd_fail;
+	}
+
+	rbr = p->br->rbr;
+	if (unlikely(!rbr))
+		goto multidest_fwd_fail;
+
+	/* Lookup the egress nick info, this is the DT root */
+	dest = rbr_find_node(rbr, egressnick);
+	if (!dest) {
+		pr_warn_ratelimited
+		    ("rbr_multidest_fwd: unable to find egress\n");
+		goto multidest_fwd_fail;
+	}
+
+	/* Send a copy to all our adjacencies on the DT root */
+	for (i = 0; i < dest->rbr_ni->adjcount; i++) {
+		/* Check for a valid adjacency node */
+		adjnick = RBR_NI_ADJNICK(dest->rbr_ni, i);
+		adj = rbr_find_node(rbr, adjnick);
+		if (!VALID_NICK(adjnick) || ingressnick == adjnick ||
+		    (!adj))
+			continue;
+		/* Do not forward back to adjacency that sent the pkt to us */
+		if ((saddr) &&
+		    (ether_addr_equal_unaligned(adj->rbr_ni->adjsnpa,
+						saddr))) {
+			rbr_node_put(adj);
+			continue;
+		}
+
+		/* save the first found adjacency to avoid coping SKB
+		 * if no other adjacency is found later no frame copy
+		 * will be made if other adjacency will be found frame
+		 * will be copied and forwarded to them if skb is needed
+		 * after rbr_multidest_fwd copy of the first skb skb
+		 * will be forced
+		 */
+		if (!nicksaved && free) {
+			adjnicksaved = adjnick;
+			nicksaved = true;
+			rbr_node_put(adj);
+			continue;
+		}
+		/* FIXME using copy instead of clone as
+		 * we are going to modify dest address
+		 */
+		skb2 = skb_copy(skb, GFP_ATOMIC);
+		if (unlikely(!skb2)) {
+			p->br->dev->stats.tx_dropped++;
+			pr_warn_ratelimited
+			    ("rbr_multidest_fwd: skb_copy failed\n");
+			goto multidest_fwd_fail;
+		}
+		rbr_fwd(p, skb2, adjnick, vid);
+		rbr_node_put(adj);
+	}
+	rbr_node_put(dest);
+
+	/* if nicksave is false it means that copy will not be forwarded
+	 * as no availeble ajacency was found in such a case frame should
+	 * be dropped
+	 */
+
+	if (nicksaved)
+		rbr_fwd(p, skb, adjnicksaved, vid);
+	else
+		kfree_skb(skb);
+
+	return 0;
+
+ multidest_fwd_fail:
+	if (likely(p && p->br))
+		p->br->dev->stats.tx_dropped++;
+	kfree_skb(skb);
+	return -EINVAL;
+}
+
 static void rbr_encaps(struct sk_buff *skb, u16 egressnick, u16 vid)
 {
 	u16 local_nick;
@@ -272,7 +366,7 @@ static void rbr_encaps(struct sk_buff *skb, u16 egressnick, u16 vid)
 		br_flood_deliver_flags(p->br, skb2, true, TRILL_FLAG_ACCESS);
 		if (unlikely(add_header(skb, local_nick, dtnick, 1)))
 			goto encaps_drop;
-		/* TODO Multi forward */
+		rbr_multidest_fwd(p, skb, dtnick, local_nick, NULL, vid, true);
 	} else {
 		if (unlikely(add_header(skb, local_nick, egressnick, 0)))
 			goto encaps_drop;
@@ -504,7 +598,9 @@ static void rbr_recv(struct sk_buff *skb, u16 vid)
 		goto recv_drop;
 	}
 
-	/* TODO multi forwarding */
+	if (rbr_multidest_fwd(p, skb2, trh->th_egressnick, trh->th_ingressnick,
+			      eth_hdr(skb)->h_source, vid, false))
+		goto recv_drop;
 
 	/* Send de-capsulated frame locally */
 	rbr_decaps(p, skb, trhsize, vid);
-- 
2.1.4

  parent reply	other threads:[~2015-09-01 15:53 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
2015-09-01 15:42 ` [PATCH RFC v2 01/21] net: rbridge: add trill frame description Ahmed Amamou
2015-09-01 15:42 ` [PATCH RFC v2 02/21] net: rbridge: add layer 2 IS-IS Ethertype Ahmed Amamou
2015-09-01 15:42 ` [PATCH RFC v2 03/21] net: rbridge: add RBridge structure Ahmed Amamou
2015-09-01 15:42 ` [PATCH RFC v2 04/21] net: rbridge: add CONFIG_TRILL Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 05/21] net: rbridge: adapt Bridge structure Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 06/21] net: rbridge: enable/disable TRILL capability Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 07/21] net: rbridge: add sysfs for trill_state Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 08/21] net: rbridge: get Rbridge nickname from daemon Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 09/21] net: rbridge: add elected dtroot Ahmed Amamou
2015-09-01 18:18   ` Sergei Shtylyov
2015-09-01 18:26     ` ahmed amamou
2015-09-01 15:43 ` [PATCH RFC v2 10/21] net: rbridge: add rbr_node management function Ahmed Amamou
2015-09-01 18:30   ` Sergei Shtylyov
2015-09-01 15:43 ` [PATCH RFC v2 11/21] net: rbridge: clean up rbr_node on rbridge stop Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 12/21] net: rbridge: update node table Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 13/21] net: rbridge: add basic trill frame handling function Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 14/21] net: rbridge: update forwarding database Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 15/21] net: rbridge: add test on trill flag before flood Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 16/21] net: rbridge: add encapsulation process Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 17/21] net: rbridge: add receive function Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 18/21] net: rbridge: add rbr_fwd Ahmed Amamou
2015-09-01 15:43 ` Ahmed Amamou [this message]
2015-09-01 15:43 ` [PATCH RFC v2 20/21] net: rbridge: replace net_port rx_handler Ahmed Amamou
2015-09-01 15:43 ` [PATCH RFC v2 21/21] net: handle packet split for trill Ahmed Amamou

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=1441122196-11662-20-git-send-email-ahmed@gandi.net \
    --to=ahmed@gandi.net \
    --cc=kamel@gandi.net \
    --cc=netdev@vger.kernel.org \
    --cc=william@gandi.net \
    /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;
as well as URLs for NNTP newsgroup(s).