//==========================================================================
//
//      include/net/if_bridge.h
//
//     
//
//==========================================================================
// ####BSDALTCOPYRIGHTBEGIN####                                             
// -------------------------------------------                              
// Portions of this software may have been derived from OpenBSD             
// or other sources, and if so are covered by the appropriate copyright     
// and license included herein.                                             
// -------------------------------------------                              
// ####BSDALTCOPYRIGHTEND####                                               
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    Jason L. Wright (jason@thought.net)
// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt, manu.sharma@ascom.ch
// Date:         2000-07-18
// Purpose:      Ethernet bridge
// Description:  
//              
//
//####DESCRIPTIONEND####
//
//==========================================================================

/*      $OpenBSD: if_bridge.h,v 1.25 2003/07/15 03:41:15 jason Exp $        */

/*
 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Effort sponsored in part by the Defense Advanced Research Projects
 * Agency (DARPA) and Air Force Research Laboratory, Air Force
 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
 *
 */

/*
 * Bridge control request: add/delete member interfaces.
 */
struct ifbreq {
        char            ifbr_name[IFNAMSIZ];       /* bridge ifs name */
        char            ifbr_ifsname[IFNAMSIZ];    /* member ifs name */
        u_int32_t       ifbr_ifsflags;             /* member ifs flags */
        u_int8_t        ifbr_state;                /* member stp state */
        u_int8_t        ifbr_priority;             /* member stp priority */
        u_int8_t        ifbr_portno;               /* member port number */
        u_int32_t       ifbr_path_cost;            /* member stp path cost */
};
/* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */
#define IFBIF_LEARNING          0x0001        /* ifs can learn */
#define IFBIF_DISCOVER          0x0002        /* ifs sends packets w/unknown dest */
#define IFBIF_BLOCKNONIP        0x0004        /* ifs blocks non-IP/ARP in/out */
#define IFBIF_STP               0x0008        /* ifs participates in spanning tree */
#define IFBIF_SPAN              0x0100        /* ifs is a span port (ro) */
#define IFBIF_RO_MASK           0xff00        /* read only bits */
/* SIOCBRDGFLUSH */
#define IFBF_FLUSHDYN        0x0        /* flush dynamic addresses only */
#define IFBF_FLUSHALL        0x1        /* flush all addresses from cache */

/* port states */
#define BSTP_IFSTATE_DISABLED        0
#define BSTP_IFSTATE_LISTENING       1
#define BSTP_IFSTATE_LEARNING        2
#define BSTP_IFSTATE_FORWARDING      3
#define BSTP_IFSTATE_BLOCKING        4

/*
 * Interface list structure
 */
struct ifbifconf {
        char             ifbic_name[IFNAMSIZ];        /* bridge ifs name */
        u_int32_t        ifbic_len;                /* buffer size */
        union {
                caddr_t       ifbicu_buf;
                struct        ifbreq *ifbicu_req;
        } ifbic_ifbicu;
#define ifbic_buf        ifbic_ifbicu.ifbicu_buf
#define ifbic_req        ifbic_ifbicu.ifbicu_req
};

/*
 * Bridge address request
 */
struct ifbareq {
        char                    ifba_name[IFNAMSIZ];     /* bridge name */
        char                    ifba_ifsname[IFNAMSIZ];  /* destination ifs */
        u_int8_t                ifba_age;                /* address age */
        u_int8_t                ifba_flags;              /* address flags */
        struct ether_addr       ifba_dst;                /* destination addr */
};

#define IFBAF_TYPEMASK              0x03                /* address type mask */
#define IFBAF_DYNAMIC               0x00                /* dynamically learned */
#define IFBAF_STATIC                0x01                /* static address */

struct ifbaconf {
        char                     ifbac_name[IFNAMSIZ];     /* bridge ifs name */
        u_int32_t                ifbac_len;                /* buffer size */
        union {
                caddr_t        ifbacu_buf;                 /* buffer */
                struct ifbareq *ifbacu_req;                /* request pointer */
        } ifbac_ifbacu;
#define ifbac_buf        ifbac_ifbacu.ifbacu_buf
#define ifbac_req        ifbac_ifbacu.ifbacu_req
};

