owned this note
owned this note
Published
Linked with GitHub
[TOC]
# Capture packets
## Information in wireshark
### RAND value
### AUTN value
# GO language
* 看要不要獨立一篇出來
* chatgpt之前問的問題要紀錄下來
## main.go / init.go



### Example in Free5GC
* You can find that there are some building logs when you run the run.sh, and they are really start from run.sh.

* After it do something, start UPF and MongoDB, it will run every NF in ~/bin/NF and read the config of them.


* If you see the log in detail, you can find some descreption of each NF, and it is not from run.sh because run.sh is done.

* About the files in bin folder, we can not read it because of the garbled characters.


* About the explanation of these files.


* So after bin file is executed, system will enter main.go and it will call init.go, then in this process, you can the logs is printed from here.


* In init.go, you can see it imports a lot of service

* And call some functions which will print out the logs.





## Go module
:::warning
### Example before
* [Link](https://hackmd.io/fH1eBOchRbGLQA3qb202PQ?view#Test)
* Compared to my [study](https://hackmd.io/AMzUH2F7TzOxIo5o3H3CyA?both#import-method) on Terry's method.
:::
:::success
### go.mod
* I want to clearify the usage of this, because this is one of the point in the newer version(>1.11) of Go language, most of the import methods don't rely on GOPATH.
* When I was browsing my past method and Terry's, I found that there is no a direct URL calling the Network Function in each go.mod, but it exists on the first line.

* For ex, there is no 1 and 2 in go.mod, but for 3 there are in go.mod, which means I can directly import the things in the same amf folder.

### Answar




```go=
go mod init github.com/yourusername/yourproject
```






#### Test



### replace
* Before I know how Terry use the import, I dont understand why he doesnt use replace in go.mod to redirect the URL but he can import his own local folder.
* Here is some concept of replace.





* So the point is that **there has already a UR**L which calls the resouce from github, and **we use "replace" to cut the link with github, rebuild a link with local folder/file** if we want to do a test in local environment.
* Then what I had done using replace may be **an unnecessory move**, because the OG URL has already call the folder I want to use, and replace just add one more command to call the local path.

#### The environment path check

#### Some other possibility

```go=
go env GOPATH //This command is also useful for check the location.
```

```go=
go list -m all
```




> ### import
### import( github.com/... )
* When I was modifying the UDM/UDR part in AUSF improvement, I found that there is no this imported address in the local free5gc folder (free5gc/util/...).

* But it is indeed in the go.mod in UDR.

* **The answar is in the [repository](https://github.com/orgs/free5gc/repositories)** on free5GC official github, the URL will be the same as what you import when you click into one of the repo.

:::
### Use code from github
:::spoiler reference
https://blog.csdn.net/yeshang_lady/article/details/134272955
https://home.gamer.com.tw/artwork.php?sn=5463024

:::
#### Code
* In smf, take sm_context.go in package context as example, below are the functions it import, some are the functions from the official go language, the other imported lines including "github.com/..." are from the github of free5gc.


* You can see the reference about how you can add the frepository into your code, in free5gc's NFs, every NF has a file called go.mod, recording the url it imports.

* Until here, Im curious about if the free5gc works without internet, because the modules from github are imported, not copied to local host, so I do a test closing the network interface and running the 5gc.
The result is that it needs addresses binded for using http service, but it doesnt explan whether the github module affect the program.

### Use code from local place
:::spoiler reference
https://calvertyang.github.io/2019/11/12/a-beginners-guide-to-packages-in-golang/
:::
#### Package context



#### Package



### GOPATH
* Check the path in your environment, it will be void if you havent set GOPATH.
* The default path will be $HOME/go if your version >= Go 1.11
```shell=
echo $GOPATH
```
* Set the path.
* It will not affect other path directly, GOPATH is used for store 3rd party packages or items, and dealing with the improting relation in Go, it will tell compiler where to find and check the library.
* Other package provided by Go standard library exist when installing Go, and can be accessed everywhere.
```shell=
export GOPATH=/home/ubuntu/free5gc_AUSF_v2.0
```
## make

:::danger

:::
:::success

:::
## Run .go in VScode


```go=
package main
import (
"fmt"
"strings"
)
func main() {
suci := "suci-0-208-93-0000-0-0-0000000003"
parts := strings.Split(suci, "-")
lastPart := parts[len(parts)-1]
supi := "imsi-20893" + lastPart
fmt.Println(supi) // 輸出: imsi-208930000000003
}
```

```shell=
go mod init example.com/myapp
```

```shell=
go run main.go
```

### Set the environment PATH for Go
:::danger
* Error when I want to go run.
```
go : 無法辨識 'go' 詞彙是否為 Cmdlet、函數、指令檔或可執行程式的名稱。請檢查名稱拼字是否正確,如果包含路徑的話,請確認路徑是否正
確,然後再試一次。
位於 線路:1 字元:1
+ go run main.go
+ ~~
+ CategoryInfo : ObjectNotFound: (go:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
```
:::
:::success
* Usually after the installation, the PATH of Go will be added automatically, like the pic below, I added it repeatly.

* The reason why this error popped up is that I need to **restart the VScode** after installing Go, after restart :


:::


```shell=
go version
```


## const
```go=
// suci-0(SUPI type: IMSI)-mcc-mnc-routingIndicator-protectionScheme-homeNetworkPublicKeyID-schemeOutput.
// TODO:
// suci-1(SUPI type: NAI)-homeNetworkID-routingIndicator-protectionScheme-homeNetworkPublicKeyID-schemeOutput.
const (
PrefixPlace = iota
SupiTypePlace
MccPlace
MncPlace
RoutingIndicatorPlace
SchemePlace
HNPublicKeyIDPlace
SchemeOuputPlace
MaxPlace
)
const (
PrefixIMSI = "imsi-"
PrefixSUCI = "suci"
SupiTypeIMSI = "0"
NullScheme = "0"
ProfileAScheme = "1"
ProfileBScheme = "2"
)
func ToSupi(suci string, suciProfiles []SuciProfile) (string, error) {
suciPart := strings.Split(suci, "-")
logger.SuciLog.Infof("suciPart: %+v", suciPart)
suciPrefix := suciPart[0]
if suciPrefix == "imsi" || suciPrefix == "nai" {
logger.SuciLog.Infof("Got supi\n")
return suci, nil
} else if suciPrefix == PrefixSUCI {
if len(suciPart) < 6 {
return "", fmt.Errorf("Suci with wrong format\n")
}
} else {
return "", fmt.Errorf("Unknown suciPrefix [%s]", suciPrefix)
}
logger.SuciLog.Infof("scheme %s\n", suciPart[SchemePlace])
scheme := suciPart[SchemePlace]
mccMnc := suciPart[MccPlace] + suciPart[MncPlace]
supiPrefix := PrefixIMSI
if suciPrefix == PrefixSUCI && suciPart[SupiTypePlace] == SupiTypeIMSI {
logger.SuciLog.Infof("SUPI type is IMSI\n")
}
if scheme == NullScheme { // NULL scheme
return supiPrefix + mccMnc + suciPart[len(suciPart)-1], nil
}
.
.
.
```
:::danger
* How ToSupi can use the variable MccPlace or MncPlace without calling ?
:::
:::success



:::



## P0 := []byte(snName)

```go=
package main
import "fmt"
func main() {
snName := "Hello, Go!"
P0 := []byte(snName)
fmt.Println("Original string:", snName)
fmt.Println("Byte slice:", P0)
}
```

## Return
### return "" & return nil

```go=
package main
import "fmt"
func getEmptyString() string {
return ""
}
func main() {
result := getEmptyString()
fmt.Println(result) // 輸出一個空行,因為 result 是一個空字符串
}
```



```go=
package main
import "fmt"
// 返回空字符串
func getEmptyString() string {
return ""
}
// 返回空指針
func getNilPointer() *int {
return nil
}
// 返回空切片
func getNilSlice() []int {
return nil
}
// 返回空映射
func getNilMap() map[string]int {
return nil
}
// 返回空通道
func getNilChannel() chan int {
return nil
}
// 返回空接口
func getNilInterface() interface{} {
return nil
}
func main() {
fmt.Println("Empty String:", getEmptyString())
fmt.Println("Nil Pointer:", getNilPointer())
fmt.Println("Nil Slice:", getNilSlice())
fmt.Println("Nil Map:", getNilMap())
fmt.Println("Nil Channel:", getNilChannel())
fmt.Println("Nil Interface:", getNilInterface())
}
```

## API link

```go=
package models
type LinksValueSchema struct {
Href string `json:"href"`
}
```

---

```go=
linksValue := models.LinksValueSchema{Href: putLink}
responseBody.Links = make(map[string]models.LinksValueSchema)
responseBody.Links["5g-aka"] = linksValue
```
* make function doesnt need to import module.



```go=
//You can use this example to print the result, and see the structure.
package main
import (
"fmt"
"models"
)
func main() {
// 假設 putLink 是一個有效的 URL 字串
putLink := "https://example.com/5g-aka"
// 創建 LinksValueSchema 實例
linksValue := models.LinksValueSchema{Href: putLink}
// 初始化 responseBody 的 Links 映射
var responseBody models.ResponseBody
responseBody.Links = make(map[string]models.LinksValueSchema)
// 將 linksValue 添加到映射中,鍵為 "5g-aka"
responseBody.Links["5g-aka"] = linksValue
// 打印結果
fmt.Println(responseBody)
}
```
## strictHex()

```go=
func strictHex(s string, n int) string {
l := len(s)
if l < n {
return fmt.Sprintf(strings.Repeat("0", n-l) + s)
} else {
return s[l-n : l]
}
}
```

```go=
package main
import (
"fmt"
"strings"
)
func strictHex(s string, n int) string {
l := len(s)
if l < n {
return fmt.Sprintf(strings.Repeat("0", n-l) + s)
} else {
return s[l-n : l]
}
}
func main() {
authSubsSequenceNumber := "12345"
sqnStr := strictHex(authSubsSequenceNumber, 12)
fmt.Println(sqnStr) // 輸出 "0000000012345"
authSubsSequenceNumber = "1234567890ABCDEF"
sqnStr = strictHex(authSubsSequenceNumber, 12)
fmt.Println(sqnStr) // 輸出 "7890ABCDEF"
}
```

## Some computation
### big/SetString

```go=
package main
import (
"fmt"
"math/big"
)
func main() {
sqnStr := "123ABC"
bigSQN := new(big.Int)
bigSQN, success := bigSQN.SetString(sqnStr, 16)
if !success {
fmt.Println("轉換失敗")
} else {
fmt.Println("轉換成功:", bigSQN)
}
}
```

```go=
// 假設 authSubs.SequenceNumber 是一個十六進制字符串
sqnStr := "16f3b3f70ff2"
bigSQN := new(big.Int)
bigSQN, success := bigSQN.SetString(sqnStr, 16)
if !success {
logger.GmmLog.Infof("轉換失敗")
return nil, fmt.Errorf("無法轉換序列號")
}
// 進行大數運算,例如增加序列號
bigInc := big.NewInt(1)
bigSQN.Add(bigSQN, bigInc)
// 將結果轉換回十六進制字符串
newSqnStr := fmt.Sprintf("%x", bigSQN)
logger.GmmLog.Infof("新的序列號: %s", newSqnStr)
```
### NewInt/Add/Mod


```go=
package main
import (
"fmt"
"math/big"
)
func main() {
// 定義常數和初始值
SqnMAx := int64(0xFFFFFFFFFFFF)
sqnStr := "16f3b3f70ff2"
// 將 sqnStr 轉換為大數
bigSQN := new(big.Int)
bigSQN, success := bigSQN.SetString(sqnStr, 16)
if !success {
fmt.Println("轉換失敗")
return
}
// 定義增量和最大值
bigInc := big.NewInt(1)
bigP := big.NewInt(SqnMAx)
// 增加序列號並進行模運算
bigSQN.Add(bigSQN, bigInc)
bigSQN.Mod(bigSQN, bigP)
// 將結果轉換回十六進制字符串
newSqnStr := fmt.Sprintf("%x", bigSQN)
fmt.Println("新的序列號:", newSqnStr)
}
```
## Declaration & :=, =, ==

```go=
package main
import "fmt"
// 全域變數宣告
var globalVar int = 100
func main() {
// 宣告並初始化變數
var a int = 10
var b = 20 // 類型推斷
var c int // 宣告但不初始化,默認值為 0
fmt.Println(a, b, c)
fmt.Println(globalVar)
}
```


```go=
package main
import "fmt"
func main() {
var (
a int = 10
b string = "hello"
c float64 = 3.14
)
fmt.Println(a, b, c)
}
```

```go=
package main
import "fmt"
func main() {
const pi = 3.14159
const hello = "Hello, World!"
fmt.Println(pi)
fmt.Println(hello)
}
```

```go=
package main
import "fmt"
func add(a int, b int) int {
return a + b
}
func main() {
result := add(3, 4)
fmt.Println(result) // 輸出: 7
}
```

```go=
package main
import "fmt"
func swap(a, b int) (int, int) {
return b, a
}
func main() {
x, y := swap(3, 4)
fmt.Println(x, y) // 輸出: 4 3
}
```

```go=
package main
import "fmt"
func divide(a, b int) (result int, err error) {
if b == 0 {
err = fmt.Errorf("division by zero")
return
}
result = a / b
return
}
func main() {
result, err := divide(10, 2)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Result:", result) // 輸出: Result: 5
}
}
```


```go=
package main
import "fmt"
func main() {
// 使用 := 進行變數宣告和賦值
a := 5 // a 是 int 型別,值為 5
b := "hello" // b 是 string 型別,值為 "hello"
c := 3.14 // c 是 float64 型別,值為 3.14
// 打印變數的值
fmt.Println(a) // 輸出: 5
fmt.Println(b) // 輸出: hello
fmt.Println(c) // 輸出: 3.14
}
```

```go=
package main
import "fmt"
func main() {
// 使用 := 宣告並初始化變數
x := 10
fmt.Println(x) // 輸出: 10
// 使用 = 賦值給已宣告的變數
x = 20
fmt.Println(x) // 輸出: 20
}
```

```go=
package main
import "fmt"
func main() {
a := 5
b := 5
c := 10
// 使用 == 比較變數的值
fmt.Println(a == b) // 輸出: true
fmt.Println(a == c) // 輸出: false
}
```

## recover()

```go=
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
mightPanic()
fmt.Println("This will not be printed if panic is not recovered")
}
func mightPanic() {
panic("Something went wrong!")
}
```

```go=
package main
import (
"fmt"
)
func main() {
safeFunction()
fmt.Println("Program continues to run...")
}
func safeFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in safeFunction:", r)
}
}()
panicFunction()
}
func panicFunction() {
panic("A severe error occurred!")
}
```

## map[string]interface {}

```go=
package main
import (
"fmt"
)
func main() {
// 定義一個 map[string]interface{}
data := make(map[string]interface{})
// 向 map 中添加不同類型的數據
data["name"] = "Alice"
data["age"] = 30
data["isStudent"] = false
data["grades"] = []int{85, 90, 92}
// 訪問 map 中的數據
fmt.Println("Name:", data["name"])
fmt.Println("Age:", data["age"])
fmt.Println("Is Student:", data["isStudent"])
fmt.Println("Grades:", data["grades"])
}
```

```go=
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonString := `{
"name": "Bob",
"age": 25,
"isStudent": true,
"grades": [88, 76, 93]
}`
var data map[string]interface{}
// 將 JSON 字符串解析為 map[string]interface{}
err := json.Unmarshal([]byte(jsonString), &data)
if err != nil {
fmt.Println("Error:", err)
return
}
// 訪問解析後的數據
fmt.Println("Name:", data["name"])
fmt.Println("Age:", data["age"])
fmt.Println("Is Student:", data["isStudent"])
fmt.Println("Grades:", data["grades"])
}
```

```go=
func main() {
data := map[string]interface{}{
"name": "Alice",
"age": 30,
"isStudent": false,
"grades": []int{85, 90, 92},
}
// 類型斷言
name, ok := data["name"].(string)
if !ok {
fmt.Println("Name is not a string")
} else {
fmt.Println("Name:", name)
}
age, ok := data["age"].(int)
if !ok {
fmt.Println("Age is not an int")
} else {
fmt.Println("Age:", age)
}
isStudent, ok := data["isStudent"].(bool)
if !ok {
fmt.Println("isStudent is not a bool")
} else {
fmt.Println("Is Student:", isStudent)
}
grades, ok := data["grades"].([]int)
if !ok {
fmt.Println("Grades is not a []int")
} else {
fmt.Println("Grades:", grades)
}
}
```

### The reason MongoDB use this format

```shell=
go get go.mongodb.org/mongo-driver/mongo
```

```go=
package main
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/bson"
"log"
"time"
)
func main() {
// 設置 MongoDB 連接選項
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
// 連接到 MongoDB
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
}
// 檢查連接是否成功
err = client.Ping(context.TODO(), nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Connected to MongoDB!")
// 指定數據庫和集合
collection := client.Database("testdb").Collection("testcollection")
// 查詢一個文檔
var result bson.M
filter := bson.M{"name": "Alice"}
err = collection.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
log.Fatal(err)
}
// 打印結果
fmt.Println("Result:", result)
// 關閉連接
err = client.Disconnect(context.TODO())
if err != nil {
log.Fatal(err)
}
fmt.Println("Connection to MongoDB closed.")
}
```

```go=
// 假設 result 已經包含從 MongoDB 查詢到的數據
name, ok := result["name"].(string)
if ok {
fmt.Println("Name:", name)
}
age, ok := result["age"].(int32)
if ok {
fmt.Println("Age:", age)
}
```
### Why don't we access the content of this format in free5GC directly, but use structure to replace ?

```go=
authSubs := map[string]interface{}{
"authenticationMethod": "5G_AKA",
"permanentKey": map[string]interface{}{
"permanentKeyValue": "8baf473f2f8fd09487cccbd7097c6862",
"encryptionAlgorithm": "0",
"encryptionKey": "0",
},
"sequenceNumber": "000000000034",
"authenticationManagementField": "8000",
"milenage": map[string]interface{}{
"op": map[string]interface{}{
"opValue": "8e27b6af0e692e750f32667a3b14605d",
"encryptionAlgorithm": "0",
"encryptionKey": "0",
},
"opc": map[string]interface{}{
"opcValue": "",
"encryptionAlgorithm": "0",
"encryptionKey": "0",
},
},
"ueId": "imsi-208930000000003",
}
```

```go=
// 先從 map 中取出 permanentKey
permanentKey, ok := authSubs["permanentKey"].(map[string]interface{})
if !ok {
// 處理錯誤,例如 permanentKey 字段不存在或類型不匹配
log.Fatalf("permanentKey not found or not a map[string]interface{}")
}
// 從 permanentKey 中取出 permanentKeyValue
permanentKeyValue, ok := permanentKey["permanentKeyValue"].(string)
if !ok {
// 處理錯誤,例如 permanentKeyValue 字段不存在或類型不匹配
log.Fatalf("permanentKeyValue not found or not a string")
}
fmt.Println("PermanentKeyValue:", permanentKeyValue)
```

```go=
type PermanentKey struct {
PermanentKeyValue string `json:"permanentKeyValue"`
EncryptionAlgorithm string `json:"encryptionAlgorithm"`
EncryptionKey string `json:"encryptionKey"`
}
type Milenage struct {
Op struct {
OpValue string `json:"opValue"`
EncryptionAlgorithm string `json:"encryptionAlgorithm"`
EncryptionKey string `json:"encryptionKey"`
} `json:"op"`
Opc struct {
OpcValue string `json:"opcValue"`
EncryptionAlgorithm string `json:"encryptionAlgorithm"`
EncryptionKey string `json:"encryptionKey"`
} `json:"opc"`
}
type AuthSubs struct {
AuthenticationMethod string `json:"authenticationMethod"`
PermanentKey *PermanentKey `json:"permanentKey"`
SequenceNumber string `json:"sequenceNumber"`
AuthenticationManagementField string `json:"authenticationManagementField"`
Milenage *Milenage `json:"milenage"`
UeId string `json:"ueId"`
}
func main() {
var authSubs AuthSubs
// 假設從數據庫中獲取數據並反序列化為 authSubs 結構體
// ...
// 直接訪問 PermanentKeyValue 字段
fmt.Println("PermanentKeyValue:", authSubs.PermanentKey.PermanentKeyValue)
}
```

## int32()


```go=
package main
import (
"fmt"
)
type ProblemDetails struct {
Status int32
Detail string // 假設有其他欄位
}
func main() {
// 假設 rsp 是一個 HTTP 回應物件,StatusCode 是其狀態碼
rsp := struct {
StatusCode int
}{
StatusCode: 404, // 假設狀態碼為 404
}
var problemDetails ProblemDetails
// 將 rsp.StatusCode 轉換為 int32,並賦值給 problemDetails.Status
problemDetails.Status = int32(rsp.StatusCode)
fmt.Printf("ProblemDetails 的狀態碼為: %d\n", problemDetails.Status)
}
```

## %x

```go=
package main
import (
"fmt"
)
func main() {
num := 255
fmt.Printf("%x\n", num) // 輸出:ff
}
```

```go=
package main
import (
"fmt"
)
func main() {
str := "hello"
fmt.Printf("%x\n", str) // 輸出:68656c6c6f
}
```

```go=
package main
import (
"fmt"
)
func main() {
data := []byte{0, 1, 2, 10, 15, 255}
fmt.Printf("%x\n", data) // 輸出:0001020a0fff
}
```

```go=
package main
import (
"fmt"
)
func main() {
data := []byte{0, 1, 2, 10, 15, 255}
fmt.Printf("% x\n", data) // 輸出:00 01 02 0a 0f ff
}
```

```go=
package main
import (
"fmt"
)
func main() {
num := 255
str := "hello"
data := []byte{0, 1, 2, 10, 15, 255}
fmt.Printf("Number in hex: %x\n", num) // Number in hex: ff
fmt.Printf("String in hex: %x\n", str) // String in hex: 68656c6c6f
fmt.Printf("Bytes in hex: %x\n", data) // Bytes in hex: 0001020a0fff
fmt.Printf("Bytes with space: % x\n", data) // Bytes with space: 00 01 02 0a 0f ff
}
```
## Function declaration


## Structure printing

```go=
package main
import (
"fmt"
)
type Person struct {
Name string
Age int
Email string
}
func main() {
p := Person{
Name: "Alice",
Age: 30,
Email: "alice@example.com",
}
// 使用%v打印 struct
fmt.Printf("%v\n", p) // {Alice 30 alice@example.com}
// 使用%+v打印 struct,包括字段名
fmt.Printf("%+v\n", p) // {Name:Alice Age:30 Email:alice@example.com}
// 使用%#v打印 struct,顯示詳細信息
fmt.Printf("%#v\n", p) // main.Person{Name:"Alice", Age:30, Email:"alice@example.com"}
// 使用%T打印 struct 的類型
fmt.Printf("%T\n", p) // main.Person
// 打印 struct 的字段值,分別用不同格式
fmt.Printf("Name: %s, Age: %d (bin: %b, hex: %x), Email: %s\n", p.Name, p.Age, p.Age, p.Age, p.Email)
}
```
```shell=
{Alice 30 alice@example.com}
{Name:Alice Age:30 Email:alice@example.com}
main.Person{Name:"Alice", Age:30, Email:"alice@example.com"}
main.Person
Name: Alice, Age: 30 (bin: 11110, hex: 1e), Email: alice@example.com
```
## MongoDB
* About the explanation of Go language executing sequence -> [Link](https://hackmd.io/DETj57LjQFimKBIOaD6csQ?view#maingo--initgo)
### Connection
* At first I thought these logs represent that 5GC has connected to MongoDB.

* But no, because the modification in AMF still can not connect to DB, but original UDR can, and the logs are just print after UPF start from run.sh, I dont know what it is for.

* The thing turned to my mind is that [Terry manually set](https://hackmd.io/AMzUH2F7TzOxIo5o3H3CyA#Connection-building) the connection in the init.go in AMF, which means it is necessary to do this before get the data.
* So I go to search the name of **func SetMongoDB** to see where it is used, it must be in UDR but we can only find **func getDataFromDB** use **mongoapi.RestfulAPIGetOne**.

* You can see it is called here to build the connection when start UDR in init.go.


## go.work










:::success





:::
:::success




:::
## PCF context problem
### go.mod replace









---








---
### internal in golang



### Combine two go.mod





### go.work











### internal bigger than go.work









---
### Move outside internal



#### can not still use shared go.mod








#### The reason



#### The result




:::danger
* Then is the same problem so ask more detailed (The screenshots see the improvement note).










* Then is to ask the method how to solve, so no take screenshots here, just see the results in improvement note.
:::
---
### The method of two go routine













# OpenAPI
## Use SMF--PCF as example
* Consumer means the http client, and producer means the http server in the communication between NFs
* Sbi is the service based interface related folder, storing the api files in each NF.

### Architecture

### Tracing
* How can sm_policy.go use the parameter smContext to call the function on github?
1. First, this parameter is passed from pdu_session.go

V

2. And the parameter is declared by the function in smf_context,

which is imported from the the other package "context"

3. Let's saerch the calling function directly, we can see two context folder, but the one in smf is correct.


4. Final, the func NewSMContext create a new smContext using a defined structure SMContxt, we can find the structure up there,

then when we look back to the parameter "SMPolicyClient" the sm_policy.go use,

we can find it is in the structure.

5. So the result is that "SMPolicyClient" in the structure is declared as a APIClient reference of the package "Npcf_SMPolicyControl".

6. If we see into github, we can find this function which including "DefaultApi",


then the DefaultApi can call "SmPloiciesPost" (dont know how it can, maybe it can use DefaultApi to call the function in the same folder?) which call the routers.go in PCF,


# Core modules/Network functions
## AMF
### Security mode
* Procedure defined in 3GPP **TS 33.501** version 15.2.0 Release 15
* Header type defined in 3GPP **TS 24.501** version 15.3.0 Release 15
* The conclusion made by chatGPT :


## AUSF
[Authentication Server Services / ETSI TS 129 509 V16.7.0 (2021-04)](https://www.etsi.org/deliver/etsi_ts/129500_129599/129509/16.07.00_60/ts_129509v160700p.pdf)
[Security architecture and procedures for 5G System / ETSI TS 133 501 V15.2.0 (2018-10)](https://www.etsi.org/deliver/etsi_ts/133500_133599/133501/15.02.00_60/ts_133501v150200p.pdf)
### Functionalities
- Authenticate the UE for the requester NF,
- Provide keying material to the requester NF,
- Protect the Steering Information List for the requester NF.
- Protect the UE Parameter Update Data for the requester NF.
### Service-based architecture

* SEAF(SEcurity Anchor Function)(安全錨功能) : The function that serves in the serving network as the anchor for security in 5G, provides the authentication functionality via the AMF in the serving network. The SEAF shall support primary authentication using SUCI.
* 
* SEAF function is collocated(搭配) with the AMF.
* PLMN
* Public Land Mobile Network is hosted by government or the permitted operator, provides mobile communication technology to public.
* PLMN=mcc+mnc.
* Home PLMN(歸屬PLMN) : the PLMN in IMSI of the user SIM card is identical with HPLMN.
* Visited PLMN(訪問PLMN) : The PLMN of SIM is not completely same as VPLMN.
:::warning
#### Serving network & Home network
* In 5G, serving network include the component which provide the service, like AMF, and home network includes the components which store the register info.


* For example, if you are roaming, you will be changed to different serving network, but go to the same home network for getting your subscriber data.

:::
### Provided services
- Nausf_UEAuthentication
- Nausf_SoRProtection
- Nausf_UPUProtection

#### Nausf_UEAuthentication

[Ref](https://blog.csdn.net/zhonglinzhang/article/details/109749426)
#### 5G-AKA

* UE's identifier like IMSI, SUCI(Subscription Concealed Identifier) will not be transmitted in plaintext in 5G, it's different from 4G.
* SNN(Service Network Name) can be used for authenticaion of SEAF in AUSF
* SIDF(Subscriber Identity De-concealing Function) can decrypt the SUCI into SUPI if AUSF provides to UDM, and the SUPI can be used for choosing the authenticating method.
* AV : Authentication Vector
[Ref](https://nccnews.com.tw/202010/ch4.html)
:::warning
#### 5G-AKA v.s. EAP-AKA'
* In free5GC, AUSF will search the authentication method in UDM ([Ref](https://blog.csdn.net/zhonglinzhang/article/details/108636015)), UDM will check the contract content to see which method it use.
* Normally, the authentication method is decided by the operator, which is pre-assigned to the 5GC.
- 5G-AKA (Authentication and Key Agreement)
- Specifically Designed for 5G.
- Based on SIM and AuC (Authentication Center).
- 5G-AKA is integrated into the 5G standards and is widely used as the primary authentication mechanism in 5G networks.
- It provides robust security features to protect user identities and ensure the confidentiality and integrity of communications.
- 5G AKA involves multiple stages, including a series of challenges and responses, to ensure secure communication between the user and the network.
- EAP-AKA' (Extensible Authentication Protocol - AKA Prime):
- EAP-AKA' is an extension of the Extensible Authentication Protocol (EAP) that encapsulates the AKA (Authentication and Key Agreement) protocol
- EAP is a more general authentication protocol used not only in 5G networks but also widely in other wireless networks such as Wi-Fi.
- In the 5GC, EAP is typically used in conjunction with EAP-AKA' (a version encapsulating 5G AKA) to provide greater flexibility and interoperability.
- EAP-AKA' allows for compatibility with existing authentication infrastructures and protocols, making it suitable for integration into heterogeneous networks.
- EAP requires more infrastructure support and is typically more complex than 5G AKA, but it offers greater flexibility and scalability.
- It offers greater flexibility in authentication methods and protocols, allowing operators to leverage various authentication mechanisms beyond 5G-AKA.
- EAP-AKA' enhances interoperability between different network types and facilitates seamless roaming across networks.
:::
:::warning
#### Auth parameters generating
*




[Ref](https://1drv.ms/p/s!AndI1JV-h1Q5jeI3KMCmpMuBShSd2A?e=GlVTJ8)
:::
#### Nausf_SoRProtection & Nausf_UPUProtection

* Left is in the free5gc, right is in the AUSF services spec.
* Until now, it dosent affect the main UEauthentication part, so I didnt do any detailed investigation on it.
## NSSF
### Definition
* [Ref](https://free5gc.org/blog/20230726/network_slice/)
* NS allows for the creation of multiple logical, isolated, and independent virtual networks that can coexist within a shared physical infrastructure.
* Each network slice provides dedicated and customized network resources to meet the specific requirements of different services
* The main elements of a network slice include:
* Virtualized Network Functions (VNFs)
* Isolation and Resource Allocation
* Orchestration and Management

* MANO is a NFV based architecture.

* [MANO 5GC](https://www.google.com/search?q=mano+5gc&rlz=1C1GCEA_enTW807TW810&oq=mano+&gs_lcrp=EgZjaHJvbWUqBggBEEUYOzIGCAAQRRg5MgYIARBFGDvSAQgyOTUzajBqN6gCALACAA&sourceid=chrome&ie=UTF-8)
### Network Slicing Identifier
* [Ref](https://free5gc.org/blog/20230726/network_slice/)
* NSSAI (Network Slice Selection Assistance Information) is a set of S-NSSAI, can be classified into 5.

* The deifnition in 5GC.

* The NFs join the NS function, and the NSSAI they have. (From On the Rollout of Network Slicing in Carrier Networks: A Technology Radar)

- From the release of 3GPP R15, the NS is mentioned, and it needs the support from not only NG-RAN but also CN, so 5G system use S-NSSAI(Single-NSSAI) and NSSAI to do slice management.
- S-NSSAI is combined from two fields.
- SST (Slice/Service Type) : Different SST implies different applied scene, like 1 for eMBB, 2 for uRLLC, 3 for mIoT, 4 for V2V and 5 for HMTC(High-Performance Machine-Type Communications).
- SD (Slice Differentiator) : Subdivide functions in the same scenario, including mobile network or fixed wireless access network, charging, slice priority, tenancy.
### Info in SPEC
* [Ref](https://1drv.ms/b/s!AndI1JV-h1Q5kYZeG2Sr2dIbSdACRA?e=JjRZBp)

* [Ref](https://1drv.ms/b/s!AndI1JV-h1Q5kYsPCXpzC6mA3SW7Dw?e=ji9tew)


* [Ref](https://1drv.ms/b/s!AndI1JV-h1Q5kYsQilw4YRQwvQS-yA?e=copnMw)

#### Nnssf_NSSelection
* [Ref](https://blog.csdn.net/zhonglinzhang/article/details/108166165)
* Comsumer in other PLMN (AMF, NSSF) search (**GET**) the info about network slice in roaming or not in roaming.
* Comsumer find NSSF based on local configuration, or find NSSF in different PLMN based on its own FQDN.
* NSSF use it to provide **Allowed NSSAI** and **Configured NSSAI** of served PLMN to AMF.
* Applied Scenes

* 


#### Nnssf_NSSAIAvailability
* Comsumer (AMF) update the **Supported S-NSSAI** on every [Tracking Area](https://xdxdd.blogspot.com/2012/08/lte-tracking-area-tai-tau-tac.html) of NSSF
* Subscribe or unsubscribe the change notification of
* NSSAI Availability info on each TA.
* Resricted S-NSSAI in every PLMN in the TA of UE served PLMN.

### Info from Terry
* There are some slicing method, one is using multiple UPF, one is using one UPF only.
* The test ref from Terry : [Link](https://1drv.ms/f/s!AndI1JV-h1Q5kYwVSWzGBETacpiY3A?e=uJghQO)
* Ther conclusion for this test is that we can not see the influence of slice seperate by using only one UPF, because different UE can ping each other in different slice.
* UPF is like a router, can assign different sub-domain and set the router to make them able to communication with each other.
#### UCLC

* Ref : [Link](https://free5gc.org/guide/Smf/design/#description), [Link](https://free5gc.org/guide/SMF-Config/#userplane-information), [Link](https://github.com/s5uishida/free5gc_ueransim_ulcl_sample_config)
## PCF
### Study from our content
* The code tracing I done before : [Link](https://hackmd.io/IUW_ewqoTSy3djiAgi7Btg?view#4-Remove-PCF)
* The AMF policy part is useless because it is all about commenting out the error, but didnt solve the panic error.
* The SMF part may be useful, because there are some record of the process of SMF policy creating.
* Note from Rifqi : [Link](https://hackmd.io/@arifadh2003/rkdMlftUA#Understanding-PCF)
* Thers are some info from SPEC, and his own code tracing, but it is not finished.
### Study on SPEC/Background
* AMF policy : [Link](https://blog.csdn.net/zhonglinzhang/article/details/107881343), [R16](https://www.etsi.org/deliver/etsi_ts/129500_129599/129507/16.06.00_60/ts_129507v160600p.pdf)
* SMF policy : [Link](https://blog.csdn.net/zhonglinzhang/article/details/107882933), [R16](https://www.etsi.org/deliver/etsi_ts/129500_129599/129512/16.08.00_60/ts_129512v160800p.pdf)
* PCF : [Series](https://blog.csdn.net/yifei800327/category_12415665.html), [R15](https://www.etsi.org/deliver/etsi_ts/129500_129599/129513/15.03.00_60/ts_129513v150300p.pdf), [R16](https://www.etsi.org/deliver/etsi_ts/129500_129599/129513/16.06.00_60/ts_129513v160600p.pdf), [Framework R15](https://www.etsi.org/deliver/etsi_ts/123500_123599/123503/15.02.00_60/ts_123503v150200p.pdf), [Brief intro 1](https://blog.51cto.com/u_14758357/4725777), [Brief intro 2](https://blog.csdn.net/zhonglinzhang/article/details/107877819)
### BSF
* The function related to PCF.
* [Ref](https://techjunction.co/tech-question/binding-support-function-bsf-in-5g/)
## UDM/UDR
### UDM
* Authentication part has been introduced in AUSF.
* Here just introduces some SDM functions which will be part of the modification in UDM/UDR.
#### UeCmRegistration

#### SdmSubscriptions

### UDR
* You can see it as an **API** between NFs and MongoDB.
* UDM (AUSF) will call it to manage UE auth info.
* PCF will call it to manage policy data.
* AMF will do SDM by calling UDM to call it.
* SMF will get context from UDM calling it.
* ...
## SMF
### IP allocation
[Ref](https://www.sharetechnote.com/html/5G/5G_IP_Allocation.html)
[Ref](https://www.tech-invite.com/3m23/toc/tinv-3gpp-23-501_ze.html)
* I think the IP allocation in CN has many probability, from SMF, UPF, or the DHCP server outside, but in usual E2E test with UERANSIM is from SMF.

# Protocols
NGAP
# Lightweight core
## Before & After
* [Ref](https://1drv.ms/w/s!AndI1JV-h1Q5sGh3kUKtfyAhbWGH?e=vCy3RB)
### Module



### Call flow
* Original




* Lightweight




## Fix the parameter
## Authen. context
## Remove AUSF
### What happen?
### How to repair?
## Remove NSSF
## Remove PCF