All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC v2 00/21] TRILL implementation
@ 2015-09-01 15:42 Ahmed Amamou
  2015-09-01 15:42 ` [PATCH RFC v2 01/21] net: rbridge: add trill frame description Ahmed Amamou
                   ` (20 more replies)
  0 siblings, 21 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:42 UTC (permalink / raw)
  To: netdev
  Cc: William Dauchy, Ahmed Amamou, François Cachereul,
	Sergei Shtylyov, Vlad Yasevich, Stephen Hemminger,
	Francois Romieu

Hi,

We have been working on a TRILL implementation in the Linux kernel for some
time now. We have sent a first RFC a year ago (already!) and we are back
with a second version; this time we will try to update more quicly according
to the comments.
The code has been pushed here https://github.com/Gandi/ktrill.git in the devel
branch (be careful this branch is constantly rebased!)
Attached a series of patch as a second request for comment. The code is
not perfect and probably still lacks of improvements.
It's a second request of comment in order to get some feedbacks. This code has been
tested for some time now.

These patch tries to implement TRILL protocol RFC 6325.
As a first implementation, some RFC details are still not implemented.

In order to test these patches please follow the instruction:
download quagga (userland) from here https://github.com/Gandi/quagga.git
compile it using these options

./bootstrap.sh && ./configure --localstatedir=/var/run/quagga \
--enable-isisd --enable-trilld --enable-trilld-monitoring --disable-ipv6 \
--disable-ospfd --disable-ospfclient --disable-ripd --disable-babeld \
--disable-bgpd && make && make install

start zebra and trilld
$ zebra -f $ZEBRA_CONF -P 2121 -u quagga -d
$ trilld -f $TRILLD_CONF -P 2021 -u quagga -d

Configuration sample can be found here
https://github.com/Gandi/quagga/blob/dev_trill/zebra/zebra.conf.sample
and here https://github.com/Gandi/quagga/blob/dev_trill/isisd/trilld.conf.sample

Finally you need to correctly configure bridge port
For access port (native frames)
echo 4 > /sys/class/net/<INTERFACE>/brport/trill_state
For trunk port (trill frame and control frames)
echo 8 > /sys/class/net/<INTERFACE>/brport/trill_state
more detail can be found here: https://github.com/Gandi/ktrill/wiki
NB: for port state github version has different flags as we did not take
into consideration all port flag when implementing it

---
Changes in V2:
- rebase on v4.2 tag
- replace genl netlink by rtnetlink
- each port will either have TRILL or bridge packet handler
  deponding on bridge status in version 0 all port used to
  have a unique handler that fallback to bridge handler if
  trill is not enabled
- remove usesless locks
- remove all format errors
- handle TRILL packets within packet split process


Ahmed Amamou (19):
  net: rbridge: add trill frame description
  net: rbridge: add RBridge structure
  net: rbridge: add CONFIG_TRILL
  net: rbridge: adapt Bridge structure
  net: rbridge: enable/disable TRILL capability
  net: rbridge: add sysfs for trill_state
  net: rbridge: get Rbridge nickname from daemon
  net: rbridge: add elected dtroot
  net: rbridge: add rbr_node management function
  net: rbridge: clean up rbr_node on rbridge stop
  net: rbridge: update node table
  net: rbridge: add basic trill frame handling function
  net: rbridge: update forwarding database
  net: rbridge: add test on trill flag before flood
  net: rbridge: add encapsulation process
  net: rbridge: add receive function
  net: rbridge: add rbr_fwd
  net: rbridge: add rbr_multidest_fwd
  net: rbridge: replace net_port rx_handler

François Cachereul (1):
  net: rbridge: add layer 2 IS-IS Ethertype

William Dauchy (1):
  net: handle packet split for trill

 include/linux/etherdevice.h   |  17 +
 include/net/if_trill.h        |  88 ++++++
 include/uapi/linux/if_ether.h |   2 +
 include/uapi/linux/if_link.h  |   6 +
 net/bridge/Kconfig            |   8 +
 net/bridge/Makefile           |   2 +
 net/bridge/br_fdb.c           |  41 +++
 net/bridge/br_forward.c       |  37 ++-
 net/bridge/br_if.c            |   7 +-
 net/bridge/br_netlink.c       |  10 +-
 net/bridge/br_private.h       |  53 ++++
 net/bridge/br_sysfs_br.c      |  38 +++
 net/bridge/br_sysfs_if.c      |  26 ++
 net/bridge/rbr.c              | 718 ++++++++++++++++++++++++++++++++++++++++++
 net/bridge/rbr_private.h      |  85 +++++
 net/bridge/rbr_rtnetlink.c    |  93 ++++++
 net/core/flow_dissector.c     |  31 ++
 17 files changed, 1259 insertions(+), 3 deletions(-)
 create mode 100644 include/net/if_trill.h
 create mode 100644 net/bridge/rbr.c
 create mode 100644 net/bridge/rbr_private.h
 create mode 100644 net/bridge/rbr_rtnetlink.c

-- 
2.1.4

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 01/21] net: rbridge: add trill frame description
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
@ 2015-09-01 15:42 ` Ahmed Amamou
  2015-09-01 15:42 ` [PATCH RFC v2 02/21] net: rbridge: add layer 2 IS-IS Ethertype Ahmed Amamou
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:42 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Emmanuel Hocdet, Kamel Haddadou

add basic trill header description and basic header getter and setter
functions

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Emmanuel Hocdet <manu@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
---
 include/net/if_trill.h        | 88 +++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/if_ether.h |  1 +
 2 files changed, 89 insertions(+)
 create mode 100644 include/net/if_trill.h

diff --git a/include/net/if_trill.h b/include/net/if_trill.h
new file mode 100644
index 0000000..c4caf58
--- /dev/null
+++ b/include/net/if_trill.h
@@ -0,0 +1,88 @@
+#ifndef _LINUX_IF_TRILL_H_
+#define _LINUX_IF_TRILL_H_
+
+#include <linux/types.h>
+
+/* trill_hdr structure
+ *                                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *                                | V | R |M|op-Length| Hop Count |
+ *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *|  Egress RBridge Nickname      |    Ingress RBridge Nickname   |
+ *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+struct trill_hdr {
+	__be16 th_flags;
+	__be16 th_egressnick;
+	__be16 th_ingressnick;
+} __packed;
+
+static inline u16 trill_get_version(u16 trill_flags)
+{
+	return (trill_flags >> 14) & 0x0003;
+}
+
+static inline u16 trill_set_version(u16 trill_flags, u16 v)
+{
+	trill_flags |= (v & 0x0003) << 14;
+	return trill_flags;
+}
+
+static inline u16 trill_get_reserved(u16 trill_flags)
+{
+	return (trill_flags >> 12) & 0x0003;
+}
+
+static inline u16 trill_set_reserved(u16 trill_flags, u16 v)
+{
+	trill_flags |= (v & 0x0003) << 12;
+	return trill_flags;
+}
+
+static inline u16 trill_get_multidest(u16 trill_flags)
+{
+	return (trill_flags >> 11) & 0x0001;
+}
+
+static inline u16 trill_set_multidest(u16 trill_flags, u16 flag)
+{
+	trill_flags |= (flag & 0x0001) << 11;
+	return trill_flags;
+}
+
+/* len is in 4 bytes units << 2*/
+static inline size_t trill_get_optslen(u16 trill_flags)
+{
+	return ((trill_flags >> 6) & 0x001F) << 2;
+}
+
+static inline u16 trill_set_optslen(u16 trill_flags, u16 len)
+{
+	trill_flags |= ((len >> 2) & 0x001F) << 6;
+	return trill_flags;
+}
+
+static inline u16 trill_get_hopcount(u16 trill_flags)
+{
+	return trill_flags & 0x003F;
+}
+
+static inline u16 trill_set_hopcount(u16 trill_flags, u16 count)
+{
+	trill_flags |= count & 0x003F;
+	return trill_flags;
+}
+
+static inline void trillhdr_dec_hopcount(struct trill_hdr *trh)
+{
+	u8 *flags = (u8 *) &trh->th_flags;
+
+	if (flags[1] & 0x3F)
+		flags[1] -= 1;
+}
+
+static inline size_t trill_header_len(struct trill_hdr *trh)
+{
+	return sizeof(*trh) + trill_get_optslen(ntohs(trh->th_flags));
+}
+#endif /* _LINUX_IF_TRILL_H_ */
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index aa63ed0..5cd75b6 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -48,6 +48,7 @@
 #define	ETH_P_BPQ	0x08FF		/* G8BPQ AX.25 Ethernet Packet	[ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_IEEEPUP	0x0a00		/* Xerox IEEE802.3 PUP packet */
 #define ETH_P_IEEEPUPAT	0x0a01		/* Xerox IEEE802.3 PUP Addr Trans packet */
+#define ETH_P_TRILL	0x22F3		/* TRILL frames RFC 6325 */
 #define ETH_P_BATMAN	0x4305		/* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_DEC       0x6000          /* DEC Assigned proto           */
 #define ETH_P_DNA_DL    0x6001          /* DEC DNA Dump/Load            */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 02/21] net: rbridge: add layer 2 IS-IS Ethertype
  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 ` Ahmed Amamou
  2015-09-01 15:42 ` [PATCH RFC v2 03/21] net: rbridge: add RBridge structure Ahmed Amamou
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:42 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, François Cachereul

From: François Cachereul <f.cachereul@alphalink.fr>

Signed-off-by: François Cachereul <f.cachereul@alphalink.fr>
Signed-off-by: William Dauchy <william@gandi.net>
Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
---
 include/uapi/linux/if_ether.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 5cd75b6..b071bb4 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -49,6 +49,7 @@
 #define ETH_P_IEEEPUP	0x0a00		/* Xerox IEEE802.3 PUP packet */
 #define ETH_P_IEEEPUPAT	0x0a01		/* Xerox IEEE802.3 PUP Addr Trans packet */
 #define ETH_P_TRILL	0x22F3		/* TRILL frames RFC 6325 */
