#ifndef _VNET_H
#define _VNET_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/vnet_res.h>
#include <sys/vnet_mailbox.h>
#include <sys/modhash.h>
#include <net/if.h>
#include <sys/mac_client.h>
#define VNET_SUCCESS (0)
#define VNET_FAILURE (-1)
#define KMEM_FREE(_p) kmem_free((_p), sizeof (*(_p)))
#define VNET_NUM_DESCRIPTORS 512
#define IS_BROADCAST(ehp) \
(ether_cmp(&ehp->ether_dhost, ðerbroadcastaddr) == 0)
#define IS_MULTICAST(ehp) \
((ehp->ether_dhost.ether_addr_octet[0] & 01) == 1)
#define VNET_MATCH_RES(vresp, vnetp) \
(ether_cmp(vresp->local_macaddr, vnetp->curr_macaddr) == 0)
typedef enum vnet_flags {
VNET_STOPPED = 0x0,
VNET_STARTED = 0x1,
VNET_STOPPING = 0x2
} vnet_flags_t;
typedef struct vnet_hio_stats {
uint64_t ipackets;
uint64_t ierrors;
uint64_t opackets;
uint64_t oerrors;
uint64_t rbytes;
uint64_t obytes;
uint32_t multircv;
uint32_t multixmt;
uint32_t brdcstrcv;
uint32_t brdcstxmt;
uint32_t norcvbuf;
uint32_t noxmtbuf;
} vnet_hio_stats_t;
typedef struct vnet_hio_kstats {
kstat_named_t ipackets;
kstat_named_t ipackets64;
kstat_named_t ierrors;
kstat_named_t opackets;
kstat_named_t opackets64;
kstat_named_t oerrors;
kstat_named_t rbytes;
kstat_named_t rbytes64;
kstat_named_t obytes;
kstat_named_t obytes64;
kstat_named_t multircv;
kstat_named_t multixmt;
kstat_named_t brdcstrcv;
kstat_named_t brdcstxmt;
kstat_named_t norcvbuf;
kstat_named_t noxmtbuf;
} vnet_hio_kstats_t;
typedef struct vnet_tx_ring_stats {
uint64_t opackets;
uint64_t obytes;
} vnet_tx_ring_stats_t;
typedef struct vnet_res {
struct vnet_res *nextp;
mac_register_t macreg;
vio_net_res_type_t type;
ether_addr_t local_macaddr;
ether_addr_t rem_macaddr;
vnet_flags_t flags;
uint32_t refcnt;
struct vnet *vnetp;
kstat_t *ksp;
void *rx_ringp;
} vnet_res_t;
#define VNET_DDS_TASK_ADD_SHARE 0x01
#define VNET_DDS_TASK_DEL_SHARE 0x02
#define VNET_DDS_TASK_REL_SHARE 0x04
typedef struct vnet_dds_info {
kmutex_t lock;
uint8_t task_flags;
uint8_t dds_req_id;
vio_dds_msg_t dmsg;
dev_info_t *hio_dip;
uint64_t hio_cookie;
char hio_ifname[LIFNAMSIZ];
ddi_taskq_t *dds_taskqp;
struct vnet *vnetp;
} vnet_dds_info_t;
#define VNET_NFDB_HASH 64
#define KEY_HASH(key, addr) \
(key = (((uint64_t)(addr[0])) << 40) | \
(((uint64_t)(addr[1])) << 32) | \
(((uint64_t)(addr[2])) << 24) | \
(((uint64_t)(addr[3])) << 16) | \
(((uint64_t)(addr[4])) << 8) | \
((uint64_t)(addr[5])));
#define READ_ENTER(x) rw_enter(x, RW_READER)
#define WRITE_ENTER(x) rw_enter(x, RW_WRITER)
#define RW_EXIT(x) rw_exit(x)
#define VLAN_ID_KEY(key) ((mod_hash_key_t)(uintptr_t)(key))
typedef enum {
AST_init = 0x0, AST_vnet_alloc = 0x1,
AST_ring_init = 0x2, AST_vdds_init = 0x4,
AST_read_macaddr = 0x8, AST_fdbh_alloc = 0x10,
AST_taskq_create = 0x20, AST_vnet_list = 0x40,
AST_vgen_init = 0x80, AST_macreg = 0x100,
AST_init_mdeg = 0x200
} vnet_attach_progress_t;
#define VNET_NUM_PSEUDO_GROUPS 1
#define VNET_NUM_HYBRID_RINGS 2
#define VNET_HYBRID_RXRING_INDEX 1
#define VNET_NUM_PSEUDO_TXRINGS VNET_NUM_HYBRID_RINGS
#define VNET_NUM_PSEUDO_RXRINGS_DEFAULT (VNET_NUM_HYBRID_RINGS + 1)
typedef enum {
VNET_RXRING_FREE = 0x0,
VNET_RXRING_INUSE = 0x1,
VNET_RXRING_LDC_SERVICE = 0x2,
VNET_RXRING_LDC_GUEST = 0x4,
VNET_RXRING_HYBRID = 0x8,
VNET_RXRING_STARTED = 0x10
} vnet_rxring_state_t;
typedef enum {
VNET_TXRING_FREE = 0x0,
VNET_TXRING_INUSE = 0x1,
VNET_TXRING_SHARED = 0x2,
VNET_TXRING_HYBRID = 0x4,
VNET_TXRING_STARTED = 0x8
} vnet_txring_state_t;
typedef struct vnet_pseudo_tx_ring {
uint_t index;
vnet_txring_state_t state;
void *grp;
void *vnetp;
mac_ring_handle_t handle;
mac_ring_handle_t hw_rh;
boolean_t woken_up;
vnet_tx_ring_stats_t tx_ring_stats;
} vnet_pseudo_tx_ring_t;
typedef struct vnet_pseudo_rx_ring {
uint_t index;
vnet_rxring_state_t state;
void *grp;
void *vnetp;
mac_ring_handle_t handle;
mac_ring_handle_t hw_rh;
uint64_t gen_num;
} vnet_pseudo_rx_ring_t;
typedef struct vnet_pseudo_tx_group {
uint_t index;
void *vnetp;
mac_group_handle_t handle;
uint_t ring_cnt;
vnet_pseudo_tx_ring_t *rings;
kmutex_t flowctl_lock;
kcondvar_t flowctl_cv;
kthread_t *flowctl_thread;
boolean_t flowctl_done;
void *tx_notify_handle;
} vnet_pseudo_tx_group_t;
typedef struct vnet_pseudo_rx_group {
krwlock_t lock;
int index;
void *vnetp;
mac_group_handle_t handle;
uint_t max_ring_cnt;
uint_t ring_cnt;
vnet_pseudo_rx_ring_t *rings;
} vnet_pseudo_rx_group_t;
typedef struct vnet {
int instance;
dev_info_t *dip;
uint64_t reg;
vnet_attach_progress_t attach_progress;
struct vnet *nextp;
mac_handle_t mh;
uchar_t vendor_addr[ETHERADDRL];
uchar_t curr_macaddr[ETHERADDRL];
void *vgenhdl;
uint32_t fdb_nchains;
mod_hash_t *fdb_hashp;
vnet_res_t *vsw_fp;
krwlock_t vsw_fp_rw;
uint32_t mtu;
uint16_t default_vlan_id;
uint16_t pvid;
uint16_t *vids;
uint16_t nvids;
link_state_t link_state;
boolean_t pls_update;
vnet_flags_t flags;
vnet_res_t *hio_fp;
vnet_res_t *vres_list;
vnet_dds_info_t vdds_info;
krwlock_t vrwlock;
ddi_taskq_t *taskqp;
vnet_pseudo_rx_group_t rx_grp[VNET_NUM_PSEUDO_GROUPS];
vnet_pseudo_tx_group_t tx_grp[VNET_NUM_PSEUDO_GROUPS];
vio_net_handle_t hio_vhp;
mac_handle_t hio_mh;
mac_client_handle_t hio_mch;
mac_unicast_handle_t hio_muh;
mac_group_handle_t rx_hwgh;
mac_group_handle_t tx_hwgh;
} vnet_t;
#ifdef DEBUG
enum { DBG_LEVEL1 = 0x01, DBG_LEVEL2 = 0x02, DBG_WARN = 0x04,
DBG_ERR = 0x08 };
#define DBG1(...) do { \
if ((vnet_dbglevel & DBG_LEVEL1) != 0) { \
DEBUG_PRINTF(__func__, __VA_ARGS__); \
} \
_NOTE(CONSTCOND) } while (0)
#define DBG2(...) do { \
if ((vnet_dbglevel & DBG_LEVEL2) != 0) { \
DEBUG_PRINTF(__func__, __VA_ARGS__); \
} \
_NOTE(CONSTCOND) } while (0)
#define DWARN(...) do { \
if ((vnet_dbglevel & DBG_WARN) != 0) { \
DEBUG_PRINTF(__func__, __VA_ARGS__); \
} \
_NOTE(CONSTCOND) } while (0)
#define DERR(...) do { \
if ((vnet_dbglevel & DBG_ERR) != 0) { \
DEBUG_PRINTF(__func__, __VA_ARGS__); \
} \
_NOTE(CONSTCOND) } while (0)
#else
#define DBG1(...)
#define DBG2(...)
#define DWARN(...)
#define DERR(...)
#endif
#ifdef VNET_IOC_DEBUG
#define VNET_FORCE_LINK_DOWN 0x1
#define VNET_FORCE_LINK_UP 0x2
#endif
#ifdef __cplusplus
}
#endif
#endif