Table of Contents

Name

linx - The LINX for Linux communication protocol

Synopsis

#include <linx.h>
#include <linx_socket.h>
#include <linx_ioctl.h>
#include <linx_types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

Description

The LINX for Linux is an implementation of the Enea OSE Delta and OSEck messaging API, adapted for Linux. The implementation needs to be efficient and able to access kernel resources such as drivers. A new socket protocol family called LINX, identified by the name AF_LINX/PF_LINX, is implemented that provides the functionality of the OSE messaging API in the LINX Socket API. The liblinx library provides the LINX API high level messaging functions, above the LINX Socket API. This library is linked with each application that uses the messaging API. The library contains function for sending, receiving and other operations, similar to the OSE / OSEck functions.

As the OSE messaging API implementation is different from the OSE implementation, some OSE concepts need to be adapted to the socket environment. This is an overview of how OSE concepts are adapted to LINX and how that affects terminology and characteristics.

The main difference in terminology is that in OSE a process is the communicating endpoint, while in LINX for Linux, a process can open and close several LINX endpoints. In addition, the word signal in OSE always means signal buffer. indicating a data buffer to transfer, which includes a signal number. A signal buffer in LINX (or just signal in OSE) has nothing to do with a POSIX signal.

Linx Acronyms

· In LINX for Linux, a LINX endpoint is the communicating endpoint. A LINX endpoint owns signal buffers, sends and receives them and the owned signal buffers have the same lifetime as the LINX endpoint (unless sent to another endpoint). The LINX endpoint can be supervised from other endpoints and have a name, to be hunted for and the endpoint can be supervised from other endpoints which attached to it. A LINX endpoint is created and destroyed by a process and a process can own multiple LINX endpoints. A Linux process accesses a LINX endpoint via a LINX handle, returned when the endpoint is created.

· The unique binary identifier (spid) of a LINX endpoint is used in the API for directly accessing it from other endpoints. Signal buffers are sent/received using the spid identifiers. This spid is unique in the local node.

· A LINX endpoint has a non-unique name (a string), called hunt name, that can be hunted for, to get the spid for use in communication.

· A link in LINX is a communication link between two nodes, transparently handling the communication with remote LINX endpoints. Each LINX link to another node has a link name. The link can, and usually have, different names on the opposite nodes, e.g. "LinkToA" and "LinkToB" for a link between A and B.

· To hunt for a LINX endpoint in another node, prepend a suitable path of link names before the name. When the hunt is resolved, a local (phantom) LINX endpoint with a local spid is available for communicating with the remote LINX endpoint. This allows transparent communication with local or remote LINX endpoints, using locally unique spids.

· When a LINX endpoint is opened (created), pending hunts to its name are resolved.

· When a LINX endpoint is closed (destroyed), its owned signal buffers are automatically freed.

· When a LINX endpoint is closed (destroyed), attach signals are sent to any other LINX endpoints that have attached to it (are supervising it), except if the LINX endpoint is owned also by other Linux processes that is still active.

· When a Linux process is killed, all its resources are removed, including resources of any open LINX endpoints, causing all its LINX endpoints to be closed as described above.

· When a Linux process that has opened LINX endpoints, is forked, all its socket related resources are cloned, including LINX endpoint resources, causing the LINX endpoint to be owned by more than one process. Either the parent or the child must close a LINX endpoint, as a LINX endpoint cannot be used by more than one process. A LINX endpoint needs to be closed by all owners before it is removed and attachments are triggered.

· For efficiency, it is permitted to send messages to the ID (spid) of a not-yet existing LINX endpoint. However in LINX it is considered an error to attempt to send a message to a LINX endpoint that have been closed (or a remote endpoint to which the link has been broken). Such an endpoint is called a zombie, as information is saved for used LINX endpoints (until overflow in a counter causes reuse of entries).

LINX for Linux Application Interfaces

The LINX for Linux has two distinct APIs, the LINX API and the LINK Socket API.

a) The LINX API is an application API in the liblinx library, to be linked into the application. It implements functions similar to the OSE Delta and OSEck message passing API. The LINX API is specified in linx.h(3) and in other linx* man-pages. The LINX API implements more features on top of the LINX Socket API and an endpoint created by the LINX API contains more resources in addition to the LINX socket.

b) The LINX Socket API is the underlying socket implementation of the message passing interface and is used by the LINX library. The LINX Socket API is described below.

