free5gc + UERANSIM でUPF Selectionしてみた

今回はNSSAI値によるUPF Selectionを試してみる。想定としては、SST=1の時はUPF1経由（60.60.0.0/24払い出し）、SST=2の時にはUPF2経由(60.70.0.0/24払い出し)での外部との疎通が可能となる感じ。
前回との構築差分としては下記。
・2台目UPF用VM作成(upf.yaml作成含む)
・smf.yaml編集(2台目UPFの設定追加)
・ue.yaml編集(NSSAI変更)

# 環境
- HW
    - MacbookPro(2020)
        - OS : Monterey(12.1)
    - CPU : 2GHz クアッドコアIntel Core i5
    - Memory : 16GB
- SW
    - VirtualBox 6.1.32
        - Ubuntu 18.04 (5.4.0-87-generic)
    - free5gc 3.0.6
    - UERANSIM 3.25
- 構成
![k.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83723/169b7297-4147-7e5b-aeef-35cb42c29121.png)


# 構築
### 1. 2台目UPF構築
前回と同様にVMを複製して作成。UPF用のVMを複製して構成に合わせる形で適宜アドレス等変更を実施。
2台目UPF用としてupf.yamlを下記のように変更。
・pfcp: をVMのenp0s9アドレスに変更
・cidr: 払い出すIPアドレスをupf2用に変更

```diff
root@upf2:~/free5gc/config# diff -u upfcfg.yaml.org upfcfg.yaml
--- upfcfg.yaml.org	2022-02-06 09:25:18.249000000 -0500
+++ upfcfg.yaml	2022-02-09 23:51:40.617002331 -0500
@@ -15,12 +15,12 @@
 
   # The IP list of the N4 interface on this UPF (Can't set to 0.0.0.0)
   pfcp:
-    - addr: 127.0.0.8
+    - addr: 192.168.100.201
 
   # The IP list of the N3/N9 interfaces on this UPF
   # If there are multiple connection, set addr to 0.0.0.0 or list all the addresses
   gtpu:
-    - addr: 127.0.0.8
+    - addr: 0.0.0.0
     # [optional] gtpu.name
     # - name: upf.5gc.nctu.me
     # [optional] gtpu.ifname
@@ -29,6 +29,6 @@
   # The DNN list supported by UPF
   dnn_list:
     - dnn: internet # Data Network Name
-      cidr: 60.60.0.0/24 # Classless Inter-Domain Routing for assigned IPv4 pool of UE
+      cidr: 60.70.0.0/24 # Classless Inter-Domain Routing for assigned IPv4 pool of UE
       # [optional] dnn_list[*].natifname
       # natifname: eth0
```

### 2.SMF設定変更
1つのSMFに二つUPFを紐づける設定変更を実施する。下記差分は前回のsmf.yamlとのdiff
・snssaiInfos:にsst=2/sd=010203分を追加
・userplane_information:のUPF記載をUPF1/UPF2それぞれ分に変更
・links:のgNB1/UPF記載をgNB1/UPF1, gNB1/UPF2に変更
・ulcl:をfalseで記載

```diff
root@f5g:~/free5gc/config# diff -u smfcfg.yaml.org smfcfg.yaml
--- smfcfg.yaml.org	2022-02-09 23:38:54.898997260 -0500
+++ smfcfg.yaml	2022-02-10 04:26:34.020002516 -0500
@@ -31,6 +31,13 @@
         - dnn: internet # Data Network Name
           dns: # the IP address of DNS
             ipv4: 8.8.8.8
+    - sNssai:
+        sst: 2
+        sd: 010203
+      dnnInfos:
+        - dnn: internet
+          dns:
+            ipv4: 8.8.8.8
   plmnList: # the list of PLMN IDs that this SMF belongs to (optional, remove this key when unnecessary)
     - mcc: "208" # Mobile Country Code (3 digits string, digit: 0~9)
       mnc: "93" # Mobile Network Code (2 or 3 digits string, digit: 0~9)
@@ -40,7 +47,7 @@
     up_nodes: # information of userplane node (AN or UPF)
       gNB1: # the name of the node
         type: AN # the type of the node (AN or UPF)
-      UPF:  # the name of the node
+      UPF1:  # the name of the node
         type: UPF # the type of the node (AN or UPF)
         node_id: 192.168.100.200 # the IP/FQDN of N4 interface on this UPF (PFCP)
         sNssaiUpfInfos: # S-NSSAI information list for this UPF
@@ -51,6 +58,22 @@
               - dnn: internet
                 pools:
                   - cidr: 60.60.0.0/16
+        interfaces: # Interface list for this UPF
+          - interfaceType: N3 # the type of the interface (N3 or N9)
+            endpoints: # the IP address of this N3/N9 interface on this UPF
+              - 192.168.100.200
+            networkInstance: internet # Data Network Name (DNN)
+      UPF2:
+        type: UPF
+        node_id: 192.168.100.201
+        sNssaiUpfInfos:
+          - sNssai:
+              sst: 2
+              sd: 010203
+            dnnUpfInfoList:
+              - dnn: internet
+                pools:
+                  - cidr: 60.70.0.0/16
           - sNssai: # S-NSSAI (Single Network Slice Selection Assistance Information)
               sst: 1 # Slice/Service Type (uinteger, range: 0~255)
               sd: 112233 # Slice Differentiator (3 bytes hex string, range: 000000~FFFFFF)
@@ -58,16 +81,19 @@
               - dnn: internet
                 pools:
                   - cidr: 60.61.0.0/16
-        interfaces: # Interface list for this UPF
-          - interfaceType: N3 # the type of the interface (N3 or N9)
-            endpoints: # the IP address of this N3/N9 interface on this UPF
-              - 192.168.100.200
-            networkInstance: internet # Data Network Name (DNN)
+        interfaces:
+          - interfaceType: N3
+            endpoints:
+              - 192.168.100.201
+            networkInstance: internet 
     links: # the topology graph of userplane, A and B represent the two nodes of each link
       - A: gNB1
-        B: UPF
+        B: UPF1
+      - A: gNB1
+        B: UPF2
   nrfUri: http://127.0.0.10:8000 # a valid URI of NRF
   locality: area1 # Name of the location where a set of AMF, SMF and UPFs are located
+  ulcl: false
 
 # the kind of log output
   # debugLevel: how detailed to output, value: trace, debug, info, warn, error, fatal, panic
```

