Skip to content

QoS Policies v0.2.0

QoS policies define per-subscriber rate limiting and traffic shaping. Each policy is a named template instantiated per subscriber at session activation.

CAKE scheduling is only supported on the subscriber egress direction (download, internet to subscriber). The ingress direction (upload, subscriber to internet) always uses a policer.

Policies are defined under the top-level qos-policies key and referenced by name from service groups. For architectural details, see QoS Architecture.

Policy Settings

Field Type Description Default
cir uint32 Committed information rate (kbps) required
eir uint32 Excess information rate (kbps) equal to cir
cbs uint64 Committed burst size (bytes) cir * 1000 / 8
ebs uint64 Excess burst size (bytes) equal to cbs
conform Action Action for conforming traffic required (policer-only)
exceed Action Action for exceeding traffic required (policer-only)
violate Action Action for violating traffic required (policer-only)
scheduler Scheduler CAKE scheduler config optional

All rates are in kilobits per second. For example, cir: 100000 = 100 Mbps.

When no scheduler block is present, the policy operates as a pure policer using the 2-rate 3-colour (2R3C) model defined in RFC 2698. Traffic is classified into one of three colours based on instantaneous rate against the CIR and EIR token buckets, and the configured action is applied.

CAKE Scheduler v0.6.0

Adding a scheduler block to a policy switches the egress direction from policer to CAKE-based shaping with fair queuing and AQM.

Scheduler Settings

Field Type Description Default
tin-mode string DSCP-to-tin classification mode besteffort
weight uint32 DRR weight multiplier under an aggregate, 1-256. Multiplies the share the subscriber's rate already earns; see Hierarchical QoS 1

Tin Modes

Value Tins Description
besteffort 1 Single tin, all traffic treated equally
diffserv3 3 Bulk, Best Effort, Voice
diffserv4 4 Bulk, Best Effort, Video, Voice (recommended)
diffserv8 8 Full 8-tin DSCP classification

Example: CAKE Egress Shaping

qos-policies:
  cake-100m:
    cir: 100000
    scheduler:
      tin-mode: diffserv4

service-groups:
  residential:
    qos:
      egress-policy: cake-100m

This creates a 100 Mbps CAKE shaper with 4-tin DiffServ classification on each subscriber's egress. No policer action fields are needed when using the scheduler.

Example: CAKE Egress with Ingress Policer

qos-policies:
  upload-50m:
    cir: 50000
    conform:
      action: transmit
    exceed:
      action: drop
    violate:
      action: drop

  download-100m-shaped:
    cir: 100000
    scheduler:
      tin-mode: diffserv4

service-groups:
  residential:
    qos:
      ingress-policy: upload-50m
      egress-policy: download-100m-shaped

Example: Per-Service-Group Rate Override

The service group's download-rate field overrides the policy's cir for the scheduler rate. This lets you share a single CAKE policy across service groups with different speeds.

qos-policies:
  cake-shaped:
    cir: 100000
    scheduler:
      tin-mode: diffserv4

service-groups:
  residential-100m:
    qos:
      egress-policy: cake-shaped

  residential-500m:
    qos:
      egress-policy: cake-shaped
      download-rate: 500000

Hierarchical QoS (Aggregates) v0.9.0

Above the per-subscriber schedulers, the dataplane can shape two aggregate tiers: an S-VLAN aggregate (one shaper for every subscriber behind an outer tag or tag range) under a port aggregate (one shaper for the whole physical or bond interface). Contention at each tier is arbitrated by weighted deficit round robin across the tier's active children. See QoS Architecture for how the hierarchy schedules.

Aggregates are defined under the top-level qos-aggregates key, one named entry per tier instance:

qos-aggregates:
  port:
    interface: eth1        # physical or bond interface
    rate: 8000             # kbps
  svlan-100:
    interface: eth1
    svlans: ["100"]        # single tag
    rate: 6000
  svlan-rest:
    interface: eth1
    svlans: ["200-300"]    # tag range: one shaper for every tag in it
    rate: 3000
    weight: 4
    burst-ms: 50

Aggregate Settings

Field Type Description Default
interface string Physical or bond interface, both levels required
svlans []string Outer tags this aggregate shapes: a tag ("100") or a range ("200-300"). Omit entirely for a port aggregate port level
rate uint32 Shaping rate (kbps) required
weight uint32 DRR weight multiplier under the parent, 1-256 1
burst-ms uint32 Idle credit ceiling, 10-150 ms 10
buffer-limit uint32 Max buffered bytes derived from rate