LINX_SIGSELECT and Signal Numbers


A signal buffer contains a signal number and the actual payload contents. The signal numbers are mainly application specific, but a few are reserved. Zero (0) must not be used, it is illegal, and 252-255 are reserved for LINX, e.g. hunt, attach, etc. A signal buffer with a signal number has a unique structure declaration of which the first member is the necessary signal number, followed by all the signal's possible data fields. The signal number must be of type LINX_SIGSELECT. When a pointer to any type of signal buffer is needed, use the opaque typedef LINX_SIGNAL *.

Ose Acronyms

· The OSE process is the communicating endpoint. It owns signal buffers, sends and receives them and the owned signal buffers have the same lifetime as the OSE process (unless sent to another process). The OSE process has a name that can be hunted for and the process can be supervised from other processes which attaches to it.

· The unique OSE process ID (pid) is used to directly send/receive signal to/from another process. The pid is unique in the node.

· In OSE, a link handler transparently handles communication with processes in other nodes, using local phantom processes representing each remote process, after resolving hunt requests. The local phantom processes have local pids. This allows transparent communication with local or remote processes, using locally unique pids.

· An OSE process has a none-unique name (a string) that can be hunted for. To hunt for a process in another node, prepend a suitable path of link names before the name. When the hunt is resolved, a local pid is available for communicating with the remote process.

· When an OSE process is created, pending hunts to its name are resolved.

· When an OSE process is killed, its owned signal buffers are automatically freed (not always true for OSEck processes).

· When an OSE process is killed, attach signals are sent to any other OSE processes that have attached to it (are supervising it).

· In OSE it is permitted both to send messages to the pid of a not-yet existing process and to send messages to a killed process (or a remote process to which the link has been broken).

LINX Socket API

The LINX Socket API allows application writers to access LINX through the LINX socket interface. However, it is recommended to use the LINX API as much as possible becauce it simplifies for the programmer by abstracting parts of the socket interface. Programmers, using sockets for other protocols, should note that only a subset, suitable for LINX, of the socket calls are implemented and that some features have been added, not provided by the ordinary socket paradigm (mainly through ioctl calls). These deviations and new features are described below.

The payload transferred between LINX sockets, must be a signal buffer, containing 4 leading bytes with a 32-bit signal number, optionally followed by any data.

struct sockaddr_linx


When using the LINX Socket API directly, a struct sockaddr_linx struct is needed in each socket call. It contains the identifier, spid, of a LINX endpoint. When passing a sockaddr_linx struct to the socket functions, it shall be type-casted into a generic struct sockaddr.

The struct is defined as:


struct sockaddr_linx {
  sa_family_t family;
  LINX_SPID   spid;
};

Where family must be AF_LINX and spid is a non-zero LINX endpoint identifier.

The following socket API calls are supported by LINX sockets:

socket()
A LINX socket is created by calling the socket(2) function as socket(PF_LINX, SOCK_DGRAM, 0) which returns a socket descriptor (sd). The protocol family is PF_LINX, The socket type is SOCK_DGRAM and the protocol is 0. No other options are supported. To bind a huntname to a socket, use the ioctl(sd, LINX_IOCTL_HUNTNAME, huntname) call, where huntname is a name string (corresponding to the name of the own LINX endpoint, when using LINX API). When sending messages to other LINX sockets, the binary identifier of the target endpoint, called spid, is needed. The target spid is acquired by performing a hunt for the target huntname, using ioctl(sd, LINX_IOCTL_HUNT, huntname). A message containing the spid is received, when the target LINX endpoint, hunted for, is ready. The spid can then be placed in a sockaddr_linx struct and passed as an argument to all following sendto(2) or sendmsg(2) . At error, -1 is returned and errno can be one of the following errors:

EPROTONOTSUPPORTED
A socket(2) call was directed to the LINX protocol stack with the wrong protocol family. Only PF_LINX is accepted.

ESOCKTNOSUPPORT
SOCK_DGRAM was not used as socket type.

ENOMEM
There are not enough memory resources to create the socket. Alternatively too many sockets were created, the maximum is set by Linux and not the LINX implementation.

