root/usr/src/uts/common/io/ppp/sppp/sppp.h
/*
 * sppp.h - Solaris STREAMS PPP multiplexing pseudo-driver definitions
 *
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, provided that the above copyright
 * notice appears in all copies.
 *
 * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
 *
 * Copyright (c) 1994 The Australian National University.
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, provided that the above copyright
 * notice appears in all copies.  This software is provided without any
 * warranty, express or implied. The Australian National University
 * makes no representations about the suitability of this software for
 * any purpose.
 *
 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
 * OR MODIFICATIONS.
 *
 * This driver is derived from the original SVR4 STREAMS PPP driver
 * originally written by Paul Mackerras <paul.mackerras@cs.anu.edu.au>.
 *
 * Adi Masputra <adi.masputra@sun.com> rewrote and restructured the code
 * for improved performance and scalability.
 *
 * $Id: sppp.h,v 1.0 2000/05/08 01:10:12 masputra Exp $
 */

#ifndef __SPPP_H
#define __SPPP_H

#include <sys/dlpi.h>
#include <net/ppp_defs.h>

#ifdef  __cplusplus
extern "C" {
#endif

#if !defined(ETHERTYPE_IP)
#define ETHERTYPE_IP    0x800
#endif

#if !defined(ETHERTYPE_IPV6)
#define ETHERTYPE_IPV6  0x86dd
#endif

#if !defined(ETHERTYPE_PPP)
#define ETHERTYPE_PPP   0x880b
#endif

#if !defined(ETHERTYPE_ALLSAP)
#define ETHERTYPE_ALLSAP        0
#endif

#if !defined(PPP_ALLSAP)
#define PPP_ALLSAP      PPP_ALLSTATIONS
#endif

/*
 * DLPI handler (function table item).
 */
struct  sppp_dlpi_pinfo_t {
        int     pi_minlen;              /* minimum primitive length */
        int     pi_state;               /* acceptable starting state */
        int     (*pi_funcp)();          /* function() to call */
};

#ifndef DL_MAXPRIM
#define DL_MAXPRIM DL_GET_STATISTICS_ACK
#endif

/*
 * Per-attachment kstats.
 */
typedef struct sppp_kstats {
        kstat_named_t   allocbfail;
        kstat_named_t   rbytes;
        kstat_named_t   ierrors;
        kstat_named_t   ierrors_lower;
        kstat_named_t   ioctlsfwd;
        kstat_named_t   ioctlsfwdok;
        kstat_named_t   ioctlsfwderr;
        kstat_named_t   ipackets;
        kstat_named_t   ipackets_ctl;
        kstat_named_t   iqdropped;
        kstat_named_t   irunts;
        kstat_named_t   itoolongs;
        kstat_named_t   lsneedup;
        kstat_named_t   lsdown;
        kstat_named_t   mctlsfwd;
        kstat_named_t   mctlsfwderr;
        kstat_named_t   mctlsknown;
        kstat_named_t   mctlsunknown;
        kstat_named_t   obytes;
        kstat_named_t   oerrors;
        kstat_named_t   oerrors_lower;
        kstat_named_t   opackets;
        kstat_named_t   opackets_ctl;
        kstat_named_t   oqdropped;
        kstat_named_t   otoolongs;
        kstat_named_t   orunts;

        /* 64 bit entries */
        kstat_named_t   ipackets64;
        kstat_named_t   opackets64;
        kstat_named_t   rbytes64;
        kstat_named_t   obytes64;
} sppp_kstats_t;

/*
 * Same order as above.  Note that for netstat -i to work, there needs
 * to be "ipackets", "opackets", "ierrors", and "oerrors" kstat named
 * variables.
 */
#define SPPP_KSTATS_NAMES       \
        "allocbfail", "rbytes", "ierrors", "ierrors_lower", "ioctlsfwd", \
        "ioctlsfwdok", "ioctlsfwderr", "ipackets", "ipkts_ctl", \
        "ipkts_qdropped", "ipkts_runts", "ipkts_toolong", "lsneedup", \
        "lsdown", "mctlsfwd", "mctlsfwderr", "mctlsknown", "mctlsunknown", \
        "obytes", "oerrors", "oerrors_lower", "opackets", "opkts_ctl", \
        "opkts_qdropped", "opkts_toolong", "opkts_runts"

#define SPPP_KSTATS64_NAMES     \
        "ipackets64", "opackets64", "rbytes64", "obytes64"

/*
 * dl_addr_length needs to be equal to the absolute value of dl_sap_length,
 * in order for IP to derive a default setting for IFF_POINTOPOINT flag.
 */
typedef t_uscalar_t     spppreqsap_t;
#define SPPP_SAPL       sizeof (spppreqsap_t)
#define SPPP_ADDRL      SPPP_SAPL

/*
 * Per-Stream instance state information.
 *
 * Each instance is dynamically allocated at open() and free'd at close().
 * Each per-Stream instance points to at most one per-attachment structure
 * using the sps_ppa field. All instances are threaded together into one
 * list of active instances ordered on minor device number, using the
 * sps_nextmn field.
 */
typedef struct spppstr {
        /*
         * Note that EX_st_nextmn field should never be referenced other
         * than by the routines manipulating the global upper streams list,
         * by first obtaining exclusive access at the outer perimeter.
         */
        struct spppstr  *sps_nextmn;    /* next minor in global list */
        /*
         * These fields are common to all upper streams. If this stream
         * is attached to a ppa, then the sps_ppa field will point to the
         * ppa structure associated with this particular upper stream.
         */
        minor_t         sps_mn_id;      /* minor device number of this stream */
        queue_t         *sps_rq;        /* pointer to the read queue */
        uint32_t        sps_flags;      /* miscellaneous flags */
        uint32_t        sps_ioc_id;     /* last ioctl ID for this stream */
        struct sppa     *sps_ppa;       /* pointer to ppa structure */
        /*
         * sps_nextsib is protected by the ppa's sibling lock (ppa_sib_lock),
         * and access made to it should only be done by first ensuring that
         * the sps_ppa field is valid, i.e., this stream has been attached.
         */
        struct spppstr  *sps_nextsib;   /* next stream of same ppa (sibling) */
        /*
         * These fields are common to all non-control streams, i.e., those
         * in which a PPPIO_NEWPPA has not been issued on. Non-control
         * streams are valid candidates for network streams, and they can
         * only be considered network streams (ones which carry IP packets)
         * if they are attached and bound. The only mandatory requirement
         * for control stream is that its sps_npmode field should always
         * be equal to NPMODE_PASS, as we obviously will never block the
         * control stream from sending or receiving packets.
         */
        t_scalar_t      sps_sap;        /* bound sap */
        spppreqsap_t    sps_req_sap;    /* requested sap */
        enum NPmode     sps_npmode;     /* network protocol mode */
        /*
         * sps_dlstate is only valid for network streams in which DLPI
         * is intended to be used to transfer network-layer data. It is set
         * to DL_UNATTACHED for all other streams.
         */
        t_uscalar_t     sps_dlstate;    /* current DLPI state */
        mblk_t          *sps_hangup;    /* preallocated M_HANGUP message */

        zoneid_t        sps_zoneid;     /* zone in which we were opened */
} spppstr_t;

/*
 * Values for sps_flags, and their descriptions.
 */
/*                      0x00000001      unused */
#define SPS_CONTROL     0x00000002      /* stream is a control stream */
#define SPS_FASTPATH    0x00000004      /* stream uses IP fastpath */
#define SPS_PROMISC     0x00000008      /* stream is promiscuous */
#define SPS_RAWDATA     0x00000010      /* raw M_DATA, no DLPI header */
#define SPS_PIOATTACH   0x00000020      /* attached using PPPIO_ATTACH */
#define SPS_KDEBUG      0x00000040      /* stream has kdebug turned on */
#define SPS_CACHED      0x00000080      /* network stream pointer is cached */
#define SPS_IOCQ        0x00000100      /* queue ioctls */

#define IS_SPS_CONTROL(x)       \
        ((x)->sps_flags & SPS_CONTROL)
#define IS_SPS_FASTPATH(x)      \
        ((x)->sps_flags & SPS_FASTPATH)
#define IS_SPS_PROMISC(x)       \
        ((x)->sps_flags & SPS_PROMISC)
#define IS_SPS_RAWDATA(x)       \
        ((x)->sps_flags & SPS_RAWDATA)
#define IS_SPS_PIOATTACH(x)     \
        ((x)->sps_flags & SPS_PIOATTACH)
#define IS_SPS_KDEBUG(x)        \
        ((x)->sps_flags & SPS_KDEBUG)
#define IS_SPS_CACHED(x)        \
        ((x)->sps_flags & SPS_CACHED)
#define IS_SPS_IOCQ(x)          \
        ((x)->sps_flags & SPS_IOCQ)

/*
 * Bit format (octal based) string for cmn_err, which represents the flags.
 */
#define SPS_FLAGS_STR   \
        "\020"          \
        "\1priv"        \
        "\2control"     \
        "\3fastpath"    \
        "\4promisc"     \
        "\5rawdata"     \
        "\6pioattach"   \
        "\7kdebug"      \
        "\10cached"

/*
 * Per-Attachment instance state information.
 *
 * Each instance is dynamically allocated on first attach (PPPIO_NEWPPA).
 * Allocation of this structure is only done once per control stream. A ppa
 * instance may be shared by two or more upper streams, and it is always
 * linked to the upper stream marked as the control stream (SPS_CONTROL)
 * via the ppa_ctl field.  Non-control streams are linked to ppa_streams.
 */
typedef struct sppa {
        /*
         * Note that EX_st_nextppa field should only be accessed (walked)
         * by the ppa manipulation routines, i.e, those which affect
         * the global ppa list, e.g: open, close, new_ppa, and XX_attach_upper.
         */
        struct sppa     *ppa_nextppa;   /* next attachment instance */
        /*
         * ppa_sib_lock guards the linkages between all upper streams related
         * to this ppa. Walking the sps_nextsib of any upper streams should
         * be done by first holding this lock.
         */
        krwlock_t       ppa_sib_lock;   /* lock for sibling upper streams */
        uint32_t        ppa_flags;      /* miscellaneous flags */
        int32_t         ppa_refcnt;     /* upper stream reference count */
        uint32_t        ppa_ppa_id;     /* unique attachment id */
        spppstr_t       *ppa_streams;   /* list of all non-control streams */
        spppstr_t       *ppa_ctl;       /* back pointer to control stream */
        queue_t         *ppa_lower_wq;  /* pointer to lower write queue */
        uint16_t        ppa_mru;        /* link layer maximum receive unit */
        uint16_t        ppa_mtu;        /* link layer maximum transmit unit */
        hrtime_t        ppa_lasttx;     /* last transmit time for a packet */
        hrtime_t        ppa_lastrx;     /* last receive time for a packet */
        int32_t         ppa_promicnt;   /* promiscous stream count */
        /*
         * ppa_sta_lock mutex guards the statistic fields of this ppa, since
         * this structure is shared by upper streams of the same ppa.
         */
        kmutex_t        ppa_sta_lock;   /* mutex to lock structure */
        struct ppp_stats64 ppa_stats;   /* legacy stats structure */
        uint32_t        ppa_allocbfail; /* memory allocation failure count */
        uint32_t        ppa_ierr_low;   /* errors from below during receive */
        uint32_t        ppa_ioctlsfwd;  /* total ioctl forwarded down */
        uint32_t        ppa_ioctlsfwdok;  /* and the reply sent upward */
        uint32_t        ppa_ioctlsfwderr; /* or discarded replies */
        uint32_t        ppa_ipkt_ctl;   /* received control pkts */
        uint32_t        ppa_iqdropped;  /* msg dropped due to putq error */
        uint32_t        ppa_irunts;     /* packet rcvd is too short */
        uint32_t        ppa_itoolongs;  /* packet rcvd is larger than MRU */
        uint32_t        ppa_lsneedup;   /* total LINKSTAT_NEEDUP msg sent up */
        uint32_t        ppa_lsdown;     /* total LINKSTAT_DOWN msg sent up */
        uint32_t        ppa_mctlsfwd;   /* total M_{PC}PROTO forwarded down */
        uint32_t        ppa_mctlsfwderr; /*   and discarded count */
        uint32_t        ppa_mctlsknown; /* total known M_CTL messages */
        uint32_t        ppa_mctlsunknown; /* total unknown M_CTL messages */
        uint32_t        ppa_oerr_low;   /* errors from below during transmit */
        uint32_t        ppa_opkt_ctl;   /* transmitted control pkts */
        uint32_t        ppa_oqdropped;  /* msg dropped due to putq error */
        uint32_t        ppa_orunts;     /* packet sent is too short */
        uint32_t        ppa_otoolongs;  /* packet sent is larger than MTU */
        kstat_t         *ppa_kstats;    /* pointer to kstats structure */
        /*
         * We keep the following pointers for performance reasons. Instead
         * of walking the list of attached upper streams to find the
         * destination upper stream everytime we need to send a packet up,
         * we keep them here for easy access.
         */
        spppstr_t       *ppa_ip_cache;  /* ptr to PPP_IP upper stream */
        spppstr_t       *ppa_ip6_cache; /* ptr to PPP_IPV6 upper stream */

        kmutex_t        ppa_npmutex;    /* protects the 2 fields below */
        uint32_t        ppa_npflag;     /* network protocols blocked */
        uint32_t        ppa_holdpkts[3]; /* # of packets blocked per np */

        zoneid_t        ppa_zoneid;     /* zone where PPA is in use */
} sppa_t;

/* bit position (in ppa_npflag) for each ppp_protocol that can be blocked */
#define NP_IP   1
#define NP_IPV6 2

/*
 * Values for ppa_flags, and their descriptions.
 */
#define PPA_LASTMOD     0x00000001      /* last PPP entity on the stream */
#define PPA_TIMESTAMP   0x00000002      /* time-stamp each packet */

#define IS_PPA_LASTMOD(x)       \
        ((x)->ppa_flags & PPA_LASTMOD)
#define IS_PPA_TIMESTAMP(x)     \
        ((x)->ppa_flags & PPA_TIMESTAMP)

/*
 * Bit format (octal based) string for cmn_err, which represents the flags.
 */
#define PPA_FLAGS_STR   \
        "\020"          \
        "\1lastmod"     \
        "\2timestamp"

/*
 * General macros.
 */
#define SPDEBUG printf

/*
 * Function declarations.
 */
extern int      sppp_close(queue_t *, int, cred_t *);
extern mblk_t   *sppp_dladdud(spppstr_t *, mblk_t *, t_scalar_t, boolean_t);
extern void     sppp_dlpi_pinfoinit(void);
extern void     sppp_dlprsendup(spppstr_t *, mblk_t *, t_scalar_t, boolean_t);
extern int      sppp_lrput(queue_t *, mblk_t *);
extern int      sppp_lrsrv(queue_t *);
extern int      sppp_lwsrv(queue_t *);
extern int      sppp_mproto(queue_t *, mblk_t *, spppstr_t *);
extern int      sppp_open(queue_t *, dev_t *, int, int, cred_t *);
extern int      sppp_uwput(queue_t *, mblk_t *);
extern int      sppp_uwsrv(queue_t *);
extern void     sppp_remove_ppa(spppstr_t *sps);
extern sppa_t   *sppp_find_ppa(uint32_t ppa_id);
extern sppa_t   *sppp_create_ppa(uint32_t ppa_id, zoneid_t zoneid);

#ifdef  __cplusplus
}
#endif

#endif /* __SPPP_H */