OpenSolaris_b135/uts/common/net/bridge_impl.h

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _BRIDGE_IMPL_H
#define	_BRIDGE_IMPL_H

/*
 * These are the internal data structures used by the layer-two (Ethernet)
 * bridging module.
 */

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/list.h>
#include <sys/sysmacros.h>
#include <sys/avl.h>
#include <sys/queue.h>
#include <sys/kstat.h>
#include <sys/ksynch.h>
#include <sys/ethernet.h>
#include <sys/dld.h>
#include <sys/mac.h>
#include <sys/mac_client.h>
#include <sys/vlan.h>
#include <net/bridge.h>

#define	BRIDGE_DEV_NAME	"bridge"

#define	KSINST_NAMES	"recv", "sent", "drops", \
	"forward_direct", "forward_unknown", "forward_mbcast",	\
	"learn_source", "learn_moved", "learn_expire", "learn_size"
typedef struct bridge_ksinst_s {
	kstat_named_t	bki_recv;	/* packets received */
	kstat_named_t	bki_sent;	/* packets sent through */
	kstat_named_t	bki_drops;	/* packets dropped (untowardly) */
	kstat_named_t	bki_forwards;	/* packets forwarded */
	kstat_named_t	bki_unknown;	/* packets forwarded (unknown dest) */
	kstat_named_t	bki_mbcast;	/* packets forwarded (multi/bcast) */
	kstat_named_t	bki_source;	/* source addresses learned */
	kstat_named_t	bki_moved;	/* source addresses moved */
	kstat_named_t	bki_expire;	/* source addresses expired */
	kstat_named_t	bki_count;	/* source addresses known */
} bridge_ksinst_t;

#define	KSLINK_NAMES	"recv", "xmit", "drops"
typedef struct bridge_kslink_s {
	kstat_named_t	bkl_recv;	/* packets received */
	kstat_named_t	bkl_xmit;	/* packets transmitted */
	kstat_named_t	bkl_drops;	/* packets dropped */
} bridge_kslink_t;

/*
 * There's one instance structure and one observability mac node for each
 * bridge.  Each open non-DLPI stream gets a 'stream' structure; these are used
 * for bridge instance allocation and control.  Each link on the bridge has a
 * link structure.  Finally, the bridge has a table of learned forwarding
 * entries, each with a list of outputs, which are either links or TRILL
 * nicknames.
 *
 * The mac structure lives as long as the dls and mac layers are busy.  It can
 * outlive the bridge instance and be picked up again (by name) if the instance
 * is restarted.
 */

struct bridge_mac_s;
struct bridge_stream_s;

typedef struct bridge_inst_s {
	list_node_t	bi_node;
	dev_t		bi_dev;
	uint_t		bi_flags;
	uint_t		bi_refs;
	uint32_t	bi_tablemax;
	uint_t		bi_tshift;
	krwlock_t	bi_rwlock;
	list_t		bi_links;
	kcondvar_t	bi_linkwait;
	avl_tree_t	bi_fwd;
	kstat_t		*bi_ksp;
	struct bridge_stream_s *bi_control;
	struct bridge_mac_s *bi_mac;
	void		*bi_trilldata;
	char		bi_name[MAXLINKNAMELEN];
	bridge_ksinst_t	bi_kstats;
} bridge_inst_t;

#define	BIF_SHUTDOWN	0x0001		/* control stream has closed */

/*
 * The bridge MAC structure has the same lifetime as an observability node.
 * It's created when a bridge instance is allocated, but is not freed when the
 * instance is removed because there's no way for a MAC client to guarantee
 * that all users have disappeared.
 */
typedef struct bridge_mac_s {
	list_node_t	bm_node;
	mac_handle_t	bm_mh;
	bridge_inst_t	*bm_inst;
	uint_t		bm_flags;	/* BMF_* below */
	uint_t		bm_maxsdu;
	link_state_t	bm_linkstate;
	char		bm_name[MAXLINKNAMELEN];
} bridge_mac_t;

#define	BMF_DLS		0x0001		/* dls monitor node created */
#define	BMF_STARTED	0x0002		/* snoop-like client is present */

/*
 * Bridge streams are used only for instance allocation and control.
 */
typedef struct bridge_stream_s {
	bridge_inst_t	*bs_inst;
	queue_t		*bs_wq;		/* write-side queue for stream */
	minor_t		bs_minor;
	uint_t		bs_taskq_cnt;	/* taskq references */
} bridge_stream_t;

/*
 * These macros are used to set and test link membership in particular VLANs.
 * This membership is used to determine how to forward packets between
 * interfaces.
 */

#define	BRIDGE_VLAN_ARR_SIZE	\
	(P2ROUNDUP(VLAN_ID_MAX, NBBY) / NBBY)

#define	BRIDGE_VLAN_ISSET(l, v)	((l)->bl_vlans[(v) / NBBY] & \
	(1 << ((v) % NBBY)))

#define	BRIDGE_VLAN_SET(l, v)	((l)->bl_vlans[(v) / NBBY] |= \
	(1 << ((v) % NBBY)))

#define	BRIDGE_VLAN_CLR(l, v)	((l)->bl_vlans[(v) / NBBY] &= \
	~(1 << ((v) % NBBY)))