sendto()
This function is called as sendto(sd, payload, size, 0, (struct sockaddr*) &sockaddr_linx, sizeof(struct sockaddr_linx)). The payload buffer shall contain the signal buffer to transfer and size shall be its size in bytes. The sockaddr_linx struct shall contain the target LINX endpoint spid. The flags field of the sendto(2) call should be set to zero. At success, the transferred size is returned, otherwise -1 is returned and errno can be one of the following errors:

EBADF
The sd is an invalid socket descriptor.

EINVAL
One or more of the arguments are invalid.

ENOMEM
The system is lacking memory resources to send the signal.

EOPNOTSUPP
The sending socket is not bound or the to spid is invalid.

EMSGSIZE
The size of the signal is not possible to send.

sendmsg()
This function is called as sendmsg(sd, *msg, 0). The msg is a struct msghdr message header with information, according to sendmsg(2) . The signal buffer (payload) should be placed in a struct iovec and its pointer placed in the msg_iov field of the message header. The msg_iovlen field should be set to 1 (number of elements in the iovec array). A pointer to the sockaddr_linx struct, with the target spid, shall be placed in the msg_name field of a message header and the msg_namelen field be set to sizeof(struct sockaddr_linx) . The sockaddr_linx structure should contain the spid of the receiving endpoint. The ancillary fields and the flags field of the message header shall not be used and set to zero. At success, the transferred size (signal buffer size) is returned, otherwise -1 is returned and errno can be one of the following errors:


EBADF
The sd is an invalid socket descriptor.

EINVAL
One or more of the arguments are invalid.

ENOMEM
The system is lacking memory resources to send the signal.

EOPNOTSUPP
The sending socket is not bound or the target spid is invalid.

EMSGSIZE
The size of the signal is not possible to send.

recvfrom()
This function is called as recvfrom(sd, payload, size, 0, (struct sockaddr*) &sockaddr_linx, sizeof(struct sockaddr_linx)). It is used to receive any message (signal buffer) from any LINX endpoint through this socket. recvfrom can only be used when no signal number filtering and no sender filtering is needed. The first signal buffer in the socket's receive queue is returned in the payload buffer, otherwise the call blocks until a signal buffer is received. The sender of the signal is returned in the sockaddr_linx structure. The recvfrom(2) function's flags parameter shall always be set to zero. The payload size must be at least 4 bytes large. If the recvfrom(2) call fails, because the received signal buffer does not fit in the provided buffer, zero is returned and the actual size of the signal buffer, to receive, is written as a 32-bit value in the first 4 bytes of the provided payload buffer. At success, the transferred size (signal buffer size) is returned, otherwise -1 is returned and errno can be one of the following errors:

EBADF
The sd is an invalid socket descriptor.

EINVAL
One or more of the arguments are invalid.

ENOMEM
The system is lacking memory resources to receive the signal.

EOPNOTSUPP
The receiving socket is not bound or an unsupported flag in flags caused the error.

recvmsg()
This function is called as recvmsg(sd, *msg, 0). The msg is a struct msghdr message header, according to recvmsg(2) , which is very flexible in its design and makes it possible to pass any parameter to the call. The recvmsg(2) is adaptable to different address and protocol family implementations. The LINX socket implementation uses the ancillary data fields of the message header to pass signal number filtering and sender filtering information. The payload (signal buffer) size must be at least 4 bytes, in a struct iovec pointed to from the message header. If the recvfrom(2) call fails because the received signal buffer does not fit in the provided buffer, zero is returned and the actual size of the signal buffer, to receive, is written as a 32-bit value in the first 4 bytes of the provided payload buffer.

The filtering, using ancillary fields in the message buffer in the recvmsg(2) function, is described by the following example code:


struct msghdr msg;
char cmsg[CMSG_SPACE(sizeof(struct linx_receive_filter_param))];
struct linx_receive_filter_param * rfp;
struct iovec iov;

rfp = ((struct linx_receive_filter_param *)
        (CMSG_DATA(((struct cmsghdr *)cmsg))));
rfp->sigselect_size = LINX_SIGSELECT_ARRAY_SIZE(sig_sel);
rfp->from = from;
rfp->sigselect = sig_sel;
msg.msg_name = (void*)&linx_addr;
msg.msg_namelen = sizeof(struct sockaddr_linx);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = cmsg;
msg.msg_controllen = 
        CMSG_SPACE(sizeof(struct linx_receive_filter_param));
