Skip to content

Commit fc6ef76

Browse files
authored
[CENNSO-1947] fix: Error indication report crash (#399)
Report message could contain invalid session handler if send the same moment as deletion request for this session. This resulted in crash in session report response.
1 parent dfdf640 commit fc6ef76

File tree

5 files changed

+94
-3
lines changed

5 files changed

+94
-3
lines changed

test/e2e/framework/gtpu.go

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"os"
2323

2424
"github.com/pkg/errors"
25+
"github.com/wmnsk/go-gtp/gtpv1/ie"
26+
"github.com/wmnsk/go-gtp/gtpv1/message"
2527

2628
"github.com/sirupsen/logrus"
2729

@@ -148,6 +150,14 @@ func (gtpu *GTPU) Stop() error {
148150
return gtpu.up.Stop()
149151
}
150152

153+
func (gtpu *GTPU) SendErrorIndication(teid uint32, seq uint16, IEs ...*ie.IE) error {
154+
dst := net.UDPAddr{
155+
IP: gtpu.cfg.PGWIP,
156+
Port: 2152,
157+
}
158+
return gtpu.up.WriteTo(&dst, message.NewErrorIndication(teid, seq, IEs...))
159+
}
160+
151161
func (gtpu *GTPU) Context(parent context.Context) context.Context {
152162
return gtpu.up.Context(parent)
153163
}

test/e2e/pfcp/pfcp.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -918,8 +918,10 @@ func (pc *PFCPConnection) sendSessionReportResponse(req *message.SessionReportRe
918918

919919
up_seid = ses.up_seid
920920
}
921+
} else if sess := pc.sessions[SEID(req.SEID())]; sess != nil {
922+
up_seid = sess.up_seid
921923
} else {
922-
up_seid = pc.sessions[SEID(req.SEID())].up_seid
924+
return pc.send(message.NewSessionReportResponse(0, 0, 0, req.SequenceNumber, 0, ie.NewCause(ie.CauseSessionContextNotFound)))
923925
}
924926
ies = append(ies, ie.NewRecoveryTimeStamp(pc.timestamp))
925927
return pc.send(message.NewSessionReportResponse(0, 0, uint64(up_seid), req.SequenceNumber, 0, ies...))

test/e2e/upg_e2e.go

+69
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/onsi/ginkgo"
3434
"github.com/onsi/gomega"
3535
"github.com/pkg/errors"
36+
gtpuie "github.com/wmnsk/go-gtp/gtpv1/ie"
3637
gtpumessage "github.com/wmnsk/go-gtp/gtpv1/message"
3738
"github.com/wmnsk/go-pfcp/ie"
3839
"github.com/wmnsk/go-pfcp/message"
@@ -2218,6 +2219,74 @@ var _ = ginkgo.Describe("Error handling", func() {
22182219
})
22192220
})
22202221

