feat!: carry the network indicator through the MTP interface
The MTP-TRANSFER primitive carries OPC, DPC, SLS, SIO and user data (ITU-T Q.711 (03/01) §7.2, Table 18), and a signalling point code is an address element only "together with the MTP-SAP instance" (§6.1.1.2.2). The network indicator in the SIO (ITU-T Q.704 (07/96) §14.2.2: 00 international, 01 spare, 10 national, 11 reserved for national use) says which network a point code belongs to. M3UA carries it in its protocol data (RFC 4666 §3.3.1).
RoutingLabel had only OPC, DPC and SLS. The stack therefore answered without knowing which network a message came from, keyed reassembly and the per-peer bound on point codes that are unique only within a network, and left every application to remember the network itself. The SGP example did exactly that with its own reply table.
Changes
RoutingLabel.NI, aNetworkIndicatorwith the four codes of Q.704 §14.2.2 (stringer-generated names).StackConfig.NetworkIndicatoris the network of the messages the stack originates, international by default. A node that originates in several networks runs oneStackper network.- Every response goes to the network of the message it answers. That covers the UDTS/XUDTS/LUDTS returns, the CREF, the Table B.2 responses, and the messages of a connection section, whose peer is now identified by its NI and point code. A CC in state c3 associates both.
- The reassembly key (the whole
RoutingLabel) and the per-peer bound (now keyed on NI and OPC) include the network. - The MTP side is held to the field widths of the standard routing label: 14-bit DPC and OPC and a 4-bit SLS (Q.704 §§2.2.2-2.2.4), which §2.2.1 applies to national applications too, and the 2-bit NI.
NewStackrefuses a point code above 14 bits and a network indicator above 3.UnitdataandConnectrefuse a DPC above 14 bits.- A received message that breaks a width is discarded with
ErrInvalidRequest, without being parsed or reachingLocalGlobalTitle, instead of being answered with a label the MTP cannot carry.
docs/standards.mdand the README describe the network handling.
BREAKING CHANGE: RoutingLabel has a new field, and point codes above 14 bits and SLS values above 15 are refused on the MTP side.
Verification
network_indicator_test.gocovers:- the configuration and width boundaries: 0x3fff accepted, 0x4000 refused; SLS 15 accepted, 16 refused; NI 3 accepted, 4 refused;
- origination in the configured network;
- returns, CREF, CC, DT1, IT, RLSD and the Table B.2 responses in the received network;
- two messages identical except for NI reassembling independently;
- separate per-peer budgets for one OPC in two networks;
- a section refusing its own OPC from another network as a point code mismatch;
- the NI exposed on indications and discards.
FuzzUnitdataTransferandFuzzConnectionTransfervary the NI. The connectionless fuzz checks the per-(NI, OPC) accounting against its own tally. 60 s each: 13.3 and 18.7 million executions, no failure.- 15 planted faults, one per guard and propagation path, each fail the tests. Two were re-run independently in review: replies without NI, and the per-peer key without NI.
go test -race, vet, staticcheck (current and 0.8.1), golangci-lint: clean.go generatewith stringer v0.52.0 is stable;go fix -diffreports nothing.- On the wire, the SCCP examples over M3UA/SCTP between two Linux containers, captured with tshark at the SGP, with the examples branch that follows this PR:
| Scenario | Request NI | Reply NI |
|---|---|---|
| Before: an SGP that stops tracking the network itself, on the current library | 2 | 0, wrong network |
| After, national network | 2 | 2 (UDTS, cause 0x04) |
| After, default | 0 | 0 |
| After, national, two XUDT segments | 2 | 2 (one XUDTS with the first segment's segmentation parameter) |
No Wireshark expert information in any capture.
Summary by cubic
Carries the network indicator through the MTP interface so the SCCP stack can tell which network each message came from and answer in that network. The routing label now carries the NI (Q.704 §14.2.2), every response goes to the network of the message it answers, and reassembly and the per-peer octet bound are keyed on (NI, OPC). Originated messages use the network from StackConfig.NetworkIndicator, international by default.
The MTP side is also held to the field widths of the standard routing label: 14-bit OPC/DPC, 4-bit SLS, 2-bit NI. Values wider than that are refused with ErrInvalidRequest instead of being truncated or answered with a label the MTP cannot carry.
Breaking changes
RoutingLabelgains aNetworkIndicatorfield; point codes above 14 bits and SLS values above 15 are refused at the MTP.