((struct cmsghdr *)cmsg)->cmsg_len = msg.msg_controllen;
((struct cmsghdr *)cmsg)->cmsg_level = 0;
((struct cmsghdr *)cmsg)->cmsg_type = 0;
iov.iov_base = *signal;
iov.iov_len = sigsize;
read_size = recvmsg(linx->socket, &msg, 0);

Where struct linx_receive_filter_param has the following structure:


struct linx_receive_filter_param {
  LINX_SPID             from;
  const LINX_SIGSELECT *sigselect;
  LINX_OSBUFSIZE        sigselect_size;
};

The from parameter specifies is the only signals from a specific SPID should be received and sigselect is an array of LINX_SIGSELECT filters and sigselect_size is the size of the array in bytes.

At success, the recvmsg(2) returns transferred size (signal buffer size), otherwise -1 is returned and errno can be one of the following errors:

EBADF
The sd is an invalid socket descriptor.

EINVAL
One or more of the arguments are invalid.

ENOMEM
The system is lacking memory resources to receive the signal.

EOPNOTSUPP
The receiving socket is not bound or an unsupported flag in flags caused the error.

poll()
It is possible to do poll(2) on a LINX socket. This returns a bitmask that indicates the state of the receiving queue. The following possible bits can be set at return from this function; POLLERR if the LINX socket is in an error state, POLLHUP if the LINX socket has been shutdown/released, POLLIN and POLLRDNORM if the LINX socket has data to read in receive queue. On error, -1 is returned and errno can be:

EBADF
An invalid socket descriptor is part of a fd_set.

ENOMEM
Out of memory resources.

EINVAL
Bad input parameters.

select()
There are situations where it is needed to use a combination of the LINX API and the LINX socket API, for instance when there is a need for simultaneous usage of several LINX endpoints and/or other types of socket descriptors. In that case the LINX API function linx_get_descriptor(3) can be used to get the underlying socket descriptor for a LINX endpoint, created by linx_open(3) . However, never close a socket descriptor from linx_get_descriptor(3) with the socket close(2) function! As example, this LINX socket descriptor can be used together with other socket descriptors in a generic poll(2) or select(2) call. If a state change occurs in a socket with a descriptor associated with a LINX endpoint, the LINX API functions can be used for actions on the corresponding LINX endpoint, or the LINX socket API could be used directly on the socket descriptor. On error, -1 is returned and errno can be:

EBADF
An invalid socket descriptor is part of a fd_set.

ENOMEM
Out of memory resources.

EINVAL
Bad input parameters.

ioctl()
With ioctl(sd, request, ...), special requests are sent to a LINX socket. See below for all IOCTL request codes, supported by LINX sockets. At success, 0 is returned, otherwise -1 is returned and errno can be one of the following errors:

EBADF
fd is an invalid socket descriptor.

ENOMEM
Out of memory resources.

EINVAL
Bad input parameters.

close()
A LINX socket created by a socket(2) call can be closed with close(2) . Note: Never use this function on a LINX socket descriptor returned from the LINX API function linx_get_descriptor(3) on a LINX endpoint created with linx_open(3) . Such a LINX endpoint must be closed with linx_close(3) . At success, 0 is returned, otherwise -1 is returned and errno can be one of the following errors:

EBADF
fd is an invalid socket descriptor.

Only the calls described above are supported by a LINX socket. The following are NOT supported on a LINX socket and should never be used: bind(2) , connect(2) , socketpair(2) , accept(2) , getname(2) , listen(2) , shutdown(2) , setsockopt(2) , getsockopt(2) , mmap(2) and sendpage(2) .

IOCTL Request Codes supported in LINX

These ioctls can be accessed using ioctl(2) on LINX sockets.

LINX_IOCTL_HUNTNAME

Sets the huntname of the own LINX socket sd and returns its binary LINX endpoint identifier, the spid. The correct syntax is:


struct linx_huntname *huntname;
error = ioctl(sd, LINX_IOCTL_HUNTNAME, huntname);

The huntname parameter is a struct linx_huntname with the following fields:


struct linx_huntname {
  /* Input parameters */
  size_t     namelen;
  char      *name;
  /* Output parameters */
  LINX_SPID  spid;
};

Where namelen is the size in bytes of the string name that contains the huntname to assign to the socket. At successful return, the spid is set to the SPID of the socket.

LINX_IOCTL_HUNT

Hunts for another LINX socket, that has a huntname, to get its spid, used to communicate with it. The correct syntax is:


