iscsi/rpc: Set processor affinity of connection through JSON-RPC

Currently setting cpumask to portal is possible only through
iSCSI.conf. This patch makes possible for any user to set cpumask
through JSON-RPC too.

The following are done in this patch:
- To keep compatibility, cpumask parameter handled as optional.
- Python test code is added.
- Current python script for JSON-RPC does not work correctly for
  IPv6 and the issue is fixed.

Change-Id: I42ef397ce95040a36db4430417a35e9e97527477
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/391728
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Shuhei Matsumoto 2018-01-22 08:04:19 +09:00 committed by Jim Harris
parent 7bae25dfcd
commit 632f0ced75
3 changed files with 26 additions and 9 deletions

View File

@ -732,6 +732,8 @@ spdk_rpc_get_portal_groups(struct spdk_jsonrpc_request *request,
spdk_json_write_string(w, portal->host); spdk_json_write_string(w, portal->host);
spdk_json_write_name(w, "port"); spdk_json_write_name(w, "port");
spdk_json_write_string(w, portal->port); spdk_json_write_string(w, portal->port);
spdk_json_write_name(w, "cpumask");
spdk_json_write_string_fmt(w, "%#" PRIx64, portal->cpumask);
spdk_json_write_object_end(w); spdk_json_write_object_end(w);
} }
spdk_json_write_array_end(w); spdk_json_write_array_end(w);
@ -751,6 +753,7 @@ SPDK_RPC_REGISTER("get_portal_groups", spdk_rpc_get_portal_groups)
struct rpc_portal { struct rpc_portal {
char *host; char *host;
char *port; char *port;
char *cpumask;
}; };
struct rpc_portal_list { struct rpc_portal_list {
@ -767,9 +770,8 @@ static void
free_rpc_portal(struct rpc_portal *portal) free_rpc_portal(struct rpc_portal *portal)
{ {
free(portal->host); free(portal->host);
portal->host = NULL;
free(portal->port); free(portal->port);
portal->port = NULL; free(portal->cpumask);
} }
static void static void
@ -792,6 +794,7 @@ free_rpc_portal_group(struct rpc_portal_group *pg)
static const struct spdk_json_object_decoder rpc_portal_decoders[] = { static const struct spdk_json_object_decoder rpc_portal_decoders[] = {
{"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string},
{"port", offsetof(struct rpc_portal, port), 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 static int
@ -838,7 +841,8 @@ spdk_rpc_add_portal_group(struct spdk_jsonrpc_request *request,
for (i = 0; i < req.portal_list.num_portals; i++) { for (i = 0; i < req.portal_list.num_portals; i++) {
portal_list[i] = spdk_iscsi_portal_create(req.portal_list.portals[i].host, portal_list[i] = spdk_iscsi_portal_create(req.portal_list.portals[i].host,
req.portal_list.portals[i].port, NULL); req.portal_list.portals[i].port,
req.portal_list.portals[i].cpumask);
if (portal_list[i] == NULL) { if (portal_list[i] == NULL) {
SPDK_ERRLOG("portal_list allocation failed\n"); SPDK_ERRLOG("portal_list allocation failed\n");
goto out; goto out;

View File

@ -488,16 +488,24 @@ def add_portal_group(args):
# parse out portal list host1:port1 host2:port2 # parse out portal list host1:port1 host2:port2
portals = [] portals = []
for p in args.portal_list: for p in args.portal_list:
host_port = p.split(':') ip, separator, port_cpumask = p.rpartition(':')
portals.append({'host': host_port[0], 'port': host_port[1]}) split_port_cpumask = port_cpumask.split('@')
if len(split_port_cpumask) == 1:
port = port_cpumask
portals.append({'host': ip, 'port': port})
else:
port = split_port_cpumask[0]
cpumask = split_port_cpumask[1]
portals.append({'host': ip, 'port': port, 'cpumask': cpumask})
params = {'tag': args.tag, 'portals': portals} params = {'tag': args.tag, 'portals': portals}
jsonrpc_call('add_portal_group', params) jsonrpc_call('add_portal_group', params)
p = subparsers.add_parser('add_portal_group', help='Add a portal group') p = subparsers.add_parser('add_portal_group', help='Add a portal group')
p.add_argument('tag', help='Portal group tag (unique, integer > 0)', type=int) p.add_argument('tag', help='Portal group tag (unique, integer > 0)', type=int)
p.add_argument('portal_list', nargs=argparse.REMAINDER, help="""List of portals in 'host:port' format, separated by whitespace p.add_argument('portal_list', nargs=argparse.REMAINDER, help="""List of portals in 'host:port@cpumask' format, separated by whitespace
Example: '192.168.100.100:3260' '192.168.100.100:3261'""") (cpumask is optional and can be skipped)
Example: '192.168.100.100:3260' '192.168.100.100:3261' '192.168.100.100:3262@0x1""")
p.set_defaults(func=add_portal_group) p.set_defaults(func=add_portal_group)

View File

@ -28,7 +28,8 @@ rpc_param = {
'chap_auth_group': 0, 'chap_auth_group': 0,
'header_digest': 0, 'header_digest': 0,
'data_digest': 0, 'data_digest': 0,
'trace_flag': 'rpc' 'trace_flag': 'rpc',
'cpumask': 0x1
} }
@ -187,7 +188,7 @@ def verify_portal_groups_rpc_methods(rpc_py, rpc_param):
for idx, value in enumerate(lo_ip): for idx, value in enumerate(lo_ip):
# The portal group tag must start at 1 # The portal group tag must start at 1
tag = idx + 1 tag = idx + 1
rpc.add_portal_group(tag, "{}:{}".format(value, rpc_param['port'])) rpc.add_portal_group(tag, "{}:{}@{}".format(value, rpc_param['port'], rpc_param['cpumask']))
output = rpc.get_portal_groups() output = rpc.get_portal_groups()
jsonvalues = json.loads(output) jsonvalues = json.loads(output)
verify(len(jsonvalues) == tag, 1, verify(len(jsonvalues) == tag, 1,
@ -199,6 +200,8 @@ def verify_portal_groups_rpc_methods(rpc_py, rpc_param):
"host value is {}, expected {}".format(value['portals'][0]['host'], rpc_param['target_ip'])) "host value is {}, expected {}".format(value['portals'][0]['host'], rpc_param['target_ip']))
verify(value['portals'][0]['port'] == str(rpc_param['port']), 1, verify(value['portals'][0]['port'] == str(rpc_param['port']), 1,
"port value is {}, expected {}".format(value['portals'][0]['port'], str(rpc_param['port']))) "port value is {}, expected {}".format(value['portals'][0]['port'], str(rpc_param['port'])))
verify(value['portals'][0]['cpumask'] == format(rpc_param['cpumask'], '#x'), 1,
"cpumask value is {}, expected {}".format(value['portals'][0]['cpumask'], format(rpc_param['cpumask'], '#x')))
tag_list.append(value['tag']) tag_list.append(value['tag'])
verify(value['tag'] == idx + 1, 1, verify(value['tag'] == idx + 1, 1,
"tag value is {}, expected {}".format(value['tag'], idx + 1)) "tag value is {}, expected {}".format(value['tag'], idx + 1))
@ -217,6 +220,8 @@ def verify_portal_groups_rpc_methods(rpc_py, rpc_param):
"host value is {}, expected {}".format(jvalue['portals'][0]['host'], lo_ip[idx + jidx + 1])) "host value is {}, expected {}".format(jvalue['portals'][0]['host'], lo_ip[idx + jidx + 1]))
verify(jvalue['portals'][0]['port'] == str(rpc_param['port']), 1, verify(jvalue['portals'][0]['port'] == str(rpc_param['port']), 1,
"port value is {}, expected {}".format(jvalue['portals'][0]['port'], str(rpc_param['port']))) "port value is {}, expected {}".format(jvalue['portals'][0]['port'], str(rpc_param['port'])))
verify(jvalue['portals'][0]['cpumask'] == format(rpc_param['cpumask'], '#x'), 1,
"cpumask value is {}, expected {}".format(jvalue['portals'][0]['cpumask'], format(rpc_param['cpumask'], '#x')))
verify(jvalue['tag'] != value or jvalue['tag'] == tag_list[idx + jidx + 1], 1, verify(jvalue['tag'] != value or jvalue['tag'] == tag_list[idx + jidx + 1], 1,
"tag value is {}, expected {} and not {}".format(jvalue['tag'], tag_list[idx + jidx + 1], value)) "tag value is {}, expected {} and not {}".format(jvalue['tag'], tag_list[idx + jidx + 1], value))