iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0

本文目標

  • 認識 SBI
  • 認識 OpenAPI

Service Based Interface

SBI 是由 3GPP 提出的 interface,除了 UPF 以外的 5G NF 都使用 SBI 溝通。

5G SBI Protocols

  • 接受 HTTP/2 作為應用層的 Protocol。
  • 接受 TCP 作為傳輸層的 protocol
  • 接受 JSON 格式作為 serialization protocol
  • REST-style API 設計,每一個 NF 要提供什麼樣的服務、這些服務會由哪些 NF 存取都已經被 3GPP 定義好了。

個人想法:
使用 REST-style API 以及 JSON 應該是為了可讀性,如果想要降低 SBI 的 Latency 或許可以嘗試非 3GPP 定義的作法,像是使用 gRPC 替代之類的。

Example 1

根據 3GPP 的定義,NF 之間的溝通都會依據 SBI (Service Based Interface) 進行實作,以 Nudm_UECM (UECM) service 為例,其他使用該服務的 NF 為 Consumer,提供服務的 UDM 在這裡則扮演 Producer。
如果其他 NF 想要註冊該服務,只需要調用 Nudm_UECM_Registration 即可。

Description: Register UE’s serving NF (if NF Type is AMF, SMSF, or NWDAF) or Session’s serving NF (if NF Type is SMF) on the UDM.

Example 2

SBI 讓 NF 之間可以使用一般的 http 請求溝通,並且 NF 在實作 Producer 的邏輯時,也可以採用 RestFul API 的設計。

Service Based Architecture

參考上圖,SBA(Service Based Architecture)就是整個架構圖上方方格中的骨幹網路。

SBA Service Framework

下方的三張圖片更細的介紹了核心網路中的 Network Functions 如何在 SBA 上溝通:

上圖的範例中,我們可以看到三個 Network Function:

  • AMF(這裡扮演 SBI producer)
  • PCF(扮演 SBI consumer)
  • NRF(NRF 作為 Service discovery 的元件,每一個 SBI 都少不了它的參與)

    觀察上圖,會有幾個部分需要注意:
  • AMF 啟動時向 NRF 發起 NF Service Registration,它的用意是讓 NRF 知道整個核網有這個 AMF 的存在。
  • 接著,我們可以看到已經向 NRF 註冊的 PCF 向 NRF 發起 NF Service Discovery,NRF 會回應 PCF 它想要知道的對象的資訊。

    當 PCF 有了 AMF 的資訊,就能夠向 AMF 發起 http 請求來使用 AMF 提供的 service 囉!

SBA Example NF Services

  • AMF (Access Management Function)
    • Communication – enables other NFs to communication with
      the UE / the access network
    • Mobility Event Exposure – other NFs can subscribe to
      notifications about the UE’s mobility events
  • SMF (Session Management Function)
    • PDUSessions – Protocol Data Units exchange with the UE,
      including policy and charging.
  • UDM (Unified Data Management)
    • Context – provides information about UEs serving NF & status (讓其他 NF 不需要存放 Context,實現無狀態的目的)
    • UEAuthentciation – provides authentication data & info

OpenAPI Generator

先前的文章有介紹到 SBI 是採用 HTTP/2 protocol 作為傳輸協定。
與 HTTP/1.1 相比,它支援 Multiplexing 以及 Header 的壓縮演算法 (HPACK)。並且,HTTP/2 使用 Binary 的方式傳輸,更將節省流量開銷。
不只如此,SBI 更採用了 RESTful API 的設計,讓 NF 與 NF 之間可以使用 HTTP Verb (POST, GET, PUT, DELETE) 溝通,提供了格式統一、簡潔易懂的 URL 操作。

OpenAPI

