BearerConfigurator

Package: simu5g.corenetwork.bearerConfigurator

BearerConfigurator

simple module

Central configurator of the network's data radio bearers.

This module does not model a single 3GPP network function. It combines, in one network-wide service, decisions that a real system distributes between the core network and the RAN: in 5GS, the SMF controls PDU sessions and QoS flows, while the NG-RAN decides how QoS flows map onto DRBs and derives the radio configuration (TS 23.501 5.7.1, TS 38.300 12); in EPS, the corresponding roles are spread across the MME and the eNB. Here every bearer is authored in one place instead, and the signalling that would carry the configuration (N1/N2/S1/RRC procedures) is not modeled: within the model, the RAN never authors a bearer of its own -- every bearer comes from this module's tables.

One cellular network holds one instance of this module, alongside its Binder. Like the Binder, it is always reached through module paths supplied in parameters (bearerConfiguratorModule), never through hardcoded ones, so several cellular networks -- each with its own Binder and BearerConfigurator pair -- can coexist within one simulation. The "ue" patterns of the definition tables range over the UEs registered in this instance's Binder only, but are matched against module paths relative to the toplevel network, so in such a setup the entries (and the module-path parameters) name their nodes by qualified paths, e.g. "networkA.ue[*]".

Modeling abstractions and current limitations:

  • Bearer establishment is a direct call into the RRC of each node involved; no signalling procedure carries it.
  • Packet-triggered establishment (onDemandDrbs) is a simulation policy. In 5GS, a first UL packet with an unmapped QFI would ride the already-established default DRB, and the gNB could reconfigure the mapping afterwards (TS 38.300 Annex A); creating the DRB before the first packet is delivered is a shortcut.
  • One PDU session (in EPS terms: one PDN connection) per UE is assumed. QFI mappings, the default DRB and the pduSessionType are therefore scoped per UE, although the spec scopes all of them per PDU session (TS 37.324); a UE with several sessions, e.g. toward multiple DNs or with two session types, cannot be described yet.
  • The QoS characteristics attached to a definition describe the DRB as a whole. In 5GS they belong to QoS flows, and flows with different QoS profiles may legitimately share a DRB; per-flow QoS is not modeled.
  • legSelection is a Simu5G extension: 3GPP steers split bearers by PDCP-level controls (primaryPath, ul-DataSplitThreshold), not by per-PDU expressions.

The staticDrbs parameter is the network's data radio bearer configuration: one entry per bearer per UE, describing the bearer before and independent of its establishment (modeled on the DRB-ToAddMod and RLC-BearerConfig records of TS 38.331). This module tells the RRC of each node involved in a bearer -- the UE and its serving node -- what to set up, and RRC pushes on what each of its layers consumes. Nothing reads this configuration back out.

A static bearer is not only configured but also established up front, in the last initialization stage: each entry results in the same establishment call that packet-triggered setup makes, so traffic finds the bearer in place. A dual-stack UE's bearer is established on the stack that packet-triggered establishment would pick (split into per-technology legs when the UE is served by a node pair in dual connectivity); an entry whose UE is attached to no cell at that point is a configuration error. To make the static configuration the only source of bearers, disable packet-triggered establishment via the establishBearersOnDemand parameter of NrSdap (or Ip2Nic, for stacks without SDAP); see the VoIP-DL-MultiQfi-NoOnDemand configuration of the simulations/nr/standalone_drb example.

Because an entry names its UE by module path rather than by node id, the configuration follows the UE from cell to cell, and neither end of the radio link is configured directly from the ini.

