Skip to content
VLSI Mentor

Ethernet · Module 25

"VLANs Improve Performance Automatically"

Segmentation moves no bits: the same 6.4 Tb/s before and after, a trunk carrying 320 broadcasts a second at every VLAN count, and a tag that costs 4.76% of the wire.

Chapter 13.1 said what VLANs are for and Chapter 13.4 built the datapath. Neither chapter claimed a bandwidth improvement, and this one derives why no such claim is available.

The myth, stated as the people who hold it would state it. A flat network is slow because every station hears every other. Dividing it into VLANs cuts the traffic each station sees, so each VLAN gets a share of the switch and the network goes faster.

The first clause is true, the second is true about one specific quantity, and the third does not follow from either.

The kill is conservation and it fits on one line.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
a switch with aggregate capacity C, offered load L
divide its ports into V VLANs
the capacity is still C and the offered load is still L
Δ throughput = 0

And the tag is not free.

Wire slotPayload efficiencyThe tag's cost
64-octet frame, untagged84 octets54.76%
64-octet frame, tagged88 octets52.27%4.762% of the wire
1 518-octet frame, tagged1 542 octets97.28%0.260%
9 018-octet frame, tagged9 042 octets99.54%0.044%

The only effect a VLAN has on bandwidth is negative, and it is 4.76% of the wire at minimum frame size — which is Chapter 24.3 §1's framing-tax arithmetic with four more octets in it.

What a VLAN genuinely does change is Chapter 12.4's flood width, and that change is large. Sections 4 and 6 derive it, Section 8 finds where it stops helping, and Section 10 finds the case it makes worse.


1. Scope — Conservation, and the One Quantity That Moves

This chapter owns four derivations.

What is derived
Sections 2 to 3conservation: Δ throughput is zero, and the tag costs 4.76% at minimum frame size
Sections 4 to 7flood width and domain rate at 64 ports — 63 copies against 7, and 315 broadcasts per second against 35
Sections 8 to 9the trunk, which carries every VLAN's broadcasts and is unchanged by segmentation
Sections 10 to 13three cases where VLANs make throughput worse, priced

What this chapter does not own. Chapter 13.1 owns why VLANs exist; Chapter 13.2 owns the four octets and their fields; Chapter 13.3 owns access and trunk port behaviour; Chapter 13.4 owns the datapath and its cost at a 24-port switch. This chapter uses all four, re-derives none, and scales Chapter 13.4 §8's key-widening result to Chapter 23.3's table rather than repeating it at 8 192 entries.


2. Conservation, Stated as Arithmetic

A switch of sixty four ports at one hundred gigabits per second has an aggregate capacity of six point four terabits per second. Dividing the ports into eight virtual local area networks leaves the port count at sixty four, the port rate at one hundred gigabits per second, the fabric bandwidth unchanged, the packet buffer shared and dynamically thresholded, and the egress scheduler serving all queues. The aggregate capacity is therefore still six point four terabits per second and the offered load is unchanged, so the change in throughput is zero. The one bandwidth quantity that does move is the tag: four octets added to every frame on a trunk, which is four point seven six per cent of an eighty four octet wire slot at minimum frame size, zero point two six per cent at fifteen hundred and thirty eight, and zero point zero four four per cent at nine thousand and thirty eight.64 ports × 100Gb/s6.4 Tb/s aggregateDivide into 8VLANsa membership relationPorts: 64unchangedRate: 100 Gb/sunchangedFabric and buffershared, unchangedStill 6.4 Tb/sΔ throughput = 0+4 octets ontrunks4.76% at 64 octetsThe onlybandwidth effectand it is negative12
Figure 1 — every term in the capacity expression survives segmentation unchanged, and the tag adds four octets.

The myth's central claim is that dividing a switch gives each part more. Write the conservation law down and it disappears.

Let the switch have N ports each at rate R, so aggregate capacity is C = N × R. Divide the ports into V VLANs of N ÷ V ports each.

BeforeAfter
portsNN
port rateRR
aggregate capacityN × RN × R
offered loadLL
fabric bandwidthunchangedunchanged
bufferunchangedunchanged, and now partitioned by policy

Nothing in the second column differs from the first, and that is the whole of it. A VLAN is a membership relation evaluated during forwarding — Chapter 13.4 §6's key construction — and evaluating a relation does not create a link.

Two objections are worth answering because they are the ones people raise.

Objection one: "but each VLAN now has the switch to itself." It does not. Chapter 23.3 §9's packet buffer is shared and dynamically thresholded, the fabric is shared, and the egress scheduler serves all queues. A VLAN is not a partition of the hardware; it is a constraint on which egress ports a frame may reach.

Objection two: "but the traffic is more local now." Segmenting does not move a station. If two stations that talked to each other end up in different VLANs, their traffic now goes through a router, which is strictly more hops and strictly more latency. Segmentation can make the traffic pattern worse and never makes it better, because it does not choose who talks to whom.


3. RTL 1 — The VLAN Package and the Tag Cost Model

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// vlanperf_pkg -- the constants a conservation argument needs, with
// every derived figure computed here rather than written as a literal.
//
// Unit: Chapter 23.3 Section 2's bitcell equivalent.
//   1 BCE = 0.35 GE = one bit of usable on-die SRAM
//   1 flip-flop = 20 BCE
//   Chapter 19.7 Section 19's MAC receive datapath = 283 320 BCE
//   Chapter 23.3's 64-port switch = 5.62e8 BCE, table 128k x 96 b
// ---------------------------------------------------------------------
package vlanperf_pkg;

  localparam int unsigned DATAPATH_BCE  = 283_320;
  localparam int unsigned BCE_PER_FLOP  = 20;
  localparam int unsigned SWITCH_BCE_E4 = 56_200;      // 5.62e8 / 1e4
  localparam int unsigned TBL_ENTRIES   = 128 * 1024;
  localparam int unsigned TBL_WIDTH     = 96;

  // ---- Chapter 24.3 Section 1's framing tax ---------------------------
  localparam int unsigned OCT_FIXED = 38;   // preamble 8, gap 12,
                                            // addresses 12, FCS 4, type 2
  // ---- Chapter 13.2's tag ----------------------------------------------
  localparam int unsigned OCT_TAG   = 4;    // TPID 2 + TCI 2
  localparam int unsigned VID_BITS  = 12;
  localparam int unsigned VID_USABLE = 4094;   // 0 and 4095 reserved

  // ---- Chapter 12.4 Section 10's domain arithmetic ---------------------
  localparam int unsigned DEFAULT_B_PER_S = 5;   // broadcasts per station

  typedef enum logic [1:0] {
    PORT_ACCESS = 2'd0,       // Chapter 13.3
    PORT_TRUNK  = 2'd1,
    PORT_HYBRID = 2'd2
  } portmode_e;

  // ---- derived: wire cost ----------------------------------------------
  function automatic int unsigned wire_slot(int unsigned payload,
                                            bit tagged);
    return payload + OCT_FIXED + (tagged ? OCT_TAG : 0);
  endfunction

  function automatic int unsigned tag_cost_ppm(int unsigned payload);
    return (OCT_TAG * 1_000_000) / wire_slot(payload, 1'b0);
  endfunction

  function automatic int unsigned efficiency_ppm(int unsigned payload,
                                                 bit tagged);
    return (payload * 1_000_000) / wire_slot(payload, tagged);
  endfunction

  // ---- derived: flood width --------------------------------------------
  function automatic int unsigned ports_per_vlan(int unsigned ports,
                                                 int unsigned vlans);
    return (vlans == 0) ? ports : (ports / vlans);
  endfunction

  function automatic int unsigned flood_copies(int unsigned ports,
                                               int unsigned vlans);
    int unsigned p;
    p = ports_per_vlan(ports, vlans);
    return (p == 0) ? 0 : (p - 1);
  endfunction

  // ---- derived: per-station broadcast rate ------------------------------
  function automatic int unsigned station_rx_per_s(int unsigned ports,
                                                   int unsigned vlans,
                                                   int unsigned b_per_s);
    return flood_copies(ports, vlans) * b_per_s;
  endfunction

  // ---- derived: the trunk, which segmentation does not reduce -----------
  function automatic int unsigned trunk_per_s(int unsigned ports,
                                              int unsigned vlans,
                                              int unsigned b_per_s);
    // every VLAN's stations, all of them, cross the trunk.
    return ports_per_vlan(ports, vlans) * vlans * b_per_s;
  endfunction

  function automatic int unsigned datapaths_milli(int unsigned bce);
    return (bce * 1000) / DATAPATH_BCE;
  endfunction

endpackage
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// tag_cost_model -- what four octets cost, and the conservation law
// that says nothing else about bandwidth changed.
//
// The output that matters is throughput_delta_ppm, which is zero for
// every configuration. The tag's cost is the only nonzero bandwidth
// figure in this chapter and it has the wrong sign.
// ---------------------------------------------------------------------
module tag_cost_model
  import vlanperf_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [15:0] payload_octets,
  input  logic        tagged,
  input  logic [15:0] ports,
  input  logic [15:0] vlans,
  input  logic [15:0] port_rate_gbps,

  output logic [31:0] slot_untagged,
  output logic [31:0] slot_tagged,
  output logic [31:0] tag_cost_ppm_o,
  output logic [31:0] eff_untagged_ppm,
  output logic [31:0] eff_tagged_ppm,
  output logic [31:0] aggregate_gbps_before,
  output logic [31:0] aggregate_gbps_after,
  output logic signed [31:0] throughput_delta_ppm,
  output logic        capacity_is_conserved,
  output logic        only_effect_is_negative,
  output logic [31:0] c_evaluations
);
  always_comb begin
    slot_untagged = 32'(wire_slot(int'(payload_octets), 1'b0));
    slot_tagged   = 32'(wire_slot(int'(payload_octets), 1'b1));

    tag_cost_ppm_o   = 32'(tag_cost_ppm(int'(payload_octets)));
    eff_untagged_ppm = 32'(efficiency_ppm(int'(payload_octets), 1'b0));
    eff_tagged_ppm   = 32'(efficiency_ppm(int'(payload_octets), 1'b1));

    // Section 2's conservation law, evaluated rather than asserted.
    aggregate_gbps_before = 32'(ports) * 32'(port_rate_gbps);
    aggregate_gbps_after  = 32'(ports) * 32'(port_rate_gbps);
    throughput_delta_ppm  = 32'sd0;

    capacity_is_conserved = (aggregate_gbps_after == aggregate_gbps_before);

    // And the one bandwidth figure that does move.
    only_effect_is_negative = tagged
                           && (eff_tagged_ppm < eff_untagged_ppm);
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) c_evaluations <= '0;
    else        c_evaluations <= c_evaluations + 32'd1;
  end
