libxcoder 5.7.0
Loading...
Searching...
No Matches
ni_rsrc_namespace.c
Go to the documentation of this file.
1/*******************************************************************************
2 *
3 * Copyright (C) 2022 NETINT Technologies
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 * SOFTWARE.
19 *
20 ******************************************************************************/
21
22/*!*****************************************************************************
23 * \file ni_rsrc_namespace.c
24 *
25 * \brief This utility aims to set the NVMe namespace number for a Quadra NVMe
26 * block device. It can operate on physical devices (PCIe physical
27 * function) or virtual devices (PCIe virtual function). Before setting
28 * namespace number, use SR-IOV to create the PCIe virtual function.
29 * Note that only block device name is accepted for this utility.
30 *
31 * To effect the name space change, reload the NVMe driver:
32 * sudo modprobe -r nvme
33 * sudo modprobe nvme
34 * sudo nvme list #check the result with nvme list
35 ******************************************************************************/
36
37#include "ni_device_api.h"
38#include "ni_nvme.h"
39#include "ni_util.h"
40#ifdef _WIN32
41#include "ni_getopt.h"
42#else
43#include <sys/stat.h>
44#include <unistd.h>
45#include <string.h>
46#include <getopt.h>
47#endif
48
49#define NI_NAMESPACE_SZ 32
50
51typedef struct {
53 float allowance;
55
56static void usage(void)
57{
58 printf("usage: ni_rsrc_namespace [OPTION]\n"
59 "Provides NETINT QUADRA NVMe block device namespace IO operations.\n"
60 " -v show version.\n"
61 " -d the nvme block namespace. Only PF with nsid 1 allowed\n"
62 " -D the nvme block namespace for target over provision setting\n"
63 " -n the nvme block namespace count.\n"
64 " Default: 0\n"
65 " -p overprovision percent. Use exclusive of -n and -s and -q\n"
66 " -q namespace QoS setting. Use exclusive of -n and -s and -p\n"
67 " Default: 0 disabled.\n"
68 " 1 enable qos\n"
69 " 2 enable qos with overprovision\n"
70 " -a <allowance> Set allowance for specific namespace (0.0-100.0) Requires -D <target_ns_device>\n"
71 " -s Index of virtual PCIe functions in SR-IOV tied to the \n"
72 " physical PCIe function. '0' to select physical PCIe \n"
73 " function.\n"
74 " Eg. '1' to select the first virtual SR-IOV device tied \n"
75 " to the physical block device defined by '-d' option.\n"
76 " Default: 0\n"
77 " -c Persist the configuration of the namespace\n"
78 " -h help info.\n");
79}
80
81int send_config_ns_command(char* dev, int ns, int sr)
82{
83 ni_device_handle_t handle = ni_device_open2(dev, NI_DEVICE_READ_WRITE);
84 ni_retcode_t retval;
85 char errmsg[NI_ERRNO_LEN] = {0};
86 if (handle == NI_INVALID_DEVICE_HANDLE)
87 {
89 fprintf(stderr, "ERROR: open %s failure for %s\n", dev,
90 errmsg);
91 exit(-1);
92 } else
93 {
94 printf("Succeed to open block namespace %s\n", dev);
95 }
96
97 retval = ni_device_config_namespace_num(handle, ns, sr);
98 if (retval != NI_RETCODE_SUCCESS)
99 {
101 fprintf(stderr, "ERROR: Config setting failure for %s\n",
102 errmsg);
103 }
104 ni_device_close(handle);
105 return retval;
106}
107
108int send_config_qos_mode(char *dev, int value)
109{
110 ni_device_handle_t handle = ni_device_open2(dev, NI_DEVICE_READ_WRITE);
111 ni_retcode_t retval;
112 char errmsg[NI_ERRNO_LEN] = {0};
113 if (handle == NI_INVALID_DEVICE_HANDLE)
114 {
116 fprintf(stderr, "ERROR: open %s failure for %s\n", dev,
117 errmsg);
118 exit(-1);
119 } else
120 {
121 printf("Succeed to open block namespace %s\n", dev);
122 }
123
124 retval = ni_device_config_qos(handle, value);
125 if (retval != NI_RETCODE_SUCCESS)
126 {
128 fprintf(stderr, "ERROR: Config setting failure for %s\n",
129 errmsg);
130 }
131 ni_device_close(handle);
132 return retval;
133}
134
135int send_config_qos_op(char *dev, char *devt, int op)
136{
137 ni_retcode_t retval;
138 ni_device_handle_t handle = ni_device_open2(dev, NI_DEVICE_READ_WRITE);
139 char errmsg[NI_ERRNO_LEN] = {0};
140 if (handle == NI_INVALID_DEVICE_HANDLE)
141 {
143 fprintf(stderr, "ERROR: open %s failure for %s\n", dev,
144 errmsg);
145 exit(-1);
146 } else
147 {
148 printf("Succeed to open block namespace %s\n", dev);
149 }
150 ni_device_handle_t handle_t = ni_device_open2(devt, NI_DEVICE_READ_WRITE);
151 if (handle_t == NI_INVALID_DEVICE_HANDLE)
152 {
154 fprintf(stderr, "ERROR: open %s failure for %s\n", devt,
155 errmsg);
156 ni_device_close(handle);
157 exit(-1);
158 } else
159 {
160 printf("Succeed to open block namespace %s\n", devt);
161 }
162
163 retval = ni_device_config_qos_op(handle, handle_t, op);
164 if (retval != NI_RETCODE_SUCCESS)
165 {
167 fprintf(stderr, "ERROR: Config setting failure for %s\n",
168 errmsg);
169 }
170 ni_device_close(handle);
171 ni_device_close(handle_t);
172 return retval;
173}
174int send_config_qos_allowance(char *dev, char *devt, int allowance)
175{
176 ni_retcode_t retval;
177 ni_device_handle_t handle = ni_device_open2(dev, NI_DEVICE_READ_WRITE);
178 char errmsg[NI_ERRNO_LEN] = {0};
179 if (handle == NI_INVALID_DEVICE_HANDLE)
180 {
182 fprintf(stderr, "ERROR: open %s failure for %s\n", dev,
183 errmsg);
184 exit(-1);
185 } else
186 {
187 printf("Succeed to open block namespace %s\n", dev);
188 }
189 ni_device_handle_t handle_t = ni_device_open2(devt, NI_DEVICE_READ_WRITE);
190 if (handle_t == NI_INVALID_DEVICE_HANDLE)
191 {
193 fprintf(stderr, "ERROR: open %s failure for %s\n", devt,
194 errmsg);
195 ni_device_close(handle);
196 exit(-1);
197 } else
198 {
199 printf("Succeed to open block namespace %s\n", devt);
200 }
201
202 retval = ni_device_config_qos_allowance(handle, handle_t, allowance);
203 if (retval != NI_RETCODE_SUCCESS)
204 {
206 fprintf(stderr, "ERROR: Config setting failure for %s\n",
207 errmsg);
208 }
209 ni_device_close(handle);
210 ni_device_close(handle_t);
211 return retval;
212}
213
214static int get_ns_id_from_path(const char *path)
215{
216 const char *n_pos = strrchr(path, 'n');
217 if (!n_pos || n_pos[1] == '\0')
218 return -1;
219 int id = atoi(n_pos + 1);
220 return (id >= 1 && id <= NI_NAMESPACE_MAX_NUM) ? id : -1;
221}
222
223int main(int argc, char *argv[])
224{
225 ni_retcode_t retval;
226 int opt;
227 char device_namespace[NI_NAMESPACE_SZ] = {'\0'};
228 char device_namespace_OP[NI_NAMESPACE_SZ] = {'\0'};
229 int namespace_num = 1;
230 float over_provision_percent = -1;
231 int i32_over_provision_percent = 0;
232 int sriov_index = 0;
233 int qos_mode = -1;
234 int persistence = 0;
235#ifdef __linux__
236 struct stat sb;
237#endif
238 namespace_allowance_t allowances = {0};
239 int allowance_count = 0;
240 float pending_allowance = -1.0f;
241 int i32_allowance = 0;
242 float allowance = 0;
243 int ns_id;
244 int current_qos_mode = -1;
245 bool has_zero_allowance = false;
246 float total_all_namespaces = 0.0f;
247 ni_qos_header_info_log_page_t qos_header = {0};
248
249 while ((opt = getopt(argc, argv, "d:D:n:p:q:s:a:chv")) != EOF)
250 {
251 switch (opt)
252 {
253 case 'h':
254 usage();
255 exit(0);
256 case 'v':
257 printf("Release ver: %s\n"
258 "API ver: %s\n"
259 "Date: %s\n"
260 "ID: %s\n",
263 exit(0);
264 case 'd':
265 ni_strcpy(device_namespace, NI_NAMESPACE_SZ, optarg);
266#ifdef __linux__
267 if (lstat(device_namespace, &sb) != 0 ||
268 (sb.st_mode & S_IFMT) != S_IFBLK)
269 {
270 fprintf(stderr, "ERROR: Only block device is supported! "
271 "%s is not block device!\n", device_namespace);
272 exit(-1);
273 }
274#endif
275 break;
276 case 'D':
277 ni_strcpy(device_namespace_OP, NI_NAMESPACE_SZ, optarg);
278 if (pending_allowance >= 0.0f)
279 {
280 ns_id = get_ns_id_from_path(device_namespace_OP);
281 if (ns_id < 1)
282 {
283 fprintf(stderr, "ERROR: Cannot get namespace ID from -D path %s\n", device_namespace_OP);
284 exit(-1);
285 }
286 allowances.namespace_id = ns_id;
287 allowances.allowance = pending_allowance;
288 allowance_count = 1;
289 pending_allowance = -1.0f;
290 }
291 break;
292 case 'n':
293 // A maximum of 64 namespaces are supported for firmware
294 namespace_num = atoi(optarg);
295 if (namespace_num < 0 || namespace_num > NI_NAMESPACE_MAX_NUM)
296 {
297 fprintf(stderr, "ERROR: The number of namespace cannot "
298 "exceed %d\n", NI_NAMESPACE_MAX_NUM);
299 exit(-1);
300 }
301 break;
302 case 'p':
303 // set overprovision %
304 over_provision_percent = (float)atof(optarg);
305 if (over_provision_percent > 100 || over_provision_percent < 0)
306 {
307 fprintf(stderr, "ERROR: Overprovision percent cannot "
308 "exceed 100%% or become negative\n");
309 exit(-1);
310 }
311 break;
312 case 'q':
313 // 0 disabled, 1 enabled - no idle sharing
314 qos_mode = atoi(optarg);
315 if (qos_mode < QOS_MODE_DISABLED ||
316 qos_mode > QOS_MODE_ENABLED_SHARE)
317 {
318 fprintf(stderr,
319 "ERROR: QoS mode %d not supported\n",
320 qos_mode);
321 exit(-1);
322 }
323 break;
324 case 's':
325 sriov_index = atoi(optarg);
326 if (sriov_index < 0)
327 {
328 fprintf(stderr, "ERROR: Invalid SR-IOV device index: %d\n",
329 sriov_index);
330 exit(-1);
331 }
332 break;
333 case 'c':
334 persistence = 1;
335 break;
336 case 'a':
337 allowance = (float)atof(optarg);
338 if (allowance < 0.0f || allowance > 100.0f)
339 {
340 fprintf(stderr, "ERROR: Allowance %.2f out of range [0-100]\n", allowance);
341 exit(-1);
342 }
343 if (device_namespace_OP[0] != '\0')
344 {
345 ns_id = get_ns_id_from_path(device_namespace_OP);
346 if (ns_id < 1)
347 {
348 fprintf(stderr, "ERROR: Cannot get namespace ID from -D path %s\n", device_namespace_OP);
349 exit(-1);
350 }
351 allowances.namespace_id = ns_id;
352 allowances.allowance = allowance;
353 allowance_count = 1;
354 }
355 else
356 pending_allowance = allowance;
357 break;
358 default:
359 fprintf(stderr, "ERROR: Invalid option: %c\n", opt);
360 exit(-1);
361 }
362 }
363
364 if (pending_allowance >= 0.0f)
365 {
366 fprintf(stderr, "ERROR: -a requires -D (e.g. -d /dev/nvme0n1 -a 80 -D /dev/nvme0n2)\n");
367 exit(-1);
368 }
369
370 if (allowance_count > 0)
371 {
372 if (allowances.allowance == 0.0f)
373 has_zero_allowance = true;
374
375 ni_device_handle_t ns_handle = ni_device_open2(device_namespace_OP, NI_DEVICE_READ_ONLY);
376 if (ns_handle == NI_INVALID_DEVICE_HANDLE)
377 {
378 fprintf(stderr, "ERROR: Failed to open device %s\n", device_namespace_OP);
379 return NI_RETCODE_FAILURE;
380 }
381
382 ni_device_capability_t device_capability = {0};
383 if (ni_device_capability_query2(ns_handle, &device_capability, false) != NI_RETCODE_SUCCESS)
384 {
385 ni_device_close(ns_handle);
386 fprintf(stderr, "ERROR: Failed to query device capability for %s\n", device_namespace_OP);
387 return NI_RETCODE_FAILURE;
388 }
389
390 if (ni_query_qos_info(ns_handle, &qos_header, device_capability.fw_rev) != NI_RETCODE_SUCCESS)
391 {
392 ni_device_close(ns_handle);
393 fprintf(stderr, "ERROR: Failed to query QoS info for %s\n", device_namespace_OP);
394 return NI_RETCODE_FAILURE;
395 }
396
397 if (has_zero_allowance)
398 {
399 current_qos_mode = (uint8_t)(qos_header.ui16QosState & 0xFF);
400 if (current_qos_mode != QOS_MODE_ENABLED_SHARE)
401 {
402 ni_device_close(ns_handle);
403 fprintf(stderr, "ERROR: 0%% allowance only allowed with QoS mode 2 (current mode: %d)\n",
404 current_qos_mode);
405 return NI_RETCODE_FAILURE;
406 }
407 }
408
409 total_all_namespaces = qos_header.fTotalAllowance;
410
411 ni_qos_namespace_info_log_page_t qos_ns_info = {0};
412 if (ni_query_qos_namespace_info(ns_handle, &qos_ns_info, device_capability.fw_rev) != NI_RETCODE_SUCCESS)
413 {
414 ni_device_close(ns_handle);
415 fprintf(stderr, "ERROR: Failed to query QoS namespace info for %s\n", device_namespace_OP);
416 return NI_RETCODE_FAILURE;
417 }
418 ni_device_close(ns_handle);
419
420 total_all_namespaces = total_all_namespaces - qos_ns_info.fAllowance + allowances.allowance;
421
422 if (total_all_namespaces > 100.0f)
423 {
424 fprintf(stderr, "ERROR: Total allowance will be %.2f%% (exceeds 100%%)\n", total_all_namespaces);
425 return NI_RETCODE_FAILURE;
426 }
427 if (total_all_namespaces < 100.0f)
428 fprintf(stderr, "INFO: Total allowance will be %.2f%% (under 100%%)\n", total_all_namespaces);
429
430 memcpy(&i32_allowance, &allowances.allowance, sizeof(int32_t));
431 retval = send_config_qos_allowance(device_namespace, device_namespace_OP, i32_allowance);
432 if (retval != NI_RETCODE_SUCCESS)
433 {
434 fprintf(stderr, "ERROR: Failed to set allowance for namespace %d\n", allowances.namespace_id);
435 return NI_RETCODE_FAILURE;
436 }
437 printf("Set namespace %d allowance to %.2f%%\n",
438 allowances.namespace_id, allowances.allowance);
439 printf("Total allowance across all namespaces: %.2f%%\n", total_all_namespaces);
440 return NI_RETCODE_SUCCESS;
441 }
442
443 if (device_namespace[0] == '\0')
444 {
445 fprintf(stderr, "ERROR: missing argument for -d\n");
446 exit(-1);
447 }
448 if (strlen(device_namespace) < 3 ||
449 strcmp(device_namespace + strlen(device_namespace) - 2, "n1") != 0)
450 {
451 fprintf(stderr, "ERROR: Invalid device name %s, need n1, no vf\n", device_namespace);
452 exit(-1);
453 }
454
455 if (qos_mode != -1)
456 {
457 if (namespace_num != 1 || sriov_index || over_provision_percent != -1)
458 {
459 fprintf(stderr,
460 "ERROR: QoS mode -q mutually exclusive of namespace and "
461 "SR-IOV\n");
462 exit(-1);
463 }
464 retval = send_config_qos_mode(device_namespace, qos_mode);
465 if (retval == NI_RETCODE_SUCCESS)
466 {
467 printf("QoS mode setting succeed with number of %d\n", qos_mode);
468 }
469 return retval;
470 }
471
472 if (over_provision_percent != -1)
473 {
474 if (device_namespace_OP[0] == '\0')
475 {
476 fprintf(stderr, "ERROR: missing argument for -D\n");
477 exit(-1);
478 }
479 if (namespace_num != 1 || sriov_index || qos_mode != -1)
480 {
481 fprintf(stderr,
482 "ERROR: Overprovision percent -p mutually exclusive of "
483 "namespace and SR-IOV and QOS mode\n");
484 exit(-1);
485 }
486 memcpy(&i32_over_provision_percent, &over_provision_percent, sizeof(int32_t));
487 retval = send_config_qos_op(device_namespace, device_namespace_OP,
488 i32_over_provision_percent);
489 if (retval == NI_RETCODE_SUCCESS)
490 {
491 printf("Overprovision percent setting succeed with number of %f\n",
492 over_provision_percent);
493 }
494 return retval;
495 }
496
497 if (persistence) namespace_num += 256;
498 retval = send_config_ns_command(device_namespace, namespace_num, sriov_index);
499 if (retval == NI_RETCODE_SUCCESS)
500 {
501 printf("Namespace setting succeed with number of %d and SR-IOV "
502 "index %d\n",
503 namespace_num, sriov_index);
504 }
505 return retval;
506}
int main()
Definition client.cpp:51
#define NI_XCODER_REVISION
Definition ni_defs.h:98
#define LIBXCODER_API_VERSION
Definition ni_defs.h:115
#define NI_ERRNO
Definition ni_defs.h:229
ni_retcode_t
Definition ni_defs.h:445
@ NI_RETCODE_FAILURE
Definition ni_defs.h:447
@ NI_RETCODE_SUCCESS
Definition ni_defs.h:446
#define atof(p_str)
ni_retcode_t ni_device_config_qos_op(ni_device_handle_t device_handle, ni_device_handle_t device_handle_t, uint32_t over_provision)
Send qos over provisioning mode to target namespace with specified logic block address.
ni_retcode_t ni_device_config_qos_allowance(ni_device_handle_t device_handle, ni_device_handle_t device_handle_t, uint32_t allowance)
Set QoS allowance for a specific namespace.
ni_retcode_t ni_device_capability_query2(ni_device_handle_t device_handle, ni_device_capability_t *p_cap, bool device_in_ctxt)
Query device and return device capability structure This function had replaced ni_device_capability_q...
#define atoi(p_str)
void ni_device_close(ni_device_handle_t device_handle)
Close device and release resources.
ni_retcode_t ni_query_qos_info(ni_device_handle_t device_handle, ni_qos_header_info_log_page_t *p_dev_qos_header, uint8_t fw_rev[])
Query QoS information for the device.
ni_retcode_t ni_device_config_namespace_num(ni_device_handle_t device_handle, uint32_t namespace_num, uint32_t sriov_index)
Send namespace num and SRIOv index to the device with specified logic block address.
ni_device_handle_t ni_device_open2(const char *p_dev, ni_device_mode_t mode)
Open device and return device device_handle if successful.
ni_retcode_t ni_query_qos_namespace_info(ni_device_handle_t device_handle, ni_qos_namespace_info_log_page_t *p_dev_qos_ns, uint8_t fw_rev[])
Query QoS information for a specific namespace.
ni_retcode_t ni_device_config_qos(ni_device_handle_t device_handle, uint32_t mode)
Send qos mode to the device with specified logic block address.
Public definitions for operating NETINT video processing devices for video processing.
@ QOS_MODE_DISABLED
@ QOS_MODE_ENABLED_SHARE
@ NI_DEVICE_READ_ONLY
@ NI_DEVICE_READ_WRITE
#define NI_NAMESPACE_MAX_NUM
int getopt(int argc, char *argv[], const char *optstring)
Definition ni_getopt.c:38
char * optarg
Definition ni_getopt.c:33
Implementation of getopt() and getopt_long() for Windows environment.
#define NI_ERRNO_LEN
Definition ni_log.h:51
Private definitions for interfacing with NETINT video processing devices over NVMe.
#define NI_SW_RELEASE_ID
#define NI_SW_RELEASE_TIME
#define NI_NAMESPACE_SZ
int send_config_qos_allowance(char *dev, char *devt, int allowance)
int send_config_qos_op(char *dev, char *devt, int op)
int send_config_qos_mode(char *dev, int value)
int send_config_ns_command(char *dev, int ns, int sr)
ni_retcode_t ni_strerror(char *dest, size_t dmax, int errnum)
Definition ni_util.c:656
ni_retcode_t ni_strcpy(char *dest, size_t dmax, const char *src)
Definition ni_util.c:453
Utility definitions.
device capability type