#define	BRIDGE_AF_ISSET(l, v)	((l)->bl_afs[(v) / NBBY] & \
	(1 << ((v) % NBBY)))

/*
 * This structure represents a link attached to a bridge.  VLAN membership
 * information is kept here; when forwarding, we must look at the membership of
 * the input link and the output to determine when to update the packet
 * contents and when to discard.
 */
typedef struct bridge_link_s {
	list_node_t	bl_node;
	uint_t		bl_refs;
	datalink_id_t	bl_linkid;	/* allocated link ID for bridge */
	bridge_state_t	bl_state;	/* blocking/learning/forwarding */
	uint_t		bl_pvid;	/* VLAN ID for untagged traffic */
	uint_t		bl_flags;	/* BLF_* below */
	uint_t		bl_learns;	/* learning limit */
	mac_handle_t	bl_mh;
	mac_client_handle_t	bl_mch;
	uint32_t	bl_margin;
	uint_t		bl_maxsdu;
	mac_unicast_handle_t	bl_mah;
	mac_notify_handle_t	bl_mnh;
	mac_promisc_handle_t	bl_mphp;
	bridge_inst_t	*bl_inst;	/* backpointer to bridge instance */
	kstat_t		*bl_ksp;
	void		*bl_trilldata;
	mblk_t		*bl_lfailmp;	/* preallocated */
	link_state_t	bl_linkstate;
	uint_t		bl_trillthreads;
	kcondvar_t	bl_trillwait;
	kmutex_t	bl_trilllock;
	uint8_t		bl_local_mac[ETHERADDRL];
	uint8_t		bl_vlans[BRIDGE_VLAN_ARR_SIZE];
	uint8_t		bl_afs[BRIDGE_VLAN_ARR_SIZE];
	bridge_kslink_t	bl_kstats;
} bridge_link_t;

#define	BLF_DELETED		0x0001	/* waiting for last reference to go */
#define	BLF_CLIENT_OPEN		0x0002	/* MAC client opened */
#define	BLF_MARGIN_ADDED	0x0004	/* MAC margin added */
#define	BLF_SET_BRIDGE		0x0008	/* MAC in bridging mode */
#define	BLF_PROM_ADDED		0x0010	/* MAC promiscuous added */
#define	BLF_FREED		0x0020	/* free has begun; debug assertion */
#define	BLF_TRILLACTIVE		0x0040	/* in active forwarding use */
#define	BLF_SDUFAIL		0x0080	/* has mismatched SDU */
#define	BLF_LINK_ADDED		0x0100	/* link added in bridge instance */

/*
 * This represents a learned forwarding entry.  These are generally created and
 * refreshed on demand as we learn about nodes through source MAC addresses we
 * see.  They're destroyed when they age away.  For forwarding, we look up the
 * destination address in an AVL tree, and the entry found tells us where the
 * that source must live.
 */
typedef struct bridge_fwd_s {
	avl_node_t	bf_node;
	uchar_t		bf_dest[ETHERADDRL];
	uint16_t	bf_trill_nick;	/* destination nickname */
	clock_t		bf_lastheard;	/* time we last heard from this node */
	uint_t		bf_flags;	/* BFF_* below */
	uint_t		bf_refs;
	uint16_t	bf_vlanid;	/* VLAN ID for IVL */
	uint16_t	bf_vcnt;	/* number of duplicates */
	uint_t		bf_nlinks;	/* number of links in bf_links */
	uint_t		bf_maxlinks;	/* allocated size of link array */
	bridge_link_t	**bf_links;
} bridge_fwd_t;

#define	BFF_INTREE	0x0001
#define	BFF_LOCALADDR	0x0002		/* address is known to mac layer */
#define	BFF_VLANLOCAL	0x0004		/* set if duplicate for IVL */

/* TRILL linkage */
typedef void (*trill_recv_pkt_t)(void *, bridge_link_t *, mac_resource_handle_t,
    mblk_t *, mac_header_info_t *);
typedef void (*trill_encap_pkt_t)(void *, bridge_link_t *, mac_header_info_t *,
    mblk_t *, uint16_t);
typedef void (*trill_br_dstr_t)(void *, bridge_inst_t *);
typedef void (*trill_ln_dstr_t)(void *, bridge_link_t *);

extern void bridge_trill_register_cb(trill_recv_pkt_t, trill_encap_pkt_t,
    trill_br_dstr_t, trill_ln_dstr_t);
extern bridge_inst_t *bridge_trill_brref(const char *, void *);
extern void bridge_trill_brunref(bridge_inst_t *);
extern bridge_link_t *bridge_trill_lnref(bridge_inst_t *, datalink_id_t,
    void *);
extern void bridge_trill_lnunref(bridge_link_t *);
extern void bridge_trill_decaps(bridge_link_t *, mblk_t *, uint16_t);
extern mblk_t *bridge_trill_output(bridge_link_t *, mblk_t *);
extern void bridge_trill_setvlans(bridge_link_t *, const uint8_t *);
extern void bridge_trill_flush(bridge_link_t *, uint16_t, boolean_t);

/* Ethernet multicast address; constant stored in bridge module */
extern const uint8_t all_isis_rbridges[];
extern const uint8_t bridge_group_address[];

#ifdef __cplusplus
}
#endif

#endif /* _BRIDGE_IMPL_H */