Subject: Implementation of RFC 1201 arcnet
To: None <Chris_G_Demetriou@LAGAVULIN.PDL.CS.CMU.EDU>
From: Ignatios Souvatzis <ignatios@cs.uni-bonn.de>
List: tech-net
Date: 03/12/1995 17:01:03
cgd answered:

   > I'm working on the implementation of the newer RFC 1201 method of IP over
   > ARCnet, which does link level fragmentation and reassembly.

   hmm.  i think i'd call that "cute."  8-)

   I just looked up the relevant RFCs, and i can confidently say that my
   stomach is not any better off for it.  8-)

   > Unfortunately, the header format (but also packet type number) is changed 
   > wrt. RFC 1051.

   You mean the "protocol ID" number (as described in 1201)?

   > My idea was to make the format switchable through the
   > link0 flag.

   This seems like it could be reasonable; have arc_output switch on that
   type, and DTRT with the packets...

   > I would like to keep the details of header coding out of the hardware
   > drivers as much as possible. So, I would 
   > 
   > - add a 
   > 
   > void arcfilter(struct mbuf *m)
   > 
   > to /sys/net/if_arcsubr.c, which would give the recoded (to 1051
   > format) packet to the packetfilter input, if it was a "first"
   > packet, and else ignore it. The hardware drivers would no longer
   > call the bpf stuff themselves.

   This seems wrong to me for a couple of reasons:
	   (1) the "packet filter" wants to see packets _as they come in_
	       over the network; if it doesn't, it can't be as useful when
		   debugging network problems.

Thats a very good argument against it. In this case, however, it would
be necessary to tell, e.g. TCPDUMP, about both ARC packet formats
(possible), but it seems necessary, from the comments in tbe bpf*
stuff, to tell the bpf stuff about possibly different framing header
lengths (I wanted to avoid that, as I have no idea how much work that
would be).

	   (2) it's not clear to me what this arcfilter() would do

Well, here is the packet format of 1051-like packets,

+----+----+----+--------------+-----------------------------+
|SRC |DST |TYP |User Data ... | possibly 3 bytes 00 padding |
+----+----+----+--------------+-----------------------------+

and of 1201-like packets:

+----+----+----+----+----+----+--------------+
|SRC |DST |TYP |FLAG|seq.id.  |User Data ... |
+----+----+----+----+----+----+--------------+

or

+----+----+----+----+----+----+----+----+----+----+--------------+
|SRC |DST |TYP |0xFF|0xFFFF   |TYP |FLAG|seq.id.  |User Data ... |
+----+----+----+----+----+----+----+----+----+----+--------------+

as written by the hardware driver into a mbuf and handed to arc_input().

My idea was, to let arc_filter() hand all 1051-like packets (that are,
to my knowledge, old IP and old ARP, possibly a few more) and the
first-fragment 1201-like packets (new IP, ARP, RARP, Novell IPX, 
stuff, etc) to the bpf input. It could also change the packet format
of the 1051-like to the 1201-like-unfragmented format, to make life
easier for the bpf-stuff and tcpdump. Of course, if I did this, I
could no longer debug the packet assembly/disassembly part of
arc_input() and arc_output(), so you're probably right about this
being a bad idea.

   It seems to me that stuff like reassembly, and, indeed, most of the
   work in fishing the data out of the packets, should be done by arc_input().

yes, of course.

   I don't understand what you mean.  First, what do you mean by
   "alignment"?  second, in what ways are the headers "aligned"
   differently?  i notice that the 1201 packets can contain a bunch of
   NUL padding in the header (YECH!), is that what you mean?

No no... there is no real padding in the headers of 1201 or 1051
packets (with the exception of the 1201 exception packets, which
insert a special 4byte sequence to avoide the forbidden packet length
range 253-256 and also avoid the 0 byte padding at the and).

What the hardware does, is: putting src and dst at the front of the
hardware buffer, then a pointer to the start of the data, which is
aligned with its end to the end of a 256 or 512 byte hardware buffer.

The padding in between is not sent over the wire, nor need it be
written at all.

   In particular, looking at 1051 vs 1201, i see the only differences at
   the front of the packet headers:

	   the "ALERT*" bits in the 1051 header,
	   the SOH bits in the 1051 header.

This is just a on the wire issue, and in fact, the headers are the
same, just the details of the description in both RFCs vary. 

   I'm not at all sure what the "preferable alignment" array would be
   needed for?  what do you think you need to know it for?

Ah, yes. As you might have noticed, the start of the "User Data" (e.g.
the IP packet) is at offset 3 in my representation for 1051-like
packets, and at offset 6 (or 10) for 1201-like packets.

When writing the RFC-1051 if_arcsubr.c and the hardware driver, I
looked at some Ethernet drivers and if_ether.c to get an idea about
what I should need to do. I noticed that most Ethernet drivers put a
(16 - sizeof(etherheader))byte padding at the beginning of the mbufs
they copy the received packets to, to make the IP packet longword
aligned. One of the authors of an ethernet driver mumbled, in a
comment, s.th. about a NFS bug which makes it necessary to align the
IP packet on longword boundaries.  Thats what I also did for arcnet.

Now, if that is still necessary, I have to put 1 byte of alignment in
for 1051-like packets, and 2 bytes for 1201-like packets. I can switch
that on the link0 flag, but then I would punish other protocols which
stay at 1201 encoding even if I use old style IP. I hope its more
clear now. If i looked at the "system id" in the hardware driver, I'd
be able to choose the correct padding, but then I would have to
incorporate knowledge about what protocols are 1051 or 1201-like into
hardware drivers. Or build an table into the if_arcsubr.c, which the
hardware drivers would use.

   It also seems that all of the stuff you're dealing with are
   (effectively) chars, or structures comprised of chars.  Given that
   (and given GCC's somewhat depressing attempt to pad e.g. structures of
   three chars to 4 bytes...), you may need to do something odd with
   just addressing things as arrays, or something, rather than as
   structure members (though i'd rather not see "packed" declarations, or
   things like that 8-)...

I discovered that the hard way. I could very well transmit IP packets
from one of the arcnet boards to the other in my Amiga, but my alpha
tester failed to see them with his OTHER amiga runnign AmigaOS...
finally I saw what was wrong with the help of a packet dumping routine
built into arc_input.

   It looks like an awful lot of "generic arcnet input" processing is
   currently being done in the driver's receive interrupt, and could be
   pushed into arc_input().  In particular, since all of the 1051/1201

   processing seems to be board-independent (is it?), it could all go at

yes, it is.

   the if_arcsubr.c layer.  I don't think that there's anything written
   in stone saying that the "media input" routine (i.e. arc_input()) has
   to take (interface, header, mbuf chain) as its parameters; you should
   be able to call it with (interface, mbuf chain), and let it deal with
   all of the ARCnet processing...

ah, thats no problem, if you tell me its not written in stone... I
only had source files to look at. I'll change that tonight.

Regards,
	Ignatios Souvatzis