+#define ETH_P_L2_ISIS	0x22F4		/* L2-IS-IS frames RFC 6325 */
 #define ETH_P_BATMAN	0x4305		/* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_DEC       0x6000          /* DEC Assigned proto           */
 #define ETH_P_DNA_DL    0x6001          /* DEC DNA Dump/Load            */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 03/21] net: rbridge: add RBridge structure
  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 ` Ahmed Amamou
  2015-09-01 15:42 ` [PATCH RFC v2 04/21] net: rbridge: add CONFIG_TRILL Ahmed Amamou
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:42 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

add basic RBridge structure
add basic TRILL constant
define rbr_nickinfo structure which represent distant RBridge information

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
---
 net/bridge/rbr_private.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 net/bridge/rbr_private.h

diff --git a/net/bridge/rbr_private.h b/net/bridge/rbr_private.h
new file mode 100644
index 0000000..8d9fb4c
--- /dev/null
+++ b/net/bridge/rbr_private.h
@@ -0,0 +1,60 @@
+#ifndef _RBR_PRIVATE_H
+#define _RBR_PRIVATE_H
+
+#include <linux/atomic.h>
+
+#define	RBRIDGE_NICKNAME_MIN	0x0000
+#define	RBRIDGE_NICKNAME_MAX	0xFFFF
+
+/* Define well-known nicknames */
+#define	RBRIDGE_NICKNAME_NONE	RBRIDGE_NICKNAME_MIN
+#define	RBRIDGE_NICKNAME_UNUSED	RBRIDGE_NICKNAME_MAX
+
+#define	TRILL_PROTOCOL_VERS 0	/* th_version */
+#define	TRILL_DEFAULT_HOPS 21	/* th_hopcount */
+#define VALID_NICK(n)	((n) != RBRIDGE_NICKNAME_NONE && \
+			(n) != RBRIDGE_NICKNAME_UNUSED)
+
+struct rbr_nickinfo {
+	/* Nickname of the RBridge */
+	u16 nick;
+	/* Next-hop SNPA address to reach this RBridge */
+	u8 adjsnpa[ETH_ALEN];
+	/* Link on our system to use to reach next-hop */
+	u32 linkid;
+	/* Num of *our* adjacencies on a tree rooted at this RBridge */
+	u16 adjcount;
+	/* Num of distribution tree root nicks chosen by this RBridge */
+	u16 dtrootcount;
+	/* Variable size bytes to store adjacency nicks, distribution
+	 * tree roots. Adjacency nicks and
+	 * distribution tree roots are 16-bit fields.
+	 */
+};
+
+struct rbr_node {
+	struct rbr_nickinfo *rbr_ni;
+	atomic_t refs;		/* reference count */
+};
+
+struct rbr {
+	u16 nick;		/* our nickname */
+	u16 treeroot;	/* tree root nickname */
+	struct rbr_node *rbr_nodes[RBRIDGE_NICKNAME_MAX];
+	struct net_bridge *br;	/* back pointer */
+};
+
+/* Access the adjacency nick list at the end of rbr_nickinfo */
+#define	RBR_NI_ADJNICKSPTR(v) ((u16 *)((struct rbr_nickinfo *)(v) + 1))
+#define	RBR_NI_ADJNICK(v, n) (RBR_NI_ADJNICKSPTR(v)[(n)])
+
+/* Access the DT root nick list in rbr_nickinfo after adjacency nicks */
+#define	RBR_NI_DTROOTNICKSPTR(v) (RBR_NI_ADJNICKSPTR(v) + (v)->adjcount)
+#define	RBR_NI_DTROOTNICK(v, n) (RBR_NI_DTROOTNICKSPTR(v)[(n)])
+
+#define	RBR_NI_TOTALSIZE(v) (\
+		(sizeof(struct rbr_nickinfo)) + \
+		(sizeof(u16) * (v)->adjcount) + \
+		(sizeof(u16) * (v)->dtrootcount)\
+		)
+#endif
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 04/21] net: rbridge: add CONFIG_TRILL
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (2 preceding siblings ...)
  2015-09-01 15:42 ` [PATCH RFC v2 03/21] net: rbridge: add RBridge structure Ahmed Amamou
@ 2015-09-01 15:42 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 05/21] net: rbridge: adapt Bridge structure Ahmed Amamou
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:42 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

add TRILL option kconfig file in order to enable RBridge feature
in linux Bridge

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
---
 net/bridge/Kconfig | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig
index aa0d3b2..2381567 100644
--- a/net/bridge/Kconfig
+++ b/net/bridge/Kconfig
@@ -60,3 +60,11 @@ config BRIDGE_VLAN_FILTERING
 	  Say N to exclude this support and reduce the binary size.
 
 	  If unsure, say Y.
+
+config TRILL
+	bool "Enable RBridge capabilities (RFC6325) (EXPERIMENTAL)"
+	depends on BRIDGE
+	default n
+	---help---
+	  enable trill option on bridge to get Rbridge
+	  If unsure, say N.
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 05/21] net: rbridge: adapt Bridge structure
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (3 preceding siblings ...)
  2015-09-01 15:42 ` [PATCH RFC v2 04/21] net: rbridge: add CONFIG_TRILL Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 06/21] net: rbridge: enable/disable TRILL capability Ahmed Amamou
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev
  Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou, François Cachereul

change bridge structure to add corresponding RBridge reference
change bridge port structure to identify disable /P2P/ ACCESS / TRUNK port/

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
Signed-off-by: François Cachereul <f.cachereul@alphalink.fr>
Signed-off-by: William Dauchy <william@gandi.net>
---
 net/bridge/br_private.h | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8b21146..ff757da 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -20,6 +20,9 @@
 #include <net/route.h>
 #include <net/ip6_fib.h>
 #include <linux/if_vlan.h>
+#ifdef CONFIG_TRILL
+#include "rbr_private.h"
+#endif
 
 #define BR_HASH_BITS 8
 #define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -32,6 +35,19 @@
 
 #define BR_VERSION	"2.3"
 
+#ifdef CONFIG_TRILL
+  /* TRILL flagged ports are ports where we expect
+   * receiving native layer 2 frames
+   */
+#define TRILL_FLAG_DISABLE	0x1
+#define TRILL_FLAG_P2P		0x2
+#define TRILL_FLAG_ACCESS	0x4
+#define TRILL_FLAG_TRUNK	0x8	/* DROP ALL native L2 frame */
+/* Bridge TRILL state */
+#define BR_NO_TRILL		0	/* no trill  */
+#define BR_TRILL		1	/* trill enabled */
+#endif
+
 /* Control of forwarding link local multicast */
 #define BR_GROUPFWD_DEFAULT	0
 /* Don't allow forwarding of control protocols like STP, MAC PAUSE and LACP */
@@ -165,6 +181,11 @@ struct net_bridge_port
 	struct rcu_head			rcu;
 
 	unsigned long 			flags;
+	/* Trill */
+#ifdef CONFIG_TRILL
+	u8				trill_flag;
+#endif /* CONFIG_TRILL */
+
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 	struct bridge_mcast_own_query	ip4_own_query;
@@ -248,6 +269,11 @@ struct net_bridge
 		BR_USER_STP,		/* new RSTP in userspace */
 	} stp_enabled;
 
+#ifdef CONFIG_TRILL
+	bool				trill_enabled;
+	struct rbr			*rbr;
+#endif
+
 	unsigned char			topology_change;
 	unsigned char			topology_change_detected;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 06/21] net: rbridge: enable/disable TRILL capability
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (4 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 05/21] net: rbridge: adapt Bridge structure Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 07/21] net: rbridge: add sysfs for trill_state Ahmed Amamou
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

enable switching TRILL capability state via sysfs command

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
---
 net/bridge/Makefile     |  2 ++
 net/bridge/br_private.h |  5 ++++
 net/bridge/rbr.c        | 71 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+)
 create mode 100644 net/bridge/rbr.c

diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index a1cda5d..27da487 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -21,3 +21,5 @@ bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o
 bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o
 
 obj-$(CONFIG_NETFILTER) += netfilter/
+
+bridge-$(CONFIG_TRILL) += rbr.o
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index ff757da..67da2ae 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -834,6 +834,11 @@ int br_stp_set_port_priority(struct net_bridge_port *p, unsigned long newprio);
 int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost);
 ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id);
 
+/* rbr.c */
+#ifdef CONFIG_TRILL
+void br_trill_set_enabled(struct net_bridge *br, unsigned long val);
+#endif
+
 /* br_stp_bpdu.c */
 struct stp_proto;
 void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
new file mode 100644
index 0000000..c554743
--- /dev/null
+++ b/net/bridge/rbr.c
@@ -0,0 +1,71 @@
+/*
+ *	Generic parts
+ *	Linux ethernet Rbridge
+ *
+ *	Authors:
+ *	Ahmed AMAMOU	<ahmed@gandi.net>
+ *	Kamel Haddadou	<kamel@gandi.net>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+#include "br_private.h"
+#include "rbr_private.h"
+
+static struct rbr *add_rbr(struct net_bridge *br)
+{
+	struct rbr *rbr;
+
+	if (!br->rbr) {
+		rbr = kzalloc(sizeof(*rbr), GFP_KERNEL);
+		if (!rbr)
+			return NULL;
+
+		rbr->br = br;
+		rbr->nick = RBRIDGE_NICKNAME_NONE;
+		rbr->treeroot = RBRIDGE_NICKNAME_NONE;
+		return rbr;
+	}
+
+	return br->rbr;
+}
+
+static void br_trill_start(struct net_bridge *br)
+{
+	/* Disable STP if it is already enabled */
+
+	if (br->stp_enabled != BR_NO_STP)
+		br_stp_set_enabled(br, false);
+	br->rbr = add_rbr(br);
+	if (br->rbr)
+		br->trill_enabled = BR_TRILL;
+	else
+		pr_warn("RBridge allocation for bridge '%s' failed\n",
+			br->dev->name);
+}
+
+static void br_trill_stop(struct net_bridge *br)
+{
+	struct rbr *old;
+
+	spin_lock_bh(&br->lock);
+	br->trill_enabled = BR_NO_TRILL;
+	spin_unlock_bh(&br->lock);
+	old = br->rbr;
+	br->rbr = NULL;
+	if (likely(old))
+		kfree(old);
+}
+
+void br_trill_set_enabled(struct net_bridge *br, unsigned long val)
+{
+	if (val) {
+		if (br->trill_enabled == BR_NO_TRILL)
+			br_trill_start(br);
+	} else {
+		if (br->trill_enabled != BR_NO_TRILL)
+			br_trill_stop(br);
+	}
+}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 07/21] net: rbridge: add sysfs for trill_state
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (5 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 06/21] net: rbridge: enable/disable TRILL capability Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 08/21] net: rbridge: get Rbridge nickname from daemon Ahmed Amamou
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou

in order to activate trill port without need for brctl
add a sysfs for trill_state for net_bridge_port

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
---
 net/bridge/br_sysfs_br.c | 38 ++++++++++++++++++++++++++++++++++++++
 net/bridge/br_sysfs_if.c | 26 ++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)

diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 4c97fc5..63820c1 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -146,6 +146,41 @@ static ssize_t stp_state_store(struct device *d,
 }
 static DEVICE_ATTR_RW(stp_state);
 
+#ifdef CONFIG_TRILL
+static ssize_t trill_state_show(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct net_bridge *br = to_bridge(d);
+
+	return sprintf(buf, "%d\n", br->trill_enabled);
+}
+
+static ssize_t trill_state_store(struct device *d,
+				 struct device_attribute *attr, const char *buf,
+				 size_t len)
+{
+	struct net_bridge *br = to_bridge(d);
+	int err;
+	unsigned long val;
+
+	if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
+		return -EPERM;
+
+	err = kstrtoul(buf, 0, &val);
+	if (err)
+		return err;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+	br_trill_set_enabled(br, val);
+	rtnl_unlock();
+
+	return len;
+}
+
+static DEVICE_ATTR_RW(trill_state);
+#endif
+
 static ssize_t group_fwd_mask_show(struct device *d,
 				   struct device_attribute *attr,
 				   char *buf)
@@ -749,6 +784,9 @@ static struct attribute *bridge_attrs[] = {
 	&dev_attr_max_age.attr,
 	&dev_attr_ageing_time.attr,
 	&dev_attr_stp_state.attr,
+#ifdef CONFIG_TRILL
+	&dev_attr_trill_state.attr,
+#endif
 	&dev_attr_group_fwd_mask.attr,
 	&dev_attr_priority.attr,
 	&dev_attr_bridge_id.attr,
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index efe415a..174a705 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -137,6 +137,29 @@ static ssize_t show_port_state(struct net_bridge_port *p, char *buf)
 }
 static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL);
 
+#ifdef CONFIG_TRILL
+
+static ssize_t show_port_trill_state(struct net_bridge_port *p, char *buf)
+{
+	return sprintf(buf, "%d\n", p->trill_flag);
+}
+
+static int store_port_trill_state(struct net_bridge_port *p,  unsigned long v)
+{
+	u8 val;
+
+	if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN))
+		return -EPERM;
+	val = (u8)v;
+	if (val > TRILL_FLAG_TRUNK)
+		return -ERANGE;
+	p->trill_flag = val;
+	return 0;
+}
+static BRPORT_ATTR(trill_state, S_IRUGO | S_IWUSR, show_port_trill_state,
+				   store_port_trill_state);
+#endif
+
 static ssize_t show_message_age_timer(struct net_bridge_port *p,
 					    char *buf)
 {
@@ -200,6 +223,9 @@ static const struct brport_attribute *brport_attrs[] = {
 	&brport_attr_designated_port,
 	&brport_attr_designated_cost,
 	&brport_attr_state,
+#ifdef CONFIG_TRILL
+	&brport_attr_trill_state,
+#endif
 	&brport_attr_change_ack,
 	&brport_attr_config_pending,
 	&brport_attr_message_age_timer,
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 08/21] net: rbridge: get Rbridge nickname from daemon
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (6 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 07/21] net: rbridge: add sysfs for trill_state Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 09/21] net: rbridge: add elected dtroot Ahmed Amamou
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
---
 include/uapi/linux/if_link.h |  6 ++++++
 net/bridge/Makefile          |  2 +-
 net/bridge/br_netlink.c      | 10 +++++++++-
 net/bridge/br_private.h      |  6 ++++++
 net/bridge/rbr_rtnetlink.c   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 66 insertions(+), 2 deletions(-)
 create mode 100644 net/bridge/rbr_rtnetlink.c

diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 2c7e8e3..07a3f01 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -229,6 +229,12 @@ enum {
 	IFLA_BR_AGEING_TIME,
 	IFLA_BR_STP_STATE,
 	IFLA_BR_PRIORITY,
+#ifdef CONFIG_TRILL
+/* TRILL section */
+	IFLA_TRILL_NICKNAME,
+	IFLA_TRILL_ROOT,
+	IFLA_TRILL_INFO,
+#endif
 	__IFLA_BR_MAX,
 };
 
diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index 27da487..472dc24 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -22,4 +22,4 @@ bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o
 
 obj-$(CONFIG_NETFILTER) += netfilter/
 
-bridge-$(CONFIG_TRILL) += rbr.o
+bridge-$(CONFIG_TRILL) += rbr.o rbr_rtnetlink.o
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 4d74a06..def0ea3 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -730,6 +730,11 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = {
 	[IFLA_BR_AGEING_TIME] = { .type = NLA_U32 },
 	[IFLA_BR_STP_STATE] = { .type = NLA_U32 },
 	[IFLA_BR_PRIORITY] = { .type = NLA_U16 },
+#ifdef CONFIG_TRILL
+	[IFLA_TRILL_NICKNAME]   = { .type = NLA_U16 },
+	[IFLA_TRILL_ROOT]       = { .type = NLA_U16 },
+	[IFLA_TRILL_INFO]       = { .type = NLA_BINARY },
+#endif
 };
 
 static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
@@ -776,8 +781,11 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
 
 		br_stp_set_bridge_priority(br, priority);
 	}
+#ifdef CONFIG_TRILL
+	err = rbr_set_data(brdev, tb, data);
+#endif
 
-	return 0;
+	return err;
 }
 
 static size_t br_get_size(const struct net_device *brdev)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 67da2ae..ceaf5a9 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -864,6 +864,12 @@ int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
 int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev,
 	       u32 filter_mask, int nlflags);
 
+#ifdef CONFIG_TRILL
+/* rbr_netlink.c */
+int rbr_set_data(struct net_device *dev, struct nlattr *tb[],
+		 struct nlattr *data[]);
+#endif
+
 #ifdef CONFIG_SYSFS
 /* br_sysfs_if.c */
 extern const struct sysfs_ops brport_sysfs_ops;
diff --git a/net/bridge/rbr_rtnetlink.c b/net/bridge/rbr_rtnetlink.c
new file mode 100644
index 0000000..d75d45c
--- /dev/null
+++ b/net/bridge/rbr_rtnetlink.c
@@ -0,0 +1,44 @@
+/*
+ *	Generic parts
+ *	Linux ethernet Rbridge
+ *
+ *	Authors:
+ *	Ahmed AMAMOU	<ahmed@gandi.net>
+ *	William Dauchy	<william@gandi.net>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+
+#include <net/rtnetlink.h>
+#include "br_private.h"
+#include "rbr_private.h"
+
+int rbr_set_data(struct net_device *dev, struct nlattr *tb[],
+		 struct nlattr *data[])
+{
+	struct net_bridge *br = netdev_priv(dev);
+	u16 nick;
+	int err = -ENOMEM;
+
+	if (!br)
+		return -EINVAL;
+
+	if (data[IFLA_TRILL_NICKNAME]) {
+		nick =  nla_get_u16(data[IFLA_TRILL_NICKNAME]);
+		if (br->trill_enabled == BR_NO_TRILL)
+			br_trill_set_enabled(br, 1);
+
+		spin_lock_bh(&br->lock);
+		if (VALID_NICK(nick))
+			br->rbr->nick = htons(nick);
+		spin_unlock_bh(&br->lock);
+	}
+
+	return 0;
+fail:
+	pr_warn("rbr_set_data FAILED\n");
+	return err;
+}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 09/21] net: rbridge: add elected dtroot
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (7 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 08/21] net: rbridge: get Rbridge nickname from daemon Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 18:18   ` Sergei Shtylyov
  2015-09-01 15:43 ` [PATCH RFC v2 10/21] net: rbridge: add rbr_node management function Ahmed Amamou
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
---
 net/bridge/rbr.c           | 14 ++++++++++++++
 net/bridge/rbr_private.h   |  2 ++
 net/bridge/rbr_rtnetlink.c |  6 ++++++
 3 files changed, 22 insertions(+)

diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
index c554743..31e72ef 100644
--- a/net/bridge/rbr.c
+++ b/net/bridge/rbr.c
@@ -69,3 +69,17 @@ void br_trill_set_enabled(struct net_bridge *br, unsigned long val)
 			br_trill_stop(br);
 	}
 }
+
+int set_treeroot(struct rbr *rbr, uint16_t treeroot)
+{
+	if (unlikely(!VALID_NICK(treeroot))) {
+		pr_warn_ratelimited
+			("rbr_set_treeroot: given tree root not valid\n");
+		goto set_tree_root_fail;
+	}
+	if (rbr->treeroot != treeroot)
+		rbr->treeroot = treeroot;
+	return 0;
+ set_tree_root_fail:
+	return -ENOENT;
+}
diff --git a/net/bridge/rbr_private.h b/net/bridge/rbr_private.h
index 8d9fb4c..9166a8b 100644
--- a/net/bridge/rbr_private.h
+++ b/net/bridge/rbr_private.h
@@ -44,6 +44,8 @@ struct rbr {
 	struct net_bridge *br;	/* back pointer */
 };
 
+int set_treeroot(struct rbr *rbr, uint16_t treeroot);
+
 /* Access the adjacency nick list at the end of rbr_nickinfo */
 #define	RBR_NI_ADJNICKSPTR(v) ((u16 *)((struct rbr_nickinfo *)(v) + 1))
 #define	RBR_NI_ADJNICK(v, n) (RBR_NI_ADJNICKSPTR(v)[(n)])
diff --git a/net/bridge/rbr_rtnetlink.c b/net/bridge/rbr_rtnetlink.c
index d75d45c..5b6dab4 100644
--- a/net/bridge/rbr_rtnetlink.c
+++ b/net/bridge/rbr_rtnetlink.c
@@ -36,6 +36,12 @@ int rbr_set_data(struct net_device *dev, struct nlattr *tb[],
 			br->rbr->nick = htons(nick);
 		spin_unlock_bh(&br->lock);
 	}