2222+
var _ = ginkgo.Describe("PGW Error indication", func() {
2223+
f := framework.NewDefaultFramework(framework.UPGModePGW, framework.UPGIPModeV4)
2224+
ginkgo.It("Error indication for deleted session", func() {
2225+
ginkgo.By("Configuring session")
2226+
2227+
var sessionCfgs []framework.SessionConfig
2228+
var seids []pfcp.SEID
2229+
2230+
// Create another session to trigger crash
2231+
ueIPs := []net.IP{f.UEIP(), f.AddUEIP()}
2232+
for i, ueIP := range ueIPs {
2233+
sessionCfgs = append(sessionCfgs, framework.SessionConfig{
2234+
IdBase: 1,
2235+
UEIP: ueIP,
2236+
Mode: f.Mode,
2237+
VolumeQuota: 100000000,
2238+
TEIDPGWs5u: framework.TEIDPGWs5u + uint32(i),
2239+
TEIDSGWs5u: framework.TEIDSGWs5u + uint32(i),
2240+
PGWIP: f.VPPCfg.GetVPPAddress("grx").IP,
2241+
SGWIP: f.VPPCfg.GetNamespaceAddress("grx").IP,
2242+
})
2243+
seids = append(seids, f.PFCP.NewSEID())
2244+
}
2245+
2246+
for i := range sessionCfgs {
2247+
_, err := f.PFCP.EstablishSession(f.Context, seids[i], sessionCfgs[i].SessionIEs()...)
2248+
framework.ExpectNoError(err)
2249+
}
2250+
2251+
ginkgo.By("Starting some traffic")
2252+
tg, clientNS, serverNS := newTrafficGen(f, &traffic.UDPPingConfig{
2253+
PacketCount: 5,
2254+
Retry: false,
2255+
Delay: 10 * time.Millisecond,
2256+
}, &traffic.SimpleTrafficRec{})
2257+
tg.Start(f.Context, clientNS, serverNS)
2258+
2259+
ginkgo.By("Sending error indication")
2260+
2261+
stopSpam := make(chan struct{}, 1)
2262+
2263+
spamErrorsIndications := func() {
2264+
for {
2265+
select {
2266+
case _, closed := <-stopSpam:
2267+
if closed {
2268+
return
2269+
}
2270+
default:
2271+
err := f.GTPUs[0].SendErrorIndication(0, 0,
2272+
gtpuie.NewTEIDDataI(sessionCfgs[0].TEIDSGWs5u),
2273+
gtpuie.NewGSNAddress(f.VPPCfg.GetNamespaceAddress("grx").IP.String()),
2274+
)
2275+
gomega.Expect(err).NotTo(gomega.HaveOccurred())
2276+
time.Sleep(time.Millisecond)
2277+
}
2278+
}
2279+
}
2280+
go spamErrorsIndications()
2281+
2282+
f.PFCP.DeleteSession(f.Context, seids[0])
2283+
time.Sleep(time.Second / 2)
2284+
f.PFCP.DeleteSession(f.Context, seids[1])
2285+
close(stopSpam)
2286+
time.Sleep(10 * time.Second)
2287+
})
2288+
})
2289+
22212290
var _ = ginkgo.Describe("Error handling", func() {
22222291
f := framework.NewDefaultFramework(framework.UPGModeTDF, framework.UPGIPModeV4)
22232292

upf/upf_pfcp_api.c

+7
Original file line numberDiff line numberDiff line change
@@ -2953,6 +2953,13 @@ handle_session_report_response (pfcp_msg_t *msg, pfcp_decoded_msg_t *dmsg)
29532953
return -1;
29542954
}
29552955

2956+
if (pool_is_free_index (gtm->sessions, msg->session.idx))
2957+
{
2958+
/* Precaution against buggy code */
2959+
ASSERT (0);
2960+
return -1;
2961+
}
2962+
29562963
upf_session_t *sx = pool_elt_at_index (gtm->sessions, msg->session.idx);
29572964

29582965
if (msg->up_seid != sx->up_seid)

upf/upf_pfcp_server.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -1499,8 +1499,10 @@ pfcp_process (vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
14991499
pfcp_msg_t *tx = (pfcp_msg_t *) event_data[i];
15001500
// Handle case when session was removed before
15011501
// receiving this event
1502-
1503-
if (!pool_is_free_index (gtm->nodes, tx->node))
1502+
if (!pool_is_free_index (gtm->nodes, tx->node) &&
1503+
!pool_is_free_index (gtm->sessions, tx->session.idx) &&
1504+
pool_elt_at_index (gtm->sessions, tx->session.idx)
1505+
->up_seid == tx->up_seid)
15041506
{
15051507
pfcp_msg_t *msg;
15061508

@@ -1509,6 +1511,7 @@ pfcp_process (vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
15091511
}
15101512
else
15111513
{
1514+
upf_debug ("ignored tx event because session deleted");
15121515
vec_free (tx->data);
15131516
}
15141517

0 commit comments

Comments
 (0)