:::spoiler Jump through topic
> # Modify the packet parameters with “Security Mode Command”
>
> # Modify the packet parameters with “Initial Context Setup Request”
:::
:::spoiler Original log from core




:::
# 1. Modify the packet parameters with “Authentication request”
## After modification in 
### Make problem : imported not use

:::success
* Detached this two module.

* Then compile again and it's successful.
* Then run core, gnb and UE again.
:::
### Core error
1. 

2. Make(compiler) problem(Need to add one more parameter to the function)
(Screenshot gone)


:::success
**Solution**
* Modification in 
:::
## After modification in 

:::success
**Solution**

:::
### UE error

:::success
* It is related to CN, after CN errors are fixed, it can access the network.
:::
# 2. Remove “AUSF”
## File editting to ignore this NF
```
nano /home/ubuntu/free5gc/run.sh
nano /home/ubuntu/free5gc/Makefile
```
* run.sh

* Makefile

* **Then complile it again, we can see the error messages on 5gc log, it is a important clue to find where to modify in source code.**


## After modification in 
* Need to detached the including function.

:::success
**Solution**

:::
:::danger
**Problem**

* It looks the same as I met in lll testing process.
* And it it not related to MongoDB because in lll testing I thought that the error message included the mongodb part, but it only related to UPF problem.
:::success
**Solution**
* forcekill and make agaiin and again, then it runs successfully.
:::
## After compiling
### Core (From NG setup)

* We can search the error message in VScode, and find it is in send.go
### UE (Past screenshot)

## After modification in 
* **Test successfully, see the testing result.**
# 3. Remove "NSSF"
## File editting
* Makefile

* run.sh

### Record the log before accessing UE
* We can see if there is defference between this and the orignal clean 5GC.




* The NSSF part in original log disappear, see below is the original one.

## The error messages after ignore NSSF
### AMF can't select NSSF
:::spoiler Past note




:::success
:::
#### Core side



* Repeat that **AMF can not select an NSSF Instance by NRF[Error: AMF can not select an NSSF by NRF]**
#### UE side

* After a while, it keep trying retransmitting PDU session establishment request, and when it attempts 5 time it will abort the SM procedure.
### Error fixing process
:::warning
1. Use **ctrl+shift+F** to find the keyword in the whole folder, here we can see there are two places which may print out this error messages.

