All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/24] TRILL implementation
@ 2014-09-24 15:51 Ahmed Amamou
  2014-09-24 15:51 ` [RFC PATCH 01/24] net: rbridge: add trill frame description Ahmed Amamou
                   ` (24 more replies)
  0 siblings, 25 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:51 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou

Hi,

We have been working on a TRILL implementation in the Linux kernel for some
months now.  The code has been pushed here https://github.com/Gandi/ktrill.git
along the way.  Attached a series of patch as a first proposition.  The code is
not perfect and probably still lacks of improvements. It's a first request of
comment in order to get some feedbacks. This code has been tested for some
months now.

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

We still need to fix these points: 
- The use of rtnetlink instead of the actual netlink.
- BPDU handling

Also some parts may not be fully linux compliant, so we are waiting for
comments

In order to test theses patches please follow this small wiki 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 --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

Ahmed Amamou (23):
  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: Add Rbridge netlink message skeleton
  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: Add set_node function
  net: rbridge: Add get_node function
  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 multicast recv handling
  net: rbridge: Add decapsulation 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

 include/linux/etherdevice.h      |  34 ++
 include/linux/if_trill.h         |  89 +++++
 include/uapi/linux/if_ether.h    |   2 +
 net/bridge/Kconfig               |   8 +
 net/bridge/Makefile              |   2 +
 net/bridge/br.c                  |   6 +
 net/bridge/br_fdb.c              |  40 +++
 net/bridge/br_forward.c          |  38 ++
 net/bridge/br_if.c               |   4 +
 net/bridge/br_private.h          |  51 +++
 net/bridge/br_sysfs_br.c         |  38 ++
 net/bridge/br_sysfs_if.c         |  23 ++
 net/bridge/rbridge/rbr.c         | 723 +++++++++++++++++++++++++++++++++++++++
 net/bridge/rbridge/rbr_netlink.c | 404 ++++++++++++++++++++++
 net/bridge/rbridge/rbr_netlink.h |  62 ++++
 net/bridge/rbridge/rbr_private.h |  86 +++++
 16 files changed, 1610 insertions(+)
 create mode 100644 include/linux/if_trill.h
 create mode 100644 net/bridge/rbridge/rbr.c
 create mode 100644 net/bridge/rbridge/rbr_netlink.c
 create mode 100644 net/bridge/rbridge/rbr_netlink.h
 create mode 100644 net/bridge/rbridge/rbr_private.h

-- 
Ahmed Amamou 

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

* [RFC PATCH 01/24] net: rbridge: add trill frame description
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
@ 2014-09-24 15:51 ` Ahmed Amamou
  2014-09-24 16:38   ` Stephen Hemminger
  2014-09-24 17:01   ` Cong Wang
  2014-09-24 15:51 ` [RFC PATCH 02/24] net: rbridge: Add layer 2 IS-IS Ethertype Ahmed Amamou
                   ` (23 subsequent siblings)
  24 siblings, 2 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:51 UTC (permalink / raw)
  To: netdev
  Cc: william, f.cachereul, Ahmed Amamou, Emmanuel Hocdet, Kamel Haddadou

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

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/linux/if_trill.h      | 89 +++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/if_ether.h |  1 +
 2 files changed, 90 insertions(+)
 create mode 100644 include/linux/if_trill.h

diff --git a/include/linux/if_trill.h b/include/linux/if_trill.h
new file mode 100644
index 0000000..ad9c631
--- /dev/null
+++ b/include/linux/if_trill.h
@@ -0,0 +1,89 @@
+#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;
+} __attribute__ ((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 0f8210b..a9eb2f2 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            */
-- 
1.9.1

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

* [RFC PATCH 02/24] net: rbridge: Add layer 2 IS-IS Ethertype
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
  2014-09-24 15:51 ` [RFC PATCH 01/24] net: rbridge: add trill frame description Ahmed Amamou
@ 2014-09-24 15:51 ` Ahmed Amamou
  2014-09-24 15:51 ` [RFC PATCH 03/24] net: rbridge: Add RBridge structure Ahmed Amamou
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:51 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou

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 a9eb2f2..5cc2de6 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            */
-- 
1.9.1

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

* [RFC PATCH 03/24] net: rbridge: Add RBridge structure
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
  2014-09-24 15:51 ` [RFC PATCH 01/24] net: rbridge: add trill frame description Ahmed Amamou
  2014-09-24 15:51 ` [RFC PATCH 02/24] net: rbridge: Add layer 2 IS-IS Ethertype Ahmed Amamou
@ 2014-09-24 15:51 ` Ahmed Amamou
  2014-09-24 16:40   ` Stephen Hemminger
  2014-09-24 17:18   ` Cong Wang
  2014-09-24 15:52 ` [RFC PATCH 04/24] net: rbridge: Add CONFIG_TRILL Ahmed Amamou
                   ` (21 subsequent siblings)
  24 siblings, 2 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:51 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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/rbridge/rbr_private.h | 60 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 net/bridge/rbridge/rbr_private.h

diff --git a/net/bridge/rbridge/rbr_private.h b/net/bridge/rbridge/rbr_private.h
new file mode 100644
index 0000000..f21e4a5
--- /dev/null
+++ b/net/bridge/rbridge/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 */
+	uint16_t nick;
+	/* Next-hop SNPA address to reach this RBridge */
+	u8 adjsnpa[ETH_ALEN];
+	/* Link on our system to use to reach next-hop */
+	uint32_t linkid;
+	/* Num of *our* adjacencies on a tree rooted at this RBridge */
+	uint16_t adjcount;
+	/* Num of distribution tree root nicks chosen by this RBridge */
+	uint16_t 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 {
+	uint16_t nick;		/* our nickname */
+	uint16_t 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) ((uint16_t *)((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 (uint16_t) * (v)->adjcount) + \
+		(sizeof (uint16_t) * (v)->dtrootcount)\
+		)
+#endif
-- 
1.9.1

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

* [RFC PATCH 04/24] net: rbridge: Add CONFIG_TRILL
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (2 preceding siblings ...)
  2014-09-24 15:51 ` [RFC PATCH 03/24] net: rbridge: Add RBridge structure Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 05/24] net: rbridge: Adapt Bridge structure Ahmed Amamou
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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.
-- 
1.9.1

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

* [RFC PATCH 05/24] net: rbridge: Adapt Bridge structure
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (3 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 04/24] net: rbridge: Add CONFIG_TRILL Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 20:56   ` Francois Romieu
  2014-09-24 15:52 ` [RFC PATCH 06/24] net: rbridge: Enable/disable TRILL capability Ahmed Amamou
                   ` (19 subsequent siblings)
  24 siblings, 1 reply; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

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>
---
 include/linux/etherdevice.h | 34 ++++++++++++++++++++++++++++++++++
 net/bridge/br_private.h     | 25 +++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 9c5529d..09dc18c 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -54,6 +54,16 @@ struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs,
 /* 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};
+
+static const u8 eth_reserved_addr_isis_rbridge[ETH_ALEN] __aligned(2) = {
+0x01, 0x80, 0xc2, 0x00, 0x00, 0x41};
+
+static const u8 eth_reserved_addr_esadi_rbridge[ETH_ALEN] __aligned(2) = {
+0x01, 0x80, 0xc2, 0x00, 0x00, 0x42};
+#endif
 
 /**
  * is_link_local_ether_addr - Determine if given Ethernet address is link-local
@@ -391,4 +401,28 @@ static inline unsigned long compare_ether_header(const void *a, const void *b)
 #endif
 }
 
+#ifdef CONFIG_TRILL
+/**
+ * is_all_rbr_address - check if it is a specific Rbridge brodcast mac address
+ * @addr1: 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 * addr1)
+{
+	return ether_addr_equal(addr1, eth_reserved_addr_all_rbridge);
+}
+
+static inline bool is_isis_rbr_address(const u8 * addr1)
+{
+	return ether_addr_equal(addr1, eth_reserved_addr_isis_rbridge);
+}
+
+static inline bool is_esadi_rbr_address(const u8 * addr1)
+{
+	return ether_addr_equal(addr1, eth_reserved_addr_esadi_rbridge);
+}
+#endif
+
+
 #endif	/* _LINUX_ETHERDEVICE_H */
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 62a7fa2..430c556 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -19,6 +19,9 @@
 #include <linux/u64_stats_sync.h>
 #include <net/route.h>
 #include <linux/if_vlan.h>
+#ifdef CONFIG_TRILL
+#include "rbridge/rbr_private.h"
+#endif
 
 #define BR_HASH_BITS 8
 #define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -31,6 +34,18 @@
 
 #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 control protocols like STP and LLDP */
@@ -163,6 +178,11 @@ struct net_bridge_port
 	struct rcu_head			rcu;
 
 	unsigned long 			flags;
+	/* Trill */
+#ifdef CONFIG_TRILL
+	uint8_t					trill_flag;
+#endif /* CONFIG_TRILL */
+
 #define BR_HAIRPIN_MODE		0x00000001
 #define BR_BPDU_GUARD           0x00000002
 #define BR_ROOT_BLOCK		0x00000004
@@ -252,6 +272,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;
 
-- 
1.9.1

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

* [RFC PATCH 06/24] net: rbridge: Enable/disable TRILL capability
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (4 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 05/24] net: rbridge: Adapt Bridge structure Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 17:46   ` Vlad Yasevich
  2014-09-24 15:52 ` [RFC PATCH 07/24] net: rbridge: Add sysfs for trill_state Ahmed Amamou
                   ` (18 subsequent siblings)
  24 siblings, 1 reply; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

enable switching TRILL capability state via sysfs command

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
---
 net/bridge/Makefile      |  2 ++
 net/bridge/br_private.h  |  5 ++++
 net/bridge/br_sysfs_br.c | 38 +++++++++++++++++++++++
 net/bridge/rbridge/rbr.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 123 insertions(+)
 create mode 100644 net/bridge/rbridge/rbr.c

diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index 8590b94..314783c 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -17,3 +17,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) += rbridge/rbr.o
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 430c556..844c87b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -811,6 +811,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);
 
