/*
* Copyright (c) 2017 Pure Storage, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
if (!priv->cq_event) {
while (ibv_get_cq_event(priv->channel, &ev_cq, &ev_ctx) < 0) {
if (errno != EINTR) {
return PCAP_ERROR;
}
if (handle->break_loop) {
handle->break_loop = 0;
return PCAP_ERROR_BREAK;
}
}
ibv_ack_cq_events(priv->cq, 1);
ibv_req_notify_cq(priv->cq, 0);
priv->cq_event = 1;
}
/*
* This can conceivably process more than INT_MAX packets,
* which would overflow the packet count, causing it either
* to look like a negative number, and thus cause us to
* return a value that looks like an error, or overflow
* back into positive territory, and thus cause us to
* return a too-low count.
*
* Therefore, if the packet count is unlimited, we clip
* it at INT_MAX; this routine is not expected to
* process packets indefinitely, so that's not an issue.
*/
if (PACKET_COUNT_IS_UNLIMITED(max_packets))
max_packets = INT_MAX;
while (count < max_packets) {
if (ibv_poll_cq(priv->cq, 1, &wc) != 1) {
priv->cq_event = 0;
break;
}
if (wc.status != IBV_WC_SUCCESS) {
fprintf(stderr, "failed WC wr_id %" PRIu64 " status %d/%s\n",
wc.wr_id,
wc.status, ibv_wc_status_str(wc.status));
continue;
}
int
rdmasniff_findalldevs(pcap_if_list_t *devlistp, char *err_str)
{
struct ibv_device **dev_list;
int numdev;
int i;
int ret = 0;
dev_list = ibv_get_device_list(&numdev);
if (!dev_list) {
return 0;
}
for (i = 0; i < numdev; ++i) {
/*
* XXX - do the notions of "up", "running", or
* "connected" apply here?
*/
if (!pcapint_add_dev(devlistp, dev_list[i]->name, 0, "RDMA sniffer", err_str)) {
ret = -1;
break;
}
}