開放應用程式介面規格 (OAS,OpenAPI Specification) 是讓 Open API 得以被標準化的關鍵,OAS 原先名為 Swagger Specification,由一家名為 SmartBear 的軟體公司所發展,後由開放軟體社群及 Linux 合作贊助推動的 API 技術規格,開發出 OAS 國際標準。
OAS 定義了一套機器可讀的 API 規範,使其可以做更多元的應用。像是建立起互動式的 API 說明文件、產生靜態文件、產生客戶端/伺服器端程式碼架構等。由於 OAS 主要是以 YAML 或 JSON 格式來呈現,這樣的規格檔較為簡潔、輕便,讓我們在運用 OAS 的方式上,不受限於 top-down 或 bottom-up 的開發模式。
-- www.fisc.com.tw

3GPP 也採用了 OpenAPI 格式,讓開發者可以利用轉換工具產生專案的部分程式碼。
我們可以在 3GPP 的網站上找到相關文件與檔案,以 Nsmf_EventExposure 為例,其 OpenAPI 的 Yaml 檔可以在 TS 29.508 取得。

補充:
國外也有開發者針對 3GPP R15 與 R16 整理了 OpenAPI Specification Files,可以參考 5GC_APIs

產生程式碼

前面有提到 3GPP 提供了 OpenAPI Spec Files,有了這些檔案後就能夠搭配 OpenAPI generator 產生 API 相關的程式碼:

$ git clone https://github.com/jdegre/5GC_APIs.git
$ cd 5GC_APIs
$ docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i TS29522_5GLANParameterProvision.yaml -g go-gin-server -o /local/output

上面的範例使用 TS 29.522 5GLANParameterProvision 產生相關程式碼,執行完畢後可以使用以下命令檢查輸出的資料夾結構:

$ tree output

資料夾結構如下:

output
├── Dockerfile
├── api
│   └── openapi.yaml
├── go
│   ├── README.md
│   ├── api_class5_glan_parameters_provision_subscriptions.go
│   ├── api_individual5_glan_parameters_provision_subscription.go
│   ├── model_5_g_lan_parameters.go
│   ├── model_5_g_lan_parameters_patch.go
│   ├── model_5_g_lan_parameters_provision.go
│   ├── model_5_g_lan_parameters_provision_patch.go
│   ├── model_aaa_usage.go
│   ├── model_aaa_usage_any_of.go
│   ├── model_app_descriptor.go
│   ├── model_app_descriptor_rm.go
│   ├── model_invalid_param.go
│   ├── model_ipv6_addr.go
│   ├── model_pdu_session_type.go
│   ├── model_pdu_session_type_any_of.go
│   ├── model_problem_details.go
│   ├── model_snssai.go
│   └── routers.go
└── main.go

讓我們打開其中幾個檔案觀察輸出內容:

/*
 * 3gpp-5glan-pp
 *
 * API for 5G LAN Parameter Provision.   © 2022, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC).   All rights reserved. 
 *
 * API version: 1.1.0-alpha.3
 * Generated by: OpenAPI Generator (https://openapi-generator.tech)
 */

package openapi

// Model5GLanParameters - Represents 5G LAN service related parameters that need to be provisioned.
type Model5GLanParameters struct {

	// string containing a local identifier followed by \"@\" and a domain identifier. Both the local identifier and the domain identifier shall be encoded as strings that do not contain any \"@\" characters. See Clauses 4.6.2 and 4.6.3 of 3GPP TS 23.682 for more information.
	ExterGroupId string `json:"exterGroupId"`

	// Contains the list of 5G VN Group members, each member is identified by GPSI. Any string value can be used as a key of the map. 
	Gpsis map[string]string `json:"gpsis"`

	// String representing a Data Network as defined in clause 9A of 3GPP TS 23.003; it shall contain either a DNN Network Identifier, or a full DNN with both the Network Identifier and Operator Identifier, as specified in 3GPP TS 23.003 clause 9.1.1 and 9.1.2. It shall be coded as string in which the labels are separated by dots (e.g. \"Label1.Label2.Label3\").
	Dnn string `json:"dnn"`

	// String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
	AaaIpv4Addr string `json:"aaaIpv4Addr,omitempty"`

	AaaIpv6Addr Ipv6Addr `json:"aaaIpv6Addr,omitempty"`

	AaaUsgs []AaaUsage `json:"aaaUsgs,omitempty"`

	// String uniquely identifying MTC provider information.
	MtcProviderId string `json:"mtcProviderId,omitempty"`

	Snssai Snssai `json:"snssai"`

	SessionType PduSessionType `json:"sessionType"`

	// Further allowed PDU Session types.
	SessionTypes []PduSessionType `json:"sessionTypes,omitempty"`

	// Describes the operation systems and the corresponding applications for each operation systems. The key of map is osId.
	AppDesps map[string]AppDescriptor `json:"appDesps"`
}
/*
 * 3gpp-5glan-pp
 *
 * API for 5G LAN Parameter Provision.   © 2022, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC).   All rights reserved. 
 *
 * API version: 1.1.0-alpha.3
 * Generated by: OpenAPI Generator (https://openapi-generator.tech)
 */