+/* rbridge/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/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index c9e2572..787ab84 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);
+	char *endp;
+	unsigned long val;
+
+	if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
+		return -EPERM;
+
+	val = simple_strtoul(buf, &endp, 0);
+	if (endp == buf)
+		return -EINVAL;
+
+	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)
@@ -733,6 +768,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/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
new file mode 100644
index 0000000..41d47db
--- /dev/null
+++ b/net/bridge/rbridge/rbr.c
@@ -0,0 +1,78 @@
+/*
+ *	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) {
+		spin_lock_bh(&br->lock);
+		br->trill_enabled = BR_TRILL;
+		spin_unlock_bh(&br->lock);
+	} else {
+		printk(KERN_WARNING
+		       "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)) {
+		spin_lock_bh(&br->lock);
+		kfree(old);
+		spin_unlock_bh(&br->lock);
+	}
+}
+
+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);
+	}
+}
-- 
1.9.1

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

* [RFC PATCH 07/24] net: rbridge: Add sysfs for trill_state
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (5 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 06/24] net: rbridge: Enable/disable TRILL capability Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 08/24] net: rbridge: Add Rbridge netlink message skeleton Ahmed Amamou
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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_if.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index e561cd5..6edc00b 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -137,6 +137,26 @@ 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)
+{
+	uint8_t val;
+	if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN))
+		return -EPERM;
+	val = (uint8_t) 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)
 {
@@ -198,6 +218,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,
-- 
1.9.1

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

* [RFC PATCH 08/24] net: rbridge: Add Rbridge netlink message skeleton
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (6 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 07/24] net: rbridge: Add sysfs for trill_state Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 17:52   ` Vlad Yasevich
  2014-09-24 15:52 ` [RFC PATCH 09/24] net: rbridge: Get Rbridge nickname from daemon Ahmed Amamou
                   ` (16 subsequent siblings)
  24 siblings, 1 reply; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

add data plane and control plane basic message skeleton
add netlink socket registration and unregistration respectively within module init and deinit function

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
---
 net/bridge/Makefile              |   2 +-
 net/bridge/br.c                  |   6 ++
 net/bridge/br_private.h          |   1 +
 net/bridge/rbridge/rbr_netlink.c | 152 +++++++++++++++++++++++++++++++++++++++
 net/bridge/rbridge/rbr_netlink.h |  62 ++++++++++++++++
 5 files changed, 222 insertions(+), 1 deletion(-)
 create mode 100644 net/bridge/rbridge/rbr_netlink.c
 create mode 100644 net/bridge/rbridge/rbr_netlink.h

diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index 314783c..b11a22b 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -18,4 +18,4 @@ bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o
 
 obj-$(CONFIG_NETFILTER) += netfilter/
 
-bridge-$(CONFIG_TRILL) += rbridge/rbr.o
+bridge-$(CONFIG_TRILL) += rbridge/rbr.o rbridge/rbr_netlink.o
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 1a755a1..51af134 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -178,6 +178,9 @@ static int __init br_init(void)
 #if IS_ENABLED(CONFIG_ATM_LANE)
 	br_fdb_test_addr_hook = br_fdb_test_addr;
 #endif
+#ifdef CONFIG_TRILL
+	rbridge_register_genl();
+#endif
 
 	return 0;
 err_out4:
@@ -210,6 +213,9 @@ static void __exit br_deinit(void)
 	br_fdb_test_addr_hook = NULL;
 #endif
 
+#ifdef CONFIG_TRILL
+	rbridge_unregister_genl();
+#endif
 	br_fdb_fini();
 }
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 844c87b..6952db8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -21,6 +21,7 @@
 #include <linux/if_vlan.h>
 #ifdef CONFIG_TRILL
 #include "rbridge/rbr_private.h"
+#include "rbridge/rbr_netlink.h"
 #endif
 
 #define BR_HASH_BITS 8
diff --git a/net/bridge/rbridge/rbr_netlink.c b/net/bridge/rbridge/rbr_netlink.c
new file mode 100644
index 0000000..eb7c902
--- /dev/null
+++ b/net/bridge/rbridge/rbr_netlink.c
@@ -0,0 +1,152 @@
+/*
+ *	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 <net/genetlink.h>
+#include <net/netlink.h>
+#include <linux/if_trill.h>
+#include <linux/socket.h>
+#include <linux/socket.h>
+#include "br_private.h"
+#include "rbr_private.h"
+#include "rbr_netlink.h"
+
+static struct nla_policy attrs_policy[TRILL_ATTR_MAX + 1] = {
+	[TRILL_ATTR_U16] = {.type = NLA_U16},
+	[TRILL_ATTR_BIN] = {.type = NLA_UNSPEC},
+};
+
+static struct genl_family trill_genl_family = {
+	.id = GENL_ID_GENERATE,
+	.hdrsize = sizeof(struct trill_nl_header),
+	.name = TRILL_NL_FAMILY,
+	.version = TRILL_NL_VERSION,
+	.maxattr = TRILL_ATTR_MAX
+};
+
+static struct genl_multicast_group trill_mcgrps[] = {
+	[TRILL_MCGRP_OFFSET] = {.name = TRILL_MCAST_NAME,},
+};
+
+static int trill_cmd_set_nicks_info(struct sk_buff *skb, struct genl_info *info)
+{
+	return 0;
+}
+
+static int trill_cmd_get_nicks_info(struct sk_buff *skb, struct genl_info *info)
+{
+	return 0;
+}
+
+static int trill_cmd_add_nicks_info(struct sk_buff *skb, struct genl_info *info)
+{
+	return 0;
+}
+
+static int trill_cmd_set_treeroot_id(struct sk_buff *skb,
+				     struct genl_info *info)
+{
+	return 0;
+}
+
+static int trill_cmd_get_rbridge(struct sk_buff *skb, struct genl_info *info)
+{
+	return 0;
+}
+
+static int trill_cmd_set_rbridge(struct sk_buff *skb, struct genl_info *info)
+{
+	return 0;
+}
+
+static int trill_cmd_port_flush(struct sk_buff *skb, struct genl_info *info)
+{
+	return 0;
+}
+
+static int trill_cmd_nick_flush(struct sk_buff *skb, struct genl_info *info)
+{
+	return 0;
+}
+
+static struct genl_ops trill_genl_ops[] = {
+	{
+	 .cmd = TRILL_CMD_SET_NICKS_INFO,
+	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
+	 .policy = attrs_policy,
+	 .doit = trill_cmd_set_nicks_info,
+	 },
+	{
+	 .cmd = TRILL_CMD_GET_NICKS_INFO,
+	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
+	 .policy = attrs_policy,
+	 .doit = trill_cmd_get_nicks_info,
+	 },
+	{
+	 .cmd = TRILL_CMD_ADD_NICKS_INFO,
+	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
+	 .policy = attrs_policy,
+	 .doit = trill_cmd_add_nicks_info,
+	 },
+	{
+	 .cmd = TRILL_CMD_SET_TREEROOT_ID,
+	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
+	 .policy = attrs_policy,
+	 .doit = trill_cmd_set_treeroot_id,
+	 },
+	{
+	 .cmd = TRILL_CMD_GET_RBRIDGE,
+	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
+	 .policy = attrs_policy,
+	 .doit = trill_cmd_get_rbridge,
+	 },
+	{
+	 .cmd = TRILL_CMD_SET_RBRIDGE,
+	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
+	 .policy = attrs_policy,
+	 .doit = trill_cmd_set_rbridge,
+	 },
+	{
+	 .cmd = TRILL_CMD_PORT_FLUSH,
+	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
+	 .doit = trill_cmd_port_flush,
+	 },
+	{
+	 .cmd = TRILL_CMD_NICK_FLUSH,
+	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
+	 .policy = attrs_policy,
+	 .doit = trill_cmd_nick_flush,
+	 },
+};
+
+void __exit rbridge_unregister_genl(void)
+{
+	genl_unregister_family(&trill_genl_family);
+}
+
+int __init rbridge_register_genl(void)
+{
+	int err;
+
+	err =
+	    genl_register_family_with_ops_groups(&trill_genl_family,
+						 trill_genl_ops, trill_mcgrps);
+	if (err)
+		goto fail_genl_register_family;
+
+	return 0;
+
+ fail_genl_register_family:
+
+	return err;
+}
diff --git a/net/bridge/rbridge/rbr_netlink.h b/net/bridge/rbridge/rbr_netlink.h
new file mode 100644
index 0000000..0556323
--- /dev/null
+++ b/net/bridge/rbridge/rbr_netlink.h
@@ -0,0 +1,62 @@
+/*
+ *	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.
+ */
+
+#ifndef RBR_NETLINK_H_
+#define RBR_NETLINK_H_
+
+/* TRILL Generic Netlink attributes definition*/
+#define TRILL_NL_VERSION	0x1
+#define TRILL_NL_FAMILY		"TRILL_NL"
+#define TRILL_MCAST_NAME	"TR_NL_MCAST"
+#define TRILL_MCGRP_OFFSET     0
+
+struct trill_nl_header {
+	int ifindex;		/* port id */
+	int total_length;	/* message total length for mutipart messages check */
+	int msg_number;		/* message number for multipart messages check */
+};
+
+enum {
+	TRILL_ATTR_UNSPEC,
+	TRILL_ATTR_U16,
+	TRILL_ATTR_BIN,
+	__TRILL_ATTR_MAX,
+};
+#define TRILL_ATTR_MAX (__TRILL_ATTR_MAX-1)
+
+/* GET and set are from user space perspective  example TRILL_CMD_GET_BRIDGE
+ * means that the kernel will send this bridge name to userspace
+ */
+enum {
+	TRILL_CMD_UNSPEC,
+	TRILL_CMD_SET_NICKS_INFO,
+	TRILL_CMD_GET_NICKS_INFO,
+	TRILL_CMD_ADD_NICKS_INFO,
+	TRILL_CMD_DEL_NICK,
+	TRILL_CMD_SET_TREEROOT_ID,
+	TRILL_CMD_GET_RBRIDGE,
+	TRILL_CMD_SET_RBRIDGE,
+	TRILL_CMD_PORT_FLUSH,
+	TRILL_CMD_NICK_FLUSH,
+	__TRILL_CMD_MAX,
+};
+#define TRILL_CMD_MAX (__TRILL_CMD_MAX - 1)
+
+int __init rbridge_register_genl(void);
+void __exit rbridge_unregister_genl(void);
+
+/* used to indicate that message is provided by kernel to user space */
+#define KERNL_RESPONSE_INTERFACE -1
+
+#endif				/* RBR_NETLINK_H_ */
-- 
1.9.1

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

* [RFC PATCH 09/24] net: rbridge: Get Rbridge nickname from daemon
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (7 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 08/24] net: rbridge: Add Rbridge netlink message skeleton Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 10/24] net: rbridge: Add elected dtroot Ahmed Amamou
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

added get and set nickname functions that allows daemon to check if
RBridge aleady have a nickname (daemon crash scenario)
if yes and nickname uniqueness is verified on toplogy no set nickname is provided by the daemon
if nickname is not unique or not existant daemon will set the automatically generated nickanme

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/rbridge/rbr_netlink.c | 92 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/net/bridge/rbridge/rbr_netlink.c b/net/bridge/rbridge/rbr_netlink.c
index eb7c902..ccba5ae 100644
--- a/net/bridge/rbridge/rbr_netlink.c
+++ b/net/bridge/rbridge/rbr_netlink.c
@@ -59,14 +59,106 @@ static int trill_cmd_set_treeroot_id(struct sk_buff *skb,
 	return 0;
 }
 
+/* trill_cmd_get_rbridge when started daemon inquire for already
+ * existant nickname
+ * bridge with TRILL capability may already have a nickname
+ * is daemon have crashed
+ */
 static int trill_cmd_get_rbridge(struct sk_buff *skb, struct genl_info *info)
 {
+	struct trill_nl_header *trnlhdr;
+	struct sk_buff *msg;
+	struct net_bridge_port *p;
+	struct net_device *source_port = NULL;
+	struct net *net = sock_net(skb->sk);
+	u16 nickname;
+	int err = -EINVAL;
+	int trill_genlseqnb = info->snd_seq;
+
+	trnlhdr = info->userhdr;
+	if (trnlhdr->ifindex)
+		source_port = __dev_get_by_index(net, trnlhdr->ifindex);
+
+	if (!source_port)
+		goto fail;
+
+	p = br_port_get_rcu(source_port);
+	if (!p || !(p->br))
+		goto fail;
+
+	if (p->br->rbr)
+		nickname = ntohs(p->br->rbr->nick);
+	else
+		nickname = RBRIDGE_NICKNAME_NONE;
+
+	err = -ENOMEM;
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		goto fail;
+
+	trnlhdr = genlmsg_put(msg, info->snd_portid, trill_genlseqnb,
+			      &trill_genl_family, sizeof(*trnlhdr),
+			      TRILL_CMD_GET_RBRIDGE);
+	if (!trnlhdr)
+		goto fail_free;
+
+	trnlhdr->ifindex = KERNL_RESPONSE_INTERFACE;
+	nla_put_u16(msg, TRILL_ATTR_U16, nickname);
+	genlmsg_end(msg, trnlhdr);
+
+	err = genlmsg_reply(msg, info);
+	if (err)
+		goto fail;
+
 	return 0;
+
+ fail_free:
+	nlmsg_free(msg);
+ fail:
+	printk(KERN_WARNING "trill_cmd_get_rbridge FAILED\n");
+	return err;
 }
 
 static int trill_cmd_set_rbridge(struct sk_buff *skb, struct genl_info *info)
 {
+	struct trill_nl_header *trnlhdr;
+	struct net_device *source_port = NULL;
+	struct net_bridge_port *p = NULL;
+	struct net_bridge *br = NULL;
+	struct net *net = sock_net(skb->sk);
+	u16 nickname = nla_get_u16(info->attrs[TRILL_ATTR_U16]);
+
+	trnlhdr = info->userhdr;
+	if (trnlhdr->ifindex)
+		source_port = __dev_get_by_index(net, trnlhdr->ifindex);
+
+	if (!source_port)
+		goto fail;
+
+	p = br_port_get_rcu(source_port);
+	if (!p || !(p->br))
+		goto fail;
+
+	br = p->br;
+
+	/* if daemon has started and bridge TRILL capability
+	 * is not enabled then start it
+	 */
+	if (br->trill_enabled == BR_NO_TRILL)
+		br_trill_set_enabled(br, 1);
+
+	if (!(br->rbr))
+		goto fail;
+
+	spin_lock_bh(&br->lock);
+	br->rbr->nick = htons(nickname);
+	spin_unlock_bh(&br->lock);
+
 	return 0;
+
+ fail:
+	printk(KERN_WARNING "trill_cmd_set_bridge FAILED\n");
+	return -EINVAL;
 }
 
 static int trill_cmd_port_flush(struct sk_buff *skb, struct genl_info *info)
-- 
1.9.1

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

