Skip to content

Commit 355aad2

Browse files
authored
Merge pull request #156 from Alonza0314/feat/nr-dc
feat/nr dc
2 parents 95a0bb8 + 1b7e375 commit 355aad2

8 files changed

Lines changed: 818 additions & 7 deletions

File tree

internal/context/datapath.go

Lines changed: 428 additions & 0 deletions
Large diffs are not rendered by default.

internal/context/ngap_build.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ func BuildPDUSessionResourceSetupRequestTransfer(ctx *SMContext) ([]byte, error)
1616
ANUPF := ctx.Tunnel.DataPathPool.GetDefaultPath().FirstDPNode
1717
UpNode := ANUPF.UPF
1818
teidOct := make([]byte, 4)
19+
teidOctForSplitPDUSession := make([]byte, 4)
1920
binary.BigEndian.PutUint32(teidOct, ctx.LocalULTeid)
21+
binary.BigEndian.PutUint32(teidOctForSplitPDUSession, ctx.LocalULTeidForSplitPDUSession)
2022

2123
resourceSetupRequestTransfer := ngapType.PDUSessionResourceSetupRequestTransfer{}
2224

@@ -69,6 +71,37 @@ func BuildPDUSessionResourceSetupRequestTransfer(ctx *SMContext) ([]byte, error)
6971

7072
resourceSetupRequestTransfer.ProtocolIEs.List = append(resourceSetupRequestTransfer.ProtocolIEs.List, ie)
7173

74+
// Additional UL NG-U UP TNL Information
75+
ie = ngapType.PDUSessionResourceSetupRequestTransferIEs{}
76+
ie.Id.Value = ngapType.ProtocolIEIDAdditionalULNGUUPTNLInformation
77+
ie.Criticality.Value = ngapType.CriticalityPresentIgnore
78+
if n3IP, err := UpNode.N3Interfaces[0].IP(ctx.SelectedPDUSessionType); err != nil {
79+
return nil, err
80+
} else {
81+
ie.Value = ngapType.PDUSessionResourceSetupRequestTransferIEsValue{
82+
Present: ngapType.PDUSessionResourceSetupRequestTransferIEsPresentAdditionalULNGUUPTNLInformation,
83+
AdditionalULNGUUPTNLInformation: &ngapType.UPTransportLayerInformationList{
84+
List: []ngapType.UPTransportLayerInformationItem{
85+
{
86+
NGUUPTNLInformation: ngapType.UPTransportLayerInformation{
87+
Present: ngapType.UPTransportLayerInformationPresentGTPTunnel,
88+
GTPTunnel: &ngapType.GTPTunnel{
89+
TransportLayerAddress: ngapType.TransportLayerAddress{
90+
Value: aper.BitString{
91+
Bytes: n3IP,
92+
BitLength: uint64(len(n3IP) * 8),
93+
},
94+
},
95+
GTPTEID: ngapType.GTPTEID{Value: teidOctForSplitPDUSession},
96+
},
97+
},
98+
},
99+
},
100+
},
101+
}
102+
}
103+
resourceSetupRequestTransfer.ProtocolIEs.List = append(resourceSetupRequestTransfer.ProtocolIEs.List, ie)
104+
72105
// PDU Session Type
73106
ie = ngapType.PDUSessionResourceSetupRequestTransferIEs{}
74107
ie.Id.Value = ngapType.ProtocolIEIDPDUSessionType

internal/context/ngap_handler.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,38 @@ func HandlePDUSessionResourceSetupResponseTransfer(b []byte, ctx *SMContext) err
4949
}
5050

5151
QosFlowPerTNLInformation := resourceSetupResponseTransfer.DLQosFlowPerTNLInformation
52+
var DCQosFlowPerTNLInformationItem ngapType.QosFlowPerTNLInformationItem
53+
DCQosFlowPerTNLInformation := resourceSetupResponseTransfer.AdditionalDLQosFlowPerTNLInformation
54+
if DCQosFlowPerTNLInformation != nil && len(DCQosFlowPerTNLInformation.List) > 0 {
55+
ctx.NrdcIndicator = true
56+
DCQosFlowPerTNLInformationItem = DCQosFlowPerTNLInformation.List[0]
57+
}
5258

