NVMf RPC接口文件 nvmf_rpc.c
迪丽瓦拉
2024-06-03 23:45:23
0

NVMf RPC接口文件 nvmf_rpc.c

  • 在spdk的lib/nvmf/下的NVMf RPC接口文件nvmf_rpc.c是干啥的?有什么用发挥了什么功能
      • 3. spdk_nvmf_tgt_listen
  • 在spdk里面的nvmf_rpc.c文件中创建RDMA Port 的意义与流程

在spdk的lib/nvmf/下的NVMf RPC接口文件nvmf_rpc.c是干啥的?有什么用发挥了什么功能

nvmf_rpc.c是SPDK的NVMf(NVMe over Fabrics)远程过程调用(RPC)接口文件,它定义了NVMf管理器(NVMf Target)的RPC接口。

NVMf管理器是一种软件实体,它在NVMe存储设备和网络之间提供桥梁,使得通过网络访问NVMe存储设备成为可能。NVMf管理器实现了NVMf协议和NVMe协议之间的转换,并提供了一些管理和控制接口,以便远程主机能够使用NVMe协议访问远程存储设备。

nvmf_rpc.c中的函数实现了管理和控制NVMf管理器的RPC接口,包括创建和删除NVMf命名空间(Namespace)、注册和注销NVMf传输连接(Transport Connection)等。这些RPC接口可以通过RPC机制被远程主机调用,从而实现对NVMf管理器的管理和控制。

总之,nvmf_rpc.c文件实现了NVMf管理器的RPC接口,提供了一种方便的远程管理和控制NVMf管理器的方式。

在SPDK(Storage Performance Development Kit)中,nvmf_rpc.c文件包含了许多用于管理NVMe over Fabrics(NVMf)子系统的RPC命令,包括创建RDMA Port监听的函数。下面是一些相关函数的代码片段和详细讲解:

  1. rpc_nvmf_subsystem_add_listener

rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request,const struct spdk_json_val *params)
{struct rpc_listen_ctx ctx = {};struct spdk_json_write_ctx *w;struct spdk_nvme_transport_id trid = {};struct spdk_nvmf_subsystem *subsystem;const char *name;uint16_t port;int rc;if (g_nvmf_tgt.pause) {ctx.request = request;ctx.params = params;TAILQ_INSERT_TAIL(&g_nvmf_tgt.listen_queue, &ctx, link);return;}/* ... 解析参数 ... */rc = spdk_nvmf_subsystem_add_listener(subsystem, &trid, nvmf_rpc_listen_done, request);if (rc) {SPDK_DEBUGLOG(SPDK_LOG_NVMF_RPC, "Failed to add listener. rc:%d\n", rc);goto invalid;}w = spdk_jsonrpc_begin_result(request);spdk_json_write_object_begin(w);spdk_json_write_named_string(w, "subsystem", name);spdk_json_write_named_string(w, "transport", trid.trstring);spdk_json_write_named_string(w, "traddr", trid.traddr);spdk_json_write_named_uint32(w, "trsvcid", trid.trsvcid);spdk_json_write_object_end(w);spdk_jsonrpc_end_result(request, w);return;invalid:spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Failed to add listener.");
}

函数rpc_nvmf_subsystem_add_listener用于在指定的NVMf子系统中添加一个新的RDMA端口监听。函数首先解析输入参数,然后调用SPDK库中的spdk_nvmf_subsystem_add_listener函数来实现添加监听的功能。如果添加成功,函数将返回一个JSON RPC响应,其中包含新添加监听的信息。如果添加失败,函数将返回一个错误响应。

  1. nvmf_rpc_listen_paused
nvmf_rpc_listen_paused(void *arg1, void *arg2)
{struct rpc_listen_ctx *ctx = arg1;struct spdk_json_write_ctx *w;struct spdk_nvme_transport_id trid = {};struct spdk_nvmf_subsystem *subsystem;const char *name;uint16_t port;int rc;/* ... 解析参数 ... */rc = spdk_nvmf_subsystem_add_listener(subsystem, &trid, nvmf_rpc_listen_done, ctx->request);if (rc) {SPDK_DEBUGLOG(SPDK_LOG_NVMF_RPC, "Failed to add listener. rc:%d\n", rc);spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,"Failed to add listener.");} else {w = spdk_jsonrpc_begin_result(ctx->request);spdk_json_write_object_begin(w);spdk_json_write_named_string(w, "subsystem", name);spdk_json_write_named_string(w, "transport",trid.trstring);
spdk_json_write_named_string(w, "traddr", trid.traddr);
spdk_json_write_named_uint32(w, "trsvcid", trid.trsvcid);
spdk_json_write_object_end(w);
spdk_jsonrpc_end_result(ctx->request, w);
}