+	if (data[IFLA_TRILL_ROOT]) {
+		if (!br->rbr)
+			return -EINVAL;
+		nick = nla_get_u16(data[IFLA_TRILL_ROOT]);
+		err = set_treeroot(br->rbr, htons(nick));
+	}
 
 	return 0;
 fail:
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 10/21] net: rbridge: add rbr_node management function
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (8 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 09/21] net: rbridge: add elected dtroot Ahmed Amamou
@ 2015-09-01 15:43 ` 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
                   ` (10 subsequent siblings)
  20 siblings, 1 reply; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

rbr_node are used to save distant Rbridges information
they are use by local Rbridge to take routing decision
this patch add get/put/free/find/del  function to rbr_node to
avoid freeing a rbr_node that is still in use for routing

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
---
 net/bridge/rbr.c         | 35 +++++++++++++++++++++++++++++++++++
 net/bridge/rbr_private.h | 23 +++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
index 31e72ef..718deb3 100644
--- a/net/bridge/rbr.c
+++ b/net/bridge/rbr.c
@@ -83,3 +83,38 @@ int set_treeroot(struct rbr *rbr, uint16_t treeroot)
  set_tree_root_fail:
 	return -ENOENT;
 }
+
+struct rbr_node *rbr_find_node(struct rbr *rbr, __u16 nickname)
+{
+	struct rbr_node *rbr_node;
+
+	if (unlikely(!VALID_NICK(nickname)))
+		return NULL;
+	rbr_node = rcu_dereference(rbr->rbr_nodes[nickname]);
+	rbr_node_get(rbr_node);
+
+	return rbr_node;
+}
+
+static void rbr_del_node(struct rbr *rbr, uint16_t nickname)
+{
+	struct rbr_node *rbr_node;
+
+	if (likely(VALID_NICK(nickname))) {
+		rbr_node = rbr->rbr_nodes[nickname];
+		if (likely(rbr_node)) {
+			rcu_assign_pointer(rbr->rbr_nodes[nickname], NULL);
+			rbr_node_put(rbr_node);
+		}
+	}
+}
+
+static void rbr_del_all(struct rbr *rbr)
+{
+	unsigned int i;
+
+	for (i = RBRIDGE_NICKNAME_MIN; i < RBRIDGE_NICKNAME_MAX; i++) {
+		if (likely(rbr->rbr_nodes[i]))
+			rbr_del_node(rbr, i);
+	}
+}
diff --git a/net/bridge/rbr_private.h b/net/bridge/rbr_private.h
index 9166a8b..186e454 100644
--- a/net/bridge/rbr_private.h
+++ b/net/bridge/rbr_private.h
@@ -44,7 +44,30 @@ struct rbr {
 	struct net_bridge *br;	/* back pointer */
 };
 
+static inline void rbr_node_free(struct rbr_node *rbr_node)
+{
+	if (likely(rbr_node)) {
+		kfree(rbr_node->rbr_ni);
+		kfree(rbr_node);
+	}
+}
+
+static inline void rbr_node_get(struct rbr_node *rbr_node)
+{
+	if (likely(rbr_node))
+		atomic_inc(&rbr_node->refs);
+}
+
+static inline void rbr_node_put(struct rbr_node *rbr_node)
+{
+	if (rbr_node) {
+		if (unlikely(atomic_dec_and_test(&rbr_node->refs)))
+			rbr_node_free(rbr_node);
+	}
+}
+
 int set_treeroot(struct rbr *rbr, uint16_t treeroot);
+struct rbr_node *rbr_find_node(struct rbr *rbr, __u16 nickname);
 
 /* Access the adjacency nick list at the end of rbr_nickinfo */
 #define	RBR_NI_ADJNICKSPTR(v) ((u16 *)((struct rbr_nickinfo *)(v) + 1))
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 11/21] net: rbridge: clean up rbr_node on rbridge stop
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (9 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 10/21] net: rbridge: add rbr_node management function Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 12/21] net: rbridge: update node table Ahmed Amamou
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

In order to avoid memleak need to clean all rbr_node once rbridge is
stopped

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
---
 net/bridge/rbr.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
index 718deb3..67842fe 100644
--- a/net/bridge/rbr.c
+++ b/net/bridge/rbr.c
@@ -13,6 +13,7 @@
  */
 #include "br_private.h"
 #include "rbr_private.h"
+static void rbr_del_all(struct rbr *rbr);
 
 static struct rbr *add_rbr(struct net_bridge *br)
 {
@@ -55,8 +56,10 @@ static void br_trill_stop(struct net_bridge *br)
 	spin_unlock_bh(&br->lock);
 	old = br->rbr;
 	br->rbr = NULL;
-	if (likely(old))
+	if (likely(old)) {
+		rbr_del_all(old);
 		kfree(old);
+	}
 }
 
 void br_trill_set_enabled(struct net_bridge *br, unsigned long val)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 12/21] net: rbridge: update node table
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (10 preceding siblings ...)
  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 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 13/21] net: rbridge: add basic trill frame handling function Ahmed Amamou
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
---
 net/bridge/rbr_rtnetlink.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/net/bridge/rbr_rtnetlink.c b/net/bridge/rbr_rtnetlink.c
index 5b6dab4..23fd0d7 100644
--- a/net/bridge/rbr_rtnetlink.c
+++ b/net/bridge/rbr_rtnetlink.c
@@ -42,7 +42,50 @@ int rbr_set_data(struct net_device *dev, struct nlattr *tb[],
 		nick = nla_get_u16(data[IFLA_TRILL_ROOT]);
 		err = set_treeroot(br->rbr, htons(nick));
 	}
+	if (data[IFLA_TRILL_INFO]) {
+		struct rbr_nickinfo *rbr_ni;
+		struct rbr_node *old;
+		size_t old_size = 0;
+		size_t size = 0;
+		struct rbr *rbr;
 
+		if (!br->rbr)
+			return -EINVAL;
+
+		rbr = br->rbr;
+		size = nla_len(data[IFLA_TRILL_INFO]);
+		rbr_ni = kzalloc(size, GFP_KERNEL);
+		if (!rbr_ni)
+			goto fail;
+		memcpy(rbr_ni, nla_data(data[IFLA_TRILL_INFO]), size);
+		nick = rbr_ni->nick;
+		old = br->rbr->rbr_nodes[nick];
+		if (old)
+			old_size = RBR_NI_TOTALSIZE(old->rbr_ni);
+		/* replace old node by a new one only if nickname
+		 * information have changed
+		 */
+		if (!old || old_size != size ||
+		    memcmp(old->rbr_ni, rbr_ni, size)) {
+			struct rbr_node *new;
+
+			new = kzalloc(sizeof(*old), GFP_KERNEL);
+			if (!new) {
+				kfree(rbr_ni);
+				goto fail;
+			}
+			atomic_set(&new->refs, 1);
+			new->rbr_ni = rbr_ni;
+			/* Avoid deleting node while it is been used for
+			 * routing
+			 */
+			rcu_assign_pointer(rbr->rbr_nodes[nick], new);
+			if (old)
+				rbr_node_put(old);
+		} else {
+			kfree(rbr_ni);
+		}
+	}
 	return 0;
 fail:
 	pr_warn("rbr_set_data FAILED\n");
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 13/21] net: rbridge: add basic trill frame handling function
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (11 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 12/21] net: rbridge: update node table Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 14/21] net: rbridge: update forwarding database Ahmed Amamou
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

if trill is not enabled pass frame directly to the old handling function
if trill is enabled
frames from access port:
- destination is another access port -> deliver directly
- unknown or not an access port -> encapsulate (TODO)
frames from trunk port:
- 0x22F3 protocol -> trill frame -> TRILL handling process (TODO)
- desintation is localhost consume frame

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
Suggested-by: François Cachereul <f.cachereul@alphalink.fr>
---
 include/linux/etherdevice.h | 17 +++++++++
 net/bridge/rbr.c            | 92 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 9012f87..fc3173e 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -58,6 +58,10 @@ int eth_gro_complete(struct sk_buff *skb, int nhoff);
 /* Reserved Ethernet Addresses per IEEE 802.1Q */
 static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) =
 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
+#ifdef CONFIG_TRILL
+static const u8 eth_reserved_addr_all_rbridge[ETH_ALEN] __aligned(2) = {
+0x01, 0x80, 0xc2, 0x00, 0x00, 0x40};
+#endif
 
 /**
  * is_link_local_ether_addr - Determine if given Ethernet address is link-local
@@ -447,4 +451,17 @@ static inline int eth_skb_pad(struct sk_buff *skb)
 	return skb_put_padto(skb, ETH_ZLEN);
 }
 
+#ifdef CONFIG_TRILL
+/**
+ * is_all_rbr_address - check if it is a specific Rbridge brodcast mac address
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * returns true if it is a RBridge brodcast address 01:80:C2:00:00:40
+ */
+static inline bool is_all_rbr_address(const u8 *addr)
+{
+	return ether_addr_equal(addr, eth_reserved_addr_all_rbridge);
+}
+#endif
+
 #endif	/* _LINUX_ETHERDEVICE_H */
diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
index 67842fe..fdff167 100644
--- a/net/bridge/rbr.c
+++ b/net/bridge/rbr.c
@@ -13,6 +13,7 @@
  */
 #include "br_private.h"
 #include "rbr_private.h"
+#include <linux/netfilter_bridge.h>
 static void rbr_del_all(struct rbr *rbr);
 
 static struct rbr *add_rbr(struct net_bridge *br)
@@ -121,3 +122,94 @@ static void rbr_del_all(struct rbr *rbr)
 			rbr_del_node(rbr, i);
 	}
 }
