Skip to content

Commit fc9da74

Browse files
allen0091Allen00991
andauthored
Feat/deregistration trigger by core (#18)
* feat: Add deregistration request sending by core network handling * feat: Add re-registration config to control whether to re-regist after ike connection fail * chore: rename IKE retransmit related function name * chore: rename ReRegistration to AutoRegistration in config --------- Co-authored-by: Allen00991 <allen.chen@saviah.com>
1 parent ddf5df4 commit fc9da74

14 files changed

Lines changed: 210 additions & 66 deletions

File tree

config/n3ue.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@ configuration:
3232
SNSSAI: # Single Network Slice Selection Assistance Information
3333
SST: 1 # Slice/Service Type (1 byte hex string, range: 0~F)
3434
SD: 112233 # Slice Differentiator (3 bytes hex string, range: 000000~FFFFFF)
35-
DpdInterval: 5s # Dead peer detection trigger interval, if is 0, disable DPD
35+
DpdInterval: 60s # Dead peer detection trigger interval, if is 0, disable DPD
3636
IkeRetransmit:
3737
enable: true
3838
base: 1
3939
expireTime: 2s
4040
maxRetryTimes: 3
41+
AutoReRegistration: false # Re-registration after connection is failed between N3UE and N3IWF
4142
Security:
4243
K: b73a90cbcf3afb622dba83c58a8415df
4344
RAND: b120f1c1a0102a2f507dd543de68281f

internal/nwucp/handler.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ func (s *Server) handleEvent(evt context.NwucpEvt) {
2626
s.handleStartPduSessionEstablishmentEvt()
2727
case *context.SendDeregistrationEvt:
2828
s.handleSendDeregistrationEvt()
29+
case *context.HandleDeregistrationReqUeTerminatedEvt:
30+
s.handleDeregistrationReqUeTerminated(t)
2931
}
3032
}
3133

@@ -151,3 +153,29 @@ func (s *Server) handleSendDeregistrationEvt() {
151153

152154
s.SendDeregistration()
153155
}
156+
157+
func (s *Server) handleDeregistrationReqUeTerminated(evt *context.HandleDeregistrationReqUeTerminatedEvt) {
158+
nwucpLog := logger.NWuCPLog
159+
nwucpLog.Tracef("Get Deregistration Request UE Terminated")
160+
161+
n3ueSelf := s.Context()
162+
nasMsg := evt.NasMsg
163+
deregistrationRequest := nasMsg.GmmMessage.DeregistrationRequestUETerminatedDeregistration
164+
if deregistrationRequest == nil {
165+
nwucpLog.Errorf("Deregistration Request UE Terminated is nil")
166+
return
167+
}
168+
169+
deregType := deregistrationRequest.SpareHalfOctetAndDeregistrationType
170+
deregistrationAccept := nasPacket.GetDeregistrationAccept()
171+
if deregType.GetReRegistrationRequired() == 1 {
172+
nwucpLog.Infof("handleDeregistrationReqUeTerminated(): Core network triggered re-registration required")
173+
n3ueSelf.ReRegistrationRequired = true
174+
}
175+
176+
// Send Deregistration Accept
177+
SendNasMsg(n3ueSelf.RanUeContext, n3ueSelf.N3IWFRanUe.TCPConnection, deregistrationAccept)
178+
179+
// Stop TCP connection
180+
s.StopTCPConnection()
181+
}

