![]() |
|
||||
LynxOS Networking Guide |
Raw Ethernet Support
Raw Ethernet Support is a facility available with LynxOS used to communicate among nodes over an Ethernet/IEEE 802.3 data link from an application layer. This facility provides for a direct link between application and link layers, and transfers the burden of protocol-related processing to the application level. This implementation facilitates the following interface-specific functions:
- Setting up the interface to allow raw ethernet reception
- Setting up the station address
- Setting up the protocol list
- Setting up the multicast address list
- Setting/resetting the promiscuous reception
- Setting/resetting the interface in blocking mode
- Enabling/disabling interface level debugging
- Getting the interface statistics, current station address and factory address
- Resetting the interface to stop raw ethernet reception
- Filtering the incoming packets with respect to an ethernet header
Raw Ethernet Support
AF_RAWETH Description
AF_RAWETH includes sockets of type SOCK_RAWETH. The raw Ethernet functions are implemented with a set of ioctl calls on a raw Ethernet socket, providing the interface between an application and the Ethernet interface driver.
Multiple sockets can be operating simultaneously in raw Ethernet mode. Many of the operations are restricted to use by a super-user and fail with return -1, if used otherwise. The write and read system calls may be used to send and receive Ethernet packets containing the Ethernet header and data fields. The following is the list of ioctl functions available to the user with which to set up the interface in raw Ethernet mode and communicate among nodes in Ethernet/IEEE 802.3 datalink.
- GE_SET_DEV
- GE_SET_SADDR
- GE_SET_PROTO
- GE_SET_MCAST
- GE_PROM
- GE_BLOCKING
- GE_DEBUG_MODE
- GE_SET_MODE
- GE_GET_CTRS
- GE_GET_SADDR
- GE_GET_FADDR
- GE_CLRIFNAME
- GE_SET_FILTER
The Ethernet driver facilitates simultaneous reception of regular TCP/IP packets (ARP, RARP, and IP type) and processing, in case the Internet support exists. Facilities exist for exclusive reception of all packets through raw Ethernet sockets. The following sections explain each of the ioctl functions.
GE_SET_DEV
To use the interface in raw Ethernet mode, a socket needs to be created in the AF_RAWETH domain of the SOCK_RAWETH type. The returned socket descriptor can be used to set the device in raw Ethernet mode.
This ioctl function sets up the interface to accept raw Ethernet packets. Optionally, this socket can be made to receive TCP/IP packets, where regular TCP/IP processing is suspended until this socket gets closed for processing.
The arguments to this ioctl call, are as follows:
- Interface name
- Maximum queue length for the raw Ethernet interface
- Flag indicating the reception of all packets to raw Ethernet sockets. (flag -RECV_ALL). If this flag is passed, TCP/IP packets are sent to the AF_RAWETH domain to see if a socket is waiting.
Example
int qlen; /* max. Qsize for this interface */
char ename[13]; /* interface name */
int recv_all; ,/* flag indicating the receiving
of all packets to AF_RAWETH domain */
} T_GE_DEV;
int s, ret_val;
T_GE_DEV re_dev;
s = socket(AF_RAWETH, SOCK_RAWETH, 0);
re_dev.qlen = IFQ_MAXLEN; /* num packets to be cached
IFQ_MAXLEN = 50 */
bcopy("wd0", re_dev.ename, sizeof("wd0"));
re_dev.recv_all = 0; /* TCP/IP packets not be
received to this socket */
if ((ret_val = ioctl (s, GE_SET_DEV, &re_dev)) != 0) {
perror("GE_SET_DEV:");
exit(1);
};
This socket descriptor is used for all the raw Ethernet ioctl functions.
Facilities exist for configuring the Ethernet driver and protocol processing code to get rid of TCP/IP processing entirely, such that any packet for this interface is received by a properly matching raw Ethernet socket.
GE_SET_SADDR
This ioctl call is used to change the station address (Ethernet address) of this interface. The address must be 6 bytes long, and the bit-0 of first byte should be zero. This conforms to the Ethernet/IEEE 802.3 specification, which defines the distinction between physical and multicast addresses depending on the bit-0 of the first byte of the node address. The newly set address identifies this node and all packets with this address as the source Ethernet address.
char saddr[6];
saddr[0] = 0xAA; saddr[1] = 00; saddr[2] = 04;
saddr[3] = 00; saddr[4] = 04; saddr[5] = 00;
GE_SET_PROTO
This ioctl facilitates the setting up of the protocol range which the raw Ethernet socket needs to receive. As many as four protocol ranges can be received by each raw Ethernet socket.
typedef struct {
int lowp; /* lower bound protocol type */
int highp; /* upper bound protocol type */
} T_GE_LIST;
typedef struct {
int num_items; /* num entries in list */
T_GE_LIST plist[GE_MAX_PROTO];/* GE_MAX_PROTO=4 */
} T_GE_PROTO;
T_GE_PROTO pr_list;
pr_list.num_items = 2;
pr_list.plist[0].lowp = 0x100;
pr_list.plist[0].highp = 0x125;
pr_list.plist[1].lowp = 0x150;
pr_list.plist[1].highp = 0x175;
GE_SET_MCAST
It is possible to set up a list of multicast addresses which the interface receives as the destination node. Thus, data packets can be sent to a set of nodes, where a certain multicast address is acceptable. This address is used as the destination station address in such packets. According to the IEEE802.3 specifications, a multicast address is identified from the physical address by the D0 bit of the first byte in the 6-byte station address. If this bit is set, it is considered as a multicast address. The interface needs to be programmed to accept a specific multicast address.
int num_items; /* num entries in the list */
char mlist[GE_MAX_MCAST][6]; /* GE_MAX_MCAST=3 */
} T_GE_MCAST;
T_GE_MCAST m_list;
m_list.num_items = 2;
m_list.mlist[0][0] = 0xCF;
m_list.mlist[0][1] = 0;
m_list.mlist[0][2] = 0;
m_list.mlist[0][3] = 0;
m_list.mlist[0][4] = 0;
m_list.mlist[0][5] = 0;
m_list.mlist[1][0] = 0xAB;
m_list.mlist[1][1] = 0;
m_list.mlist[1][2] = 0;
m_list.mlist[1][3] = 3;
m_list.mlist[1][4] = 0;
m_list.mlist[1][5] = 0;
if ((ret_val = ioctl (s, GE_SET_MCAST, &m_list)) != 0) {
perror ("GE_SET_MCAST:");
exit (1);
};
GE_PROM
This ioctl allows the interface to receive all packets, whether or not all packets are destined for that node. Normally, this mode is not set, as it heavily loads the system.
int prom;
prom = 1;
if ((ret_val = ioctl (s, GE_PROM, &prom)) != 0) {
perror ("GE_PROM:");
exit (1);
};
GE_BLOCKING
This call puts the raw Ethernet socket in blocking mode. This call can be made to be blocked or return with error for lack of input in case of read, or for lack of output space in case of write). Note that the flag is set to 0 to put the socket in blocking mode. The example below tests for non-blocking mode.
int donot_block;
donot_block = 1;/* set interface in non-blocked mode */
if ((ret_val = ioctl (s,GE_BLOCKING,&donot_block)) != 0) {
perror ("GE_BLOCKING");
exit (1);
};
GE_DEBUG_MODE
This ioctl call puts the interface in debug mode. The data which transfers through this interface is displayed in the debug terminal.
int debug;
debug = 1;
if ((ret_val = ioctl (s, GE_DEBUG_MODE, &debug)) != 0) {
perror ("GE_DEBUG_MODE:");
exit (1);
};
GE_GET_CTRS
This ioctl call gets the raw Ethernet interface statistics.
typedef struct {
long
last_zeroed, /* unused now */
msg_rcv, /* messages received */
msg_xmt, /* messages transmitted */
byt_rcv, /* bytes received */
byt_xmt, /* bytes transmitted */
xmt_err, /* transmit errors */
msg_no_buff, /* no buffer occurrences */
msg_qfull; /* no of qfull occurrences */
int zero; /* unused now */
} T_GE_CTRS;
T_GE_CTRS ctrs;
if ((ret_val = ioctl (s, GE_GET_CTRS, &ctrs)) != 0) {
perror ("GE_GET_CTRS:");
exit (1);
};
GE_GET_SADDR
This call gets the current station address of the raw Ethernet interface.
char saddr[6];
if ((ret_val = ioctl (s, GE_GET_SADDR, saddr)) != 0) {
perror ("GE_GET_SADDR:");
exit (1);
};
GE_GET_FADDR
This function gets the station address assigned by the manufacturer for the Ethernet interface hardware.
char faddr[6];
if ((ret_val = ioctl (s, GE_GET_FADDR, faddr)) != 0) {
perror ("GE_GET_FADDR:");
exit (1);
};
GE_CLRIFNAME
This ioctl call closes the interface for raw Ethernet reception. It needs to be followed by the closing of the raw Ethernet socket. Note that the flag RECV_ALL needs to be set in the recv_all field, in case that option was chosen while opening this socket.
typedef struct {
int qlen; /* max. Qsize for this interface */
char ename[13]; /* interface name */
int recv_all; /* flag indicating the receiving
all packets to AF_RAWETH domain */
} T_GE_DEV;
int s, ret_val;
T_GE_DEV re_dev;
re_dev.recv_all = 0; /* set to RECV_ALL if set while opening the i/f */
if ((ret_val = ioctl (s, GE_CLRIFNAME, &re_dev)) != 0){
perror ("GE_CLRIFNAME");
exit (1);
};
if (close (s) < 0) {
perror ("close:");
exit (1);
};
GE_SET_FILTER
This ioctl provides filtering for the incoming packets with respect to the Ethernet header (first 14 bytes.) For example, the received packets falling within the protocol range set for this socket are passed through the filter and compared against a given mask. In case of a match, the packet is sent to the socket receive buffer. The argument for this ioctl contains two fields: filter and mask. The bits in the header that are of interest for this socket are set to 1 in the filter field. The bits that are expected to be set (logic 1) in the incoming pattern are reset (set to 0) in the mask field.
The filtering is released by logically EX-NORing the incoming packet header with the filter pattern. The resultant string is logically ORed with the mask pattern. The output pattern is checked to see is all bits are set to 1. If yes, that packet is received in the socket receive buffer.
By default, the filter is deactivated (i.e, there is no filtering on a received packet).
T_GE_FILTER filter;
filter.filter[0] = 0xff; /* Pass the whole */
filter.filter[1] = 0xff; /* header (14 bytes) */
filter.filter[2] = 0xff; /* through the filter. */
filter.filter[3] = 0xff;
filter.filter[4] = 0xff;
filter.filter[5] = 0xff;
filter.filter[6] = 0xff;
filter.filter[7] = 0xff;
filter.filter[8] = 0xff;
filter.filter[9] = 0xff;
filter.filter[10] = 0xff;
filter.filter[11] = 0xff;
filter.filter[12] = 0xff;
filter.filter[13] = 0xff;
filter.mask[0] = ~0xab; /* Mask set for a */
filter.mask[1] = ~0; /* certain pattern of */
filter.mask[2] = ~0; /* destination */
filter.mask[3] = ~3; /* address and source */
filter.mask[4] = ~0; /* address but */
filter.mask[5] = ~0; /* doesn't care for */
filter.mask[6] = ~0; /* protocol field. */
filter.mask[7] = ~0x10; /* Note that the bits */
filter.mask[8] = ~0xc0; /* that are expected */
filter.mask[9] = ~0x40; /* to be 1 are */
filter.mask[10] = ~0xab; /* set to `0' in the */
filter.mask[11] = ~0x66; /* mask and vise-versa.*/
filter.mask[12] = 0xff; /* Do not care for */
filter.mask[13] = 0xff; /* protocol field. */
![]() LynuxWorks, Inc. 855 Branham Lane East San Jose, CA 95138 http://www.lynuxworks.com 1.800.255.5969 |
![]() |
![]() |
![]() |
![]() |