+
+/* handling function hook allow handling
+ * a frame upon reception called via
+ * br_handle_frame_hook = rbr_handle_frame
+ * in  br.c
+ * Return NULL if skb is handled
+ * note: already called with rcu_read_lock
+ */
+rx_handler_result_t rbr_handle_frame(struct sk_buff **pskb)
+{
+	struct net_bridge *br;
+	struct net_bridge_port *p;
+	struct sk_buff *skb = *pskb;
+	u16 vid = 0;
+
+	p = br_port_get_rcu(skb->dev);
+	br = p->br;
+	if (!br || !br->rbr)
+		goto drop_no_stat;
+
+	if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
+		return RX_HANDLER_PASS;
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		return RX_HANDLER_CONSUMED;
+	if (unlikely(!is_valid_ether_addr(eth_hdr(skb)->h_source))) {
+		pr_warn_ratelimited("rbr_handle_frame: invalid src address\n");
+		goto drop;
+	}
+	if (!br_allowed_ingress(p->br, nbp_get_vlan_info(p), skb, &vid))
+		goto drop;
+	/* do not handle any BPDU from the moment */
+	if (is_all_rbr_address((const u8 *)&eth_hdr(skb)->h_dest)) {
+		br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false);
+		/* BPDU has to be dropped */
+		goto drop_no_stat;
+	}
+	/* DROP if port is in disable state */
+	if (p->trill_flag & TRILL_FLAG_DISABLE)
+		goto drop;
+	/* ACCESS port encapsulate packets */
+	if (p->trill_flag & TRILL_FLAG_ACCESS) {
+		/* check if destination is connected on the same bridge */
+		struct net_bridge_fdb_entry *dst;
+
+		dst = __br_fdb_get(br, eth_hdr(skb)->h_dest, vid);
+		if (likely(dst)) {
+			if (dst->dst->trill_flag & TRILL_FLAG_ACCESS) {
+				br_deliver(dst->dst, skb);
+				return RX_HANDLER_CONSUMED;
+			}
+		}
+
+		/* if packet is from access port and trill is enabled and dest
+		 * is not an access port or is unknown, encaps it
+		 */
+		/* TODO */
+		return RX_HANDLER_CONSUMED;
+	}
+	if (p->trill_flag & TRILL_FLAG_TRUNK) {
+		/* packet is from trunk port and trill is enabled */
+		if (eth_hdr(skb)->h_proto == htons(ETH_P_TRILL)) {
+			/* Packet is from trunk port, decapsulate
+			 * if destined to access port
+			 * or trill forward to next hop
+			 */
+			/* TODO */
+			return RX_HANDLER_CONSUMED;
+		}
+		/* packet is destinated to localhost */
+		if (ether_addr_equal(p->br->dev->dev_addr,
+				     eth_hdr(skb)->h_dest)) {
+			skb->pkt_type = PACKET_HOST;
+			NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, NULL, skb,
+				skb->dev, NULL,
+				br_handle_frame_finish);
+			return RX_HANDLER_CONSUMED;
+		}
+
+		/* packet is not from trill  we don't handle
+		 * such packet from the moment
+		 */
+	}
+
+ drop:
+	if (br->dev)
+		br->dev->stats.rx_dropped++;
+ drop_no_stat:
+	kfree_skb(skb);
+	return RX_HANDLER_CONSUMED;
+}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 14/21] net: rbridge: update forwarding database
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (12 preceding siblings ...)
  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 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 15/21] net: rbridge: add test on trill flag before flood Ahmed Amamou
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

update forwarding database to include nickname information used
in encapsulation and decapsulation
add functions to get and update nickname

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
---
 net/bridge/br_fdb.c     | 41 +++++++++++++++++++++++++++++++++++++++++
 net/bridge/br_private.h | 11 +++++++++++
 2 files changed, 52 insertions(+)

diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 9e9875d..14540f1 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -552,8 +552,14 @@ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 	return ret;
 }
 
+#ifdef CONFIG_TRILL
+void br_fdb_update_nick(struct net_bridge *br, struct net_bridge_port *source,
+			const unsigned char *addr, u16 vid, bool added_by_user,
+			uint16_t nick)
+#else
 void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 		   const unsigned char *addr, u16 vid, bool added_by_user)
+#endif
 {
 	struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
 	struct net_bridge_fdb_entry *fdb;
@@ -587,6 +593,10 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 				fdb->added_by_user = 1;
 			if (unlikely(fdb_modified))
 				fdb_notify(br, fdb, RTM_NEWNEIGH);
+#ifdef CONFIG_TRILL
+			if (nick != RBRIDGE_NICKNAME_UNUSED)
+				fdb->nick = nick;
+#endif
 		}
 	} else {
 		spin_lock(&br->hash_lock);
@@ -605,6 +615,16 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 	}
 }
 
+#ifdef CONFIG_TRILL
+void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
+		   const unsigned char *addr, u16 vid, bool added_by_user)
+{
+	br_fdb_update_nick(br, source, addr, vid, added_by_user,
+			   RBRIDGE_NICKNAME_UNUSED);
+}
+
+#endif
+
 static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb)
 {
 	if (fdb->is_local)
@@ -1076,3 +1096,24 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
 
 	return err;
 }
+
+#ifdef CONFIG_TRILL
+/* get_nick_from_mac: used to get correspondant nick to Mac address
+ * used only on ingress/Egress Rbridge (those how encapsulate
+ * and decapsulate frames)
+ * must be called while encapsulating  to get mac <-> nick correspondance
+ */
+uint16_t get_nick_from_mac(struct net_bridge_port *p, unsigned char *dest,
+			   u16 vid)
+{
+	struct hlist_head *head = &p->br->hash[br_mac_hash(dest, vid)];
+	struct net_bridge_fdb_entry *fdb;
+
+	if (is_multicast_ether_addr(dest))
+		return RBRIDGE_NICKNAME_NONE;
+	fdb = fdb_find(head, dest, vid);
+	if (likely(fdb))
+		return fdb->nick;
+	return RBRIDGE_NICKNAME_NONE;
+}
+#endif
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index ceaf5a9..a62e41e 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -120,6 +120,9 @@ struct net_bridge_fdb_entry
 					added_by_user:1,
 					added_by_external_learn:1;
 	__u16				vlan_id;
+#ifdef CONFIG_TRILL
+	__u16				nick; /* destination's nickname */
+#endif
 };
 
 struct net_bridge_port_group {
@@ -436,6 +439,14 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 			      const unsigned char *addr, u16 vid);
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
 			      const unsigned char *addr, u16 vid);
+#ifdef CONFIG_TRILL
+void br_fdb_update_nick(struct net_bridge *br,
+			struct net_bridge_port *source,
+			const unsigned char *addr,
+			u16 vid, bool added_by_user, uint16_t nick);
+uint16_t get_nick_from_mac(struct net_bridge_port *p, unsigned char *dest,
+			   u16 vid);
+#endif
 
 /* br_forward.c */
 void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 15/21] net: rbridge: add test on trill flag before flood
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (13 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 14/21] net: rbridge: update forwarding database Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 16/21] net: rbridge: add encapsulation process Ahmed Amamou
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou

frame from ACCESS PORT can not be flooded on TRUNK port
the opposite is also true, so we add a check on trill_flag on
br_flood function an add a special call
br_flood_forward_flags and br_flood_deliver_flags for them

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
---
 net/bridge/br_forward.c | 37 ++++++++++++++++++++++++++++++++++++-
 net/bridge/br_private.h |  4 ++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index fa7bfce..c27b213 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -190,7 +190,11 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb,
 		     struct sk_buff *skb0,
 		     void (*__packet_hook)(const struct net_bridge_port *p,
 					   struct sk_buff *skb),
+#ifdef CONFIG_TRILL
+		     bool unicast, uint8_t flag)
+#else
 		     bool unicast)
+#endif
 {
 	struct net_bridge_port *p;
 	struct net_bridge_port *prev;
@@ -209,6 +213,10 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb,
 		    BR_INPUT_SKB_CB(skb)->proxyarp_replied)
 			continue;
 
+#ifdef CONFIG_TRILL
+		if (flag && !(p->trill_flag & flag))
+			continue;
+#endif
 		prev = maybe_deliver(prev, p, skb, __packet_hook);
 		if (IS_ERR(prev))
 			goto out;
@@ -228,19 +236,46 @@ out:
 		kfree_skb(skb);
 }
 
-
 /* called with rcu_read_lock */
+#ifdef CONFIG_TRILL
+void br_flood_deliver_flags(struct net_bridge *br, struct sk_buff *skb,
+			    bool unicast, uint8_t flags)
+{
+	br_flood(br, skb, NULL, __br_deliver, unicast, flags);
+}
+
+void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast)
+{
+	br_flood_deliver_flags(br, skb, unicast, false);
+}
+
+#else
 void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast)
 {
 	br_flood(br, skb, NULL, __br_deliver, unicast);
 }
+#endif
 
 /* called under bridge lock */
+#ifdef CONFIG_TRILL
+void br_flood_forward_flags(struct net_bridge *br, struct sk_buff *skb,
+			    struct sk_buff *skb2, bool unicast, uint8_t flags)
+{
+	br_flood(br, skb, skb2, __br_forward, unicast, flags);
+}
+
+void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
+		      struct sk_buff *skb2, bool unicast)
+{
+	br_flood_forward_flags(br, skb, skb2, unicast, false);
+}
+#else
 void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
 		      struct sk_buff *skb2, bool unicast)
 {
 	br_flood(br, skb, skb2, __br_forward, unicast);
 }
+#endif
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 /* called with rcu_read_lock */
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index a62e41e..5e622e1 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -457,6 +457,10 @@ int br_forward_finish(struct sock *sk, struct sk_buff *skb);
 void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast);
 void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
 		      struct sk_buff *skb2, bool unicast);
+void br_flood_deliver_flags(struct net_bridge *br, struct sk_buff *skb,
+			    bool unicast, uint8_t flags);
+void br_flood_forward_flags(struct net_bridge *br, struct sk_buff *skb,
+			    struct sk_buff *skb2, bool unicast, uint8_t flags);
 
 /* br_if.c */
 void br_port_carrier_check(struct net_bridge_port *p);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 16/21] net: rbridge: add encapsulation process
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (14 preceding siblings ...)
  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 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 17/21] net: rbridge: add receive function Ahmed Amamou
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

add encapsulation process to detect frame type (multicast or unicast)
for known unicast frame add proper TRILL header

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
---
 net/bridge/rbr.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 123 insertions(+), 1 deletion(-)

diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
index fdff167..8081b20 100644
--- a/net/bridge/rbr.c
+++ b/net/bridge/rbr.c
@@ -14,6 +14,8 @@
 #include "br_private.h"
 #include "rbr_private.h"
 #include <linux/netfilter_bridge.h>
