#ifndef _MAC_FLOW_IMPL_H
#define _MAC_FLOW_IMPL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/param.h>
#include <sys/atomic.h>
#include <sys/ksynch.h>
#include <sys/mac_flow.h>
#include <sys/stream.h>
#include <sys/sdt.h>
#include <net/if.h>
#define FLOW_REFHOLD(flent) { \
DTRACE_PROBE1(flow_refhold, flow_entry_t *, (flent)); \
mutex_enter(&(flent)->fe_lock); \
(flent)->fe_refcnt++; \
mutex_exit(&(flent)->fe_lock); \
}
#define FLOW_TRY_REFHOLD(flent, err) { \
DTRACE_PROBE1(flow_refhold, flow_entry_t *, (flent)); \
(err) = 0; \
mutex_enter(&(flent)->fe_lock); \
if ((flent)->fe_flags & (FE_INCIPIENT | FE_QUIESCE | FE_CONDEMNED | \
FE_UF_NO_DATAPATH | FE_MC_NO_DATAPATH)) \
(err) = -1; \
else \
(flent)->fe_refcnt++; \
mutex_exit(&(flent)->fe_lock); \
}
#define FLOW_REFRELE(flent) { \
DTRACE_PROBE1(flow_refrele, flow_entry_t *, (flent)); \
mutex_enter(&(flent)->fe_lock); \
ASSERT((flent)->fe_refcnt != 0); \
(flent)->fe_refcnt--; \
if ((flent)->fe_flags & FE_WAITER) { \
ASSERT((flent)->fe_refcnt != 0); \
cv_signal(&(flent)->fe_cv); \
mutex_exit(&(flent)->fe_lock); \
} else if ((flent)->fe_refcnt == 0) { \
mac_flow_destroy(flent); \
} else { \
mutex_exit(&(flent)->fe_lock); \
} \
}
#define FLOW_USER_REFHOLD(flent) { \
mutex_enter(&(flent)->fe_lock); \
(flent)->fe_user_refcnt++; \
mutex_exit(&(flent)->fe_lock); \
}
#define FLOW_USER_REFRELE(flent) { \
mutex_enter(&(flent)->fe_lock); \
ASSERT((flent)->fe_user_refcnt != 0); \
if (--(flent)->fe_user_refcnt == 0 && \
((flent)->fe_flags & FE_WAITER)) \
cv_signal(&(flent)->fe_cv); \
mutex_exit(&(flent)->fe_lock); \
}
#define FLOW_FINAL_REFRELE(flent) { \
ASSERT(flent->fe_refcnt == 1 && flent->fe_user_refcnt == 0); \
FLOW_REFRELE(flent); \
}
#define FLOW_MARK(flent, flag) { \
mutex_enter(&(flent)->fe_lock); \
(flent)->fe_flags |= flag; \
mutex_exit(&(flent)->fe_lock); \
}
#define FLOW_UNMARK(flent, flag) { \
mutex_enter(&(flent)->fe_lock); \
(flent)->fe_flags &= ~flag; \
mutex_exit(&(flent)->fe_lock); \
}
#define FLENT_TO_MIP(flent) \
(flent->fe_mbg != NULL ? mac_bcast_grp_mip(flent->fe_mbg) : \
((mac_client_impl_t *)flent->fe_mcip)->mci_mip)
#define FLOW_BYTES_PER_TICK(bps) (((bps) >> 3) / hz)
#define FLOW_MIN_PRIORITY(min, max, pri) \
((min) + ((((max) - (min)) / MRP_PRIORITY_LEVELS) * (pri)))
#define FLOW_MAX_PRIORITY(min, max, base) \
((base) + (((max) - (min)) / MRP_PRIORITY_LEVELS))
#define FLOW_PRIORITY(min, max, pri) \
(pri) == MPL_HIGH ? (max) : \
(pri) == MPL_LOW ? (min) : \
((min) + (((max) - (min)) / 2))
#define MAC_FLOW_TAB_SIZE 500
typedef struct flow_entry_s flow_entry_t;
typedef struct flow_tab_s flow_tab_t;
typedef struct flow_state_s flow_state_t;
struct mac_impl_s;
struct mac_client_impl_s;
struct mac_soft_ring_set_s;
struct mac_group_s;
struct mac_bcast_grp_s;
#define FLOW_INBOUND 0x01
#define FLOW_OUTBOUND 0x02
#define FLOW_IGNORE_VLAN 0x04
typedef void (*flow_fn_t)(void *, void *, mblk_t *, boolean_t);
typedef enum {
FLOW_DRIVER_UPCALL,
FLOW_USER_REF
} mac_flow_state_t;
typedef boolean_t (*flow_match_fn_t)(flow_tab_t *, flow_entry_t *,
flow_state_t *);
typedef enum {
FE_QUIESCE = 0x01,
FE_WAITER = 0x02,
FE_FLOW_TAB = 0x04,
FE_G_FLOW_HASH = 0x08,
FE_INCIPIENT = 0x10,
FE_CONDEMNED = 0x20,
FE_UF_NO_DATAPATH = 0x40,
FE_MC_NO_DATAPATH = 0x80,
} flow_entry_flags_t;
typedef enum {
FLOW_PRIMARY_MAC = 0x01,
FLOW_VNIC_MAC = 0x02,
FLOW_MCAST = 0x04,
FLOW_OTHER = 0x08,
FLOW_USER = 0x10,
FLOW_NO_STATS = 0x20,
} flow_entry_type_t;
#define FLOW_VNIC FLOW_VNIC_MAC
typedef struct mac_bw_ctl_s {
kmutex_t mac_bw_lock;
uint32_t mac_bw_state;
size_t mac_bw_sz;
size_t mac_bw_limit;
size_t mac_bw_used;
size_t mac_bw_drop_threshold;
size_t mac_bw_drop_bytes;
size_t mac_bw_polled;
size_t mac_bw_intr;
clock_t mac_bw_curr_time;
} mac_bw_ctl_t;
struct flow_entry_s {
flow_entry_t *fe_next;
datalink_id_t fe_link_id;
mac_resource_props_t fe_resource_props;
mac_resource_props_t fe_effective_props;
kmutex_t fe_lock;
char fe_flow_name[MAXFLOWNAMELEN];
flow_desc_t fe_flow_desc;
kcondvar_t fe_cv;
uint32_t fe_refcnt;
uint32_t fe_user_refcnt;
flow_entry_flags_t fe_flags;
flow_fn_t fe_cb_fn;
void *fe_cb_arg1;
void *fe_cb_arg2;
void *fe_client_cookie;
struct mac_group_s *fe_rx_ring_group;
struct mac_soft_ring_set_s *fe_rx_srs[MAX_RINGS_PER_GROUP];
uint32_t fe_rx_srs_cnt;
struct mac_group_s *fe_tx_ring_group;
struct mac_soft_ring_set_s *fe_tx_srs;
struct mac_client_impl_s *fe_mcip;
flow_entry_t *fe_client_next;
struct mac_bcast_grp_s *fe_mbg;
flow_entry_type_t fe_type;
mac_bw_ctl_t fe_tx_bw;
mac_bw_ctl_t fe_rx_bw;
flow_match_fn_t fe_match;
int fe_index;
flow_tab_t *fe_flow_tab;
kstat_t *fe_ksp;
kstat_t *fe_misc_stat_ksp;
boolean_t fe_desc_logged;
uint64_t fe_nic_speed;
};
typedef struct flow_l2info_s {
uchar_t *l2_start;
uint8_t *l2_daddr;
uint16_t l2_vid;
uint32_t l2_sap;
uint_t l2_hdrsize;
} flow_l2info_t;
typedef struct flow_l3info_s {
uchar_t *l3_start;
uint8_t l3_protocol;
uint8_t l3_version;
boolean_t l3_dst_or_src;
uint_t l3_hdrsize;
boolean_t l3_fragmented;
} flow_l3info_t;
typedef struct flow_l4info_s {
uchar_t *l4_start;
uint16_t l4_src_port;
uint16_t l4_dst_port;
uint16_t l4_hash_port;
} flow_l4info_t;
struct flow_state_s {
uint_t fs_flags;
mblk_t *fs_mp;
flow_l2info_t fs_l2info;
flow_l3info_t fs_l3info;
flow_l4info_t fs_l4info;
};
#define FLOW_MAX_ACCEPT 16
typedef struct flow_ops_s {
int (*fo_accept_fe)(flow_tab_t *, flow_entry_t *);
uint32_t (*fo_hash_fe)(flow_tab_t *, flow_entry_t *);
boolean_t (*fo_match_fe)(flow_tab_t *, flow_entry_t *,
flow_entry_t *);
int (*fo_insert_fe)(flow_tab_t *, flow_entry_t **,
flow_entry_t *);
uint32_t (*fo_hash)(flow_tab_t *, flow_state_t *);
int (*fo_accept[FLOW_MAX_ACCEPT])(flow_tab_t *,
flow_state_t *);
} flow_ops_t;
struct flow_tab_s {
krwlock_t ft_lock;
flow_ops_t ft_ops;
flow_mask_t ft_mask;
flow_entry_t **ft_table;
uint_t ft_size;
uint_t ft_flow_count;
struct mac_impl_s *ft_mip;
struct mac_client_impl_s *ft_mcip;
};
typedef struct flow_tab_info_s {
flow_ops_t *fti_ops;
flow_mask_t fti_mask;
uint_t fti_size;
} flow_tab_info_t;
#define FLOW_TAB_EMPTY(ft) ((ft) == NULL || (ft)->ft_flow_count == 0)
#define MCIP_STAT_UPDATE(m, s, c) { \
((mac_client_impl_t *)(m))->mci_misc_stat.mms_##s \
+= ((uint64_t)(c)); \
}
#define SRS_RX_STAT_UPDATE(m, s, c) { \
((mac_soft_ring_set_t *)(m))->srs_rx.sr_stat.mrs_##s \
+= ((uint64_t)(c)); \
}
#define SRS_TX_STAT_UPDATE(m, s, c) { \
((mac_soft_ring_set_t *)(m))->srs_tx.st_stat.mts_##s \
+= ((uint64_t)(c)); \
}
#define SRS_TX_STATS_UPDATE(m, s) { \
SRS_TX_STAT_UPDATE((m), opackets, (s)->mts_opackets); \
SRS_TX_STAT_UPDATE((m), obytes, (s)->mts_obytes); \
SRS_TX_STAT_UPDATE((m), oerrors, (s)->mts_oerrors); \
}
#define SOFTRING_TX_STAT_UPDATE(m, s, c) { \
((mac_soft_ring_t *)(m))->s_st_stat.mts_##s += ((uint64_t)(c)); \
}
#define SOFTRING_TX_STATS_UPDATE(m, s) { \
SOFTRING_TX_STAT_UPDATE((m), opackets, (s)->mts_opackets); \
SOFTRING_TX_STAT_UPDATE((m), obytes, (s)->mts_obytes); \
SOFTRING_TX_STAT_UPDATE((m), oerrors, (s)->mts_oerrors); \
}
extern void mac_flow_init();
extern void mac_flow_fini();
extern int mac_flow_create(flow_desc_t *, mac_resource_props_t *,
char *, void *, uint_t, flow_entry_t **);
extern int mac_flow_add(flow_tab_t *, flow_entry_t *);
extern int mac_flow_add_subflow(mac_client_handle_t, flow_entry_t *,
boolean_t);
extern int mac_flow_hash_add(flow_entry_t *);
extern int mac_flow_lookup_byname(char *, flow_entry_t **);
extern int mac_flow_lookup(flow_tab_t *, mblk_t *, uint_t,
flow_entry_t **);
extern int mac_flow_walk(flow_tab_t *, int (*)(flow_entry_t *, void *),
void *);
extern int mac_flow_walk_nolock(flow_tab_t *,
int (*)(flow_entry_t *, void *), void *);
extern void mac_flow_modify(flow_tab_t *, flow_entry_t *,
mac_resource_props_t *);
extern void *mac_flow_get_client_cookie(flow_entry_t *);
extern uint32_t mac_flow_modify_props(flow_entry_t *, mac_resource_props_t *);
extern void mac_flow_get_desc(flow_entry_t *, flow_desc_t *);
extern void mac_flow_set_desc(flow_entry_t *, flow_desc_t *);
extern void mac_flow_remove(flow_tab_t *, flow_entry_t *, boolean_t);
extern void mac_flow_hash_remove(flow_entry_t *);
extern void mac_flow_wait(flow_entry_t *, mac_flow_state_t);
extern void mac_flow_cleanup(flow_entry_t *);
extern void mac_flow_destroy(flow_entry_t *);
extern void mac_flow_tab_create(flow_ops_t *, flow_mask_t, uint_t,
struct mac_impl_s *, flow_tab_t **);
extern void mac_flow_l2tab_create(struct mac_impl_s *, flow_tab_t **);
extern void mac_flow_tab_destroy(flow_tab_t *);
extern void flow_stat_destroy(flow_entry_t *);
#ifdef __cplusplus
}
#endif
#endif