Link-Layer Switches and Bridging

Imagine an office building with 200 machines plugged into an Ethernet network. Every frame sent by every host could, in principle, reach every other host. This is because Ethernet was born as a shared broadcast medium. That design does not scale. As the number of hosts grows, collisions and wasted bandwidth grow with it. Privacy leaks too, since anyone can see everyone else's traffic. The link-layer switch solves this problem, transparently and without any configuration. It learns where hosts live and forwards frames only where they need to go. Switches (historically called bridges when connecting only two segments) sit at the heart of nearly every modern local-area network. A single Ethernet switch chip today can move terabits per second between hundreds of ports. Data-center fabrics are built from thousands of such switches wired into fat-tree or Clos topologies. It is essential to understand how a switch decides where to send a frame. It is also essential to understand why that decision is both fast and provably loop-free (given a spanning tree). This understanding underlies everything built on top: Virtual LANs (VLANs), data-center networking, and even how the Internet's edge attaches to the wired world. This article builds the switch from first principles. We start from the naive "flood everything" hub. Then we show exactly what a self-learning switch adds. It adds a forwarding table built by passive observation of source addresses. It also adds a forwarding decision built by table lookup on destination addresses. We prove the learning algorithm is correct under a plausible model of network behavior. We analyze its time and space cost. We trace a worked example frame-by-frame through a small topology, so the mechanism is not just believable but visible. By the end you will be able to hand-simulate a switch's forwarding table evolving over a sequence of frames. You will be able to explain why switches must flood on an unknown or broadcast destination. You will be able to articulate why filtering is what actually gives switches their performance and privacy advantages over hubs. You will also see precisely where this simple mechanism needs help — namely when physical topology contains loops. This limitation motivates the spanning tree protocol and eventually VLANs.