+#include <net/if_trill.h>
+
 static void rbr_del_all(struct rbr *rbr);
 
 static struct rbr *add_rbr(struct net_bridge *br)
@@ -123,6 +125,124 @@ static void rbr_del_all(struct rbr *rbr)
 	}
 }
 
+static bool add_header(struct sk_buff *skb, uint16_t ingressnick,
+		       u16 egressnick, bool multidest)
+{
+	struct trill_hdr *trh;
+	size_t trhsize;
+	u16 vlan_tci;
+	u16 trill_flags = 0;
+
+	trhsize = sizeof(*trh);
+	skb_push(skb, ETH_HLEN);
+	if (!skb->encapsulation) {
+		skb_reset_inner_headers(skb);
+		skb->encapsulation = 1;
+	}
+	/* fix inner VLAN */
+	if (br_vlan_get_tag(skb, &vlan_tci) == 0) {
+		skb = vlan_insert_tag(skb, skb->vlan_proto, vlan_tci);
+		if (!skb) {
+			pr_err("add_header: vlan_insert_tag failed\n");
+			return 1;
+		}
+		skb->vlan_proto = 0;
+		skb->vlan_tci = 0;
+	}
+	if (unlikely(skb_cow_head(skb, trhsize + ETH_HLEN))) {
+		pr_err("add_header: cow_head failed\n");
+		return 1;
+	}
+
+	trh = (struct trill_hdr *)skb_push(skb, sizeof(*trh));
+	trill_flags = trill_set_version(trill_flags, TRILL_PROTOCOL_VERS);
+	trill_flags = trill_set_hopcount(trill_flags, TRILL_DEFAULT_HOPS);
+	trill_flags = trill_set_multidest(trill_flags, multidest ? 1 : 0);
+
+	trh->th_flags = htons(trill_flags);
+	trh->th_egressnick = egressnick;
+	trh->th_ingressnick = ingressnick;	/* self nick name */
+	/* make skb->mac_header point to outer mac header */
+	skb_push(skb, ETH_HLEN);
+	skb_reset_mac_header(skb);	/* instead of the inner one */
+	eth_hdr(skb)->h_proto = htons(ETH_P_TRILL);
+	/* reset skb->data pointer */
+	skb_pull(skb, ETH_HLEN);
+	skb_reset_mac_len(skb);
+	return 0;
+}
+
+static void rbr_encaps(struct sk_buff *skb, u16 egressnick, u16 vid)
+{
+	u16 local_nick;
+	u16 dtnick;
+	struct rbr_node *self;
+	struct sk_buff *skb2;
+	struct rbr *rbr;
+	struct net_bridge_port *p;
+
+	p = br_port_get_rcu(skb->dev);
+	if (unlikely(!p)) {
+		pr_warn_ratelimited("rbr_encaps_prepare: port error\n");
+		goto encaps_drop;
+	}
+	rbr = p->br->rbr;
+
+	if (unlikely(egressnick != RBRIDGE_NICKNAME_NONE &&
+		     !VALID_NICK(egressnick))) {
+		pr_warn_ratelimited
+		    ("rbr_encaps_prepare: invalid destinaton nickname\n");
+		goto encaps_drop;
+	}
+	local_nick = rbr->nick;
+	if (unlikely(!VALID_NICK(local_nick))) {
+		pr_warn_ratelimited
+		    ("rbr_encaps_prepare: invalid local nickname\n");
+		goto encaps_drop;
+	}
+	/* Daemon has not yet sent the local nickname */
+	self = rbr_find_node(rbr, local_nick);
+	if (unlikely(!self)) {
+		pr_warn_ratelimited
+		    ("rbr_encaps_prepare: waiting for nickname\n");
+		goto encaps_drop;
+	}
+
+	/* Unknown destination => multidestination frame */
+	if (egressnick == RBRIDGE_NICKNAME_NONE) {
+		if (self->rbr_ni->dtrootcount > 0)
+			dtnick = RBR_NI_DTROOTNICK(self->rbr_ni, 0);
+		else
+			dtnick = rbr->treeroot;
+		rbr_node_put(self);
+		if (unlikely(!VALID_NICK(dtnick))) {
+			pr_warn_ratelimited
+			    ("rbr_encaps_prepare: dtnick is unvalid\n");
+			goto encaps_drop;
+		}
+		skb2 = skb_clone(skb, GFP_ATOMIC);
+		if (unlikely(!skb2)) {
+			p->br->dev->stats.tx_dropped++;
+			pr_warn_ratelimited
+			    ("rbr_encaps_prepare: skb_clone failed\n");
+			goto encaps_drop;
+		}
+		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 */
+	} else {
+		if (unlikely(add_header(skb, local_nick, egressnick, 0)))
+			goto encaps_drop;
+		/* TODO simple forwarding */
+	}
+	return;
+ encaps_drop:
+	if (likely(p && p->br))
+		p->br->dev->stats.tx_dropped++;
+	kfree_skb(skb);
+}
+
 /* handling function hook allow handling
  * a frame upon reception called via
  * br_handle_frame_hook = rbr_handle_frame
@@ -136,6 +256,7 @@ rx_handler_result_t rbr_handle_frame(struct sk_buff **pskb)
 	struct net_bridge_port *p;
 	struct sk_buff *skb = *pskb;
 	u16 vid = 0;
+	u16 nick;
 
 	p = br_port_get_rcu(skb->dev);
 	br = p->br;
@@ -178,7 +299,8 @@ rx_handler_result_t rbr_handle_frame(struct sk_buff **pskb)
 		/* if packet is from access port and trill is enabled and dest
 		 * is not an access port or is unknown, encaps it
 		 */
-		/* TODO */
+		nick = get_nick_from_mac(p, eth_hdr(skb)->h_dest, vid);
+		rbr_encaps(skb, nick, vid);
 		return RX_HANDLER_CONSUMED;
 	}
 	if (p->trill_flag & TRILL_FLAG_TRUNK) {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 17/21] net: rbridge: add receive function
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (15 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 16/21] net: rbridge: add encapsulation process Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 18/21] net: rbridge: add rbr_fwd Ahmed Amamou
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

add receiving function
process unicast frames in receiving function
multicast frame are not handled from the moment

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
---
 net/bridge/rbr.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 232 insertions(+), 1 deletion(-)

diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
index 8081b20..c04c05a 100644
--- a/net/bridge/rbr.c
+++ b/net/bridge/rbr.c
@@ -243,6 +243,237 @@ static void rbr_encaps(struct sk_buff *skb, u16 egressnick, u16 vid)
 	kfree_skb(skb);
 }
 
