Summary
- A Click connection represents a possible forward path for packet handoff. It does not, on its own, say which endpoint initiates the transfer or prove that a packet traversed the path at runtime.
- Push processing begins at the source and carries control downstream. Pull processing begins at the destination and sends requests upstream; the returned packet still moves forward. An explicit
Queuecan join those two regimes. - Kohler and Click's collaborators made configuration a readable control surface without confusing it with execution evidence. Port types, initialization, queue state, scheduler choices and device receipts remain separate facts.
One arrow, two histories
Click begins with a deliberately small vocabulary. A router is assembled from elements. An element might read a device, check a header, choose a route, count packets, store them or send them. Connections form a directed graph, and an edge records a possible path by which one element can hand a packet to another.
That description is visual enough to invite a mistake. If the arrow points from A to B, an observer may assume A always calls B. Click separates two questions. Which way can the packet move? Who asks for the movement now?
The journal article by Eddie Kohler, Robert Morris, Benjie Chen, John Jannotti and M. Frans Kaashoek answers with two transfer mechanisms. In push processing, the source endpoint initiates the handoff. In pull processing, the destination asks its source for a packet. The graph's packet direction stays forward in both cases. The call path does not.
This is more than an implementation curiosity. A diagram that loses the distinction can assign authority to the wrong component. It can blame an input element for a pause actually controlled by an output device, or describe a packet as scheduled merely because a line exists on paper.
Push starts where the packet appears
Unsolicited arrivals naturally create push work. A receive device obtains a packet and cannot wait for a downstream component to know that the arrival occurred. Its element invokes the next push interface. Each downstream element processes the packet and can pass it onward until something consumes, drops or stores it.
Control and packet direction therefore travel together. The source owns the moment at which the handoff begins. That does not give it authority over the whole route. A classifier may choose another output, a check may reject the packet and a bounded queue may refuse or drop it. “Pushed” is a statement about initiation, not a certificate of acceptance at every later stage.
A useful receipt names the initiating element, input event, configuration identity, packet or batch handle and the exact downstream outcome. A device counter alone cannot show which graph branch was taken. A counter at a later element cannot prove which upstream event produced it unless the observation chain preserves that relation.
Pull starts where capacity appears
Transmission reverses the demand. An output device should not receive a packet merely because an upstream component has one. It needs the next packet when the hardware is ready to send. In Click, a destination with a pull input initiates a request. That request travels backward through pull connections until an element can return a packet or report that none is available.
The packet then moves forward along the same logical direction shown by the graph. Kohler's dissertation illustrates the asymmetry precisely: during push, control begins at the receiving device and moves forward; during pull, control begins at the transmitting device and moves backward; the packet always moves forward.
Pull also gives a scheduler a composable shape. An element with several pull inputs and one pull output can receive a downstream request, choose one input and ask it for a packet. The scheduler owns that selection for that request. The lines connected to it expose the candidates but do not reveal which candidate won, whether another input was empty or how long one source waited.
The Queue is a hand-off, not decoration
The simplest Click example places a Queue between receive-side push and transmit-side pull. Packets arriving from the device are pushed into its input and stored in FIFO order. When the output device is ready, it pulls from the queue's output and receives the packet at the front.
This element is an architectural confession. Arrival and service have different clocks, so storage must own the interval between them. Rather than bury that interval in a large router procedure, Click gives it a name, ports, configuration and inspectable state.
The resulting evidence is still bounded. Enqueue success can prove that this queue accepted a packet under this configuration. It does not prove persistence across a crash, later selection by a scheduler, transmission by hardware or receipt at the destination. A dequeue receipt says the packet left this queue; it does not say what every downstream element did.
Nor does FIFO settle fairness for the system. Several queues may feed one scheduler. Capacity limits may drop arrivals before enqueue. Notifications and device readiness affect when pulls occur. The visible queue localizes responsibility; it does not dissolve the rest of the chain.
Port types make an invalid promise rejectable
In a running Click router, ports acquire push, pull or compatible agnostic behavior. A connection between push ports is push; one between pull ports is pull. Connecting a push port directly to a pull port is illegal. Agnostic ports can take the type required by their neighbors.
This narrow type rule is a minimum common specification. Independently written elements do not need a central designer to approve every composition. They do need to agree on who may initiate the next transfer. A mismatch is not a political dispute or a runtime mystery. It is an invalid connection that initialization can reject.
The distinction between declaration and adoption remains important. The SMP Click description says the system parses the configuration, creates the router, attempts initialization, and installs and starts it only if initialization succeeds. A checked-in graph, a screenshot or a successful parse is not proof that the configuration became the running datapath. The receipts are configuration hash, initialization result, installation state and observed runtime behavior.
Readability survives optimization only with lineage
Fine-grained elements create flexibility but also introduce calls and repeated work. Kohler, Morris and Chen later applied compiler-like optimization at the level of router configurations. Other Click tools could specialize classifiers, eliminate dead code, remove virtual dispatch, transform patterns, check alignment and combine router definitions.
That creates another evidence boundary. The authored graph is valuable because it states logical responsibilities. The optimized program may no longer preserve one call boundary for every drawn edge. An operator auditing a production path therefore needs lineage: the source configuration, transformation sequence, generated configuration or code, build identity and installed instance.
Without that chain, two opposite errors are possible. A diagram may be treated as a literal trace even though optimizers changed execution boundaries. Or an optimized binary may be treated as inscrutable, even though its behavior was derived from a readable declarative configuration. Running-code primacy requires both the declared rule and proof of the code that adopted it.
Kohler's contribution belongs to a team and a method
Kohler's official Harvard page lists Click among their projects, and the publication record places their name first on the expanded 2000 journal article. Their MIT dissertation develops Click's architecture and language tools. The project, however, is visibly collaborative: Morris, Chen, Jannotti and Kaashoek share the journal paper; Massimiliano Poletto joins the language-techniques report; later contributors appear throughout the software history.
The careful attribution matters because this article is about separated control. Turning a team system into a lone-inventor legend would repeat the same mistake at the human layer—drawing one arrow and imagining it contains every call.
Click's lasting lesson is narrower. A useful common layer can specify packet handoff, port compatibility and configuration structure. The next decision may remain with a receiving device, transmitting device, queue or scheduler. What becomes real is what parses, initializes, installs and runs, not what a diagram appears to command.
Sources
- Eddie Kohler — official Harvard profile
- Eddie Kohler — official publication list
- The Click Modular Router — ACM TOCS author PDF
- The Click Modular Router — Eddie Kohler's MIT dissertation
- Programming Language Techniques for Modular Router Configurations
- Programming Language Optimizations for Modular Router Configurations
- Flexible Control of Parallelism in a Multiprocessor PC Router
- Click for Measurement
- Click modular router — official GitHub repository
- Heng Lu — Running-Code Primacy
- Heng Lu — Minimum Initial Specification, Localized Future Decision, and Voluntary Adoption
Member Briefing
Deeper Profile Context
Sign in with the right membership level to unlock the full briefing and source notes.
Only for Strategic Circle
Strategic Circle
Open to all readers. Unlock profile briefings after joining and signing in.
Join Strategic CircleOnly for Leadership Alliance
Leadership Alliance
For qualified IP-asset owners and management; sign in to unlock alliance briefings.
Join Leadership Alliance
