1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  14  */
  15 
  16 #ifndef _KRRP_SESSION_H
  17 #define _KRRP_SESSION_H
  18 
  19 #include <sys/kstat.h>
  20 #include <sys/avl.h>
  21 #include <sys/uuid.h>
  22 
  23 #include <sys/krrp.h>
  24 #include <krrp_error.h>
  25 
  26 #include "krrp_stream.h"
  27 #include "krrp_connection.h"
  28 #include "krrp_pdu.h"
  29 #include "krrp_queue.h"
  30 
  31 #ifdef __cplusplus
  32 extern "C" {
  33 #endif
  34 
  35 typedef char krrp_sess_id_str_t[UUID_PRINTABLE_STRING_LENGTH];
  36 
  37 typedef enum {
  38         KRRP_SESS_SENDER = 1,
  39         KRRP_SESS_RECEIVER,
  40         KRRP_SESS_COMPOUND,
  41 } krrp_sess_type_t;
  42 
  43 /*
  44  * To extend stats need to add to the following define new field and
  45  * write corresponding update-code in krrp_sess_sender_kstat_update()
  46  */
  47 #define KRRP_SESS_SENDER_STAT_NAME_MAP(X) \
  48         X(avg_rpo, KSTAT_DATA_UINT64, 0) \
  49         X(avg_network_rpo, KSTAT_DATA_UINT64, 0) \
  50         X(cur_send_stream_txg, KSTAT_DATA_UINT64, 0) \
  51         X(cur_send_network_txg, KSTAT_DATA_UINT64, 0) \
  52         X(last_stream_ack_txg, KSTAT_DATA_UINT64, 0) \
  53         X(last_network_ack_txg, KSTAT_DATA_UINT64, 0) \
  54         X(max_pdu_seq_num, KSTAT_DATA_UINT64, 0) \
  55         X(max_pdu_seq_num_adjusted, KSTAT_DATA_UINT64, 0) \
  56         X(cur_pdu_seq_num, KSTAT_DATA_UINT64, 0) \
  57         X(fl_ctrl_window_size, KSTAT_DATA_UINT64, 0) \
  58         X(bytes_tx, KSTAT_DATA_UINT64, 0) \
  59         X(bytes_rx, KSTAT_DATA_UINT64, 0) \
  60         X(rbytes, KSTAT_DATA_UINT64, 0) \
  61         X(mem_used, KSTAT_DATA_UINT64, 0) \
  62         X(uptime, KSTAT_DATA_UINT64, 0) \
  63 
  64 /*
  65  * To extend stats need to add to the following define new field and
  66  * write corresponding update-code in krrp_sess_receiver_kstat_update()
  67  */
  68 #define KRRP_SESS_RECEIVER_STAT_NAME_MAP(X) \
  69         X(cur_recv_stream_txg, KSTAT_DATA_UINT64, 0) \
  70         X(cur_recv_network_txg, KSTAT_DATA_UINT64, 0) \
  71         X(max_pdu_seq_num, KSTAT_DATA_UINT64, 0) \
  72         X(cur_pdu_seq_num, KSTAT_DATA_UINT64, 0) \
  73         X(bytes_tx, KSTAT_DATA_UINT64, 0) \
  74         X(bytes_rx, KSTAT_DATA_UINT64, 0) \
  75         X(wbytes, KSTAT_DATA_UINT64, 0) \
  76         X(mem_used, KSTAT_DATA_UINT64, 0) \
  77         X(uptime, KSTAT_DATA_UINT64, 0) \
  78 
  79 /*
  80  * To extend stats need to add to the following define new field and
  81  * write corresponding update-code in krrp_sess_compound_kstat_update()
  82  */
  83 #define KRRP_SESS_COMPOUND_STAT_NAME_MAP(X) \
  84         X(avg_rpo, KSTAT_DATA_UINT64, 0) \
  85         X(cur_send_stream_txg, KSTAT_DATA_UINT64, 0) \
  86         X(cur_recv_stream_txg, KSTAT_DATA_UINT64, 0) \
  87         X(rbytes, KSTAT_DATA_UINT64, 0) \
  88         X(wbytes, KSTAT_DATA_UINT64, 0) \
  89         X(mem_used, KSTAT_DATA_UINT64, 0) \
  90         X(uptime, KSTAT_DATA_UINT64, 0) \
  91 
  92 #define NUM_OF_FIELDS(S) (sizeof (S) / sizeof (kstat_named_t))
  93 
  94 #define KRRP_SESS_STAT_NAME_GEN(name, dtype, def_value) kstat_named_t name;
  95 typedef struct krrp_sess_sender_kstat_s {
  96         KRRP_SESS_SENDER_STAT_NAME_MAP(KRRP_SESS_STAT_NAME_GEN)
  97 } krrp_sess_sender_kstat_t;
  98 
  99 typedef struct krrp_sess_receiver_kstat_s {
 100         KRRP_SESS_RECEIVER_STAT_NAME_MAP(KRRP_SESS_STAT_NAME_GEN)
 101 } krrp_sess_receiver_kstat_t;
 102 
 103 typedef struct krrp_sess_compound_kstat_s {
 104         KRRP_SESS_COMPOUND_STAT_NAME_MAP(KRRP_SESS_STAT_NAME_GEN)
 105 } krrp_sess_compound_kstat_t;
 106 #undef KRRP_SESS_STAT_NAME_GEN
 107 
 108 typedef struct krrp_fl_ctrl_s {
 109         uint64_t        max_pdu_seq_num_orig;
 110         uint64_t        max_pdu_seq_num;
 111         uint64_t        ack_pdu_seq_num;
 112         uint64_t        cur_pdu_seq_num;
 113         uint64_t        cwnd;
 114         boolean_t       disabled;
 115         kmutex_t        mtx;
 116         kcondvar_t      cv;
 117 } krrp_fl_ctrl_t;
 118 
 119 typedef struct krrp_sess_s {
 120         avl_node_t                              node;
 121         krrp_sess_id_str_t              id;
 122         krrp_sess_type_t                type;
 123         boolean_t                               fake_mode;
 124         boolean_t                               started;
 125         boolean_t                               running;
 126         boolean_t                               destroying;
 127         boolean_t                               shutdown;
 128         boolean_t                               on_hold;
 129 
 130         size_t                                  ref_cnt;
 131 
 132         kmutex_t                                mtx;
 133         kcondvar_t                              cv;
 134 
 135         krrp_pdu_engine_t               *data_pdu_engine;
 136         krrp_stream_t                   *stream_read;
 137         krrp_stream_t                   *stream_write;
 138         krrp_conn_t                             *conn;
 139 
 140         krrp_queue_t                    *ctrl_tx_queue;
 141         krrp_queue_t                    *data_tx_queue;
 142         krrp_queue_t                    *data_write_queue;
 143         krrp_fl_ctrl_t                  fl_ctrl;
 144 
 145         struct {
 146                 kstat_t                         *ctx;
 147                 union {
 148                         krrp_sess_sender_kstat_t        sender;
 149                         krrp_sess_receiver_kstat_t      receiver;
 150                         krrp_sess_compound_kstat_t      compound;
 151                 } data;
 152                 char                            id[KRRP_KSTAT_ID_STRING_LENGTH];
 153         } kstat;
 154 
 155         timeout_id_t                    ping_timer;
 156         boolean_t                               ping_wait_for_response;
 157 
 158         char auth_digest[KRRP_AUTH_DIGEST_MAX_LEN];
 159 
 160         krrp_error_t                    error;
 161         nvlist_t                                *private_data;
 162 } krrp_sess_t;
 163 
 164 int krrp_sess_create(krrp_sess_t **result_sess, const char *id,
 165     const char *kstat_id, const char *auth_digest,
 166     boolean_t sender, boolean_t fake_mode,
 167     boolean_t compound, krrp_error_t *error);
 168 void krrp_sess_destroy(krrp_sess_t *sess);
 169 
 170 int krrp_sess_attach_pdu_engine(krrp_sess_t *sess,
 171     krrp_pdu_engine_t *pdu_engine, krrp_error_t *error);
 172 
 173 int krrp_sess_attach_read_stream(krrp_sess_t *sess,
 174     krrp_stream_t *stream, krrp_error_t *error);
 175 int krrp_sess_attach_write_stream(krrp_sess_t *sess,
 176     krrp_stream_t *stream, krrp_error_t *error);
 177 
 178 int krrp_sess_initiator_attach_conn(krrp_sess_t *sess, krrp_conn_t *conn,
 179     krrp_error_t *error);
 180 int krrp_sess_target_attach_conn(krrp_sess_t *sess, krrp_conn_t *conn,
 181     nvlist_t *params, krrp_error_t *error);
 182 
 183 void krrp_sess_get_status(krrp_sess_t *sess, nvlist_t *result);
 184 
 185 int krrp_sess_run(krrp_sess_t *sess, boolean_t only_once,
 186     krrp_error_t *error);
 187 int krrp_sess_send_stop(krrp_sess_t *sess, krrp_error_t *error);
 188 
 189 int krrp_sess_throttle_conn(krrp_sess_t *sess, size_t limit,
 190     krrp_error_t *error);
 191 
 192 int krrp_sess_get_conn_info(krrp_sess_t *sess, nvlist_t *result,
 193     krrp_error_t *error);
 194 
 195 int krrp_sess_set_id(krrp_sess_t *sess, const char *sess_id_str,
 196     krrp_error_t *error);
 197 int krrp_sess_compare_id(const void *opaque_sess1, const void *opaque_sess2);
 198 
 199 boolean_t krrp_sess_is_started(krrp_sess_t *sess);
 200 boolean_t krrp_sess_is_running(krrp_sess_t *sess);
 201 
 202 int krrp_sess_try_hold(krrp_sess_t *sess);
 203 void krrp_sess_rele(krrp_sess_t *sess);
 204 
 205 #ifdef __cplusplus
 206 }
 207 #endif
 208 
 209 #endif /* _KRRP_SESSION_H */