2. In this line , we can see it is printed from GMM(GPRS Mobility Management, [LINK1](https://www.mpirical.com/glossary/gmm-gprs-mobility-management), [LINK2](https://blog.csdn.net/hitguolu/article/details/109215507)), so first we modify the handler.go which is in the GMM folder.
```go=
if needSliceSelection {
if ue.NssfUri == "" {
for {
err := consumer.SearchNssfNSSelectionInstance(ue, amfSelf.NrfUri, models.NfType_NSSF, models.NfType_AMF, nil)
if err != nil {
//ue.GmmLog.Errorf("AMF can not select an NSSF Instance by NRF[Error: %+v]", err)
//time.Sleep(2 * time.Second)
} else {
break
}
}
}
```
* After modifying and compiling, the error message is still the same, so we should modify the **sm_context.go**.
3. If I directly ignore the error printing and time sleep lines, the error message is gone, but it will enter a infinite loop to look for NSSF.

4. Then I add some messages printed to see the log sequence running in the code, and try to break the for loop after TEST04.
* 
```go=
func SelectSmf(
ue *amf_context.AmfUe,
anType models.AccessType,
pduSessionID int32,
snssai models.Snssai,
dnn string,
) (*amf_context.SmContext, uint8, error) {
var (
smfID string
smfUri string
)
ue.GmmLog.Infof("Select SMF [snssai: %+v, dnn: %+v]", snssai, dnn)
nrfUri := ue.ServingAMF().NrfUri // default NRF URI is pre-configured by AMF
ue.GmmLog.Errorf("/////////////////TEST01////////////////")
nsiInformation := ue.GetNsiInformationFromSnssai(anType, snssai)
ue.GmmLog.Errorf("/////////////////TEST02////////////////")
if nsiInformation == nil {
if ue.NssfUri == "" {
// TODO: Set a timeout of NSSF Selection or will starvation here
for {
ue.GmmLog.Errorf("/////////////////TEST03////////////////")
if err := SearchNssfNSSelectionInstance(ue, nrfUri, models.NfType_NSSF,
models.NfType_AMF, nil); err != nil {
ue.GmmLog.Errorf("/////////////////TEST04////////////////")
//ue.GmmLog.Errorf("AMF can not select an NSSF Instance by NRF[Error: %+v]", err)
//time.Sleep(2 * time.Second)
break
} else {
break
}
}
}
response, problemDetails, err := NSSelectionGetForPduSession(ue, snssai)
if err != nil {
err = fmt.Errorf("NSSelection Get Error[%+v]", err)
return nil, nasMessage.Cause5GMMPayloadWasNotForwarded, err
} else if problemDetails != nil {
err = fmt.Errorf("NSSelection Get Failed Problem[%+v]", problemDetails)
return nil, nasMessage.Cause5GMMPayloadWasNotForwarded, err
}
nsiInformation = response.NsiInformation
}
.
.
.
```
* 
```go=
func SendSearchNFInstances(nrfUri string, targetNfType, requestNfType models.NfType,
param *Nnrf_NFDiscovery.SearchNFInstancesParamOpts,
) (models.SearchResult, error) {
// Set client and set url
fmt.Println("////TEST A////")
configuration := Nnrf_NFDiscovery.NewConfiguration()
fmt.Println("////TEST B////")
configuration.SetBasePath(nrfUri)
client := Nnrf_NFDiscovery.NewAPIClient(configuration)
fmt.Println("////TEST C////")
result, res, err := client.NFInstancesStoreApi.SearchNFInstances(context.TODO(), targetNfType, requestNfType, param)
// 從這行印出 Handle NFDiscoveryRequest 和 200 GET,然後就到下面return回去了。
fmt.Println("////TEST D////")
if res != nil && res.StatusCode == http.StatusTemporaryRedirect {
err = fmt.Errorf("Temporary Redirect For Non NRF Consumer")
}
if res == nil || res.Body == nil {
return result, err
}
defer func() {
if res != nil {
if bodyCloseErr := res.Body.Close(); bodyCloseErr != nil {
err = fmt.Errorf("SearchNFInstances' response body cannot close: %+w", bodyCloseErr)
}
}
}()
return result, err
}
```
5. The result is like below.

* Although it breaks successfully, it gets in another error which go back to resend DL NAS Transport.
* Then enters another infinite loop which still want to find SMF based on snssai.
:::
### Select SMD failed: NSSelection Get Error[NSSF No Response]
* From 5.
### Error fixing process
:::warning
* Originally I thought that the error message is from here, where is below the ignored two lines.

* But when searching the prefix of this line, it actually starts from **func CreatePDUSession** in 
```go=
func CreatePDUSession(ulNasTransport *nasMessage.ULNASTransport,
ue *context.AmfUe,
anType models.AccessType,
pduSessionID int32,
smMessage []uint8,
) (setNewSmContext bool, err error) {
var (
snssai models.Snssai
dnn string
)
// A) AMF shall select an SMF
// If the S-NSSAI IE is not included and the user's subscription context obtained from UDM. AMF shall
// select a default snssai
if ulNasTransport.SNSSAI != nil {
snssai = nasConvert.SnssaiToModels(ulNasTransport.SNSSAI)
} else {
if allowedNssai, ok := ue.AllowedNssai[anType]; ok {
snssai = *allowedNssai[0].AllowedSnssai
} else {
return false, errors.New("Ue doesn't have allowedNssai")
}
}
if ulNasTransport.DNN != nil {
dnn = ulNasTransport.DNN.GetDNN()
} else {
// if user's subscription context obtained from UDM does not contain the default DNN for the,
// S-NSSAI, the AMF shall use a locally configured DNN as the DNN
dnn = ue.ServingAMF().SupportDnnLists[0]
if ue.SmfSelectionData != nil {
snssaiStr := util.SnssaiModelsToHex(snssai)
if snssaiInfo, ok := ue.SmfSelectionData.SubscribedSnssaiInfos[snssaiStr]; ok {
for _, dnnInfo := range snssaiInfo.DnnInfos {
if dnnInfo.DefaultDnnIndicator {
dnn = dnnInfo.Dnn
}
}
}
}
}
if newSmContext, cause, err := consumer.SelectSmf(ue, anType, pduSessionID, snssai, dnn); err != nil {
ue.GmmLog.Errorf("Select SMF failed: %+v", err)
gmm_message.SendDLNASTransport(ue.RanUe[anType], nasMessage.PayloadContainerTypeN1SMInfo,
smMessage, pduSessionID, cause, nil, 0)
} else {
_, smContextRef, errResponse, problemDetail, err := consumer.SendCreateSmContextRequest(
ue, newSmContext, nil, smMessage)
if err != nil {
ue.GmmLog.Errorf("CreateSmContextRequest Error: %+v", err)
return false, nil
} else if problemDetail != nil {
// TODO: error handling
return false, fmt.Errorf("Failed to Create smContext[pduSessionID: %d], Error[%v]", pduSessionID, problemDetail)
} else if errResponse != nil {
ue.GmmLog.Warnf("PDU Session Establishment Request is rejected by SMF[pduSessionId:%d]",
pduSessionID)
gmm_message.SendDLNASTransport(ue.RanUe[anType], nasMessage.PayloadContainerTypeN1SMInfo,
errResponse.BinaryDataN1SmMessage, pduSessionID, 0, nil, 0)
} else {
newSmContext.SetSmContextRef(smContextRef)
newSmContext.SetUserLocation(deepcopy.Copy(ue.Location).(models.UserLocation))
ue.StoreSmContext(pduSessionID, newSmContext)
ue.GmmLog.Infof("create smContext[pduSessionID: %d] Success", pduSessionID)
// TODO: handle response(response N2SmInfo to RAN if exists)
return true, nil
}
}
return false, nil
}
```
* It is kinda complicated, so I draw the clall flow :

6. Until here, I may have two ways to solve it :
- Keep ingoring the lines produce the error messages.
1. First I try to skip the SendDLNASTransport process, let it continue to next else function.
 but it turns out

or modify like this
 but it need the parameters passed from SelectSMF

2. Then I turn to **sm_context.go** to see if I can ignore the error parameter(err) which will be returned to **handler.go**.
3. I add some text before each return line in **func SelectSmf**, and result is that it returns at here :

in the first if function,

and it actually means that the prefix of the  is from **CreatePDUSession** but afterpart(suffix) is printed here before return back(return01), so if I ignore this ,
the log looks like this
,
which is different from this
.
4. Then I scroll down to see the rest code of the func SelectSmf after return01, and find that maybe I can try to ignore the whole if function, because it seems that it doesnt really need it, if I remove it, the error will also not be put in err parameter.
* Try to modify the code, let SMF stop to find NSSF or give AMF a fixed value snssai to select SMF.
1. So in the last method, we cannot just ignore the error meassage lines to jump through this process.
2. Like the point 4. up there, I try to ingore the whole nsiInformation checking function, the result put in below part.
:::
### Solution
:::success
1. Continued to say, because the if function I modified seems to be useless for afterpart in SelectSmf :
```go=
.
.
.
smContext := amf_context.NewSmContext(pduSessionID)
smContext.SetSnssai(snssai)
smContext.SetDnn(dnn)
smContext.SetAccessType(anType)
if nsiInformation == nil {
ue.GmmLog.Warnf("nsiInformation is still nil, use default NRF[%s]", nrfUri)
} else {
smContext.SetNsInstance(nsiInformation.NsiId)
nrfApiUri, err := url.Parse(nsiInformation.NrfId)
if err != nil {
ue.GmmLog.Errorf("Parse NRF URI error, use default NRF[%s]", nrfUri)
} else {
nrfUri = fmt.Sprintf("%s://%s", nrfApiUri.Scheme, nrfApiUri.Host)
}
}
param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{
ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NSMF_PDUSESSION}),
Dnn: optional.NewString(dnn),
Snssais: optional.NewInterface(openapi.MarshToJsonString([]models.Snssai{snssai})),
}
if ue.PlmnId.Mcc != "" {
param.TargetPlmnList = optional.NewInterface(openapi.MarshToJsonString(ue.PlmnId))
}
if amf_context.GetSelf().Locality != "" {
param.PreferredLocality = optional.NewString(amf_context.GetSelf().Locality)
}
ue.GmmLog.Debugf("Search SMF from NRF[%s]", nrfUri)
result, err := SendSearchNFInstances(nrfUri, models.NfType_SMF, models.NfType_AMF, ¶m)
if err != nil {
ue.GmmLog.Errorf("////return03////")
return nil, nasMessage.Cause5GMMPayloadWasNotForwarded, err
}
if len(result.NfInstances) == 0 {
err = fmt.Errorf("DNN[%s] is not supported or not subscribed in the slice[Snssai: %+v]", dnn, snssai)
ue.GmmLog.Errorf("////return04////")
return nil, nasMessage.Cause5GMMDNNNotSupportedOrNotSubscribedInTheSlice, err
}
// select the first SMF, TODO: select base on other info
for _, nfProfile := range result.NfInstances {
smfUri = util.SearchNFServiceUri(nfProfile, models.ServiceName_NSMF_PDUSESSION, models.NfServiceStatus_REGISTERED)
if smfUri != "" {
break
}
}
smContext.SetSmfID(smfID)
smContext.SetSmfUri(smfUri)
ue.GmmLog.Errorf("////return05////")
return smContext, 0, nil
}
```
2. I try to do this, not just ingore the lines produce the error messages, but stop the NSSelection error production :

3. And it works, the PDUSession is builded successfully, though there is a warning message, see the [testing result](https://hackmd.io/inBBnqB5Qx-ZMNsb_jaq0Q#Remove-NSSF).
:::
# 4. Remove "PCF"
## File editting
* Makefile

* run.sh

### Record the log before accessing UE
* You can see PCF log dispear, and check the difference with the last part "Remove NSSF"




## The error logs after ignoring PCF and acessing the UE
### 1. AMF can not select an PCF by NRF
**Core side**



**gnb side**
* Repeated messages

**UE side**
* Repeated messages

### Error fixing process
:::warning
1. Search in the folder

* In handler.go, the logs is from this function, and you can check it start from printing out **Handle InitialRegistration** by see the log up there(Core side).
```go=
func HandleInitialRegistration(ue *context.AmfUe, anType models.AccessType) error {
ue.GmmLog.Infoln("Handle InitialRegistration")
amfSelf := context.GetSelf()
// update Kgnb/Kn3iwf
ue.UpdateSecurityContext(anType)
// Registration with AMF re-allocation (TS 23.502 4.2.2.2.3)
if len(ue.SubscribedNssai) == 0 {
getSubscribedNssai(ue)
}
if err := handleRequestedNssai(ue, anType); err != nil {
return err
}
if ue.RegistrationRequest.Capability5GMM != nil {
ue.Capability5GMM = *ue.RegistrationRequest.Capability5GMM
} else {
gmm_message.SendRegistrationReject(ue.RanUe[anType], nasMessage.Cause5GMMProtocolErrorUnspecified, "")
return fmt.Errorf("Capability5GMM is nil")
}
storeLastVisitedRegisteredTAI(ue, ue.RegistrationRequest.LastVisitedRegisteredTAI)
if ue.RegistrationRequest.MICOIndication != nil {
ue.GmmLog.Warnf("Receive MICO Indication[RAAI: %d], Not Supported",
ue.RegistrationRequest.MICOIndication.GetRAAI())
}
// TODO: Negotiate DRX value if need (TS 23.501 5.4.5)
negotiateDRXParameters(ue, ue.RegistrationRequest.RequestedDRXParameters)
// TODO (step 10 optional): send Namf_Communication_RegistrationCompleteNotify to old AMF if need
if ue.ServingAmfChanged {
// If the AMF has changed the new AMF notifies the old AMF that the registration of the UE in the new AMF is completed
req := models.UeRegStatusUpdateReqData{
TransferStatus: models.UeContextTransferStatus_TRANSFERRED,
}
// TODO: based on locol policy, decide if need to change serving PCF for UE
regStatusTransferComplete, problemDetails, err := consumer.RegistrationStatusUpdate(ue, req)
if problemDetails != nil {
ue.GmmLog.Errorf("Registration Status Update Failed Problem[%+v]", problemDetails)
} else if err != nil {
ue.GmmLog.Errorf("Registration Status Update Error[%+v]", err)
} else {
if regStatusTransferComplete {
ue.GmmLog.Infof("Registration Status Transfer complete")
}
}
}
if len(ue.Pei) == 0 {
gmm_message.SendIdentityRequest(ue.RanUe[anType], anType, nasMessage.MobileIdentity5GSTypeImei)
return nil
}
// TODO (step 12 optional): the new AMF initiates ME identity check by invoking the
// N5g-eir_EquipmentIdentityCheck_Get service operation
if ue.ServingAmfChanged || ue.State[models.AccessType_NON_3_GPP_ACCESS].Is(context.Registered) ||
!ue.ContextValid {
if err := communicateWithUDM(ue, anType); err != nil {
ue.GmmLog.Errorf("communicateWithUDM error: %v", err)
gmm_message.SendRegistrationReject(ue.RanUe[anType], nasMessage.Cause5GMMPLMNNotAllowed, "")
return errors.Wrap(err, "communicateWithUDM failed")
}
}
param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{
Supi: optional.NewString(ue.Supi),
}
if amfSelf.Locality != "" {
param.PreferredLocality = optional.NewString(amfSelf.Locality)
}
for {
resp, err := consumer.SendSearchNFInstances(amfSelf.NrfUri, models.NfType_PCF, models.NfType_AMF, ¶m)
if err != nil {
ue.GmmLog.Error("AMF can not select an PCF by NRF")
} else {
// select the first PCF, TODO: select base on other info
var pcfUri string
for _, nfProfile := range resp.NfInstances {
pcfUri = util.SearchNFServiceUri(nfProfile, models.ServiceName_NPCF_AM_POLICY_CONTROL,
models.NfServiceStatus_REGISTERED)
if pcfUri != "" {
ue.PcfId = nfProfile.NfInstanceId
break
}
}
if ue.PcfUri = pcfUri; ue.PcfUri == "" {
ue.GmmLog.Error("AMF can not select an PCF by NRF")
} else {
break
}
}
time.Sleep(500 * time.Millisecond) // sleep a while when search NF Instance fail
}
problemDetails, err := consumer.AMPolicyControlCreate(ue, anType)
if problemDetails != nil {
ue.GmmLog.Errorf("AM Policy Control Create Failed Problem[%+v]", problemDetails)
} else if err != nil {
ue.GmmLog.Errorf("AM Policy Control Create Error[%+v]", err)
}
// Service Area Restriction are applicable only to 3GPP access
if anType == models.AccessType__3_GPP_ACCESS {
if ue.AmPolicyAssociation != nil && ue.AmPolicyAssociation.ServAreaRes != nil {
servAreaRes := ue.AmPolicyAssociation.ServAreaRes
if servAreaRes.RestrictionType == models.RestrictionType_ALLOWED_AREAS {
numOfallowedTAs := 0
for _, area := range servAreaRes.Areas {
numOfallowedTAs += len(area.Tacs)
}
// if numOfallowedTAs < int(servAreaRes.MaxNumOfTAs) {
// TODO: based on AMF Policy, assign additional allowed area for UE,
// and the upper limit is servAreaRes.MaxNumOfTAs (TS 29.507 4.2.2.3)
// }
}
}
}
// TODO (step 18 optional):
// If the AMF has changed and the old AMF has indicated an existing NGAP UE association towards a N3IWF, the new AMF
// creates an NGAP UE association towards the N3IWF to which the UE is connectedsend N2 AMF mobility request to N3IWF
// if anType == models.AccessType_NON_3_GPP_ACCESS && ue.ServingAmfChanged {
// TODO: send N2 AMF Mobility Request
// }
amfSelf.AllocateRegistrationArea(ue, anType)
ue.GmmLog.Debugf("Use original GUTI[%s]", ue.Guti)
assignLadnInfo(ue, anType)
amfSelf.AddAmfUeToUePool(ue, ue.Supi)
ue.T3502Value = amfSelf.T3502Value
if anType == models.AccessType__3_GPP_ACCESS {
ue.T3512Value = amfSelf.T3512Value
} else {
ue.Non3gppDeregTimerValue = amfSelf.Non3gppDeregTimerValue
}
gmm_message.SendRegistrationAccept(ue, anType, nil, nil, nil, nil, nil)
return nil
}
```
2. Try to break after error
* After first error printing message, it still enter infinite loop, so the error is not printed here.

* So it is actually printed from here.

3. And it turns out to be panic error.
* Core side

* Repeated UE side

4. But sometimes it will print out another kind of panic error.
* Core side


* Repeated UE side

* Here the 4. should be the right way to print out the message, because when we close core, gnb, ue completely, and restart all of them, they always look like 4.
* **But if we dont stop gnb and ue**, just restart the core, then also restart the gnb, and ue can connect again which doesnt need to stop and restart, you will see in the message

will be printed out in the core side, then when ue connect to core again, the error in 3. will happen.
* The **panic error** means some of pointer parameters have an error address or value, which is also met in NSSF removing(in SMF selection), so I guess that if we dont stop the ue, the reconnected ue will cause the authentication parameter error in restarted 5GC.
* So when we meet panic error, we may accidentally comment out some parameter which is using in the process of ignoring error printing line.
* In the past experence, the panic error is hard to solve, because we may need to redefine the parameter or give some value to it
* If we derectly comment out the patameter, other function need it.
* If we dont comment out it, the function returning process need the parameter which we want to comment out, like the err parameter.
* For example, response is needed for other function, err is needed for access the returned value, but we want to comment out err.

5. **But** in here, we can see the panic error is after another error message  which is happened after , so we can deal with it first and see if the panic error disapears.
:::
### 2. AM Policy Control Create Error[server no response]
* From 5.
### Error fixing process
:::warning
6. You can see this error is from here.
* And when you check other parts of **func HandleInitialRegistration**, you can see the only part has relation with PCF is this part, but I need to study more about PolicyControl to know what kind of relation it is.
```go=
.
.
.
for {
resp, err := consumer.SendSearchNFInstances(amfSelf.NrfUri, models.NfType_PCF, models.NfType_AMF, ¶m)
if err != nil {
ue.GmmLog.Error("AMF can not select an PCF by NRF")
//break
} else {
// select the first PCF, TODO: select base on other info
var pcfUri string
for _, nfProfile := range resp.NfInstances {
pcfUri = util.SearchNFServiceUri(nfProfile, models.ServiceName_NPCF_AM_POLICY_CONTROL,
models.NfServiceStatus_REGISTERED)
if pcfUri != "" {
ue.PcfId = nfProfile.NfInstanceId
break
}
}
if ue.PcfUri = pcfUri; ue.PcfUri == "" {
ue.GmmLog.Error("AMF can not select an PCF by NRF")
break
} else {
break
}
}
time.Sleep(500 * time.Millisecond) // sleep a while when search NF Instance fail
}
problemDetails, err := consumer.AMPolicyControlCreate(ue, anType)
if problemDetails != nil {
ue.GmmLog.Errorf("AM Policy Control Create Failed Problem[%+v]", problemDetails)
} else if err != nil {
ue.GmmLog.Errorf("AM Policy Control Create Error[%+v]", err)
}
.
.
.
```
7. I think there are some ways to **comment out** the PCF related part in initial registration.
1. **Remove the function SendSearchNFInstances** to stop the production of err.
* The function SendSearchNFInstances is like a **global variable** in free5gc, other part of code will call it to find NF.
* There will has an error about resp because it is used at below code.
2. **Break the for loop** after error printing line(this line can be commented out or it will be printed out as usual)
* It seems to be OK, it successfully jump to next part and will not cause some implicit errors that will not be seen in logs, because the original error is trigered by PCF's uri is blank, and the blank PCFuri will not cause other problem, it is just because PCF is removed.
* If this is OK, maybe we dont need to comment out the whole for loop, but if the err parameter is used in afterpart and the value stored in it caused another problem, we should do this or other modification(In the code, after this part, err will not be used.)
3. **Remove the function AMPolicyControlCreate**
* It seems to be ok because the parameters problemDetails and err is only used in here.
4. But I just **comment out this part**

8. As 7-2 says, I also comment it out,

and the result is like below, the error message are gone, but the panic error still exists.

9. As stated above, now I just need to try figuring out how to solve this out.
* The panic error happended **after I break the for loop**, and it is **printed after Send Initial Context Setup Request**, which is produced here :
1. In the end of func HandleInitialRegistration, it calls
2. The func SendRegistrationAccept is in

, which will print out this before Send Initial Context Setup Request


3. And func SendRegistrationAccept calls this function

, which is in here and will print out this


* So there might have some parameters needed in the process of Send Registration Accept and Send Initial Context Setup Request, like below is one of the ue info but not be written in because the printed error and break.

10. Originally I think the panic may have relation with commenting out some kind of parameter needed in **consumer.AMPolicyControlCreate**
* (Uncertain) But compare to the panic error screenshot attached above, we can say there is no difference between this(after commenting out) and that(before commenting out).
* So we might still turn to 9. for the answar.
:::
### 3. [FATA][AMF][Ngap] panic: runtime error: invalid memory address or nil pointer dereference
* From 10.
### Error fixing process
:::warning
11. Continue from 9.
* After doing this, it still has panic.

12. And I think the reason is in the parameters passed from HandleInitialRegistration to SendRegistrationAccept and to SendInitialContextSetupRequest.


13. So I add some lines of fmt.println. to see the value passing process. If you has an error which says no import "fmt", you need to add this.

In this process, we need to repeat compiling core and change the line of print to see where the panic happens.
1. First in , wa can see the printed info before passing to SendRegistrationAccept :

2. Then in , the info can be printed out after BuildRegistrationAccept and before the if lines :

3. Then in the **SendInitialContextSetupRequest** of , I add these lines so I can check where the panic is from, here the HERE3 is printed and HERE4 is not printed, which means the panic is from **BuildInitialContextSetupRequest**.

14. In this function, there are so many if functions, about 300 lines, so I just repeat printing to see which one is the last one run before panic error.


And result is here, wa can see +++++ is printed, and ===== is not printed.

15. The log is like below, because the value of ue is printed in original type, I dont know how to modify it.

16. Here just try to fix the PcfId, but it change nothing.

17. Keep tracing, we can dig more deep in **BuildIEMobilityRestrictionList**.

And it is in , in the function I just try this if line first because it relates to PolicyAssociation, then the line of 55555 is not printed, so I want to print the ServAreaRes parameter, but it is not printed too, so the panic reason is in the parameter.

18. Here we can see the log stops at 33333.

At the same time, when checking the log of panic error, we can see it has already printed out the start of error

and the end of the error,

so next time we can follow this.
19. Next step, I find where is AmPolicyAssociation and ServAreaRes. One is in **type AmfUe struct** of this file
,
the other one is in
.
20. If I derectly comment out here.

I will get another panic error.
:::
### 4. [ERRO][SMF][GIN] panic: runtime error: index out of range [0] with length 0
* from 20.
**Core side**
* It skip the policy part of AMF and it seems entering the part of SMF but get panic error and repeat it.



**gnb side**

**UE side**

### Error fixing process
:::warning
21.  This line just disappears if I directly comment out in the code, so I didnt touch it.
22.  Then I search this information to find where the panic error happend, and it is in here. 
When I want to print the value of rep.NfInstances[0], it turns out this, the error happenning place move to line 444.

23. Test in original full CN, the value of this **structure** is 
* Because I use logger.CtxLog.Warningf() to print it, it can be more conspicuous in many logs.
* Because I use %v, the printed values is not only the first element, it print out all values in the struc.
* Using %+v can print in detailed including the parameter name.
...
24. And I use the original value of NfInstance Id to write into it.

But the result stay the same.

I guess it may need all value of struc, so I do this to write the parameter if it has value in original CN.

But the result stay the same.

25.






:::
### 5. PDU Session Establishment Request is rejected by SMF
* From 25.
**Core side**


**gnb side**

**UE side**

### Error fixing process
:::warning
26. Only reserve these two lines.


And dont comment out here.

* Result stay the same
27. Original values which printed in free5gc_v3.3_01(full core).




28. Dont comment out these lines and replace the apiprefix, I want to recover the policy in SMF.


* It is hard to specify the NfServices, so i didnt use original parameter service.ApiPrefix
* Result stay the same
* It use this kind of url to use the reference from github of openapi, in [detail](https://hackmd.io/DETj57LjQFimKBIOaD6csQ?view#Use-code-from-github).


:::
### 6. Combine PCF to SMF to recover the policy creating process
* From 28.
Because the log result has already on the stage of SMcontext and PDUsession creaing, so if I keep commenting out something, it may influence the whole process.
#### 6-1. Investiigation in original core
:::success
29. Compare to the modified core side(get the 504 error and release the IP of UE), the highlighted part in the picture(original core), maybe we can recover it through moving the removed function of PCF to SMF.

* If I searh the first message(**[PCF][SMpolicy] Handle CreateSmPolicy**) in code directly, I can find this kind of sequence :
**smpolicy.go <== api_default.go <== routers.go**
(HandleCreateSmPolicyRequest <== HTTPSmPoliciesPost <== var routes = Routes)



30. Print some numbers to seperate them so that I can know the breakpoints, then can know how and where to call router.go.





* Call between 1 and 2, which is by **consumer.SendSMPolicyAssociationCreate(smContext)**.
31. Keep tracing to **sm_policy.go** in sbi/consumer of SMF, we can find it calls the API producer in PCF through router.go between 2-6 and 2-7, which produce the messages in the log.



32. About the detailed situation of openAPI call flow, [see here](https://hackmd.io/DETj57LjQFimKBIOaD6csQ?both#OpenAPI).
33. Keep finding where the logs between 2-6 and 2-7, we can find that they are all in the func createSMPolicyProcedure which is in the same SMF calling file (smpolicy.go).
Here are the sources of each line :
1. 

2. 

3. 

4. 

5. 

6. 

:::
#### 6-2.
:::success
34. Before moving the function between 2-6~2-7, I find that I miss some clues :
* In modifed core, it send 504 error after PDUAdress allocated.

* But in original core, it will send 200 for finding PCF successfully after PDUAdress allocated.

* And if I just move the part I investigated in 6-1, although it is truely the lacked policy part in SMF, I may still have error because of skipping this difference before 1 and some value printed by me.
* The difference here is also caused by the lack of PCF I guess.
35. The releasing part after api 504.



:::
### *v3.3_PCF_v0.3 & v3.3_Full_PCF_v0.1*