struct ifbrparam {
        char                        ifbrp_name[IFNAMSIZ];
        union {
                u_int32_t       ifbrpu_csize;           /* cache size */
                int             ifbrpu_ctime;           /* cache time (sec) */
                u_int16_t       ifbrpu_prio;            /* bridge priority */
                u_int8_t        ifbrpu_hellotime;       /* hello time (sec) */
                u_int8_t        ifbrpu_fwddelay;        /* fwd delay (sec) */
                u_int8_t        ifbrpu_maxage;          /* max age (sec) */
        } ifbrp_ifbrpu;
};
#define ifbrp_csize       ifbrp_ifbrpu.ifbrpu_csize
#define ifbrp_ctime       ifbrp_ifbrpu.ifbrpu_ctime
#define ifbrp_prio        ifbrp_ifbrpu.ifbrpu_prio
#define ifbrp_hellotime   ifbrp_ifbrpu.ifbrpu_hellotime
#define ifbrp_fwddelay    ifbrp_ifbrpu.ifbrpu_fwddelay
#define ifbrp_maxage      ifbrp_ifbrpu.ifbrpu_maxage

/*
 * Bridge cache size get/set
 */
struct ifbcachereq {
	char			ifbc_name[IFNAMSIZ];	/* bridge ifs name */
	u_int32_t		ifbc_size;		/* cache size */
};

/*
 * Bridge cache timeout get/set
 */
struct ifbcachetoreq {
	char			ifbct_name[IFNAMSIZ];	/* bridge ifs name */
	u_int32_t		ifbct_time;		/* cache time (sec) */
};

/*
 * Bridge mac rules
 */
struct ifbrlreq {
        char                    ifbr_name[IFNAMSIZ];     /* bridge ifs name */
        char                    ifbr_ifsname[IFNAMSIZ];  /* member ifs name */
        u_int8_t                ifbr_action;             /* disposition */
        u_int8_t                ifbr_flags;              /* flags */
        struct ether_addr       ifbr_src;                /* source mac */
        struct ether_addr       ifbr_dst;                /* destination mac */
};
#define BRL_ACTION_BLOCK         0x01                        /* block frame */
#define BRL_ACTION_PASS          0x02                        /* pass frame */
#define BRL_FLAG_IN              0x08                        /* input rule */
#define BRL_FLAG_OUT             0x04                        /* output rule */
#define BRL_FLAG_SRCVALID        0x02                        /* src valid */
#define BRL_FLAG_DSTVALID        0x01                        /* dst valid */

struct ifbrlconf {
        char             ifbrl_name[IFNAMSIZ];    /* bridge ifs name */
        char             ifbrl_ifsname[IFNAMSIZ]; /* member ifs name */
        u_int32_t        ifbrl_len;               /* buffer size */
        union {
                caddr_t        ifbrlu_buf;
                struct        ifbrlreq *ifbrlu_req;
        } ifbrl_ifbrlu;
#define ifbrl_buf        ifbrl_ifbrlu.ifbrlu_buf
#define ifbrl_req        ifbrl_ifbrlu.ifbrlu_req
};

/*
 * Bridge filtering rules
 */
SIMPLEQ_HEAD(brl_head, brl_node);

struct brl_node {
        SIMPLEQ_ENTRY(brl_node)        brl_next;        /* next rule */
        struct ether_addr        brl_src;        /* source mac address */
        struct ether_addr        brl_dst;        /* destination mac address */
        u_int16_t                brl_tag;        /* pf tag ID */
        u_int8_t                brl_action;        /* what to do with match */
        u_int8_t                brl_flags;        /* comparision flags */
};

struct bridge_timer {
        u_int16_t active;
        u_int16_t value;
};

struct bstp_config_unit {
        u_int64_t        cu_rootid;
        u_int64_t        cu_bridge_id;
        u_int32_t        cu_root_path_cost;
        u_int16_t        cu_message_age;
        u_int16_t        cu_max_age;
        u_int16_t        cu_hello_time;
        u_int16_t        cu_forward_delay;
        u_int16_t        cu_port_id;
        u_int8_t        cu_message_type;
        u_int8_t        cu_topology_change_acknowledgment;
        u_int8_t        cu_topology_change;
};