* [RFC PATCH 10/24] net: rbridge: Add elected dtroot
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (8 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 09/24] net: rbridge: Get Rbridge nickname from daemon Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-25 11:30   ` Sergei Shtylyov
  2014-09-24 15:52 ` [RFC PATCH 11/24] net: rbridge: Add rbr_node management function Ahmed Amamou
                   ` (14 subsequent siblings)
  24 siblings, 1 reply; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

provide function to get the locally elected distributed tree root from the daemon
in TRILL RFC multiple tree root can be elected but this is not mendatory
for this first version we use a unique distributed tree root

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          |  1 +
 net/bridge/rbridge/rbr.c         | 17 +++++++++++++++++
 net/bridge/rbridge/rbr_netlink.c | 21 +++++++++++++++++++++
 3 files changed, 39 insertions(+)

diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 6952db8..2d15b35 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -815,6 +815,7 @@ ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id);
 /* rbridge/rbr.c */
 #ifdef CONFIG_TRILL
 void br_trill_set_enabled(struct net_bridge *br, unsigned long val);
+extern int set_treeroot(struct rbr *rbr, uint16_t treeroot);
 #endif
 
 /* br_stp_bpdu.c */
diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index 41d47db..8d6d37e 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/rbr.c
@@ -76,3 +76,20 @@ 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) {
+		spin_lock_bh(&rbr->br->lock);
+		rbr->treeroot = treeroot;
+		spin_unlock_bh(&rbr->br->lock);
+	}
+	return 0;
+ set_tree_root_fail:
+	return ENOENT;
+}
diff --git a/net/bridge/rbridge/rbr_netlink.c b/net/bridge/rbridge/rbr_netlink.c
index ccba5ae..889e6c8 100644
--- a/net/bridge/rbridge/rbr_netlink.c
+++ b/net/bridge/rbridge/rbr_netlink.c
@@ -56,7 +56,28 @@ static int trill_cmd_add_nicks_info(struct sk_buff *skb, struct genl_info *info)
 static int trill_cmd_set_treeroot_id(struct sk_buff *skb,
 				     struct genl_info *info)
 {
+	int err = -EINVAL;
+	u16 nickname;
+	struct trill_nl_header *trnlhdr;
+	struct net_device *source_port = NULL;
+	struct net *net = sock_net(skb->sk);
+	struct net_bridge_port *p = NULL;
+	nickname = nla_get_u16(info->attrs[TRILL_ATTR_U16]);
+	trnlhdr = info->userhdr;
+	if (trnlhdr->ifindex)
+		source_port = __dev_get_by_index(net, trnlhdr->ifindex);
+	if (!source_port)
+		goto fail;
+	p = br_port_get_rcu(source_port);
+	if (!p || !(p->br) || !(p->br->rbr))
+		goto fail;
+	err = set_treeroot(p->br->rbr, htons(nickname));
+	if (err)
+		goto fail;
 	return 0;
+ fail:
+	printk(KERN_WARNING "trill_cmd_set_treeroot_id FAILED\n");
+	return err;
 }
 
 /* trill_cmd_get_rbridge when started daemon inquire for already
-- 
1.9.1

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

* [RFC PATCH 11/24] net: rbridge: Add rbr_node management function
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (9 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 10/24] net: rbridge: Add elected dtroot Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-25 11:24   ` Sergei Shtylyov
  2014-09-24 15:52 ` [RFC PATCH 12/24] net: rbridge: Clean up rbr_node on rbridge stop Ahmed Amamou
                   ` (13 subsequent siblings)
  24 siblings, 1 reply; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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/rbridge/rbr.c         | 34 ++++++++++++++++++++++++++++++++++
 net/bridge/rbridge/rbr_private.h | 26 ++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index 8d6d37e..1df8f8d 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/rbr.c
@@ -93,3 +93,37 @@ 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 != NULL)) {
+			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] != NULL))
+			rbr_del_node(rbr, i);
+	}
+}
diff --git a/net/bridge/rbridge/rbr_private.h b/net/bridge/rbridge/rbr_private.h
index f21e4a5..68485d3 100644
--- a/net/bridge/rbridge/rbr_private.h
+++ b/net/bridge/rbridge/rbr_private.h
@@ -44,6 +44,32 @@ struct rbr {
 	struct net_bridge *br;	/* back pointer */
 };
 
+static inline void rbr_node_free(struct rbr_node *rbr_node)
+{
+	if (likely(rbr_node != NULL)) {
+		if (rbr_node->rbr_ni != NULL)
+			kfree(rbr_node->rbr_ni);
+		kfree(rbr_node);
+	}
+}
+
+static inline void rbr_node_get(struct rbr_node *rbr_node)
+{
+	if (likely(rbr_node != NULL))
+		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) ((uint16_t *)((struct rbr_nickinfo *)(v)+1))
 #define	RBR_NI_ADJNICK(v, n) (RBR_NI_ADJNICKSPTR(v)[(n)])
-- 
1.9.1

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

* [RFC PATCH 12/24] net: rbridge: Clean up rbr_node on rbridge stop
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (10 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 11/24] net: rbridge: Add rbr_node management function Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 13/24] net: rbridge: Add set_node function Ahmed Amamou
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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/rbridge/rbr.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index 1df8f8d..edd1e7c 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/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)
 {
@@ -61,6 +62,7 @@ static void br_trill_stop(struct net_bridge *br)
 	br->rbr = NULL;
 	if (likely(old)) {
 		spin_lock_bh(&br->lock);
+		rbr_del_all(old);
 		kfree(old);
 		spin_unlock_bh(&br->lock);
 	}
-- 
1.9.1

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

* [RFC PATCH 13/24] net: rbridge: Add set_node function
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (11 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 12/24] net: rbridge: Clean up rbr_node on rbridge stop Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-25 11:34   ` Sergei Shtylyov
  2014-09-24 15:52 ` [RFC PATCH 14/24] net: rbridge: Add get_node function Ahmed Amamou
                   ` (11 subsequent siblings)
  24 siblings, 1 reply; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

allow daemon to set distant Rbridges information in local database
daemon has to periodically update distant Rbridges informations in local database
create a new node only if change on distant RBridge information are detected

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/rbridge/rbr_netlink.c | 78 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/net/bridge/rbridge/rbr_netlink.c b/net/bridge/rbridge/rbr_netlink.c
index 889e6c8..bb893f0 100644
--- a/net/bridge/rbridge/rbr_netlink.c
+++ b/net/bridge/rbridge/rbr_netlink.c
@@ -38,9 +38,87 @@ static struct genl_multicast_group trill_mcgrps[] = {
 	[TRILL_MCGRP_OFFSET] = {.name = TRILL_MCAST_NAME,},
 };
 
+static int create_node(struct net_bridge_port *p, struct rbr *rbr,
+		       struct rbr_nickinfo *rbr_ni_partial,
+		       struct genl_info *info)
+{
+	size_t size = 0;
+	size_t old_size = 0;
+	struct rbr_node *old;
+	struct rbr_nickinfo *rbr_ni;
+
+	if (rbr_ni_partial == NULL)
+		return -EINVAL;
+
+	size = RBR_NI_TOTALSIZE(rbr_ni_partial);
+	if (size > PAGE_SIZE - sizeof(struct trill_nl_header)) {
+		pr_warn_ratelimited
+		    ("create_node: size > (PAGE_SIZE-nickinfo_offset)\n");
+		return -EINVAL;
+	}
+	rbr_ni = kzalloc(size, GFP_KERNEL);
+	if (!rbr_ni)
+		return -ENOMEM;
+	old = rbr->rbr_nodes[rbr_ni_partial->nick];
+	nla_memcpy(rbr_ni, info->attrs[TRILL_ATTR_BIN], size);
+	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 == NULL || 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);
+			return -ENOMEM;
+		}
+		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[rbr_ni->nick], new);
+		if (old)
+			rbr_node_put(old);
+	} else {
+		kfree(rbr_ni);
+	}
+
+	return 0;
+}
+
 static int trill_cmd_set_nicks_info(struct sk_buff *skb, struct genl_info *info)
 {
+	struct trill_nl_header *trnlhdr;
+	struct rbr_nickinfo rbr_ni;
+	struct net_device *source_port = NULL;
+	struct net *net = sock_net(skb->sk);
+	struct net_bridge_port *p = NULL;
+	int err = -EINVAL;
+
+	nla_memcpy(&rbr_ni, info->attrs[TRILL_ATTR_BIN], sizeof(rbr_ni));
+	if (!VALID_NICK(rbr_ni.nick))
+		goto fail;
+
+	trnlhdr = info->userhdr;
+	if (trnlhdr->ifindex)
+		source_port = __dev_get_by_index(net, trnlhdr->ifindex);
+
+	if (!source_port)
+		goto fail;
+
+	p = br_port_get_rcu(source_port);
+	if (!p || !(p->br) || !(p->br->rbr))
+		goto fail;
+
+	err = create_node(p, p->br->rbr, &rbr_ni, info);
+	if (err)
+		goto fail;
+
 	return 0;
+
+ fail:
+	printk(KERN_WARNING "trill_cmd_set_nicks_info FAILED\n");
+	return err;
 }
 
 static int trill_cmd_get_nicks_info(struct sk_buff *skb, struct genl_info *info)
-- 
1.9.1

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

* [RFC PATCH 14/24] net: rbridge: Add get_node function
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (12 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 13/24] net: rbridge: Add set_node function Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 15/24] net: rbridge: Add basic trill frame handling function Ahmed Amamou
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

allow daemon to get any node information
daemon has to provide a netlink message containing the nickname of
requested node.
This function is provided but not used by the daemon for the moment
it can be used to check information accuracy in futur version

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/rbridge/rbr_netlink.c | 61 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/net/bridge/rbridge/rbr_netlink.c b/net/bridge/rbridge/rbr_netlink.c
index bb893f0..983d647 100644
--- a/net/bridge/rbridge/rbr_netlink.c
+++ b/net/bridge/rbridge/rbr_netlink.c
@@ -123,7 +123,68 @@ static int trill_cmd_set_nicks_info(struct sk_buff *skb, struct genl_info *info)
 
 static int trill_cmd_get_nicks_info(struct sk_buff *skb, struct genl_info *info)
 {
+	struct sk_buff *msg;
+	struct nlattr *attr;
+	struct rbr_nickinfo rbr_ni;
+	void *data;
+	struct trill_nl_header *trnlhdr;
+	struct net_device *source_port = NULL;
+	struct net *net = sock_net(skb->sk);
+	struct net_bridge_port *p = NULL;
+	struct rbr_node *rbr_node;
+	int err = -EINVAL;
+
+	nla_memcpy(&rbr_ni, info->attrs[TRILL_ATTR_BIN], sizeof(rbr_ni));
+	trnlhdr = info->userhdr;
+	if (trnlhdr->ifindex)
+		source_port = __dev_get_by_index(net, trnlhdr->ifindex);
+
+	if (!source_port)
+		goto fail;
+
+	p = br_port_get_rcu(source_port);
+	if (!p || !(p->br) || !(p->br->rbr))
+		goto fail;
+
+	rbr_node = rbr_find_node(p->br->rbr, rbr_ni.nick);
+	if (!rbr_node)
+		goto fail;
+
+	err = -ENOMEM;
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		goto fail_put;
+
+	trnlhdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+			      &trill_genl_family, sizeof(*trnlhdr),
+			      TRILL_CMD_GET_NICKS_INFO);
+	if (!trnlhdr)
+		goto fail_free;
+
+	attr = nla_reserve(msg, TRILL_ATTR_BIN,
+			   RBR_NI_TOTALSIZE(rbr_node->rbr_ni));
+	if (!attr)
+		goto fail_free;
+
+	data = nla_data(attr);
+	trnlhdr->ifindex = KERNL_RESPONSE_INTERFACE;
+	memcpy(data, rbr_node->rbr_ni, RBR_NI_TOTALSIZE(rbr_node->rbr_ni));
+	genlmsg_end(msg, trnlhdr);
+	rbr_node_put(rbr_node);
+
+	err = genlmsg_reply(msg, info);
+	if (err)
+		goto fail_put;
+
 	return 0;
+
+ fail_free:
+	nlmsg_free(msg);
+ fail_put:
+	rbr_node_put(rbr_node);
+ fail:
+	printk(KERN_WARNING "trill_cmd_get_nicks_info FAILED\n");
+	return err;
 }
 
 static int trill_cmd_add_nicks_info(struct sk_buff *skb, struct genl_info *info)
-- 
1.9.1

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

* [RFC PATCH 15/24] net: rbridge: Add basic trill frame handling function
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (13 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 14/24] net: rbridge: Add get_node function Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 19:23   ` Francois Romieu
  2014-09-24 15:52 ` [RFC PATCH 16/24] net: rbridge: Update forwarding database Ahmed Amamou
                   ` (9 subsequent siblings)
  24 siblings, 1 reply; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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>
---
 net/bridge/rbridge/rbr.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index edd1e7c..4b41d4c 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/rbr.c
@@ -129,3 +129,103 @@ 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 (preempt_disabled)
+ */
+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);
+	if (unlikely(!p))
+		goto drop_no_stat;
+	br = p->br;
+
+	/* if trill is not enabled, handle by bridge */
+	if (br->trill_enabled == BR_NO_TRILL) {
+		goto handle_by_bridge;
+	} else {
+		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 ==
+			    __constant_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;
+			} else {
+				/* packet is destinated to localhost */
+				if (ether_addr_equal(p->br->dev->dev_addr,
+							eth_hdr(skb)->h_dest)) {
+					skb->pkt_type = PACKET_HOST;
+					br_handle_frame_finish(skb);
+					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;
+ handle_by_bridge:
+	/* trill is not enable return to bridge handle function */
+	return br_handle_frame(pskb);
+}
-- 
1.9.1

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

* [RFC PATCH 16/24] net: rbridge: Update forwarding database
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (14 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 15/24] net: rbridge: Add basic trill frame handling function Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 17/24] net: rbridge: Add test on trill flag before flood Ahmed Amamou
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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     | 40 ++++++++++++++++++++++++++++++++++++++++
 net/bridge/br_private.h | 11 +++++++++++
 2 files changed, 51 insertions(+)

diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 6f6c95c..544151f 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -531,8 +531,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;
@@ -566,6 +572,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);
@@ -584,6 +594,17 @@ 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)
@@ -1014,3 +1035,22 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
 		}
 	}
 }
+#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 2d15b35..37456cf 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -118,6 +118,9 @@ struct net_bridge_fdb_entry
 	unsigned char			is_static;
 	unsigned char			added_by_user;
 	__u16				vlan_id;
+#ifdef CONFIG_TRILL
+	__u16				nick; /* destination's nickname */
+#endif
 };
 
 struct net_bridge_port_group {
@@ -428,6 +431,14 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
 		struct net_device *dev, struct net_device *fdev, int idx);
 int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
 void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
+#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);
-- 
1.9.1

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

* [RFC PATCH 17/24] net: rbridge: Add test on trill flag before flood
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (15 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 16/24] net: rbridge: Update forwarding database Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 18/24] net: rbridge: Add encapsulation process Ahmed Amamou
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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 | 38 ++++++++++++++++++++++++++++++++++++++
 net/bridge/br_private.h |  4 ++++
 2 files changed, 42 insertions(+)

diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 056b67b..a8b3c5d 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -170,7 +170,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;
@@ -181,6 +185,10 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb,
 		/* Do not flood unicast traffic to ports that turn it off */
 		if (unicast && !(p->flags & BR_FLOOD))
 			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;
@@ -202,17 +210,47 @@ out:
 
 
 /* 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 37456cf..152545e 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -449,6 +449,10 @@ int br_forward_finish(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);
-- 
1.9.1

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

* [RFC PATCH 18/24] net: rbridge: Add encapsulation process
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (16 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 17/24] net: rbridge: Add test on trill flag before flood Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 19/24] net: rbridge: Add receive function Ahmed Amamou
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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/rbridge/rbr.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 121 insertions(+), 2 deletions(-)

diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index 4b41d4c..488c75d 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/rbr.c
@@ -13,6 +13,8 @@
  */
 #include "br_private.h"
 #include "rbr_private.h"
+#include <linux/if_trill.h>
+
 static void rbr_del_all(struct rbr *rbr);
 
 static struct rbr *add_rbr(struct net_bridge *br)
@@ -130,6 +132,121 @@ static void rbr_del_all(struct rbr *rbr)
 	}
 }
 
+static bool add_header(struct sk_buff *skb, uint16_t ingressnick,
+		       uint16_t 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 == NULL) {
+			printk(KERN_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))) {
+		printk(KERN_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 */
+	skb_push(skb, ETH_HLEN);	/* make skb->mac_header point to outer mac header */
+	skb_reset_mac_header(skb);	/* instead of the inner one */
+	eth_hdr(skb)->h_proto = __constant_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, uint16_t egressnick, u16 vid)
+{
+	uint16_t local_nick;
+	uint16_t dtrNick;
+	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 */
+	if (unlikely((self = rbr_find_node(rbr, local_nick)) == NULL)) {
+		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)
+			dtrNick = RBR_NI_DTROOTNICK(self->rbr_ni, 0);
+		else
+			dtrNick = rbr->treeroot;
+		rbr_node_put(self);
+		if (unlikely(!VALID_NICK(dtrNick))) {
+			pr_warn_ratelimited
+			    ("rbr_encaps_prepare: dtrNick is unvalid\n");
+			goto encaps_drop;
+		}
+		if (unlikely((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)) {
+			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, dtrNick, 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);
+	return;
+}
+
 /* handling function hook allow handling
  * a frame upon reception called via
  * br_handle_frame_hook = rbr_handle_frame
@@ -143,6 +260,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;
+	uint16_t nick;
 
 	p = br_port_get_rcu(skb->dev);
 	if (unlikely(!p))
@@ -189,7 +307,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) {
@@ -205,7 +324,7 @@ rx_handler_result_t rbr_handle_frame(struct sk_buff **pskb)
 			} else {
 				/* packet is destinated to localhost */
 				if (ether_addr_equal(p->br->dev->dev_addr,
-							eth_hdr(skb)->h_dest)) {
+						     eth_hdr(skb)->h_dest)) {
 					skb->pkt_type = PACKET_HOST;
 					br_handle_frame_finish(skb);
 					return RX_HANDLER_CONSUMED;
-- 
1.9.1

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

* [RFC PATCH 19/24] net: rbridge: Add receive function
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (17 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 18/24] net: rbridge: Add encapsulation process Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 20/24] net: rbridge: Add multicast recv handling Ahmed Amamou
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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/rbridge/rbr.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 104 insertions(+), 1 deletion(-)

diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index 488c75d..29ef0f7 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/rbr.c
@@ -247,6 +247,109 @@ static void rbr_encaps(struct sk_buff *skb, uint16_t egressnick, u16 vid)
 	return;
 }
 
+static void rbr_recv(struct sk_buff *skb, u16 vid)
+{
+	uint16_t local_nick, dtrNick, adjnick, idx;;
+	struct rbr *rbr;
+	uint8_t srcaddr[ETH_ALEN];
+	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;
+	} else {
+		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) == 0)
+		goto recv_drop;
+	memcpy(srcaddr, eth_hdr(skb)->h_source, ETH_ALEN);
+	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;
+	dtrNick = 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) {
+			/* TODO decapsulate function */
+		} else if (likely(trill_get_hopcount(trill_flags))) {
+			br_fdb_update(p->br, p, srcaddr, vid, false);
+			/* TODO simple forwarding */
+		} else {
+			pr_warn_ratelimited
+			    ("rbr_recv: hop count limit reached\n");
+			goto recv_drop;
+		}
+		return;
+	}
+
+	return;
+
+ recv_drop:
+	if (likely(p && p->br))
+		p->br->dev->stats.rx_dropped++;
+	kfree_skb(skb);
+	return;
+}
+
 /* handling function hook allow handling
  * a frame upon reception called via
  * br_handle_frame_hook = rbr_handle_frame
@@ -319,7 +422,7 @@ rx_handler_result_t rbr_handle_frame(struct sk_buff **pskb)
 				 * Packet is from trunk port, decapsulate if destined to access port
 				 * or trill forward to next hop
 				 */
-				/* TODO */
+				rbr_recv(skb, vid);
 				return RX_HANDLER_CONSUMED;
 			} else {
 				/* packet is destinated to localhost */
-- 
1.9.1

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

* [RFC PATCH 20/24] net: rbridge: Add multicast recv handling
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (18 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 19/24] net: rbridge: Add receive function Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 21/24] net: rbridge: Add decapsulation function Ahmed Amamou
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

