| /* |
| * Copyright (c) 2014 Intel Corporation, All rights reserved. |
| * |
| * This software is available to you under a choice of one of two |
| * licenses. You may choose to be licensed under the terms of the GNU |
| * General Public License (GPL) Version 2, available from the file |
| * COPYING in the main directory of this source tree, or the |
| * OpenIB.org BSD license below: |
| * |
| * Redistribution and use in source and binary forms, with or |
| * without modification, are permitted provided that the following |
| * conditions are met: |
| * |
| * - Redistributions of source code must retain the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer. |
| * |
| * - 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. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| * |
| */ |
| |
| #include <config.h> |
| |
| #include <string.h> |
| #include <stdio.h> |
| #include <inttypes.h> |
| #include <errno.h> |
| #include <sys/ioctl.h> |
| |
| #include <infiniband/umad.h> |
| |
| #define UNLIKELY_MGMT_CLASS 0x2F |
| #define UNLIKELY_RMPP_MGMT_CLASS 0x4F |
| |
| struct ib_user_mad_reg_req2 { |
| uint32_t id; |
| uint32_t qpn; |
| uint8_t mgmt_class; |
| uint8_t mgmt_class_version; |
| uint16_t res; |
| uint32_t flags; |
| uint64_t method_mask[2]; |
| uint32_t oui; |
| uint8_t rmpp_version; |
| uint8_t reserved[3]; |
| }; |
| |
| static int test_failures = 0; |
| |
| static void dump_reg_attr(struct umad_reg_attr *reg_attr) |
| { |
| printf("\nmgmt_class %u\n" |
| "mgmt_class_version %u\n" |
| "flags 0x%08x\n" |
| "method_mask 0x%016"PRIx64" %016"PRIx64"\n" |
| "oui 0x%06x\n" |
| "rmpp_version %u\n\n", |
| reg_attr->mgmt_class, |
| reg_attr->mgmt_class_version, |
| reg_attr->flags, |
| reg_attr->method_mask[1], reg_attr->method_mask[0], |
| reg_attr->oui, |
| reg_attr->rmpp_version); |
| } |
| |
| static int open_test_device(void) |
| { |
| int fd = umad_open_port(NULL, 0); |
| if (fd < 0) { |
| printf("\n *****\nOpen Port Failure... Aborting\n"); |
| printf(" Ensure you have an HCA to test against.\n"); |
| exit(0); |
| } |
| return fd; |
| } |
| |
| static void test_fail(void) |
| { |
| int rc = 0; |
| struct umad_reg_attr reg_attr; |
| uint32_t agent_id; |
| uint32_t agent_id2; |
| int fd; |
| |
| printf("\n *****\nBegin invalid tests\n"); |
| |
| fd = open_test_device(); |
| |
| memset(®_attr, 0, sizeof(reg_attr)); |
| reg_attr.mgmt_class = UNLIKELY_MGMT_CLASS; |
| reg_attr.mgmt_class_version = 0x1; |
| reg_attr.flags = 0x80000000; |
| printf("\n invalid register flags ... "); |
| rc = umad_register2(fd, ®_attr, &agent_id); |
| if (rc == 0) { |
| printf("\n umad_register2 registered invalid flags. rc = %d\n", |
| rc); |
| dump_reg_attr(®_attr); |
| test_failures++; |
| goto out; |
| } else { |
| printf(" PASS\n"); |
| umad_unregister(fd, agent_id); |
| } |
| |
| memset(®_attr, 0, sizeof(reg_attr)); |
| reg_attr.mgmt_class = 0x03; |
| reg_attr.mgmt_class_version = 0x2; |
| reg_attr.rmpp_version = 0x02; |
| printf("\n invalid rmpp_version ... "); |
| rc = umad_register2(fd, ®_attr, &agent_id); |
| if (rc == 0) { |
| printf("\n umad_register2 registered an invalid rmpp_version. rc = %d\n", |
| rc); |
| dump_reg_attr(®_attr); |
| test_failures++; |
| goto out; |
| } else { |
| printf(" PASS\n"); |
| umad_unregister(fd, agent_id); |
| } |
| |
| memset(®_attr, 0, sizeof(reg_attr)); |
| reg_attr.mgmt_class = UNLIKELY_RMPP_MGMT_CLASS; |
| reg_attr.oui = 0x0100066a; |
| printf("\n invalid oui ... "); |
| rc = umad_register2(fd, ®_attr, &agent_id); |
| if (rc == 0) { |
| printf("\n umad_register2 registered an invalid oui. rc = %d\n", |
| rc); |
| dump_reg_attr(®_attr); |
| test_failures++; |
| goto out; |
| } else { |
| printf(" PASS\n"); |
| umad_unregister(fd, agent_id); |
| } |
| |
| /* The following 2 registrations attempt to register the same OUI 2 |
| * times. The second one is supposed to fail with the same method |
| * mask. |
| */ |
| printf("\n duplicate oui ... "); |
| memset(®_attr, 0, sizeof(reg_attr)); |
| reg_attr.mgmt_class = UNLIKELY_RMPP_MGMT_CLASS; |
| reg_attr.mgmt_class_version = 0x1; |
| reg_attr.rmpp_version = 0x00; |
| reg_attr.oui = 0x00066a; |
| reg_attr.method_mask[0] = 0x80000000000000DEULL; |
| reg_attr.method_mask[1] = 0xAD00000000000001ULL; |
| rc = umad_register2(fd, ®_attr, &agent_id); |
| if (rc != 0) { |
| printf("\n umad_register2 Failed to register an oui for the duplicate test. rc = %d\n", |
| rc); |
| dump_reg_attr(®_attr); |
| test_failures++; |
| goto out; |
| } |
| |
| memset(®_attr, 0, sizeof(reg_attr)); |
| reg_attr.mgmt_class = UNLIKELY_RMPP_MGMT_CLASS; |
| reg_attr.mgmt_class_version = 0x1; |
| reg_attr.rmpp_version = 0x00; |
| reg_attr.oui = 0x00066a; |
| reg_attr.method_mask[0] = 0x80000000000000DEULL; |
| reg_attr.method_mask[1] = 0xAD00000000000001ULL; |
| rc = umad_register2(fd, ®_attr, &agent_id2); |
| if (rc == 0) { |
| printf("\n umad_register2 registered a duplicate oui. rc = %d\n", |
| rc); |
| dump_reg_attr(®_attr); |
| test_failures++; |
| goto out; |
| } else { |
| printf(" PASS\n"); |
| umad_unregister(fd, agent_id); |
| umad_unregister(fd, agent_id2); |
| } |
| |
| umad_close_port(fd); |
| out: |
| printf("\n *****\nEnd invalid tests\n"); |
| } |
| |
| static void test_oui(void) |
| { |
| int rc = 0; |
| struct umad_reg_attr reg_attr; |
| uint32_t agent_id; |
| int fd; |
| |
| printf("\n *****\nStart valid oui tests\n"); |
| |
| fd = open_test_device(); |
| |
| printf("\n valid oui ... "); |
| memset(®_attr, 0, sizeof(reg_attr)); |
| reg_attr.mgmt_class = UNLIKELY_RMPP_MGMT_CLASS; |
| reg_attr.mgmt_class_version = 0x1; |
| reg_attr.rmpp_version = 0x00; |
| reg_attr.oui = 0x00066a; |
| reg_attr.method_mask[0] = 0x80000000000000DEULL; |
| reg_attr.method_mask[1] = 0xAD00000000000001ULL; |
| rc = umad_register2(fd, ®_attr, &agent_id); |
| if (rc != 0) { |
| printf("\n umad_register2 failed oui 0x%x. rc = %d\n", |
| reg_attr.oui, rc); |
| dump_reg_attr(®_attr); |
| test_failures++; |
| goto out; |
| } else { |
| printf(" PASS\n"); |
| umad_unregister(fd, agent_id); |
| } |
| |
| printf("\n valid oui with flags ... "); |
| memset(®_attr, 0, sizeof(reg_attr)); |
| reg_attr.mgmt_class = UNLIKELY_RMPP_MGMT_CLASS; |
| reg_attr.mgmt_class_version = 0x1; |
| reg_attr.rmpp_version = 0x00; |
| reg_attr.flags = 0x01; |
| /* Use Intel OUI for testing */ |
| reg_attr.oui = 0x00066a; |
| rc = umad_register2(fd, ®_attr, &agent_id); |
| if (rc != 0) { |
| printf("\n umad_register2 failed oui 0x%x with flags 0x%x. rc = %d\n", |
| reg_attr.oui, reg_attr.flags, rc); |
| dump_reg_attr(®_attr); |
| test_failures++; |
| goto out; |
| } else { |
| printf(" PASS\n"); |
| umad_unregister(fd, agent_id); |
| } |
| |
| umad_close_port(fd); |
| |
| out: |
| printf("\n End valid oui tests\n *****\n"); |
| } |
| |
| static void check_register2_support(void) |
| { |
| struct ib_user_mad_reg_req2 req; |
| int fd; |
| |
| fd = open_test_device(); |
| |
| memset(&req, 0, sizeof(req)); |
| req.mgmt_class = UNLIKELY_MGMT_CLASS; |
| req.mgmt_class_version = 0x1; |
| req.qpn = 0x1; |
| |
| if (ioctl(fd, IB_USER_MAD_REGISTER_AGENT2, (void *)&req) != 0) { |
| if (errno == ENOTTY || errno == EINVAL) { |
| printf("\n *****\nKernel does not support the new ioctl. Aborting tests\n"); |
| exit(0); |
| } |
| } |
| |
| umad_close_port(fd); |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| //umad_debug(1); |
| check_register2_support(); |
| test_fail(); |
| test_oui(); |
| printf("\n *******************\n"); |
| printf(" umad_register2 had %d failures\n", test_failures); |
| printf(" *******************\n"); |
| return test_failures; |
| } |