struct bstp_tcn_unit {
        u_int8_t        tu_message_type;
};

/*
 * Bridge interface list
 */
struct bridge_iflist {
        LIST_ENTRY(bridge_iflist)        next;                /* next in list */
        u_int64_t                        bif_designated_root;
        u_int64_t                        bif_designated_bridge;
        u_int32_t                        bif_path_cost;
        u_int32_t                        bif_designated_cost;
        struct bridge_timer                bif_hold_timer;
        struct bridge_timer                bif_message_age_timer;
        struct bridge_timer                bif_forward_delay_timer;
        struct bstp_config_unit                bif_config_bpdu;
        u_int16_t                        bif_port_id;
        u_int16_t                        bif_designated_port;
        u_int8_t                        bif_state;
        u_int8_t                        bif_topology_change_acknowledge;
        u_int8_t                        bif_config_pending;
        u_int8_t                        bif_change_detection_enabled;
        u_int8_t                        bif_priority;
        struct brl_head                        bif_brlin;        /* input rules */
        struct brl_head                        bif_brlout;        /* output rules */
        struct                                ifnet *ifp;        /* member interface */
        u_int32_t                        bif_flags;        /* member flags */
};

/*
 * Bridge route node
 */
struct bridge_rtnode {
        LIST_ENTRY(bridge_rtnode)        brt_next;        /* next in list */
        struct                                ifnet *brt_if;        /* destination ifs */
        u_int8_t                        brt_flags;        /* address flags */
        u_int8_t                        brt_age;        /* age counter */
        struct                                ether_addr brt_addr;        /* dst addr */
};

/*
 * Software state for each bridge
 */
struct bridge_softc {
        struct                     ifnet sc_if;        /* the interface */
        u_int64_t                  sc_designated_root;
        u_int64_t                  sc_bridge_id;
        struct bridge_iflist       *sc_root_port;
        u_int32_t                  sc_root_path_cost;
        u_int16_t                  sc_max_age;
        u_int16_t                  sc_hello_time;
        u_int16_t                  sc_forward_delay;
        u_int16_t                  sc_bridge_max_age;
        u_int16_t                  sc_bridge_hello_time;
        u_int16_t                  sc_bridge_forward_delay;
        u_int16_t                  sc_topology_change_time;
        u_int16_t                  sc_hold_time;
        u_int16_t                  sc_bridge_priority;
        u_int8_t                   sc_topology_change_detected;
        u_int8_t                   sc_topology_change;
        struct bridge_timer        sc_hello_timer;
        struct bridge_timer        sc_topology_change_timer;
        struct bridge_timer        sc_tcn_timer;
        u_int32_t                  sc_brtmax;        /* max # addresses */
        u_int32_t                  sc_brtcnt;        /* current # addrs */
        int                        sc_brttimeout;        /* timeout ticks */
        u_int32_t                  sc_hashkey;        /* hash key */
#ifndef __ECOS
        struct timeout             sc_brtimeout;        /* timeout state */
        struct timeout             sc_bstptimeout;        /* stp timeout */
#endif
        LIST_HEAD(, bridge_iflist)        sc_iflist;        /* interface list */
        LIST_HEAD(bridge_rthead, bridge_rtnode)        *sc_rts;/* hash table */
        LIST_HEAD(, bridge_iflist)        sc_spanlist;        /* span ports */
};

#ifdef _KERNEL
extern u_int8_t bstp_etheraddr[];

void    bridge_ifdetach(struct ifnet *);
struct mbuf *bridge_input(struct ifnet *, struct ether_header *,
                    struct mbuf *);
int     bridge_output(struct ifnet *, struct mbuf *, struct sockaddr *,
                    struct rtentry *);
struct mbuf *bstp_input(struct bridge_softc *, struct ifnet *,
                    struct ether_header *, struct mbuf *);
void    bstp_initialization(struct bridge_softc *);
int     bstp_ioctl(struct ifnet *, u_long, caddr_t);
void    bridge_rtdelete(struct bridge_softc *, struct ifnet *, int);
#endif /* _KERNEL */