in receiving function: add multicast frame processing

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/rbridge/rbr.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index 29ef0f7..9206682 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/rbr.c
@@ -340,6 +340,91 @@ static void rbr_recv(struct sk_buff *skb, u16 vid)
 		}
 		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 == NULL)) {
+		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 (adj == NULL)
+			continue;
+		if (memcmp(adj->rbr_ni->adjsnpa, srcaddr, 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 unknow 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 == NULL)) {
+		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 != dtrNick) {
+			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 */
+	if (unlikely((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)) {
+		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
+	 */
+	/* TODO decapsulate function */
 
 	return;
 
-- 
1.9.1

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

* [RFC PATCH 21/24] net: rbridge: Add decapsulation function
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (19 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 20/24] net: rbridge: Add multicast recv handling Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 22/24] net: rbridge: Add rbr_fwd Ahmed Amamou
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

for frame destined to local RBridge (egress Rbridge == local_nick)
have de be decapsuled and forwarded to corresponding host
if frame is from type multicast a copy has 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>
---
 net/bridge/rbridge/rbr.c | 56 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 53 insertions(+), 3 deletions(-)

diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index 9206682..8aa5182 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/rbr.c
@@ -247,9 +247,59 @@ static void rbr_encaps(struct sk_buff *skb, uint16_t egressnick, u16 vid)
 	return;
 }
 
+static void rbr_decap_finish(struct sk_buff *skb, u16 vid)
+{
+	struct net_bridge *br;
+	const unsigned char *dest = eth_hdr(skb)->h_dest;
+	struct net_bridge_fdb_entry *dst;
+	struct net_device *dev = skb->dev;
+
+	br = netdev_priv(dev);
+	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 == NULL))
+		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;
+	/* Mark bridge as source device */
+	skb->dev = p->br->dev;
+	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)
 {
-	uint16_t local_nick, dtrNick, adjnick, idx;;
+	uint16_t local_nick, dtrNick, adjnick, idx;
 	struct rbr *rbr;
 	uint8_t srcaddr[ETH_ALEN];
 	struct trill_hdr *trh;
@@ -329,7 +379,7 @@ static void rbr_recv(struct sk_buff *skb, u16 vid)
 			goto recv_drop;
 		}
 		if (trh->th_egressnick == local_nick) {
-			/* TODO decapsulate function */
+			rbr_decaps(p, skb, trhsize, vid);
 		} else if (likely(trill_get_hopcount(trill_flags))) {
 			br_fdb_update(p->br, p, srcaddr, vid, false);
 			/* TODO simple forwarding */
@@ -424,7 +474,7 @@ static void rbr_recv(struct sk_buff *skb, u16 vid)
 	/*
 	 * Send de-capsulated frame locally
 	 */
-	/* TODO decapsulate function */
+	rbr_decaps(p, skb, trhsize, vid);
 
 	return;
 
-- 
1.9.1

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

* [RFC PATCH 22/24] net: rbridge: Add rbr_fwd
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (20 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 21/24] net: rbridge: Add decapsulation function Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-25 11:43   ` Sergei Shtylyov
  2014-09-24 15:52 ` [RFC PATCH 23/24] net: rbridge: Add rbr_multidest_fwd Ahmed Amamou
                   ` (2 subsequent siblings)
  24 siblings, 1 reply; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, Ahmed Amamou, Kamel Haddadou

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/rbridge/rbr.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index 8aa5182..39aa816c 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/rbr.c
@@ -177,6 +177,51 @@ 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,
+		    uint16_t adj_nick, u16 vid)
+{
+	struct rbr_node *adj;
+	struct trill_hdr *trh;
+	struct ethhdr *outerethhdr;
+	struct net *net = dev_net(p->br->dev);
+	struct net_device *outdev;
+
+	adj = rbr_find_node(p->br->rbr, adj_nick);
+    outdev = __dev_get_by_index(net, adj->rbr_ni->linkid);
+	if (!outdev) {
+		pr_warn_ratelimited("rbr_fwd: cannot find source port device for forwrding\n");
+		goto dest_fwd_fail;
+    }
+	if (unlikely(adj == NULL)) {
+		pr_warn_ratelimited
+		    ("rbr_fwd: unable to find adjacent RBridge\n");
+		goto dest_fwd_fail;
+	}
+
+	trh = (struct trill_hdr *)skb->data;
+	trillhdr_dec_hopcount(trh);
+	outerethhdr = eth_hdr(skb);
+
+	/* change outer ether header */
+	/* bridge become the source_port address in outeretherhdr */
+	memcpy(outerethhdr->h_source, p->br->dev->dev_addr, ETH_ALEN);
+	/* dist port become dest address in outeretherhdr */
+	memcpy(outerethhdr->h_dest, adj->rbr_ni->adjsnpa, ETH_ALEN);
+	rbr_node_put(adj);
+	/* set Bridge as source device */
+	skb->dev = p->br->dev;
+	br_forward(br_port_get_rcu(outdev), skb, NULL);
+
+	return;
+
+ dest_fwd_fail:
+	if (likely(p && p->br))
+		p->br->dev->stats.tx_dropped++;
+	kfree_skb(skb);
+	return;
+}
+
+
 static void rbr_encaps(struct sk_buff *skb, uint16_t egressnick, u16 vid)
 {
 	uint16_t local_nick;
@@ -236,7 +281,7 @@ static void rbr_encaps(struct sk_buff *skb, uint16_t 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;
 
@@ -382,7 +427,7 @@ static void rbr_recv(struct sk_buff *skb, u16 vid)
 			rbr_decaps(p, skb, trhsize, vid);
 		} else if (likely(trill_get_hopcount(trill_flags))) {
 			br_fdb_update(p->br, p, srcaddr, vid, false);
-			/* TODO simple forwarding */
+			rbr_fwd(p, skb, trh->th_egressnick, vid);
 		} else {
 			pr_warn_ratelimited
 			    ("rbr_recv: hop count limit reached\n");
-- 
1.9.1

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

* [RFC PATCH 23/24] net: rbridge: Add rbr_multidest_fwd
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (21 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 22/24] net: rbridge: Add rbr_fwd Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 15:52 ` [RFC PATCH 24/24] net: rbridge: replace net_port rx_handler Ahmed Amamou
  2014-09-24 16:44 ` [RFC PATCH 00/24] TRILL implementation Stephen Hemminger
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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>
---
 net/bridge/rbridge/rbr.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 92 insertions(+), 2 deletions(-)

diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
index 39aa816c..99272ac 100644
--- a/net/bridge/rbridge/rbr.c
+++ b/net/bridge/rbridge/rbr.c
@@ -221,6 +221,94 @@ static void rbr_fwd(struct net_bridge_port *p, struct sk_buff *skb,
 	return;
 }
 
+static int rbr_multidest_fwd(struct net_bridge_port *p,
+			     struct sk_buff *skb, uint16_t egressnick,
+			     uint16_t ingressnick, const uint8_t * saddr,
+			     u16 vid, bool free)
+{
+	struct rbr *rbr;
+	struct rbr_node *dest;
+	struct rbr_node *adj;
+	struct sk_buff *skb2;
+	uint16_t adjnicksaved = 0;
+	uint16_t 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 == NULL))
+		goto multidest_fwd_fail;
+
+	/* Lookup the egress nick info, this is the DT root */
+	if ((dest = rbr_find_node(rbr, egressnick)) == NULL) {
+		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);
+		if (!VALID_NICK(adjnick) || ingressnick == adjnick ||
+		    ((adj = rbr_find_node(rbr, adjnick)) == NULL))
+			continue;
+		/* Do not forward back to adjacency that sent the pkt to us */
+		if ((saddr != NULL) &&
+		    (memcmp(adj->rbr_ni->adjsnpa, saddr, ETH_ALEN) == 0)) {
+			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 adress
+		 */
+		if (unlikely((skb2 = skb_copy(skb, GFP_ATOMIC)) == NULL)) {
+			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, uint16_t egressnick, u16 vid)
 {
@@ -277,7 +365,7 @@ static void rbr_encaps(struct sk_buff *skb, uint16_t egressnick, u16 vid)
 		br_flood_deliver_flags(p->br, skb2, true, TRILL_FLAG_ACCESS);
 		if (unlikely(add_header(skb, local_nick, dtrNick, 1)))
 			goto encaps_drop;
-		/* TODO Multi forward */
+		rbr_multidest_fwd(p, skb, dtrNick, local_nick, NULL, vid, true);
 	} else {
 		if (unlikely(add_header(skb, local_nick, egressnick, 0)))
 			goto encaps_drop;
@@ -514,7 +602,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,
+			      srcaddr, vid, false))
+		goto recv_drop;
 
 	/*
 	 * Send de-capsulated frame locally
-- 
1.9.1

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

* [RFC PATCH 24/24] net: rbridge: replace net_port rx_handler
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (22 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 23/24] net: rbridge: Add rbr_multidest_fwd Ahmed Amamou
@ 2014-09-24 15:52 ` Ahmed Amamou
  2014-09-24 16:44 ` [RFC PATCH 00/24] TRILL implementation Stephen Hemminger
  24 siblings, 0 replies; 46+ messages in thread
From: Ahmed Amamou @ 2014-09-24 15:52 UTC (permalink / raw)
  To: netdev; +Cc: william, f.cachereul, 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      | 4 ++++
 net/bridge/br_private.h | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 078d336..7e6c6a0 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -480,7 +480,11 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	if (err)
 		goto err4;
 
+#ifdef CONFIG_TRILL
+	err = netdev_rx_handler_register(dev, rbr_handle_frame, p);
+#else
 	err = netdev_rx_handler_register(dev, br_handle_frame, p);
+#endif
 	if (err)
 		goto err5;
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 152545e..31bccf8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -876,4 +876,8 @@ static inline int br_sysfs_addbr(struct net_device *dev) { return 0; }
 static inline void br_sysfs_delbr(struct net_device *dev) { return; }
 #endif /* CONFIG_SYSFS */
 
+#ifdef CONFIG_TRILL
+/* rbridge/rbr.c */
+extern rx_handler_result_t rbr_handle_frame(struct sk_buff **pskb);
+#endif /* CONFIG_TRILL */
 #endif
-- 
1.9.1

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

* Re: [RFC PATCH 01/24] net: rbridge: add trill frame description
  2014-09-24 15:51 ` [RFC PATCH 01/24] net: rbridge: add trill frame description Ahmed Amamou
@ 2014-09-24 16:38   ` Stephen Hemminger
  2014-09-24 16:48     ` William Dauchy
  2014-09-24 17:01   ` Cong Wang
  1 sibling, 1 reply; 46+ messages in thread
From: Stephen Hemminger @ 2014-09-24 16:38 UTC (permalink / raw)
  To: Ahmed Amamou
  Cc: netdev, william, f.cachereul, Emmanuel Hocdet, Kamel Haddadou

On Wed, 24 Sep 2014 17:51:57 +0200
Ahmed Amamou <ahmed@gandi.net> wrote:

> add basic trill header description and basic header getter and setter fuctions
> 
> Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
> Signed-off-by: Emmanuel Hocdet <manu@gandi.net>
> Signed-off-by: Kamel Haddadou <kamel@gandi.net>

Excessive paren's.

Did you even run this through checkpatch?

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

* Re: [RFC PATCH 03/24] net: rbridge: Add RBridge structure
  2014-09-24 15:51 ` [RFC PATCH 03/24] net: rbridge: Add RBridge structure Ahmed Amamou
@ 2014-09-24 16:40   ` Stephen Hemminger
  2014-09-24 16:55     ` William Dauchy
  2014-09-24 17:18   ` Cong Wang
  1 sibling, 1 reply; 46+ messages in thread
From: Stephen Hemminger @ 2014-09-24 16:40 UTC (permalink / raw)
  To: Ahmed Amamou; +Cc: netdev, william, f.cachereul, Kamel Haddadou

On Wed, 24 Sep 2014 17:51:59 +0200
Ahmed Amamou <ahmed@gandi.net> wrote:

> +struct rbr_nickinfo {
> +	/* Nickname of the RBridge */
> +	uint16_t nick;
> +	/* Next-hop SNPA address to reach this RBridge */
> +	u8 adjsnpa[ETH_ALEN];

Be consistent, always use kernel types (u16) not stdint types (uint16_t)

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

* Re: [RFC PATCH 00/24] TRILL implementation
  2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
                   ` (23 preceding siblings ...)
  2014-09-24 15:52 ` [RFC PATCH 24/24] net: rbridge: replace net_port rx_handler Ahmed Amamou
@ 2014-09-24 16:44 ` Stephen Hemminger
  2014-09-24 16:54   ` William Dauchy
  24 siblings, 1 reply; 46+ messages in thread
From: Stephen Hemminger @ 2014-09-24 16:44 UTC (permalink / raw)
  To: Ahmed Amamou; +Cc: netdev, william, f.cachereul

On Wed, 24 Sep 2014 17:51:56 +0200
Ahmed Amamou <ahmed@gandi.net> wrote:

> Hi,
> 
> We have been working on a TRILL implementation in the Linux kernel for some
> months now.  The code has been pushed here https://github.com/Gandi/ktrill.git
> along the way.  Attached a series of patch as a first proposition.  The code is
> not perfect and probably still lacks of improvements. It's a first request of
> comment in order to get some feedbacks. This code has been tested for some
> months now.
> 
> These patch tries to implement TRILL protocol RFC 6325.  As a First
> implementation, some RFC details are still not implemented.
> 
> We still need to fix these points: 
> - The use of rtnetlink instead of the actual netlink.
> - BPDU handling
> 
> Also some parts may not be fully linux compliant, so we are waiting for
> comments
> 
> In order to test theses patches please follow this small wiki 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 --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

Is this patch series bisectable? does it build at each step?

Also, it seems when you build with trill you lose normal bridge functionality.
Whether kernel is doing bridge or rbridge has to be a runtime (not compile time)
choice on a per-bridge basis.

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

* Re: [RFC PATCH 01/24] net: rbridge: add trill frame description
  2014-09-24 16:38   ` Stephen Hemminger
@ 2014-09-24 16:48     ` William Dauchy
  2014-09-24 17:26       ` Cong Wang
  0 siblings, 1 reply; 46+ messages in thread
From: William Dauchy @ 2014-09-24 16:48 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Ahmed Amamou, netdev, william, f.cachereul, Emmanuel Hocdet,
	Kamel Haddadou

[-- Attachment #1: Type: text/plain, Size: 221 bytes --]

On Sep24 09:38, Stephen Hemminger wrote:
> Excessive paren's.

true; to be exact, forgot to add a patch that was fixing this.

> Did you even run this through checkpatch?

no but we will.

Thanks,
-- 
William

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

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

* Re: [RFC PATCH 00/24] TRILL implementation
  2014-09-24 16:44 ` [RFC PATCH 00/24] TRILL implementation Stephen Hemminger
@ 2014-09-24 16:54   ` William Dauchy
  2014-09-24 17:24     ` Cong Wang
  2014-09-24 20:57     ` Francois Romieu
  0 siblings, 2 replies; 46+ messages in thread
From: William Dauchy @ 2014-09-24 16:54 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Ahmed Amamou, netdev, william, f.cachereul

[-- Attachment #1: Type: text/plain, Size: 457 bytes --]

On Sep24 09:44, Stephen Hemminger wrote:
> Is this patch series bisectable? does it build at each step?

it should be the case but we will double check that.

> Also, it seems when you build with trill you lose normal bridge functionality.
> Whether kernel is doing bridge or rbridge has to be a runtime (not compile time)
> choice on a per-bridge basis.

The normal bridge functionnality are still ok until TRILL is not
enabled.

-- 
William

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

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

* Re: [RFC PATCH 03/24] net: rbridge: Add RBridge structure
  2014-09-24 16:40   ` Stephen Hemminger
@ 2014-09-24 16:55     ` William Dauchy
  0 siblings, 0 replies; 46+ messages in thread
From: William Dauchy @ 2014-09-24 16:55 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Ahmed Amamou, netdev, william, f.cachereul, Kamel Haddadou

[-- Attachment #1: Type: text/plain, Size: 156 bytes --]

On Sep24 09:40, Stephen Hemminger wrote:
> Be consistent, always use kernel types (u16) not stdint types (uint16_t)

true, we'll fix that
-- 
William

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

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

* Re: [RFC PATCH 01/24] net: rbridge: add trill frame description
  2014-09-24 15:51 ` [RFC PATCH 01/24] net: rbridge: add trill frame description Ahmed Amamou
  2014-09-24 16:38   ` Stephen Hemminger
@ 2014-09-24 17:01   ` Cong Wang
  1 sibling, 0 replies; 46+ messages in thread
From: Cong Wang @ 2014-09-24 17:01 UTC (permalink / raw)
  To: Ahmed Amamou
  Cc: netdev, william, f.cachereul, Emmanuel Hocdet, Kamel Haddadou

On Wed, Sep 24, 2014 at 8:51 AM, Ahmed Amamou <ahmed@gandi.net> wrote:
> diff --git a/include/linux/if_trill.h b/include/linux/if_trill.h
> new file mode 100644
> index 0000000..ad9c631
> --- /dev/null
> +++ b/include/linux/if_trill.h

Keep it in include/net/ directory unless you plan to use it for non-networking,
I don't think this is case here.

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

* Re: [RFC PATCH 03/24] net: rbridge: Add RBridge structure
  2014-09-24 15:51 ` [RFC PATCH 03/24] net: rbridge: Add RBridge structure Ahmed Amamou
  2014-09-24 16:40   ` Stephen Hemminger
@ 2014-09-24 17:18   ` Cong Wang
  1 sibling, 0 replies; 46+ messages in thread
From: Cong Wang @ 2014-09-24 17:18 UTC (permalink / raw)
  To: Ahmed Amamou; +Cc: netdev, william, f.cachereul, Kamel Haddadou

On Wed, Sep 24, 2014 at 8:51 AM, Ahmed Amamou <ahmed@gandi.net> wrote:
> 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/rbridge/rbr_private.h | 60 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 60 insertions(+)
>  create mode 100644 net/bridge/rbridge/rbr_private.h

Do you really need to create net/bridge/rbridge/ for the code?
Using rbr_* prefix seems enough for me since they anyway
share some code elsewhere.

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

* Re: [RFC PATCH 00/24] TRILL implementation
  2014-09-24 16:54   ` William Dauchy
@ 2014-09-24 17:24     ` Cong Wang
  2014-09-24 17:33       ` William Dauchy
  2014-09-24 20:57     ` Francois Romieu
  1 sibling, 1 reply; 46+ messages in thread
From: Cong Wang @ 2014-09-24 17:24 UTC (permalink / raw)
  To: William Dauchy
  Cc: Stephen Hemminger, Ahmed Amamou, netdev, f.cachereul, Fengguang Wu

On Wed, Sep 24, 2014 at 9:54 AM, William Dauchy <william@gandi.net> wrote:
> On Sep24 09:44, Stephen Hemminger wrote:
>> Is this patch series bisectable? does it build at each step?
>
> it should be the case but we will double check that.
>

You can ask Fengguang to add your repo to his kbuild bot,
I am sure it can catch much more than we do. :)

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

* Re: [RFC PATCH 01/24] net: rbridge: add trill frame description
  2014-09-24 16:48     ` William Dauchy
@ 2014-09-24 17:26       ` Cong Wang
  2014-09-24 17:34         ` William Dauchy
  0 siblings, 1 reply; 46+ messages in thread
From: Cong Wang @ 2014-09-24 17:26 UTC (permalink / raw)
  To: William Dauchy
  Cc: Stephen Hemminger, Ahmed Amamou, netdev, f.cachereul,
	Emmanuel Hocdet, Kamel Haddadou

On Wed, Sep 24, 2014 at 9:48 AM, William Dauchy <william@gandi.net> wrote:
>> Did you even run this through checkpatch?
>
> no but we will.
>

At least the comment style is not what DaveM prefers.
Please take a look at netdev-FAQ.txt.

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

* Re: [RFC PATCH 00/24] TRILL implementation
  2014-09-24 17:24     ` Cong Wang
@ 2014-09-24 17:33       ` William Dauchy
  0 siblings, 0 replies; 46+ messages in thread
From: William Dauchy @ 2014-09-24 17:33 UTC (permalink / raw)
  To: Cong Wang
  Cc: William Dauchy, Stephen Hemminger, Ahmed Amamou, netdev,
	f.cachereul, Fengguang Wu

[-- Attachment #1: Type: text/plain, Size: 257 bytes --]

On Sep24 10:24, Cong Wang wrote:
> You can ask Fengguang to add your repo to his kbuild bot,
> I am sure it can catch much more than we do. :)

ok; give us some time so we can send a branch somewhere with these patch
version.

Thanks,
-- 
William

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

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

* Re: [RFC PATCH 01/24] net: rbridge: add trill frame description
  2014-09-24 17:26       ` Cong Wang
@ 2014-09-24 17:34         ` William Dauchy
  0 siblings, 0 replies; 46+ messages in thread
From: William Dauchy @ 2014-09-24 17:34 UTC (permalink / raw)
  To: Cong Wang
  Cc: William Dauchy, Stephen Hemminger, Ahmed Amamou, netdev,
	f.cachereul, Emmanuel Hocdet, Kamel Haddadou

[-- Attachment #1: Type: text/plain, Size: 192 bytes --]

On Sep24 10:26, Cong Wang wrote:
> At least the comment style is not what DaveM prefers.
> Please take a look at netdev-FAQ.txt.

agreed, will correct and double check that
-- 
William

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

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

* Re: [RFC PATCH 06/24] net: rbridge: Enable/disable TRILL capability
  2014-09-24 15:52 ` [RFC PATCH 06/24] net: rbridge: Enable/disable TRILL capability Ahmed Amamou
@ 2014-09-24 17:46   ` Vlad Yasevich
  0 siblings, 0 replies; 46+ messages in thread
From: Vlad Yasevich @ 2014-09-24 17:46 UTC (permalink / raw)
  To: Ahmed Amamou, netdev; +Cc: william, f.cachereul, Kamel Haddadou

On 09/24/2014 11:52 AM, Ahmed Amamou wrote:
> enable switching TRILL capability state via sysfs command
> 
> Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
> Signed-off-by: Kamel Haddadou <kamel@gandi.net>
> ---
>  net/bridge/Makefile      |  2 ++
>  net/bridge/br_private.h  |  5 ++++
>  net/bridge/br_sysfs_br.c | 38 +++++++++++++++++++++++
>  net/bridge/rbridge/rbr.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 123 insertions(+)
>  create mode 100644 net/bridge/rbridge/rbr.c
> 
> diff --git a/net/bridge/Makefile b/net/bridge/Makefile
> index 8590b94..314783c 100644
> --- a/net/bridge/Makefile
> +++ b/net/bridge/Makefile
> @@ -17,3 +17,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) += rbridge/rbr.o
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 430c556..844c87b 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -811,6 +811,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);
>  
> +/* rbridge/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/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
> index c9e2572..787ab84 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);
> +	char *endp;
> +	unsigned long val;
> +
> +	if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
> +		return -EPERM;
> +
> +	val = simple_strtoul(buf, &endp, 0);
> +	if (endp == buf)
> +		return -EINVAL;
> +
> +	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)
> @@ -733,6 +768,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/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
> new file mode 100644
> index 0000000..41d47db
> --- /dev/null
> +++ b/net/bridge/rbridge/rbr.c
> @@ -0,0 +1,78 @@
> +/*
> + *	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) {
> +		spin_lock_bh(&br->lock);
> +		br->trill_enabled = BR_TRILL;
> +		spin_unlock_bh(&br->lock);
> +	} else {
> +		printk(KERN_WARNING
> +		       "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);

Are the locks around trill_enabled really needed?  Seems to be already
protected by rtnl.  Are you protecting against something else?

> +	old = br->rbr;
> +	br->rbr = NULL;
> +	if (likely(old)) {
> +		spin_lock_bh(&br->lock);
> +		kfree(old);
> +		spin_unlock_bh(&br->lock);

These locks appear to be completely unnecessary.

Also what's protecting future refrences to br->rbr?  Should it be rcu
protected?

-vlad
> +	}
> +}
> +
> +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);
> +	}
> +}
> 

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

* Re: [RFC PATCH 08/24] net: rbridge: Add Rbridge netlink message skeleton
  2014-09-24 15:52 ` [RFC PATCH 08/24] net: rbridge: Add Rbridge netlink message skeleton Ahmed Amamou
@ 2014-09-24 17:52   ` Vlad Yasevich
  0 siblings, 0 replies; 46+ messages in thread
From: Vlad Yasevich @ 2014-09-24 17:52 UTC (permalink / raw)
  To: Ahmed Amamou, netdev; +Cc: william, f.cachereul, Kamel Haddadou

On 09/24/2014 11:52 AM, Ahmed Amamou wrote:
> add data plane and control plane basic message skeleton
> add netlink socket registration and unregistration respectively within module init and deinit function
> 
> Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
> Signed-off-by: Kamel Haddadou <kamel@gandi.net>
> ---
>  net/bridge/Makefile              |   2 +-
>  net/bridge/br.c                  |   6 ++
>  net/bridge/br_private.h          |   1 +
>  net/bridge/rbridge/rbr_netlink.c | 152 +++++++++++++++++++++++++++++++++++++++
>  net/bridge/rbridge/rbr_netlink.h |  62 ++++++++++++++++
>  5 files changed, 222 insertions(+), 1 deletion(-)
>  create mode 100644 net/bridge/rbridge/rbr_netlink.c
>  create mode 100644 net/bridge/rbridge/rbr_netlink.h
> 
> diff --git a/net/bridge/Makefile b/net/bridge/Makefile
> index 314783c..b11a22b 100644
> --- a/net/bridge/Makefile
> +++ b/net/bridge/Makefile
> @@ -18,4 +18,4 @@ bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o
>  
>  obj-$(CONFIG_NETFILTER) += netfilter/
>  
> -bridge-$(CONFIG_TRILL) += rbridge/rbr.o
> +bridge-$(CONFIG_TRILL) += rbridge/rbr.o rbridge/rbr_netlink.o
> diff --git a/net/bridge/br.c b/net/bridge/br.c
> index 1a755a1..51af134 100644
> --- a/net/bridge/br.c
> +++ b/net/bridge/br.c
> @@ -178,6 +178,9 @@ static int __init br_init(void)
>  #if IS_ENABLED(CONFIG_ATM_LANE)
>  	br_fdb_test_addr_hook = br_fdb_test_addr;
>  #endif
> +#ifdef CONFIG_TRILL
> +	rbridge_register_genl();
> +#endif
>  
>  	return 0;
>  err_out4:
> @@ -210,6 +213,9 @@ static void __exit br_deinit(void)
>  	br_fdb_test_addr_hook = NULL;
>  #endif
>  
> +#ifdef CONFIG_TRILL
> +	rbridge_unregister_genl();
> +#endif
>  	br_fdb_fini();
>  }

The above #defines should be removed and inline noop stubs should
be added.

>  
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 844c87b..6952db8 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -21,6 +21,7 @@
>  #include <linux/if_vlan.h>
>  #ifdef CONFIG_TRILL
>  #include "rbridge/rbr_private.h"
> +#include "rbridge/rbr_netlink.h"
>  #endif
>  
>  #define BR_HASH_BITS 8
> diff --git a/net/bridge/rbridge/rbr_netlink.c b/net/bridge/rbridge/rbr_netlink.c
> new file mode 100644
> index 0000000..eb7c902
> --- /dev/null
> +++ b/net/bridge/rbridge/rbr_netlink.c
> @@ -0,0 +1,152 @@
> +/*
> + *	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 <net/genetlink.h>
> +#include <net/netlink.h>
> +#include <linux/if_trill.h>
> +#include <linux/socket.h>
> +#include <linux/socket.h>
> +#include "br_private.h"
> +#include "rbr_private.h"
> +#include "rbr_netlink.h"
> +
> +static struct nla_policy attrs_policy[TRILL_ATTR_MAX + 1] = {
> +	[TRILL_ATTR_U16] = {.type = NLA_U16},
> +	[TRILL_ATTR_BIN] = {.type = NLA_UNSPEC},
> +};
> +
> +static struct genl_family trill_genl_family = {
> +	.id = GENL_ID_GENERATE,
> +	.hdrsize = sizeof(struct trill_nl_header),
> +	.name = TRILL_NL_FAMILY,
> +	.version = TRILL_NL_VERSION,
> +	.maxattr = TRILL_ATTR_MAX
> +};
> +
> +static struct genl_multicast_group trill_mcgrps[] = {
> +	[TRILL_MCGRP_OFFSET] = {.name = TRILL_MCAST_NAME,},
> +};
> +
> +static int trill_cmd_set_nicks_info(struct sk_buff *skb, struct genl_info *info)
> +{
> +	return 0;
> +}
> +
> +static int trill_cmd_get_nicks_info(struct sk_buff *skb, struct genl_info *info)
> +{
> +	return 0;
> +}
> +
> +static int trill_cmd_add_nicks_info(struct sk_buff *skb, struct genl_info *info)
> +{
> +	return 0;
> +}
> +
> +static int trill_cmd_set_treeroot_id(struct sk_buff *skb,
> +				     struct genl_info *info)
> +{
> +	return 0;
> +}
> +
> +static int trill_cmd_get_rbridge(struct sk_buff *skb, struct genl_info *info)
> +{
> +	return 0;
> +}
> +
> +static int trill_cmd_set_rbridge(struct sk_buff *skb, struct genl_info *info)
> +{
> +	return 0;
> +}
> +
> +static int trill_cmd_port_flush(struct sk_buff *skb, struct genl_info *info)
> +{
> +	return 0;
> +}
> +
> +static int trill_cmd_nick_flush(struct sk_buff *skb, struct genl_info *info)
> +{
> +	return 0;
> +}
> +
> +static struct genl_ops trill_genl_ops[] = {
> +	{
> +	 .cmd = TRILL_CMD_SET_NICKS_INFO,
> +	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
> +	 .policy = attrs_policy,
> +	 .doit = trill_cmd_set_nicks_info,
> +	 },
> +	{
> +	 .cmd = TRILL_CMD_GET_NICKS_INFO,
> +	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
> +	 .policy = attrs_policy,
> +	 .doit = trill_cmd_get_nicks_info,
> +	 },
> +	{
> +	 .cmd = TRILL_CMD_ADD_NICKS_INFO,
> +	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
> +	 .policy = attrs_policy,
> +	 .doit = trill_cmd_add_nicks_info,
> +	 },
> +	{
> +	 .cmd = TRILL_CMD_SET_TREEROOT_ID,
> +	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
> +	 .policy = attrs_policy,
> +	 .doit = trill_cmd_set_treeroot_id,
> +	 },
> +	{
> +	 .cmd = TRILL_CMD_GET_RBRIDGE,
> +	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
> +	 .policy = attrs_policy,
> +	 .doit = trill_cmd_get_rbridge,
> +	 },
> +	{
> +	 .cmd = TRILL_CMD_SET_RBRIDGE,
> +	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
> +	 .policy = attrs_policy,
> +	 .doit = trill_cmd_set_rbridge,
> +	 },
> +	{
> +	 .cmd = TRILL_CMD_PORT_FLUSH,
> +	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
> +	 .doit = trill_cmd_port_flush,
> +	 },
> +	{
> +	 .cmd = TRILL_CMD_NICK_FLUSH,
> +	 .flags = GENL_ADMIN_PERM,	/* Requires CAP_NET_ADMIN privilege. */
> +	 .policy = attrs_policy,
> +	 .doit = trill_cmd_nick_flush,
> +	 },
> +};
> +
> +void __exit rbridge_unregister_genl(void)
> +{
> +	genl_unregister_family(&trill_genl_family);
> +}
> +
> +int __init rbridge_register_genl(void)
> +{
> +	int err;
> +
> +	err =
> +	    genl_register_family_with_ops_groups(&trill_genl_family,
> +						 trill_genl_ops, trill_mcgrps);
> +	if (err)
> +		goto fail_genl_register_family;
> +
> +	return 0;
> +
> + fail_genl_register_family:
> +
> +	return err;
> +}
> diff --git a/net/bridge/rbridge/rbr_netlink.h b/net/bridge/rbridge/rbr_netlink.h
> new file mode 100644
> index 0000000..0556323
> --- /dev/null
> +++ b/net/bridge/rbridge/rbr_netlink.h
> @@ -0,0 +1,62 @@
> +/*
> + *	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.
> + */
> +
> +#ifndef RBR_NETLINK_H_
> +#define RBR_NETLINK_H_
> +
> +/* TRILL Generic Netlink attributes definition*/
> +#define TRILL_NL_VERSION	0x1
> +#define TRILL_NL_FAMILY		"TRILL_NL"
> +#define TRILL_MCAST_NAME	"TR_NL_MCAST"
> +#define TRILL_MCGRP_OFFSET     0
> +
> +struct trill_nl_header {
> +	int ifindex;		/* port id */
> +	int total_length;	/* message total length for mutipart messages check */
> +	int msg_number;		/* message number for multipart messages check */
> +};
> +
> +enum {
> +	TRILL_ATTR_UNSPEC,
> +	TRILL_ATTR_U16,
> +	TRILL_ATTR_BIN,
> +	__TRILL_ATTR_MAX,
> +};
> +#define TRILL_ATTR_MAX (__TRILL_ATTR_MAX-1)
> +
> +/* GET and set are from user space perspective  example TRILL_CMD_GET_BRIDGE
> + * means that the kernel will send this bridge name to userspace
> + */
> +enum {
> +	TRILL_CMD_UNSPEC,
> +	TRILL_CMD_SET_NICKS_INFO,
> +	TRILL_CMD_GET_NICKS_INFO,
> +	TRILL_CMD_ADD_NICKS_INFO,
> +	TRILL_CMD_DEL_NICK,
> +	TRILL_CMD_SET_TREEROOT_ID,
> +	TRILL_CMD_GET_RBRIDGE,
> +	TRILL_CMD_SET_RBRIDGE,
> +	TRILL_CMD_PORT_FLUSH,
> +	TRILL_CMD_NICK_FLUSH,
> +	__TRILL_CMD_MAX,
> +};
> +#define TRILL_CMD_MAX (__TRILL_CMD_MAX - 1)
> +
> +int __init rbridge_register_genl(void);
> +void __exit rbridge_unregister_genl(void);
> +
> +/* used to indicate that message is provided by kernel to user space */
> +#define KERNL_RESPONSE_INTERFACE -1
> +
> +#endif				/* RBR_NETLINK_H_ */
> 

Bridge is typically configured through rtnetlink and there is an
effort to make this configuration easier.  Switching to genl means
there will be yet another tool to configure some part of the bridge.

-vlad

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

* Re: [RFC PATCH 15/24] net: rbridge: Add basic trill frame handling function
  2014-09-24 15:52 ` [RFC PATCH 15/24] net: rbridge: Add basic trill frame handling function Ahmed Amamou
@ 2014-09-24 19:23   ` Francois Romieu
  0 siblings, 0 replies; 46+ messages in thread
From: Francois Romieu @ 2014-09-24 19:23 UTC (permalink / raw)
  To: Ahmed Amamou; +Cc: netdev, william, f.cachereul, Kamel Haddadou

Ahmed Amamou <ahmed@gandi.net> :
[...]
> diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
> index edd1e7c..4b41d4c 100644
> --- a/net/bridge/rbridge/rbr.c
> +++ b/net/bridge/rbridge/rbr.c
> @@ -129,3 +129,103 @@ static void rbr_del_all(struct rbr *rbr)
[...]
> +	/* if trill is not enabled, handle by bridge */
> +	if (br->trill_enabled == BR_NO_TRILL) {
> +		goto handle_by_bridge;
> +	} else {

No need for an 'else' branch after a 'goto'. Please save an indent level.

Same remark apply in patches #19 and and #21 (almost: 'else' before 'goto').

-- 
Ueimor

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

* Re: [RFC PATCH 05/24] net: rbridge: Adapt Bridge structure
  2014-09-24 15:52 ` [RFC PATCH 05/24] net: rbridge: Adapt Bridge structure Ahmed Amamou
@ 2014-09-24 20:56   ` Francois Romieu
  0 siblings, 0 replies; 46+ messages in thread
From: Francois Romieu @ 2014-09-24 20:56 UTC (permalink / raw)
  To: Ahmed Amamou; +Cc: netdev, william, f.cachereul, Kamel Haddadou

Ahmed Amamou <ahmed@gandi.net> :
[...]
> diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
> index 9c5529d..09dc18c 100644
> --- a/include/linux/etherdevice.h
> +++ b/include/linux/etherdevice.h
[...]
> @@ -391,4 +401,28 @@ static inline unsigned long compare_ether_header(const void *a, const void *b)
>  #endif
>  }
>  
> +#ifdef CONFIG_TRILL
> +/**
> + * is_all_rbr_address - check if it is a specific Rbridge brodcast mac address
> + * @addr1: 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 * addr1)
> +{
> +	return ether_addr_equal(addr1, eth_reserved_addr_all_rbridge);
> +}
> +
> +static inline bool is_isis_rbr_address(const u8 * addr1)
> +{
> +	return ether_addr_equal(addr1, eth_reserved_addr_isis_rbridge);
> +}
> +
> +static inline bool is_esadi_rbr_address(const u8 * addr1)
> +{
> +	return ether_addr_equal(addr1, eth_reserved_addr_esadi_rbridge);
> +}

Nit: s/addr1/addr (there's no addr2).

Neither is_isis_rbr_address nor is_esadi_rbr_address is ever used. They
could be added later.

You may consider merging the hunk above with patch #15.

-- 
Ueimor

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

* Re: [RFC PATCH 00/24] TRILL implementation
  2014-09-24 16:54   ` William Dauchy
  2014-09-24 17:24     ` Cong Wang
@ 2014-09-24 20:57     ` Francois Romieu
  1 sibling, 0 replies; 46+ messages in thread
From: Francois Romieu @ 2014-09-24 20:57 UTC (permalink / raw)
  To: William Dauchy; +Cc: Stephen Hemminger, Ahmed Amamou, netdev, f.cachereul

William Dauchy <william@gandi.net> :
> On Sep24 09:44, Stephen Hemminger wrote:
[...]
> > Also, it seems when you build with trill you lose normal bridge functionality.
> > Whether kernel is doing bridge or rbridge has to be a runtime (not compile time)
> > choice on a per-bridge basis.
> 
> The normal bridge functionnality are still ok until TRILL is not
> enabled.

Imvho you should remove patch #24 and plug directly into br_handle_frame.
It is not fair for usual bridge interfaces to become second class
citizens - rbr_handle_frame _is_ unbalanced - as soon as CONFIG_TRILL is
set and they are not TRILL enabled.

-- 
Ueimor

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

* Re: [RFC PATCH 11/24] net: rbridge: Add rbr_node management function
  2014-09-24 15:52 ` [RFC PATCH 11/24] net: rbridge: Add rbr_node management function Ahmed Amamou
@ 2014-09-25 11:24   ` Sergei Shtylyov
  0 siblings, 0 replies; 46+ messages in thread
From: Sergei Shtylyov @ 2014-09-25 11:24 UTC (permalink / raw)
  To: Ahmed Amamou, netdev; +Cc: william, f.cachereul, Kamel Haddadou

Hello.

On 9/24/2014 7:52 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/rbridge/rbr.c         | 34 ++++++++++++++++++++++++++++++++++
>   net/bridge/rbridge/rbr_private.h | 26 ++++++++++++++++++++++++++
>   2 files changed, 60 insertions(+)

> diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
> index 8d6d37e..1df8f8d 100644
> --- a/net/bridge/rbridge/rbr.c
> +++ b/net/bridge/rbridge/rbr.c
> @@ -93,3 +93,37 @@ 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;

    There should be an empty line here, like in the next functions.

> +	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 != NULL)) {
> +			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] != NULL))
> +			rbr_del_node(rbr, i);
> +	}
> +}
[...]