struct linx_hunt_param *hunt_param;
error = ioctl(sd, LINX_IOCTL_HUNT, hunt_param);

The hunt_param parameter is a struct linx_hunt_param with the following fields:


struct linx_hunt_param {
  /* Input parameters */
  LINX_OSBUFSIZE     sigsize;
  union LINX_SIGNAL *sig;
  LINX_SPID          from;
  size_t             namelen;
  char              *name;
  /* Output parameter */
  LINX_SPID          spid;
};

Where sigsize is the size of the hunt signal buffer sig, to be sent back when the hunted other LINX socket is available. If no signal is provided ( sig is NULL and sigsize is zero) the LINX default hunt signal will be used. The from parameter must be set to the owner of the hunt. The normal case is to set this to the same SPID as the LINX socket in the sockaddr_linx. It is always the LINX socket in the sockaddr_linx that receives the hunt signal if such is provided but if the from parameter is set to the SPID of another LINX socket the hunt is canceled if that socket is closed. The namelen is the size in bytes of the string name that contains the huntname of the other LINX socket to be hunted. At return, the spid parameter will be set to the SPID of the hunted socket, if the socket already exists locally, but if a hunt signal is provided it will also be sent. Otherwise spid is LINX_ILLEGAL_SPID at return from the hunt call.

LINX_IOCTL_ATTACH

Attaches this LINX socket to another LINX socket to supervise it, i.e. to get an attach signal if/when it disappears. The correct syntax is:


struct linx_attach_param *attach_param;
error = ioctl(sd, LINX_IOCTL_ATTACH, attach_param);

The attach_param parameter is a struct linx_attach_param with the following fields:


struct linx_attach_param {
  /* Input parameters */
  LINX_SPID          spid;
  LINX_OSBUFSIZE     sigsize;
  union LINX_SIGNAL *sig;
  /* Output parameter */
  LINX_OSATTREF      attref;
};

Where spid is the spid of the LINX socket to supervise and sigsize is the size of the attach signal buffer sig, to be sent back when the supervised LINX socket becomes unreachable. If sig is NULL, the LINX default attach signal will be used. The attref is an attach reference, returned, to be used in any later LINX_IOCTL_DETACH.

LINX_IOCTL_DETACH

Detaches from another LINX socket, i.e. stops supervising it. The correct syntax is:


struct linx_detach_param *detach_param;
error = ioctl(sd, LINX_IOCTL_DETACH, detach_param);

The detach_param parameter is a struct linx_detach_param with the following fields:


struct linx_detach_param {
  LINX_OSATTREF      attref;
};

Where attref is the attach reference, that was returned from LINX_IOCTL_ATTACH, indicated which attach to remove.

LINX_IOCTL_SET_RECEIVE_FILTER

This is used to setup a receive filter prior to a select(2) call. The correct syntax is:


struct linx_receive_filter_param *rfp;
error = ioctl(sd, LINX_IOCTL_SET_RECEIVE_FILTER, rfp);

The struct linx_receive_filter_param has the following fields:


struct linx_receive_filter_param {
  /* Input parameters */
  LINX_SPID             from;
  const LINX_SIGSELECT *sigselect;
  LINX_OSBUFSIZE        sigselect_size;
};

Where from is one spid of the another LINX socket, to receive from and sigselect_size is the size of the sigselect array in bytes. The sigselect is a pointer to an array of signal numbers.

LINX_IOCTL_REGISTER_LINK_SUPERVISOR

This is used to supervise a LINX link between two nodes. The correct syntax is:


error = ioctl(sd, LINX_IOCTL_REGISTER_LINK_SUPERVISOR, 0);

When a LINX link is created to any other node, a signal will be sent to all LINX sockets, that have registered as link supervisors. The signal buffer will have the format:


struct linx_new_link {
  LINX_SIGSELECT signo;
  char           name[1];
};

Where signo is LINX_OS_LINK_SIG and name is a null terminated string, containing the link name of the newly created link. To be notified when a link dies a LINX_IOCTL_HUNT can be performed on the name which returns the SPID of the LINX socket representing the link, then do an LINX_IOCTL_ATTACH to that SPID to get notified when the link is destroyed.

LINX_IOCTL_UNREGISTER_LINK_SUPERVISOR

This is used to stop supervising LINX links. The correct syntax is:


