root/usr/src/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 */