X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Frdma%2Fdevice.c;h=62dff21b0609f48c4836ca1ae40c8de2814d70d0;hb=0dcafcc505dccb9243c90c57a20295d4f0afce29;hp=b6609ca4bdcee30a919aff0ce339d73890b1257f;hpb=5763e47b7d0d9de7a46541e432abee39e17b5f1e;p=vpp.git diff --git a/src/plugins/rdma/device.c b/src/plugins/rdma/device.c index b6609ca4bdc..62dff21b060 100644 --- a/src/plugins/rdma/device.c +++ b/src/plugins/rdma/device.c @@ -45,20 +45,155 @@ static u8 rdma_rss_hash_key[] = { rdma_main_t rdma_main; -#define rdma_log_debug(dev, f, ...) \ -{ \ - vlib_log(VLIB_LOG_LEVEL_DEBUG, rdma_main.log_class, "%U: " f, \ - format_vlib_pci_addr, &rd->pci_addr, ##__VA_ARGS__); \ -}; +#define rdma_log__(lvl, dev, f, ...) \ + do { \ + vlib_log((lvl), rdma_main.log_class, "%s: " f, \ + &(dev)->name, ##__VA_ARGS__); \ + } while (0) + +#define rdma_log(lvl, dev, f, ...) \ + rdma_log__((lvl), (dev), "%s (%d): " f, strerror(errno), errno, ##__VA_ARGS__) + +static struct ibv_flow * +rdma_rxq_init_flow (const rdma_device_t * rd, struct ibv_qp *qp, + const mac_address_t * mac, const mac_address_t * mask, + u32 flags) +{ + struct ibv_flow *flow; + struct raw_eth_flow_attr + { + struct ibv_flow_attr attr; + struct ibv_flow_spec_eth spec_eth; + } __attribute__ ((packed)) fa; + + memset (&fa, 0, sizeof (fa)); + fa.attr.num_of_specs = 1; + fa.attr.port = 1; + fa.attr.flags = flags; + fa.spec_eth.type = IBV_FLOW_SPEC_ETH; + fa.spec_eth.size = sizeof (struct ibv_flow_spec_eth); + + memcpy (fa.spec_eth.val.dst_mac, mac, sizeof (fa.spec_eth.val.dst_mac)); + memcpy (fa.spec_eth.mask.dst_mac, mask, sizeof (fa.spec_eth.mask.dst_mac)); + + flow = ibv_create_flow (qp, &fa.attr); + if (!flow) + rdma_log (VLIB_LOG_LEVEL_ERR, rd, "ibv_create_flow() failed"); + return flow; +} static u32 -rdma_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, u32 flags) +rdma_rxq_destroy_flow (const rdma_device_t * rd, struct ibv_flow **flow) +{ + if (!*flow) + return 0; + + if (ibv_destroy_flow (*flow)) + { + rdma_log (VLIB_LOG_LEVEL_ERR, rd, "ibv_destroy_flow() failed"); + return ~0; + } + + *flow = 0; + return 0; +} + +static u32 +rdma_dev_set_promisc (rdma_device_t * rd) +{ + const mac_address_t all = {.bytes = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }; + int err; + + err = rdma_rxq_destroy_flow (rd, &rd->flow_mcast); + if (err) + return ~0; + + err = rdma_rxq_destroy_flow (rd, &rd->flow_ucast); + if (err) + return ~0; + + rd->flow_ucast = rdma_rxq_init_flow (rd, rd->rx_qp, &all, &all, 0); + if (!rd->flow_ucast) + return ~0; + + rd->flags |= RDMA_DEVICE_F_PROMISC; + return 0; +} + +static u32 +rdma_dev_set_ucast (rdma_device_t * rd) +{ + const mac_address_t ucast = {.bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + }; + const mac_address_t mcast = {.bytes = {0x1, 0x0, 0x0, 0x0, 0x0, 0x0} }; + int err; + + err = rdma_rxq_destroy_flow (rd, &rd->flow_mcast); + if (err) + return ~0; + + err = rdma_rxq_destroy_flow (rd, &rd->flow_ucast); + if (err) + return ~0; + + /* receive only packets with src = our MAC */ + rd->flow_ucast = rdma_rxq_init_flow (rd, rd->rx_qp, &rd->hwaddr, &ucast, 0); + if (!rd->flow_ucast) + return ~0; + + /* receive multicast packets */ + rd->flow_mcast = rdma_rxq_init_flow (rd, rd->rx_qp, &mcast, &mcast, + IBV_FLOW_ATTR_FLAGS_DONT_TRAP + /* let others receive mcast packet too (eg. Linux) */ + ); + if (!rd->flow_mcast) + return ~0; + + rd->flags &= ~RDMA_DEVICE_F_PROMISC; + return 0; +} + +static clib_error_t * +rdma_mac_change (vnet_hw_interface_t * hw, const u8 * old, const u8 * new) { rdma_main_t *rm = &rdma_main; - vlib_log_warn (rm->log_class, "TODO"); + rdma_device_t *rd = vec_elt_at_index (rm->devices, hw->dev_instance); + mac_address_from_bytes (&rd->hwaddr, new); + if (!(rd->flags & RDMA_DEVICE_F_PROMISC) && rdma_dev_set_ucast (rd)) + { + mac_address_from_bytes (&rd->hwaddr, old); + return clib_error_return_unix (0, "MAC update failed"); + } return 0; } +static u32 +rdma_dev_change_mtu (rdma_device_t * rd) +{ + rdma_log__ (VLIB_LOG_LEVEL_ERR, rd, "MTU change not supported"); + return ~0; +} + +static u32 +rdma_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, u32 flags) +{ + rdma_main_t *rm = &rdma_main; + rdma_device_t *rd = vec_elt_at_index (rm->devices, hw->dev_instance); + + switch (flags) + { + case 0: + return rdma_dev_set_ucast (rd); + case ETHERNET_INTERFACE_FLAG_ACCEPT_ALL: + return rdma_dev_set_promisc (rd); + case ETHERNET_INTERFACE_FLAG_MTU: + return rdma_dev_change_mtu (rd); + } + + rdma_log__ (VLIB_LOG_LEVEL_ERR, rd, "unknown flag %x requested", flags); + return ~0; +} + static void rdma_update_state (vnet_main_t * vnm, rdma_device_t * rd, int port) { @@ -145,9 +280,7 @@ rdma_async_event_read_ready (clib_file_t * f) struct ibv_async_event event; ret = ibv_get_async_event (rd->ctx, &event); if (ret < 0) - { - return clib_error_return_unix (0, "ibv_get_async_event() failed"); - } + return clib_error_return_unix (0, "ibv_get_async_event() failed"); switch (event.event_type) { @@ -164,9 +297,8 @@ rdma_async_event_read_ready (clib_file_t * f) format_vlib_pci_addr, &rd->pci_addr); break; default: - vlib_log_warn (rm->log_class, - "Unhandeld RDMA async event %i for device %U", - event.event_type, format_vlib_pci_addr, &rd->pci_addr); + rdma_log__ (VLIB_LOG_LEVEL_ERR, rd, "unhandeld RDMA async event %i", + event.event_type); break; } @@ -183,14 +315,11 @@ rdma_async_event_init (rdma_device_t * rd) /* make RDMA async event fd non-blocking */ ret = fcntl (rd->ctx->async_fd, F_GETFL); if (ret < 0) - { - return clib_error_return_unix (0, "fcntl(F_GETFL) failed"); - } + return clib_error_return_unix (0, "fcntl(F_GETFL) failed"); + ret = fcntl (rd->ctx->async_fd, F_SETFL, ret | O_NONBLOCK); if (ret < 0) - { - return clib_error_return_unix (0, "fcntl(F_SETFL, O_NONBLOCK) failed"); - } + return clib_error_return_unix (0, "fcntl(F_SETFL, O_NONBLOCK) failed"); /* register RDMA async event fd */ t.read_function = rdma_async_event_read_ready; @@ -201,7 +330,6 @@ rdma_async_event_init (rdma_device_t * rd) format (0, "RMDA %U async event", format_vlib_pci_addr, &rd->pci_addr); rd->async_event_clib_file_index = clib_file_add (&file_main, &t); - return 0; } @@ -238,7 +366,7 @@ rdma_dev_cleanup (rdma_device_t * rd) { \ int rv; \ if ((rv = fn (arg))) \ - rdma_log_debug (rd, #fn "() failed (rv = %d)", rv); \ + rdma_log (VLIB_LOG_LEVEL_DEBUG, rd, #fn "() failed (rv = %d)", rv); \ } _(ibv_destroy_flow, rd->flow_mcast); @@ -268,33 +396,6 @@ rdma_dev_cleanup (rdma_device_t * rd) pool_put (rm->devices, rd); } -static clib_error_t * -rdma_rxq_init_flow (struct ibv_flow **flow, struct ibv_qp *qp, - const mac_address_t * mac, const mac_address_t * mask, - u32 flags) -{ - struct raw_eth_flow_attr - { - struct ibv_flow_attr attr; - struct ibv_flow_spec_eth spec_eth; - } __attribute__ ((packed)) fa; - - memset (&fa, 0, sizeof (fa)); - fa.attr.num_of_specs = 1; - fa.attr.port = 1; - fa.attr.flags = flags; - fa.spec_eth.type = IBV_FLOW_SPEC_ETH; - fa.spec_eth.size = sizeof (struct ibv_flow_spec_eth); - - memcpy (fa.spec_eth.val.dst_mac, mac, sizeof (fa.spec_eth.val.dst_mac)); - memcpy (fa.spec_eth.mask.dst_mac, mask, sizeof (fa.spec_eth.mask.dst_mac)); - - if ((*flow = ibv_create_flow (qp, &fa.attr)) == 0) - return clib_error_return_unix (0, "create Flow Failed"); - - return 0; -} - static clib_error_t * rdma_rxq_init (vlib_main_t * vm, rdma_device_t * rd, u16 qid, u32 n_desc) { @@ -332,11 +433,7 @@ rdma_rxq_finalize (vlib_main_t * vm, rdma_device_t * rd) { struct ibv_rwq_ind_table_init_attr rwqia; struct ibv_qp_init_attr_ex qpia; - const mac_address_t ucast = {.bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - }; - const mac_address_t mcast = {.bytes = {0x1, 0x0, 0x0, 0x0, 0x0, 0x0} }; struct ibv_wq **ind_tbl; - clib_error_t *err; u32 i; ASSERT (is_pow2 (vec_len (rd->rxqs)) @@ -368,16 +465,10 @@ rdma_rxq_finalize (vlib_main_t * vm, rdma_device_t * rd) if ((rd->rx_qp = ibv_create_qp_ex (rd->ctx, &qpia)) == 0) return clib_error_return_unix (0, "Queue Pair create failed"); - /* receive only packets with src = our MAC */ - if ((err = - rdma_rxq_init_flow (&rd->flow_ucast, rd->rx_qp, &rd->hwaddr, &ucast, - 0)) != 0) - return err; - /* receive multicast packets */ - return rdma_rxq_init_flow (&rd->flow_mcast, rd->rx_qp, &mcast, &mcast, - IBV_FLOW_ATTR_FLAGS_DONT_TRAP - /* let others receive mcast packet too (eg. Linux) */ - ); + if (rdma_dev_set_ucast (rd)) + return clib_error_return_unix (0, "Set unicast mode failed"); + + return 0; } static clib_error_t * @@ -541,7 +632,7 @@ rdma_create_if (vlib_main_t * vm, rdma_create_if_args_t * args) clib_error_return_unix (0, "no RDMA devices available, errno = %d. " "Is the ib_uverbs module loaded?", errno); - goto err1; + goto err0; } for (int i = 0; i < n_devs; i++) @@ -563,7 +654,7 @@ rdma_create_if (vlib_main_t * vm, rdma_create_if_args_t * args) if ((args->error = rdma_dev_init (vm, rd, args->rxq_size, args->txq_size, args->rxq_num))) - goto err2; + goto err1; if ((args->error = rdma_register_interface (vnm, rd))) goto err2; @@ -658,7 +749,7 @@ static char *rdma_tx_func_error_strings[] = { }; /* *INDENT-OFF* */ -VNET_DEVICE_CLASS (rdma_device_class,) = +VNET_DEVICE_CLASS (rdma_device_class) = { .name = "RDMA interface", .format_device = format_rdma_device, @@ -667,6 +758,7 @@ VNET_DEVICE_CLASS (rdma_device_class,) = .rx_redirect_to_node = rdma_set_interface_next_node, .tx_function_n_errors = RDMA_TX_N_ERROR, .tx_function_error_strings = rdma_tx_func_error_strings, + .mac_addr_change_function = rdma_mac_change, }; /* *INDENT-ON* */