5359
if QosFlowPerTNLInformation.UPTransportLayerInformation.Present !=
5460
ngapType.UPTransportLayerInformationPresentGTPTunnel {
5561
return errors.New("resourceSetupResponseTransfer.QosFlowPerTNLInformation.UPTransportLayerInformation.Present")
5662
}
63+
if ctx.NrdcIndicator && DCQosFlowPerTNLInformationItem.QosFlowPerTNLInformation.UPTransportLayerInformation.Present !=
64+
ngapType.UPTransportLayerInformationPresentGTPTunnel {
65+
return errors.New(
66+
"resourceSetupResponseTransfer.AdditionalQosFlowPerTNLInformation." +
67+
"QosFlowPerTNLInformation.UPTransportLayerInformation.Present")
68+
}
5769

5870
GTPTunnel := QosFlowPerTNLInformation.UPTransportLayerInformation.GTPTunnel
71+
DCGTPTunnel := &ngapType.GTPTunnel{}
72+
if ctx.NrdcIndicator {
73+
DCGTPTunnel = DCQosFlowPerTNLInformationItem.QosFlowPerTNLInformation.UPTransportLayerInformation.GTPTunnel
74+
}
5975

6076
ctx.Tunnel.UpdateANInformation(
6177
GTPTunnel.TransportLayerAddress.Value.Bytes,
6278
binary.BigEndian.Uint32(GTPTunnel.GTPTEID.Value))
79+
if ctx.NrdcIndicator {
80+
ctx.DCTunnel.UpdateANInformation(
81+
DCGTPTunnel.TransportLayerAddress.Value.Bytes,
82+
binary.BigEndian.Uint32(DCGTPTunnel.GTPTEID.Value))
83+
}
6384

6485
ctx.UpCnxState = models.UpCnxState_ACTIVATED
6586
for _, qos := range ctx.AdditonalQosFlows {

internal/context/pcc_rule.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,37 @@ func (r *PCCRule) AddDataPathForwardingParameters(c *SMContext,
129129
}
130130
}
131131