error = ioctl(sd, LINX_IOCTL_UNREGISTER_LINK_SUPERVISOR, 0);

LINX_IOCTL_VERSION

This is used to find out the version of the installed LINX kernel module. The correct syntax is:


unsigned int version;
error = ioctl(sd, LINX_IOCTL_VERSION, &version);

Where version will contain the version of the LINX kernel module when the ioctl(2) call returns. The LINX version number is a 32 bit number, composed of an 8-bit major version, an 16-bit minor version, and a 8-bit seq (patch) number.

LINX_IOCTL_INFO

This is used to get different kinds of information from the LINX kernel module. The correct syntax is:


struct linx_info info;
error = ioctl(sd, LINX_IOCTL_INFO, &info);

The info parameter is a struct linx_info with the following fields:


struct linx_info {
  int    type;
  void *type_spec;
};

Where type indicates what kind of information is requested from the kernel and type_spec is a pointer to a struct that will contain input and return parameters for the ioctl call. The different kinds of information that can be retrieved from the LINX kernel module are:

LINX_INFO_SUMMARY


Provides a summary of the most important information from the LINX kernel module.


struct linx_info info;
struct linx_info_summary info_summary;
info.type = LINX_INFO_SUMMARY;
info.type_spec = &info_summary;

The struct linx_info_summary has the following structure:


struct linx_info_summary {
  /* Output parameters */
  int no_of_local_sockets;
  int no_of_remote_sockets;
  int no_of_link_sockets;
  int no_of_pend_attach;
  int no_of_pend_hunt;
  int no_of_queued_signals;
};

Where no_of_local_sockets is the number of LINX sockets open locally, no_of_remote_sockets is the number of phantom sockets opened internally by the LINX kernel module, representing remote LINX sockets and no_of_link_sockets is the number of sockets opened, representing LINX links to other nodes. The no_of_pend_attach is the number of pending attaches, no_of_pend_hunt is the number of pending hunts and no_of_queued_signals is the number of queued signals.

LINX_INFO_SOCKETS


Returns the number of opened LINX sockets and their LINX endpoint identifiers (spids).


struct linx_info info;
struct linx_info_sockets info_sockets;
info.type = LINX_INFO_SOCKETS;
info.type_spec = &info_sockets;

The struct linx_info_sockets has the following fields:


struct linx_info_sockets {
  /* Input parameters */
  LINX_OSBOOLEAN local;
  LINX_OSBOOLEAN remote;
  LINX_OSBOOLEAN link;
  /* Output parameter */
  int            no_of_sockets;
  /* Input parameter */
  int            buffer_size;
  /* Output parameters */
  LINX_SPID     *buffer;
};

If local is true, local sockets are included in the output, if remote is true, remote sockets are included and if link is true, LINX links are included. The number of LINX sockets matching the search is returned in no_of_sockets and the array of spids is returned in the preallocated buffer. of size buffer_size bytes. However, if the given buffer_size in bytes is too small, not all sockets will be reported in the buffer.

LINX_INFO_TYPE


Returns the type of any given LINX socket endpoint.


struct linx_info info;
struct linx_info_type info_type;
info.type = LINX_INFO_TYPE;
info.type_spec = &info_type;

The struct linx_info_type has the following fields:


struct linx_info_type {
  /* Input parameter */
  LINX_SPID spid;
  /* Output parameter */
  int       type;
};

Where spid is the identifier of the LINX socket endpoint, for which the type is requested. The type of the socket is returned in type. A LINX socket type can be one of: LINX_TYPE_UNKNOWN, LINX_TYPE_LOCAL, LINX_TYPE_REMOTE, LINX_TYPE_LINK, LINX_TYPE_ILLEGAL or LINX_TYPE_ZOMBIE.

LINX_INFO_STATE


Returns the state of any given LINX socket endpoint.


struct linx_info info;
struct linx_info_state info_state;
info.type = LINX_INFO_STATE;
info.type_spec = &info_state;

The struct linx_info_state has the following fields:


struct linx_info_state {
  /* Input parameter */
  LINX_SPID spid;
  /* Output parameter */
  int       state;
};

Where spid is the identifier of the LINX socket endpoint, for which the state information is requested. The state of the socket is returned in state. A LINX socket state can be one of: LINX_STATE_UNKNOWN, LINX_STATE_RUNNING, LINX_STATE_RECV or LINX_STATE_POLL.