endmodule

Classification: an accounting model whose central output is a hard-wired zero.

What it teaches: that throughput_delta_ppm is zero and vlans appears nowhere in the capacity calculation. The module takes the VLAN count as an input and does not use it, deliberately — because there is no term in N × R for it, and a model that produced a nonzero delta would have to invent one.

And it teaches that tag_cost_ppm_o reports 47 619 at a 46-octet payload4.762% of the wireand 2 600 at 1 500 octets and 442 at 9 000. Chapter 8.3 §2's hyperbola once more: the constant grew by four octets and the shape did not change.

Deliberately simplified: the model treats every frame as tagged or untagged uniformly, where a real switch tags on trunk ports and strips on access ports — Chapter 13.3 §3's rule — so the 4.76% is paid on trunk links and not on access links. Ports are divided evenly among VLANs, which no deployment does. And aggregate_gbps_after is written as a separate expression identical to before, which a synthesis tool will collapse and which is written out so the conservation is visible in the source rather than argued in a comment.

Production implication: the trunk-only tagging is the detail that makes the 4.76% bearable and it is worth being precise about where it is paid. An access port carries untagged frames and pays nothing; a trunk carries tagged frames and pays 4.76% at minimum frame size. So the cost falls exactly on the links that are already the most heavily loaded — the uplinks — and Section 8 shows those same links carry every VLAN's broadcast traffic unreduced. A design that segments to relieve its uplinks has added 4.76% to them and moved none of their broadcast load, which is the chapter's central finding arriving as a deployment consequence.


4. What a VLAN Actually Changes — the Flood Width

A flooded frame arriving at one port of a sixty four port switch. In a flat network it is replicated to sixty three other ports. Divided into two virtual local area networks it reaches thirty one, into four it reaches fifteen, into eight it reaches seven, and into thirty two it reaches one. Eight virtual local area networks therefore reduce the flood width to eleven point one per cent of its unsegmented value. But what that is worth depends on how often frames flood. At a flood share of one tenth of one per cent the mean egress copies per frame fall from one point zero six two to one point zero zero six, an improvement of five point three per cent. At one per cent the improvement is thirty four point six per cent, at five per cent sixty eight point three, and at nineteen point five per cent eighty three point four. So the width reduction is a factor and the flood share is the other factor, and the property that names only the first is section twenty's rejected class.One flooded frameat one ingress port1 VLAN63 copies8 VLANs7 copies — 11.1%Width falls 9×the first factor× the flood sharethe second factor0.1% share5.3% improvement19.5% share83.4% improvementless 4.76%the tag, on trunks12
Figure 2 — the flood width falls by the VLAN count, and what the reduction is worth is that factor times the flood share.

Section 2 found the bandwidth delta to be zero. This section finds the quantity that does move, and it moves by a factor of nine.

Chapter 12.4 §3 established that a flood is the only one-to-many operation in a switch and that the multiplier is the port count less one. A VLAN replaces the port count with the VLAN's member count.

Configuration, 64 portsPorts per VLANCopies per flooded frameShare of the unsegmented width
1 VLAN6463100%
2 VLANs323149.2%
4 VLANs161523.8%
8 VLANs8711.1%
16 VLANs434.8%
32 VLANs211.6%

Eight VLANs of eight ports reduce a flood's egress demand to 11.1% of its unsegmented value, and that is a real, large, correctly-claimed improvement in exactly one quantity.

Put it in the units Chapter 12.4 §3 used, at Chapter 23.3's scale. One port flooding minimum-size frames at 100 Gb/s emits 148.81 Mpps.

VLANsCopiesEmissions/s from one flooding portOf the switch's 9.524 Gpps budget
1639.375 G98.4%
4152.232 G23.4%
871.042 G10.9%
1630.446 G4.7%

Row one is the number this chapter shares with Chapter 25.5: one port flooding at line rate consumes 98.4% of a 64-port switch's entire frame-emission budget. Row three says segmentation takes that to 10.9%.

So the claim "VLANs improve performance" is true of a switch that is flooding and false of one that is not, and the difference between those two switches is Chapter 12.5's table rather than anything about VLANs.


