39e850d17b
Connections will soon be assigned to poll groups, which will be dynamically moved between CPU cores based on load. It no longer makes sense to restrict certain portal groups to specific cpu cores in this model. Change-Id: Iee983d75febc9797aa60021c5bc0680335e895cd Signed-off-by: Ben Walker <benjamin.walker@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/463358 Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
1481 lines
42 KiB
C
1481 lines
42 KiB
C
/*-
|
|
* BSD LICENSE
|
|
*
|
|
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
|
* Copyright (c) Intel Corporation.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "iscsi/iscsi.h"
|
|
#include "iscsi/conn.h"
|
|
#include "iscsi/tgt_node.h"
|
|
#include "iscsi/portal_grp.h"
|
|
#include "iscsi/init_grp.h"
|
|
|
|
#include "spdk/rpc.h"
|
|
#include "spdk/util.h"
|
|
#include "spdk/event.h"
|
|
#include "spdk/string.h"
|
|
#include "spdk_internal/log.h"
|
|
|
|
static void
|
|
spdk_rpc_get_initiator_groups(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
if (params != NULL) {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"get_initiator_groups requires no parameters");
|
|
return;
|
|
}
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_array_begin(w);
|
|
spdk_iscsi_init_grps_info_json(w);
|
|
spdk_json_write_array_end(w);
|
|
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("get_initiator_groups", spdk_rpc_get_initiator_groups, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_initiator_list {
|
|
size_t num_initiators;
|
|
char *initiators[MAX_INITIATOR];
|
|
};
|
|
|
|
static int
|
|
decode_rpc_initiator_list(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_initiator_list *list = out;
|
|
|
|
return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR,
|
|
&list->num_initiators, sizeof(char *));
|
|
}
|
|
|
|
static void
|
|
free_rpc_initiator_list(struct rpc_initiator_list *list)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < list->num_initiators; i++) {
|
|
free(list->initiators[i]);
|
|
}
|
|
}
|
|
|
|
struct rpc_netmask_list {
|
|
size_t num_netmasks;
|
|
char *netmasks[MAX_NETMASK];
|
|
};
|
|
|
|
static int
|
|
decode_rpc_netmask_list(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_netmask_list *list = out;
|
|
|
|
return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK,
|
|
&list->num_netmasks, sizeof(char *));
|
|
}
|
|
|
|
static void
|
|
free_rpc_netmask_list(struct rpc_netmask_list *list)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < list->num_netmasks; i++) {
|
|
free(list->netmasks[i]);
|
|
}
|
|
}
|
|
|
|
struct rpc_initiator_group {
|
|
int32_t tag;
|
|
struct rpc_initiator_list initiator_list;
|
|
struct rpc_netmask_list netmask_list;
|
|
};
|
|
|
|
static void
|
|
free_rpc_initiator_group(struct rpc_initiator_group *ig)
|
|
{
|
|
free_rpc_initiator_list(&ig->initiator_list);
|
|
free_rpc_netmask_list(&ig->netmask_list);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = {
|
|
{"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32},
|
|
{"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list},
|
|
{"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_add_initiator_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_initiator_group req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
if (spdk_json_decode_object(params, rpc_initiator_group_decoders,
|
|
SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
if (req.initiator_list.num_initiators == 0 ||
|
|
req.netmask_list.num_netmasks == 0) {
|
|
goto invalid;
|
|
}
|
|
|
|
if (spdk_iscsi_init_grp_create_from_initiator_list(req.tag,
|
|
req.initiator_list.num_initiators,
|
|
req.initiator_list.initiators,
|
|
req.netmask_list.num_netmasks,
|
|
req.netmask_list.netmasks)) {
|
|
SPDK_ERRLOG("create_from_initiator_list failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
free_rpc_initiator_group(&req);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
|
free_rpc_initiator_group(&req);
|
|
}
|
|
SPDK_RPC_REGISTER("add_initiator_group", spdk_rpc_add_initiator_group, SPDK_RPC_RUNTIME)
|
|
|
|
static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = {
|
|
{"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32},
|
|
{"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true},
|
|
{"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_add_initiators_to_initiator_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_initiator_group req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
|
|
SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
if (spdk_iscsi_init_grp_add_initiators_from_initiator_list(req.tag,
|
|
req.initiator_list.num_initiators,
|
|
req.initiator_list.initiators,
|
|
req.netmask_list.num_netmasks,
|
|
req.netmask_list.netmasks)) {
|
|
SPDK_ERRLOG("add_initiators_from_initiator_list failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
free_rpc_initiator_group(&req);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
|
free_rpc_initiator_group(&req);
|
|
}
|
|
SPDK_RPC_REGISTER("add_initiators_to_initiator_group",
|
|
spdk_rpc_add_initiators_to_initiator_group, SPDK_RPC_RUNTIME)
|
|
|
|
static void
|
|
spdk_rpc_delete_initiators_from_initiator_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_initiator_group req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
|
|
SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
if (spdk_iscsi_init_grp_delete_initiators_from_initiator_list(req.tag,
|
|
req.initiator_list.num_initiators,
|
|
req.initiator_list.initiators,
|
|
req.netmask_list.num_netmasks,
|
|
req.netmask_list.netmasks)) {
|
|
SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
free_rpc_initiator_group(&req);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
|
free_rpc_initiator_group(&req);
|
|
}
|
|
SPDK_RPC_REGISTER("delete_initiators_from_initiator_group",
|
|
spdk_rpc_delete_initiators_from_initiator_group, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_delete_initiator_group {
|
|
int32_t tag;
|
|
};
|
|
|
|
static const struct spdk_json_object_decoder rpc_delete_initiator_group_decoders[] = {
|
|
{"tag", offsetof(struct rpc_delete_initiator_group, tag), spdk_json_decode_int32},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_delete_initiator_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_delete_initiator_group req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_init_grp *ig;
|
|
|
|
if (spdk_json_decode_object(params, rpc_delete_initiator_group_decoders,
|
|
SPDK_COUNTOF(rpc_delete_initiator_group_decoders),
|
|
&req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
ig = spdk_iscsi_init_grp_unregister(req.tag);
|
|
if (!ig) {
|
|
goto invalid;
|
|
}
|
|
spdk_iscsi_tgt_node_delete_map(NULL, ig);
|
|
spdk_iscsi_init_grp_destroy(ig);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
|
}
|
|
SPDK_RPC_REGISTER("delete_initiator_group", spdk_rpc_delete_initiator_group, SPDK_RPC_RUNTIME)
|
|
|
|
static void
|
|
spdk_rpc_get_target_nodes(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
if (params != NULL) {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"get_target_nodes requires no parameters");
|
|
return;
|
|
}
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_array_begin(w);
|
|
spdk_iscsi_tgt_nodes_info_json(w);
|
|
spdk_json_write_array_end(w);
|
|
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("get_target_nodes", spdk_rpc_get_target_nodes, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_pg_ig_map {
|
|
int32_t pg_tag;
|
|
int32_t ig_tag;
|
|
};
|
|
|
|
static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = {
|
|
{"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32},
|
|
{"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32},
|
|
};
|
|
|
|
static int
|
|
decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_pg_ig_map *pg_ig_map = out;
|
|
|
|
return spdk_json_decode_object(val, rpc_pg_ig_map_decoders,
|
|
SPDK_COUNTOF(rpc_pg_ig_map_decoders),
|
|
pg_ig_map);
|
|
}
|
|
|
|
struct rpc_pg_ig_maps {
|
|
size_t num_maps;
|
|
struct rpc_pg_ig_map maps[MAX_TARGET_MAP];
|
|
};
|
|
|
|
static int
|
|
decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_pg_ig_maps *pg_ig_maps = out;
|
|
|
|
return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps,
|
|
MAX_TARGET_MAP, &pg_ig_maps->num_maps,
|
|
sizeof(struct rpc_pg_ig_map));
|
|
}
|
|
|
|
#define RPC_CONSTRUCT_TARGET_NODE_MAX_LUN 64
|
|
|
|
struct rpc_lun {
|
|
char *bdev_name;
|
|
int32_t lun_id;
|
|
};
|
|
|
|
static const struct spdk_json_object_decoder rpc_lun_decoders[] = {
|
|
{"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string},
|
|
{"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32},
|
|
};
|
|
|
|
static int
|
|
decode_rpc_lun(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_lun *lun = out;
|
|
|
|
return spdk_json_decode_object(val, rpc_lun_decoders,
|
|
SPDK_COUNTOF(rpc_lun_decoders), lun);
|
|
}
|
|
|
|
struct rpc_luns {
|
|
size_t num_luns;
|
|
struct rpc_lun luns[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN];
|
|
};
|
|
|
|
static int
|
|
decode_rpc_luns(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_luns *luns = out;
|
|
|
|
return spdk_json_decode_array(val, decode_rpc_lun, luns->luns,
|
|
RPC_CONSTRUCT_TARGET_NODE_MAX_LUN,
|
|
&luns->num_luns, sizeof(struct rpc_lun));
|
|
}
|
|
|
|
static void
|
|
free_rpc_luns(struct rpc_luns *p)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < p->num_luns; i++) {
|
|
free(p->luns[i].bdev_name);
|
|
}
|
|
}
|
|
|
|
struct rpc_target_node {
|
|
char *name;
|
|
char *alias_name;
|
|
|
|
struct rpc_pg_ig_maps pg_ig_maps;
|
|
struct rpc_luns luns;
|
|
|
|
int32_t queue_depth;
|
|
bool disable_chap;
|
|
bool require_chap;
|
|
bool mutual_chap;
|
|
int32_t chap_group;
|
|
|
|
bool header_digest;
|
|
bool data_digest;
|
|
};
|
|
|
|
static void
|
|
free_rpc_target_node(struct rpc_target_node *req)
|
|
{
|
|
free(req->name);
|
|
free(req->alias_name);
|
|
free_rpc_luns(&req->luns);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_target_node_decoders[] = {
|
|
{"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string},
|
|
{"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string},
|
|
{"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps},
|
|
{"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns},
|
|
{"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32},
|
|
{"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true},
|
|
{"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true},
|
|
{"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true},
|
|
{"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true},
|
|
{"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true},
|
|
{"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_construct_target_node(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_target_node req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_tgt_node *target;
|
|
int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
|
|
char *bdev_names[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0};
|
|
int32_t lun_ids[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0};
|
|
size_t i;
|
|
|
|
if (spdk_json_decode_object(params, rpc_target_node_decoders,
|
|
SPDK_COUNTOF(rpc_target_node_decoders),
|
|
&req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
|
|
pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
|
|
ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
|
|
}
|
|
|
|
for (i = 0; i < req.luns.num_luns; i++) {
|
|
bdev_names[i] = req.luns.luns[i].bdev_name;
|
|
lun_ids[i] = req.luns.luns[i].lun_id;
|
|
}
|
|
|
|
/*
|
|
* Use default parameters in a few places:
|
|
* index = -1 : automatically pick an index for the new target node
|
|
* alias = NULL
|
|
*/
|
|
target = spdk_iscsi_tgt_node_construct(-1, req.name, req.alias_name,
|
|
pg_tags,
|
|
ig_tags,
|
|
req.pg_ig_maps.num_maps,
|
|
(const char **)bdev_names,
|
|
lun_ids,
|
|
req.luns.num_luns,
|
|
req.queue_depth,
|
|
req.disable_chap,
|
|
req.require_chap,
|
|
req.mutual_chap,
|
|
req.chap_group,
|
|
req.header_digest,
|
|
req.data_digest);
|
|
|
|
if (target == NULL) {
|
|
goto invalid;
|
|
}
|
|
|
|
free_rpc_target_node(&req);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
|
free_rpc_target_node(&req);
|
|
}
|
|
SPDK_RPC_REGISTER("construct_target_node", spdk_rpc_construct_target_node, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_tgt_node_pg_ig_maps {
|
|
char *name;
|
|
struct rpc_pg_ig_maps pg_ig_maps;
|
|
};
|
|
|
|
static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = {
|
|
{"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string},
|
|
{"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_add_pg_ig_maps(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_tgt_node_pg_ig_maps req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_tgt_node *target;
|
|
int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
|
|
size_t i;
|
|
int rc;
|
|
|
|
if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders,
|
|
SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders),
|
|
&req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
target = spdk_iscsi_find_tgt_node(req.name);
|
|
if (target == NULL) {
|
|
SPDK_ERRLOG("target is not found\n");
|
|
goto invalid;
|
|
}
|
|
|
|
for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
|
|
pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
|
|
ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
|
|
}
|
|
|
|
rc = spdk_iscsi_tgt_node_add_pg_ig_maps(target, pg_tags, ig_tags,
|
|
req.pg_ig_maps.num_maps);
|
|
if (rc < 0) {
|
|
SPDK_ERRLOG("add pg-ig maps failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
free(req.name);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid parameters");
|
|
free(req.name);
|
|
}
|
|
SPDK_RPC_REGISTER("add_pg_ig_maps", spdk_rpc_add_pg_ig_maps, SPDK_RPC_RUNTIME)
|
|
|
|
static void
|
|
spdk_rpc_delete_pg_ig_maps(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_tgt_node_pg_ig_maps req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_tgt_node *target;
|
|
int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
|
|
size_t i;
|
|
int rc;
|
|
|
|
if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders,
|
|
SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders),
|
|
&req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
target = spdk_iscsi_find_tgt_node(req.name);
|
|
if (target == NULL) {
|
|
SPDK_ERRLOG("target is not found\n");
|
|
goto invalid;
|
|
}
|
|
|
|
for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
|
|
pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
|
|
ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
|
|
}
|
|
|
|
rc = spdk_iscsi_tgt_node_delete_pg_ig_maps(target, pg_tags, ig_tags,
|
|
req.pg_ig_maps.num_maps);
|
|
if (rc < 0) {
|
|
SPDK_ERRLOG("remove pg-ig maps failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
free(req.name);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid parameters");
|
|
free(req.name);
|
|
}
|
|
SPDK_RPC_REGISTER("delete_pg_ig_maps", spdk_rpc_delete_pg_ig_maps, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_delete_target_node {
|
|
char *name;
|
|
};
|
|
|
|
static void
|
|
free_rpc_delete_target_node(struct rpc_delete_target_node *r)
|
|
{
|
|
free(r->name);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_delete_target_node_decoders[] = {
|
|
{"name", offsetof(struct rpc_delete_target_node, name), spdk_json_decode_string},
|
|
};
|
|
|
|
struct rpc_delete_target_node_ctx {
|
|
struct rpc_delete_target_node req;
|
|
struct spdk_jsonrpc_request *request;
|
|
};
|
|
|
|
static void
|
|
rpc_delete_target_node_done(void *cb_arg, int rc)
|
|
{
|
|
struct rpc_delete_target_node_ctx *ctx = cb_arg;
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
free_rpc_delete_target_node(&ctx->req);
|
|
|
|
w = spdk_jsonrpc_begin_result(ctx->request);
|
|
if (w == NULL) {
|
|
goto exit;
|
|
}
|
|
|
|
spdk_json_write_bool(w, rc == 0);
|
|
spdk_jsonrpc_end_result(ctx->request, w);
|
|
exit:
|
|
free(ctx);
|
|
}
|
|
|
|
static void
|
|
spdk_rpc_delete_target_node(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_delete_target_node_ctx *ctx;
|
|
|
|
ctx = calloc(1, sizeof(*ctx));
|
|
if (!ctx) {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
|
spdk_strerror(ENOMEM));
|
|
return;
|
|
}
|
|
|
|
if (spdk_json_decode_object(params, rpc_delete_target_node_decoders,
|
|
SPDK_COUNTOF(rpc_delete_target_node_decoders),
|
|
&ctx->req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
if (ctx->req.name == NULL) {
|
|
SPDK_ERRLOG("missing name param\n");
|
|
goto invalid;
|
|
}
|
|
|
|
ctx->request = request;
|
|
|
|
spdk_iscsi_shutdown_tgt_node_by_name(ctx->req.name,
|
|
rpc_delete_target_node_done, ctx);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
|
free_rpc_delete_target_node(&ctx->req);
|
|
free(ctx);
|
|
}
|
|
SPDK_RPC_REGISTER("delete_target_node", spdk_rpc_delete_target_node, SPDK_RPC_RUNTIME)
|
|
|
|
static void
|
|
spdk_rpc_get_portal_groups(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
if (params != NULL) {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"get_portal_groups requires no parameters");
|
|
return;
|
|
}
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_array_begin(w);
|
|
spdk_iscsi_portal_grps_info_json(w);
|
|
spdk_json_write_array_end(w);
|
|
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("get_portal_groups", spdk_rpc_get_portal_groups, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_portal {
|
|
char *host;
|
|
char *port;
|
|
char *cpumask;
|
|
};
|
|
|
|
struct rpc_portal_list {
|
|
size_t num_portals;
|
|
struct rpc_portal portals[MAX_PORTAL];
|
|
};
|
|
|
|
struct rpc_portal_group {
|
|
int32_t tag;
|
|
struct rpc_portal_list portal_list;
|
|
};
|
|
|
|
static void
|
|
free_rpc_portal(struct rpc_portal *portal)
|
|
{
|
|
free(portal->host);
|
|
free(portal->port);
|
|
free(portal->cpumask);
|
|
}
|
|
|
|
static void
|
|
free_rpc_portal_list(struct rpc_portal_list *pl)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < pl->num_portals; i++) {
|
|
free_rpc_portal(&pl->portals[i]);
|
|
}
|
|
pl->num_portals = 0;
|
|
}
|
|
|
|
static void
|
|
free_rpc_portal_group(struct rpc_portal_group *pg)
|
|
{
|
|
free_rpc_portal_list(&pg->portal_list);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_portal_decoders[] = {
|
|
{"host", offsetof(struct rpc_portal, host), spdk_json_decode_string},
|
|
{"port", offsetof(struct rpc_portal, port), spdk_json_decode_string},
|
|
{"cpumask", offsetof(struct rpc_portal, cpumask), spdk_json_decode_string, true},
|
|
};
|
|
|
|
static int
|
|
decode_rpc_portal(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_portal *portal = out;
|
|
|
|
return spdk_json_decode_object(val, rpc_portal_decoders,
|
|
SPDK_COUNTOF(rpc_portal_decoders),
|
|
portal);
|
|
}
|
|
|
|
static int
|
|
decode_rpc_portal_list(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_portal_list *list = out;
|
|
|
|
return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals,
|
|
sizeof(struct rpc_portal));
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = {
|
|
{"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32},
|
|
{"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_add_portal_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_portal_group req = {};
|
|
struct spdk_iscsi_portal_grp *pg = NULL;
|
|
struct spdk_iscsi_portal *portal;
|
|
struct spdk_json_write_ctx *w;
|
|
size_t i = 0;
|
|
int rc = -1;
|
|
|
|
if (spdk_json_decode_object(params, rpc_portal_group_decoders,
|
|
SPDK_COUNTOF(rpc_portal_group_decoders),
|
|
&req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto out;
|
|
}
|
|
|
|
pg = spdk_iscsi_portal_grp_create(req.tag);
|
|
if (pg == NULL) {
|
|
SPDK_ERRLOG("portal_grp_create failed\n");
|
|
goto out;
|
|
}
|
|
for (i = 0; i < req.portal_list.num_portals; i++) {
|
|
if (req.portal_list.portals[i].cpumask) {
|
|
SPDK_WARNLOG("A portal was specified with a CPU mask which is no longer supported.\n");
|
|
SPDK_WARNLOG("Ignoring the cpumask.\n");
|
|
}
|
|
|
|
portal = spdk_iscsi_portal_create(req.portal_list.portals[i].host,
|
|
req.portal_list.portals[i].port);
|
|
if (portal == NULL) {
|
|
SPDK_ERRLOG("portal_create failed\n");
|
|
goto out;
|
|
}
|
|
spdk_iscsi_portal_grp_add_portal(pg, portal);
|
|
}
|
|
|
|
rc = spdk_iscsi_portal_grp_open(pg);
|
|
if (rc != 0) {
|
|
SPDK_ERRLOG("portal_grp_open failed\n");
|
|
goto out;
|
|
}
|
|
|
|
rc = spdk_iscsi_portal_grp_register(pg);
|
|
if (rc != 0) {
|
|
SPDK_ERRLOG("portal_grp_register failed\n");
|
|
}
|
|
|
|
out:
|
|
if (rc == 0) {
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
} else {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
|
|
|
if (pg != NULL) {
|
|
spdk_iscsi_portal_grp_release(pg);
|
|
}
|
|
}
|
|
free_rpc_portal_group(&req);
|
|
}
|
|
SPDK_RPC_REGISTER("add_portal_group", spdk_rpc_add_portal_group, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_delete_portal_group {
|
|
int32_t tag;
|
|
};
|
|
|
|
static const struct spdk_json_object_decoder rpc_delete_portal_group_decoders[] = {
|
|
{"tag", offsetof(struct rpc_delete_portal_group, tag), spdk_json_decode_int32},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_delete_portal_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_delete_portal_group req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_portal_grp *pg;
|
|
|
|
if (spdk_json_decode_object(params, rpc_delete_portal_group_decoders,
|
|
SPDK_COUNTOF(rpc_delete_portal_group_decoders),
|
|
&req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
pg = spdk_iscsi_portal_grp_unregister(req.tag);
|
|
if (!pg) {
|
|
goto invalid;
|
|
}
|
|
|
|
spdk_iscsi_tgt_node_delete_map(pg, NULL);
|
|
spdk_iscsi_portal_grp_release(pg);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
|
}
|
|
SPDK_RPC_REGISTER("delete_portal_group", spdk_rpc_delete_portal_group, SPDK_RPC_RUNTIME)
|
|
|
|
static void
|
|
spdk_rpc_get_iscsi_connections(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_conn *conns = g_conns_array;
|
|
int i;
|
|
uint16_t tsih;
|
|
|
|
if (params != NULL) {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"get_iscsi_connections requires no parameters");
|
|
return;
|
|
}
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_array_begin(w);
|
|
|
|
for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) {
|
|
struct spdk_iscsi_conn *c = &conns[i];
|
|
|
|
if (!c->is_valid) {
|
|
continue;
|
|
}
|
|
|
|
spdk_json_write_object_begin(w);
|
|
|
|
spdk_json_write_named_int32(w, "id", c->id);
|
|
|
|
spdk_json_write_named_int32(w, "cid", c->cid);
|
|
|
|
/*
|
|
* If we try to return data for a connection that has not
|
|
* logged in yet, the session will not be set. So in this
|
|
* case, return -1 for the tsih rather than segfaulting
|
|
* on the null c->sess.
|
|
*/
|
|
if (c->sess == NULL) {
|
|
tsih = -1;
|
|
} else {
|
|
tsih = c->sess->tsih;
|
|
}
|
|
spdk_json_write_named_int32(w, "tsih", tsih);
|
|
|
|
spdk_json_write_named_int32(w, "lcore_id", c->lcore);
|
|
|
|
spdk_json_write_named_string(w, "initiator_addr", c->initiator_addr);
|
|
|
|
spdk_json_write_named_string(w, "target_addr", c->target_addr);
|
|
|
|
spdk_json_write_named_string(w, "target_node_name", c->target_short_name);
|
|
|
|
spdk_json_write_object_end(w);
|
|
}
|
|
spdk_json_write_array_end(w);
|
|
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("get_iscsi_connections", spdk_rpc_get_iscsi_connections, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_target_lun {
|
|
char *name;
|
|
char *bdev_name;
|
|
int32_t lun_id;
|
|
};
|
|
|
|
static void
|
|
free_rpc_target_lun(struct rpc_target_lun *req)
|
|
{
|
|
free(req->name);
|
|
free(req->bdev_name);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = {
|
|
{"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string},
|
|
{"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string},
|
|
{"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_target_node_add_lun(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_target_lun req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_tgt_node *target;
|
|
int rc;
|
|
|
|
req.lun_id = -1;
|
|
|
|
if (spdk_json_decode_object(params, rpc_target_lun_decoders,
|
|
SPDK_COUNTOF(rpc_target_lun_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
target = spdk_iscsi_find_tgt_node(req.name);
|
|
if (target == NULL) {
|
|
SPDK_ERRLOG("target is not found\n");
|
|
goto invalid;
|
|
}
|
|
|
|
rc = spdk_iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id);
|
|
if (rc < 0) {
|
|
SPDK_ERRLOG("add lun failed\n");
|
|
goto invalid;
|
|
}
|
|
|
|
free_rpc_target_lun(&req);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
invalid:
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid parameters");
|
|
free_rpc_target_lun(&req);
|
|
}
|
|
SPDK_RPC_REGISTER("target_node_add_lun", spdk_rpc_target_node_add_lun, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_target_auth {
|
|
char *name;
|
|
bool disable_chap;
|
|
bool require_chap;
|
|
bool mutual_chap;
|
|
int32_t chap_group;
|
|
};
|
|
|
|
static void
|
|
free_rpc_target_auth(struct rpc_target_auth *req)
|
|
{
|
|
free(req->name);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = {
|
|
{"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string},
|
|
{"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true},
|
|
{"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true},
|
|
{"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true},
|
|
{"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_set_iscsi_target_node_auth(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_target_auth req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_tgt_node *target;
|
|
int rc;
|
|
|
|
if (spdk_json_decode_object(params, rpc_target_auth_decoders,
|
|
SPDK_COUNTOF(rpc_target_auth_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid parameters");
|
|
goto exit;
|
|
}
|
|
|
|
target = spdk_iscsi_find_tgt_node(req.name);
|
|
if (target == NULL) {
|
|
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Could not find target %s", req.name);
|
|
goto exit;
|
|
}
|
|
|
|
rc = spdk_iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap,
|
|
req.mutual_chap, req.chap_group);
|
|
if (rc < 0) {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid combination of auth params");
|
|
goto exit;
|
|
}
|
|
|
|
free_rpc_target_auth(&req);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
return;
|
|
|
|
exit:
|
|
free_rpc_target_auth(&req);
|
|
}
|
|
SPDK_RPC_REGISTER("set_iscsi_target_node_auth", spdk_rpc_set_iscsi_target_node_auth,
|
|
SPDK_RPC_RUNTIME)
|
|
|
|
static void
|
|
spdk_rpc_get_iscsi_global_params(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
if (params != NULL) {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"get_iscsi_global_params requires no parameters");
|
|
return;
|
|
}
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_iscsi_opts_info_json(w);
|
|
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("get_iscsi_global_params", spdk_rpc_get_iscsi_global_params, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_discovery_auth {
|
|
bool disable_chap;
|
|
bool require_chap;
|
|
bool mutual_chap;
|
|
int32_t chap_group;
|
|
};
|
|
|
|
static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = {
|
|
{"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true},
|
|
{"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true},
|
|
{"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true},
|
|
{"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_set_iscsi_discovery_auth(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_discovery_auth req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
int rc;
|
|
|
|
if (spdk_json_decode_object(params, rpc_discovery_auth_decoders,
|
|
SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid parameters");
|
|
return;
|
|
}
|
|
|
|
rc = spdk_iscsi_set_discovery_auth(req.disable_chap, req.require_chap,
|
|
req.mutual_chap, req.chap_group);
|
|
if (rc < 0) {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid combination of CHAP params");
|
|
return;
|
|
}
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("set_iscsi_discovery_auth", spdk_rpc_set_iscsi_discovery_auth, SPDK_RPC_RUNTIME)
|
|
|
|
|
|
#define MAX_AUTH_SECRETS 64
|
|
|
|
struct rpc_auth_secret {
|
|
char *user;
|
|
char *secret;
|
|
char *muser;
|
|
char *msecret;
|
|
};
|
|
|
|
static void
|
|
free_rpc_auth_secret(struct rpc_auth_secret *_secret)
|
|
{
|
|
free(_secret->user);
|
|
free(_secret->secret);
|
|
free(_secret->muser);
|
|
free(_secret->msecret);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = {
|
|
{"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string},
|
|
{"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string},
|
|
{"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true},
|
|
{"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true},
|
|
};
|
|
|
|
static int
|
|
decode_rpc_auth_secret(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_auth_secret *_secret = out;
|
|
|
|
return spdk_json_decode_object(val, rpc_auth_secret_decoders,
|
|
SPDK_COUNTOF(rpc_auth_secret_decoders), _secret);
|
|
}
|
|
|
|
struct rpc_auth_secrets {
|
|
size_t num_secret;
|
|
struct rpc_auth_secret secrets[MAX_AUTH_SECRETS];
|
|
};
|
|
|
|
static void
|
|
free_rpc_auth_secrets(struct rpc_auth_secrets *secrets)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < secrets->num_secret; i++) {
|
|
free_rpc_auth_secret(&secrets->secrets[i]);
|
|
}
|
|
}
|
|
|
|
static int
|
|
decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out)
|
|
{
|
|
struct rpc_auth_secrets *secrets = out;
|
|
|
|
return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets,
|
|
MAX_AUTH_SECRETS, &secrets->num_secret,
|
|
sizeof(struct rpc_auth_secret));
|
|
}
|
|
|
|
struct rpc_auth_group {
|
|
int32_t tag;
|
|
struct rpc_auth_secrets secrets;
|
|
};
|
|
|
|
static void
|
|
free_rpc_auth_group(struct rpc_auth_group *group)
|
|
{
|
|
free_rpc_auth_secrets(&group->secrets);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = {
|
|
{"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32},
|
|
{"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_add_iscsi_auth_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_auth_group req = {};
|
|
struct rpc_auth_secret *_secret;
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_auth_group *group = NULL;
|
|
int rc;
|
|
size_t i;
|
|
|
|
if (spdk_json_decode_object(params, rpc_auth_group_decoders,
|
|
SPDK_COUNTOF(rpc_auth_group_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid parameters");
|
|
free_rpc_auth_group(&req);
|
|
return;
|
|
}
|
|
|
|
pthread_mutex_lock(&g_spdk_iscsi.mutex);
|
|
|
|
rc = spdk_iscsi_add_auth_group(req.tag, &group);
|
|
if (rc != 0) {
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Could not add auth group (%d), %s",
|
|
req.tag, spdk_strerror(-rc));
|
|
free_rpc_auth_group(&req);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < req.secrets.num_secret; i++) {
|
|
_secret = &req.secrets.secrets[i];
|
|
rc = spdk_iscsi_auth_group_add_secret(group, _secret->user, _secret->secret,
|
|
_secret->muser, _secret->msecret);
|
|
if (rc != 0) {
|
|
spdk_iscsi_delete_auth_group(group);
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Could not add secret to auth group (%d), %s",
|
|
req.tag, spdk_strerror(-rc));
|
|
free_rpc_auth_group(&req);
|
|
return;
|
|
}
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
free_rpc_auth_group(&req);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("add_iscsi_auth_group", spdk_rpc_add_iscsi_auth_group, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_delete_auth_group {
|
|
int32_t tag;
|
|
};
|
|
|
|
static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = {
|
|
{"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_delete_iscsi_auth_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_delete_auth_group req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_auth_group *group;
|
|
|
|
if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders,
|
|
SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid parameters");
|
|
return;
|
|
}
|
|
|
|
pthread_mutex_lock(&g_spdk_iscsi.mutex);
|
|
|
|
group = spdk_iscsi_find_auth_group_by_tag(req.tag);
|
|
if (group == NULL) {
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Could not find auth group (%d)", req.tag);
|
|
return;
|
|
}
|
|
|
|
spdk_iscsi_delete_auth_group(group);
|
|
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("delete_iscsi_auth_group", spdk_rpc_delete_iscsi_auth_group, SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_add_auth_secret {
|
|
int32_t tag;
|
|
char *user;
|
|
char *secret;
|
|
char *muser;
|
|
char *msecret;
|
|
};
|
|
|
|
static void
|
|
free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret)
|
|
{
|
|
free(_secret->user);
|
|
free(_secret->secret);
|
|
free(_secret->muser);
|
|
free(_secret->msecret);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = {
|
|
{"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32},
|
|
{"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string},
|
|
{"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string},
|
|
{"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true},
|
|
{"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_add_secret_to_iscsi_auth_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_add_auth_secret req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_auth_group *group;
|
|
int rc;
|
|
|
|
if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders,
|
|
SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid parameters");
|
|
free_rpc_add_auth_secret(&req);
|
|
return;
|
|
}
|
|
|
|
pthread_mutex_lock(&g_spdk_iscsi.mutex);
|
|
|
|
group = spdk_iscsi_find_auth_group_by_tag(req.tag);
|
|
if (group == NULL) {
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Could not find auth group (%d)", req.tag);
|
|
free_rpc_add_auth_secret(&req);
|
|
return;
|
|
}
|
|
|
|
rc = spdk_iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret);
|
|
if (rc != 0) {
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Could not add secret to auth group (%d), %s",
|
|
req.tag, spdk_strerror(-rc));
|
|
free_rpc_add_auth_secret(&req);
|
|
return;
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
free_rpc_add_auth_secret(&req);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("add_secret_to_iscsi_auth_group", spdk_rpc_add_secret_to_iscsi_auth_group,
|
|
SPDK_RPC_RUNTIME)
|
|
|
|
struct rpc_delete_auth_secret {
|
|
int32_t tag;
|
|
char *user;
|
|
};
|
|
|
|
static void
|
|
free_rpc_delete_auth_secret(struct rpc_delete_auth_secret *_secret)
|
|
{
|
|
free(_secret->user);
|
|
}
|
|
|
|
static const struct spdk_json_object_decoder rpc_delete_auth_secret_decoders[] = {
|
|
{"tag", offsetof(struct rpc_delete_auth_secret, tag), spdk_json_decode_int32},
|
|
{"user", offsetof(struct rpc_delete_auth_secret, user), spdk_json_decode_string},
|
|
};
|
|
|
|
static void
|
|
spdk_rpc_delete_secret_from_iscsi_auth_group(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct rpc_delete_auth_secret req = {};
|
|
struct spdk_json_write_ctx *w;
|
|
struct spdk_iscsi_auth_group *group;
|
|
int rc;
|
|
|
|
if (spdk_json_decode_object(params, rpc_delete_auth_secret_decoders,
|
|
SPDK_COUNTOF(rpc_delete_auth_secret_decoders), &req)) {
|
|
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Invalid parameters");
|
|
free_rpc_delete_auth_secret(&req);
|
|
return;
|
|
}
|
|
|
|
pthread_mutex_lock(&g_spdk_iscsi.mutex);
|
|
|
|
group = spdk_iscsi_find_auth_group_by_tag(req.tag);
|
|
if (group == NULL) {
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Could not find auth group (%d)", req.tag);
|
|
free_rpc_delete_auth_secret(&req);
|
|
return;
|
|
}
|
|
|
|
rc = spdk_iscsi_auth_group_delete_secret(group, req.user);
|
|
if (rc != 0) {
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"Could not delete secret from CHAP group (%d), %s",
|
|
req.tag, spdk_strerror(-rc));
|
|
free_rpc_delete_auth_secret(&req);
|
|
return;
|
|
}
|
|
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
free_rpc_delete_auth_secret(&req);
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_bool(w, true);
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("delete_secret_from_iscsi_auth_group",
|
|
spdk_rpc_delete_secret_from_iscsi_auth_group, SPDK_RPC_RUNTIME)
|
|
|
|
static void
|
|
spdk_rpc_get_iscsi_auth_groups(struct spdk_jsonrpc_request *request,
|
|
const struct spdk_json_val *params)
|
|
{
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
if (params != NULL) {
|
|
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
|
"get_iscsi_auth_groups requires no parameters");
|
|
return;
|
|
}
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
spdk_json_write_array_begin(w);
|
|
spdk_iscsi_auth_groups_info_json(w);
|
|
spdk_json_write_array_end(w);
|
|
|
|
spdk_jsonrpc_end_result(request, w);
|
|
}
|
|
SPDK_RPC_REGISTER("get_iscsi_auth_groups", spdk_rpc_get_iscsi_auth_groups, SPDK_RPC_RUNTIME)
|