函数nvmf_rpc_listen_paused是一个回调函数,当NVMf目标暂停时被调用。它接收之前暂停时排队的监听请求上下文ctx,并根据该请求的参数来添加新的RDMA端口监听。如果添加成功,它将发送JSON RPC响应。否则,它将发送一个错误响应。

3. spdk_nvmf_tgt_listen


int
spdk_nvmf_tgt_listen(struct spdk_nvmf_listen_opts *opts)
{/* ... 检查opts参数 ... */return spdk_nvmf_transport_listen(opts);
}

函数spdk_nvmf_tgt_listen用于为SPDK NVMf目标创建一个新的监听器。它接收一个spdk_nvmf_listen_opts类型的结构体指针作为参数,该结构体包含了创建监听器所需的所有信息。函数首先检查传入的参数,然后调用SPDK库中的spdk_nvmf_transport_listen函数来实现创建监听器的功能。

  1. spdk_nvmf_transport_listen
int
spdk_nvmf_transport_listen(struct spdk_nvmf_listen_opts *opts)
{/* ... 检查opts参数 ... */return g_nvmf_transports[opts->transport->ops->type]->listen(opts);
}

函数spdk_nvmf_transport_listen是一个SPDK NVMf传输层的通用函数,用于为指定的传输类型创建一个新的监听器。它接收一个spdk_nvmf_listen_opts类型的结构体指针作为参数,该结构体包含了创建监听器所需的所有信息。函数首先检查传入的参数,然后调用相应的传输层函数来实现创建监听器的功能。

  1. nvmf_rdma_listen
static int
nvmf_rdma_listen(struct spdk_nvmf_transport *transport,const struct spdk_nvme_transport_id *trid,struct spdk_nvmf_listen_opts *opts)
{struct spdk_nvmf_rdma_transport *rtransport;struct spdk_nvmf_rdma_device *device;struct spdk_nvmf_rdma_listen_addr *addr;struct spdk_nvmf_rdma_qpair *qpair;struct sockaddr_storage listen_addr;socklen_t addr_size;char addr_buf[SPDK_NVMF_TRADDR_MAX_LEN + 1];int rc;rtransport = SPDK_CONTAINEROF(transport, struct spdk_nvmf_rdma_transport, transport);device = nvmf_rdma_find_device(trid, rtransport);if (!device) {SPDK_ERRLOG("Unable to find device with guid: %s\n", trid->traddr);return -EINVAL;}/* ... 创建sockaddr_storage结构体 ... */addr_size = rdma_sockaddr_size((struct sockaddr *)&listen_addr);memcpy(&opts->listen_id, trid, sizeof(opts->listen_id));
opts->listen_fd = rdma_create_ep(rtransport->cm_channel, (struct sockaddr *)&listen_addr,
NULL, rtransport->cm_event_channel);
if (opts->listen_fd < 0) {
SPDK_ERRLOG("rdma_create_ep() failed, errno %d: %s\n", errno, spdk_strerror(errno));
return -errno;
}rc = rdma_listen(opts->listen_fd, 128); /* 128 is the maximum backlog for listen() */
if (rc < 0) {SPDK_ERRLOG("rdma_listen() failed, errno %d: %s\n", errno, spdk_strerror(errno));close(opts->listen_fd);return -errno;
}SPDK_DEBUGLOG(SPDK_LOG_NVMF_RDMA, "Added RDMA listen address %s port %u\n",spdk_nvmf_trtype_str(opts->listen_id.trtype), opts->listen_id.trsvcid);/* Add the new listen address */
addr = calloc(1, sizeof(*addr));
if (!addr) {SPDK_ERRLOG("Unable to allocate memory for listen address\n");close(opts->listen_fd);return -ENOMEM;
}SPDK_DEBUGLOG(SPDK_LOG_NVMF_RDMA, "Adding listen addr %p\n", addr);
addr->id = opts->listen_id;
addr->device = device;
addr->listen_fd = opts->listen_fd;
TAILQ_INSERT_TAIL(&rtransport->listen_addrs, addr, link);/* Queue up an accept event for the listen socket */
qpair = spdk_nvmf_rdma_qpair_create(device, rtransport, addr, 0);
if (!qpair) {SPDK_ERRLOG("Unable to allocate qpair for listening on %s:%u\n",trid->traddr, trid->trsvcid);close(opts->listen_fd);return -ENOMEM;
}return 0;
}