5. RTL 2 — The Flood-Width Model

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// flood_width_model -- Chapter 12.4 Section 3's amplification with the
// port count replaced by a VLAN's member count, and the flood share
// that bounds what the reduction is worth.
//
// The output that matters is improvement_ppm, because it is zero when
// nothing was flooding -- which is the condition the myth omits.
// ---------------------------------------------------------------------
module flood_width_model
  import vlanperf_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [15:0] ports,
  input  logic [15:0] vlans,
  input  logic [31:0] flood_share_ppm,
  input  logic [31:0] port_pps_k,          // thousands of frames/s
  input  logic [31:0] switch_budget_pps_k,

  output logic [15:0] members_per_vlan,
  output logic [15:0] copies_segmented,
  output logic [15:0] copies_flat,
  output logic [31:0] width_share_ppm,
  output logic [31:0] emissions_flat_k,
  output logic [31:0] emissions_segmented_k,
  output logic [31:0] budget_share_flat_ppm,
  output logic [31:0] budget_share_seg_ppm,
  output logic [31:0] mean_copies_flat_x1000,
  output logic [31:0] mean_copies_seg_x1000,
  output logic [31:0] improvement_ppm,
  output logic        improvement_needs_flooding,
  output logic [31:0] c_evaluations
);
  always_comb begin
    members_per_vlan = 16'(ports_per_vlan(int'(ports), int'(vlans)));
    copies_segmented = 16'(flood_copies(int'(ports), int'(vlans)));
    copies_flat      = 16'(flood_copies(int'(ports), 1));

    width_share_ppm = (copies_flat == 0) ? 32'd0
                    : ((32'(copies_segmented) * 1_000_000) / 32'(copies_flat));

    emissions_flat_k      = port_pps_k * 32'(copies_flat);
    emissions_segmented_k = port_pps_k * 32'(copies_segmented);

    budget_share_flat_ppm = (switch_budget_pps_k == 0) ? 32'd0
                          : ((emissions_flat_k * 1_000_000)
                             / switch_budget_pps_k);
    budget_share_seg_ppm  = (switch_budget_pps_k == 0) ? 32'd0
                          : ((emissions_segmented_k * 1_000_000)
                             / switch_budget_pps_k);

    // Mean egress copies per frame: 1 normally, copies when flooding.
    mean_copies_flat_x1000 = 32'd1000
      + ((flood_share_ppm * (32'(copies_flat) - 32'd1)) / 32'd1000);
    mean_copies_seg_x1000  = 32'd1000
      + ((flood_share_ppm * (32'(copies_segmented) - 32'd1)) / 32'd1000);

    improvement_ppm = (mean_copies_flat_x1000 == 0) ? 32'd0
                    : (((mean_copies_flat_x1000 - mean_copies_seg_x1000)
                        * 1_000_000) / mean_copies_flat_x1000);

    // THE condition the myth omits.
    improvement_needs_flooding = (flood_share_ppm != 32'd0);
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) c_evaluations <= '0;
    else        c_evaluations <= c_evaluations + 32'd1;
  end
endmodule

Classification: Chapter 12.4 §3's amplification with one substitution, and a weighting that bounds what the substitution buys.

What it teaches: that improvement_ppm is zero when flood_share_ppm is zero, and that this is the module's whole contribution over the naive version. A model that reports only width_share_ppm says eight VLANs cut flooding to 11.1% and stops there; this one weights that by how much flooding there was, and at a 0.1% flood share the improvement is 5.3%.

And it teaches that budget_share_flat_ppm reports 984 252 for one flooding port on a 64-port 100 Gb/s switch98.4% of Chapter 23.3 §2's 9.524 Gpps pipeline budget — which is the number that makes a flood an emergency rather than an inefficiency.

Deliberately simplified: ports divide evenly among VLANs, which no deployment does, and an uneven division makes the largest VLAN the binding one. flood_share_ppm is a single scalar where the three flood causes have different shares and different fates at the receiver — Chapter 12.4 §6 established that an unknown unicast costs the receiving station nothing and a broadcast costs it everything. And the model counts egress copies rather than egress octets, which is the right unit for a frame-rate budget and the wrong one for a bandwidth budget.

Production implication: the flood-cause distinction is the one that changes what a deployment should do. A switch flooding unknown unicast has a table problem and segmentation treats the symptomChapter 25.5's subject. A switch flooding broadcast has a domain-size problem and segmentation is the correct and only fix at layer 2 — Chapter 12.4 §10's domain limit. A switch flooding multicast has a membership problem and neither helps, because Chapter 12.4 §13 established there is no local fix. Three causes, three different verdicts on the same intervention, and a flood_share_ppm that does not distinguish them gives one answer to three questions.


6. The Domain Rate, and Where It Genuinely Helps

Flood width is an egress demand inside the switch. The broadcast domain's size is a load on every station's CPU, and that is the quantity segmentation improves without qualification.

Chapter 12.4 §10's method: with N stations each emitting B broadcasts per second, each station receives (N − 1) × B.

Configuration, 64 ports, B = 5/sStations per domainEach station receives
1 VLAN64315/s
2 VLANs32155/s
4 VLANs1675/s
8 VLANs835/s
16 VLANs415/s

And unlike the flood width, this improvement has no flood_share qualifier, because a broadcast is always floodedChapter 12.4 §6: a card cannot discard it, the address means everyone, and every broadcast reaches every host's CPU on every station, always.

Segmentation's one unconditional benefit is that it reduces how many broadcasts each station's CPU must process, and at 64 ports divided into 8 it is a factor of nine.

Chapter 12.4 §10 turned this into a domain-size limit and the same arithmetic gives the VLAN count a deployment needs.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
station budget ÷ B = stations per domain
64 ports ÷ stations per domain = VLANs required
Per-station budgetB = 5/sStationsVLANs needed at 64 ports
500/s51011 — 64 fits
100/s5214
50/s5116
20/s5513

Row one is the case a deployment is usually ina 64-port switch in one VLAN puts 315 broadcasts per second on each station, against a budget of 500so segmentation is not required and the myth's claim has no room to be true.


7. RTL 3 — The Domain-Rate Model

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// domain_rate_model -- Chapter 12.4 Section 10's arithmetic with the
// VLAN count as the free variable, and the CPU budget as the bound.
//
// The output that matters is domain_spans_switches, which is an input
// the switch cannot determine and which changes the answer by a factor
// of the fabric's size.
// ---------------------------------------------------------------------
module domain_rate_model
  import vlanperf_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [15:0] ports_per_switch,
  input  logic [15:0] switches_in_domain,
  input  logic [15:0] vlans,
  input  logic [15:0] b_per_station_s,
  input  logic [15:0] cpu_budget_fps,
  input  logic [15:0] us_per_frame,

  output logic [31:0] stations_in_domain,
  output logic [31:0] rx_per_station_s,
  output logic [31:0] cpu_us_per_s,
  output logic [15:0] core_share_ppm,
  output logic        within_budget,
  output logic [15:0] vlans_required,
  output logic        domain_spans_switches,
  output logic        switch_can_determine_this,
  output logic [31:0] c_over_budget
);
  logic [31:0] stations_per_vlan;

  always_comb begin
    // The domain is the fabric, not the switch -- Chapter 12.4 Sec 10.
    stations_in_domain = 32'(ports_per_switch) * 32'(switches_in_domain);

    stations_per_vlan = (vlans == 0) ? stations_in_domain
                      : (stations_in_domain / 32'(vlans));

    rx_per_station_s = (stations_per_vlan == 0) ? 32'd0
                     : ((stations_per_vlan - 32'd1) * 32'(b_per_station_s));

    cpu_us_per_s   = rx_per_station_s * 32'(us_per_frame);
    core_share_ppm = 16'(cpu_us_per_s / 32'd1);   // us/s is ppm of a core

    within_budget = (rx_per_station_s <= 32'(cpu_budget_fps));

    // How many VLANs the budget demands.
    vlans_required = (cpu_budget_fps == 0) ? 16'hFFFF
                   : 16'((stations_in_domain * 32'(b_per_station_s)
                          + 32'(cpu_budget_fps) - 32'd1)
                         / 32'(cpu_budget_fps));

    domain_spans_switches = (switches_in_domain > 16'd1);

    // THE gap. A switch learns what it hears; nothing tells it how many
    // other switches share its broadcast domain.
    switch_can_determine_this = 1'b0;
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n)              c_over_budget <= '0;
    else if (!within_budget) c_over_budget <= c_over_budget + 32'd1;
  end
endmodule

Classification: a division and a ceiling, whose interesting output is a hard-wired zero saying the inputs are unavailable.

What it teaches: that core_share_ppm reports 1 575 for a single 64-port switch in one VLAN0.16% of a coreand 102 375 for a 4 096-station domain, which is 10.2%. The rule of thumb everybody carries is the transition between those two, and on one modern switch the broadcast argument for segmentation is weak.

And it teaches that switch_can_determine_this is zero, so vlans_required depends on an input no device supplies. The switch knows its own port count; it does not know how many switches share its broadcast domain, and Chapter 12.4 §10's sub-argument is that the domain is the fabric. A design that computes a VLAN requirement from its own port count has computed it for a topology of one.

Deliberately simplified: vlans_required uses total broadcasts ÷ budget rather than the exact ceil(ports ÷ (budget ÷ B + 1)), so it is conservative by one VLAN in places — it reports 7 where the exact figure is 6 at a 50/s budget — and the conservatism is deliberate in a sizing model. us_per_frame is a single constant where the cost varies enormously by protocol — an ARP request a host must answer costs far more than a discovery beacon it ignores. The model assumes every station emits at the same rate, where a small number of chatty stations dominate. And core_share_ppm treats microseconds per second as parts per million of a core, which is exact and looks like a coincidence.

Production implication: the chatty-station skew is what turns a comfortable domain into an uncomfortable one without the station count changing. A single misconfigured host emitting 500 broadcasts per second raises every other station's receive rate by 500 — which on a 64-station domain takes it from 315 to 815 and past a 500/s budget — and the domain size did not move. So the quantity to monitor is broadcasts received per station, which Chapter 12.4 §11's storm-control mechanism already measures per ingress port, and the per-port view names the offender while the per-domain average hides it. One counter per ingress port, already present in most parts, and the answer is a sort.


8. The Trunk, Which Segmentation Does Not Relieve

Two switches joined by a trunk. Sixty four stations emit five broadcasts per second each, which is three hundred and twenty broadcasts per second in total. In a flat network all sixty four are in one broadcast domain and all three hundred and twenty cross the trunk. Divided into two virtual local area networks of thirty two, each domain produces one hundred and sixty and both cross the trunk, for the same three hundred and twenty. Into four, eight, sixteen or thirty two the arithmetic is identical: the per domain rate falls and the number of domains rises by the same factor, so the trunk carries three hundred and twenty per second in every configuration. And the trunk additionally pays four octets per frame for the tag, which is four point seven six per cent of the wire at minimum frame size, while access ports strip the tag and pay nothing. Segmentation therefore redistributes a load it does not reduce and makes the busiest link slightly worse.64 stations5 broadcasts/s each1 VLAN64 × 5 = 320/s8 VLANs8 × 8 × 5 = 320/sThe trunkcarries every VLAN320/sat every VLAN count+4 octets/frame4.76% at 64 octetsAccess portsstrip the tag, pay 0Busier, notquieterthe busiest link12
Figure 3 — three hundred and twenty broadcasts a second at every VLAN count, because the station count did not change.

Sections 4 and 6 gave segmentation's two genuine benefits, both inside a switch and both about a station. This section is about the link between switches, and there the arithmetic does not move at all.

A trunk carries every VLAN. Chapter 13.3 §2's definition: an access port belongs to one VLAN and a trunk port carries tagged frames for many. So a broadcast in any VLAN crosses the trunk.

Work it at 64 ports and B = 5 per station per second.

VLANsPorts eachStations totalBroadcasts/s on the trunk
16464320
23264320
41664320
8864320
16464320
32264320

Three hundred and twenty broadcasts per second, at every VLAN count, because the station count did not change and every station's broadcasts still cross the trunk. Segmentation redistributes a load it does not reduce.

And the trunk pays the tag. Chapter 13.3 §3: a trunk carries tagged frames, so every frame on it is four octets longer — Section 3's 4.76% at minimum frame size.

Access linkTrunk
frames taggedno — stripped on egressyes
wire cost of the tag04.76% at 64 octets, 0.26% at 1 518
broadcasts carriedits own VLAN'severy VLAN's — unchanged by segmentation
flood copies deliveredreduced by segmentationthe trunk is one port; it carries one copy per VLAN

Row four is the subtlety and it is worth stating precisely. A flooded frame in one VLAN crosses the trunk once — the trunk is a single port, and Chapter 12.4 §5's replication puts one copy on it. So the trunk's flood load is the sum over VLANs of each VLAN's flood rate, and segmenting into more VLANs does not reduce that sum; it only reduces how many ports on the far side receive each copy.

Which produces the chapter's most quotable consequence.

Segmenting 64 ports into 8 VLANs
each station's broadcast CPU load315/s → 35/s — a factor of 9
each flood's egress demand inside the switch63 copies → 7 — a factor of 9
the trunk's broadcast load320/s → 320/s — no change
the trunk's wire cost0 → 4.76% at minimum frame size

Rows one and two improve by nine and rows three and four get worse or stay still, and rows three and four are about the link a deployment is usually worried about.


9. RTL 4 — The Trunk Load Model

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// trunk_load_model -- what the uplink carries before and after
// segmentation, which is the same thing plus a tag.
//
// The output that matters is trunk_relief_ppm, which is zero or
// negative for every configuration. It is the chapter's conservation
// law measured on the link a deployment cares about.
// ---------------------------------------------------------------------
module trunk_load_model
  import vlanperf_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [15:0] ports,
  input  logic [15:0] vlans,
  input  logic [15:0] b_per_station_s,
  input  logic [15:0] mean_frame_octets,
  input  logic [15:0] trunk_rate_gbps,

  output logic [31:0] stations,
  output logic [31:0] trunk_bcast_flat,
  output logic [31:0] trunk_bcast_segmented,
  output logic signed [31:0] trunk_relief_ppm,
  output logic [31:0] trunk_tag_cost_ppm,
  output logic [31:0] trunk_bcast_bps,
  output logic [31:0] trunk_bcast_share_ppm,
  output logic        segmentation_relieves_trunk,
  output logic        trunk_pays_the_tag,
  output logic [31:0] c_evaluations
);
  always_comb begin
    stations = 32'(ports_per_vlan(int'(ports), int'(vlans)))
             * ((vlans == 0) ? 32'd1 : 32'(vlans));

    // Chapter 12.4 Section 10's rate, summed over every VLAN.
    trunk_bcast_flat      = 32'(trunk_per_s(int'(ports), 1, int'(b_per_station_s)));
    trunk_bcast_segmented = 32'(trunk_per_s(int'(ports), int'(vlans),
                                            int'(b_per_station_s)));

    trunk_relief_ppm = (trunk_bcast_flat == 0) ? 32'sd0
                     : $signed((32'(trunk_bcast_flat)
                                - 32'(trunk_bcast_segmented)) * 1_000_000)
                       / $signed(32'(trunk_bcast_flat));

    // And the tag, which the trunk pays and the access ports do not.
    trunk_tag_cost_ppm = 32'(tag_cost_ppm(int'(mean_frame_octets)));

    // Broadcast bandwidth on the trunk, for scale.
    trunk_bcast_bps = trunk_bcast_segmented
                    * (32'(mean_frame_octets) + 32'(OCT_FIXED) + 32'(OCT_TAG))
                    * 32'd8;
    trunk_bcast_share_ppm = (trunk_rate_gbps == 0) ? 32'd0
                          : (trunk_bcast_bps / (32'(trunk_rate_gbps) * 1000));

    // THE two structural facts.
    segmentation_relieves_trunk = (trunk_relief_ppm > 32'sd0);
    trunk_pays_the_tag          = 1'b1;
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) c_evaluations <= '0;
    else        c_evaluations <= c_evaluations + 32'd1;
  end
endmodule

Classification: a sum over VLANs that equals a sum over stations, which is the point.

What it teaches: that trunk_relief_ppm is zero at every VLAN count, because trunk_per_s multiplies the per-VLAN station count by the VLAN count and recovers the total. The function is written that way deliberately — it looks like it depends on the VLAN count and the two factors cancel, which is Section 2's conservation law in the one place a deployment would most like it not to hold.

And it teaches that trunk_bcast_share_ppm puts the load in perspective. At 320 broadcasts per second and a 1 500-octet mean frame, the trunk carries 3.95 Mb/s of broadcast — 0.004% of a 100 Gb/s uplink. The broadcast load on a modern trunk is not a bandwidth problem at all, which is why Section 6's CPU argument is the real one and Section 8's tag cost is the real cost.

Deliberately simplified: the model counts broadcasts and not the unknown-unicast floods that share the trunk, and Chapter 25.5 establishes that those can be far larger. Stations emit uniformly. And trunk_relief_ppm is declared signed and can only be zero, which is written out rather than hard-wired so that a reader can see the subtraction produce it.

Production implication: the omitted unknown-unicast flood is what actually loads a trunk and it changes the verdict on segmentation. A switch refusing 19.5% of its addresses — Chapter 25.5's figure at a 128k four-way table offered 131 072 addresses — floods nearly a fifth of its unicast traffic, and every one of those floods crosses the trunk once per VLAN that contains a member. Segmenting into eight VLANs therefore multiplies the trunk's flood load by up to eight, because a frame that was flooded once now has eight VLANs' worth of copies to cross with. That is segmentation making the trunk strictly worse, it is the case Section 10 develops, and it is invisible to a model that counts only broadcasts.


10. Three Cases Where VLANs Make Throughput Worse

Sections 4 and 6 gave the benefits and Section 8 gave the null result. This section gives the negatives, and there are three.

Case one — the tag, on every trunk frame. Section 3: 4.76% of the wire at minimum frame size, 0.26% at 1 518, 0.04% at jumbo — and it is paid on the trunk, which is the busiest link.

Case two — a flood that now crosses the trunk once per VLAN. Section 9's production note. A frame flooded in a flat network crosses the trunk once; in an eight-VLAN network with members on both sides, a flood in each VLAN crosses it separately.

Flat8 VLANs, members on both sides
a broadcast from one station1 trunk crossing1 — it is in one VLAN
the aggregate broadcast load320/s320/s — Section 8
an unknown-unicast flood rate of f per VLANf crossings8f crossings

Row three is the case and it needs the condition stated. A flat network floods an unknown destination once across the trunk; a segmented one floods it once per VLAN in which the destination is unknown — and a destination unknown in one VLAN is usually unknown in all of them, because the reason is the table. So the trunk's flood load multiplies by the VLAN count.

Case three — the forwarding key grew, and so did the table. Chapter 13.4 §8 derived that the key goes from 48 bits to 60 and the table's memory grows by exactly 25%, with no change to the set-occupancy fractions because the key's width appears nowhere in a balls-in-bins calculation.

Scale that to Chapter 23.3's table rather than repeating it at 8 192 entries.

BCE× the datapath% of the switch
Chapter 23.3's MAC table, 128k × 96 b1.26 × 10⁷44.42.24%
12 bits per entry for the VID1 572 8645.550.28%
the table after widening1.42 × 10⁷50.02.52%

A quarter of a per cent of the switch, which is affordable — and it is a cost, in a chapter about a mechanism people believe is a benefit.

Three negatives — 4.76% of the trunk's wire, up to 8× its flood load, and 0.28% of the die — against two positives that are both about scope and neither of which is bandwidth.


11. RTL 5 — The Realignment and Table Cost

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// tag_realign_cost -- what inserting four octets mid-frame costs a
// datapath, and what the widened key costs a table at Chapter 23.3's
// scale.
//
// The output that matters is on_critical_path, which is high: the
// realignment sits in the middle of the fastest path in the design,
// and its cost is a timing margin rather than an area.
// ---------------------------------------------------------------------
module tag_realign_cost
  import vlanperf_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [15:0] datapath_bits,
  input  logic [15:0] max_tags,
  input  logic [31:0] table_entries,
  input  logic [15:0] key_bits_before,
  input  logic [15:0] key_bits_after,

  output logic [15:0] shift_positions,
  output logic [15:0] mux_ways,
  output logic [31:0] realign_ge,
  output logic [31:0] holdover_flops,
  output logic [31:0] key_growth_bits,
  output logic [31:0] table_growth_bce,
  output logic [31:0] table_growth_dp_milli,
  output logic [15:0] table_growth_pct,
  output logic        on_critical_path,
  output logic        occupancy_fractions_move,
  output logic [31:0] c_evaluations
);
  always_comb begin
    // A tag stack of 0..max_tags means a shift of 0, 4, 8, ... octets.
    shift_positions = max_tags + 16'd1;
    mux_ways        = shift_positions;

    // One mux per datapath bit, about 3 GE per 2:1 way.
    realign_ge = 32'(datapath_bits) * 32'(mux_ways - 16'd1) * 32'd3;

    // The octets carried across a beat boundary.
    holdover_flops = 32'(max_tags) * 32'd32;

    // Chapter 13.4 Section 8's widening, at Chapter 23.3's scale.
    key_growth_bits  = 32'(key_bits_after) - 32'(key_bits_before);
    table_growth_bce = table_entries * key_growth_bits;
    table_growth_dp_milli = 32'(datapaths_milli(table_growth_bce));
    table_growth_pct = (key_bits_before == 0) ? 16'd0
                     : 16'((key_growth_bits * 32'd100) / 32'(key_bits_before));

    // Chapter 13.2 Section 2: four octets is a fraction of a word on
    // every datapath wider than 32 bits, so it misaligns everything
    // after it -- in the middle of the fastest path in the design.
    on_critical_path = (datapath_bits > 16'd32);

    // Chapter 13.4 Section 8's structural result: the key's width
    // appears nowhere in a balls-in-bins calculation.
    occupancy_fractions_move = 1'b0;
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) c_evaluations <= '0;
    else        c_evaluations <= c_evaluations + 32'd1;
  end
endmodule

Classification: a mux count and a memory delta, with two constants that carry results from Chapter 13.2 and Chapter 13.4.

What it teaches: that realign_ge at a 1 024-bit datapath with two tags is 6 144 GE1 024 bits × 2 extra ways × 3 GE — which is small in area and on the critical path. Chapter 13.2 §2 established why: four octets is half a word at 64 bits, a quarter at 128 and an eighth at 256, so inserting or removing it misaligns everything after it. on_critical_path is the output that matters and the gate count is not.

And it teaches that table_growth_bce is 1 572 864 at Chapter 23.3's 128k entries with a 12-bit VID5.55 datapaths, 0.28% of the switch — while occupancy_fractions_move is zero, which is Chapter 13.4 §8's structural result: widening the key widens what is stored and compared and does not widen the index.

Deliberately simplified: the realignment is priced as a flat mux per bit, where a real implementation folds it into an existing alignment stage and pays a delay rather than an area. holdover_flops assumes the carried-over octets are registered, which a combinational implementation avoids at a further timing cost. And max_tags bounds the stack where Chapter 13.2 §7's question of how deep a stack to tolerate has no standard answer.

Production implication: the timing cost is the one that is never in a budget and always in a schedule. Chapter 23.6 §8 established that frequency is an output of the implementation flow, and a three-way realignment mux inserted between a parser and a datapath is exactly the kind of structure that turns a closing design into one that misses by a few per cent. The area is 6 144 GE — nothing — and the delay is one mux level on the block Chapter 19.1 §9 already calls the MAC's critical path. A design that adds VLAN support late discovers this after synthesis, and the fix is a pipeline stage, which costs latency in a design whose latency budget was closed.


12. Where the Claim Is Actually True

Five sections of negatives and nulls owe a positive statement, and there is one. It is narrow, it is conditional, and the condition is measurable.

Segmentation improves delivered throughput exactly when a switch was already wasting egress capacity on floods. Section 5's arithmetic, restated as a decision rule.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
improvement ≈ flood_share × (copies_flat − copies_segmented) ÷ mean_copies_flat
and the tag costs 4.76% of the trunk's wire at minimum frame size
so segmentation pays when   flood_share × (copies_flat − copies_segmented)
                          > tag_cost × mean_copies_flat

Work it at 64 ports into 8 VLANs, where copies_flat − copies_segmented is 56.

Flood shareImprovementTag cost at the trunk's mean frameNet, minimum framesNet, 1 518-octet frames
0.1%5.3%4.76% / 0.26%+0.5%+5.0%
1%34.6%4.76% / 0.26%+29.8%+34.3%
5%68.3%4.76% / 0.26%+63.5%+68.0%
19.5%83.4%4.76% / 0.26%+78.6%+83.1%

Every row is positive, which is the honest result — and row one is positive by half a percentage point at minimum frame size, which is inside the noise of any measurement anybody would make.

Segmentation is worth its cost above about a 0.1% flood share, and the flood share is a quantity Chapter 12.4 §15's telemetry already reports.

And the three benefits, ordered by how conditional they are.

BenefitConditional onSize at 64 ports into 8 VLANs
fewer broadcasts per station's CPUnothing — a broadcast is always flooded315/s → 35/s, a factor of 9
smaller blast radius for a stormnothinga storm reaches 8 stations, not 64
lower flood egress demandthere being floods63 copies → 7, weighted by the flood share
more bandwidthnone, ever

Rows one and two are unconditional and neither is bandwidth. Row three is the bandwidth-adjacent one and it is conditional. Row four is the myth.


13. RTL 6 — The Benefit Auditor

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// benefit_auditor -- which of segmentation's claimed benefits this
// deployment will actually receive, given its own counters.
//
// The output that matters is bandwidth_benefit, which is hard-wired
// zero. Every other benefit this module reports is about a scope.
// ---------------------------------------------------------------------
module benefit_auditor
  import vlanperf_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic [47:0] c_flooded,
  input  logic [47:0] c_forwarded,
  input  logic [15:0] ports,
  input  logic [15:0] vlans,
  input  logic [15:0] mean_frame_octets,
  input  logic [15:0] b_per_station_s,
  input  logic [15:0] cpu_budget_fps,

  output logic [31:0] flood_share_ppm,
  output logic [31:0] egress_improvement_ppm,
  output logic [31:0] tag_cost_ppm_o,
  output logic signed [31:0] net_ppm,
  output logic        worth_the_tag,
  output logic [31:0] cpu_improvement_ppm,
  output logic        cpu_benefit_unconditional,
  output logic [31:0] blast_radius_before,
  output logic [31:0] blast_radius_after,
  output logic        bandwidth_benefit,
  output logic [31:0] c_audits
);
  logic [31:0] copies_flat, copies_seg, mean_flat_x1000, mean_seg_x1000;

  always_comb begin
    flood_share_ppm = (c_forwarded == 0) ? 32'd0
                    : 32'((c_flooded * 48'd1_000_000) / c_forwarded);

    copies_flat = 32'(flood_copies(int'(ports), 1));
    copies_seg  = 32'(flood_copies(int'(ports), int'(vlans)));

    mean_flat_x1000 = 32'd1000
                    + ((flood_share_ppm * (copies_flat - 32'd1)) / 32'd1000);
    mean_seg_x1000  = 32'd1000
                    + ((flood_share_ppm * (copies_seg - 32'd1)) / 32'd1000);

    egress_improvement_ppm = (mean_flat_x1000 == 0) ? 32'd0
      : (((mean_flat_x1000 - mean_seg_x1000) * 1_000_000) / mean_flat_x1000);

    tag_cost_ppm_o = 32'(tag_cost_ppm(int'(mean_frame_octets)));

    net_ppm = $signed(egress_improvement_ppm) - $signed(tag_cost_ppm_o);
    worth_the_tag = (net_ppm > 32'sd0);

    // The unconditional benefit: a broadcast is always flooded, so the
    // per-station CPU load falls with the domain size regardless of
    // what the flood share is.
    cpu_improvement_ppm = (copies_flat == 0) ? 32'd0
      : (((copies_flat - copies_seg) * 1_000_000) / copies_flat);
    cpu_benefit_unconditional = 1'b1;

    blast_radius_before = copies_flat + 32'd1;
    blast_radius_after  = copies_seg + 32'd1;

    // THE constant. Section 2's conservation law, as a bit.
    bandwidth_benefit = 1'b0;
  end

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) c_audits <= '0;
    else        c_audits <= c_audits + 32'd1;
  end
endmodule

Classification: a decision model built entirely from counters a switch already keeps.

What it teaches: that worth_the_tag is computable from c_flooded, c_forwarded and a mean frame size, all of which Chapter 12.4 §15 and Chapter 19.7 already provide. The segmentation decision is an arithmetic question about a deployment's own traffic and it is almost always made on a diagram instead.

And it teaches that bandwidth_benefit is a hard-wired zero beside a cpu_improvement_ppm that reports 888 888 at 64 ports into 8 VLANs88.9%, unconditionally. The module is designed so that the real benefit and the mythical one sit next to each other and are visibly different kinds of thing: one is a measured improvement in a CPU load and the other is a constant zero.

Deliberately simplified: flood_share_ppm lumps Chapter 12.4 §2's three flood causes together, and Section 5's production note established that they have three different verdicts on segmentation. net_ppm compares an egress-copy improvement with a wire-octet cost, which are different units — copies per frame against octets per frame — and the comparison is meaningful only because both are expressed as fractions of the same baseline. And the model assumes the flood share is unchanged by segmentation, which Section 10's case two shows is the assumption most likely to be false.

Production implication: that last assumption is the one to test rather than to make, and the test is a before-and-after measurement of the same ratio. Segment a pilot VLAN, leave the rest flat, and compare c_flooded ÷ c_forwarded on the trunk in both. If the ratio rises, Section 10's case two is happening — more VLANs, more keys, more offered addresses, more refusals — and the intervention is making the thing it was deployed to fix worse. The measurement costs nothing because both counters already exist, and it is the only way to distinguish the two directions, since Section 12's model predicts a benefit under an assumption the deployment itself decides.


14. What a Segmentation Claim Must Never Do

Five prohibitions.

#NeverBecause
1claim a bandwidth improvement from segmentationSection 2: N × R has no term for the VLAN count
2quote a flood-width reduction without the flood shareSection 5: 63 → 7 is worth 5.3% at a 0.1% flood share and 83.4% at 19.5%
3claim a trunk is relievedSection 8: 320 broadcasts per second at every VLAN count, and the trunk pays the tag
4segment to fix unknown-unicast floodingSection 10: the cause is the table, and more VLANs can offer it more addresses
5cross-VLAN traffic without counting the extra switch traversalSection 2's callout: a split conversation costs the switch twice

Row four is the one that inverts the outcome and Section 13's production note gives the test.


15. RTL 7 — VLAN Performance Telemetry

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// vlanperf_telemetry -- the counters that make a segmentation claim
// checkable against the deployment it was made about.
//
// Design rule: every claimed benefit gets a counter, and the claim
// that has no counter is the one to disbelieve.
// ---------------------------------------------------------------------
module vlanperf_telemetry
  import vlanperf_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,
  input  logic        clear,

  input  logic        frame_valid,
  input  logic        frame_tagged,
  input  logic        frame_flooded,
  input  logic        frame_broadcast,
  input  logic        frame_unknown_unicast,
  input  logic        frame_crossed_router,
  input  logic        on_trunk,
  input  logic [15:0] frame_octets,
  input  logic [15:0] copies_emitted,

  output logic [47:0] c_frames,
  output logic [47:0] c_tagged,
  output logic [47:0] c_flooded_o,
  output logic [47:0] c_broadcast,
  output logic [47:0] c_unknown_unicast,
  output logic [47:0] c_cross_vlan,
  output logic [47:0] c_trunk_frames,
  output logic [47:0] c_trunk_tag_octets,
  output logic [47:0] c_copies,
  output logic [31:0] flood_share_ppm_o,
  output logic [31:0] mean_copies_x1000,
  output logic [31:0] cross_vlan_ppm,
  output logic [31:0] trunk_tag_overhead_ppm,
  output logic        flood_is_unknown_unicast_dominated
);
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n || clear) begin
      c_frames <= '0; c_tagged <= '0; c_flooded_o <= '0;
      c_broadcast <= '0; c_unknown_unicast <= '0; c_cross_vlan <= '0;
      c_trunk_frames <= '0; c_trunk_tag_octets <= '0; c_copies <= '0;
    end else if (frame_valid) begin
      c_frames <= c_frames + 48'd1;
      c_copies <= c_copies + 48'(copies_emitted);
      if (frame_tagged)          c_tagged          <= c_tagged + 48'd1;
      if (frame_flooded)         c_flooded_o       <= c_flooded_o + 48'd1;
      if (frame_broadcast)       c_broadcast       <= c_broadcast + 48'd1;
      if (frame_unknown_unicast) c_unknown_unicast <= c_unknown_unicast + 48'd1;
      if (frame_crossed_router)  c_cross_vlan      <= c_cross_vlan + 48'd1;
      if (on_trunk) begin
        c_trunk_frames     <= c_trunk_frames + 48'd1;
        c_trunk_tag_octets <= c_trunk_tag_octets + 48'(OCT_TAG);
      end
    end
  end

  always_comb begin
    flood_share_ppm_o = (c_frames == 0) ? 32'd0
                      : 32'((c_flooded_o * 48'd1_000_000) / c_frames);

    mean_copies_x1000 = (c_frames == 0) ? 32'd0
                      : 32'((c_copies * 48'd1000) / c_frames);

    // Section 2's callout: a split conversation costs the switch twice.
    cross_vlan_ppm = (c_frames == 0) ? 32'd0
                   : 32'((c_cross_vlan * 48'd1_000_000) / c_frames);

    // Section 8: the trunk pays 4 octets a frame and nothing else does.
    trunk_tag_overhead_ppm = (c_trunk_frames == 0) ? 32'd0
      : 32'((c_trunk_tag_octets * 48'd1_000_000)
            / (c_trunk_frames * 48'd84));

    // Section 5's production note: three flood causes, three verdicts.
    flood_is_unknown_unicast_dominated =
      (c_flooded_o != 48'd0) && (c_unknown_unicast > c_broadcast);
  end
endmodule

Classification: nine counters and four ratios, of which one ratio decides the chapter's whole argument for a given deployment.

What it teaches: that flood_share_ppm_o is the number Section 12's decision rule needs and it is already in the hardware. Chapter 12.4 §15's flood-to-forward telemetry provides it; a deployment arguing about VLANs without reading it is arguing about a quantity it could measure in an hour.

And it teaches that flood_is_unknown_unicast_dominated is the bit that selects the right intervention. A flood share dominated by unknown unicast points at Chapter 12.5's table and segmentation treats a symptom; one dominated by broadcast points at Chapter 12.4 §10's domain size and segmentation is the correct fix. Same ratio, different cause, opposite verdicts.

Deliberately simplified: copies_emitted is supplied from the replication engine rather than counted here, so the module trusts a structure it is measuring. cross_vlan_ppm requires a frame_crossed_router input the switch cannot generate — it knows a frame left toward a router and not that it came back — so a real deployment measures it by correlating ingress and egress at the router port. And trunk_tag_overhead_ppm normalises against an 84-octet slot rather than the observed mean frame.

Production implication: the cross-VLAN counter is the one nobody has and it is the one that catches Section 2's callout in the field. A conversation split across VLANs enters the switch, leaves toward the router, comes back, and leaves againtwo ingress events and two egress events for one conversation — and every counter in the switch records both halves as ordinary traffic. The signature is a router port whose ingress and egress rates are both high and nearly equal, which is exactly what a router port looks like when it is doing its job, so the pathological case and the healthy case are indistinguishable without knowing the traffic matrix. The measurement that separates them is a per-VLAN-pair matrix at the router, which is counters and is why nobody builds it — and the practical substitute is to compare the router port's rate against the switch's total, since a healthy deployment sends a small fraction of its traffic through a router and a badly segmented one sends most of it.


16. RTL 8 — The Segmentation Conformance Monitor

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------------
// vlanperf_conformance -- the checks that hold a segmentation claim to
// the quantity it actually moved.
//
// There is no check that throughput improved, because Section 2
// establishes it cannot. Every check here is about a claim's shape.
// ---------------------------------------------------------------------
module vlanperf_conformance
  import vlanperf_pkg::*;
(
  input  logic        clk,
  input  logic        rst_n,

  input  logic        claims_bandwidth_gain,
  input  logic        claims_trunk_relief,
  input  logic        claims_flood_reduction,
  input  logic        flood_share_measured,
  input  logic [31:0] flood_share_ppm_i,
  input  logic        segmented_to_fix_unknown_unicast,
  input  logic        flood_is_uu_dominated_i,
  input  logic [31:0] cross_vlan_ppm_i,
  input  logic [31:0] cross_vlan_budget_ppm,
  input  logic signed [31:0] net_ppm_i,

  output logic        v_bandwidth_claim,
  output logic        v_trunk_relief_claim,
  output logic        v_flood_claim_unmeasured,
  output logic        v_symptom_treated,
  output logic        v_cross_vlan_excessive,
  output logic        v_net_negative,
  output logic  [5:0] violations,
  output logic        conformant
);
  always_comb begin
    // 1. Section 2 -- there is no term for it.
    v_bandwidth_claim = claims_bandwidth_gain;

    // 2. Section 8 -- 320/s at every VLAN count.
    v_trunk_relief_claim = claims_trunk_relief;

    // 3. Section 5 -- a width reduction is worth the flood share.
    v_flood_claim_unmeasured = claims_flood_reduction && !flood_share_measured;

    // 4. Section 10 -- the cause is the table.
    v_symptom_treated = segmented_to_fix_unknown_unicast
                     && flood_is_uu_dominated_i;

    // 5. Section 2's callout -- a split conversation costs twice.
    v_cross_vlan_excessive = (cross_vlan_ppm_i > cross_vlan_budget_ppm);

    // 6. Section 12 -- the tag is not free.
    v_net_negative = flood_share_measured && (net_ppm_i <= 32'sd0);

    violations = { v_net_negative, v_cross_vlan_excessive, v_symptom_treated,
                   v_flood_claim_unmeasured, v_trunk_relief_claim,
                   v_bandwidth_claim };
    conformant = (violations == 6'b000000);
  end
endmodule

Classification: six checks on claims rather than on behaviour, of which two are unconditional refusals.

What it teaches: that v_bandwidth_claim and v_trunk_relief_claim fire on the claim alone, with no traffic input at all. Section 2's conservation law and Section 8's trunk arithmetic are true of every configuration, so the claims are wrong before any measurement — and a monitor that refuses them without data is correct rather than lazy.

And it teaches that v_flood_claim_unmeasured is the useful one in practice. The flood-reduction claim is true and its size is entirely a function of a ratio the deployment can read. A claim made without reading it is not false; it is unquantified, and this check distinguishes the two.

Deliberately simplified: segmented_to_fix_unknown_unicast is an intent an operator supplies, which no hardware can infer — the same unavoidable input Chapter 25.3 §5 needed for threat. cross_vlan_budget_ppm has no principled default. And there is no check that the flood share fell after segmentation, which Section 13's production note argues is the measurement that matters and which requires a before-and-after rather than an instantaneous state.

Production implication: the before-and-after gap is the general shape of what a runtime monitor cannot do, and it is worth stating because this chapter is the fourth place it has appeared. A monitor evaluates the present; a claim about an intervention is about a difference between two presents. Chapter 24.3 §21's directed test needed the same thing — a regression's pass rate before and after a specification amendment — and Chapter 25.2 §21's needed a count distribution an hour later. The repair in all three is the same: record the quantity with a timestamp and a configuration identifier, so a later comparison is possible, which costs a counter and a register and is the difference between a fabric that can be reasoned about and one that can only be observed.


17. The Five Quantities, Priced Side by Side

Five mechanisms that partition a resource, and what each creates. Virtual local area networks partition a broadcast domain and create nothing. Virtual lanes partition a credit reservation and create nothing, and chapter twenty four point two showed the reservation becomes a sum rather than a maximum. Virtual output queues partition an ingress queue and create nothing, but they remove a coupling that was destroying forty one point four per cent of a switch's capacity under the two minus root two bound, so capacity is recovered rather than created. Priority queues partition an egress scheduler's attention and create nothing. Traffic classes partition a link and create nothing. The general rule therefore has two branches: a partition can recover capacity that a coupling was wasting, as virtual output queues do and as segmentation does on a switch that was already flooding; and a partition can never create capacity that was not there, which is what the myth claims.A partitionof some resourceVLANsa broadcast domainVirtual lanesa credit reservationVirtual outputqueuesan ingress queuePriority queuesa scheduler's attentionCreates nothingconservationRecovers wasteVOQs: 58.6% → 100%What was wastedbefore?the diagnostic question12
Figure 4 — a partition can recover capacity a coupling was wasting; it can never create capacity that was not there.

Everything this chapter derived, at 64 ports divided into 8 VLANs.

QuantityFlat8 VLANsChangeIs it bandwidth?
aggregate capacity6.4 Tb/s6.4 Tb/s0YES, and it does not move
wire per tagged frame, 64 octets8488+4.76%YES, and it is worse
flood copies per flooded frame637−88.9%an egress demand — conditionally
broadcasts per station per second31535−88.9%no — a CPU load
trunk broadcasts per second3203200no, and it does not move either
MAC table1.26 × 10⁷ BCE1.42 × 10⁷+0.28% of the switchno — a cost
a cross-VLAN conversation1 switch traversal2+100%YES, and it is worse

Two rows are bandwidth and improve nothing; two rows are bandwidth and get worse; two rows improve by 88.9% and are not bandwidth; one row is a cost.

Segmentation's genuine, unconditional benefit is that it divides a broadcast domain by the VLAN count. Everything the myth claims beyond that is either conditional on a flood rate the deployment can measure, or false by conservation.

And the decision rule, in one line.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
read c_flooded ÷ c_forwarded
above about 0.1%, segmentation pays for its tag
below it, segment for scope, containment and policy — not for throughput

18. What the Correction Assumes

Eight assumptions.

#AssumptionIf it is false
1ports divide evenly among VLANsthe largest VLAN binds; the flood width is its member count, not the mean
2B = 5 broadcasts per station per secondChapter 12.4 §10's typical figure; every domain-rate number scales linearly with it
3a 4-octet tag — Chapter 13.2a stacked tag is 8 and doubles the wire cost to 9.52% at minimum frame size
4the trunk carries every VLANa trunk pruned to the VLANs with members on both sides carries fewer, and Section 8's null result becomes a partial one
5Chapter 23.3's 128k × 96 b tablethe widening is 12 bits per entry either way; the percentage of the switch scales
6a 12-bit VIDChapter 13.2 §3's field; 4 094 usable values
7flood share unchanged by segmentationSection 10's case two; this is the assumption most likely to be false and the one Section 13's test checks
8BCE prices the table growthSection 19 examines it and it holds

Assumption 4 deserves the caveat because pruning is real and it is the one thing that moves Section 8's result. A trunk configured to carry only the VLANs with members on both sides carries a subset, and if the segmentation is drawn so that most VLANs are local to one switch, the trunk's broadcast load does fall. The condition is a topology property rather than a VLAN-count property: pruning helps exactly when the segmentation aligns with the physical layout, and a deployment that segments by function across a fabric has guaranteed it does not.


19. The Cost, Accounted — in BCE

This chapter's blocks.

BlockFlopsBCE× the datapath
tag_cost_model326400.002
flood_width_model326400.002
domain_rate_model326400.002
trunk_load_model326400.002
tag_realign_cost326400.002
benefit_auditor326400.002
vlanperf_telemetry4809 6000.034
vlanperf_conformance0 — combinational00
this chapter's additions67213 4400.047

Seven of the eight blocks are models and one holds state, which is characteristic of a chapter whose subject is an argument rather than a datapath.

And the designs the blocks describe.

BCE× the datapath% of the switch
Chapter 23.3's MAC table, 48-bit key1.26 × 10⁷44.42.24%
the VID widening, 12 bits × 128k1 572 8645.550.28%
the table after widening1.42 × 10⁷50.02.52%
Chapter 13.4 §17's VLAN state, scaled to 64 ports2.62 × 10⁵0.930.047%
the realignment mux, 1 024 bits, 2 tags6 144 GElogic, not state

Row four is Chapter 13.4 §17's 9.6 KiB of VLAN state at 24 ports, scaled: the per-port arrays grow with the port count and the VID maps do not, so at 64 ports it is about 32 KiB — 2.62 × 10⁵ BCE, 0.047% of the switch. The VLAN machinery itself is nearly free and the table's growth is five times larger, which is Chapter 13.4 §17's finding confirmed at a different scale.


20. Properties Worth Asserting, and One Worth Refusing

Fifty-one properties in six groups, and the refused one is true, measurable, and about one factor of a product.

Group A — conservation and the tag (9).

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// A1. Aggregate capacity does not depend on the VLAN count.
p_cn_conserved: assert property (@(posedge clk) disable iff (!rst_n)
  (aggregate_gbps_after == aggregate_gbps_before));

// A2. And the delta is zero, always.
p_cn_delta_zero: assert property (@(posedge clk) disable iff (!rst_n)
  (throughput_delta_ppm == 32'sd0));

// A3. The model reports conservation.
p_cn_reports: assert property (@(posedge clk) disable iff (!rst_n)
  capacity_is_conserved);

// A4. A tagged slot is four octets longer.
p_cn_slot: assert property (@(posedge clk) disable iff (!rst_n)
  (slot_tagged == slot_untagged + 32'(OCT_TAG)));

// A5. Tagging always lowers efficiency.
p_cn_eff_falls: assert property (@(posedge clk) disable iff (!rst_n)
  (eff_tagged_ppm < eff_untagged_ppm));

// A6. And the model says the only bandwidth effect is negative.
p_cn_negative: assert property (@(posedge clk) disable iff (!rst_n)
  tagged |-> only_effect_is_negative);

// A7. The tag's cost falls as the frame grows -- Chapter 8.3's curve.
p_cn_hyperbola: assert property (@(posedge clk) disable iff (!rst_n)
  (payload_octets > $past(payload_octets)) |->
    (tag_cost_ppm_o <= $past(tag_cost_ppm_o)));

// A8. At minimum frame size it is 47 619 ppm.
p_cn_min_frame: assert property (@(posedge clk) disable iff (!rst_n)
  (payload_octets == 16'd46) |-> (tag_cost_ppm_o == 32'd47_619));

// A9. The VLAN count enters no capacity expression.
p_cn_vlans_absent: assert property (@(posedge clk) disable iff (!rst_n)
  (vlans != $past(vlans)) |-> (aggregate_gbps_after == $past(aggregate_gbps_after)));

Group B — flood width (9).

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// B1. Copies are the member count less one.
p_fw_copies: assert property (@(posedge clk) disable iff (!rst_n)
  (copies_segmented == members_per_vlan - 16'd1));

// B2. Segmenting never raises the copy count.
p_fw_monotone: assert property (@(posedge clk) disable iff (!rst_n)
  (vlans >= 16'd1) |-> (copies_segmented <= copies_flat));

// B3. One VLAN is the flat case.
p_fw_one_vlan: assert property (@(posedge clk) disable iff (!rst_n)
  (vlans == 16'd1) |-> (copies_segmented == copies_flat));

// B4. The width share is the ratio of the two.
p_fw_share: assert property (@(posedge clk) disable iff (!rst_n)
  (copies_flat != 16'd0) |->
    (width_share_ppm == (32'(copies_segmented) * 1_000_000) / 32'(copies_flat)));

// B5. THE qualifier: no flooding, no improvement.
p_fw_needs_flooding: assert property (@(posedge clk) disable iff (!rst_n)
  (flood_share_ppm == 32'd0) |-> (improvement_ppm == 32'd0));

// B6. And with flooding there is one.
p_fw_has_improvement: assert property (@(posedge clk) disable iff (!rst_n)
  ((flood_share_ppm != 32'd0) && (vlans > 16'd1)) |-> (improvement_ppm != 32'd0));

// B7. The improvement never exceeds unity.
p_fw_bounded: assert property (@(posedge clk) disable iff (!rst_n)
  (improvement_ppm <= 32'd1_000_000));

// B8. Emissions are copies times the port rate.
p_fw_emissions: assert property (@(posedge clk) disable iff (!rst_n)
  (emissions_flat_k == port_pps_k * 32'(copies_flat)));

// B9. One flooding port at 64 ports takes most of the budget.
p_fw_budget: assert property (@(posedge clk) disable iff (!rst_n)
  ((ports == 16'd64) && (port_pps_k == 32'd148_810) &&
   (switch_budget_pps_k == 32'd9_524_000))
    |-> (budget_share_flat_ppm >= 32'd980_000));

Group C — the domain rate (8).

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// C1. The domain is the fabric, not the switch.
p_dr_domain: assert property (@(posedge clk) disable iff (!rst_n)
  (stations_in_domain == 32'(ports_per_switch) * 32'(switches_in_domain)));

// C2. Each station receives the others' broadcasts.
p_dr_rx: assert property (@(posedge clk) disable iff (!rst_n)
  (stations_in_domain != 0) |-> (rx_per_station_s <
    (stations_in_domain * 32'(b_per_station_s)) + 32'd1));

// C3. More VLANs never raises the per-station rate.
p_dr_monotone: assert property (@(posedge clk) disable iff (!rst_n)
  (vlans > $past(vlans)) |-> (rx_per_station_s <= $past(rx_per_station_s)));

// C4. The switch cannot determine the domain's extent.
p_dr_unknowable: assert property (@(posedge clk) disable iff (!rst_n)
  (switch_can_determine_this == 1'b0));

// C5. Spanning switches is reported.
p_dr_spans: assert property (@(posedge clk) disable iff (!rst_n)
  (switches_in_domain > 16'd1) |-> domain_spans_switches);

// C6. Within budget is a comparison and nothing else.
p_dr_budget: assert property (@(posedge clk) disable iff (!rst_n)
  within_budget |-> (rx_per_station_s <= 32'(cpu_budget_fps)));

// C7. Over budget is counted.
p_dr_counted: assert property (@(posedge clk) disable iff (!rst_n)
  !within_budget |=> (c_over_budget == $past(c_over_budget) + 32'd1));

// C8. CPU microseconds follow the frame rate.
p_dr_cpu: assert property (@(posedge clk) disable iff (!rst_n)
  (cpu_us_per_s == rx_per_station_s * 32'(us_per_frame)));

Group D — the trunk (8).

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// D1. The trunk's broadcast load is the station count times B.
p_tk_load: assert property (@(posedge clk) disable iff (!rst_n)
  (trunk_bcast_segmented == 32'(trunk_per_s(int'(ports), int'(vlans),
                                            int'(b_per_station_s)))));

// D2. And it does not depend on the VLAN count.
p_tk_invariant: assert property (@(posedge clk) disable iff (!rst_n)
  (trunk_bcast_segmented == trunk_bcast_flat));

// D3. So the relief is zero.
p_tk_no_relief: assert property (@(posedge clk) disable iff (!rst_n)
  (trunk_relief_ppm == 32'sd0));

// D4. And the model says so.
p_tk_reports: assert property (@(posedge clk) disable iff (!rst_n)
  !segmentation_relieves_trunk);

// D5. The trunk pays the tag.
p_tk_pays: assert property (@(posedge clk) disable iff (!rst_n)
  trunk_pays_the_tag);

// D6. The tag cost is Chapter 24.3's arithmetic with four octets.
p_tk_tag_cost: assert property (@(posedge clk) disable iff (!rst_n)
  (trunk_tag_cost_ppm == 32'(tag_cost_ppm(int'(mean_frame_octets)))));

// D7. Broadcast bandwidth is a small share of a fast trunk.
p_tk_small: assert property (@(posedge clk) disable iff (!rst_n)
  ((trunk_rate_gbps >= 16'd100) && (trunk_bcast_segmented <= 32'd1000))
    |-> (trunk_bcast_share_ppm <= 32'd100));

// D8. Station count is preserved across segmentation.
p_tk_stations: assert property (@(posedge clk) disable iff (!rst_n)
  (vlans != 16'd0) |-> (stations == 32'(ports)));

Group E — realignment, table growth and the auditor (9).

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// E1. Shift positions are the tag depth plus one.
p_rl_positions: assert property (@(posedge clk) disable iff (!rst_n)
  (shift_positions == max_tags + 16'd1));

// E2. The realignment is on the critical path above 32 bits.
p_rl_critical: assert property (@(posedge clk) disable iff (!rst_n)
  (datapath_bits > 16'd32) |-> on_critical_path);

// E3. The key's width does not move the occupancy fractions.
p_rl_fractions: assert property (@(posedge clk) disable iff (!rst_n)
  (occupancy_fractions_move == 1'b0));

// E4. Table growth is entries times the added bits.
p_rl_growth: assert property (@(posedge clk) disable iff (!rst_n)
  (table_growth_bce == table_entries * key_growth_bits));

// E5. A 48-to-60-bit key is a 25% growth.
p_rl_25pct: assert property (@(posedge clk) disable iff (!rst_n)
  ((key_bits_before == 16'd48) && (key_bits_after == 16'd60))
    |-> (table_growth_pct == 16'd25));

// E6. The auditor's bandwidth benefit is zero.
p_au_no_bandwidth: assert property (@(posedge clk) disable iff (!rst_n)
  (bandwidth_benefit == 1'b0));

// E7. And the CPU benefit is unconditional.
p_au_cpu: assert property (@(posedge clk) disable iff (!rst_n)
  cpu_benefit_unconditional);

// E8. Worth-the-tag requires a positive net.
p_au_worth: assert property (@(posedge clk) disable iff (!rst_n)
  worth_the_tag |-> (net_ppm > 32'sd0));

// E9. The blast radius shrinks with the VLAN count.
p_au_radius: assert property (@(posedge clk) disable iff (!rst_n)
  (vlans > 16'd1) |-> (blast_radius_after <= blast_radius_before));

Group F — telemetry and conformance (8).

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// F1. Flooded frames are a subset of frames.
p_tl_subset: assert property (@(posedge clk) disable iff (!rst_n)
  (c_flooded_o <= c_frames));

// F2. The flood share is the ratio the decision rule needs.
p_tl_share: assert property (@(posedge clk) disable iff (!rst_n)
  (c_frames != 48'd0) |->
    (flood_share_ppm_o == 32'((c_flooded_o * 48'd1_000_000) / c_frames)));

// F3. Mean copies is at least one.
p_tl_mean: assert property (@(posedge clk) disable iff (!rst_n)
  (c_frames != 48'd0) |-> (mean_copies_x1000 >= 32'd1000));

// F4. A bandwidth claim is always a violation.
p_cf_bandwidth: assert property (@(posedge clk) disable iff (!rst_n)
  claims_bandwidth_gain |-> v_bandwidth_claim);

// F5. So is a trunk-relief claim.
p_cf_trunk: assert property (@(posedge clk) disable iff (!rst_n)
  claims_trunk_relief |-> v_trunk_relief_claim);

// F6. A flood claim needs the share measured.
p_cf_measured: assert property (@(posedge clk) disable iff (!rst_n)
  (claims_flood_reduction && !flood_share_measured) |-> v_flood_claim_unmeasured);

// F7. Segmenting to fix unknown unicast treats a symptom.
p_cf_symptom: assert property (@(posedge clk) disable iff (!rst_n)
  (segmented_to_fix_unknown_unicast && flood_is_uu_dominated_i)
    |-> v_symptom_treated);

// F8. Conformance is the disjunction of its six checks.
p_cf_vector: assert property (@(posedge clk) disable iff (!rst_n)
  conformant |-> (violations == 6'b000000));

Coverage — the configurations that decide the argument.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
c_cn_min_frame:  cover property (@(posedge clk) payload_octets <= 16'd46);
c_cn_jumbo:      cover property (@(posedge clk) payload_octets >= 16'd9000);
c_fw_no_flood:   cover property (@(posedge clk) flood_share_ppm == 32'd0);
c_fw_heavy:      cover property (@(posedge clk) flood_share_ppm >= 32'd195_000);
c_fw_32_vlans:   cover property (@(posedge clk) vlans == 16'd32);
c_dr_multiswitch:cover property (@(posedge clk) switches_in_domain >= 16'd4);
c_dr_over:       cover property (@(posedge clk) !within_budget);
c_tk_relief:     cover property (@(posedge clk) segmentation_relieves_trunk);
c_rl_two_tags:   cover property (@(posedge clk) max_tags == 16'd2);
c_rl_1024:       cover property (@(posedge clk) datapath_bits == 16'd1024);
c_au_marginal:   cover property (@(posedge clk) (net_ppm > 32'sd0) && (net_ppm < 32'sd10_000));
c_au_negative:   cover property (@(posedge clk) net_ppm <= 32'sd0);
c_tl_uu_dom:     cover property (@(posedge clk) flood_is_unknown_unicast_dominated);
c_cf_symptom:    cover property (@(posedge clk) v_symptom_treated);

21. Verification Scenarios

Fifty-eight scenarios in six groups, plus one directed test random stimulus will not produce.

Group 1 — conservation and the tag (10).

#ScenarioExpect
164 ports at 100 Gb/s, 1 VLAN6 400 Gb/s aggregate
2the same, 8 VLANs6 400 Gb/s — throughput_delta_ppm = 0
3the same, 32 VLANs6 400 Gb/s
446-octet payload, untaggedslot 84; efficiency 547 619 ppm
546-octet payload, taggedslot 88; efficiency 522 727 ppm; tag 47 619 ppm
61 500-octet payload, taggedtag 2 600 ppm — 0.26%
79 000-octet payload, taggedtag 442 ppm — 0.044%
8a stacked tag, 8 octets, 46-octet payload9.52% of the wire
9vlans changed with rates fixedcapacity unchanged — p_cn_vlans_absent
10any tagged configurationonly_effect_is_negative high

Group 2 — flood width (10).

#ScenarioExpect
1164 ports, 1 VLAN63 copies
1264 ports, 2 VLANs31 copies; 49.2% of flat
1364 ports, 8 VLANs7 copies; 11.1%
1464 ports, 32 VLANs1 copy; 1.6%
15flood share 0improvement_ppm = 0 — p_fw_needs_flooding
16flood share 0.1%, 8 VLANs5.3% improvement
17flood share 1%, 8 VLANs34.6%
18flood share 19.5%, 8 VLANs83.4%
19one port flooding at 148.81 Mpps, 64 ports9.375 Gpps — 98.4% of the budget
20the same at 8 VLANs1.042 Gpps — 10.9%

Group 3 — the domain rate (9).

#ScenarioExpect
2164 stations, 1 VLAN, B = 5315/s each; 1 575 µs/s; 0.16% of a core
22the same, 8 VLANs35/s each
23512 stations, 1 domain2 555/s; 1.28% of a core
244 096 stations20 475/s; 10.2%
254 switches of 63, 1 domain252 stations; 1 255/s; 0.63%
26budget 500/s, B = 5, 64 ports101 stations fit; 1 VLAN suffices
27budget 50/s11 stations; 6 VLANs exact, 7 from the model
28switches_in_domain = 4domain_spans_switches high
29switch_can_determine_this0, at every setting

Group 4 — the trunk (10).

#ScenarioExpect
3064 ports, 1 VLAN, B = 5320/s on the trunk
31the same, 4 VLANs320/s
32the same, 16 VLANs320/s
33trunk_relief_ppm at any VLAN count0
34segmentation_relieves_trunklow, always
35trunk_pays_the_taghigh, always
361 500-octet mean frame on the trunktag 2 600 ppm
37320 broadcasts/s, 1 500-octet frames, 100 Gb/s trunk3.95 Mb/s — 0.004%
38a pruned trunk carrying 2 of 8 VLANsthe model reports the unpruned figure — a stated simplification
39stations across configurations64, unchanged — p_tk_stations

Group 5 — realignment, table and the auditor (10).

#ScenarioExpect
401 024-bit datapath, 2 tags3 shift positions; 6 144 GE; on the critical path
4132-bit datapathon_critical_path low — a tag is exactly one word
4248-bit key → 60-bit25% table growth; fractions unmoved
43128k entries, 12 added bits1 572 864 BCE; 5.55 datapaths; 0.28%
44occupancy_fractions_move0 — Chapter 13.4 §8's structural result
45flood share 0.1%, 1 500-octet trunk framesnet +5.0%; worth_the_tag high
46flood share 0.1%, minimum-size trunk framesnet +0.5% — inside anybody's measurement noise
47flood share 0.01%, minimum-size framesnet negative; worth_the_tag low
48bandwidth_benefit at any setting0
49cpu_improvement_ppm, 64 ports into 8888 888 — 88.9%, unconditional

Group 6 — telemetry and conformance (9).

#ScenarioExpect
501 000 frames, 10 floodedflood_share_ppm_o = 10 000
51flooded frames dominated by unknown unicastflood_is_unknown_unicast_dominated high
52the same, dominated by broadcastlow — and segmentation is now the correct fix
53a bandwidth-gain claimv_bandwidth_claim, with no traffic input
54a trunk-relief claimv_trunk_relief_claim
55a flood claim with no measurementv_flood_claim_unmeasured
56segmenting to fix unknown unicastv_symptom_treated
57cross-VLAN share above budgetv_cross_vlan_excessive
58all six checks clearconformant high

22. Debugging a Segmentation Decision

Six symptoms, and the first question in every row is which quantity did you expect to move.

SymptomFirst questionWhere to look
segmentation deployed, throughput unchangedwhat was the flood share before?Section 5 — at 0.1% the improvement is 5.3% and the tag costs 4.76%
the trunk is as busy as it wasdid you expect it to change?Section 8 — 320 broadcasts per second at every VLAN count
flooding got worse after segmentingdid the distinct key count grow?Section 21's directed test — servers reachable from several VLANs
a design that closed timing now misseswhen was VLAN support added?Section 11 — one mux level on the MAC's critical path
the switch is carrying every frame twicewhich conversations cross a router?Section 2's callout — a split conversation costs the switch twice
stations report fewer broadcasts and users report no changewas the problem ever broadcast?Section 6 — 0.16% of a core at 64 stations

Row six is the common case and it is worth being blunt about. A 64-port switch in one VLAN puts 315 broadcasts per second on each station, which is 0.16% of one core. Reducing it to 35 is a factor of nine on a number that was already negligible, and users notice nothing because there was nothing to notice.


23. Misconceptions

Misconception 1 — "VLANs give each segment more bandwidth."

The wrong model: dividing a switch into parts gives each part a share it did not have.

What it costs: a capacity plan built on a term that does not exist. Section 2: a switch of N ports at rate R has aggregate capacity N × R before and after, and the VLAN count appears in no factor of it. The fabric, the buffer and the scheduler are all shared.

The corrected model: a VLAN is a membership relation evaluated during forwardingChapter 13.4 §6's key construction — and evaluating a relation does not create a link.

Misconception 2 — "the tag is free."

The wrong model: four octets on a 1 518-octet frame is nothing.

What it costs: 4.76% of the wire at minimum frame size, paid on trunks. Section 3: the tag's cost is Chapter 8.3 §2's hyperbola with the constant raised from 38 to 424.76% at 46 octets of payload, 0.26% at 1 500, 0.044% at 9 000.

The corrected model: access ports strip the tag and pay nothing; trunks carry it and pay 4.76% at the small end — and trunks are the links a deployment is usually worried about.

Misconception 3 — "segmenting relieves the uplink."

The wrong model: fewer stations per domain means less broadcast traffic crossing the trunk.

What it costs: an uplink upgrade deferred on a false premise. Section 8: the trunk carries every VLAN, so its broadcast load is the total station count times B — 320 per second at 64 ports and B = 5, at every VLAN count from 1 to 32.

The corrected model: segmentation redistributes a load it does not reduce, and the only things that relieve a trunk are routing at the edge, more uplinks, a faster uplink, storm control, or fixing the table.

Misconception 4 — "more VLANs is always safer."

The wrong model: finer segmentation contains more and costs nothing.

What it costs: two switch traversals per split conversation and a multiplied key count. Section 2's callout: two stations put in different VLANs now go through a router, which costs the switch twice the capacity it cost before. Section 21's directed test: segmenting by traffic class multiplied 20 000 keys into 160 000 and took the flood share from 0.08% to 27.68%.

The corrected model: segmentation's cost is paid by whatever traffic crosses the boundaries it draws, and segmenting by function segments along exactly the lines the traffic crosses.

Misconception 5 — "we segmented and flooding went down, so it worked."

The wrong model: the flood width fell, therefore the flood load fell.

What it costs: Section 20's class 118. Flood load is rate × copies and segmentation moves both — the copies down by the VLAN count and the rate up, if the widened key multiplies the address population past the table's effective capacity.

The corrected model: assert the product and report both factors. c_flooded ÷ c_forwarded before and after, on the same switch, and Chapter 12.4 §15's telemetry already provides both numbers.

Misconception 6 — "the broadcast load was the problem."

The wrong model: stations were drowning in broadcasts and segmentation fixed it.

What it costs: a project justified by a quantity that was never binding. Section 6: 64 stations at 5 broadcasts per second each is 315 per station per second — 1 575 µs of CPU per second, 0.16% of one core. The rule of thumb everybody carries comes from a domain of a few thousand stations, where it is 10.2% and genuinely matters.

The corrected model: compute the domain's station count, not the switch's port countChapter 12.4 §10's sub-argument that the domain is the fabric. Four 64-port switches in one domain is 252 stations and 0.63% of a core; sixteen is 1 008 and 2.5%.


24. Interview Questions

Six, with what a strong answer contains.

1. Do VLANs improve performance?

They improve one quantity conditionally and one unconditionally, and neither is bandwidth. A strong answer opens with conservation: a switch of N ports at rate R has aggregate capacity N × R before and after segmentation, and the VLAN count appears in no factor of it. Then the two real benefits: flood width falls from 63 copies to 7 at 64 ports into 8 VLANs, worth flood_share × 88.9%; and each station's broadcast receive rate falls from 315 per second to 35, unconditionally. The best answers add the cost: 4.76% of the trunk's wire at minimum frame size.

2. Does segmenting relieve an uplink?

No, and the arithmetic is one line. A trunk carries every VLAN, so its broadcast load is the total station count times the per-station rate — 320 per second at 64 ports and B = 5, at every VLAN count. A strong answer names what does relieve a trunk: routing at the edge, more uplinks, a faster uplink, storm control, or fixing the table — and observes that only one of those adds bandwidth.

3. What does a VLAN tag cost?

Four octets, on trunks only. Chapter 8.3 §2's hyperbola with the constant raised from 38 to 42: 4.76% of the wire at a 46-octet payload, 0.26% at 1 500, 0.044% at 9 000. A strong answer adds the two costs that are not the tag: the forwarding key grows from 48 to 60 bits, which at Chapter 23.3's 128k table is 1 572 864 BCE — 0.28% of the switchand the mid-frame realignment is one mux level on the MAC's critical path.

4. When is segmenting worth it?

When the flood share is above about 0.1%, and the deployment can read it off its own hardware. c_flooded ÷ c_forwardedChapter 12.4 §15's telemetry. A strong answer gives the comparison: at a 0.1% flood share the improvement is 5.3% and the tag costs 4.76% on minimum-size trunk frames, so the net is half a percentage point. At 19.5% the improvement is 83.4%.

5. Can segmenting make things worse?

Yes, three ways. A split conversation costs two switch traversals instead of one. The trunk pays the tag and carries the same broadcasts. And the widened key can multiply the address population: segmenting 20 000 stations by traffic class into 8 VLANs produces 160 000 distinct keys, which against Chapter 23.3's 128k four-way table takes the refused share from 0.08% to 27.68%and the mean egress copies per frame from 1.048 to 2.661, a 2.54× regression.

6. A team reports that segmenting cut flooding from 63 copies to 7. What do you ask?

What happened to the flood rate. A strong answer names the structure: flood load is rate × copies, the measurement covers one factor, and the same intervention moves the other. That is Section 20's class 118 — an improvement in one factor of a product where the mechanism moves the other — and it belongs to the group where something outside the property's interface decides the outcome, with the distinguishing feature that here the outside term is moved by the intervention itself.


25. Questions and Answers


26. What's Next

Four myths down and two to go, and the next one is the cause behind this chapter's most uncomfortable result.

Chapter 25.5 takes "switches eliminate broadcasts". It derives Chapter 12.4 §6's replication at Chapter 23.3's scale — one port flooding minimum-size frames at 100 Gb/s emits 9.375 Gpps, which is 98.4% of a 64-port switch's entire 9.524 Gpps frame budget — and then goes to the case that actually hurts.

Unknown-unicast flooding is a broadcast in every respect except its address. A frame whose destination is not in the table is replicated to every port in the VLAN, exactly as a broadcast is; Chapter 12.4 §6 established that the receiving stations discard it in hardware at no CPU cost, so it is cheaper at the endpoint and identical inside the fabric.

And the chapter's subject is when that happens, which is a property of Chapter 12.5's table rather than of the traffic. A 128k-entry four-way table offered 131 072 distinct addresses stores 105 465 and refuses 25 607 — 19.5% — and every refused address floods every frame sent to it, permanently, while the occupancy counter reads well below capacity and no error counter moves.

Then it ties the two chapters together through Chapter 25.2 §8's stale entries833 of them at 10 000 container teardowns an hourbecause a table holding entries for stations that no longer exist is a table with fewer sets available for stations that do.

Continue learning

Standards & specifications

Governing standard
IEEE Std 802.3 (Ethernet)(opens IEEE in a new tab)

Defines the Ethernet MAC, the media-independent interfaces and the physical-layer sublayers, including framing, access control, auto-negotiation and per-rate PHY specifications. VLAN tagging, priority and time-sensitive shaping are defined by IEEE 802.1, not by 802.3.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the Ethernet curriculum.