iproute2/rdma/res-cmid.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
   2/*
   3 * res-cmid.c   RDMA tool
   4 * Authors:     Leon Romanovsky <leonro@mellanox.com>
   5 */
   6
   7#include "res.h"
   8#include <inttypes.h>
   9
  10static const char *cm_id_state_to_str(uint8_t idx)
  11{
  12        static const char *const cm_id_states_str[] = {
  13                "IDLE",           "ADDR_QUERY",     "ADDR_RESOLVED",
  14                "ROUTE_QUERY",    "ROUTE_RESOLVED", "CONNECT",
  15                "DISCONNECT",     "ADDR_BOUND",     "LISTEN",
  16                "DEVICE_REMOVAL", "DESTROYING"
  17        };
  18
  19        if (idx < ARRAY_SIZE(cm_id_states_str))
  20                return cm_id_states_str[idx];
  21        return "UNKNOWN";
  22}
  23
  24static const char *cm_id_ps_to_str(uint32_t ps)
  25{
  26        switch (ps) {
  27        case RDMA_PS_IPOIB:
  28                return "IPoIB";
  29        case RDMA_PS_IB:
  30                return "IPoIB";
  31        case RDMA_PS_TCP:
  32                return "TCP";
  33        case RDMA_PS_UDP:
  34                return "UDP";
  35        default:
  36                return "---";
  37        }
  38}
  39
  40static void print_cm_id_state(struct rd *rd, uint8_t state)
  41{
  42        print_color_string(PRINT_ANY, COLOR_NONE, "state", "state %s ",
  43                           cm_id_state_to_str(state));
  44}
  45
  46static void print_ps(struct rd *rd, uint32_t ps)
  47{
  48        print_color_string(PRINT_ANY, COLOR_NONE, "ps", "ps %s ",
  49                           cm_id_ps_to_str(ps));
  50}
  51
  52static void print_ipaddr(struct rd *rd, const char *key, char *addrstr,
  53                         uint16_t port)
  54{
  55        int name_size = INET6_ADDRSTRLEN + strlen(":65535");
  56        char json_name[name_size];
  57
  58        snprintf(json_name, name_size, "%s:%u", addrstr, port);
  59        print_color_string(PRINT_ANY, COLOR_NONE, key, key, json_name);
  60        print_color_string(PRINT_FP, COLOR_NONE, NULL, " %s:", addrstr);
  61        print_color_uint(PRINT_FP, COLOR_NONE, NULL, "%u ", port);
  62}
  63
  64static int ss_ntop(struct nlattr *nla_line, char *addr_str, uint16_t *port)
  65{
  66        struct __kernel_sockaddr_storage *addr;
  67
  68        addr = (struct __kernel_sockaddr_storage *)mnl_attr_get_payload(
  69                nla_line);
  70        switch (addr->ss_family) {
  71        case AF_INET: {
  72                struct sockaddr_in *sin = (struct sockaddr_in *)addr;
  73
  74                if (!inet_ntop(AF_INET, (const void *)&sin->sin_addr, addr_str,
  75                               INET6_ADDRSTRLEN))
  76                        return -EINVAL;
  77                *port = ntohs(sin->sin_port);
  78                break;
  79        }
  80        case AF_INET6: {
  81                struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
  82
  83                if (!inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
  84                               addr_str, INET6_ADDRSTRLEN))
  85                        return -EINVAL;
  86                *port = ntohs(sin6->sin6_port);
  87                break;
  88        }
  89        default:
  90                return -EINVAL;
  91        }
  92        return 0;
  93}
  94static int res_cm_id_line(struct rd *rd, const char *name, int idx,
  95                       struct nlattr **nla_line)
  96{
  97        char src_addr_str[INET6_ADDRSTRLEN];
  98        char dst_addr_str[INET6_ADDRSTRLEN];
  99        uint16_t src_port, dst_port;
 100        uint32_t port = 0, pid = 0;
 101        uint8_t type = 0, state;
 102        uint32_t lqpn = 0, ps;
 103        uint32_t cm_idn = 0;
 104        char *comm = NULL;
 105
 106        if (!nla_line[RDMA_NLDEV_ATTR_RES_STATE] ||
 107            !nla_line[RDMA_NLDEV_ATTR_RES_PS])
 108                return MNL_CB_ERROR;
 109
 110        if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
 111                port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]);
 112
 113        if (port && port != rd->port_idx)
 114                goto out;
 115
 116        if (nla_line[RDMA_NLDEV_ATTR_RES_LQPN])
 117                lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
 118
 119        if (rd_is_filtered_attr(rd, "lqpn", lqpn,
 120                                nla_line[RDMA_NLDEV_ATTR_RES_LQPN]))
 121                goto out;
 122
 123        if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE])
 124                type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]);
 125        if (rd_is_string_filtered_attr(rd, "qp-type", qp_types_to_str(type),
 126                                       nla_line[RDMA_NLDEV_ATTR_RES_TYPE]))
 127                goto out;
 128
 129        ps = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PS]);
 130        if (rd_is_string_filtered_attr(rd, "ps", cm_id_ps_to_str(ps),
 131                                       nla_line[RDMA_NLDEV_ATTR_RES_PS]))
 132                goto out;
 133
 134        state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]);
 135        if (rd_is_string_filtered_attr(rd, "state", cm_id_state_to_str(state),
 136                                       nla_line[RDMA_NLDEV_ATTR_RES_STATE]))
 137                goto out;
 138
 139        if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR])
 140                if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR],
 141                            src_addr_str, &src_port))
 142                        goto out;
 143        if (rd_is_string_filtered_attr(rd, "src-addr", src_addr_str,
 144                                       nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]))
 145                goto out;
 146        if (rd_is_filtered_attr(rd, "src-port", src_port,
 147                                nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]))
 148                goto out;
 149
 150        if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR])
 151                if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR],
 152                            dst_addr_str, &dst_port))
 153                        goto out;
 154        if (rd_is_string_filtered_attr(rd, "dst-addr", dst_addr_str,
 155                                       nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]))
 156                goto out;
 157        if (rd_is_filtered_attr(rd, "dst-port", dst_port,
 158                                nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]))
 159                goto out;
 160
 161        if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
 162                pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
 163                comm = get_task_name(pid);
 164        }
 165
 166        if (rd_is_filtered_attr(rd, "pid", pid,
 167                                nla_line[RDMA_NLDEV_ATTR_RES_PID]))
 168                goto out;
 169
 170        if (nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN])
 171                cm_idn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]);
 172        if (rd_is_filtered_attr(rd, "cm-idn", cm_idn,
 173                                nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]))
 174                goto out;
 175
 176        if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) {
 177                /* discard const from mnl_attr_get_str */
 178                comm = (char *)mnl_attr_get_str(
 179                        nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]);
 180        }
 181
 182        open_json_object(NULL);
 183        print_link(rd, idx, name, port, nla_line);
 184        res_print_uint(rd, "cm-idn", cm_idn,
 185                       nla_line[RDMA_NLDEV_ATTR_RES_CM_IDN]);
 186        res_print_uint(rd, "lqpn", lqpn, nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
 187        if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE])
 188                print_qp_type(rd, type);
 189        print_cm_id_state(rd, state);
 190        print_ps(rd, ps);
 191        res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]);
 192        print_comm(rd, comm, nla_line);
 193
 194        if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR])
 195                print_ipaddr(rd, "src-addr", src_addr_str, src_port);
 196        if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR])
 197                print_ipaddr(rd, "dst-addr", dst_addr_str, dst_port);
 198
 199        print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]);
 200        newline(rd);
 201
 202out:    if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
 203                free(comm);
 204        return MNL_CB_OK;
 205}
 206
 207int res_cm_id_idx_parse_cb(const struct nlmsghdr *nlh, void *data)
 208{
 209        struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
 210        struct rd *rd = data;
 211        const char *name;
 212        int idx;
 213
 214        mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
 215        if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
 216                return MNL_CB_ERROR;
 217
 218        name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
 219        idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
 220
 221        return res_cm_id_line(rd, name, idx, tb);
 222}
 223
 224int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data)
 225{
 226        struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
 227        struct nlattr *nla_table, *nla_entry;
 228        struct rd *rd = data;
 229        int ret = MNL_CB_OK;
 230        const char *name;
 231        int idx;
 232
 233        mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
 234        if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
 235            !tb[RDMA_NLDEV_ATTR_RES_CM_ID])
 236                return MNL_CB_ERROR;
 237
 238        name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
 239        idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
 240        nla_table = tb[RDMA_NLDEV_ATTR_RES_CM_ID];
 241
 242        mnl_attr_for_each_nested(nla_entry, nla_table) {
 243                struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
 244
 245                ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
 246                if (ret != MNL_CB_OK)
 247                        break;
 248
 249                ret = res_cm_id_line(rd, name, idx, nla_line);
 250                if (ret != MNL_CB_OK)
 251                        break;
 252        }
 253        return ret;
 254}
 255