mirror of
https://github.com/open5gs/open5gs.git
synced 2025-10-22 23:31:57 +00:00
[HR] V-UPF: preserve PSC on N2 indirect (Access->Access) without QER (#2194)
Home-Routed roaming: during Xn/N2 handover the source gNB may forward remaining DL data to the core using UL PDU Session Information (PSC). On the V-UPF the PSC was lost on the indirect path because OHR+OHC removed the incoming GTP-U header (and its extensions) and we did not recreate PSC when no QER/QFI was provisioned by the V-SMF. This change makes the V-UPF rebuild a DL PSC for the target gNB even when QER is absent, limited to the Access->Access indirect path (source gNB -> V-UPF -> target gNB). Why this is needed in HR: - In HR deployments the V-SMF typically does not provision QER/QFI for the temporary indirect path. Without recreating PSC from recvhdr, the extension header disappears after OHR+OHC and the target gNB cannot see the QFI during handover buffering/forwarding.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "v2.7.6 - Bug fixed"
|
title: "v2.7.6 - Bug fixed"
|
||||||
date: 2025-03-30 22:05:00 +0900
|
date: 2025-07-19 22:05:00 +0900
|
||||||
categories:
|
categories:
|
||||||
- Release
|
- Release
|
||||||
tags:
|
tags:
|
||||||
|
@@ -303,6 +303,39 @@ bool ogs_pfcp_up_handle_pdr(
|
|||||||
sendhdr.pdu_type =
|
sendhdr.pdu_type =
|
||||||
OGS_GTP2_EXTENSION_HEADER_PDU_TYPE_DL_PDU_SESSION_INFORMATION;
|
OGS_GTP2_EXTENSION_HEADER_PDU_TYPE_DL_PDU_SESSION_INFORMATION;
|
||||||
sendhdr.qos_flow_identifier = pdr->qer->qfi;
|
sendhdr.qos_flow_identifier = pdr->qer->qfi;
|
||||||
|
} else if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS &&
|
||||||
|
far->dst_if == OGS_PFCP_INTERFACE_ACCESS &&
|
||||||
|
recvhdr->qos_flow_identifier) {
|
||||||
|
/*
|
||||||
|
* HR Indirect Forwarding (source gNB -> V-UPF -> target gNB)
|
||||||
|
*
|
||||||
|
* Context:
|
||||||
|
* - Home-Routed roaming: the V-UPF is controlled by the V-SMF, which
|
||||||
|
* typically does not provision QER/QFI for the indirect path.
|
||||||
|
* - During Xn/N2 handover the source gNB may forward remaining DL data
|
||||||
|
* to the core using UL PDU Session Information (PSC PDU type = UL).
|
||||||
|
*
|
||||||
|
* Goal:
|
||||||
|
* - Preserve the PDU Session Container across the V-UPF hop and deliver
|
||||||
|
* it to the target gNB with PDU type = DL while keeping the same QFI.
|
||||||
|
*
|
||||||
|
* What we do here:
|
||||||
|
* - If this PDR has no QER/QFI and the path is Access->Access, derive
|
||||||
|
* PSC fields from the received header (recvhdr).
|
||||||
|
* - Force sendhdr.pdu_type = DL PDU Session Information.
|
||||||
|
* - Copy recvhdr->qos_flow_identifier into sendhdr.qos_flow_identifier.
|
||||||
|
* - The encapsulation routine will build a fresh GTP-U header and
|
||||||
|
* generate the PSC extension from sendhdr fields. This converts UL
|
||||||
|
* PSC to DL PSC and preserves the QFI for the target gNB.
|
||||||
|
*
|
||||||
|
* Why this is needed in HR:
|
||||||
|
* - With OHR+OHC, the incoming GTP-U (extensions included) is removed
|
||||||
|
* and a new one is created. Without recreating PSC from sendhdr.*, the
|
||||||
|
* extension header would be lost when QER is absent on the V-UPF.
|
||||||
|
*/
|
||||||
|
sendhdr.pdu_type =
|
||||||
|
OGS_GTP2_EXTENSION_HEADER_PDU_TYPE_DL_PDU_SESSION_INFORMATION;
|
||||||
|
sendhdr.qos_flow_identifier = recvhdr->qos_flow_identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recvhdr) {
|
if (recvhdr) {
|
||||||
@@ -962,6 +995,14 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_update_pdr(ogs_pfcp_sess_t *sess,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message->outer_header_removal.presence) {
|
||||||
|
pdr->outer_header_removal_len =
|
||||||
|
ogs_min(message->outer_header_removal.len,
|
||||||
|
sizeof(pdr->outer_header_removal));
|
||||||
|
memcpy(&pdr->outer_header_removal, message->outer_header_removal.data,
|
||||||
|
pdr->outer_header_removal_len);
|
||||||
|
}
|
||||||
|
|
||||||
return pdr;
|
return pdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -198,6 +198,14 @@ void sgwu_sxa_handle_session_modification_request(
|
|||||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
|
||||||
|
if (ogs_pfcp_handle_update_pdr(&sess->pfcp, &req->update_pdr[i],
|
||||||
|
&cause_value, &offending_ie_value) == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
|
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
|
||||||
if (ogs_pfcp_handle_remove_pdr(&sess->pfcp, &req->remove_pdr[i],
|
if (ogs_pfcp_handle_remove_pdr(&sess->pfcp, &req->remove_pdr[i],
|
||||||
&cause_value, &offending_ie_value) == false)
|
&cause_value, &offending_ie_value) == false)
|
||||||
|
Reference in New Issue
Block a user