From 296287ecee303a800ec7d6ec44defbcec331514a Mon Sep 17 00:00:00 2001 From: anaswara Date: Wed, 1 Jul 2026 14:57:24 +0530 Subject: [PATCH] longevity 333bug fix --- producer/pdu_session.go | 52 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/producer/pdu_session.go b/producer/pdu_session.go index e4f5a61f..bc9bcd62 100644 --- a/producer/pdu_session.go +++ b/producer/pdu_session.go @@ -704,8 +704,13 @@ func releaseTunnel(smContext *smf_context.SMContext) bool { smContext.SubPduSessLog.Errorf("releaseTunnel, pfcp tunnel already released") return false } + deletedPFCPNode := make(map[string]bool) smContext.PendingUPF = make(smf_context.PendingUPF) + + // Phase 1: populate PendingUPF fully BEFORE sending any requests. + // If requests are sent first, responses can arrive and clear PendingUPF + // before all UPFs are added, causing IsEmpty() to fire prematurely. for _, dataPath := range smContext.Tunnel.DataPathPool { dataPath.DeactivateTunnelAndPDR(smContext) for curDataPathNode := dataPath.FirstDPNode; curDataPathNode != nil; curDataPathNode = curDataPathNode.Next() { @@ -715,15 +720,54 @@ func releaseTunnel(smContext *smf_context.SMContext) bool { continue } if _, exist := deletedPFCPNode[curUPFID]; !exist { - err := pfcp_message.SendPfcpSessionDeletionRequest(curDataPathNode.UPF.NodeID, smContext, curDataPathNode.UPF.Port) - if err != nil { - smContext.SubPduSessLog.Errorf("releaseTunnel, send PFCP session deletion request failed: %v", err) - } deletedPFCPNode[curUPFID] = true smContext.PendingUPF[curDataPathNode.GetNodeIP()] = true + smContext.SubPfcpLog.Debugf( + "[PFCP] Added to PendingUPF map address[%p] content[%+v] len[%d] UE[%s] AddedUPF[%s]", + smContext.PendingUPF, + smContext.PendingUPF, + len(smContext.PendingUPF), + smContext.Supi, + curDataPathNode.GetNodeIP(), + ) } } } + + smContext.SubPfcpLog.Debugf( + "[PFCP] PendingUPF fully populated len[%d] UE[%s] content[%+v]", + len(smContext.PendingUPF), + smContext.Supi, + smContext.PendingUPF, + ) + + // Phase 2: now send deletion requests. Responses may arrive at any point + // from here, but PendingUPF is complete so IsEmpty() will only be true + // after ALL responses are processed. + deletedPFCPNode = make(map[string]bool) + for _, dataPath := range smContext.Tunnel.DataPathPool { + for curDataPathNode := dataPath.FirstDPNode; curDataPathNode != nil; curDataPathNode = curDataPathNode.Next() { + curUPFID, err := curDataPathNode.GetUPFID() + if err != nil { + smContext.SubPduSessLog.Error(err) + continue + } + if _, exist := deletedPFCPNode[curUPFID]; !exist { + deletedPFCPNode[curUPFID] = true + err := pfcp_message.SendPfcpSessionDeletionRequest( + curDataPathNode.UPF.NodeID, + smContext, + curDataPathNode.UPF.Port, + ) + if err != nil { + smContext.SubPduSessLog.Errorf( + "releaseTunnel, send PFCP session deletion request failed: %v", err, + ) + } + } + } + } + smContext.Tunnel = nil return true }