Getting Ethernet Packets under IRIX

From Higher Intellect Wiki
Jump to: navigation, search
This is a draft - as far as I know, everything is accurate, but I still want to flush out some sections. Please let me know if you find any errors.
Notes on the various ways to encapsulate packets on Ethernet.

Encapsulation Specs
RFC-894 Encapsulation
In the beginnning...There was Ethernet packet headers. These had the following format:

+--------+--------+--------+--------+--------+--------+--------+--------+
| Source Ethernet Address
+--------+--------+--------+--------+--------+--------+--------+--------+

+--------+--------+--------+--------+--------+--------+--------+--------+
| Destination Ethernet Address
+--------+--------+--------+--------+--------+--------+--------+--------+
	
+--------+--------+
| Protocol Type   |
+--------+--------+
[RFC 894]. I don't know if there is an official designation for this format; I will use the commonly used phrase: "Ethernet II encapsulation".

802.3 Encapsulation
Then came IEEE 802.3 [RFC 1042]. 802.3 packets start in a similar manner; here's the first 18 octets:

+--------+--------+--------+--------+--------+--------+--------+--------+
| Source Ethernet Address
+--------+--------+--------+--------+--------+--------+--------+--------+

+--------+--------+--------+--------+--------+--------+--------+--------+
| Destination Ethernet Address
+--------+--------+--------+--------+--------+--------+--------+--------+
	
+--------+--------+
| Packet Length   |
+--------+--------+
Note the only difference it that octets 15 & 16 are used to store a packet length rather than a protocol type. This spec uses a clever kludge, based on the following facts, to ensure backwards compatibility with Ethernet II encapsulation:

The maximum length [MTU] of an Ethernet packet is 1500 octets. "The MTU for an Ethernet is 1500 and for 802.3 is 1492" [RFC 1122].
The <Protocol Type> field under Ethernet II encapsulation is always >= 2048 (hex 0x800).
Since the length can't be greater than 1500, packets with a length field greater than 1500 are assumed to be in the older format [see RFC 1122 for a similar discussion].

The above describes the Physical Layer header (and will be different on TokenRing, FDDI etc.). This hardware dependent header is followed by a hardware independent header, called the Logical Link Control [LLC] Sublayer. The LLC header is described by the IEEE 802.2 standard, and has no parallel in the older Ethernet II encapsulation. The LLC header is followed by a 5 byte Sub-Network Access Protocol (SNAP) header. Though they have different names, these 2 headers are usually considered to be a single unit, and I will call them the LLC/SNAP header. Here's what these headers look like:

+--------+--------+--------+
| DSAP=K1| SSAP=K1| Control|                                802.2 LLC
+--------+--------+--------+

+--------+--------+---------+--------+--------+
|Protocol Id or Org Code =K2|    EtherType    |            802.2 SNAP
+--------+--------+---------+--------+--------+

The K1 value is 170 (0xAA).

The K2 value is 0 (3 zero octets).

The control value is 3 (802.2 Type 1 service - Unnumbered Information).
SAP == Service Access Point, hence DSAP == Destination SAP, SSAP == Source SAP.

Getting packets on IRIX
To get 802.2 style packets in an IRIX device driver, you must use the DLSAP interface (assuming you are NOT using the streams based DLPI). I think the best way to illustrate our DLSAP interfaces is with examples. I'll be using AppleTalk as an example.

AARP (AppleTalk Address Resolution Protocol) uses the following 802.2 LLC/SNAP header:


 +--------+--------+--------+--------+--------+--------+--------+--------+
 |   AA   |   AA   |   3    |   0    |    0   |    0   |     0x80F3      | 
 +--------+--------+--------+--------+--------+--------+--------+--------+

AppleTalk uses the following 802.2 LLC/SNAP header:


 +--------+--------+--------+--------+--------+--------+--------+--------+
 |   AA   |   AA   |   3    |   08   |    0   |   07   |     0x809B      |
 +--------+--------+--------+--------+--------+--------+--------+--------+

Here's a code fragment that illustrates how to register these types:

/* Consult The "IRIX Device Driver Programming Guide" for more
details. */

#include <sys/types.h>
#include <sys/mbuf.h>
#include <sys/dlsap_register.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/soioctl.h>

int aarpisr, ddpisr;

/*Input routines takes complete responsibiltiy for
  freeing the mbuf.  If the packet is to be queued
  and/or schednetisr need to be called this is again
  the responsibiltiy of the input routine.  If the
  routine returns zero then the packet will be passed
  to drain (this interface is for internal use only).
  All customers drivers MUST return a non-zero value.
*/

int infunc(dlsap_family_t *dfp, struct ifnet *ifp, struct mbuf *m, void *blif)
{
        if(dfp == &aarp;_dlsap_t) {
                schednetisr(aarpisr);
        } else {
                atalkq = &atintrq2; /* the protocol queue */
                /*
                 * If queue is full, we drop the packet.
                 */
                IFQ_LOCK(atalkq);
                if (IF_QFULL(atalkq)) {
                        m_freem(m);
                        IF_DROP(atalkq);
                        IFQ_UNLOCK(atalkq);
#ifdef DEBUG
                        cmn_err(CE_DEBUG, "atalkinfunc: plop\n");
#endif
                        return(-1);
                }
                IF_ENQUEUE_NOLOCK(atalkq, m);

                IFQ_UNLOCK(atalkq);

                /* XXXX This logic should be changed to use the netatalk paradigm
                   (i.e. calling aarpinput routine directly for AARP packets). */
                schednetisr(ddpisr);
	}
	return 1;
}

dlsap_family_t aarp_dlsap_t = {
	AF_UNSPEC,
	0x80F3,
	DL_SNAP0_ENCAP, /* Product Id field in SNAP is NULL */
	infunc,
	0,
	aarpnetisr
};

dlsap_family_t ddp_dlsap_t = {
	AF_UNSPEC,
	170,
	DL_LLC_ENCAP,
	infunc,
	0,
	ddpnetisr
};

/* ... */

registerservices()
{
	dlsap_family_t *dummy;

	aarpisr = register_dlsap(&aarp_dlsap_t, &dummy);
	ddpisr = register_dlsap(&ddp_dlsap_t, &dummy);
}

struct ifqueue atalkintrq;

atalk_input()
{
	struct ifqueue *atalkq;

	atalkq = &atalkintrq; /* the protocol queue */ 
	/*
	 * If queue is full, we drop the packet.
	*/
	ATALKQ_LOCK(atalkq);
	if (IF_QFULL(atalkq)) {
		m_freem(m);
		IF_DROP(atalkq);
		ATALKQ_UNLOCK(atalkq);
		return(-1);
	} 
	IF_ENQUEUE_NOLOCK(atalkq, m);
	if(aarppacket)
        	schednetisr(aarpisr);
	else
        	schednetisr(ddpisr);
	ATALKQ_UNLOCK(atalkq);
	return(0);
}

atalkinit(void)
{
}

atalkunload(void)
{
}

DDP uses another scheme, with a non-NULL organization field, that I haven't figured out yet ;^)

Notes
"AppleTalk packet" is really synonymous with "DDP packet" (Datagram Delivery Protocol), as that is the only protocol carried over AppleTalk.
0x809B is the EtherType code assigned to AppleTalk [RFC 1700].
0x80F3 is the is the EtherType code assigned to AARP [RFC 1700].
0x80007 is Apple's vendor code (the code assigned by the IEEE and used as the first 6 bytes of the Ethernet address for adapters manufactured by Apple) [Ethernet Numbers]. I don't know why this code is used for AppleTalk packets but not AARP packets (if you do, please let me know).


Share your opinion