WBR, Sergei

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

* Re: [RFC PATCH 10/24] net: rbridge: Add elected dtroot
  2014-09-24 15:52 ` [RFC PATCH 10/24] net: rbridge: Add elected dtroot Ahmed Amamou
@ 2014-09-25 11:30   ` Sergei Shtylyov
  0 siblings, 0 replies; 46+ messages in thread
From: Sergei Shtylyov @ 2014-09-25 11:30 UTC (permalink / raw)
  To: Ahmed Amamou, netdev; +Cc: william, f.cachereul, Kamel Haddadou

On 9/24/2014 7:52 PM, Ahmed Amamou wrote:

> provide function to get the locally elected distributed tree root from the daemon
> in TRILL RFC multiple tree root can be elected but this is not mendatory
> for this first version we use a unique distributed tree root

> 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          |  1 +
>   net/bridge/rbridge/rbr.c         | 17 +++++++++++++++++
>   net/bridge/rbridge/rbr_netlink.c | 21 +++++++++++++++++++++
>   3 files changed, 39 insertions(+)

[...]
> diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
> index 41d47db..8d6d37e 100644
> --- a/net/bridge/rbridge/rbr.c
> +++ b/net/bridge/rbridge/rbr.c
> @@ -76,3 +76,20 @@ 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) {
> +		spin_lock_bh(&rbr->br->lock);
> +		rbr->treeroot = treeroot;
> +		spin_unlock_bh(&rbr->br->lock);

    I think the assignment is already atomic.

> +	}
> +	return 0;

    Empty line wouldn't hurt here...