+static void rbr_decap_finish(struct sk_buff *skb, u16 vid)
+{
+	struct net_bridge *br;
+	struct net_bridge_port *p;
+	const unsigned char *dest = eth_hdr(skb)->h_dest;
+	struct net_bridge_fdb_entry *dst;
+
+	p = br_port_get_rcu(skb->dev);
+	br = p->br;
+	dst = __br_fdb_get(br, dest, vid);
+	if (likely(dst))
+		br_deliver(dst->dst, skb);
+	else
+		/* destination unknown flood on all access ports */
+		br_flood_deliver_flags(br, skb, true, TRILL_FLAG_ACCESS);
+}
+
+static void rbr_decaps(struct net_bridge_port *p,
+		       struct sk_buff *skb, size_t trhsize, u16 vid)
+{
+	struct trill_hdr *trh;
+	struct ethhdr *hdr;
+
+	if (unlikely(!p))
+		goto rbr_decaps_drop;
+	trh = (struct trill_hdr *)skb->data;
+	if (trhsize >= sizeof(*trh))
+		skb_pull(skb, sizeof(*trh));
+	else
+		goto rbr_decaps_drop;
+	trhsize -= sizeof(*trh);
+	skb_reset_mac_header(skb);	/* instead of the inner one */
+	skb->protocol = eth_hdr(skb)->h_proto;
+	hdr = (struct ethhdr *)skb->data;
+	skb_pull(skb, ETH_HLEN);
+	skb_reset_network_header(skb);
+	if (skb->encapsulation)
+		skb->encapsulation = 0;
+	br_fdb_update_nick(p->br, p, hdr->h_source, vid, false,
+			   trh->th_ingressnick);
+	rbr_decap_finish(skb, vid);
+	return;
+ rbr_decaps_drop:
+	if (likely(p && p->br))
+		p->br->dev->stats.rx_dropped++;
+	kfree_skb(skb);
+}
+
+static void rbr_recv(struct sk_buff *skb, u16 vid)
+{
+	u16 local_nick, dtnick, adjnick, idx;
+	struct rbr *rbr;
+	struct trill_hdr *trh;
+	size_t trhsize;
+	struct net_bridge_port *p;
+	u16 trill_flags;
+	struct sk_buff *skb2;
+	struct rbr_node *dest = NULL;
+	struct rbr_node *source_node = NULL;
+	struct rbr_node *adj = NULL;
+
+	p = br_port_get_rcu(skb->dev);
+	if (unlikely(!p)) {
+		pr_warn_ratelimited("rbr_recv: port error\n");
+		goto recv_drop;
+	}
+	rbr = p->br->rbr;
+	/* For trill frame the outer mac destination must correspond
+	 * to localhost address, if not frame must be discarded
+	 * such scenario is possible when switch flood frames on all ports
+	 * if frame are not discarded they will loop until reaching the
+	 * hop_count limit
+	 */
+	if (memcmp(p->dev->dev_addr, eth_hdr(skb)->h_dest, ETH_ALEN))
+		goto recv_drop;
+	trh = (struct trill_hdr *)skb->data;
+	trill_flags = ntohs(trh->th_flags);
+	trhsize = sizeof(*trh) + trill_get_optslen(trill_flags);
+	if (unlikely(skb->len < trhsize + ETH_HLEN)) {
+		pr_warn_ratelimited
+		    ("rbr_recv: sk_buff len is less then minimal len\n");
+		goto recv_drop;
+	}
+	/* seems to be a valid TRILL frame,
+	 * check if TRILL header can be pulled
+	 * before proceeding
+	 */
+	if (unlikely(!pskb_may_pull(skb, trhsize + ETH_HLEN)))
+		goto recv_drop;
+
+	/* WARNING SKB structure may be changed by pskb_may_pull
+	 * reassign trh pointer before continuing any further
+	 */
+	trh = (struct trill_hdr *)skb->data;
+
+	if (!skb->encapsulation) {
+		skb_pull(skb, trhsize + ETH_HLEN);
+		skb_reset_inner_headers(skb);
+		skb->encapsulation = 1;
+		skb_push(skb, trhsize + ETH_HLEN);
+	}
+	if (unlikely(!VALID_NICK(trh->th_ingressnick) ||
+		     !VALID_NICK(trh->th_egressnick))) {
+		pr_warn_ratelimited("rbr_recv: invalid nickname\n");
+		goto recv_drop;
+	}
+	if (unlikely(trill_get_version(trill_flags) != TRILL_PROTOCOL_VERS)) {
+		pr_warn_ratelimited("rbr_recv: not the same trill version\n");
+		goto recv_drop;
+	}
+	local_nick = rbr->nick;
+	dtnick = rbr->treeroot;
+	if (unlikely(trh->th_ingressnick == local_nick)) {
+		pr_warn_ratelimited
+		    ("rbr_recv:looping back frame check your config\n");
+		goto recv_drop;
+	}
+
+	if (!trill_get_multidest(trill_flags)) {
+		/* ntohs not needed as the 2 are in the same bit form */
+		if (trh->th_egressnick == trh->th_ingressnick) {
+			pr_warn_ratelimited
+			    ("rbr_recv: egressnick == ingressnick\n");
+			goto recv_drop;
+		}
+		if (trh->th_egressnick == local_nick) {
+			rbr_decaps(p, skb, trhsize, vid);
+		} else if (likely(trill_get_hopcount(trill_flags))) {
+			br_fdb_update(p->br, p, eth_hdr(skb)->h_source,
+				      vid, false);
+			/* TODO simple forwarding */
+		} else {
+			pr_warn_ratelimited("rbr_recv: hop count limit reached\n");
+			goto recv_drop;
+		}
+		return;
+	}
+
+	/* Multi-destination frame:
+	 * Check if received multi-destination frame from an
+	 * adjacency in the distribution tree rooted at egress nick
+	 * indicated in the frame header
+	 */
+	dest = rbr_find_node(rbr, trh->th_egressnick);
+	if (unlikely(!dest)) {
+		pr_warn_ratelimited
+		    ("rbr_recv: mulicast  with unknown destination\n");
+		goto recv_drop;
+	}
+	for (idx = 0; idx < dest->rbr_ni->adjcount; idx++) {
+		adjnick = RBR_NI_ADJNICK(dest->rbr_ni, idx);
+		adj = rbr_find_node(rbr, adjnick);
+		if (unlikely(!adj || !adj->rbr_ni))
+			continue;
+		if (memcmp(adj->rbr_ni->adjsnpa, eth_hdr(skb)->h_source,
+			   ETH_ALEN) == 0) {
+			rbr_node_put(adj);
+			break;
+		}
+		rbr_node_put(adj);
+	}
+
+	if (unlikely(idx >= dest->rbr_ni->adjcount)) {
+		pr_warn_ratelimited("rbr_recv: multicast unknown mac source\n");
+		rbr_node_put(dest);
+		goto recv_drop;
+	}
+
+	/* Reverse path forwarding check.
+	 * Check if the ingress RBridge  that has forwarded
+	 * the frame advertised the use of the distribution tree specified
+	 * in the egress nick
+	 */
+	source_node = rbr_find_node(rbr, trh->th_ingressnick);
+	if (unlikely(!source_node)) {
+		pr_warn_ratelimited
+		    ("rbr_recv: reverse path forwarding check failed\n");
+		rbr_node_put(dest);
+		goto recv_drop;
+	}
+	for (idx = 0; idx < source_node->rbr_ni->dtrootcount; idx++) {
+		if (RBR_NI_DTROOTNICK(source_node->rbr_ni, idx) ==
+		    trh->th_egressnick)
+			break;
+	}
+
+	if (idx >= source_node->rbr_ni->dtrootcount) {
+		/* Allow receipt of forwarded frame with the highest
+		 * tree root RBridge as the egress RBridge when the
+		 * ingress RBridge has not advertised the use of any
+		 * distribution trees.
+		 */
+		if (source_node->rbr_ni->dtrootcount != 0 ||
+		    trh->th_egressnick != dtnick) {
+			rbr_node_put(source_node);
+			rbr_node_put(dest);
+			goto recv_drop;
+		}
+	}
+
+	/* Check hop count before doing any forwarding */
+	if (unlikely(trill_get_hopcount(trill_flags) == 0)) {
+		pr_warn_ratelimited
+		    ("rbr_recv: multicast hop count limit reached\n");
+		rbr_node_put(dest);
+		goto recv_drop;
+	}
+	/* Forward frame using the distribution tree specified by egress nick */
+	rbr_node_put(source_node);
+	rbr_node_put(dest);
+
+	/* skb2 will be multi forwarded and skb will be locally decaps */
+	skb2 = skb_clone(skb, GFP_ATOMIC);
+	if (unlikely(!skb2)) {
+		p->br->dev->stats.tx_dropped++;
+		pr_warn_ratelimited("rbr_recv: multicast skb_clone failed\n");
+		goto recv_drop;
+	}
+
+	/* TODO multi forwarding */
+
+	/* Send de-capsulated frame locally */
+	rbr_decaps(p, skb, trhsize, vid);
+
+	return;
+ recv_drop:
+	if (likely(p && p->br))
+		p->br->dev->stats.rx_dropped++;
+	kfree_skb(skb);
+}
+
 /* handling function hook allow handling
  * a frame upon reception called via
  * br_handle_frame_hook = rbr_handle_frame
@@ -310,7 +541,7 @@ rx_handler_result_t rbr_handle_frame(struct sk_buff **pskb)
 			 * if destined to access port
 			 * or trill forward to next hop
 			 */
-			/* TODO */
+			rbr_recv(skb, vid);
 			return RX_HANDLER_CONSUMED;
 		}
 		/* packet is destinated to localhost */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 18/21] net: rbridge: add rbr_fwd
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (16 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 17/21] net: rbridge: add receive function Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 19/21] net: rbridge: add rbr_multidest_fwd Ahmed Amamou
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev
  Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou, François Cachereul

add rbridge forward function
packets arriving to rbr_fwd should be already encapsulated and correct
egress
and ingress nickname should be already assigned
rbr_fwd function will assign correct source and destination outer MAC
addresses
according to which port will send the frame and next hop to reach
the engress nickname
Nexthope to reach the egress will be found in node database

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
Signed-off-by: François Cachereul <f.cachereul@alphalink.fr>
---
 net/bridge/rbr.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
index c04c05a..ab71e6b 100644
--- a/net/bridge/rbr.c
+++ b/net/bridge/rbr.c
@@ -172,6 +172,48 @@ static bool add_header(struct sk_buff *skb, uint16_t ingressnick,
 	return 0;
 }
 
+static void rbr_fwd(struct net_bridge_port *p, struct sk_buff *skb,
+		    u16 adj_nick, u16 vid)
+{
+	struct rbr_node *adj;
+	struct trill_hdr *trh;
+	struct ethhdr *outerethhdr;
+	struct net *net = dev_net(p->dev);
+	struct net_device *outdev;
+	struct net_bridge_port *outp;
+
+	adj = rbr_find_node(p->br->rbr, adj_nick);
+	if (unlikely(!adj || !adj->rbr_ni)) {
+		pr_warn_ratelimited("rbr_fwd: unable to find adjacent RBridge\n");
+		goto dest_fwd_fail;
+	}
+	outdev = dev_get_by_index_rcu(net, adj->rbr_ni->linkid);
+	if (!outdev) {
+		pr_warn_ratelimited("rbr_fwd: cannot find source port device for forwrding\n");
+		goto dest_fwd_fail;
+	}
+
+	trh = (struct trill_hdr *)skb->data;
+	trillhdr_dec_hopcount(trh);
+	outerethhdr = eth_hdr(skb);
+
+	/* change outer ether header */
+	/* bridge becomes the source_port address in outeretherhdr */
+	outp = br_port_get_rcu(outdev);
+	ether_addr_copy(outerethhdr->h_source, outp->dev->dev_addr);
+	/* dist port becomes dest address in outeretherhdr */
+	ether_addr_copy(outerethhdr->h_dest, adj->rbr_ni->adjsnpa);
+	rbr_node_put(adj);
+	skb->dev = p->br->dev;
+	br_forward(outp, skb, NULL);
+	return;
+
+dest_fwd_fail:
+	if (likely(p && p->br))
+		p->br->dev->stats.tx_dropped++;
+	kfree_skb(skb);
+}
+
 static void rbr_encaps(struct sk_buff *skb, u16 egressnick, u16 vid)
 {
 	u16 local_nick;
@@ -234,7 +276,7 @@ static void rbr_encaps(struct sk_buff *skb, u16 egressnick, u16 vid)
 	} else {
 		if (unlikely(add_header(skb, local_nick, egressnick, 0)))
 			goto encaps_drop;
-		/* TODO simple forwarding */
+		rbr_fwd(p, skb, egressnick, vid);
 	}
 	return;
  encaps_drop:
