CONTENTS_GOES_HERE
cnet's Physical Layer
The Physical Layer
(either the internal default version or one provided with the
-R option)
has the responsibility of delivering data frames between nodes.
Frames are delivered along either point-to-point links
or Ethernet segments.
Each physical link is numbered within each node from 1 to its total
number of links.
As a special case, link 0 represents a loopback link,
and is provided to simply copy a frame immediately from a node's output
to input.
In general, the Physical Layer will randomly corrupt and drop data frames
on all point-to-point links,
but not on the loopback link or Ethernet segments.
When your protocols wish to transmit a data frame along a link,
they write that frame to the Physical Layer.
On calling the CNET_write_physical function,
you indicate the length of the frame to be written and on return
CNET_write_physical indicates how many bytes were accepted.
A typical sequence for a network of just 2 nodes,
connected by a single point-to-point link is:
char myframe[ MAX_MESSAGE_SIZE + MY_OVERHEAD ];
int length;
... /* prepare frame contents for transmission */
length = ... ;
result = CNET_write_physical(1, myframe, &length);
|
|
When cnet informs the destination node that a frame has arrived,
the handler for EV_PHYSICALREADY should read that frame.
On return from a successful call to CNET_read_physical,
your protocol is informed on which link the frame arrived and how long it was.
Of course,
in a simple network with just one point-to-point link or one Ethernet segment,
all frames will be transmitted and will arrive on link number 1.
Point-to-point links impose no particular format on the frames written to it;
unless corrupted or lost, whatever is written to a point-to-point link will
arrive unmodified, and without interpretation, at the other end of the link.
char myframe[ MAX_MESSAGE_SIZE + MY_OVERHEAD ];
int link, length;
length = sizeof(myframe);
result = CNET_read_physical(&link, myframe, &length);
... /* process frame contents */
|
|
To provide some sense of realism,
frames (or packets) written to Ethernet links are expected to carry the
address of their destination Network Interface Card (NIC) at the very
beginning of the frame.
cnet provides the data type CnetNicaddr to represent the
addresses of its NICs,
as an array of LEN_NICADDR (=6) unsigned characters.
cnet interprets the leading LEN_NICADDR bytes of each frame
on an Ethernet segment to be an address.
The special address, whose string representation is ff:ff:ff:ff:ff:ff,
is interpreted as the Ethernet broadcast address.
Any frame carrying the broadcast address as its destination address will be
delivered to all NICs on the Ethernet segment, except the sender.
cnet does not support multicast or group addressing.
Consider the following example function,
used to write data to an Ethernet segment:
typedef struct {
CnetNicaddr dest;
CnetNicaddr src;
char type[2];
char data[ETH_MAXDATA];
} ETHERPACKET;
#define LEN_ETHERHEADER (2*sizeof(CnetNicaddr) + 2)
static void write_to_ethernet(CnetNicaddr dest, int link, char *buf, int len)
{
ETHERPACKET packet;
short int twobytes;
memcpy(packet.dest, dest, sizeof(CnetNicaddr));
memcpy(packet.src, linkinfo[link].nicaddr, sizeof(CnetNicaddr));
twobytes = len; /* type carries the data's true length */
memcpy(packet.type, &twobytes, 2);
memcpy(packet.data, buf, len);
len += LEN_ETHERHEADER;
if(len < ETH_MINPACKET) /* pad short packets to minimum length */
len = ETH_MINPACKET;
CHECK(CNET_write_physical(link, (char *)&packet, &len));
......
}
|
|
This function assumes that the data's length is not too long for Ethernet
(<= ETH_MAXDATA (=1500) bytes).
The required destination's NIC address is first copied to the destination
address field,
and then the address of the local NIC used copied to the source address field.
Notice that because the CnetNicaddr type is actually an array of
characters, we do not use the & operator in the calls to memcpy.
The data's true length is copied into the packet's two-byte type
field, the provided data copied to the packet's data.
After ensuring that the packet to be written is at least
ETH_MINPACKET (=64) bytes long,
the packet is written to the link.
Again, cnet does not enforce (nor understand) the use of
our ETHERPACKET data type,
but does assume that the first
LEN_NICADDR bytes of each packet provides the destination NIC address.
Two additional Physical Layer functions are provided to assist in the
debugging of multi-layered protocols.
CNET_write_physical_reliable is identical to
CNET_write_physical except that frames sent using it will not be
subject to frame corruption or loss.
It can be considered as a ``perfect'' Data Link Layer if you just want
to implement higher-layered protocols.
The function CNET_write_direct also bypasses all Physical Layer errors
and instructs a message to be sent directly to the node whose address is
specified as a parameter.
It thus provides perfect a Data Link Layer and Network Layer.
-
int
CNET_write_physical(int link, char *frame, int *len);
-
Passes a number of bytes, pointed to by frame ``down to''
the Physical Layer
which will attempt to deliver them on the indicated link (wire).
Each node has a fixed number of links,
the first available link is number 1,
the second is number 2, and so on.
As a special case,
a node may reliably transmit a frame to itself by requesting
the LOOPBACK(=0) link.
On invocation, len must point to an integer indicating the number
of bytes to be taken from frame.
On return, len will point to an integer now indicating the number
of bytes accepted by the Physical Layer.
Possible errors: ER_BADARG, ER_BADLINK, ER_BADSIZE, ER_LINKDOWN,
ER_NOTREADY, ER_TOOBUSY.
-
int
CNET_write_physical_reliable(int link,
char *frame, int *len);
-
Identical to CNET_write_physical though the transmission is
guaranteed to be error free (providing a reliable data-link layer).
Possible errors: ER_BADARG, ER_BADLINK, ER_BADSIZE, ER_LINKDOWN,
ER_NOTREADY, ER_TOOBUSY.
-
int
CNET_write_direct(CnetAddr destaddr, char *msg, int *len);
-
Similar to CNET_write_physical_reliable but the network address of the
required destination node may be specified
(providing a reliable network/routing layer for asynchronous message passing).
Messages transmitted using CNET_write_direct are considered to be
transmitted on, and arrive on, link number 1.
The special destination address BROADCAST may be used to transmit a
message to all nodes except the sender.
Regardless of the number of hops, propagation delays, and bandwidth,
all frames sent via CNET_write_direct reach their destination in
just 1msec.
Possible errors: ER_BADARG, ER_BADLINK, ER_BADSIZE, ER_LINKDOWN,
ER_NOTREADY, ER_TOOBUSY.
-
int
CNET_read_physical(int *link, char *frame, int *len);
-
Accepts the specified maximum number of bytes from the Physical Layer,
placing them in the address pointed to by frame.
On invocation, len must point to an integer indicating the maximum
number of bytes that may be copied into frame.
On return, len will point to an integer now indicating the number
of bytes taken from the Physical Layer
and link will point to an integer indicating on which link they
were received.
Possible errors: ER_BADARG, ER_BADSIZE, ER_CORRUPTDATA, ER_NOTREADY.
-
int
CNET_set_promiscuous(int link, int Boolean_value);
-
This function places (or removes) the Network Interface Card (NIC)
of the indicated physical link into promiscuous mode.
When in promiscuous mode, the NIC will receive a copy of all frames on the
segment, even if they are neither broadcast frames or explicity addressed
to the NIC.
Promiscuous mode may only be set for links of type LT_ETHERNET,
not for LT_LOOPBACK (link=0) or LT_POINT2POINT links.
Possible errors: ER_BADLINK.
-
int
CNET_set_nicaddr(int link, CnetNicaddr new_nicaddr);
-
This function sets the address recognized by the Network Interface Card (NIC)
of the indicated physical link.
The new address may not be the zero address, 00:00:00:00:00:00,
or the broadcast address, ff:ff:ff:ff:ff:ff.
No check is made to ensure that the new address is unique within the network
(thereby enabling some snooping/sniffing protocols to be developed).
NIC addresses may only be set for links of type LT_ETHERNET,
not for LT_LOOPBACK (link=0) or LT_POINT2POINT links.
Possible errors: ER_BADARG, ER_BADLINK.
-
int
CNET_parse_nicaddr(CnetNicaddr nicaddr, char *string);
-
This function accepts a character string of the form
ab:cd:ef:gh:ij:kl,
where each letter is a valid hexadecimal character,
and converts this string representation to the ``internal'' form consisting
of an array of 6 unsigned characters.
Any valid Network Interface Card (NIC) address is accepted.
Possible errors: ER_BADARG.
-
int
CNET_format_nicaddr(char *buffer, CnetNicaddr nicaddr);
-
This function accepts a Network Interface Card (NIC) address
and formats its `internal'' form to a string of characters of the form
ab:cd:ef:gh:ij:kl,
where each letter will be a hexadecimal character.
Possible errors: ER_BADARG.
|