> + set_tree_root_fail:
> +	return ENOENT;
> +}
> diff --git a/net/bridge/rbridge/rbr_netlink.c b/net/bridge/rbridge/rbr_netlink.c
> index ccba5ae..889e6c8 100644
> --- a/net/bridge/rbridge/rbr_netlink.c
> +++ b/net/bridge/rbridge/rbr_netlink.c
> @@ -56,7 +56,28 @@ static int trill_cmd_add_nicks_info(struct sk_buff *skb, struct genl_info *info)
>   static int trill_cmd_set_treeroot_id(struct sk_buff *skb,
>   				     struct genl_info *info)
>   {
> +	int err = -EINVAL;
> +	u16 nickname;
> +	struct trill_nl_header *trnlhdr;
> +	struct net_device *source_port = NULL;
> +	struct net *net = sock_net(skb->sk);
> +	struct net_bridge_port *p = NULL;

    Need empty line here.

> +	nickname = nla_get_u16(info->attrs[TRILL_ATTR_U16]);
> +	trnlhdr = info->userhdr;
> +	if (trnlhdr->ifindex)
> +		source_port = __dev_get_by_index(net, trnlhdr->ifindex);
> +	if (!source_port)
> +		goto fail;
> +	p = br_port_get_rcu(source_port);
> +	if (!p || !(p->br) || !(p->br->rbr))

    Inner () not needed.

> +		goto fail;
> +	err = set_treeroot(p->br->rbr, htons(nickname));
> +	if (err)
> +		goto fail;
>   	return 0;

    Empty lien wouldn't hurt here...

> + fail:
> +	printk(KERN_WARNING "trill_cmd_set_treeroot_id FAILED\n");

    Use pr_warn() instead.

[...]

WBR, Sergei

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

* Re: [RFC PATCH 13/24] net: rbridge: Add set_node function
  2014-09-24 15:52 ` [RFC PATCH 13/24] net: rbridge: Add set_node function Ahmed Amamou
@ 2014-09-25 11:34   ` Sergei Shtylyov
  0 siblings, 0 replies; 46+ messages in thread
From: Sergei Shtylyov @ 2014-09-25 11:34 UTC (permalink / raw)
  To: Ahmed Amamou, netdev; +Cc: william, f.cachereul, Kamel Haddadou

Hello.

On 9/24/2014 7:52 PM, Ahmed Amamou wrote:

> allow daemon to set distant Rbridges information in local database
> daemon has to periodically update distant Rbridges informations in local database
> create a new node only if change on distant RBridge information are detected

> 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/rbridge/rbr_netlink.c | 78 ++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 78 insertions(+)

> diff --git a/net/bridge/rbridge/rbr_netlink.c b/net/bridge/rbridge/rbr_netlink.c
> index 889e6c8..bb893f0 100644
> --- a/net/bridge/rbridge/rbr_netlink.c
> +++ b/net/bridge/rbridge/rbr_netlink.c
> @@ -38,9 +38,87 @@ static struct genl_multicast_group trill_mcgrps[] = {
>   	[TRILL_MCGRP_OFFSET] = {.name = TRILL_MCAST_NAME,},
>   };
>
> +static int create_node(struct net_bridge_port *p, struct rbr *rbr,
> +		       struct rbr_nickinfo *rbr_ni_partial,
> +		       struct genl_info *info)
> +{
> +	size_t size = 0;
> +	size_t old_size = 0;
> +	struct rbr_node *old;
> +	struct rbr_nickinfo *rbr_ni;
> +
> +	if (rbr_ni_partial == NULL)
> +		return -EINVAL;
> +
> +	size = RBR_NI_TOTALSIZE(rbr_ni_partial);
> +	if (size > PAGE_SIZE - sizeof(struct trill_nl_header)) {
> +		pr_warn_ratelimited
> +		    ("create_node: size > (PAGE_SIZE-nickinfo_offset)\n");
> +		return -EINVAL;
> +	}
> +	rbr_ni = kzalloc(size, GFP_KERNEL);
> +	if (!rbr_ni)
> +		return -ENOMEM;
> +	old = rbr->rbr_nodes[rbr_ni_partial->nick];
> +	nla_memcpy(rbr_ni, info->attrs[TRILL_ATTR_BIN], size);
> +	if (old)
> +		old_size = RBR_NI_TOTALSIZE(old->rbr_ni);
> +	/* replace old node by a new one only if nickname information have changed */

    s/have/has/.

> +	if (old == NULL || 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);
> +			return -ENOMEM;
> +		}
> +		atomic_set(&new->refs, 1);
> +		new->rbr_ni = rbr_ni;
> +		/* avoid deleting node while it is been used for routing */

    Either "has been" or "is being".

> +		rcu_assign_pointer(rbr->rbr_nodes[rbr_ni->nick], new);
> +		if (old)
> +			rbr_node_put(old);
> +	} else {
> +		kfree(rbr_ni);
> +	}
> +
> +	return 0;
> +}
> +
>   static int trill_cmd_set_nicks_info(struct sk_buff *skb, struct genl_info *info)
>   {
> +	struct trill_nl_header *trnlhdr;
> +	struct rbr_nickinfo rbr_ni;
> +	struct net_device *source_port = NULL;
> +	struct net *net = sock_net(skb->sk);
> +	struct net_bridge_port *p = NULL;
> +	int err = -EINVAL;
> +
> +	nla_memcpy(&rbr_ni, info->attrs[TRILL_ATTR_BIN], sizeof(rbr_ni));
> +	if (!VALID_NICK(rbr_ni.nick))
> +		goto fail;
> +
> +	trnlhdr = info->userhdr;
> +	if (trnlhdr->ifindex)
> +		source_port = __dev_get_by_index(net, trnlhdr->ifindex);
> +
> +	if (!source_port)
> +		goto fail;
> +
> +	p = br_port_get_rcu(source_port);
> +	if (!p || !(p->br) || !(p->br->rbr))

    Inner parens not needed.

> +		goto fail;
> +
> +	err = create_node(p, p->br->rbr, &rbr_ni, info);
> +	if (err)
> +		goto fail;
> +
>   	return 0;
> +
> + fail:
> +	printk(KERN_WARNING "trill_cmd_set_nicks_info FAILED\n");

    pr_warn().

[...]

WBR, Sergei

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

* Re: [RFC PATCH 22/24] net: rbridge: Add rbr_fwd
  2014-09-24 15:52 ` [RFC PATCH 22/24] net: rbridge: Add rbr_fwd Ahmed Amamou
@ 2014-09-25 11:43   ` Sergei Shtylyov
  0 siblings, 0 replies; 46+ messages in thread
From: Sergei Shtylyov @ 2014-09-25 11:43 UTC (permalink / raw)
  To: Ahmed Amamou, netdev; +Cc: william, f.cachereul, Kamel Haddadou

On 9/24/2014 7:52 PM, Ahmed Amamou wrote:

> 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/rbridge/rbr.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 47 insertions(+), 2 deletions(-)

> diff --git a/net/bridge/rbridge/rbr.c b/net/bridge/rbridge/rbr.c
> index 8aa5182..39aa816c 100644
> --- a/net/bridge/rbridge/rbr.c
> +++ b/net/bridge/rbridge/rbr.c
> @@ -177,6 +177,51 @@ 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,
> +		    uint16_t adj_nick, u16 vid)
> +{
> +	struct rbr_node *adj;
> +	struct trill_hdr *trh;
> +	struct ethhdr *outerethhdr;
> +	struct net *net = dev_net(p->br->dev);
> +	struct net_device *outdev;
> +
> +	adj = rbr_find_node(p->br->rbr, adj_nick);
> +    outdev = __dev_get_by_index(net, adj->rbr_ni->linkid);

    Indent with a tab please.

> +	if (!outdev) {
> +		pr_warn_ratelimited("rbr_fwd: cannot find source port device for forwrding\n");
> +		goto dest_fwd_fail;
> +    }
> +	if (unlikely(adj == NULL)) {
> +		pr_warn_ratelimited
> +		    ("rbr_fwd: unable to find adjacent RBridge\n");
> +		goto dest_fwd_fail;
> +	}
> +
> +	trh = (struct trill_hdr *)skb->data;
> +	trillhdr_dec_hopcount(trh);
> +	outerethhdr = eth_hdr(skb);
> +
> +	/* change outer ether header */
> +	/* bridge become the source_port address in outeretherhdr */

    Becomes?

> +	memcpy(outerethhdr->h_source, p->br->dev->dev_addr, ETH_ALEN);
> +	/* dist port become dest address in outeretherhdr */
> +	memcpy(outerethhdr->h_dest, adj->rbr_ni->adjsnpa, ETH_ALEN);
> +	rbr_node_put(adj);
> +	/* set Bridge as source device */
> +	skb->dev = p->br->dev;
> +	br_forward(br_port_get_rcu(outdev), skb, NULL);
> +
> +	return;
> +
> + dest_fwd_fail:
> +	if (likely(p && p->br))
> +		p->br->dev->stats.tx_dropped++;
> +	kfree_skb(skb);
> +	return;
> +}
> +
> +

    One empty line is enough.

