--- old/usr/src/uts/common/sys/overlay_impl.h	Tue Apr  3 17:58:12 2018
+++ new/usr/src/uts/common/sys/overlay_impl.h	Tue Apr  3 17:58:12 2018
@@ -24,6 +24,7 @@
 #include <sys/overlay_common.h>
 #include <sys/overlay_plugin.h>
 #include <sys/overlay_target.h>
+#include <sys/overlay_router.h>
 #include <sys/ksynch.h>
 #include <sys/list.h>
 #include <sys/avl.h>
@@ -32,6 +33,7 @@
 #include <sys/refhash.h>
 #include <sys/ethernet.h>
 #include <sys/list.h>
+#include <sys/atomic.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -84,39 +86,17 @@
 			refhash_t	*ott_dhash;
 			refhash_t	*ott_l3dhash;
 			avl_tree_t	ott_tree;
-			/* XXX: Do we actually need a tree sorted by VL3? */
 			avl_tree_t	ott_l3tree;
 		} ott_dyn;
 	} ott_u;
 } overlay_target_t;
 
-/*
- * Initially at least, we represent a group of fabrics that are attached to
- * each other as a circular linked list.  Within an overlay_dev_t, we then
- * maintain a list of pointers into these lists for each fabric that's
- * present locally on the CN as we learn them:
- *
- */
-typedef struct overlay_fabric_attach {
-	struct overlay_fabric_attach *ofa_next;
-	struct in6_addr	ofa_addr;
-	uint32_t	ofa_dcid;
-	uint16_t	ofa_vlan;
-	uint8_t		ofa_prefixlen;
-	uint8_t		ofa_pad;
-} overlay_fabric_attach_t;
+typedef struct overlay_router {
+	kmutex_t		otr_lock;
+	avl_tree_t		otr_tree;	/* RW tree of all fabrics */
+	list_t			otr_tables;
+} overlay_router_t;
 
-/*
- * Since we have two different refhashes for an overlay_target_entry_t
- * (VL2 aka MAC address and VL3 aka IP address), we want to maintain
- * the refcount in only one place. We elect to use the ott_dhash
- * refhash to do so.
- */
-#define	OVERLAY_TARGET_ENTRY_HOLD(tgt, e) \
-	refhash_hold((tgt)->ott_u.ott_dyn.ott_dhash, e)
-#define	OVERLAY_TARGET_ENTRY_RELE(tgt, e) \
-	refhash_rele((tgt)->ott_u.ott_dyn.ott_dhash, e)
-
 typedef enum overlay_dev_flag {
 	OVERLAY_F_ACTIVATED	= 0x01, /* Activate ioctl completed */
 	OVERLAY_F_IN_MUX	= 0x02,	/* Currently in a mux */
@@ -147,17 +127,42 @@
 	uint64_t	odd_vid;		/* RO if active else odd_lock */
 	avl_node_t	odd_muxnode;		/* managed by mux */
 	overlay_target_t *odd_target;		/* See big theory statement */
-	overlay_fabric_attach_t **odd_fattach;	/* protected by odd_lock */
+	overlay_router_t *odd_router;
 	uint32_t	odd_dcid;		/* RO if active else odd_lock */
 	uint8_t		odd_macaddr[ETHERADDRL]; /* RO same as odd_dcid */
 	char		odd_fmamsg[OVERLAY_STATUS_BUFLEN];	/* odd_lock */
 } overlay_dev_t;
 
