Outline: x-kernel architecture
- building blocks
- flexible composition
- efficiency
- meta-protocol
Protocol Implementations
A protocol stack implementation has:
- an architecture (organization) for building a protocol stack
- a buffering strategy.
- a mechanism for threads or processes.
- inter-process synchronization.
x-kernel Overview
- The uniform protocol interface (aka metaprotocol)
defines the operations which are provided by all
protocols and sessions.
- The x-kernel message abstraction provides efficient operations
on messages.
- The x-kernel also provides events, timeouts, and semaphores.
x-kernel Protocols
- a protocol graph (a generalization of a protocol stack) is
configured statically.
- a protocol is defined by a set of source files implementing the
uniform protocol interface.
- a protocol supports open, openEnable, openDone, and
demux.
example protocol graph
- TCP, UDP, ICMP over
- IP, over
- ARP
- Ethernet
- Device driver
Protocol graphs
- The above protocol graph looks a lot like all the diagrams we have seen
so far
- however, all of these diagrams represented protocol abstraction:
this diagram represents a protocol implementation
- this is nice if the implementation is efficient
x-kernel efficiency
- never copy data (the message abstraction)
- pre-compute and store data for a sequence of operations: call
this cached state a session
- sessions are opened and closed explicitly
- when a packet is received, the device driver starts a call
up the protocol stack: an upcall
Upcalls
- traditional receive downcalls can return immediately
if the data is already present
- however, if the data is missing, the downcall must suspend (to
wait for the data) and transfer control to another thread (context switch)
- when the data becomes ready, control has to transfer back to the
suspended thread (another context switch)
- if we have N independent layers, each has to suspend and context
switch, for a total of N context switches upon packet receipt
- this is very inefficient. Upcalls require only two context switches,
independently of the number of layers
Challenges of upcalls
- in a program definition, one module normally includes another, so
the included module can be compiled and tested separately
- when modules have upcalls and downcalls, they are interdependent,
and they cannot be compiled and run separately
- the x-kernel uses object-oriented mechanisms to deal with this:
- functions refer to functions from the higher or lower layer by
calling functions in the x-kernel
- the x-kernel functions look in the data structure
to find the appropriate protocol functions
In-class exercise
- groups of 3-4
- 5 minutes
- implement (write pseudo code for) the interrupt and receive
functions given the following:
- void (*interrupt) (char * message) is a pointer to the function
called at interrupt time, with the message as its argument (be sure
your code initializes this pointer!!!!)
- char * intransit points to a packet waiting to be delivered,
and is NULL if there is no such packet
- suspension * receiver points to a suspended thread (or is null)
- void awaken (suspension * rcv, char * message)
awakens the suspending thread and gives it the message -- you must
clear receiver or
- |intransit| as appropriate
- char * suspend (suspension * rcv) will suspend
the current thread and assign its value to rcv
- if you receive a new packet and one packet is already buffered, discard
the new packet
- do not worry overmuch about synchronization
Protocols and Sessions
- a protocol is a piece of code that is
statically composed with other protocols
- a protocol must provide function such as:
- open a session
- openEnable to passively open a session, and
openDone to accept such a session
- close to close a session
- a session is a dynamic object, created as a result of
one of the open calls
- protocol functions called on open sessions:
- push outgoing data down a protocol stack
- pop received data up a protocol stack
- demux: called to select an appropriate
session in this protocol for received data
x-kernel: the big picture
- because of the layering costs of downcalls, most implementations
are not layered: they are monolithic
- a monolithic implementation is not modular, it is hard to split into
pieces to be tested independently
- lack of modularity makes maintenance difficult and expensive
- the x-kernel microprotocols is a building block that can
be re-layered as desired and tested independently
- the uniform protocol interface makes sure all building blocks will
fit -- does not guarantee they will "work" (whatever that means)