Requirements Per Level

Port aggregate — keyed by the physical/bond interface, no svlans list. At most one per interface. Must exist before (or be committed together with) any S-VLAN aggregate on the same interface.

S-VLAN aggregate — requires a port aggregate on the same interface. Each entry takes a single tag or one a-b range (comma lists are rejected — use separate entries); tag sets of all S-VLAN aggregates on one port must be disjoint; tags run 1-4095. An S-VLAN's rate may not exceed its port's.

Subscriber scheduler — enabled per session by the egress policy's scheduler block (see above); there is no per-aggregate member list to maintain. Attachment is automatic: the dataplane walks the session interface's parent chain to the physical port and, when the session's outer tag is covered by an S-VLAN aggregate, attaches it there, otherwise directly to the port aggregate. The scheduler's DRR share is derived from its rate, multiplied by the policy's weight.

Rate and weight changes to an existing aggregate are applied in place; a change to interface or the tag set recreates the aggregate (dropping and re-attaching its members).

Monitoring

Show commands (each also available at /api/show/qos/... and, with | json, as raw JSON in the CLI). Session IDs are UUIDs for every access type, exactly as show subscriber sessions reports them:

show qos scheduler [--interface X]
    Every subscriber scheduler: rate, weight, DRR state, throughput,
    drops, buffer usage, session id.

show qos scheduler session --session-id <session-uuid>
show qos scheduler session --acct-session-id <aaa-acct-session-id>
show qos scheduler session --interface <access-if> --outer-vlan N [--inner-vlan M]
    One subscriber's full shaping chain: session identity, scheduler with
    per-tin stats, and the S-VLAN / port aggregates above it. An ambiguous
    interface+VLAN lookup returns the matching candidates instead.

show qos scheduler detail --interface <session-if>
    The same view addressed by the scheduler's interface (name or
    sw_if_index) rather than by subscriber identity.

show qos aggregate [--interface X] [--level port|svlan] [--svlan N]
    Both aggregate tiers; --svlan matches the aggregate whose tag range
    covers N.

show qos aggregate detail --interface <port> [--svlan N]
    The whole hierarchy under one port as a tree: the port aggregate, its
    S-VLAN aggregates, and every member scheduler with stats and session id.

Any command runs non-interactively with osvbngcli -c "<command>", which prints the result with no banner and exits non-zero on failure — the form scripts and the test suites use.

In the CLI, the two list views render compactly. show qos scheduler is one line per scheduler:

SW_IF  INTERFACE    SESSION                               RATE  MODE  W(EFF)   PARENT      ST  TX PKTS/BYTES  DROP  Q   BUF  BLK D/P
-----  -----------  ------------------------------------  ----  ----  -------  ----------  --  -------------  ----  --  ---  -----------
7      ipoe0.100.1  9f8be1a2-77c1-4a83-9e0f-0d5a2f6b3c11  2M    ds4   1(250K)  sv100@eth1  A   18.2M/25.9G    1.2K  14  5%   88.2K/12.1K

MODE abbreviates the tin mode (be, ds3, ds4, ds8); W(EFF) is the configured weight with the effective DRR weight; ST is A while the scheduler is active in its parent's arbitration; BUF is buffer usage as a percentage of the limit; BLK D/P is drr_blocked/parent_blocked. Values are SI-scaled. show qos aggregate renders each port's hierarchy as a tree:

eth1  port  8M  ·  3 active / W 1.8M  ·  buf 1.2M/16.8M (7%)
│       shaped 88.2M pkts / 112.4 GB   backpressure 122   parent-blk 904.2K
├─ svlan 100  6M  w1 (eff 750K)   2 active / W 500K   buf 96.3K/1M (9%)
│       shaped 40.1M pkts / 51.2 GB   backpressure 31   blk drr 421.9K par 88.1K
└─ svlan 200-300  3M  w1 (eff 375K)   2 active / W 250K   buf 0/1M (0%)
        shaped 9M pkts / 11.1 GB   backpressure 0   blk drr 10.2K par 4.4K

The full field set is always available with | json.

Modify or disable a scheduler at runtime via the operational API:

