DSCP marking or provider QoS promise? Neither one is a contract
A local marking sets an intent and a carrier class supplies treatment at a boundary. Compare the two halves before anyone promises a voice quality number.
Something gets marked, a queue gets configured, and then somebody asks what quality the design actually guarantees. The honest answer is that you have described two halves of a contract that meet at a boundary. Until you can name the class the provider accepts and the treatment it applies, the local configuration is an intention rather than a promise. Both halves matter, and neither can be inferred from the other.
local match → queue and marking → provider classifier
→ provider treatment → destination
Where a correct marking can quietly die
Start by writing down, per workload, the local match condition, any marking that happens inside a tunnel, the value the provider accepts, and the service class that value selects. Four columns, and the failures usually live between the second and third.
An inner-to-outer marking behaviour is the classic problem. A packet inside an encrypted or tunnelled path carries an inner header that your classifier can see and an outer header that the provider's equipment can see, and copying one to the other is a configuration decision rather than an automatic property. Mark the inner header only and the provider classifies the outer one, usually as default, which is why a correctly marked flow can arrive in the wrong class without a single misconfigured line on your side.
A locally named class can also sit empty because its match condition never fires on real packets. Ports move, applications use several flows, and a match on a well-known port that the vendor stopped using two releases ago produces a queue with counters at zero and a policy that looks perfect in the running configuration.
Decide explicitly where markings are trusted. Promoting everything that shares a tunnel promotes bulk transfers along with the calls, and a provider that accepts your marking without validation is offering you a way to hurt yourself. If the contract lets the gateway remark at the handoff, say so in writing, because that is the point where two teams' assumptions usually diverge.
What the scheduler is actually dividing
Local policy has its own semantics, and the one that causes the most misunderstanding is the word "remaining". On the platforms the IOS XE scheduling guide describes, bandwidth remaining percent sets an excess weight, not a step in a sequence where each class takes a slice of whatever the previous class left behind. Unassigned percentages are spread across eligible unconfigured queues rather than being reserved for the last class in the file.
That distinction matters because the sequential mental model produces predictions that never match the counters. Engineers reorder classes to change an outcome, see no difference, and conclude the platform is broken, when the configuration never meant what they assumed.
A parent shaper is the other common surprise. Shaping a controlled queue down to the usable service rate is often deliberate, because it moves the congestion point to a device you administer instead of an upstream queue you do not. Removing the shaper because shaping adds delay can relocate the loss rather than remove it, and overhead accounting or a provider policer can make the effective rate lower than the interface suggests.
The counters tell you which half failed
Compare four numbers in the affected direction: what was offered, what the class matched, what was queued or dropped, and what the service actually delivered. Keep the workload description and the policy version next to the observation, because a counter screenshot without them cannot be reproduced.
The branches are different problems with different owners. A local class that matches nothing is a classification bug on your side. A class that matches, queues and drops while the provider reports clean delivery points at your own scheduler or shaper. A class that looks correct locally while loss appears beyond the handoff points at the carrier's mapping and the measured boundary in the contract. None of the three is fixed by editing the others, which is why the numbers have to be collected together.
RFC 2475 frames classification and conditioning as work done inside administrative domains, which is exactly why a marking cannot reserve queues end to end. The IOS XE scheduling guide is the reference for the excess-weight behaviour described above, and its platform comparisons are worth reading before moving a calculated rate between models.
Write the contract in one place
Put the local match, the trust boundary, the provider class and the measured service level in a single document that both sides sign. Then a percentage change has a context, and a quality complaint has an owner.
Changing a local percentage cannot repair a different queue's guarantee, and no marking scheme survives a mapping the provider does not honour. Compare the halves, name the boundary, and only then quote a number.