| USERSPACE MAD ACCESS | |
| Device files | |
| Each port of each InfiniBand device has a "umad" device and an | |
| "issm" device attached. For example, a two-port HCA will have two | |
| umad devices and two issm devices, while a switch will have one | |
| device of each type (for switch port 0). | |
| Creating MAD agents | |
| A MAD agent can be created by filling in a struct ib_user_mad_reg_req | |
| and then calling the IB_USER_MAD_REGISTER_AGENT ioctl on a file | |
| descriptor for the appropriate device file. If the registration | |
| request succeeds, a 32-bit id will be returned in the structure. | |
| For example: | |
| struct ib_user_mad_reg_req req = { /* ... */ }; | |
| ret = ioctl(fd, IB_USER_MAD_REGISTER_AGENT, (char *) &req); | |
| if (!ret) | |
| my_agent = req.id; | |
| else | |
| perror("agent register"); | |
| Agents can be unregistered with the IB_USER_MAD_UNREGISTER_AGENT | |
| ioctl. Also, all agents registered through a file descriptor will | |
| be unregistered when the descriptor is closed. | |
| 2014 -- a new registration ioctl is now provided which allows additional | |
| fields to be provided during registration. | |
| Users of this registration call are implicitly setting the use of | |
| pkey_index (see below). | |
| Receiving MADs | |
| MADs are received using read(). The receive side now supports | |
| RMPP. The buffer passed to read() must be at least one | |
| struct ib_user_mad + 256 bytes. For example: | |
| If the buffer passed is not large enough to hold the received | |
| MAD (RMPP), the errno is set to ENOSPC and the length of the | |
| buffer needed is set in mad.length. | |
| Example for normal MAD (non RMPP) reads: | |
| struct ib_user_mad *mad; | |
| mad = malloc(sizeof *mad + 256); | |
| ret = read(fd, mad, sizeof *mad + 256); | |
| if (ret != sizeof mad + 256) { | |
| perror("read"); | |
| free(mad); | |
| } | |
| Example for RMPP reads: | |
| struct ib_user_mad *mad; | |
| mad = malloc(sizeof *mad + 256); | |
| ret = read(fd, mad, sizeof *mad + 256); | |
| if (ret == -ENOSPC)) { | |
| length = mad.length; | |
| free(mad); | |
| mad = malloc(sizeof *mad + length); | |
| ret = read(fd, mad, sizeof *mad + length); | |
| } | |
| if (ret < 0) { | |
| perror("read"); | |
| free(mad); | |
| } | |
| In addition to the actual MAD contents, the other struct ib_user_mad | |
| fields will be filled in with information on the received MAD. For | |
| example, the remote LID will be in mad.lid. | |
| If a send times out, a receive will be generated with mad.status set | |
| to ETIMEDOUT. Otherwise when a MAD has been successfully received, | |
| mad.status will be 0. | |
| poll()/select() may be used to wait until a MAD can be read. | |
| Sending MADs | |
| MADs are sent using write(). The agent ID for sending should be | |
| filled into the id field of the MAD, the destination LID should be | |
| filled into the lid field, and so on. The send side does support | |
| RMPP so arbitrary length MAD can be sent. For example: | |
| struct ib_user_mad *mad; | |
| mad = malloc(sizeof *mad + mad_length); | |
| /* fill in mad->data */ | |
| mad->hdr.id = my_agent; /* req.id from agent registration */ | |
| mad->hdr.lid = my_dest; /* in network byte order... */ | |
| /* etc. */ | |
| ret = write(fd, &mad, sizeof *mad + mad_length); | |
| if (ret != sizeof *mad + mad_length) | |
| perror("write"); | |
| Transaction IDs | |
| Users of the umad devices can use the lower 32 bits of the | |
| transaction ID field (that is, the least significant half of the | |
| field in network byte order) in MADs being sent to match | |
| request/response pairs. The upper 32 bits are reserved for use by | |
| the kernel and will be overwritten before a MAD is sent. | |
| P_Key Index Handling | |
| The old ib_umad interface did not allow setting the P_Key index for | |
| MADs that are sent and did not provide a way for obtaining the P_Key | |
| index of received MADs. A new layout for struct ib_user_mad_hdr | |
| with a pkey_index member has been defined; however, to preserve binary | |
| compatibility with older applications, this new layout will not be used | |
| unless one of IB_USER_MAD_ENABLE_PKEY or IB_USER_MAD_REGISTER_AGENT2 ioctl's | |
| are called before a file descriptor is used for anything else. | |
| In September 2008, the IB_USER_MAD_ABI_VERSION will be incremented | |
| to 6, the new layout of struct ib_user_mad_hdr will be used by | |
| default, and the IB_USER_MAD_ENABLE_PKEY ioctl will be removed. | |
| Setting IsSM Capability Bit | |
| To set the IsSM capability bit for a port, simply open the | |
| corresponding issm device file. If the IsSM bit is already set, | |
| then the open call will block until the bit is cleared (or return | |
| immediately with errno set to EAGAIN if the O_NONBLOCK flag is | |
| passed to open()). The IsSM bit will be cleared when the issm file | |
| is closed. No read, write or other operations can be performed on | |
| the issm file. | |
| /dev files | |
| To create the appropriate character device files automatically with | |
| udev, a rule like | |
| KERNEL=="umad*", NAME="infiniband/%k" | |
| KERNEL=="issm*", NAME="infiniband/%k" | |
| can be used. This will create device nodes named | |
| /dev/infiniband/umad0 | |
| /dev/infiniband/issm0 | |
| for the first port, and so on. The InfiniBand device and port | |
| associated with these devices can be determined from the files | |
| /sys/class/infiniband_mad/umad0/ibdev | |
| /sys/class/infiniband_mad/umad0/port | |
| and | |
| /sys/class/infiniband_mad/issm0/ibdev | |
| /sys/class/infiniband_mad/issm0/port |