# Change rate
curl -X POST http://localhost:8080/api/exec/qos/scheduler/set \
  -d '{"sw_if_index": 5, "rate_kbps": 200000, "tin_mode": "diffserv4"}'

# Disable
curl -X POST http://localhost:8080/api/exec/qos/scheduler/set \
  -d '{"sw_if_index": 5, "disable": true}'

Prometheus Metrics

Both QoS show paths are polled by the telemetry SDK every 10 seconds and exported by the exporter.prometheus plugin. Families and labels:

Family Type Labels
osvbng_qos_scheduler_{rate_kbps,tin_count,weight,effective_weight,buffer_usage,buffer_limit,queued_buffers} gauge sw_if_index, interface, tin_mode
osvbng_qos_scheduler_{enqueued,dequeued}_{packets,bytes}, _dropped_packets, _drr_blocked, _parent_blocked counter sw_if_index, interface, tin_mode
osvbng_qos_scheduler_tin_{packets,bytes,drops,ecn_marks} counter scheduler labels + tin
osvbng_qos_scheduler_tin_{sparse_flows,bulk_flows,flow_count,peak_delay_us,avg_delay_us} gauge scheduler labels + tin
osvbng_qos_aggregate_{rate_kbps,weight,effective_weight,burst_ms,buffer_usage,buffer_limit,active_weight,active_children} gauge sw_if_index, interface, level, svlan_id, svlan_id_end
osvbng_qos_aggregate_{shaped_packets,shaped_bytes,backpressure,drr_blocked,parent_blocked} counter aggregate labels

Notes:

  • Scheduler metrics are per subscriber (keyed by the session interface). Each metric family is capped at 10,000 series; overflow is dropped and counted in osvbng_telemetry_cardinality_drops_total. Session identity is deliberately not a label — correlate sw_if_index/interface through the show API instead.
  • tin_peak_delay_us / tin_avg_delay_us read zero until the dataplane computes per-tin sojourn delay.

Dataplane Version Requirements

The control plane probes the dataplane and degrades rather than failing:

Feature Needs QoS plugin API
Per-subscriber CAKE scheduler, per-tin stats any
Aggregates (port + S-VLAN), scheduler weight >= 3.0.0
Scheduler DRR/parent state, throughput counters, show qos aggregate detail membership, per-tin flow_count >= 3.1.0

Against an older dataplane the affected fields read zero and the aggregate detail view notes that membership is unavailable.

Actions

Each action block specifies what to do with traffic in that colour class. Only required for policer-mode policies (no scheduler block).

Field Type Description Example
action string transmit, drop, or mark-and-transmit transmit
dscp uint8 DSCP value to mark (only used with mark-and-transmit) 46

Policer Usage

QoS policies without a scheduler block are applied as VPP policers. A service group references policy names for ingress (upload) and egress (download) directions independently.

qos-policies:
  100m-policer:
    cir: 100000
    conform:
      action: transmit
    exceed:
      action: drop
    violate:
      action: drop

service-groups:
  residential:
    qos:
      ingress-policy: 100m-policer
      egress-policy: 100m-policer

When a subscriber session activates, the referenced policies are instantiated as VPP policers and attached to the subscriber's sub-interface. When the session is released, the policers are detached and deleted.

Asymmetric Rates

Use different policies for upload and download to create asymmetric speed profiles.

qos-policies:
  upload-50m:
    cir: 50000
    conform:
      action: transmit
    exceed:
      action: drop
    violate:
      action: drop

  download-200m:
    cir: 200000
    conform:
      action: transmit
    exceed:
      action: drop
    violate:
      action: drop

service-groups:
  residential:
    qos:
      ingress-policy: upload-50m
      egress-policy: download-200m

DSCP Marking

Use mark-and-transmit to remark excess traffic instead of dropping it.

qos-policies:
  business-with-remarking:
    cir: 100000
    eir: 200000
    conform:
      action: transmit
    exceed:
      action: mark-and-transmit
      dscp: 0
    violate:
      action: drop

In this example, traffic up to 100 Mbps is forwarded unchanged, traffic between 100-200 Mbps is remarked to DSCP 0 (best effort), and traffic above 200 Mbps is dropped.

AAA Override

AAA can override QoS policy names per subscriber by returning qos.ingress-policy and qos.egress-policy attributes. See service groups for the full list of overridable attributes.