Key takeaways
  • A switch forwards Ethernet frames using a forwarding table mapping MAC addresses to output interfaces, built automatically by self-learning.
  • Self-learning works by recording the source address and incoming interface of every frame the switch sees — no configuration, no routing protocol.
  • On a lookup miss (or for broadcast/multicast frames), a switch floods: it forwards out every interface except the one the frame arrived on.
  • Switches provide filtering (don't forward when destination is known to be on the arrival segment) and isolation of collision domains, unlike hubs.
  • Self-learning correctness relies on frames from a host eventually arriving at the switch on the interface toward that host — true in acyclic topologies, broken by loops.
  • Physical loops (for redundancy) require a spanning tree protocol to disable redundant links logically; this constraint later motivates segmenting one physical LAN into many logical ones via Virtual LANs (VLANs).
The core insight

A switch turns a shared, broadcast Ethernet segment into a set of independent point-to-point links by learning MAC-address locations passively and forwarding frames only toward them.

The idea

A link-layer switch is a store-and-forward device that operates on Ethernet frames using only Ethernet and the Frame Format information — specifically source and destination MAC addresses — with no awareness of IP addresses or routing. Each switch port connects to either a single host, another switch, or (historically) a shared hub segment; today almost every link is a dedicated, full-duplex, point-to-point cable, so each switch port is its own collision domain. This is the crucial structural difference from a hub, which is a pure physical-layer repeater: a hub retransmits every incoming bit out every other port, so all attached hosts share one collision domain and see all traffic (a security and performance liability). A switch instead makes a per-frame forwarding decision. The core data structure is the switch (forwarding) table, a set of entries of the form `(MAC address, interface, timestamp)`. A well-formed table entry asserts: "the host with this MAC address can be reached by sending frames out this interface." Critically, the table is not configured by an administrator or computed by a routing algorithm — it is built by self-learning (also called transparent bridging), a passive observation process that requires no protocol messages between switches at all. This is what makes switches "plug and play": you can cable an arbitrary tree of switches together and correct forwarding emerges automatically. Two mechanisms complete the picture. Filtering is the decision to not forward a frame out a particular interface — most importantly, dropping a frame entirely when its destination is already known to reside on the same interface the frame arrived on (the sender and receiver share a segment, so nothing needs to be relayed elsewhere). Flooding is the fallback of forwarding a frame out every interface except the one it arrived on, used whenever the destination's location is unknown or the destination is the broadcast/multicast address. Learning, filtering, and flooding together define the complete forwarding behavior of a switch; nothing else is needed for a tree-shaped network.

How it works

The switch runs one procedure per arriving frame. Two things happen on every frame: a learning step (always executed, using the source address) and a forwarding step (using the destination address). These are independent and can be thought of as two separate passes over the same frame.

Learning step. When a frame arrives on interface `x` with source address `S`, the switch records (or refreshes) the association `S → x` in its table, tagged with the current time. This is valid because Ethernet source addresses are (assumed) globally unique and a real physical arrival on interface `x` is direct evidence that `S` is reachable via `x`. Entries are not permanent: each carries an aging timer (typically minutes), and stale entries are purged so that the table adapts if a host moves to a different port (e.g., a laptop unplugged from one switch and plugged into another).

Forwarding step. When a frame arrives on interface `x` with destination address `D`, the switch does a table lookup on `D`:

  • If `D` is the broadcast address, or a multicast address the switch treats as "flood," forward out every interface except `x`.
  • If `D` has a table entry mapping to some interface `y`:
  • If `y = x` (destination lives on the same segment as the sender — this happens on shared hub segments, or in degenerate cases), filter: drop the frame, forward nowhere.
  • Else forward the frame out interface `y` only.
  • If `D` has no table entry (an "unknown unicast"), flood: forward out every interface except `x`.

``` // State: table is a map from MAC address -> (interface, timestamp) // AGE_LIMIT is the maximum entry lifetime (e.g., 300 seconds) function ON_FRAME_ARRIVAL(frame, arrival_interface): S <- frame.source_mac D <- frame.dest_mac now <- CURRENT_TIME() // ---- Learning step (always runs) ---- table[S] <- (arrival_interface, now) // ---- Forwarding step ---- if D == BROADCAST_ADDR or IS_FLOOD_MULTICAST(D): for each interface i in ALL_INTERFACES: if i != arrival_interface: SEND(frame, i) return if D in table and (now - table[D].timestamp) <= AGE_LIMIT: target <- table[D].interface if target == arrival_interface: // destination already reachable without relaying: filter drop(frame) else: SEND(frame, target) else: // unknown destination: flood, and let learning fix this // for future frames once the destination itself transmits for each interface i in ALL_INTERFACES: if i != arrival_interface: SEND(frame, i) // Runs periodically, independent of frame arrivals function AGE_TABLE(): for each (mac, entry) in table: if CURRENT_TIME() - entry.timestamp > AGE_LIMIT: remove mac from table ``` A subtlety worth naming explicitly: learning and forwarding use different fields of the same frame — learning reads the source, forwarding reads the destination — and they happen in the same pass, so a switch effectively learns about a host's location before it might need to forward a reply back to that host, but only if that host has transmitted at least once. The first frame ever sent to a fresh MAC address is always flooded, because nothing has taught the switch where that address lives yet; only the reply (or any subsequent traffic from that host) teaches the switch, after which later frames to it are unicast-forwarded.

Figure
A small switched LAN: three switches connecting six hosts in a tree, with one switch's forwarding table shown
Switch A Switch B Switch C port 1 port 2 H1 H2 H3 H4 H5 H6 Switch A table H1,H2,H3 → port 1 H4,H5,H6 → port 2

Reading the diagram: once every host has transmitted at least one frame, Switch A's table has collapsed the entire left subtree to "port 1" and the entire right subtree to "port 2" — it does not need to know which individual host is which switch's problem, only which of its own ports leads toward that host. This is exactly what lets forwarding tables stay small even in large fanout: a switch's table size is bounded by the number of distinct MAC addresses ever seen, not by the depth or width of the whole network.

Complexity & correctness

Per-frame time complexity. With the table implemented as a hash map keyed by MAC address, both the learning update and the forwarding lookup are `O(1)` expected time. Flooding costs `O(k)` where `k` is the number of interfaces on the switch, since the frame must be copied/queued to each of the up-to-`k−1` other ports. In the worst case (every frame is an unknown unicast or broadcast), forwarding a stream of `n` frames through a switch with `k` ports costs `O(n·k)` total work; in the common case (steady state, most destinations known), it is `O(n)`. Real switch ASICs implement the table lookup in a content-addressable memory (CAM), giving true `O(1)` hardware lookup at line rate, which is why switches can forward at multi-gigabit or terabit aggregate rates without becoming the bottleneck.

Space complexity. The table stores one entry per distinct MAC address the switch has observed since entries last aged out, so space is `O(D)` where `D` is the number of distinct source addresses seen within one aging window. Real switch chips provision a fixed CAM size (e.g., 16K–128K entries); if the number of distinct addresses exceeds capacity — a MAC table exhaustion condition, sometimes triggered maliciously (MAC flooding attacks) — the switch typically degrades toward flooding-everything behavior, temporarily behaving like a hub. This is a real, documented tradeoff, not a hypothetical one: it is exactly why switches in adversarial environments need port security or rate limiting on learned addresses.

Correctness of self-learning, informally. Claim: in a network whose physical topology is a tree (no cycles among switches), after every host has transmitted at least one frame, every switch's table correctly maps every other host's MAC address to the interface on the (unique) path toward that host, and the algorithm never mis-delivers a frame to a host that shouldn't receive it (beyond unavoidable floods before learning completes). Proof sketch. Because the topology is a tree, there is a unique path between any two hosts, and hence for switch `T` and destination host `H`, there is a unique interface of `T` that lies on that unique path (call it `next(T, H)`). We show by induction on frames observed that once `T` has recorded an entry for `H`, that entry equals `next(T, H)`. Base case: `H`'s own first transmitted frame travels from `H` toward the rest of the network. Every switch it passes through receives that frame on the interface that is, by construction, the one lying on the path back to `H` — because the frame physically arrived from that direction. So every switch on the frame's path correctly learns `next(T,H)` immediately (this is the "learning step" applied to the source address). Inductive step: Suppose later, after topology and table contents have stabilized, some other host `H'` sends a frame toward `H`. At each switch `T` along the path, `T` looks up `H` in its table. Because table entries are only ever overwritten by a frame that actually arrived from a given interface (correct evidence), and because the tree topology guarantees at most one interface can ever be "the direction toward `H`," the entry `T` holds for `H`, once learned, cannot become wrong except through aging (removal) or a host physically moving (which produces a new, also-correct arrival event). Hence the invariant "table entries, when present, are correct" is preserved by every operation the algorithm performs: learning only inserts observed-true facts, and aging only removes facts (never inserts wrong ones). A missing entry causes a safe, if wasteful, flood rather than an incorrect unicast — so the algorithm degrades to correctness-preserving over-delivery, never under-delivery or mis-delivery, whenever information is incomplete. ∎ This argument depends essentially on the tree assumption. If the physical topology contains a cycle (e.g., two redundant links between the same pair of switches, added for fault tolerance), a broadcast or unknown-unicast frame injected into the cycle gets flooded around it, is received again by a switch that already forwarded it, gets flooded again, and the frame count grows without bound — this is the infamous broadcast storm, and it also corrupts learning, because a switch may see the same source's frame arrive on two different interfaces in rapid succession and thrash its table entry back and forth. The self-learning switch, as described, is only correct on acyclic topologies; making cyclic (redundant) physical topologies behave correctly requires computing a spanning tree over the physical links and logically disabling the redundant ones (the Spanning Tree Protocol), which is the natural next mechanism built on top of plain bridging, and is itself a prerequisite for safely running the segmented, VLAN-aware switching planes used in production networks.

Tradeoffs, stated honestly.

  • Self-learning is fully distributed and needs zero configuration, but it is reactive: the first frame to any address is always flooded, which is wasted bandwidth and a (mild) information leak.
  • Filtering reduces unnecessary traffic and increases effective throughput versus a hub, but only once tables have "warmed up"; a cold switch (just powered on, empty table) behaves exactly like a hub until it learns.
  • Aging keeps tables adaptive to host movement, but too-short an aging interval causes needless re-flooding, while too-long an interval risks stale entries after a host moves ports.
  • A switch cannot forward faster than the sum of its outgoing link rates for flooded traffic; heavy flooding (broadcast-heavy protocols, or attacks) degrades the very filtering benefit switches exist to provide.

Worked example

Consider the three-switch tree from the figure, with Switch A in the middle connecting to Switch B (which serves H1, H2, H3) via port 1, and Switch C (serving H4, H5, H6) via port 2. All tables start empty. Trace the following sequence of frames arriving at Switch A (we omit Switch B and C's internal tables for brevity and focus purely on A's behavior).

StepFrame (src → dst) arrives on portA's table lookup for dstA's actionA's table after step
1H1 → H4, arrives port 1H4: missflood out port 2 (only other port){H1→1}
2H4 → H1, arrives port 2H1: hit → port 1filter? no — target(1) ≠ arrival(2), so forward out port 1{H1→1, H4→2}
3H2 → H4, arrives port 1H4: hit → port 2forward out port 2{H1→1, H2→1, H4→2}
4H5 → broadcast, arrives port 2n/a (broadcast)flood out every port except 2, i.e. port 1{H1→1, H2→1, H4→2, H5→2}
5H3 → H1, arrives port 1H1: hit → port 1filter: target(1) = arrival(1), same side, drop{H1→1, H2→1, H3→1, H4→2, H5→2}
6H6 → H2, arrives port 2H2: hit → port 1forward out port 1{…, H6→2}

Two steps deserve a closer look. Step 1 is a cold-cache flood: A has never heard from H4, so it must guess "everywhere but where this came from," which happens to be correct only because port 2 is the sole other port. Step 5 shows filtering in a case that would be wrong to get backwards: H3 and H1 are both reachable via port 1 (they are both under Switch B), so when H3 sends to H1, that traffic never needs to reach Switch A's port 2 side at all; forwarding it out port 2 would be a wasted (and mildly leaky) transmission, and the algorithm correctly suppresses it. Notice this is not a trivial symmetric case — H1 and H3 are different hosts on the same interface as seen by A, even though they are not directly on the same physical wire; A only knows "reachable via port 1," and that is exactly the granularity it needs. By the end of step 6, Switch A's table fully and correctly summarizes reachability: everything behind port 1 collapses to one entry-group, everything behind port 2 to another, regardless of how many hosts eventually appear behind each port — illustrating the `O(D)` space bound independent of topology depth.

Common pitfalls & traps

PitfallWhy it happensConsequence
Forgetting to learn from the source address, only forwarding on destinationConflating the two independent passes over one frameTable never builds; switch floods forever, behaving like a hub
Assuming the first frame to a new address is unicast-forwardableIgnoring that learning requires the destination to have transmitted firstIncorrect simulation traces; students "invent" a table entry that was never learned
Not filtering when source and destination share the arrival interfaceTreating every table hit as "forward it"Unnecessary traffic sent across the rest of the network; on shared hub segments, actual duplicate delivery
Ignoring aging timersTreating the table as permanentStale entries persist after a host moves ports, causing black-holed or misdirected traffic until timeout
Deploying redundant physical links without a spanning tree mechanismWanting fault tolerance via extra cablingBroadcast storms: frame counts blow up exponentially, tables thrash, network collapses
Confusing switch forwarding-table learning with IP routing-table computationBoth are "tables mapping addresses to next hops" superficiallyStudents expect switches to compute shortest paths or exchange routing protocol messages — they don't; learning is purely passive observation

Pioneers & history

The switch grew directly out of the need to interconnect and segment Ethernet's original shared-medium design once it became clear that a single collision domain could not scale to large numbers of hosts. The transparent, self-learning bridge — the key intellectual contribution — was formalized and standardized in the 1980s, turning what could have been a manually configured device into one that "just works" when cabled into any tree topology.

Origins · 1 minRadia Perlman and how this was discovered
RP
Radia Perlman
born 1951 · Digital Equipment Corporation, 1980s networking research

Radia Perlman designed the Spanning Tree Protocol (1985), the algorithm that lets self-learning bridges safely coexist with redundant physical topologies by computing a loop-free logical tree over an arbitrary cyclic mesh of switches. Her work directly completes the picture this article builds: self-learning alone is correct only on trees, and Perlman's algorithm is what makes real, redundantly-cabled networks behave as if they were trees. She is often credited, half-jokingly (in a limerick she wrote herself), with the line "I invent, and then I explain" — an apt description of how foundational and pedagogically clear her contributions to bridging and routing have been.

History
- 1973 — Xerox PARC develops experimental Ethernet as a shared-medium local network.
- 1980 — DIX (DEC/Intel/Xerox) Ethernet standard published; shared coaxial-cable LANs become common.
- 1985 — Radia Perlman designs the Spanning Tree Protocol, enabling safe redundant bridging topologies.
- 1990 — IEEE 802.1D standardizes transparent bridging and spanning tree for Ethernet LANs.
- Early 1990s — Dedicated switch hardware (as opposed to shared hubs) becomes commercially widespread, giving each host its own collision domain.

Where this matters

Every enterprise, campus, and data-center Ethernet network today is built from link-layer switches running exactly this self-learning algorithm as their baseline forwarding behavior, augmented with spanning tree (or its modern replacements) for loop safety and, in production networks, Virtual LANs (VLANs) to segment one physical switch fabric into multiple isolated broadcast domains. Data-center fabrics built from Clos or fat-tree topologies use thousands of switch ASICs, each running hardware CAM lookups derived directly from this learning-and-filtering model, to achieve terabit-scale forwarding. Home and small-office routers contain an embedded Ethernet switch chip performing the same self-learning algorithm to connect wired LAN ports before any routing or NAT logic runs. Understanding self-learning switches is also the necessary foundation for understanding Software-Defined Networking (SDN) controllers, which often replace or augment the learning algorithm with centrally computed forwarding rules while still relying on the same underlying frame-forwarding semantics, and for understanding why network engineers care so much about physical topology design, redundancy, and loop prevention in real cabling plans.

Ask the tutor: How does the Spanning Tree Protocol decide which redundant links to block, and how does that interact with the self-learning tables discussed here?

Is a switch the same thing as a router?

No. A switch operates purely at the link layer, forwarding Ethernet frames based on MAC addresses, with no concept of IP addresses, subnets, or routing protocols. A router operates at the network layer, forwarding IP packets based on a routing table built (usually) by exchanging routing protocol messages like OSPF or BGP with other routers, and it can interconnect fundamentally different networks. A switch's forwarding table is built passively by observing traffic (self-learning); a router's routing table is typically built by active computation and message exchange. In practice, many devices ("layer-3 switches") combine both functions in one box, but conceptually they remain distinct planes of operation.

Why must the very first frame to any address always be flooded?

Self-learning is purely reactive: a switch learns "MAC address X is reachable via interface Y" only by directly observing a frame from X arriving on Y. Before X has ever transmitted anything, no switch in the network has any evidence of where X is, so a table lookup for X necessarily misses. The only safe fallback given no information is to flood — send the frame out every interface except where it arrived — guaranteeing delivery at the cost of some wasted bandwidth. Once X eventually transmits (even just a reply to the flooded frame), every switch on the path learns its location, and subsequent frames addressed to X become efficient unicast forwards rather than floods.

What happens if a switch's forwarding table fills up completely?

Real switches implement the table in a fixed-size hardware content-addressable memory (CAM), typically holding tens of thousands to over a hundred thousand entries. If the number of distinct source MAC addresses observed exceeds this capacity, the switch cannot learn new entries (or must evict old ones), and destinations without a valid entry are flooded rather than efficiently unicast. In the worst case — sometimes induced deliberately in a "MAC flooding" attack, where an attacker generates enormous numbers of forged source addresses — the table saturates entirely and the switch is forced to flood nearly all traffic, effectively degrading to hub-like behavior. This is a genuine security concern, which is why production switches often implement port security features that limit the number of MAC addresses learnable per port.

Why do redundant physical links between switches cause problems, and how is this normally fixed?

Self-learning's correctness proof assumes a tree topology, where every pair of hosts has a unique path and hence every switch interface unambiguously represents "the direction toward" some set of hosts. A redundant physical link between two switches creates a cycle; an unknown-unicast or broadcast frame injected into that cycle gets flooded around it repeatedly, since flooding never checks whether a frame has been seen before, producing an exponentially growing storm of duplicate frames that can saturate links within seconds. This also corrupts table learning, since a switch may see the same source arrive alternately from two different directions. The standard fix is the Spanning Tree Protocol, which computes a loop-free logical subgraph of the physical topology and administratively blocks the redundant links (keeping them ready as backups) until they are needed for fault tolerance.

How does a switch's forwarding table differ from a router's routing table in terms of how it is built?

A switch's forwarding table is built entirely by local, passive observation — the self-learning algorithm — with zero communication between switches required for correctness on a tree topology. A router's routing table, by contrast, is typically built through active computation, often involving distributed algorithms (distance-vector or link-state) where routers exchange explicit protocol messages describing reachability and cost, and can even use policy-based decisions (as in BGP) unrelated to shortest paths. The switch's table only ever records facts it has directly witnessed (a frame's source and arrival interface); it never "asks" another switch anything or runs a shortest-path computation of its own. This makes switches simpler and more autonomous, but also less flexible for complex path-selection policies compared to routers.

Do modern data-center switches still literally run the self-learning algorithm described here?

The core algorithm — learn from source, forward or flood based on destination — remains the default forwarding behavior of essentially every Ethernet switch chip in production, implemented in hardware for line-rate performance. However, large modern deployments typically layer significant additional machinery on top: VLANs to segment broadcast domains, spanning tree or newer loop-prevention protocols (like TRILL or multi-chassis link aggregation) to safely use redundant links, and in many data centers, centralized SDN controllers that install specific forwarding rules rather than relying purely on organic learning. So the mechanism described here is the foundational primitive, not the whole story, but it is still the layer everything else is built on top of.

What is the practical difference in behavior between a hub and a switch, given the same physical cabling?

A hub is a pure physical-layer repeater: every bit arriving on any port is repeated out every other port, meaning all attached hosts share one collision domain, contend for the same shared bandwidth, and can all observe each other's traffic. A switch, running self-learning and filtering, gives each port its own collision domain and forwards a given frame only toward the interface where its destination is known to reside, sending it everywhere only when the destination is unknown or is a broadcast address. The practical consequences are large: aggregate throughput scales with the number of ports rather than being capped by one shared medium, unrelated conversations can proceed in parallel at full link rate, and hosts no longer casually observe traffic addressed to other hosts.

Before this

Where this leads