LINX_INFO_FILTERS


Returns information about the receive signal filters issued from any given LINX socket endpoint.


struct linx_info info;
struct linx_info_filters info_filters;
info.type = LINX_INFO_FILTERS;
info.type_spec = &info_filters;

The struct linx_info_filters has the following fields:


struct linx_info_filters {
  /* Input parameter */
  LINX_SPID       spid;
  /* Output parameters */
  LINX_SPID       from_filter;
  int             no_of_sigselect;
  /* Input parameter */
  int             buffer_size;
  /* Output parameter */
  LINX_SIGSELECT *buffer;
};

Where spid is the identifier of the LINX socket endpoint, for which the receive filter is requested. If this socket has setup a receive filter, only accepting signal buffers from a specific other LINX socket endpoint, its spid is returned in the from_filter. The number of sigselect signal numbers (filter accepting only these signal buffers), is returned in no_of_sigselect and an array of these signal numbers are returned in the preallocated buffer. The buffer_size is the size in bytes of the buffer. If the buffer is too small, not all filter signals are reported in the buffer.

LINX_INFO_RECV_QUEUE


Returns the receive queue of any given LINX socket endpoint.


struct linx_info info;
struct linx_info_recv_queue info_recv_queue;
info.type = LINX_INFO_RECV_QUEUE;
info.type_spec = &info_recv_queue;

The struct linx_info_recv_queue has the following fields:


struct linx_info_recv_queue {
  /* Input parameter */
  LINX_SPID                spid;
  /* Output parameters */
  int                      no_of_signals;
  /* Input parameter */
  int                      buffer_size;
  /* Output parameter */
  struct linx_info_signal *buffer;
};

Where spid is the identifier of the LINX socket, for which the receive queue is requested. The number of signals in the queue is returned in no_of_signals. An array with queue information is returned in the preallocated buffer. The buffer_size is the size in bytes of the buffer. If the buffer is too small, not all signals are reported in the buffer. Each struct linx_info_signal has the following fields:


struct linx_info_signal {
  LINX_SIGSELECT signo;
  int            size;
  LINX_SPID      from;
};

Where signo is the signal number, size is the size in bytes of the signal and from is the SPID of the sending LINX socket.

LINX_INFO_PEND_ATTACH


Returns the number of attaches from or to any LINX socket endpoint.


struct linx_info info;
struct linx_info_pend_attach info_pend_attach;
info.type = LINX_INFO_PEND_ATTACH;
info.type_spec = &info_pend_attach;

The struct linx_info_pend_attach has the following fields:


struct linx_info_pend_attach {
  /* Input parameters */
  LINX_SPID                spid;
  int                      from_or_to;
  /* Output parameter */
  int                      no_of_attaches;
  /* Input parameter */
  int                      buffer_size;
  /* Output parameter */
  struct linx_info_attach *buffer;
};

Where spid is the identifier of the LINX socket, for which attach informations is requested. If from_or_to is set to LINX_ATTACH_FROM then information about attaches from the spid is returned else if it is set to LINX_ATTACH_TO then information about attaches to the spid is returned. The number of attaches to/from the spid is returned in no_of_attaches, Information about the attaches are returned in the preallocated buffer. The buffer_size is the size in bytes of the buffer. If the buffer is too small, not all attaches are reported in the buffer. Each struct linx_info_attach has the following fields:


struct linx_info_attach {
  /* Input parameter*/
  LINX_SPID               spid;
  /* Output parameters */
  LINX_OSATTREF           attref;
  struct linx_info_signal attach_signal;
};

Where spid is the identifier of the LINX socket that has attached to us or we have attached to depending what from_or_to is set to. The attref is the attach reference and attach_signal is the attach signal.

LINX_INFO_PEND_HUNT


Returns the pending hunts issued from any LINX socket endpoint.

struct linx_info info;
struct linx_info_pend_hunt info_pend_hunt;
info.type = LINX_INFO_PEND_HUNT;
info.type_spec = &info_pend_hunt;

The struct linx_info_pend_hunt has the following fields:


struct linx_info_pend_hunt {
  /* Input parameters */
  LINX_SPID              spid;
  /* Output parameters */
  int                    no_of_hunts;
  /* Input parameter */
  int                    buffer_size;
  /* Output parameters */
  int                    strings_offset;
  struct linx_info_hunt *buffer;
};

