Commit ba909a45 authored by Changqi Lu's avatar Changqi Lu Committed by Tomasz Zawadzki
Browse files

lib/iscsi: add rpc method iscsi_get_histogram



A new rpc method(iscsi_get_histogram) is added to get
histogram of iscsi target.

Change-Id: I4bbda04763e4db734b798657c8acb9e702c69f83
Signed-off-by: default avatarChangqi Lu <luchangqi.123@bytedance.com>
Signed-off-by: default avatarzhenwei pi <pizhenwei@bytedance.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/21001


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
parent 90ba272c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ Added `iscsi_get_stats` RPC method to get stat information about all active conn

Added `iscsi_enable_histogram` RPC method to enable or disable histogram for specified iscsi target.

Added `iscsi_get_histogram` RPC method to get histogram for specified iscsi target.

### trace

Merged `struct spdk_trace_flags` and `struct spdk_trace_histories` into
+48 −0
Original line number Diff line number Diff line
@@ -8015,6 +8015,54 @@ Example response:
}
~~~

### iscsi_get_histogram {#rpc_iscsi_get_histogram}

Get latency histogram for specified iscsi target node.

#### Parameters

Name                    | Optional | Type        | Description
----------------------- | -------- | ----------- | -----------
name                    | Required | string      | Iscsi target node name

#### Result

Name                    | Description
------------------------| -----------
histogram               | Base64 encoded histogram
bucket_shift            | Granularity of the histogram buckets
tsc_rate                | Ticks per second

#### Example

Example request:

~~~json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "iscsi_get_histogram",
  "params": {
    "name": "iqn.2016-06.io.spdk:target1"
  }
}
~~~

Example response:
Note that histogram field is trimmed, actual encoded histogram length is ~80kb.

~~~json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "histogram": "AAAAAAAAAAAAAA...AAAAAAAAA==",
    "tsc_rate": 2300000000,
    "bucket_shift": 7
  }
}
~~~

## NVMe-oF Target {#jsonrpc_components_nvmf_tgt}

### nvmf_create_transport method {#rpc_nvmf_create_transport}
+85 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#include "spdk/util.h"
#include "spdk/string.h"
#include "spdk/log.h"
#include "spdk/base64.h"
#include "spdk/histogram_data.h"

static void
rpc_iscsi_get_initiator_groups(struct spdk_jsonrpc_request *request,
@@ -1915,3 +1917,86 @@ rpc_iscsi_enable_histogram(struct spdk_jsonrpc_request *request,
}

SPDK_RPC_REGISTER("iscsi_enable_histogram", rpc_iscsi_enable_histogram, SPDK_RPC_RUNTIME)

struct rpc_iscsi_get_histogram_request {
	char *name;
};

static const struct spdk_json_object_decoder rpc_iscsi_get_histogram_request_decoders[] = {
	{"name", offsetof(struct rpc_iscsi_get_histogram_request, name), spdk_json_decode_string}
};

static void
free_rpc_iscsi_get_histogram_request(struct rpc_iscsi_get_histogram_request *r)
{
	free(r->name);
}

static void
rpc_iscsi_get_histogram(struct spdk_jsonrpc_request *request,
			const struct spdk_json_val *params)
{
	struct rpc_iscsi_get_histogram_request req = {NULL};
	struct spdk_iscsi_tgt_node *target;
	struct spdk_json_write_ctx *w;
	char *encoded_histogram;
	size_t src_len, dst_len;
	int rc;

	if (spdk_json_decode_object(params, rpc_iscsi_get_histogram_request_decoders,
				    SPDK_COUNTOF(rpc_iscsi_get_histogram_request_decoders),
				    &req)) {
		SPDK_ERRLOG("spdk_json_decode_object failed\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 "spdk_json_decode_object failed");
		goto free_req;
	}

	target = iscsi_find_tgt_node(req.name);
	if (target == NULL) {
		SPDK_ERRLOG("target is not found\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
						 "target not found");
		goto free_req;
	}

	if (!target->histogram) {
		SPDK_ERRLOG("target's histogram function is not enabled\n");
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
						 "target's histogram function is not enabled");
		goto free_req;
	}

	src_len = SPDK_HISTOGRAM_NUM_BUCKETS(target->histogram) * sizeof(uint64_t);
	dst_len = spdk_base64_get_encoded_strlen(src_len) + 1;
	encoded_histogram = malloc(dst_len);
	if (encoded_histogram == NULL) {
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 spdk_strerror(ENOMEM));
		goto free_req;
	}

	rc = spdk_base64_encode(encoded_histogram, target->histogram->bucket, src_len);
	if (rc != 0) {
		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
						 spdk_strerror(-rc));
		goto free_encoded_histogram;
	}

	w = spdk_jsonrpc_begin_result(request);

	spdk_json_write_object_begin(w);
	spdk_json_write_named_string(w, "histogram", encoded_histogram);
	spdk_json_write_named_int64(w, "bucket_shift", target->histogram->bucket_shift);
	spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz());

	spdk_json_write_object_end(w);
	spdk_jsonrpc_end_result(request, w);

free_encoded_histogram:
	free(encoded_histogram);
free_req:
	free_rpc_iscsi_get_histogram_request(&req);
}

SPDK_RPC_REGISTER("iscsi_get_histogram", rpc_iscsi_get_histogram, SPDK_RPC_RUNTIME)
+10 −0
Original line number Diff line number Diff line
@@ -183,6 +183,16 @@ def iscsi_enable_histogram(client, name, enable):
    return client.call('iscsi_enable_histogram', params)


def iscsi_get_histogram(client, name):
    """Get histogram for specified iscsi target.

    Args:
        name: name of iscsi target
    """
    params = {'name': name}
    return client.call('iscsi_get_histogram', params)


def iscsi_create_target_node(
        client,
        luns,
+8 −0
Original line number Diff line number Diff line
@@ -1506,6 +1506,14 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
    p.add_argument('name', help='iscsi target name')
    p.set_defaults(func=iscsi_enable_histogram)

    def iscsi_get_histogram(args):
        print_dict(rpc.iscsi.iscsi_get_histogram(args.client, name=args.name))

    p = subparsers.add_parser('iscsi_get_histogram',
                              help='Get histogram for specified iscsi target')
    p.add_argument('name', help='target name')
    p.set_defaults(func=iscsi_get_histogram)

    def iscsi_create_target_node(args):
        luns = []
        for u in args.bdev_name_id_pairs.strip().split(" "):