函数nvmf_rdma_listen用于为RDMA传输类型创建一个新的监听器。它接收一个spdk_nvmf_transport类型的结构体指针、一个spdk_nvme_transport_id类型的结构体指针和一个spdk_nvmf_listen_opts类型的结构体指针作为参数。函数首先在指定的传输类型中查找与给定设备ID匹配的设备。如果找到了匹配的设备,则创建一个新的RDMA监听器。函数在创建监听器时,需要先构造一个sockaddr_storage类型的地址结构体,然后使用rdma_create_ep函数创建一个RDMA端点。接下来,函数使用rdma_listen函数将监听器绑定到指定的端口上。如果创建监听器成功,则函数将创建一个新的RDMA QPair对象,并将其添加到指定设备的QPairs列表中。如果失败,则函数将发送一个错误响应。最后,函数返回0表示成功,返回其他值表示失败。

总之,这些函数都是用于在SPDK的nvmf_rpc.c文件中创建RDMA Port监听的函数。它们通过调用SPDK库中的不同函数来实现监听器的创建和管理。这些函数的详细代码和实现原理可以帮助开发人员更好地理解SPDK NVMf目标的实现细节。

函数spdk_nvmf_tgt_listen用于启动SPDK NVMf目标的监听器。它接受一个spdk_nvmf_listen_opts类型的结构体指针作为参数,该结构体包含了所需的监听器选项。函数首先使用指定的传输类型初始化全局变量g_nvmf_tgt.max_queue_depth和g_nvmf_tgt.max_qpairs_per_ctrlr,这两个变量分别代表每个队列的最大深度和每个控制器的最大QP数。接下来,函数通过调用指定传输类型的transport->listen函数来创建一个新的监听器,并将其添加到全局变量g_nvmf_tgt.subsystems中。如果创建监听器成功,则函数返回0。否则,它将释放监听器所需的资源,并返回错误代码。

总之,这些函数的作用是创建和管理SPDK NVMf目标的RDMA监听器。它们通过调用SPDK库中的不同函数来实现监听器的创建和管理。了解这些函数的实现细节可以帮助开发人员更好地理解SPDK NVMf目标的工作原理,并在需要时进行调试和优化。

函数nvmf_rpc_listen_paused用于在RPC事件中处理新的RDMA监听器请求。它接受一个spdk_jsonrpc_request类型的结构体指针、一个spdk_json_val类型的结构体指针和一个spdk_json_write_ctx类型的结构体指针作为参数。函数首先解析JSON参数对象,并使用SPDK库中的spdk_nvmf_transport_name_to_opts函数从参数中提取传输类型和选项。接下来,函数调用SPDK库中的spdk_nvmf_tgt_find_subsystem函数查找与指定名称匹配的子系统,并将其返回到全局变量g_nvmf_tgt.subsystems中。如果找不到子系统,则函数将发送一个错误响应。如果找到子系统,则函数使用spdk_nvmf_transport_create函数创建一个新的传输类型,并使用spdk_nvmf_transport_add_listener函数将其添加到子系统的监听器列表中。如果创建监听器成功,则函数将发送一个成功响应。否则,它将发送一个错误响应。

函数rpc_nvmf_subsystem_add_listener用于在RPC事件中处理新的RDMA监听器请求。它接受一个spdk_jsonrpc_request类型的结构体指针、一个spdk_json_val类型的结构体指针和一个spdk_json_write_ctx类型的结构体指针作为参数。函数首先解析JSON参数对象,并使用SPDK库中的spdk_nvmf_transport_name_to_opts函数从参数中提取传输类型和选项。接下来,函数调用SPDK库中的spdk_nvmf_tgt_find_subsystem函数查找与指定名称匹配的子系统,并将其返回到全局变量g_nvmf_tgt.subsystems中。如果找不到子系统,则函数将发送一个错误响应。如果找到子系统,则函数使用spdk_nvmf_transport_create函数创建一个新的传输类型,并使用spdk_nvmf_transport_add_listener函数将其添加到子系统的监听器列表中。如果创建监听器成功,则函数将发送一个成功响应。否则,它将发送一个错误响应。

总之,这些函数是用于在SPDK的nvmf_rpc.c文件中处理新的RDMA监听器请求的函数。它们通过调用SPDK库中的不同函数来实现监听器的创建和管理,并使用JSON-RPC协议与客户端进行通信。这些函数的详细代码和实现原理可以帮助开发人员更好地理解SPDK NVMf目标的实现细节,并在需要时进行调试和优化。