package openapi

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Route is the information for every URI.
type Route struct {
	// Name is the name of this Route.
	Name        string
	// Method is the string for the HTTP method. ex) GET, POST etc..
	Method      string
	// Pattern is the pattern of the URI.
	Pattern     string
	// HandlerFunc is the handler function of this route.
	HandlerFunc gin.HandlerFunc
}

// Routes is the list of the generated Route.
type Routes []Route

// NewRouter returns a new router.
func NewRouter() *gin.Engine {
	router := gin.Default()
	for _, route := range routes {
		switch route.Method {
		case http.MethodGet:
			router.GET(route.Pattern, route.HandlerFunc)
		case http.MethodPost:
			router.POST(route.Pattern, route.HandlerFunc)
		case http.MethodPut:
			router.PUT(route.Pattern, route.HandlerFunc)
		case http.MethodPatch:
			router.PATCH(route.Pattern, route.HandlerFunc)
		case http.MethodDelete:
			router.DELETE(route.Pattern, route.HandlerFunc)
		}
	}

	return router
}

// Index is the index handler.
func Index(c *gin.Context) {
	c.String(http.StatusOK, "Hello World!")
}

var routes = Routes{
	{
		"Index",
		http.MethodGet,
		"/3gpp-5glan-pp/v1/",
		Index,
	},

	{
		"AfIdSubscriptionsGet",
		http.MethodGet,
		"/3gpp-5glan-pp/v1/:afId/subscriptions",
		AfIdSubscriptionsGet,
	},

	{
		"AfIdSubscriptionsPost",
		http.MethodPost,
		"/3gpp-5glan-pp/v1/:afId/subscriptions",
		AfIdSubscriptionsPost,
	},

	{
		"AfIdSubscriptionsSubscriptionIdDelete",
		http.MethodDelete,
		"/3gpp-5glan-pp/v1/:afId/subscriptions/:subscriptionId",
		AfIdSubscriptionsSubscriptionIdDelete,
	},

	{
		"AfIdSubscriptionsSubscriptionIdGet",
		http.MethodGet,
		"/3gpp-5glan-pp/v1/:afId/subscriptions/:subscriptionId",
		AfIdSubscriptionsSubscriptionIdGet,
	},

	{
		"AfIdSubscriptionsSubscriptionIdPatch",
		http.MethodPatch,
		"/3gpp-5glan-pp/v1/:afId/subscriptions/:subscriptionId",
		AfIdSubscriptionsSubscriptionIdPatch,
	},

	{
		"AfIdSubscriptionsSubscriptionIdPut",
		http.MethodPut,
		"/3gpp-5glan-pp/v1/:afId/subscriptions/:subscriptionId",
		AfIdSubscriptionsSubscriptionIdPut,
	},
}
  • 觀察輸出的檔案不難發現:Code generator 已經把這個 API 會使用到的 struct、router、handler 的骨幹都產生出來了。
  • 有了這些基本的程式碼能夠加快每一個 API feature 的開發速度(只需要再去翻閱相關的規格書並將細節實作出來,不需要浪費時間去定義相關的成員結構以及 API 路由)。

Reference


上一篇
5G Identifier & Network Slicing
下一篇
5G State Management
系列文
5G 核心網路與雲原生開發之亂彈阿翔36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言