The wire between brain and muscle
The previous guide gave us the big idea of software-defined networking: pull the decision-making control plane out of every switch and box it up in one logically central controller with a network-wide view, leaving each switch as a fast, dumb data plane that just moves packets. That raises an obvious question we glossed over: if the brain lives in the controller and the muscle lives in the switch, what exactly travels down the wire between them? What does the controller actually say to a switch?
The protocol that carries that conversation is called the southbound API — "south" because in the usual picture the controller sits on top and the switches hang below it. The most famous southbound protocol, the one that kicked off the whole SDN movement, is OpenFlow. And the only thing OpenFlow really does is let the controller write into, read from, and get notified about one data structure inside each switch: a match-action table, also called a flow table. Everything else in this guide is just unpacking that one table.
What a flow-table entry actually says
Think of a flow table as a list of if-then rules a receptionist follows, read top to bottom. Each row, called a flow entry, has three parts. First a match pattern: a set of header fields to look at, where you may pin a field to an exact value or leave it as a wildcard meaning "don't care." Second a list of actions: what to do with any packet that matches — forward it out port 3, drop it, rewrite a field, send it up to the controller, and so on. Third a priority plus some counters that tick up every time the rule fires, which is how the controller later sees what the switch has been doing.
The match fields cut clean across the layering you learned earlier, and that is the point. One entry can match on a MAC address (a layer-2 idea), the next on an IPv4 address (layer 3), the next on a TCP port (layer 4). To OpenFlow these are just byte ranges at known offsets inside the packet's nested headers. A classic OpenFlow switch could match on roughly a dozen such fields at once — input port, source and destination MAC, source and destination IP, protocol, source and destination port, and a few more. So a single rule can be as broad as "any packet at all" or as narrow as "TCP traffic from this one host to that one host on port 443."
FLOW TABLE (read top to bottom; first match wins) prio match action packets ---- ------------------------------------- -------------- ------- 200 in_port=1, dst_ip=10.0.0.7, tcp_dst=80 output:3 14823 100 dst_ip=10.0.0.0/24 output:2 391 50 eth_type=ARP output:CONTROLLER 6 0 * (wildcard: matches anything) output:CONTROLLER 17
Tracing one packet through the table
Here is the whole data-plane algorithm, and it is almost embarrassingly simple. A packet arrives. The switch compares it against the flow entries and, among all the rules it matches, picks the one with the highest priority. (If your IP guides about longest-prefix match are fresh, this is the same flavor of "most specific wins," generalized to any field.) It then runs that entry's actions, bumps the entry's counter, and moves on to the next packet. No path computation, no routing protocol chatter, no thinking — just match and act, millions of times a second, in hardware.
- A packet enters on port 1, headed for IP 10.0.0.7 on TCP port 80. The switch reads its header fields.
- It scans the flow table for matches. Both the priority-200 rule and the priority-100 rule match this packet; the all-wildcard rule would too.
- Highest priority wins, so the priority-200 entry is chosen. Its action says output:3, so the packet is sent out port 3.
- The switch increments that entry's counter (14823 to 14824) and is done. Total work: a table lookup and a forward — no controller needed.
Notice how this reframes the old idea of a forwarding table. A traditional router built its forwarding table by itself, from a routing protocol baked into the box. An OpenFlow switch's flow table holds the same kind of "which port for which packet" knowledge, but the switch did not compute any of it — the controller wrote every entry from above. The muscle still moves the packets at full speed; it just no longer decides where they go.
What happens when nothing matches
The most interesting moment is the first packet of a brand-new flow — say the very first packet of a fresh connection the switch has never seen. If no specific rule matches, it falls through to that bottom catch-all entry whose action is "send to controller." The switch wraps the packet up and ships it north over OpenFlow as a packet-in message: in effect saying, "I don't know what to do with this — you decide." This is the only time the slow brain gets involved in an individual packet, and it is the heart of how an SDN network learns.
The controller, with its network-wide view, decides what should happen to packets like this one. Then it does something clever: rather than babysit every future packet of the same flow, it sends a flow-mod message back down, telling the switch to install a new flow entry. From then on every later packet of that flow matches the freshly installed rule and is handled at hardware speed, with the controller never touched again. So the controller's per-packet involvement is paid once, up front, and amortized over the whole flow.
This reveals two styles of control. In reactive mode the switch starts empty and asks the controller about each new flow as it appears, as just described — flexible, but the very first packet of every flow eats a controller round-trip of delay. In proactive mode the controller pre-loads the flow tables before any traffic arrives, the way a careful host sets out every chair before guests show up, so packets never miss and the controller is never on the critical path. Real deployments mix the two: proactive rules for the bulk of expected traffic, reactive handling for the surprises.
Up, down, and the bottleneck
We have been looking at the southbound API — the controller talking down to switches. But an operator does not want to think in flow entries any more than a driver wants to think in spark plugs. So above the controller sits the northbound API: the interface that applications and network engineers use to express what they want — "keep the guest network walled off from finance," "send video over the lightly loaded path" — and let the controller translate those intentions down into the right pile of low-level flow entries. Southbound is how the controller commands the muscle; northbound is how humans and apps command the controller.
The payoff is real. Because the flow tables are written from software with a global view, you get flexibility (forward on any field combination you like, not just destination IP) and visibility (those per-rule counters give the controller a live, network-wide picture of every flow). Want a new forwarding policy? Push new entries — no new protocol, no firmware on every box. This is also why cheap, vendor-neutral white-box switches became viable: when the brains live in the controller, the switch just needs to run match-action fast, so plain merchant-silicon hardware will do.