@@ -373,7 +415,7 @@ static void rbr_recv(struct sk_buff *skb, u16 vid)
 		} else if (likely(trill_get_hopcount(trill_flags))) {
 			br_fdb_update(p->br, p, eth_hdr(skb)->h_source,
 				      vid, false);
-			/* TODO simple forwarding */
+			rbr_fwd(p, skb, trh->th_egressnick, vid);
 		} else {
 			pr_warn_ratelimited("rbr_recv: hop count limit reached\n");
 			goto recv_drop;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 19/21] net: rbridge: add rbr_multidest_fwd
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (17 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 18/21] net: rbridge: add rbr_fwd Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  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
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

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

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 20/21] net: rbridge: replace net_port rx_handler
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (18 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 19/21] net: rbridge: add rbr_multidest_fwd Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  2015-09-01 15:43 ` [PATCH RFC v2 21/21] net: handle packet split for trill Ahmed Amamou
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou, Kamel Haddadou

replace classic rx_handler in bridge by the new rbr_handle_frame in
order to provide trill support

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
---
 net/bridge/br_if.c      |  7 ++++++-
 net/bridge/br_private.h |  1 +
 net/bridge/rbr.c        | 20 ++++++++++++++++----
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index a538cb1..3b39f69 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -483,7 +483,12 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	if (err)
 		goto err3;
 
-	err = netdev_rx_handler_register(dev, br_handle_frame, p);
+#ifdef CONFIG_TRILL
+	if (br->trill_enabled == BR_TRILL)
+		err = netdev_rx_handler_register(dev, rbr_handle_frame, p);
+	else
+#endif
+		err = netdev_rx_handler_register(dev, br_handle_frame, p);
 	if (err)
 		goto err4;
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 5e622e1..27d5cd8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -852,6 +852,7 @@ ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id);
 /* rbr.c */
 #ifdef CONFIG_TRILL
 void br_trill_set_enabled(struct net_bridge *br, unsigned long val);
+rx_handler_result_t rbr_handle_frame(struct sk_buff **pskb);
 #endif
 
 /* br_stp_bpdu.c */
diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
index 23f3e1d..2fb9b81 100644
--- a/net/bridge/rbr.c
+++ b/net/bridge/rbr.c
@@ -38,21 +38,28 @@ static struct rbr *add_rbr(struct net_bridge *br)
 
 static void br_trill_start(struct net_bridge *br)
 {
+	struct net_bridge_port *p;
 	/* Disable STP if it is already enabled */
 
 	if (br->stp_enabled != BR_NO_STP)
 		br_stp_set_enabled(br, false);
 	br->rbr = add_rbr(br);
-	if (br->rbr)
+	if (br->rbr) {
+		list_for_each_entry(p, &br->port_list, list) {
+			struct net_device *dev = p->dev;
+
+			rcu_assign_pointer(dev->rx_handler, rbr_handle_frame);
+		}
 		br->trill_enabled = BR_TRILL;
-	else
-		pr_warn("RBridge allocation for bridge '%s' failed\n",
-			br->dev->name);
+		return;
+	}
+	pr_warn("RBridge allocation for bridge '%s' failed\n", br->dev->name);
 }
 
 static void br_trill_stop(struct net_bridge *br)
 {
 	struct rbr *old;
+	struct net_bridge_port *p;
 
 	spin_lock_bh(&br->lock);
 	br->trill_enabled = BR_NO_TRILL;
@@ -60,6 +67,11 @@ static void br_trill_stop(struct net_bridge *br)
 	old = br->rbr;
 	br->rbr = NULL;
 	if (likely(old)) {
+		list_for_each_entry(p, &br->port_list, list) {
+			struct net_device *dev = p->dev;
+
+			rcu_assign_pointer(dev->rx_handler, br_handle_frame);
+		}
 		rbr_del_all(old);
 		kfree(old);
 	}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH RFC v2 21/21] net: handle packet split for trill
  2015-09-01 15:42 [PATCH RFC v2 00/21] TRILL implementation Ahmed Amamou
                   ` (19 preceding siblings ...)
  2015-09-01 15:43 ` [PATCH RFC v2 20/21] net: rbridge: replace net_port rx_handler Ahmed Amamou
@ 2015-09-01 15:43 ` Ahmed Amamou
  20 siblings, 0 replies; 25+ messages in thread
From: Ahmed Amamou @ 2015-09-01 15:43 UTC (permalink / raw)
  To: netdev; +Cc: William Dauchy, Ahmed Amamou

From: William Dauchy <william@gandi.net>

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
---
 net/core/flow_dissector.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 2a834c6..95c2794 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -18,6 +18,9 @@
 #include <linux/mpls.h>
 #include <net/flow_dissector.h>
 #include <scsi/fc/fc_fcoe.h>
+#ifdef CONFIG_TRILL
+#include <net/if_trill.h>
+#endif
 
 static bool skb_flow_dissector_uses_key(struct flow_dissector *flow_dissector,
 					enum flow_dissector_key_id key_id)
@@ -165,6 +168,34 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 
 again:
 	switch (proto) {
+#ifdef CONFIG_TRILL
+	case htons(ETH_P_TRILL): {
+		const struct trill_hdr *trillh;
+		struct trill_hdr _trillh;
+		const struct ethhdr *eth;
+		struct ethhdr _eth;
+		u8 trill_op_len;
+
+		trillh = __skb_header_pointer(skb, nhoff, sizeof(_trillh),
+					      data, hlen, &_trillh);
+		if (!trillh)
+			return false;
+		nhoff += sizeof(*trillh);
+		trill_op_len = trill_get_optslen(ntohs(trillh->th_flags));
+		if (trill_op_len)
+			nhoff += trill_op_len;
+
+		eth = __skb_header_pointer(skb, nhoff, sizeof(_eth), data,
+					   hlen, &_eth);
+		if (!eth)
+			return false;
+		proto = eth->h_proto;
+		nhoff += sizeof(*eth);
+
+		/* handle any vlan tag if present */
+		goto again;
+	}
+#endif
 	case htons(ETH_P_IP): {
 		const struct iphdr *iph;
 		struct iphdr _iph;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH RFC v2 09/21] net: rbridge: add elected dtroot
  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
  0 siblings, 1 reply; 25+ messages in thread
From: Sergei Shtylyov @ 2015-09-01 18:18 UTC (permalink / raw)
  To: Ahmed Amamou, netdev; +Cc: William Dauchy

Hello.

On 09/01/2015 06:43 PM, Ahmed Amamou wrote:

> Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
> ---
>   net/bridge/rbr.c           | 14 ++++++++++++++
>   net/bridge/rbr_private.h   |  2 ++
>   net/bridge/rbr_rtnetlink.c |  6 ++++++
>   3 files changed, 22 insertions(+)
>
> diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
> index c554743..31e72ef 100644
> --- a/net/bridge/rbr.c
> +++ b/net/bridge/rbr.c
> @@ -69,3 +69,17 @@ void br_trill_set_enabled(struct net_bridge *br, unsigned long val)
>   			br_trill_stop(br);
>   	}
>   }
> +
> +int set_treeroot(struct rbr *rbr, uint16_t treeroot)
> +{
> +	if (unlikely(!VALID_NICK(treeroot))) {
> +		pr_warn_ratelimited
> +			("rbr_set_treeroot: given tree root not valid\n");
> +		goto set_tree_root_fail;

    This seems a bit stupid. Why not *return* directly?

> +	}
> +	if (rbr->treeroot != treeroot)
> +		rbr->treeroot = treeroot;
> +	return 0;
> + set_tree_root_fail:
> +	return -ENOENT;
> +}
[...]

MBR, Sergei

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH RFC v2 09/21] net: rbridge: add elected dtroot
  2015-09-01 18:18   ` Sergei Shtylyov
@ 2015-09-01 18:26     ` ahmed amamou
  0 siblings, 0 replies; 25+ messages in thread
From: ahmed amamou @ 2015-09-01 18:26 UTC (permalink / raw)
  To: Sergei Shtylyov, netdev; +Cc: William Dauchy



On September 1, 2015 8:18:29 PM GMT+02:00, Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> wrote:
>Hello.
>
>On 09/01/2015 06:43 PM, Ahmed Amamou wrote:
>
>> Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
>> ---
>>   net/bridge/rbr.c           | 14 ++++++++++++++
>>   net/bridge/rbr_private.h   |  2 ++
>>   net/bridge/rbr_rtnetlink.c |  6 ++++++
>>   3 files changed, 22 insertions(+)
>>
>> diff --git a/net/bridge/rbr.c b/net/bridge/rbr.c
>> index c554743..31e72ef 100644
>> --- a/net/bridge/rbr.c
>> +++ b/net/bridge/rbr.c
>> @@ -69,3 +69,17 @@ void br_trill_set_enabled(struct net_bridge *br,
>unsigned long val)
>>   			br_trill_stop(br);
>>   	}
>>   }
>> +
>> +int set_treeroot(struct rbr *rbr, uint16_t treeroot)
>> +{
>> +	if (unlikely(!VALID_NICK(treeroot))) {
>> +		pr_warn_ratelimited
>> +			("rbr_set_treeroot: given tree root not valid\n");
>> +		goto set_tree_root_fail;
>
>    This seems a bit stupid. Why not *return* directly?

Indeed, we will fix it.
>
>> +	}
>> +	if (rbr->treeroot != treeroot)
>> +		rbr->treeroot = treeroot;
>> +	return 0;
>> + set_tree_root_fail:
>> +	return -ENOENT;
>> +}
>[...]
>
>MBR, Sergei

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH RFC v2 10/21] net: rbridge: add rbr_node management function
  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
  0 siblings, 0 replies; 25+ messages in thread
From: Sergei Shtylyov @ 2015-09-01 18:30 UTC (permalink / raw)
  To: Ahmed Amamou, netdev; +Cc: William Dauchy, Kamel Haddadou

On 09/01/2015 06:43 PM, Ahmed Amamou wrote:

> rbr_node are used to save distant Rbridges information
> they are use by local Rbridge to take routing decision
> this patch add get/put/free/find/del  function to rbr_node to
> avoid freeing a rbr_node that is still in use for routing
>
> Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
> Signed-off-by: Kamel Haddadou <kamel@gandi.net>
> Signed-off-by: William Dauchy <william@gandi.net>
> ---
>   net/bridge/rbr.c         | 35 +++++++++++++++++++++++++++++++++++
>   net/bridge/rbr_private.h | 23 +++++++++++++++++++++++
>   2 files changed, 58 insertions(+)

[...]
> diff --git a/net/bridge/rbr_private.h b/net/bridge/rbr_private.h
> index 9166a8b..186e454 100644
> --- a/net/bridge/rbr_private.h
> +++ b/net/bridge/rbr_private.h
> @@ -44,7 +44,30 @@ struct rbr {
[...]
> +static inline void rbr_node_put(struct rbr_node *rbr_node)
> +{
> +	if (rbr_node) {
> +		if (unlikely(atomic_dec_and_test(&rbr_node->refs)))

    Could fold both 'if's into one and avoid {} altogether.

> +			rbr_node_free(rbr_node);
> +	}
> +}
> +

MBR, Sergei

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2015-09-01 18:30 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH RFC v2 19/21] net: rbridge: add rbr_multidest_fwd Ahmed Amamou
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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.