From patchwork Tue Jan 29 19:11:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Wise X-Patchwork-Id: 10787087 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7668513BF for ; Tue, 29 Jan 2019 19:14:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 637552C96D for ; Tue, 29 Jan 2019 19:14:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 54EED2C978; Tue, 29 Jan 2019 19:14:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,UPPERCASE_50_75 autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D11FB2C96D for ; Tue, 29 Jan 2019 19:14:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729407AbfA2TOA (ORCPT ); Tue, 29 Jan 2019 14:14:00 -0500 Received: from opengridcomputing.com ([72.48.214.68]:37904 "EHLO smtp.opengridcomputing.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726852AbfA2TOA (ORCPT ); Tue, 29 Jan 2019 14:14:00 -0500 Received: by smtp.opengridcomputing.com (Postfix, from userid 503) id 00C3422792; Tue, 29 Jan 2019 13:13:59 -0600 (CST) Message-Id: In-Reply-To: References: From: Steve Wise Date: Tue, 29 Jan 2019 11:11:00 -0800 Subject: [PATCH rdma-core 1/2] Refresh rdma_netlink.h To: dledford@redhat.com, jgg@mellanox.com Cc: linux-rdma@vger.kernel.org, BMT@zurich.ibm.com, shiraz.saleem@intel.com Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Steve Wise --- kernel-headers/rdma/rdma_netlink.h | 45 +++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/kernel-headers/rdma/rdma_netlink.h b/kernel-headers/rdma/rdma_netlink.h index 2e18b77a817f..0f5263767fb4 100644 --- a/kernel-headers/rdma/rdma_netlink.h +++ b/kernel-headers/rdma/rdma_netlink.h @@ -35,6 +35,19 @@ enum { RDMA_NL_RDMA_CM_NUM_ATTR, }; +/* The minimum version that the iwpm kernel supports */ +#define IWPM_UABI_VERSION_MIN 3 + +/* The latest version that the iwpm kernel supports */ +#define IWPM_UABI_VERSION 4 + +/* iwarp port mapper message flags */ +enum { + + /* Do not map the port for this IWPM request */ + IWPM_FLAGS_NO_PORT_MAP = (1 << 0), +}; + /* iwarp port mapper op-codes */ enum { RDMA_NL_IWPM_REG_PID = 0, @@ -45,6 +58,7 @@ enum { RDMA_NL_IWPM_HANDLE_ERR, RDMA_NL_IWPM_MAPINFO, RDMA_NL_IWPM_MAPINFO_NUM, + RDMA_NL_IWPM_HELLO, RDMA_NL_IWPM_NUM_OPS }; @@ -83,20 +97,38 @@ enum { IWPM_NLA_MANAGE_MAPPING_UNSPEC = 0, IWPM_NLA_MANAGE_MAPPING_SEQ, IWPM_NLA_MANAGE_ADDR, - IWPM_NLA_MANAGE_MAPPED_LOC_ADDR, + IWPM_NLA_MANAGE_FLAGS, + IWPM_NLA_MANAGE_MAPPING_MAX +}; + +enum { + IWPM_NLA_RMANAGE_MAPPING_UNSPEC = 0, + IWPM_NLA_RMANAGE_MAPPING_SEQ, + IWPM_NLA_RMANAGE_ADDR, + IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR, + /* The following maintains bisectability of rdma-core */ + IWPM_NLA_MANAGE_MAPPED_LOC_ADDR = IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR, IWPM_NLA_RMANAGE_MAPPING_ERR, IWPM_NLA_RMANAGE_MAPPING_MAX }; -#define IWPM_NLA_MANAGE_MAPPING_MAX 3 -#define IWPM_NLA_QUERY_MAPPING_MAX 4 #define IWPM_NLA_MAPINFO_SEND_MAX 3 +#define IWPM_NLA_REMOVE_MAPPING_MAX 3 enum { IWPM_NLA_QUERY_MAPPING_UNSPEC = 0, IWPM_NLA_QUERY_MAPPING_SEQ, IWPM_NLA_QUERY_LOCAL_ADDR, IWPM_NLA_QUERY_REMOTE_ADDR, + IWPM_NLA_QUERY_FLAGS, + IWPM_NLA_QUERY_MAPPING_MAX, +}; + +enum { + IWPM_NLA_RQUERY_MAPPING_UNSPEC = 0, + IWPM_NLA_RQUERY_MAPPING_SEQ, + IWPM_NLA_RQUERY_LOCAL_ADDR, + IWPM_NLA_RQUERY_REMOTE_ADDR, IWPM_NLA_RQUERY_MAPPED_LOC_ADDR, IWPM_NLA_RQUERY_MAPPED_REM_ADDR, IWPM_NLA_RQUERY_MAPPING_ERR, @@ -114,6 +146,7 @@ enum { IWPM_NLA_MAPINFO_UNSPEC = 0, IWPM_NLA_MAPINFO_LOCAL_ADDR, IWPM_NLA_MAPINFO_MAPPED_ADDR, + IWPM_NLA_MAPINFO_FLAGS, IWPM_NLA_MAPINFO_MAX }; @@ -132,6 +165,12 @@ enum { IWPM_NLA_ERR_MAX }; +enum { + IWPM_NLA_HELLO_UNSPEC = 0, + IWPM_NLA_HELLO_ABI_VERSION, + IWPM_NLA_HELLO_MAX +}; + /* * Local service operations: * RESOLVE - The client requests the local service to resolve a path. From patchwork Tue Jan 29 19:11:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Wise X-Patchwork-Id: 10787089 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4AEA613BF for ; Tue, 29 Jan 2019 19:14:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 379C12C96D for ; Tue, 29 Jan 2019 19:14:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2BD3A2C978; Tue, 29 Jan 2019 19:14:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DC9522C96D for ; Tue, 29 Jan 2019 19:14:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728818AbfA2TOG (ORCPT ); Tue, 29 Jan 2019 14:14:06 -0500 Received: from opengridcomputing.com ([72.48.214.68]:37928 "EHLO smtp.opengridcomputing.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726852AbfA2TOG (ORCPT ); Tue, 29 Jan 2019 14:14:06 -0500 Received: by smtp.opengridcomputing.com (Postfix, from userid 503) id 0AF6922791; Tue, 29 Jan 2019 13:14:05 -0600 (CST) Message-Id: In-Reply-To: References: From: Steve Wise Date: Tue, 29 Jan 2019 11:11:04 -0800 Subject: [PATCH rdma-core 2/2] iwpmd: add NO_PORT_MAP support To: dledford@redhat.com, jgg@mellanox.com Cc: linux-rdma@vger.kernel.org, BMT@zurich.ibm.com, shiraz.saleem@intel.com Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP A soft iwarp driver that uses the host TCP stack via a kernel mode socket does not need port mapping. In fact, if the port map daemon, iwpmd, is running, then iwpmd must not try and create/bind a socket to the actual port for a soft iwarp connection, since the driver already has that socket bound. Yet if the soft iwarp driver wants to interoperate with hard iwarp devices that -are- using port mapping, then the soft iwarp driver's mappings still need to be maintained and advertised by the iwpm protocol. This patch enhances iwpmd to support the new version 4 IWPM netlink protocol. It does so while still providing support for kernels with ABI version 3. Signed-off-by: Steve Wise --- iwpmd/iwarp_pm.h | 8 +- iwpmd/iwarp_pm_helper.c | 26 ++++-- iwpmd/iwarp_pm_server.c | 229 +++++++++++++++++++++++++++++++++++------------- 3 files changed, 193 insertions(+), 70 deletions(-) diff --git a/iwpmd/iwarp_pm.h b/iwpmd/iwarp_pm.h index c3f19a12e27d..83cbb8ed9c5b 100644 --- a/iwpmd/iwarp_pm.h +++ b/iwpmd/iwarp_pm.h @@ -108,7 +108,8 @@ enum { IWPM_UNKNOWN_MAPPING_ERR, IWPM_CLIENT_DEV_INFO_ERR, IWPM_USER_LIB_INFO_ERR, - IWPM_REMOTE_QUERY_REJECT + IWPM_REMOTE_QUERY_REJECT, + IWPM_VERSION_MISMATCH_ERR, }; /* iwpm param indexes */ @@ -236,9 +237,10 @@ int is_wcard_ipaddr(struct sockaddr_storage *); /* iwarp_pm_helper.c */ -iwpm_mapped_port *create_iwpm_mapped_port(struct sockaddr_storage *, int); +iwpm_mapped_port *create_iwpm_mapped_port(struct sockaddr_storage *, int, __u32 flags); -iwpm_mapped_port *reopen_iwpm_mapped_port(struct sockaddr_storage *, struct sockaddr_storage *, int); +iwpm_mapped_port *reopen_iwpm_mapped_port(struct sockaddr_storage *, struct sockaddr_storage *, int, + __u32 flags); void add_iwpm_mapped_port(iwpm_mapped_port *); diff --git a/iwpmd/iwarp_pm_helper.c b/iwpmd/iwarp_pm_helper.c index b8c230189d50..16311a9c989c 100644 --- a/iwpmd/iwarp_pm_helper.c +++ b/iwpmd/iwarp_pm_helper.c @@ -352,7 +352,7 @@ static iwpm_mapped_port *get_iwpm_port(int client_idx, struct sockaddr_storage * * @local_addr: local address to be mapped (IP address and TCP port) * @client_idx: the index of the client owner of the mapped port */ -iwpm_mapped_port *create_iwpm_mapped_port(struct sockaddr_storage *local_addr, int client_idx) +iwpm_mapped_port *create_iwpm_mapped_port(struct sockaddr_storage *local_addr, int client_idx, __u32 flags) { iwpm_mapped_port *iwpm_port; struct sockaddr_storage mapped_addr; @@ -362,8 +362,13 @@ iwpm_mapped_port *create_iwpm_mapped_port(struct sockaddr_storage *local_addr, i if (get_iwpm_ip_addr(local_addr, &mapped_addr)) goto create_mapped_port_error; /* get a tcp port from the host net stack */ - if (get_iwpm_tcp_port(local_addr->ss_family, 0, &mapped_addr, &new_sd)) - goto create_mapped_port_error; + if (flags & IWPM_FLAGS_NO_PORT_MAP) { + mapped_addr = *local_addr; + new_sd = -1; + } else { + if (get_iwpm_tcp_port(local_addr->ss_family, 0, &mapped_addr, &new_sd)) + goto create_mapped_port_error; + } iwpm_port = get_iwpm_port(client_idx, local_addr, &mapped_addr, new_sd); return iwpm_port; @@ -380,7 +385,8 @@ create_mapped_port_error: * @client_idx: the index of the client owner of the mapped port */ iwpm_mapped_port *reopen_iwpm_mapped_port(struct sockaddr_storage *local_addr, - struct sockaddr_storage *mapped_addr, int client_idx) + struct sockaddr_storage *mapped_addr, int client_idx, + __u32 flags) { iwpm_mapped_port *iwpm_port; int new_sd; @@ -395,9 +401,12 @@ iwpm_mapped_port *reopen_iwpm_mapped_port(struct sockaddr_storage *local_addr, goto reopen_mapped_port_error; } /* get a tcp port from the host net stack */ - if (get_iwpm_tcp_port(local_addr->ss_family, htobe16(1), mapped_addr, &new_sd)) - goto reopen_mapped_port_error; - + if (flags & IWPM_FLAGS_NO_PORT_MAP) { + new_sd = -1; + } else { + if (get_iwpm_tcp_port(local_addr->ss_family, htobe16(1), mapped_addr, &new_sd)) + goto reopen_mapped_port_error; + } iwpm_port = get_iwpm_port(client_idx, local_addr, mapped_addr, new_sd); return iwpm_port; @@ -520,7 +529,8 @@ find_same_mapping_exit: */ void free_iwpm_port(iwpm_mapped_port *iwpm_port) { - close(iwpm_port->sd); + if (iwpm_port->sd != -1) + close(iwpm_port->sd); free(iwpm_port); } diff --git a/iwpmd/iwarp_pm_server.c b/iwpmd/iwarp_pm_server.c index 63ed83ab17fd..aacadc2ba01c 100644 --- a/iwpmd/iwarp_pm_server.c +++ b/iwpmd/iwarp_pm_server.c @@ -35,9 +35,12 @@ #include #include #include "iwarp_pm.h" +#include +#include +#include static const char iwpm_ulib_name [] = "iWarpPortMapperUser"; -static int iwpm_version = 3; +static __u16 iwpm_version = IWPM_UABI_VERSION; LIST_HEAD(mapping_reqs); /* list of map tracking objects */ LIST_HEAD(pending_messages); /* list of pending wire messages */ @@ -58,6 +61,7 @@ pthread_mutex_t pending_msg_mutex = PTHREAD_MUTEX_INITIALIZER; static void iwpm_cleanup(void); static int print_mappings = 0; +static int send_iwpm_mapinfo_request(int nl_sock, int client); /** * iwpm_signal_handler - Handle signals which iwarp port mapper receives @@ -290,7 +294,8 @@ register_pid_error: /* Add mapping request - nlmsg attributes */ static struct nla_policy manage_map_policy[IWPM_NLA_MANAGE_MAPPING_MAX] = { [IWPM_NLA_MANAGE_MAPPING_SEQ] = { .type = NLA_U32 }, - [IWPM_NLA_MANAGE_ADDR] = { .minlen = sizeof(struct sockaddr_storage) } + [IWPM_NLA_MANAGE_ADDR] = { .minlen = sizeof(struct sockaddr_storage) }, + [IWPM_NLA_MANAGE_FLAGS] = { .type = NLA_U32 } }; /** @@ -302,15 +307,15 @@ static struct nla_policy manage_map_policy[IWPM_NLA_MANAGE_MAPPING_MAX] = { * Process a mapping request for a local address and send a response to the client * which contains the mapped local address (IP address and TCP port) * nlmsg response attributes: - * [IWPM_NLA_MANAGE_MAPPING_SEQ] - * [IWPM_NLA_MANAGE_ADDR] - * [IWPM_NLA_MANAGE_MAPPED_LOC_ADDR] + * [IWPM_NLA_RMANAGE_MAPPING_SEQ] + * [IWPM_NLA_RMANAGE_ADDR] + * [IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR] * [IWPM_NLA_RMANAGE_MAPPING_ERR] */ static int process_iwpm_add_mapping(struct nlmsghdr *req_nlh, int client_idx, int nl_sock) { iwpm_mapped_port *iwpm_port = NULL; - struct nlattr *nltb [IWPM_NLA_MANAGE_MAPPING_MAX]; + struct nlattr *nltb [IWPM_NLA_MANAGE_MAPPING_MAX] = {}; struct nl_msg *resp_nlmsg = NULL; struct sockaddr_storage *local_addr; int not_mapped = 1; @@ -318,13 +323,18 @@ static int process_iwpm_add_mapping(struct nlmsghdr *req_nlh, int client_idx, in const char *msg_type = "Add Mapping Request"; const char *str_err = ""; int ret = -EINVAL; + __u32 flags; + int max = IWPM_NLA_MANAGE_MAPPING_MAX; - if (parse_iwpm_nlmsg(req_nlh, IWPM_NLA_MANAGE_MAPPING_MAX, manage_map_policy, nltb, msg_type)) { + if (iwpm_version != IWPM_UABI_VERSION) + max--; + if (parse_iwpm_nlmsg(req_nlh, max, manage_map_policy, nltb, msg_type)) { err_code = IWPM_INVALID_NLMSG_ERR; str_err = "Received Invalid nlmsg"; goto add_mapping_error; } local_addr = (struct sockaddr_storage *)nla_data(nltb[IWPM_NLA_MANAGE_ADDR]); + flags = nltb[IWPM_NLA_MANAGE_FLAGS] ? nla_get_u32(nltb[IWPM_NLA_MANAGE_FLAGS]) : 0; iwpm_port = find_iwpm_mapping(local_addr, not_mapped); if (iwpm_port) { @@ -337,7 +347,7 @@ static int process_iwpm_add_mapping(struct nlmsghdr *req_nlh, int client_idx, in } } else { - iwpm_port = create_iwpm_mapped_port(local_addr, client_idx); + iwpm_port = create_iwpm_mapped_port(local_addr, client_idx, flags); if (!iwpm_port) { err_code = IWPM_CREATE_MAPPING_ERR; str_err = "Unable to create new mapping"; @@ -351,12 +361,12 @@ static int process_iwpm_add_mapping(struct nlmsghdr *req_nlh, int client_idx, in goto add_mapping_free_error; } str_err = "Invalid nlmsg attribute"; - if ((ret = nla_put_u32(resp_nlmsg, IWPM_NLA_MANAGE_MAPPING_SEQ, req_nlh->nlmsg_seq))) + if ((ret = nla_put_u32(resp_nlmsg, IWPM_NLA_RMANAGE_MAPPING_SEQ, req_nlh->nlmsg_seq))) goto add_mapping_free_error; - if ((ret = nla_put(resp_nlmsg, IWPM_NLA_MANAGE_ADDR, + if ((ret = nla_put(resp_nlmsg, IWPM_NLA_RMANAGE_ADDR, sizeof(struct sockaddr_storage), &iwpm_port->local_addr))) goto add_mapping_free_error; - if ((ret = nla_put(resp_nlmsg, IWPM_NLA_MANAGE_MAPPED_LOC_ADDR, + if ((ret = nla_put(resp_nlmsg, IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR, sizeof(struct sockaddr_storage), &iwpm_port->mapped_addr))) goto add_mapping_free_error; if ((ret = nla_put_u16(resp_nlmsg, IWPM_NLA_RMANAGE_MAPPING_ERR, err_code))) @@ -392,7 +402,8 @@ add_mapping_error: static struct nla_policy query_map_policy[IWPM_NLA_QUERY_MAPPING_MAX] = { [IWPM_NLA_QUERY_MAPPING_SEQ] = { .type = NLA_U32 }, [IWPM_NLA_QUERY_LOCAL_ADDR] = { .minlen = sizeof(struct sockaddr_storage) }, - [IWPM_NLA_QUERY_REMOTE_ADDR] = { .minlen = sizeof(struct sockaddr_storage) } + [IWPM_NLA_QUERY_REMOTE_ADDR] = { .minlen = sizeof(struct sockaddr_storage) }, + [IWPM_NLA_QUERY_FLAGS] = { .type = NLA_U32 } }; /** @@ -409,7 +420,7 @@ static int process_iwpm_query_mapping(struct nlmsghdr *req_nlh, int client_idx, { iwpm_mapped_port *iwpm_port = NULL; iwpm_mapping_request *iwpm_map_req = NULL; - struct nlattr *nltb [IWPM_NLA_QUERY_MAPPING_MAX]; + struct nlattr *nltb [IWPM_NLA_QUERY_MAPPING_MAX] = {}; struct sockaddr_storage *local_addr, *remote_addr; sockaddr_union dest_addr; iwpm_msg_parms msg_parms; @@ -420,20 +431,25 @@ static int process_iwpm_query_mapping(struct nlmsghdr *req_nlh, int client_idx, const char *msg_type = "Add & Query Mapping Request"; const char *str_err = ""; int ret = -EINVAL; + __u32 flags; + int max = IWPM_NLA_QUERY_MAPPING_MAX; - if (parse_iwpm_nlmsg(req_nlh, IWPM_NLA_QUERY_MAPPING_MAX, query_map_policy, nltb, msg_type)) { + if (iwpm_version != IWPM_UABI_VERSION) + max--; + if (parse_iwpm_nlmsg(req_nlh, max, query_map_policy, nltb, msg_type)) { err_code = IWPM_INVALID_NLMSG_ERR; str_err = "Received Invalid nlmsg"; goto query_mapping_error; } local_addr = (struct sockaddr_storage *)nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]); remote_addr = (struct sockaddr_storage *)nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]); + flags = nltb[IWPM_NLA_QUERY_FLAGS] ? nla_get_u32(nltb[IWPM_NLA_QUERY_FLAGS]) : 0; iwpm_port = find_iwpm_mapping(local_addr, not_mapped); if (iwpm_port) { atomic_fetch_add(&iwpm_port->ref_cnt, 1); } else { - iwpm_port = create_iwpm_mapped_port(local_addr, client_idx); + iwpm_port = create_iwpm_mapped_port(local_addr, client_idx, flags); if (!iwpm_port) { err_code = IWPM_CREATE_MAPPING_ERR; str_err = "Unable to create new mapping"; @@ -530,7 +546,7 @@ static int process_iwpm_remove_mapping(struct nlmsghdr *req_nlh, int client_idx, const char *msg_type = "Remove Mapping Request"; int ret = 0; - if (parse_iwpm_nlmsg(req_nlh, IWPM_NLA_MANAGE_MAPPING_MAX, manage_map_policy, nltb, msg_type)) { + if (parse_iwpm_nlmsg(req_nlh, IWPM_NLA_REMOVE_MAPPING_MAX, manage_map_policy, nltb, msg_type)) { send_iwpm_error_msg(req_nlh->nlmsg_seq, IWPM_INVALID_NLMSG_ERR, client_idx, nl_sock); syslog(LOG_WARNING, "process_remove_mapping: Received Invalid nlmsg from client = %d\n", client_idx); @@ -869,7 +885,8 @@ static int process_iwpm_wire_ack(iwpm_msg_parms *msg_parms) /* Mapping info message - nlmsg attributes */ static struct nla_policy mapinfo_policy[IWPM_NLA_MAPINFO_MAX] = { [IWPM_NLA_MAPINFO_LOCAL_ADDR] = { .minlen = sizeof(struct sockaddr_storage) }, - [IWPM_NLA_MAPINFO_MAPPED_ADDR] = { .minlen = sizeof(struct sockaddr_storage) } + [IWPM_NLA_MAPINFO_MAPPED_ADDR] = { .minlen = sizeof(struct sockaddr_storage) }, + [IWPM_NLA_MAPINFO_FLAGS] = { .type = NLA_U32 } }; /** @@ -886,20 +903,25 @@ static int process_iwpm_mapinfo(struct nlmsghdr *req_nlh, int client_idx, int nl { iwpm_mapped_port *iwpm_port = NULL; struct sockaddr_storage *local_addr, *local_mapped_addr; - struct nlattr *nltb [IWPM_NLA_MAPINFO_MAX]; + struct nlattr *nltb [IWPM_NLA_MAPINFO_MAX] = {}; int not_mapped = 1; __u16 err_code = 0; const char *msg_type = "Mapping Info Msg"; const char *str_err = ""; int ret = -EINVAL; + __u32 flags; + int max = IWPM_NLA_MAPINFO_MAX; - if (parse_iwpm_nlmsg(req_nlh, IWPM_NLA_MAPINFO_MAX, mapinfo_policy, nltb, msg_type)) { + if (iwpm_version != IWPM_UABI_VERSION) + max--; + if (parse_iwpm_nlmsg(req_nlh, max, mapinfo_policy, nltb, msg_type)) { err_code = IWPM_INVALID_NLMSG_ERR; str_err = "Received Invalid nlmsg"; goto process_mapinfo_error; } local_addr = (struct sockaddr_storage *)nla_data(nltb[IWPM_NLA_MAPINFO_LOCAL_ADDR]); local_mapped_addr = (struct sockaddr_storage *)nla_data(nltb[IWPM_NLA_MAPINFO_MAPPED_ADDR]); + flags = nltb[IWPM_NLA_MAPINFO_FLAGS] ? nla_get_u32(nltb[IWPM_NLA_MAPINFO_FLAGS]) : 0; iwpm_port = find_iwpm_mapping(local_addr, not_mapped); if (iwpm_port) { @@ -915,7 +937,7 @@ static int process_iwpm_mapinfo(struct nlmsghdr *req_nlh, int client_idx, int nl str_err = "Duplicate mapped port"; goto process_mapinfo_error; } - iwpm_port = reopen_iwpm_mapped_port(local_addr, local_mapped_addr, client_idx); + iwpm_port = reopen_iwpm_mapped_port(local_addr, local_mapped_addr, client_idx, flags); if (!iwpm_port) { err_code = IWPM_CREATE_MAPPING_ERR; str_err = "Unable to create new mapping"; @@ -1045,6 +1067,63 @@ send_error_msg_exit: return ret; } +/* Hello message - nlmsg attributes */ +static struct nla_policy hello_policy[IWPM_NLA_HELLO_MAX] = { + [IWPM_NLA_HELLO_ABI_VERSION] = { .type = NLA_U16 } +}; + +/** + * process_iwpm_hello - Process mapinfo count message + * @req_nlh: netlink header of the received message from the client + * @client_idx: the index of the client + * @nl_sock: netlink socket to send a message to the client + * + * Mapinfo count message is a mechanism for the port mapper and the client to + * synchronize on the number of mapinfo messages which were sucessfully exchanged and processed + */ +static int process_iwpm_hello(struct nlmsghdr *req_nlh, int client_idx, int nl_sock) +{ + struct nlattr *nltb [IWPM_NLA_HELLO_MAX]; + const char *msg_type = "Hello Msg"; + __u16 abi_version; + __u16 err_code = 0; + const char *str_err = ""; + int ret = -EINVAL; + + if (req_nlh->nlmsg_type == NLMSG_ERROR) { + abi_version = IWPM_UABI_VERSION_MIN; + } else { + if (parse_iwpm_nlmsg(req_nlh, IWPM_NLA_HELLO_MAX, + hello_policy, nltb, msg_type)) { + str_err = "Received Invalid nlmsg"; + err_code = IWPM_INVALID_NLMSG_ERR; + goto hello_error; + } + abi_version = nla_get_u16(nltb[IWPM_NLA_HELLO_ABI_VERSION]); + } + if (abi_version > IWPM_UABI_VERSION) { + str_err = "UABI Version mismatch"; + err_code = IWPM_VERSION_MISMATCH_ERR; + goto hello_error; + } + iwpm_version = abi_version; + iwpm_debug(IWARP_PM_NETLINK_DBG, "process_iwpm_hello: using abi_version %u\n", iwpm_version); + + send_iwpm_mapinfo_request(nl_sock, RDMA_NL_IWCM); + if (iwpm_version == 3) { + /* Legacy RDMA_NL_C4IW for old kernels */ + send_iwpm_mapinfo_request(nl_sock, RDMA_NL_IWCM+1); + } + return 0; +hello_error: + syslog(LOG_WARNING, "process_iwpm_hello: %s.\n", str_err); + if (err_code) { + /* send error message to the client */ + send_iwpm_error_msg(req_nlh->nlmsg_seq, err_code, client_idx, nl_sock); + } + return ret; +} + /** * process_iwpm_netlink_msg - Dispatch received netlink messages * @nl_sock: netlink socket to read the messages from @@ -1084,13 +1163,19 @@ static int process_iwpm_netlink_msg(int nl_sock) goto process_netlink_msg_exit; } - if (nlh->nlmsg_type == NLMSG_ERROR) { - iwpm_debug(IWARP_PM_NETLINK_DBG, "process_netlink_msg: " + type = nlh->nlmsg_type; + client_idx = RDMA_NL_GET_CLIENT(type); + if (type == NLMSG_ERROR) { + + /* RDMA_NL_IWCM HELLO error indicates V3 kernel */ + if (nlh->nlmsg_seq == 0) { + ret = process_iwpm_hello(nlh, client_idx, nl_sock); + } else { + iwpm_debug(IWARP_PM_NETLINK_DBG, "process_netlink_msg: " "Netlink error message seq = %u\n", nlh->nlmsg_seq); + } goto process_netlink_msg_exit; } - type = nlh->nlmsg_type; - client_idx = RDMA_NL_GET_CLIENT(type); op = RDMA_NL_GET_OP(type); iwpm_debug(IWARP_PM_NETLINK_DBG, "process_netlink_msg: Received a new message: " "opcode = %u client idx = %u, client pid = %u," @@ -1133,6 +1218,9 @@ static int process_iwpm_netlink_msg(int nl_sock) case RDMA_NL_IWPM_MAPINFO_NUM: ret = process_iwpm_mapinfo_count(nlh, client_idx, nl_sock); break; + case RDMA_NL_IWPM_HELLO: + ret = process_iwpm_hello(nlh, client_idx, nl_sock); + break; default: str_err = "Netlink message with invalid opcode"; ret = -1; @@ -1202,55 +1290,79 @@ process_iwpm_msg_exit: } /** - * init_iwpm_clients - Initialize the known clients of the iwarp port mapper - * @iwarp_clients - array of port mapper clients to init + * send_iwpm_hello - Notify the client that the V4 iwarp port mapper is available + * @nl_sock: netlink socket to send a message to the client * - * Return the number of known clients + * Send a HELLO message including the ABI_VERSION supported by iwpmd. If the + * response is an ERROR message, then we know the kernel driver is < V4, so we + * drop back to the V3 protocol. If the kernel is >= V4, then it will reply + * with its ABI Version. The response is handled in iwarp_port_mapper(). Once + * the ABI version is negotiatied, iwpmd will send a mapinfo request to get any + * current mappings, using the correct ABI version. This allows working with + * V3 kernels. */ -static int init_iwpm_clients(__u32 iwarp_clients[]) +static int send_iwpm_hello(int nl_sock) { - int client_num = 2; + struct nl_msg *req_nlmsg; + const char *str_err; + __u16 nlmsg_type; + int ret; - iwarp_clients[0] = RDMA_NL_IWCM; - iwarp_clients[1] = RDMA_NL_IWCM+1; /* Legacy RDMA_NL_C4IW for old kernels */ + nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_IWCM, RDMA_NL_IWPM_HELLO); + req_nlmsg = create_iwpm_nlmsg(nlmsg_type, RDMA_NL_IWCM); + if (!req_nlmsg) { + ret = -ENOMEM; + str_err = "Unable to create nlmsg request"; + goto send_hello_error; + } + str_err = "Invalid nlmsg attribute"; + if ((ret = nla_put_u16(req_nlmsg, IWPM_NLA_HELLO_ABI_VERSION, iwpm_version))) + goto send_hello_error; - return client_num; + if ((ret = send_iwpm_nlmsg(nl_sock, req_nlmsg, 0))) { + str_err = "Unable to send nlmsg response"; + goto send_hello_error; + } + nlmsg_free(req_nlmsg); + return 0; +send_hello_error: + if (req_nlmsg) + nlmsg_free(req_nlmsg); + syslog(LOG_WARNING, "send_hello_request: %s ret = %d.\n", str_err, ret); + return ret; } /** * send_iwpm_mapinfo_request - Notify the client that the iwarp port mapper is available * @nl_sock: netlink socket to send a message to the client - * @iwarp_clients - array of port mapper clients to init - * @length - the length of the array + * @client - client to receive the message */ -static int send_iwpm_mapinfo_request(int nl_sock, __u32 *iwarp_clients, int length) +static int send_iwpm_mapinfo_request(int nl_sock, int client) { struct nl_msg *req_nlmsg; __u16 nlmsg_type; - int i; const char *str_err; int ret; - for (i = 0; i < length; i++) { - nlmsg_type = RDMA_NL_GET_TYPE(iwarp_clients[i], RDMA_NL_IWPM_MAPINFO); - req_nlmsg = create_iwpm_nlmsg(nlmsg_type, iwarp_clients[i]); - if (!req_nlmsg) { - ret = -ENOMEM; - str_err = "Unable to create nlmsg request"; - goto send_mapinfo_error; - } - str_err = "Invalid nlmsg attribute"; - if ((ret = nla_put_string(req_nlmsg, IWPM_NLA_MAPINFO_ULIB_NAME, iwpm_ulib_name))) - goto send_mapinfo_error; - if ((ret = nla_put_u16(req_nlmsg, IWPM_NLA_MAPINFO_ULIB_VER, iwpm_version))) - goto send_mapinfo_error; - - if ((ret = send_iwpm_nlmsg(nl_sock, req_nlmsg, 0))) { - str_err = "Unable to send nlmsg response"; - goto send_mapinfo_error; - } - nlmsg_free(req_nlmsg); + nlmsg_type = RDMA_NL_GET_TYPE(client, RDMA_NL_IWPM_MAPINFO); + req_nlmsg = create_iwpm_nlmsg(nlmsg_type, client); + if (!req_nlmsg) { + ret = -ENOMEM; + str_err = "Unable to create nlmsg request"; + goto send_mapinfo_error; } + str_err = "Invalid nlmsg attribute"; + if ((ret = nla_put_string(req_nlmsg, IWPM_NLA_MAPINFO_ULIB_NAME, iwpm_ulib_name))) + goto send_mapinfo_error; + + if ((ret = nla_put_u16(req_nlmsg, IWPM_NLA_MAPINFO_ULIB_VER, iwpm_version))) + goto send_mapinfo_error; + + if ((ret = send_iwpm_nlmsg(nl_sock, req_nlmsg, 0))) { + str_err = "Unable to send nlmsg response"; + goto send_mapinfo_error; + } + nlmsg_free(req_nlmsg); return 0; send_mapinfo_error: if (req_nlmsg) @@ -1366,8 +1478,6 @@ static void daemonize_iwpm_server(void) int main(int argc, char *argv[]) { - __u32 iwarp_clients[IWARP_PM_MAX_CLIENTS]; - int known_clients; FILE *fp; int c; int ret = EXIT_FAILURE; @@ -1441,8 +1551,9 @@ int main(int argc, char *argv[]) if (ret) goto error_exit; - known_clients = init_iwpm_clients(&iwarp_clients[0]); - send_iwpm_mapinfo_request(netlink_sock, &iwarp_clients[0], known_clients); + ret = send_iwpm_hello(netlink_sock); + if (ret) + goto error_exit; if (systemd) sd_notify(0, "READY=1");