+struct overlay_route_table;
+typedef struct overlay_route_table overlay_route_table_t;
+
+typedef struct overlay_fabric_entry {
+	avl_node_t		ofe_avllink;
+	overlay_dev_t		*ofe_odd;
+	overlay_route_table_t	*ofe_route_table;
+	volatile uint32_t	ofe_refcnt;
+	overlay_fabric_t	ofe_fabric;
+	list_t			ofe_targ_list;
+} overlay_fabric_entry_t;
+#define	OVERLAY_FAB_ENTRY_REFHOLD(ofe) atomic_inc_32(&(ofe)->ofe_refcnt)
+#define	OVERLAY_FAB_ENTRY_REFRELE(ofe) \
+	(void) ((atomic_dec_32_nv(&(ofe)->ofe_refcnt) != 0) || \
+	    (overlay_fabric_entry_free(ofe), 0))
+
+struct overlay_route_table {
+	list_node_t		ort_link;
+	overlay_fabric_entry_t	**ort_dest;
+	size_t			ort_nalloc;
+};
+
 typedef enum overlay_target_entry_flags {
 	OVERLAY_ENTRY_F_PENDING		= 0x01,	/* lookup in progress */
 	OVERLAY_ENTRY_F_VALID		= 0x02,	/* entry is currently valid */
 	OVERLAY_ENTRY_F_DROP		= 0x04,	/* always drop target */
-	OVERLAY_ENTRY_F_VALID_MASK	= 0x06
+	OVERLAY_ENTRY_F_ROUTER		= 0x08,	/* entry is for router */
+	OVERLAY_ENTRY_F_VALID_MASK	= 0x0e,
+	OVERLAY_ENTRY_F_VL3_PENDING	= 0x10,
+	OVERLAY_ENTRY_F_VL3_VALID	= 0x20,
 } overlay_target_entry_flags_t;
 
 typedef struct overlay_target_entry {
@@ -165,15 +170,16 @@
 	refhash_link_t		ote_reflink;	/* hashtable link */
 	refhash_link_t		ote_l3_reflink;	/* IP hashtable link */
 	avl_node_t		ote_avllink;	/* iteration link */
-	avl_node_t		ote_l3_avllink;	/* IP iteration link */
+	avl_node_t		ote_l3_avllink; /* IP iteration link */
 	list_node_t		ote_qlink;
+	list_node_t		ote_fablink;
+	volatile uint32_t	ote_refcnt;
 	overlay_target_entry_flags_t ote_flags;	/* RW: state flags */
-	uint32_t		ote_dcid;
-	uint16_t		ote_vlan;	/* RO: VL3 vlan id */
-	uint8_t			ote_addr[ETHERADDRL];	/* RO: mac addr */
 	struct in6_addr		ote_ip;		/* RO: VL3 IP */
+	uint8_t			ote_addr[ETHERADDRL];	/* RO: mac addr */
 	overlay_target_t	*ote_ott;	/* RO */
 	overlay_dev_t		*ote_odd;	/* RO */
+	overlay_fabric_entry_t	*ote_fab;	/* RO */
 	overlay_target_point_t	ote_dest;	/* RW: destination */
 	mblk_t			*ote_chead;	/* RW: blocked mb chain head */
 	mblk_t			*ote_ctail;	/* RW: blocked mb chain tail */
@@ -180,6 +186,10 @@
 	size_t			ote_mbsize;	/* RW: outstanding mblk size */
 	hrtime_t		ote_vtime;	/* RW: valid timestamp */
 } overlay_target_entry_t;
+#define	OVERLAY_TARG_ENTRY_REFHOLD(ote) atomic_inc_32(&(ote)->ote_refcnt)
+#define	OVERLAY_TARG_ENTRY_REFRELE(ote) \
+	(void) ((atomic_dec_32_nv(&(ote)->ote_refcnt) != 0) || \
+	    (overlay_target_entry_dtor(ote), 0))
 
 #define	OVERLAY_CTL	"overlay"
 
@@ -218,15 +228,23 @@
 extern int overlay_target_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
 extern int overlay_target_close(dev_t, int, int, cred_t *);
 extern void overlay_target_free(overlay_dev_t *);
+extern void overlay_target_entry_dtor(void *);
 
 #define	OVERLAY_TARGET_OK	0
 #define	OVERLAY_TARGET_DROP	1
 #define	OVERLAY_TARGET_ASYNC	2
 extern int overlay_target_lookup(overlay_dev_t *, mblk_t *, struct sockaddr *,
-    socklen_t *);
+    socklen_t *, uint64_t *);
+extern void overlay_target_queue(overlay_target_entry_t *);
 extern void overlay_target_quiesce(overlay_target_t *);
 extern void overlay_target_fini(void);
 
+extern int overlay_route_lookup(overlay_dev_t *, mblk_t *,
+    const mac_header_info_t *, struct sockaddr *, socklen_t *, uint64_t *);
+extern int overlay_mblk_vl3ip(mblk_t *, struct in6_addr *, struct in6_addr *);
+extern int overlay_router_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
+extern int overlay_fabric_avl(const void *, const void *);
+
 extern void overlay_fm_init(void);
 extern void overlay_fm_fini(void);
 extern void overlay_fm_degrade(overlay_dev_t *, const char *);