internal/nwucp/send.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ import (
1717

1818
func SendNasMsg(ue *security.RanUeContext, conn net.Conn, msg []byte) {
1919
nwucpLog := logger.NWuCPLog
20+
if conn == nil {
21+
nwucpLog.Errorf("TCP connection with N3IWF is nil")
22+
return
23+
}
24+
2025
pdu, err := ngapPacket.EncodeNasPduInEnvelopeWithSecurity(
2126
ue,
2227
msg,
@@ -67,7 +72,7 @@ func SendPduSessionEstablishmentRequest(ue *security.RanUeContext,
6772

6873
func (s *Server) SendDeregistration() {
6974
n3ueContext := s.Context()
70-
if n3ueContext.GUTI != nil && n3ueContext.N3IWFRanUe.TCPConnection != nil {
75+
if n3ueContext.GUTI != nil {
7176
mobileIdentity5GS := nasType.MobileIdentity5GS{
7277
Len: n3ueContext.GUTI.Len,
7378
Buffer: n3ueContext.GUTI.Octet[:],

internal/nwucp/service.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,19 @@ func (s *Server) Run(wg *sync.WaitGroup) {
5757

5858
func (s *Server) serveConn(errChan chan<- error) {
5959
nwucpLog := logger.NWuCPLog
60+
n3ueSelf := s.Context()
61+
ranUe := n3ueSelf.N3IWFRanUe
62+
6063
defer func() {
6164
if p := recover(); p != nil {
6265
// Print stack for panic to log. Fatalf() will let program exit.
6366
nwucpLog.Fatalf("panic: %v\n%s", p, string(debug.Stack()))
6467
}
6568
nwucpLog.Infof("NWUCP Connection closed")
6669
s.serverWg.Done()
70+
close(ranUe.TcpConnStopCh)
6771
}()
6872

69-
n3ueSelf := s.Context()
70-
7173
localTCPAddr := &net.TCPAddr{
7274
IP: n3ueSelf.UEInnerAddr.IP,
7375
}
@@ -76,7 +78,7 @@ func (s *Server) serveConn(errChan chan<- error) {
7678
errChan <- util.LogAndWrapError(err, nwucpLog, "TCP dial to N3IWF failed")
7779
return
7880
}
79-
n3ueSelf.N3IWFRanUe.TCPConnection = tcpConnWithN3IWF
81+
ranUe.TCPConnection = tcpConnWithN3IWF
8082

8183
close(errChan)
8284

@@ -89,6 +91,9 @@ func (s *Server) serveConn(errChan chan<- error) {
8991
nasEnv := make([]byte, 65535)
9092
for {
9193
select {
94+
case <-ranUe.TcpConnStopCh:
95+
nwucpLog.Infof("NWUCP Connection closed by TCP connection stop channel")
96+
return
9297
case <-s.serverCtx.Done():
9398
nwucpLog.Infof("NWUCP Connection closed by server context")
9499
return
@@ -125,6 +130,8 @@ func (s *Server) serveConn(errChan chan<- error) {
125130
evt = n3iwue_context.NewHandleRegistrationAcceptEvt(nasMsg)
126131
case nas.MsgTypeDLNASTransport:
127132
evt = n3iwue_context.NewHandleDLNASTransportEvt(nasMsg)
133+
case nas.MsgTypeDeregistrationRequestUETerminatedDeregistration:
134+
evt = n3iwue_context.NewHandleDeregistrationReqUeTerminatedEvt(nasMsg)
128135
default:
129136
nwucpLog.Warnf("Unknown NAS Message Type: %+v", nasMsg.GmmMessage.GetMessageType())
130137
continue
@@ -191,3 +198,13 @@ func (s *Server) Stop() {
191198

192199
nwucpLog.Info("NWUCP server shutdown complete")
193200
}
201+
202+
func (s *Server) StopTCPConnection() {
203+
n3ueSelf := s.Context()
204+
select {
205+
case n3ueSelf.N3IWFRanUe.TcpConnStopCh <- struct{}{}:
206+
// TCP connection stopped successfully
207+
default:
208+
logger.NWuCPLog.Warnf("TCP connection stop channel is not ready (may be full or closed), dropping stop signal")
209+
}
210+
}

internal/util/initContext.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ func InitN3UEContext() {
2121

2222
n3ueContext.N3ueInfo = factory.N3ueConfig.Configuration.N3UEInfo
2323
n3ueContext.N3iwfInfo = factory.N3ueConfig.Configuration.N3IWFInfo
24+
2425
n3ueContext.N3IWFRanUe = new(context.N3IWFRanUe)
26+
n3ueContext.N3IWFRanUe.TcpConnStopCh = make(chan struct{})
27+
2528
n3ueContext.N3IWFUe = new(context.N3IWFIkeUe)
2629
n3ueContext.N3IWFUe.N3IWFChildSecurityAssociation = make(map[uint32]*context.ChildSecurityAssociation)
2730
n3ueContext.N3IWFUe.TemporaryExchangeMsgIDChildSAMapping = make(map[uint32]*context.ChildSecurityAssociation)
@@ -51,6 +54,8 @@ func InitN3UEContext() {
5154
Buffer: suci,
5255
}
5356
n3ueContext.IKEConnection = make(map[int]*context.UDPSocketInfo)
57+
58+
n3ueContext.ReRegistrationRequired = false
5459
}
5560

5661
func getAuthSubscription() (authSubs models.AuthenticationSubscription) {

pkg/context/context.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ type N3UE struct {
6767

6868
// Continuous IKE_SA_INIT timer for reconnection
6969
ContinuousIkeSaInitTimer *time.Timer
70+
71+
ReRegistrationRequired bool
7072
}
7173

7274
func N3UESelf() *N3UE {
@@ -116,6 +118,7 @@ type N3IWFRanUe struct {
116118

117119
/* NAS TCP Connection */
118120
TCPConnection net.Conn
121+
TcpConnStopCh chan struct{}
119122

120123
/* Others */
121124
Guami *ngapType.GUAMI
@@ -280,49 +283,49 @@ func (ikeUe *N3IWFIkeUe) CompleteChildSA(msgID uint32, outboundSPI uint32,
280283
// ===== IKE Security Association Retransmit Methods =====
281284

282285
// Request retransmit methods (for N3UE's requests)
283-
func (ikeSA *IKESecurityAssociation) GetReqRetPrevReq() []byte {
286+
func (ikeSA *IKESecurityAssociation) GetReqRetransPrevReq() []byte {
284287
if ikeSA.ReqRetransmitInfo == nil {
285288
return nil
286289
}
287290
return ikeSA.ReqRetransmitInfo.PrevReq
288291
}
289292

290-
func (ikeSA *IKESecurityAssociation) GetReqRetTimer() *RetransmitTimer {
293+
func (ikeSA *IKESecurityAssociation) GetReqRetransTimer() *RetransmitTimer {
291294
if ikeSA.ReqRetransmitInfo == nil {
292295
return nil
293296
}
294297
return ikeSA.ReqRetransmitInfo.RetransmitTimer
295298
}
296299

297-
func (ikeSA *IKESecurityAssociation) GetReqRetUdpConnInfo() *UDPSocketInfo {
300+
func (ikeSA *IKESecurityAssociation) GetReqRetransUdpConnInfo() *UDPSocketInfo {
298301
if ikeSA.ReqRetransmitInfo == nil {
299302
return nil
300303
}
301304
return ikeSA.ReqRetransmitInfo.UdpConnInfo
302305
}
303306

304-
func (ikeSA *IKESecurityAssociation) StoreReqRetPrevReq(pkt []byte) {
307+
func (ikeSA *IKESecurityAssociation) StoreReqRetransPrevReq(pkt []byte) {
305308
if ikeSA.ReqRetransmitInfo == nil {
306309
ikeSA.ReqRetransmitInfo = &ReqRetransmitInfo{}
307310
}
308311
ikeSA.ReqRetransmitInfo.PrevReq = pkt
309312
}
310313

311-
func (ikeSA *IKESecurityAssociation) StoreReqRetUdpConnInfo(udpConnInfo *UDPSocketInfo) {
314+
func (ikeSA *IKESecurityAssociation) StoreReqRetransUdpConnInfo(udpConnInfo *UDPSocketInfo) {
312315
if ikeSA.ReqRetransmitInfo == nil {
313316
ikeSA.ReqRetransmitInfo = &ReqRetransmitInfo{}
314317
}
315318
ikeSA.ReqRetransmitInfo.UdpConnInfo = udpConnInfo
316319
}
317320

318-
func (ikeSA *IKESecurityAssociation) StoreReqRetTimer(timer *RetransmitTimer) {
321+
func (ikeSA *IKESecurityAssociation) StoreReqRetransTimer(timer *RetransmitTimer) {
319322
if ikeSA.ReqRetransmitInfo == nil {
320323
ikeSA.ReqRetransmitInfo = &ReqRetransmitInfo{}
321324
}
322325
ikeSA.ReqRetransmitInfo.RetransmitTimer = timer
323326
}
324327

325-
func (ikeSA *IKESecurityAssociation) StopReqRetTimer() {
328+
func (ikeSA *IKESecurityAssociation) StopReqRetransTimer() {
326329
if ikeSA.ReqRetransmitInfo == nil {
327330
return
328331
}
@@ -335,43 +338,43 @@ func (ikeSA *IKESecurityAssociation) StopReqRetTimer() {
335338
}
336339

337340
// Response retransmit methods (for responses to peer's requests)
338-
func (ikeSA *IKESecurityAssociation) GetRspRetPrevReqHash() [sha1.Size]byte {
341+
func (ikeSA *IKESecurityAssociation) GetRspRetransPrevReqHash() [sha1.Size]byte {
339342
if ikeSA.RspRetransmitInfo == nil {
340343
return [sha1.Size]byte{}
341344
}
342345
return ikeSA.RspRetransmitInfo.PrevReqHash
343346
}
344347

345-
func (ikeSA *IKESecurityAssociation) GetRspRetPrevRsp() []byte {
348+
func (ikeSA *IKESecurityAssociation) GetRspRetransPrevRsp() []byte {
346349
if ikeSA.RspRetransmitInfo == nil {
347350
return nil
348351
}
349352

350353
return ikeSA.RspRetransmitInfo.PrevRsp
351354
}
352355

353-
func (ikeSA *IKESecurityAssociation) GetRspRetUdpConnInfo() *UDPSocketInfo {
356+
func (ikeSA *IKESecurityAssociation) GetRspRetransUdpConnInfo() *UDPSocketInfo {
354357
if ikeSA.RspRetransmitInfo == nil {
355358
return nil
356359
}
357360
return ikeSA.RspRetransmitInfo.UdpConnInfo
358361
}
359362

360-
func (ikeSA *IKESecurityAssociation) StoreRspRetPrevRsp(pkt []byte) {
363+
func (ikeSA *IKESecurityAssociation) StoreRspRetransPrevRsp(pkt []byte) {
361364
if ikeSA.RspRetransmitInfo == nil {
362365
ikeSA.RspRetransmitInfo = &RspRetransmitInfo{}
363366
}
364367
ikeSA.RspRetransmitInfo.PrevRsp = pkt
365368
}
366369

367-
func (ikeSA *IKESecurityAssociation) StoreRspRetUdpConnInfo(udpConnInfo *UDPSocketInfo) {
370+
func (ikeSA *IKESecurityAssociation) StoreRspRetransUdpConnInfo(udpConnInfo *UDPSocketInfo) {
368371
if ikeSA.RspRetransmitInfo == nil {
369372
ikeSA.RspRetransmitInfo = &RspRetransmitInfo{}
370373
}
371374
ikeSA.RspRetransmitInfo.UdpConnInfo = udpConnInfo
372375
}
373376

374-
func (ikeSA *IKESecurityAssociation) StoreRspRetPrevReqHash(pkt []byte) {
377+
func (ikeSA *IKESecurityAssociation) StoreRspRetransPrevReqHash(pkt []byte) {
375378
if ikeSA.RspRetransmitInfo == nil {
376379
ikeSA.RspRetransmitInfo = &RspRetransmitInfo{}
377380
}

pkg/context/ike_event.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ const (
2222

2323
// For DPD event
2424
DpdCheck
25+
26+
// For re-connection event
27+
IkeReConnect
2528
)
2629

2730
var ikeEvtTypeStr = []string{
@@ -39,6 +42,9 @@ var ikeEvtTypeStr = []string{
3942

4043
// For DPD event
4144
DpdCheck: "DpdCheck",
45+
46+
// For re-connection event
47+
IkeReConnect: "IkeReConnect",
4248
}
4349

4450
func (e IkeEventType) String() string {
@@ -177,3 +183,15 @@ func (evt *DpdCheckEvt) Type() IkeEventType {
177183
func NewDpdCheckEvt() *DpdCheckEvt {
178184
return &DpdCheckEvt{}
179185
}
186+
187+
// For connection failure event
188+
189+
type IkeReConnectEvt struct{}
190+
191+
func (evt *IkeReConnectEvt) Type() IkeEventType {
192+
return IkeReConnect
193+
}
194+
195+
func NewIkeReConnectEvt() *IkeReConnectEvt {
196+
return &IkeReConnectEvt{}
197+
}

pkg/context/nwucp_event.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@ const (
1818
HandleDLNASTransport
1919
StartPduSessionEstablishment
2020
SendDeregistration
21+
HandleDeregistrationReqUeTerminated
2122
)
2223

2324
var nwucpEvtTypeStr = []string{
24-
StartNwucpConn: "StartNwucpConn",
25-
HandleRegistrationAccept: "HandleRegistrationAccept",
26-
HandleDLNASTransport: "HandleDLNASTransport",
27-
StartPduSessionEstablishment: "StartPduSessionEstablishment",
28-
SendDeregistration: "SendDeregistration",
25+
StartNwucpConn: "StartNwucpConn",
26+
HandleRegistrationAccept: "HandleRegistrationAccept",
27+
HandleDLNASTransport: "HandleDLNASTransport",
28+
StartPduSessionEstablishment: "StartPduSessionEstablishment",
29+
SendDeregistration: "SendDeregistration",
30+
HandleDeregistrationReqUeTerminated: "HandleDeregistrationReqUeTerminated",
2931
}
3032

3133
func (e NwucpEvtType) String() string {
@@ -88,3 +90,15 @@ func (evt *SendDeregistrationEvt) GetEventType() NwucpEvtType {
8890
func NewSendDeregistrationEvt() *SendDeregistrationEvt {
8991
return &SendDeregistrationEvt{}
9092
}
93+
94+
type HandleDeregistrationReqUeTerminatedEvt struct {
95+
NasMsg *nas.Message
96+
}
97+
98+
func (evt *HandleDeregistrationReqUeTerminatedEvt) GetEventType() NwucpEvtType {
99+
return HandleDeregistrationReqUeTerminated
100+
}
101+
102+
func NewHandleDeregistrationReqUeTerminatedEvt(nasMsg *nas.Message) *HandleDeregistrationReqUeTerminatedEvt {
103+
return &HandleDeregistrationReqUeTerminatedEvt{NasMsg: nasMsg}
104+
}

pkg/factory/config.go

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,21 +120,22 @@ type N3IWFInfo struct {
120120
}
121121

122122
type N3UEInfo struct {
123-
IMSI IMSI `yaml:"IMSI" valid:"required"`
124-
AMFID string `yaml:"AMFID" valid:"hexadecimal,required"`
125-
IPSecIfaceName string `yaml:"IPSecIfaceName" valid:"stringlength(1|10),required"`
126-
IPSecIfaceAddr string `yaml:"IPSecIfaceAddr" valid:"host,required"`
127-
DnIPAddr string `yaml:"DnIPAddr" valid:"host,optional"`
128-
XfrmiId uint32 `yaml:"XfrmiId" valid:"numeric,required"`
129-
XfrmiName string `yaml:"XfrmiName" valid:"stringlength(1|10),required"`
130-
GreIfaceName string `yaml:"GreIfaceName" valid:"stringlength(1|10),required"`
131-
IkeSaSPI uint64 `yaml:"IkeSaSPI" valid:"hexadecimal,required"`
132-
IPSecSaCpSPI uint32 `yaml:"IPSecSA3gppControlPlaneSPI" valid:"hexadecimal,required"`
133-
SmPolicy []PolicyItem `yaml:"SmPolicy" valid:"required"`
134-
Security Security `yaml:"Security" valid:"required"`
135-
VisitedPlmn *PLMN `yaml:"VisitedPLMN" valid:"optional"`
136-
DpdInterval time.Duration `yaml:"DpdInterval" valid:"optional"`
137-
IkeRetransmit *ExponentialTimerValue `yaml:"IkeRetransmit" valid:"required"`
123+
IMSI IMSI `yaml:"IMSI" valid:"required"`
124+
AMFID string `yaml:"AMFID" valid:"hexadecimal,required"`
125+
IPSecIfaceName string `yaml:"IPSecIfaceName" valid:"stringlength(1|10),required"`
126+
IPSecIfaceAddr string `yaml:"IPSecIfaceAddr" valid:"host,required"`
127+
DnIPAddr string `yaml:"DnIPAddr" valid:"host,optional"`
128+
XfrmiId uint32 `yaml:"XfrmiId" valid:"numeric,required"`
129+
XfrmiName string `yaml:"XfrmiName" valid:"stringlength(1|10),required"`
130+
GreIfaceName string `yaml:"GreIfaceName" valid:"stringlength(1|10),required"`
131+
IkeSaSPI uint64 `yaml:"IkeSaSPI" valid:"hexadecimal,required"`
132+
IPSecSaCpSPI uint32 `yaml:"IPSecSA3gppControlPlaneSPI" valid:"hexadecimal,required"`
133+
SmPolicy []PolicyItem `yaml:"SmPolicy" valid:"required"`
134+
Security Security `yaml:"Security" valid:"required"`
135+
VisitedPlmn *PLMN `yaml:"VisitedPLMN" valid:"optional"`
136+
DpdInterval time.Duration `yaml:"DpdInterval" valid:"optional"`
137+
IkeRetransmit *ExponentialTimerValue `yaml:"IkeRetransmit" valid:"required"`
138+
AutoReRegistration bool `yaml:"AutoReRegistration" valid:"optional"`
138139
}
139140

140141
func (i *N3UEInfo) validate() (bool, error) {

0 commit comments

Comments
 (0)