函数nvmf_rdma_listen用于创建和启动RDMA监听器。它接受一个nvmf_rdma_device结构体指针、一个nvmf_rdma_listen_opts结构体指针、一个spdk_nvmf_listen_opts结构体指针和一个nvmf_rdma_listen_cb回调函数作为参数。函数首先使用指定的RDMA设备和选项初始化RDMA监听器的相关参数,包括端口号、队列深度、接收队列大小、传输类型等等。接下来,函数使用SPDK库中的ibv_query_device函数查询RDMA设备的属性,并使用ibv_create_comp_channel和ibv_create_cq函数创建RDMA设备的完成通道和完成队列。然后,函数使用ibv_alloc_pd和ibv_reg_mr函数分配和注册内存区域,用于接收和发送RDMA数据。接着,函数使用ibv_create_srq函数创建共享接收队列,并使用ibv_post_srq_recv函数将初始接收请求添加到队列中。最后,函数使用ibv_listen函数创建RDMA监听器,并启动接收请求循环以接收新的连接请求。如果创建监听器成功,则函数调用指定的回调函数,并返回RDMA监听器的句柄。否则,它将释放所有已分配的资源,并返回NULL。

总之,函数nvmf_rdma_listen是用于创建和启动RDMA监听器的函数。它使用了RDMA库中的不同函数来实现RDMA设备的初始化、内存的分配和注册、共享接收队列的创建、RDMA监听器的创建和启动等功能。了解这个函数的实现细节可以帮助开发人员更好地理解RDMA技术的原理和实现,以及在需要时进行调试和优化。

在spdk里面的nvmf_rpc.c文件中创建RDMA Port 的意义与流程

在SPDK中,nvmf_rpc.c文件主要实现了与NVMf子系统的交互。其中,创建RDMA Port的过程是在RPC层完成的,目的是为了在用户调用SPDK库时,自动创建RDMA端口并监听连接请求,从而简化用户代码的编写。下面我们来详细说说在spdk里面的nvmf_rpc.c文件中创建RDMA Port的意义与流程。

在SPDK中,RDMA技术用于实现NVMf(Non-Volatile Memory express over Fabrics)协议的远程访问。NVMf是一种基于NVMe协议的远程存储访问协议,允许使用RDMA技术在远程计算机上访问本地存储设备。因此,在SPDK中实现NVMf协议需要创建RDMA端口,接收来自远程计算机的连接请求,并将这些请求映射到本地的NVMe设备。

nvmf_rpc.c文件中的创建RDMA Port的过程分为三个阶段:初始化RDMA设备、创建RDMA监听器和启动监听循环。下面我们分别介绍这三个阶段的具体流程:

初始化RDMA设备:在这个阶段,nvmf_rpc_subsystem_add_listener函数会调用spdk_nvmf_transport_create函数创建NVMf传输层实例,并将其与指定的RDMA设备进行关联。这个函数会调用nvmf_rdma_create函数创建一个RDMA传输层实例,并使用指定的RDMA设备初始化RDMA传输层实例的相关参数,包括端口号、队列深度、接收队列大小、传输类型等等。这个函数还会使用ibv_query_device函数查询RDMA设备的属性,并使用ibv_create_comp_channel和ibv_create_cq函数创建RDMA设备的完成通道和完成队列。

创建RDMA监听器:在这个阶段,nvmf_rpc_subsystem_add_listener函数会调用nvmf_rpc_listen_paused函数创建RDMA监听器,并将其与指定的NVMf传输层实例进行关联。这个函数会调用spdk_nvmf_tgt_listen函数创建一个RDMA监听器,并使用指定的选项初始化RDMA监听器的相关参数,包括NVMe控制器、队列深度、接收队列大小、传输类型等等。这个函数还会使用nvmf_rdma_listen函数创建和启动RDMA监听器,以接收来自远程计算机的连接请求。

启动监听循环:在这个阶段,nvmf_rpc_subsystem_add_listener函数会调用spdk_nvmf_transport_accept函数启动监听循环,用于接收来自远程计算机的连接请求。这个函数会使用RDMA监听器的句柄和相关参数创建一个监听循环,并使用ibv_get_cq_event函数等待新的连接请求。如果有新的连接请求到达,则会调用spdk_nvmf_tgt_accept函数处理这个连接请求,将其映射到本地的NVMe设备,并向远程计算机发送连接响应。如果没有新的连接请求,则会继续等待下一个连接请求。

总的来说,创建RDMA Port的过程可以简化用户代码的编写,使用户可以更方便地使用SPDK库来实现NVMf协议的远程存储访问。这个过程主要涉及到RDMA设备的初始化、RDMA监听器的创建和启动监听循环三个阶段,每个阶段都涉及到不同的函数调用和参数设置,需要仔细理解和配置。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...