132+
func (r *PCCRule) AddDataPathForwardingParametersOnDcTunnel(c *SMContext,
133+
tgtRoute *models.RouteToLocation,
134+
) {
135+
if tgtRoute == nil {
136+
return
137+
}
138+
139+
if r.Datapath == nil {
140+
logger.CtxLog.Warnf("AddDataPathForwardingParametersOnDcTunnel pcc[%s]: no data path", r.PccRuleId)
141+
return
142+
}
143+
144+
var routeProf factory.RouteProfile
145+
routeProfExist := false
146+
// specify N6 routing information
147+
if tgtRoute.RouteProfId != "" {
148+
routeProf, routeProfExist = factory.UERoutingConfig.RouteProf[factory.RouteProfID(tgtRoute.RouteProfId)]
149+
if !routeProfExist {
150+
logger.CtxLog.Warnf("Route Profile ID [%s] is not support on DCTunnel", tgtRoute.RouteProfId)
151+
return
152+
}
153+
}
154+
155+
if c.DCTunnel.DataPathPool.GetDefaultPath() == nil {
156+
logger.CtxLog.Infoln("No Default Data Path")
157+
} else {
158+
r.Datapath.AddForwardingParameters(routeProf.ForwardingPolicyID,
159+
c.DCTunnel.DataPathPool.GetDefaultPath().FirstDPNode.GetUpLinkPDR().PDI.LocalFTeid.Teid)
160+
}
161+
}
162+
132163
func (r *PCCRule) BuildNasQoSRule(smCtx *SMContext,
133164
opCode nasType.QoSRuleOperationCode,
134165
) (*nasType.QoSRule, error) {

internal/context/sm_context.go

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,11 @@ type SMContext struct {
123123
Identifier string
124124
PDUSessionID int32
125125

126-
LocalULTeid uint32
127-
LocalDLTeid uint32
126+
LocalULTeid uint32
127+
LocalDLTeid uint32
128+
LocalULTeidForSplitPDUSession uint32
129+
LocalDLTeidForSplitPDUSession uint32
130+
NrdcIndicator bool
128131

129132
UpCnxState models.UpCnxState
130133

@@ -160,6 +163,7 @@ type SMContext struct {
160163
SmStatusNotifyUri string
161164

162165
Tunnel *UPTunnel
166+
DCTunnel *UPTunnel
163167
SelectedUPF *UPNode
164168
BPManager *BPManager
165169
// NodeID(string form) to PFCP Session Context
@@ -170,6 +174,7 @@ type SMContext struct {
170174

171175
// SM Policy related
172176
PCCRules map[string]*PCCRule
177+
DCPCCRules map[string]*PCCRule
173178
SessionRules map[string]*SessionRule
174179
TrafficControlDatas map[string]*TrafficControlData
175180
ChargingData map[string]*models.ChargingData
@@ -287,6 +292,7 @@ func NewSMContext(id string, pduSessID int32) *SMContext {
287292

288293
// initialize SM Policy Data
289294
smContext.PCCRules = make(map[string]*PCCRule)
295+
smContext.DCPCCRules = make(map[string]*PCCRule)
290296
smContext.SessionRules = make(map[string]*SessionRule)
291297
smContext.TrafficControlDatas = make(map[string]*TrafficControlData)
292298
smContext.QosDatas = make(map[string]*models.QosData)
@@ -298,6 +304,7 @@ func NewSMContext(id string, pduSessID int32) *SMContext {
298304

299305
smContext.BPManager = NewBPManager(id)
300306
smContext.Tunnel = NewUPTunnel()
307+
smContext.DCTunnel = NewUPTunnel()
301308

302309
smContext.QoSRuleIDGenerator = idgenerator.NewGenerator(1, 255)
303310
if defRuleID, err := smContext.QoSRuleIDGenerator.Allocate(); err != nil {
@@ -346,6 +353,18 @@ func NewSMContext(id string, pduSessID int32) *SMContext {
346353
return nil
347354
}
348355

356+
smContext.LocalULTeidForSplitPDUSession, err = GenerateTEID()
357+
if err != nil {
358+
return nil
359+
}
360+
361+
smContext.LocalDLTeidForSplitPDUSession, err = GenerateTEID()
362+
if err != nil {
363+
return nil
364+
}
365+
366+
smContext.NrdcIndicator = false
367+
349368
return smContext
350369
}
351370

@@ -393,6 +412,10 @@ func RemoveSMContext(ref string) {
393412

394413
ReleaseTEID(smContext.LocalULTeid)
395414
ReleaseTEID(smContext.LocalDLTeid)
415+
ReleaseTEID(smContext.LocalULTeidForSplitPDUSession)
416+
ReleaseTEID(smContext.LocalDLTeidForSplitPDUSession)
417+
418+
smContext.NrdcIndicator = false
396419

397420
smContextPool.Delete(ref)
398421
canonicalRef.Delete(canonicalName(smContext.Supi, smContext.PDUSessionID))
@@ -685,6 +708,55 @@ func (c *SMContext) CreatePccRuleDataPath(pccRule *PCCRule,
685708
return nil
686709
}
687710

711+
func (c *SMContext) CreateDcPccRuleDataPathOnDcTunnel(pccRule *PCCRule,
712+
tcData *TrafficControlData, qosData *models.QosData,
713+
chgData *models.ChargingData,
714+
) error {
715+
var targetRoute models.RouteToLocation
716+
if tcData != nil && len(tcData.RouteToLocs) > 0 {
717+
targetRoute = *tcData.RouteToLocs[0]
718+
}
719+
param := &UPFSelectionParams{
720+
Dnn: c.Dnn,
721+
SNssai: &SNssai{
722+
Sst: c.SNssai.Sst,
723+
Sd: c.SNssai.Sd,
724+
},
725+
Dnai: targetRoute.Dnai,
726+
}
727+
createdUpPath := GetUserPlaneInformation().GetDefaultUserPlanePathByDNN(param)
728+
createdDataPath := GenerateDataPath(createdUpPath)
729+
if createdDataPath == nil {
730+
return fmt.Errorf("fail to create data path on DCTunnel for pcc rule[%s]", pccRule.PccRuleId)
731+
}
732+
c.Log.Infof("CreatePccRuleDataPathOnDctunnel: pcc rule: %+v", pccRule)
733+
734+
// Try to use a default pcc rule as default data path
735+
if c.DCTunnel.DataPathPool.GetDefaultPath() == nil &&
736+
pccRule.Precedence == 255 {
737+
createdDataPath.IsDefaultPath = true
738+
}
739+
740+
createdDataPath.GBRFlow = isGBRFlow(qosData)
741+
createdDataPath.ActivateDcTunnelAndPDR(c, uint32(pccRule.Precedence))
742+
c.DCTunnel.AddDataPath(createdDataPath)
743+
pccRule.Datapath = createdDataPath
744+
pccRule.AddDataPathForwardingParametersOnDcTunnel(c, &targetRoute)
745+
746+
if chgLevel, err := pccRule.IdentifyChargingLevel(); err != nil {
747+
c.Log.Warnf("fail to identify charging level[%+v] for pcc rule[%s]", err, pccRule.PccRuleId)
748+
} else {
749+
pccRule.Datapath.AddChargingRules(c, chgLevel, chgData)
750+
}
751+
752+
if pccRule.RefQosDataID() != "" {
753+
pccRule.Datapath.AddQoS(c, pccRule.QFI, qosData)
754+
c.AddQosFlow(pccRule.QFI, qosData)
755+
}
756+
757+
return nil
758+
}
759+
688760
func (c *SMContext) BuildUpPathChgEventExposureNotification(
689761
chgEvent *models.UpPathChgEvent,
690762
srcRoute, tgtRoute *models.RouteToLocation,

internal/context/sm_context_policy.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,129 @@ func (c *SMContext) ApplyPccRules(
250250
return nil
251251
}
252252

253+
func (c *SMContext) ApplyDcPccRulesOnDcTunnel() error {
254+
if c.DCTunnel == nil {
255+
c.Log.Errorf("DCTunnel is nil")
256+
return fmt.Errorf("DCTunnel is nil")
257+
}
258+
259+
for id, pcc := range c.PCCRules {
260+
if pcc == nil {
261+
continue
262+
}
263+
264+
newPcc := &PCCRule{
265+
PccRule: &models.PccRule{
266+
FlowInfos: make([]models.FlowInformation, len(pcc.FlowInfos)),
267+
AppId: pcc.AppId,
268+
AppDescriptor: pcc.AppDescriptor,
269+
ContVer: pcc.ContVer,
270+
PccRuleId: pcc.PccRuleId,
271+
Precedence: pcc.Precedence,
272+
AfSigProtocol: pcc.AfSigProtocol,
273+
AppReloc: pcc.AppReloc,
274+
EasRedisInd: pcc.EasRedisInd,
275+
RefQosData: make([]string, len(pcc.RefQosData)),
276+
RefTcData: make([]string, len(pcc.RefTcData)),
277+
RefChgData: make([]string, len(pcc.RefChgData)),
278+
RefChgN3gData: make([]string, len(pcc.RefChgN3gData)),
279+
RefUmData: make([]string, len(pcc.RefUmData)),
280+
RefUmN3gData: make([]string, len(pcc.RefUmN3gData)),
281+
RefCondData: pcc.RefCondData,
282+
RefQosMon: make([]string, len(pcc.RefQosMon)),
283+
AddrPreserInd: pcc.AddrPreserInd,
284+
TscaiTimeDom: pcc.TscaiTimeDom,
285+
DisUeNotif: pcc.DisUeNotif,
286+
PackFiltAllPrec: pcc.PackFiltAllPrec,
287+
RefAltQosParams: make([]string, len(pcc.RefAltQosParams)),
288+
},
289+
QFI: pcc.QFI,
290+
Datapath: nil,
291+
}
292+
293+
if pcc.TscaiInputDl != nil {
294+
newPcc.TscaiInputDl = &models.TscaiInputContainer{
295+
Periodicity: pcc.TscaiInputDl.Periodicity,
296+
BurstArrivalTime: pcc.TscaiInputDl.BurstArrivalTime,
297+
SurTimeInNumMsg: pcc.TscaiInputDl.SurTimeInNumMsg,
298+
SurTimeInTime: pcc.TscaiInputDl.SurTimeInTime,
299+
}
300+
}
301+
if pcc.TscaiInputUl != nil {
302+
newPcc.TscaiInputUl = &models.TscaiInputContainer{
303+
Periodicity: pcc.TscaiInputUl.Periodicity,
304+
BurstArrivalTime: pcc.TscaiInputUl.BurstArrivalTime,
305+
SurTimeInNumMsg: pcc.TscaiInputUl.SurTimeInNumMsg,
306+
SurTimeInTime: pcc.TscaiInputUl.SurTimeInTime,
307+
}
308+
}
309+
copy(newPcc.FlowInfos, pcc.FlowInfos)
310+
copy(newPcc.RefQosData, pcc.RefQosData)
311+
copy(newPcc.RefTcData, pcc.RefTcData)
312+
copy(newPcc.RefChgData, pcc.RefChgData)
313+
copy(newPcc.RefChgN3gData, pcc.RefChgN3gData)
314+
copy(newPcc.RefUmData, pcc.RefUmData)
315+
copy(newPcc.RefUmN3gData, pcc.RefUmN3gData)
316+
copy(newPcc.RefQosMon, pcc.RefQosMon)
317+
copy(newPcc.RefAltQosParams, pcc.RefAltQosParams)
318+
319+
if pcc.DdNotifCtrl != nil {
320+
newPcc.DdNotifCtrl = &models.DownlinkDataNotificationControl{
321+
NotifCtrlInds: make([]models.NotificationControlIndication, len(pcc.DdNotifCtrl.NotifCtrlInds)),
322+
TypesOfNotif: make([]models.DlDataDeliveryStatus, len(pcc.DdNotifCtrl.TypesOfNotif)),
323+
}
324+
copy(newPcc.DdNotifCtrl.NotifCtrlInds, pcc.DdNotifCtrl.NotifCtrlInds)
325+
copy(newPcc.DdNotifCtrl.TypesOfNotif, pcc.DdNotifCtrl.TypesOfNotif)
326+
}
327+
if pcc.DdNotifCtrl2 != nil {
328+
newPcc.DdNotifCtrl2 = &models.DownlinkDataNotificationControlRm{
329+
NotifCtrlInds: make([]models.NotificationControlIndication, len(pcc.DdNotifCtrl2.NotifCtrlInds)),
330+
TypesOfNotif: make([]models.DlDataDeliveryStatus, len(pcc.DdNotifCtrl2.TypesOfNotif)),
331+
}
332+
copy(newPcc.DdNotifCtrl2.NotifCtrlInds, pcc.DdNotifCtrl2.NotifCtrlInds)
333+
copy(newPcc.DdNotifCtrl2.TypesOfNotif, pcc.DdNotifCtrl2.TypesOfNotif)
334+
}
335+
336+
c.DCPCCRules[id] = newPcc
337+
}
338+
339+
for id, pcc := range c.DCPCCRules {
340+
if pcc == nil {
341+
c.Log.Warnf("PCCRule[%s] is nil", id)
342+
continue
343+
}
344+
345+
tcID := pcc.RefTcDataID()
346+
tcData := c.TrafficControlDatas[tcID]
347+
348+
chgID := pcc.RefChgDataID()
349+
chgData := c.ChargingData[chgID]
350+
351+
qosID := pcc.RefQosDataID()
352+
qosData := c.QosDatas[qosID]
353+
354+
if pcc.Datapath != nil {
355+
c.PreRemoveDataPath(pcc.Datapath)
356+
}
357+
358+
if err := c.CreateDcPccRuleDataPathOnDcTunnel(pcc, tcData, qosData, chgData); err != nil {
359+
c.Log.Errorf("CreatePccRuleDataPathOnDcTunnel for PCCRule[%s] failed: %v", id, err)
360+
continue
361+
}
362+
363+
if err := applyFlowInfoOrPFD(pcc); err != nil {
364+
c.Log.Errorf("applyFlowInfoOrPFD for PCCRule[%s] failed: %v", id, err)
365+
continue
366+
}
367+
368+
c.Log.Infof("Applied PCCRule[%s] to DCTunnel", id)
369+
}
370+
371+
c.addPduLevelChargingRuleToFlow(c.DCPCCRules)
372+
373+
return nil
374+
}
375+
253376
func (c *SMContext) getSrcTgtTcData(
254377
decisionTcDecs map[string]*models.TrafficControlData,
255378
tcID string,

0 commit comments

Comments
 (0)