staticDrbs fields:

  • coreNetwork (string, required): "5gc" or "epc" -- which bearer architecture selects the bearer. A "5gc" bearer is selected by the QFIs mapped onto it (mappedQfis; needs SDAP in the stack); an "epc" bearer is selected by packet filters (filters; for stacks without SDAP). Stated per entry, never inferred; each receiving RRC checks it against its stack.
  • ue (string): module path of the UE node, relative to the network; patterns are allowed, so one entry can describe a bearer of many UEs (e.g. "ue[*]")
  • drbId (int): DRB identity, 1..32 (TS 38.331 DRB-Identity)
  • profile (string, optional): name of a drbProfiles entry supplying defaults for the fields it does not spell out itself
  • mappedQfis (int[], optional, "5gc" only): QFI values (0..63) mapped to this DRB; an entry without it does not take part in SDAP's QFI-to-DRB mapping. This field maps already-assigned QFIs onto the DRB; which QFI a packet carries is decided by the QFI classification rules (the dlQfiRules and ulQfiRules parameters below)
  • filters (string[], optional, "epc" only): packet filters selecting this bearer, each an inet::PacketFilter -- a message-name pattern (e.g. "VoIP*") or an expression written as "expr(...)" (e.g. "expr(udp.destPort == 3000)"). An expression sees the packet that triggers establishment, i.e. an UL-triggered and a DL-triggered flow present swapped port/address roles; a list can carry both spellings.
  • lcg (int, optional): the bearer's logical channel group (0..3; mac-LogicalChannelConfig). In 3GPP an LCG only groups logical-channel buffers for buffer status reporting; that Simu5G's MAC scheduler additionally serves lower LCG indices first is a Simu5G scheduling policy, not spec semantics (the spec's per-logical-channel priority is a separate parameter, not modeled, and NR allows 8 LCGs where this model keeps LTE's 4). Omitted = derived from the QoS profile's priority level (bucketed by lcgPriorityBounds), or 0 when the definition carries no "qosPriorityLevel"
  • rlcMode (string, optional when the definition carries a "packetErrorRate"): RLC mode ("AM" or "UM"; "TM" is rejected -- 3GPP transparent mode carries BCCH/PCCH/SRB0-class channels, not DRBs); omitted = derived from the QoS profile's packet error rate (packetErrorRate <= amPerThreshold -> "AM", else "UM": a PER target HARQ alone cannot meet gets ARQ). Required, in the entry or its profile, when there is nothing to derive it from.
  • primaryPath (string, default "MCG"): on a split bearer (two legs), the preferred leg -- used in either direction whenever the bearer is not splitting; must be one of its two legs (TS 38.331 PDCP-Config, TS 38.323 5.2.1; applied by DcPdcpLegSplitter).
  • ulDataSplitThreshold (int bytes, or "infinity"; default "infinity"): uplink only. How much of a split bearer's data must be queued waiting to send (in its legs' RLC buffers) before the UE uses the second leg as well as primaryPath. "infinity" means never -- the uplink stays on primaryPath. (Only the UE has both legs' queues locally; downlink has no such threshold, see dlLegSelection.)
  • ulLegSelection (string, optional): once the uplink is using both legs (at or above the threshold), which leg each PDU takes -- an expr(...) over packetOrdinal (a running count of the bearer's PDUs) returning the leg number, 0 or 1 (e.g. "expr(packetOrdinal % 2)" for round-robin). Default when omitted: the less-loaded leg. Set ulDataSplitThreshold to 0 to have it decide every uplink PDU; stating it while leaving the threshold at infinity is rejected.
  • dlLegSelection (string, optional): the downlink counterpart, applied at the DC master. The master cannot weigh the secondary leg's queue (it is at another node, across X2), so downlink has no threshold or load-balancing: with dlLegSelection each downlink PDU takes the leg it returns, and without it the downlink stays on primaryPath. (Real downlink split flow control is X2-feedback-driven and is not modeled.)
  • legs (string[]/object[], optional): the cell groups that serve this bearer, i.e. its RLC bearers (TS 38.331 RLC-BearerConfig). One leg = an MCG or an SCG bearer, both = a split bearer (TS 37.340; stated in that order). An element is either a cell group name ("MCG" or "SCG"), or an object naming it and overriding the RLC configuration it inherits from the entry: {leg: "SCG", rlcMode: "AM", soFraming: true, snFieldLength: 18}. Omitted = the configuration does not state the legs and RRC derives them, as it always has. An SCG bearer's PDCP still terminates at the master node -- the core network delivers the UE's traffic there -- and every PDU is relayed to the secondary over X2 (an MN-terminated SCG bearer in TS 37.340 terms).
  • pduSessionType (string, optional): "IPv4", "IPv6", "IPv4v6", "Ethernet", "Unstructured"; default: "IPv4"
  • upperProtocol (string, optional): INET protocol name for upper layer dispatch (this is normally only needed for "Unstructured" PDU sessions); default: derived from pduSessionType
  • isDefault (bool, optional): marks this as the default DRB for the UE -- the fallback when no QFI-to-DRB mapping ("5gc") or packet filter ("epc") matches. If no entry of a UE is marked in either table, the UE's single static bearer takes the role; a UE with several bearers must mark one explicitly.
  • suppressSdapHeader (bool, optional, "5gc" only): the bearer's packets carry no SDAP header (TS 38.331 sdap-HeaderDL/UL "absent"). Only meaningful on the default bearer (any other bearer with at most one mapped QFI is headerless already), and only sound when a single QoS flow actually rides it: the receiver assigns every headerless packet the bearer's sole mapped QFI (QFI 0 when none is mapped), and the sender verifies each packet against that value, stopping with an error when a second flow shows up. The header decision itself is computed by this module and delivered per bearer; SDAP applies it as pushed.
  • gbr (bool), packetDelayBudget (double, ms), packetErrorRate (double), qosPriorityLevel (int) -- all optional: the QoS profile of the bearer's flows (5QI characteristics). Any of them present marks the bearer as having a QoS profile, which RRC pushes into the eNB/gNB MAC for QoS-aware scheduling.

Field groups that repeat across entries can be named once in the drbProfiles parameter (a JSON map of name -> field group) and referenced from entries via their "profile" field. A profile describes what the bearer is, so it may hold any entry field except the ones that say which UE it belongs to (ue, drbId), which architecture and flows select it (coreNetwork, mappedQfis, filters, isDefault).

A commonly used subset of the standardized QoS characteristics rows -- the core 1..9 of each table; both tables define many more -- is available as predefined profiles, referenced by name without being defined: "qci-1".."qci-9" (TS 23.203 Table 6.1.7-A) and "5qi-1".."5qi-9" (TS 23.501 Table 5.7.4-1). A row carries what the spec standardizes -- gbr, qosPriorityLevel, packetDelayBudget, packetErrorRate -- and nothing else: the RLC mode and the logical channel group are RAN choices, derived from those characteristics by default (the way a gNB derives its AS configuration from the delivered QoS profile; see the rlcMode and lcg field descriptions) and stated on the entry only to override, e.g. {coreNetwork: "5gc", ue: "ue[*]", drbId: 1, mappedQfis: [1, 2], profile: "5qi-1"}. A drbProfiles entry may not redefine a predefined name. NOTE the spec's priority scales (QCI 1..9, 5QI 10..90) differ from each other and from the small hand-picked values older configurations use. The QoS-aware scheduler weights bearers by 1/qosPriorityLevel, so only priority RATIOS matter to it and the two spec catalogs discriminate identically; but the absolute values still drive the lcgPriorityBounds bucketing (whose defaults suit the 5QI scale: single-digit priorities all land in LCG 0), so profiles from different scales still should not be mixed within one network.

Example (in an ini file):

*.bearerConfigurator.drbProfiles = {
    voice:  {rlcMode: "UM", gbr: true, packetDelayBudget: 100, packetErrorRate: 1e-2,
             qosPriorityLevel: 2}
    }
*.bearerConfigurator.staticDrbs = [
    {coreNetwork: "5gc", ue: "ue[*]", drbId: 1, mappedQfis: [1, 2], profile: "voice"}
    ]

The onDemandDrbs parameter describes bearers that are created when traffic first matches them, instead of being configured up front. Entries have the same fields as staticDrbs minus drbId: an on-demand bearer's id is assigned at creation, so definitions can never collide over ids ("ue" may also be omitted, meaning every UE). A "5gc" entry serves the QFIs in its mappedQfis: the first packet of an uncovered QFI creates the DRB (SDAP asks this module on a QFI-to-DRB lookup miss), and later QFIs of the same entry join it. An "epc" entry is matched by its filters against the packet that triggers bearer establishment, and an entry with isDefault=true catches the flows no filter matched ("5gc" entries cannot be the default: the default DRB is where unmapped QFIs go, so it must exist up front). A created bearer's definition is delivered to the RRCs involved exactly like a staticDrbs entry. Matching order is staticDrbs entries first, then onDemandDrbs entries, each in table order, first match wins.

A flow that no definition covers is a configuration error: every on-demand bearer's properties come from a definition entry, never from the packet. The parameter's default value keeps configurations that author nothing working, whichever stack they run: for SDAP-less stacks it carries the well-known packet-name classes as ordinary catch-all definitions ("VoIP*" = LCG 0, "gaming*" = LCG 2, "VoD*" = LCG 1, everything else LCG 3, all RLC UM), and for SDAP stacks a single default bearer (the last row, "5gc"), header-suppressed: an unauthored run carries the one default QoS flow with no SDAP header on the wire, and a run whose traffic actually shows up with several QFIs stops with an error asking for authored bearers (or an unsuppressed default) instead of silently mixing its flows. Overriding the parameter replaces the whole set with the configuration's own. An "epc" entry describes bearers of SDAP-less stacks only and a "5gc" entry those of SDAP stacks only; a "ue" pattern (or an omitted "ue") covering UEs of both kinds simply skips the incompatible ones, but an entry whose explicit "ue" pattern matches no UE with a compatible stack is an error. So in any given network only the rows for the stacks present take effect, and the two default rows of the two kinds coexist harmlessly: the "5gc" default bearer is what lets a UE with SDAP run unauthored (its QFI-to-DRB table would otherwise be empty and the first packet would find no bearer), the "epc" rows do the same for a UE without. D2D and multicast bearers are outside the definition system: the tables describe infrastructure (Uu) bearers, while those are sidelink ones. They are established with a fixed configuration (RLC UM, LCG 3). The model has no sidelink bearer vocabulary and needs none: the only multicast in the model is D2D groupcast, which is kept working as it stands, and the network never originates multicast of its own.

Example (in an ini file; the first entry suits a stack with SDAP, the other two one without):

*.bearerConfigurator.onDemandDrbs = [
    {coreNetwork: "5gc", ue: "ue[*]", mappedQfis: [3, 4], profile: "5qi-3"},
    {coreNetwork: "epc", filters: ["expr(udp.destPort == 3000)"], lcg: 0, rlcMode: "UM"},
    {coreNetwork: "epc", isDefault: true, lcg: 3, rlcMode: "UM"}
    ]

See the VoIP-DL-MultiQfi-OnDemandDrb configuration of simulations/nr/standalone_drb ("5gc") and the SingleCell-DL-OnDemandDrb configuration of simulations/lte/tutorial ("epc") for working setups.

The dlQfiRules and ulQfiRules parameters author the network's QFI classification: which QoS flow (QFI) each packet belongs to. The bearer definitions above map already-assigned QFIs onto DRBs (mappedQfis); these two tables are where the QFIs themselves are assigned, once per direction at its ingress. The rules are delivered from here to their evaluation sites -- dlQfiRules to the TrafficFlowFilter at each core-network tunnel entry (modeling the PDR/QER rules the SMF installs into a UPF over N4 at session setup), ulQfiRules to each UE's QosFlowClassifier (modeling the QoS rules NAS signaling installs into a UE at PDU session establishment, TS 23.501 5.7.1.4) -- and the sites never author rules of their own: the ini author writes the operator's classification policy here, and this module plays the signaling the model does not have.

Rule fields (both tables; evaluated in order at each site, first match wins):

  • filter (string, optional): an inet::PacketFilter -- a message-name pattern (e.g. "*VoIP*") or an expression written as "expr(...)" (e.g. "expr(udp.destPort == 3000)"); omitted = the rule matches every packet
  • qfi (int, 0..63) or dscpAsQfi (bool): the QFI to assign -- a fixed value, or the packet's IPv4 DSCP field read as the QFI (exactly one of the two)
  • node (string, dlQfiRules only, optional): module-path pattern of the core-network nodes whose tunnel-entry filter gets the rule (relative to the network, e.g. "upf" or "**.upf_mec"); omitted = every such node
  • ue (string, ulQfiRules only, optional): module-path pattern of the UEs that get the rule, matched like the bearer tables' "ue" field; omitted = every UE with SDAP

The two directions are authored separately, and a conversation that needs classification in both states a rule in each table, each written from its own direction's perspective. There is no sharing or reversal between them: the same filter means different things at the two ends (in "expr(udp.destPort == 3000)" the destination port is the UE's application port for downlink traffic and the server's for uplink), and a filter expression cannot be reversed mechanically. This mirrors the spec's own shape -- downlink PDRs at the UPF, uplink QoS rules in the UE.

A downlink packet no rule covers gets QFI 0, the default flow; an uplink packet no rule covers is left unclassified, which lets reflective QoS or the default DRB take over (see QosFlowClassifier). The dlQfiRules default value, [{dscpAsQfi: true}], is plain DSCP-as-QFI assignment at every tunnel entry. Overriding either parameter replaces its whole table, so a configuration that scopes rules to one node (say, a MEC host's UPF) and still wants the DSCP classification elsewhere appends the catch-all back explicitly. Base stations are not delivery sites -- no SMF installs classification rules into a gNB -- and their filters classify unattributed traffic by a built-in DSCP-as-QFI residual (see TrafficFlowFilter).

Used in

Name Type Description
ExtClientServer_bgCells network

ExtClientServerExample with background cells instead of external ones: one gNodeB served by a Upf core, a router in front of the Upf, one NrUe, and numBgCells BackgroundCell cells. The router has no simulated peer: the host it talks to, and the applications on the NrUe, are configured in the ini file.

ExtClientServerExample network

One gNodeB served by a Upf core, a router in front of the Upf, and one NrUe. numExtCells ExtCell cells can be added as interferers. The router has no simulated peer: the host it talks to, and the applications on the NrUe, are configured in the ini file.

ExtMecAppExample network

One gNodeB and one MecHost hung off the same intermediate Upf, behind an anchor Upf that carries the Ualcmp and, behind it, the MecOrchestrator, plus one NrUe. Nothing here is external: which node talks to a real host, and over which interface, is configured in the ini file.

ExtServerExample network

One gNodeB served by a Upf core, a router in front of the Upf, and two NrUe terminals. numExtCells ExtCell cells can be added as interferers. The router has no simulated peer: the host it talks to, and the applications on the UEs, are configured in the ini file.

ExtUeAppExample network

One gNodeB and one MecHost hung off the same intermediate Upf, behind an anchor Upf that carries the Ualcmp and, behind it, the MecOrchestrator, plus one NrUe. Nothing here is external: which node talks to a real host, and over which interface, is configured in the ini file.

ExtUeAppMecAppExample network

One gNodeB and one MecHost hung off the same intermediate Upf, behind an anchor Upf that carries the Ualcmp and, behind it, the MecOrchestrator, plus one NrUe. Nothing here is external: which node talks to a real host, and over which interface, is configured in the ini file.

MultiCell network

Two eNodeB cells on a shared EPC PgwStandard, joined by an X2 link, with a router and a server behind the core. Four LteUe terminals are placed two per cell, and numExtCells ExtCell cells can be added as interferers.

MultiCell_D2DMultihop network

Five eNodeB cells, each reaching the EPC PgwStandard through a router of its own, with a further router and a server behind the core. There are no X2 links. numUe1 to numUe5 LteUe terminals attach per cell, and an EventGenerator and a MultihopD2DStatistics module sit beside them, wired to nothing.

MultiCell_Standalone network

Two gNodeB cells served by a 5G core: the anchor Upf faces the data network (a router and a server), an intermediate Upf feeds both gNodeBs, and an X2 link joins them. numUe NrUe terminals attach, and numBgCells BackgroundCell cells can be added as interferers.

MultiCell_withSecondaryGnb network

The two-cell version of SingleCell_withSecondaryGnb: two eNodeB masters, each paired over X2 with its own gNodeB secondary, and a further X2 link between the two masters. Both eNodeBs connect to the EPC PgwStandard, which faces a router and a server; neither gNodeB has a core-network link. numUe NrUe terminals attach, and numBgCells BackgroundCell cells can be added as interferers.

MultiCell_X2Mesh network

Three eNodeB cells in a full X2 mesh. Each reaches the EPC PgwStandard through a router of its own, and the server sits directly on the PgwStandard's data-network gate. numUe1, numUe2 and numUe3 LteUe terminals attach per cell, and numExtCells ExtCell cells can be added as interferers.

MultiMecHost network

Two gNodeB cells, each on an intermediate Upf of its own with a MecHost hung off it, so every cell has its own MEC host. Both intermediate Upf nodes meet at the anchor Upf, which carries the Ualcmp and, behind it, the MecOrchestrator. An X2 link joins the two gNodeBs. numUe NrUe terminals attach, and numBgCells BackgroundCell cells can be added as interferers.

MultiMecHost_delay network

MultiMecHost with the two intermediate Upf nodes linked directly to each other, and with no X2 link between the gNodeBs. The length of that link -- and so its propagation delay -- follows the routersDelay parameter, which makes the distance between the two MEC hosts configurable.

MultiOperator network

Two operator networks side by side. Each has three gNodeB cells chained by X2, an intermediate Upf that feeds them and carries the operator's MecHost, an anchor Upf, and a Ualcmp with its MecOrchestrator. The two anchor Upf nodes meet at a shared router, the only node the operators have in common. numUe_A and numUe_B NrUe terminals attach to operator A and B respectively, and numBgCells BackgroundCell cells can be added as interferers.

RnisTest network

The topology of SingleMecHost -- one gNodeB and one MecHost on a shared intermediate Upf, with a Ualcmp and a MecOrchestrator behind the anchor Upf -- without its playground size parameters. numUes NrUe terminals attach to the gNodeB.

SingleCell network

The minimal LTE topology: one eNodeB connected to an EPC PgwStandard, which faces a router and a server, plus numUe LteUe terminals.

SingleCell_D2D network

SingleCell with its UEs split into three vectors, so that a configuration can address cellular terminals (ueCell), D2D transmitters (ueD2DTx) and D2D receivers (ueD2DRx) separately. The rest of the topology is the same: one eNodeB on an EPC PgwStandard, with a router and a server behind it.

SingleCell_D2DMulticast network

SingleCell with its UEs split into cellular terminals (ueCell) and members of a D2D multicast group (ueD2D). The rest of the topology is the same: one eNodeB on an EPC PgwStandard, with a router and a server behind it.

SingleCell_Standalone network

One gNodeB served by a 5G core: the anchor Upf faces the data network (a router and a server), and an intermediate Upf sits between it and the gNodeB. numUe NrUe terminals attach to the gNodeB, and numBgCells BackgroundCell cells can be added around it as interferers.

SingleCell_Standalone_D2D network

SingleCell_Standalone with its UEs split into three vectors, so that a configuration can address cellular terminals (ueCell), D2D transmitters (ueD2DTx) and D2D receivers (ueD2DRx) separately. The rest of the topology is the same: one gNodeB behind an intermediate and an anchor Upf, with a router and a server on the data network, plus numBgCells BackgroundCell interferers.

SingleCell_withSecondaryEnb network

The mirror image of SingleCell_withSecondaryGnb: here the gNodeB is the master node and the eNodeB is its secondary, so the UE is anchored on its NR stack and its LTE stack carries the secondary cell group. All data-plane traffic enters at the gNodeB.

SingleCell_withSecondaryGnb network

An EN-DC topology: an eNodeB master paired over X2 with a gNodeB secondary. The eNodeB is the only node with a core-network link -- an EPC PgwStandard facing a router and a server -- so all data-plane traffic enters there, and the gNodeB contributes its radio leg alone. numUe NrUe terminals attach to both, and numBgCells BackgroundCell cells can be added as interferers.

SingleMecHost network

One gNodeB and one MecHost hung off the same intermediate Upf, behind an anchor Upf that carries the Ualcmp and, behind it, the MecOrchestrator. numUes NrUe terminals attach to the gNodeB.

UrbanNetwork network (no description)

Parameters

Name Type Default value Description
binderModule string "binder"
staticDrbs object []

JSON array: [{coreNetwork, ue, drbId, profile, mappedQfis, filters, lcg, rlcMode, legs, pduSessionType, upperProtocol, isDefault, suppressSdapHeader, gbr, packetDelayBudget, packetErrorRate, qosPriorityLevel}, ...]; see banner comment for details

onDemandDrbs object [ // JSON array, staticDrbs schema minus "drbId" (and "ue" optional): bearers created when traffic first matches them; the default value lets both stack kinds run unauthored; see banner comment for details {coreNetwork: "epc", filters: ["VoIP*"], lcg: 0, rlcMode: "UM"}, {coreNetwork: "epc", filters: ["gaming*"], lcg: 2, rlcMode: "UM"}, {coreNetwork: "epc", filters: ["VoDPacket*", "VoDFinishPacket*"], lcg: 1, rlcMode: "UM"}, {coreNetwork: "epc", isDefault: true, lcg: 3, rlcMode: "UM"}, {coreNetwork: "5gc", isDefault: true, suppressSdapHeader: true, lcg: 3, rlcMode: "UM"} ]
drbProfiles object {}

JSON map of named field groups referenced by the staticDrbs entries' "profile" field, e.g. {voice: {rlcMode: "UM", gbr: true, ...}, ...}; see banner comment

dlQfiRules object [{dscpAsQfi: true}]

QFI classification rules, delivered to their evaluation sites (see banner comment)

ulQfiRules object []

JSON array of uplink QFI-assignment rules [{ue, filter, qfi|dscpAsQfi}, ...], delivered to the UEs' QoS-flow classifiers; [] = classify nothing

amPerThreshold double 1e-4

QoS-derived RAN defaults for definitions that do not state rlcMode/lcg themselves (operator policy, not spec-mandated: 3GPP standardizes the QoS characteristics, the RAN chooses what to make of them)

lcgPriorityBounds object [25, 50, 75]

Lcg derivation: qosPriorityLevel < bounds[k] -> LCG k, else LCG 3; strictly ascending, one bound between each pair of adjacent LCGs

Properties

Name Value Description
display i=block/cogwheel

Source code

//
// Central configurator of the network's data radio bearers.
//
// This module does not model a single 3GPP network function. It combines, in one
// network-wide service, decisions that a real system distributes between the core
// network and the RAN: in 5GS, the SMF controls PDU sessions and QoS flows, while the
// NG-RAN decides how QoS flows map onto DRBs and derives the radio configuration
// (TS 23.501 5.7.1, TS 38.300 12); in EPS, the corresponding roles are spread across
// the MME and the eNB. Here every bearer is authored in one place instead, and the
// signalling that would carry the configuration (N1/N2/S1/RRC procedures) is not
// modeled: within the model, the RAN never authors a bearer of its own -- every
// bearer comes from this module's tables.
//
// One cellular network holds one instance of this module, alongside its ~Binder. Like
// the Binder, it is always reached through module paths supplied in parameters
// (bearerConfiguratorModule), never through hardcoded ones, so several cellular
// networks -- each with its own Binder and BearerConfigurator pair -- can coexist
// within one simulation. The "ue" patterns of the definition tables range over the
// UEs registered in this instance's Binder only, but are matched against module paths
// relative to the toplevel network, so in such a setup the entries (and the
// module-path parameters) name their nodes by qualified paths, e.g. "networkA.ue[*]".
//
// Modeling abstractions and current limitations:
//  - Bearer establishment is a direct call into the RRC of each node involved; no
//    signalling procedure carries it.
//  - Packet-triggered establishment (onDemandDrbs) is a simulation policy. In 5GS, a
//    first UL packet with an unmapped QFI would ride the already-established default
//    DRB, and the gNB could reconfigure the mapping afterwards (TS 38.300 Annex A);
//    creating the DRB before the first packet is delivered is a shortcut.
//  - One PDU session (in EPS terms: one PDN connection) per UE is assumed. QFI
//    mappings, the default DRB and the pduSessionType are therefore scoped per UE,
//    although the spec scopes all of them per PDU session (TS 37.324); a UE with
//    several sessions, e.g. toward multiple DNs or with two session types, cannot
//    be described yet.
//  - The QoS characteristics attached to a definition describe the DRB as a whole.
//    In 5GS they belong to QoS flows, and flows with different QoS profiles may
//    legitimately share a DRB; per-flow QoS is not modeled.
//  - legSelection is a Simu5G extension: 3GPP steers split bearers by PDCP-level
//    controls (primaryPath, ul-DataSplitThreshold), not by per-PDU expressions.
//
// The staticDrbs parameter is the network's data radio bearer configuration: one entry per
// bearer per UE, describing the bearer before and independent of its establishment (modeled
// on the DRB-ToAddMod and RLC-BearerConfig records of TS 38.331). This module tells the RRC
// of each node involved in a bearer -- the UE and its serving node -- what to set up, and
// RRC pushes on what each of its layers consumes. Nothing reads this configuration back out.
//
// A static bearer is not only configured but also established up front, in the last
// initialization stage: each entry results in the same establishment call that
// packet-triggered setup makes, so traffic finds the bearer in place. A dual-stack UE's
// bearer is established on the stack that packet-triggered establishment would pick
// (split into per-technology legs when the UE is served by a node pair in dual
// connectivity); an entry whose UE is attached to no cell at that point is a
// configuration error. To make the static configuration the only source of bearers,
// disable packet-triggered establishment via the establishBearersOnDemand parameter of
// ~NrSdap (or ~Ip2Nic, for stacks without SDAP); see the VoIP-DL-MultiQfi-NoOnDemand
// configuration of the simulations/nr/standalone_drb example.
//
// Because an entry names its UE by module path rather than by node id, the configuration
// follows the UE from cell to cell, and neither end of the radio link is configured
// directly from the ini.
//
// staticDrbs fields:
//  - coreNetwork (string, required): "5gc" or "epc" -- which bearer architecture selects the
//    bearer. A "5gc" bearer is selected by the QFIs mapped onto it (mappedQfis; needs SDAP in
//    the stack); an "epc" bearer is selected by packet filters (filters; for stacks without
//    SDAP). Stated per entry, never inferred; each receiving RRC checks it against its stack.
//  - ue (string): module path of the UE node, relative to the network; patterns are allowed,
//    so one entry can describe a bearer of many UEs (e.g. "ue[*]")
//  - drbId (int): DRB identity, 1..32 (TS 38.331 DRB-Identity)
//  - profile (string, optional): name of a drbProfiles entry supplying defaults for the
//    fields it does not spell out itself
//  - mappedQfis (int[], optional, "5gc" only): QFI values (0..63) mapped to this DRB; an entry without
//    it does not take part in SDAP's QFI-to-DRB mapping. This field maps already-assigned
//    QFIs onto the DRB; which QFI a packet carries is decided by the QFI classification
//    rules (the dlQfiRules and ulQfiRules parameters below)
//  - filters (string[], optional, "epc" only): packet filters selecting this bearer, each
//    an inet::PacketFilter -- a message-name pattern (e.g. "VoIP*") or an expression written
//    as "expr(...)" (e.g. "expr(udp.destPort == 3000)"). An expression sees the packet that
//    triggers establishment, i.e. an UL-triggered and a DL-triggered flow present swapped
//    port/address roles; a list can carry both spellings.
//  - lcg (int, optional): the bearer's logical channel group (0..3;
//    mac-LogicalChannelConfig). In 3GPP an LCG only groups logical-channel buffers
//    for buffer status reporting; that Simu5G's MAC scheduler additionally serves
//    lower LCG indices first is a Simu5G scheduling policy, not spec semantics (the
//    spec's per-logical-channel priority is a separate parameter, not modeled, and
//    NR allows 8 LCGs where this model keeps LTE's 4). Omitted = derived from the
//    QoS profile's priority level (bucketed by lcgPriorityBounds), or 0 when the
//    definition carries no "qosPriorityLevel"
//  - rlcMode (string, optional when the definition carries a "packetErrorRate"): RLC
//    mode ("AM" or "UM"; "TM" is rejected -- 3GPP transparent mode carries
//    BCCH/PCCH/SRB0-class channels, not DRBs); omitted = derived from the QoS
//    profile's packet error rate
//    (packetErrorRate <= amPerThreshold -> "AM", else "UM": a PER target HARQ alone
//    cannot meet gets ARQ).
//    Required, in the entry or its profile, when there is nothing to derive it from.
//  - primaryPath (string, default "MCG"): on a split bearer (two legs), the preferred leg --
//    used in either direction whenever the bearer is not splitting; must be one of its two
//    legs (TS 38.331 PDCP-Config, TS 38.323 5.2.1; applied by ~DcPdcpLegSplitter).
//  - ulDataSplitThreshold (int bytes, or "infinity"; default "infinity"): uplink only. How
//    much of a split bearer's data must be queued waiting to send (in its legs' RLC buffers)
//    before the UE uses the second leg as well as primaryPath. "infinity" means never -- the
//    uplink stays on primaryPath. (Only the UE has both legs' queues locally; downlink has no
//    such threshold, see dlLegSelection.)
//  - ulLegSelection (string, optional): once the uplink is using both legs (at or above the
//    threshold), which leg each PDU takes -- an expr(...) over packetOrdinal (a running count
//    of the bearer's PDUs) returning the leg number, 0 or 1 (e.g. "expr(packetOrdinal % 2)"
//    for round-robin). Default when omitted: the less-loaded leg. Set ulDataSplitThreshold to
//    0 to have it decide every uplink PDU; stating it while leaving the threshold at infinity
//    is rejected.
//  - dlLegSelection (string, optional): the downlink counterpart, applied at the DC master.
//    The master cannot weigh the secondary leg's queue (it is at another node, across X2), so
//    downlink has no threshold or load-balancing: with dlLegSelection each downlink PDU takes
//    the leg it returns, and without it the downlink stays on primaryPath. (Real downlink
//    split flow control is X2-feedback-driven and is not modeled.)
//  - legs (string[]/object[], optional): the cell groups that serve this bearer, i.e. its
//    RLC bearers (TS 38.331 RLC-BearerConfig). One leg = an MCG or an SCG bearer, both =
//    a split bearer (TS 37.340; stated in that order). An element is either a cell group
//    name ("MCG" or "SCG"), or an object naming it and overriding the RLC configuration
//    it inherits from the entry: {leg: "SCG", rlcMode: "AM", soFraming: true,
//    snFieldLength: 18}. Omitted = the configuration does not state the legs and RRC
//    derives them, as it always has. An SCG bearer's PDCP still terminates at the master
//    node -- the core network delivers the UE's traffic there -- and every PDU is
//    relayed to the secondary over X2 (an MN-terminated SCG bearer in TS 37.340 terms).
//  - pduSessionType (string, optional): "IPv4", "IPv6", "IPv4v6", "Ethernet", "Unstructured";
//    default: "IPv4"
//  - upperProtocol (string, optional): INET protocol name for upper layer dispatch (this is
//    normally only needed for "Unstructured" PDU sessions); default: derived from
//    pduSessionType
//  - isDefault (bool, optional): marks this as the default DRB for the UE -- the fallback
//    when no QFI-to-DRB mapping ("5gc") or packet filter ("epc") matches. If no entry of
//    a UE is marked in either table, the UE's single static bearer takes the role; a UE
//    with several bearers must mark one explicitly.
//  - suppressSdapHeader (bool, optional, "5gc" only): the bearer's packets carry no SDAP
//    header (TS 38.331 sdap-HeaderDL/UL "absent"). Only meaningful on the default bearer
//    (any other bearer with at most one mapped QFI is headerless already), and only sound
//    when a single QoS flow actually rides it: the receiver assigns every headerless
//    packet the bearer's sole mapped QFI (QFI 0 when none is mapped), and the sender
//    verifies each packet against that value, stopping with an error when a second flow
//    shows up. The header decision itself is computed by this module and delivered per
//    bearer; SDAP applies it as pushed.
//  - gbr (bool), packetDelayBudget (double, ms), packetErrorRate (double),
//    qosPriorityLevel (int) -- all optional: the
//    QoS profile of the bearer's flows (5QI characteristics). Any of them present marks the
//    bearer as having a QoS profile, which RRC pushes into the eNB/gNB MAC for QoS-aware
//    scheduling.
//
// Field groups that repeat across entries can be named once in the drbProfiles parameter (a
// JSON map of name -> field group) and referenced from entries via their "profile" field. A
// profile describes what the bearer is, so it may hold any entry field except the ones that
// say which UE it belongs to (ue, drbId), which architecture and flows select it (coreNetwork,
// mappedQfis, filters, isDefault).
//
// A commonly used subset of the standardized QoS characteristics rows -- the core 1..9
// of each table; both tables define many more -- is available as predefined profiles,
// referenced by name without being defined: "qci-1".."qci-9" (TS 23.203 Table 6.1.7-A)
// and "5qi-1".."5qi-9" (TS 23.501 Table 5.7.4-1). A row carries what the spec
// standardizes -- gbr, qosPriorityLevel, packetDelayBudget, packetErrorRate -- and
// nothing else: the RLC mode and the logical channel group are RAN choices, derived
// from those characteristics by default (the way a gNB derives its AS configuration
// from the delivered QoS profile; see the rlcMode and lcg field descriptions) and
// stated on the entry only to override, e.g.
// {coreNetwork: "5gc", ue: "ue[*]", drbId: 1, mappedQfis: [1, 2], profile: "5qi-1"}.
// A drbProfiles entry may not redefine a predefined name. NOTE the spec's priority
// scales (QCI 1..9, 5QI 10..90) differ from each other and from the small hand-picked
// values older configurations use. The QoS-aware scheduler weights bearers by
// 1/qosPriorityLevel, so only priority RATIOS matter to it and the two spec catalogs
// discriminate identically; but the absolute values still drive the lcgPriorityBounds
// bucketing (whose defaults suit the 5QI scale: single-digit priorities all land in
// LCG 0), so profiles from different scales still should not be mixed within one
// network.
//
// Example (in an ini file):
//
// <pre>
// *.bearerConfigurator.drbProfiles = {
//     voice:  {rlcMode: "UM", gbr: true, packetDelayBudget: 100, packetErrorRate: 1e-2,
//              qosPriorityLevel: 2}
//     }
// *.bearerConfigurator.staticDrbs = [
//     {coreNetwork: "5gc", ue: "ue[*]", drbId: 1, mappedQfis: [1, 2], profile: "voice"}
//     ]
// </pre>
//
// The onDemandDrbs parameter describes bearers that are created when traffic first
// matches them, instead of being configured up front. Entries have the same fields as
// staticDrbs minus drbId: an on-demand bearer's id is assigned at creation, so
// definitions can never collide over ids ("ue" may also be omitted, meaning every UE).
// A "5gc" entry serves the QFIs in its mappedQfis: the first packet of an uncovered QFI
// creates the DRB (SDAP asks this module on a QFI-to-DRB lookup miss), and later QFIs
// of the same entry join it. An "epc" entry is matched by its filters against the
// packet that triggers bearer establishment, and an entry with isDefault=true catches
// the flows no filter matched ("5gc" entries cannot be the default: the default DRB is
// where unmapped QFIs go, so it must exist up front). A created bearer's definition is
// delivered to the RRCs involved exactly like a staticDrbs entry. Matching order is
// staticDrbs entries first, then onDemandDrbs entries, each in table order, first
// match wins.
//
// A flow that no definition covers is a configuration error: every on-demand bearer's
// properties come from a definition entry, never from the packet. The parameter's
// default value keeps configurations that author nothing working, whichever stack they
// run: for SDAP-less stacks it carries the well-known packet-name classes as ordinary
// catch-all definitions ("VoIP*" = LCG 0, "gaming*" = LCG 2, "VoD*" = LCG 1, everything
// else LCG 3, all RLC UM), and for SDAP stacks a single default bearer (the last row,
// "5gc"), header-suppressed: an unauthored run carries the one default QoS flow with no
// SDAP header on the wire, and a run whose traffic actually shows up with several QFIs
// stops with an error asking for authored bearers (or an unsuppressed default) instead
// of silently mixing its flows. Overriding the parameter replaces the whole set
// with the configuration's own.
// An "epc" entry describes bearers of SDAP-less stacks only and a "5gc" entry those of
// SDAP stacks only; a "ue" pattern (or an omitted "ue") covering UEs of both kinds
// simply skips the incompatible ones, but an entry whose explicit "ue" pattern matches
// no UE with a compatible stack is an error. So in any given network only the rows for
// the stacks present take effect, and the two default rows of the two kinds coexist
// harmlessly: the "5gc" default bearer is what lets a UE with SDAP run unauthored (its
// QFI-to-DRB table would otherwise be empty and the first packet would find no bearer),
// the "epc" rows do the same for a UE without.
// D2D and multicast bearers are outside the definition system: the tables describe
// infrastructure (Uu) bearers, while those are sidelink ones. They are established
// with a fixed configuration (RLC UM, LCG 3). The model has no sidelink bearer
// vocabulary and needs none: the only multicast in the model is D2D groupcast, which
// is kept working as it stands, and the network never originates multicast of its own.
//
// Example (in an ini file; the first entry suits a stack with SDAP, the other two
// one without):
//
// <pre>
// *.bearerConfigurator.onDemandDrbs = [
//     {coreNetwork: "5gc", ue: "ue[*]", mappedQfis: [3, 4], profile: "5qi-3"},
//     {coreNetwork: "epc", filters: ["expr(udp.destPort == 3000)"], lcg: 0, rlcMode: "UM"},
//     {coreNetwork: "epc", isDefault: true, lcg: 3, rlcMode: "UM"}
//     ]
// </pre>
//
// See the VoIP-DL-MultiQfi-OnDemandDrb configuration of simulations/nr/standalone_drb
// ("5gc") and the SingleCell-DL-OnDemandDrb configuration of simulations/lte/tutorial
// ("epc") for working setups.
//
// The dlQfiRules and ulQfiRules parameters author the network's QFI classification:
// which QoS flow (QFI) each packet belongs to. The bearer definitions above map
// already-assigned QFIs onto DRBs (mappedQfis); these two tables are where the QFIs
// themselves are assigned, once per direction at its ingress. The rules are
// delivered from here to their evaluation sites -- dlQfiRules to the
// ~TrafficFlowFilter at each core-network tunnel entry (modeling the PDR/QER rules
// the SMF installs into a UPF over N4 at session setup), ulQfiRules to each UE's
// ~QosFlowClassifier (modeling the QoS rules NAS signaling installs into a UE at
// PDU session establishment, TS 23.501 5.7.1.4) -- and the sites never author rules
// of their own: the ini author writes the operator's classification policy here,
// and this module plays the signaling the model does not have.
//
// Rule fields (both tables; evaluated in order at each site, first match wins):
//  - filter (string, optional): an inet::PacketFilter -- a message-name pattern
//    (e.g. "*VoIP*") or an expression written as "expr(...)"
//    (e.g. "expr(udp.destPort == 3000)"); omitted = the rule matches every packet
//  - qfi (int, 0..63) or dscpAsQfi (bool): the QFI to assign -- a fixed value, or
//    the packet's IPv4 DSCP field read as the QFI (exactly one of the two)
//  - node (string, dlQfiRules only, optional): module-path pattern of the
//    core-network nodes whose tunnel-entry filter gets the rule (relative to the
//    network, e.g. "upf" or "**.upf_mec"); omitted = every such node
//  - ue (string, ulQfiRules only, optional): module-path pattern of the UEs that
//    get the rule, matched like the bearer tables' "ue" field; omitted = every UE
//    with SDAP
//
// The two directions are authored separately, and a conversation that needs
// classification in both states a rule in each table, each written from its own
// direction's perspective. There is no sharing or reversal between them: the same
// filter means different things at the two ends (in "expr(udp.destPort == 3000)"
// the destination port is the UE's application port for downlink traffic and the
// server's for uplink), and a filter expression cannot be reversed mechanically.
// This mirrors the spec's own shape -- downlink PDRs at the UPF, uplink QoS rules
// in the UE.
//
// A downlink packet no rule covers gets QFI 0, the default flow; an uplink packet
// no rule covers is left unclassified, which lets reflective QoS or the default
// DRB take over (see ~QosFlowClassifier). The dlQfiRules default value,
// [{dscpAsQfi: true}], is plain DSCP-as-QFI assignment at every tunnel entry.
// Overriding either parameter replaces its whole table, so a configuration that
// scopes rules to one node (say, a MEC host's UPF) and still wants the DSCP
// classification elsewhere appends the catch-all back explicitly. Base stations
// are not delivery sites -- no SMF installs classification rules into a gNB -- and
// their filters classify unattributed traffic by a built-in DSCP-as-QFI residual
// (see ~TrafficFlowFilter).
//
simple BearerConfigurator
{
    parameters:
        string binderModule = default("binder");
        object staticDrbs = default([]);  // JSON array: [{coreNetwork, ue, drbId, profile, mappedQfis, filters, lcg, rlcMode, legs, pduSessionType, upperProtocol, isDefault, suppressSdapHeader, gbr, packetDelayBudget, packetErrorRate, qosPriorityLevel}, ...]; see banner comment for details
        // JSON array, staticDrbs schema minus "drbId" (and "ue" optional): bearers created when traffic first matches them; the default value lets both stack kinds run unauthored; see banner comment for details
        object onDemandDrbs = default([  // JSON array, staticDrbs schema minus "drbId" (and "ue" optional): bearers created when traffic first matches them; the default value lets both stack kinds run unauthored; see banner comment for details
                {coreNetwork: "epc", filters: ["VoIP*"], lcg: 0, rlcMode: "UM"},
                {coreNetwork: "epc", filters: ["gaming*"], lcg: 2, rlcMode: "UM"},
                {coreNetwork: "epc", filters: ["VoDPacket*", "VoDFinishPacket*"], lcg: 1, rlcMode: "UM"},
                {coreNetwork: "epc", isDefault: true, lcg: 3, rlcMode: "UM"},
                {coreNetwork: "5gc", isDefault: true, suppressSdapHeader: true, lcg: 3, rlcMode: "UM"}
            ]);
        object drbProfiles = default({});  // JSON map of named field groups referenced by the staticDrbs entries' "profile" field, e.g. {voice: {rlcMode: "UM", gbr: true, ...}, ...}; see banner comment

        // QFI classification rules, delivered to their evaluation sites (see banner comment)
        object dlQfiRules = default([{dscpAsQfi: true}]);  // JSON array of downlink QFI-assignment rules [{node, filter, qfi|dscpAsQfi}, ...], delivered to the traffic flow filters at core-network tunnel entries; first match wins per site
        object ulQfiRules = default([]);  // JSON array of uplink QFI-assignment rules [{ue, filter, qfi|dscpAsQfi}, ...], delivered to the UEs' QoS-flow classifiers; [] = classify nothing

        // QoS-derived RAN defaults for definitions that do not state rlcMode/lcg themselves
        // (operator policy, not spec-mandated: 3GPP standardizes the QoS characteristics,
        // the RAN chooses what to make of them)
        double amPerThreshold = default(1e-4);  // rlcMode derivation: a definition whose QoS profile has packetErrorRate <= this gets "AM", else "UM"
        object lcgPriorityBounds = default([25, 50, 75]);  // Lcg derivation: qosPriorityLevel < bounds[k] -> LCG k, else LCG 3; strictly ascending, one bound between each pair of adjacent LCGs
        @display("i=block/cogwheel");
}
File: src/simu5g/corenetwork/bearerConfigurator/BearerConfigurator.ned