Where spid is the identifier of the LINX socket endpoint, that has issued the hunts. The number of pending hunts is returned in no_of_hunts and information about each pending hunt is returned in the preallocated buffer. The buffer_size is the size in bytes of the buffer. If the buffer is too small, not all hunts are reported in the buffer. The strings_offset is the offset into the buffer where the name strings are stored. Each struct linx_info_hunt has the following fields:


struct linx_info_hunt {
  struct linx_info_signal hunt_signal;
  LINX_SPID               owner;
  char                   *hunt_name;
};

Where owner is the the pending hunt and hunt_name is a pointer to the string containing the name of the LINX socket that is hunted for. The hunt_signal is the hunt signal. The linx_info_signal structure is described under LINX_INFO_RECV_QUEUE.

LINX_INFO_SIGNAL_PAYLOAD


Returns the payload of a signal, owned by any LINX socket endpoint.

struct linx_info info;
struct linx_info_signal_payload info_signal_payload;
info.type = LINX_INFO_SIGNAL_PAYLOAD;
info.type_spec = &info_signal_payload;

The struct linx_info_signal_payload has the following fields:


struct linx_info_signal_payload {
  /* Input parameters */
  LINX_SPID               spid;
  struct linx_info_signal signal;
  /* Output parameter */
  int                     payload_size;
  /* Input parameter */
  int                     buffer_size;
  /* Output parameter */
  char                   *buffer;
};

Where spid is the identifier of the LINX socket endpoint, owning the signal and signal is a linx_info_signal structure returned from a previous LINX_INFO call. The signal buffer will be returned in the preallocated buffer. The buffer_size is the size in bytes of the buffer. If the provided buffer is too small, only the beginning of the signal buffer is returned. The payload_size shows the size in bytes of the returned signal payload. If the provided buffer is larger than the signal payload then payload_size will be less then buffer_size. If no signal payload matching the signal then payload_size will be set to zero.

LINX_INFO_NAME


Returns the name of the LINX socket endpoint.


struct linx_info info;
struct linx_info_name info_name;
info.type = LINX_INFO_NAME;
info.type_spec = &info_name;

The struct linx_info_name has the following fields:


struct linx_info_name {
  /* Input parameters */
  LINX_SPID spid;
  int       namelen;
  /* Output parameter */
  char     *name;
};

Where spid is the identifier of the LINX socket endpoint and namelen is the length of the provided buffer name in which the name of the LINX socket endpoint will be returned.

LINX_INFO_OWNER


Returns the owning process (PID) of any LINX socket endpoint.


struct linx_info info;
struct linx_info_owner info_owner;
info.type = LINX_INFO_OWNER;
info.type_spec = &info_owner;

The struct linx_info_owner has the following fields:


struct linx_info_owner {
  /* Input parameter */
  LINX_SPID spid;
  /* Output parameter */
  pid_t     owner;
};

Where spid is the identifier of the LINX socket endpoint and the PID of the owning process is returned in owner.

Known Bugs

None.

See Also

Generic LINX for Linux man-page:
linx(7) (this document)

LINX API man-pages (if only LINX API is used, only linx.h needs to be included by applications):
linx.h(3) , linx_types.h(3) ,
linx_alloc(3) , linx_attach(3) , linx_close(3) ,
linx_create_eth_link(3) , linx_destroy_eth_link(3) , linx_detach(3) ,
linx_free_buf(3) , linx_free_name(3) , linx_get_descriptor(3) ,
linx_get_name(3) , linx_get_spid(3) , linx_hunt(3) ,
linx_hunt_from(3) , linx_open(3) , linx_receive(3) ,
linx_receive_from(3) , linx_receive_w_buf(3) , linx_receive_w_tmo(3) ,
linx_send(3) , linx_send_w_s(3) , linx_sender(3) ,
linx_set_sigsize(3) , linx_sigsize(3) , linxdisc(8) ,
linxdisc.conf(5) , linxcfg(1) , linxstat(1)

Related generic Linux man-pages:
socket(2) , close(2) , sendto(2) , sendmsg(2) , recvfrom(2) , recvmsg(2) , poll(2) , select(2) , ioctl(2)

Author

Enea LINX team

Copyright

Copyright (c) 2006-2007, Enea Software AB All rights reserved.

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. Neither the name of Enea Software AB nor the names of its contributors may 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.


Table of Contents