fix(qos): repair PFCP session modification with remove+create rules

Description

A PFCP Session Modification that removes some rules and creates new ones (the pattern an SMF uses to reconfigure QoS flows) left the UE unable to pass traffic between N3 and N6 and could stall the N4 handler. After forwarding was resolved, changed GBR/MBR values never reached the data plane. This MR makes session modification rebuild the data plane correctly, exactly once, from the session's final state, and tears down/rebuilds QoS (HTB/TC) state idempotently.

Issues resolved (summary):

  1. Issue: the modification handler rebuilt the BPF pipeline once per removed rule; only the final rebuild reflected the created rules. Solution: Rebuild the data plane *once, after all remove/create/update deltas are applied to the session.
  2. Issue: ModifySession re-applied the mod_req deltas that pfcp_switch had already applied, and re-running removal would drop a created rule that reused a removed rule ID. Solution: Make the datapath callback a pure resync of the session's current rule set.
  3. Issue: rules_match_pdr_map / sdf_filters_map were only ever written, never pruned, so removed PDRs/QFIs lingered. Solution: Clear a session's per-rule entries before re-populating (and on session removal).
  4. Issue: session_qos_enabled_map was set but never cleared, and the prior QERProgram was replaced without TearDown(). Solution: Clear the flag and tear down the previous program on rebuild / QoS-disable.
  5. Issue: QERProgram::Setup used tc class add (fails File exists on an existing class, keeping the old ceil/MBR) and never removed classes for deleted QFIs. Solution: Track created class IDs and delete this session's subtree (children before parent) in TearDown, so Setup rebuilds with current values. Scoped per-SEID.
  6. Issue: deadlock - public CRUD helpers lock then call the locking GetSession(). Solution: Add GetSessionLocked() for callers already holding the lock.
  7. Issue: CategorizePdrs appended without clearing. Solution: Rebuild the views each call.
  8. Issue: static-IP re-attach broke the data path. session_by_ue_ip_map (keyed by UE IP, used for both uplink and downlink) was never cleared on session deletion, and StorePduSessionInMap kept the existing SEID, so after re-attach with the same IP the entry still pointed at the deleted session and traffic was dropped. Solution: Clear the map entry on session removal, and take over the entry (refreshing TEIDs) when a different SEID claims the UE IP.

Tested Environment (e.g., radios, interfaces, CN)

Configuration Updates (e.g., files, parameters)

None. No config schema or parameter changes.

Known Issues / Limitations

  • Rebuilding the session's HTB class tree on every modification means in-flight shaped traffic for that session sees a sub-millisecond gap (packets pass unshaped) during the del→add window.
  • SMF guidance: when reconfiguring an existing flow, prefer Update PDR/FAR/QER over remove+create, and ensure created PDRs carry UE IP / F-TEID and FARs carry Outer Header Creation.

Checklist

  •  Code follows project coding standards.
  •  Relevant tests have been added or updated.
  •  Documentation has been updated where necessary.
  •  Configuration changes have been validated in the target environment(s). (N/A — no config changes; data-plane behaviour validated via tc/bpftool/iperf3.)

Log files or packet captures (PCAPs)

af-qos.pcapng

For the UE re-attach issue free5gc_static_ip_reattach.pcapng

smf.logs

gnb.logs

upf.logs

Additional Notes

Edited by Tariro Mukute

Merge request reports

Loading