>   static void rbr_encaps(struct sk_buff *skb, uint16_t egressnick, u16 vid)
>   {
>   	uint16_t local_nick;
[...]

WBR, Sergei

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

end of thread, other threads:[~2014-09-25 11:43 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-24 15:51 [RFC PATCH 00/24] TRILL implementation Ahmed Amamou
2014-09-24 15:51 ` [RFC PATCH 01/24] net: rbridge: add trill frame description Ahmed Amamou
2014-09-24 16:38   ` Stephen Hemminger
2014-09-24 16:48     ` William Dauchy
2014-09-24 17:26       ` Cong Wang
2014-09-24 17:34         ` William Dauchy
2014-09-24 17:01   ` Cong Wang
2014-09-24 15:51 ` [RFC PATCH 02/24] net: rbridge: Add layer 2 IS-IS Ethertype Ahmed Amamou
2014-09-24 15:51 ` [RFC PATCH 03/24] net: rbridge: Add RBridge structure Ahmed Amamou
2014-09-24 16:40   ` Stephen Hemminger
2014-09-24 16:55     ` William Dauchy
2014-09-24 17:18   ` Cong Wang
2014-09-24 15:52 ` [RFC PATCH 04/24] net: rbridge: Add CONFIG_TRILL Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 05/24] net: rbridge: Adapt Bridge structure Ahmed Amamou
2014-09-24 20:56   ` Francois Romieu
2014-09-24 15:52 ` [RFC PATCH 06/24] net: rbridge: Enable/disable TRILL capability Ahmed Amamou
2014-09-24 17:46   ` Vlad Yasevich
2014-09-24 15:52 ` [RFC PATCH 07/24] net: rbridge: Add sysfs for trill_state Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 08/24] net: rbridge: Add Rbridge netlink message skeleton Ahmed Amamou
2014-09-24 17:52   ` Vlad Yasevich
2014-09-24 15:52 ` [RFC PATCH 09/24] net: rbridge: Get Rbridge nickname from daemon Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 10/24] net: rbridge: Add elected dtroot Ahmed Amamou
2014-09-25 11:30   ` Sergei Shtylyov
2014-09-24 15:52 ` [RFC PATCH 11/24] net: rbridge: Add rbr_node management function Ahmed Amamou
2014-09-25 11:24   ` Sergei Shtylyov
2014-09-24 15:52 ` [RFC PATCH 12/24] net: rbridge: Clean up rbr_node on rbridge stop Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 13/24] net: rbridge: Add set_node function Ahmed Amamou
2014-09-25 11:34   ` Sergei Shtylyov
2014-09-24 15:52 ` [RFC PATCH 14/24] net: rbridge: Add get_node function Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 15/24] net: rbridge: Add basic trill frame handling function Ahmed Amamou
2014-09-24 19:23   ` Francois Romieu
2014-09-24 15:52 ` [RFC PATCH 16/24] net: rbridge: Update forwarding database Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 17/24] net: rbridge: Add test on trill flag before flood Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 18/24] net: rbridge: Add encapsulation process Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 19/24] net: rbridge: Add receive function Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 20/24] net: rbridge: Add multicast recv handling Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 21/24] net: rbridge: Add decapsulation function Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 22/24] net: rbridge: Add rbr_fwd Ahmed Amamou
2014-09-25 11:43   ` Sergei Shtylyov
2014-09-24 15:52 ` [RFC PATCH 23/24] net: rbridge: Add rbr_multidest_fwd Ahmed Amamou
2014-09-24 15:52 ` [RFC PATCH 24/24] net: rbridge: replace net_port rx_handler Ahmed Amamou
2014-09-24 16:44 ` [RFC PATCH 00/24] TRILL implementation Stephen Hemminger
2014-09-24 16:54   ` William Dauchy
2014-09-24 17:24     ` Cong Wang
2014-09-24 17:33       ` William Dauchy
2014-09-24 20:57     ` Francois Romieu

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.