2台のUPFとコアを起動させ、2台のUPF上で「[PFCP] Association Setup Response」が表示されていれば、1台のSMFに対して2台にUPFが接続されている状態となる。

### 3.加入者情報変更
webconsole上から既に登録済みのSUPIに対してS-NSSAIとしてSST=2/SD=010203を追加
![l.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83723/09cc724d-3492-082f-cfa4-e7eb52e3f5ec.png)

### 4. UEファイル変更
UERANSIMのfree5gc-ue.yamlファイルのNSSAIの値を変更
・sessions: sliceのsstを0x02に変更
・configured-nssai: のsstを0x02に変更
※NSSAIのCongigured NSSAIとかDefault-NSSAIとか辺りは全く理解できてないのでどこかでまとめて整理

```diff
root@ueran:~/UERANSIM/config# diff -u free5gc-ue.yaml free5gc-ue2.yaml 
--- free5gc-ue.yaml	2022-02-06 08:28:12.943660003 -0500
+++ free5gc-ue2.yaml	2022-02-10 02:16:48.987000000 -0500
@@ -41,12 +41,12 @@
   - type: 'IPv4'
     apn: 'internet'
     slice:
-      sst: 0x01
+      sst: 0x02
       sd: 0x010203
 
 # Configured NSSAI for this UE by HPLMN
 configured-nssai:
-  - sst: 0x01
+  - sst: 0x02
     sd: 0x010203
 
 # Default Configured NSSAI for this UE
root@ueran:~/UERANSIM/config# 
```

これで、SST=1の時には60.60.0.0/24からアドレスが払い出され、upf1経由で通信が行われる。
SST=2の時には60.70.0.0/24からアドレスが払い出され、upf2経由で通信が行われる。

# 確認
まずは払い出しアドレス確認
```
root@ueran:~# ip a

### 省略 ###

5: uesimtun0: <POINTOPOINT,PROMISC,NOTRAILERS,UP,LOWER_UP> mtu 1400 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none 
    inet 60.70.0.1/32 scope global uesimtun0
       valid_lft forever preferred_lft forever
    inet6 fe80::57f2:1c61:98e6:c501/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever
```

前回は60.60.0.1/32が払い出されていたが、今回は60.70.0.1/32が払い出されている。

ping結果
```
root@ueran:~/UERANSIM/config# ping 8.8.8.8 -I uesimtun0
PING 8.8.8.8 (8.8.8.8) from 60.70.0.1 uesimtun0: 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=61 time=180 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=61 time=241 ms
```

問題なし。パケットでも確認。
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83723/62eea2f2-0dfb-0583-5863-6b037097ff55.png)
outer-headerのIP src:192.168.100.10はRAN側VM、dst:192.168.100.201はUPF2
inner-headerのIP src:60.70.0.1はUE払い出しアドレス

ついでなのでngapパケットも確認
![aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83723/948d4558-5685-bb3e-7e95-e04b0973e56b.png)
TranportLayerAddressにupf2のN3アドレスが格納されている。
これまたついでだが、このときにgtp-TEIDも通知される。このTEIDによってC-Plane通信とU-plane通信が紐づく。
今回は0000003であり、pingのgtpヘッダ上のTEIDもちゃんと0000003である。
※再接続したので払い出されたIPアドレスは変わっている。
![bbb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83723/f587ff5b-b804-f89c-c90a-4e3f3180f73b.png)

次回の予定はSMF Selection。