From f5f5887ef870e9a705bdb82d5ed7cbb9e917e7ef Mon Sep 17 00:00:00 2001 From: free5gc-org Date: Tue, 28 Apr 2020 00:30:59 +0800 Subject: [PATCH 1/7] Init commit --- .gitignore | 19 + AMPolicy/api_default.go | 93 + AMPolicy/api_default_test.go | 340 ++++ AMPolicy/routers.go | 101 ++ .../api_bdt_policies_collection_routers.go | 37 + ...pi_bdt_policies_collection_routers_test.go | 140 ++ ..._individual_bdt_policy_document_routers.go | 45 + ...vidual_bdt_policy_document_routers_test.go | 87 + BDTPolicy/routers.go | 94 + CHANGELOG.md | 9 + HttpCallback/AMFStatusChangeNotify.go | 36 + HttpCallback/SMPolicyNotify.go | 27 + HttpCallback/router.go | 70 + OAM/api_get_am_policy.go | 30 + OAM/routers.go | 62 + .../api_application_sessions_collection.go | 52 + ...pi_application_sessions_collection_test.go | 302 ++++ .../api_events_subscription_document.go | 62 + .../api_events_subscription_document_test.go | 157 ++ ...al_application_session_context_document.go | 69 + ...plication_session_context_document_test.go | 317 ++++ PolicyAuthorization/routers.go | 115 ++ SMPolicy/api_default.go | 88 + SMPolicy/api_default_test.go | 658 +++++++ SMPolicy/routers.go | 101 ++ UEPolicy/api_default.go | 34 + UEPolicy/routers.go | 93 + factory/config_config.go | 11 + factory/config_configuration.go | 24 + factory/config_info.go | 11 + factory/config_sbi.go | 12 + factory/factory.go | 36 + logger/logger.go | 71 + pcf.go | 51 + pcf_consumer/Communication.go | 47 + pcf_consumer/NFDiscovery.go | 105 ++ pcf_consumer/NFManagement.go | 73 + pcf_consumer/NFManagement_test.go | 50 + pcf_context/context.go | 285 +++ pcf_context/ue.go | 436 +++++ pcf_handler/handler.go | 93 + pcf_handler/handler_test.go | 40 + pcf_handler/pcf_message/channel.go | 23 + pcf_handler/pcf_message/event.go | 24 + pcf_handler/pcf_message/message.go | 125 ++ pcf_producer/HandleSmPolicyNotify.go | 74 + pcf_producer/callback.go | 15 + pcf_producer/oam.go | 55 + pcf_producer/pcf_ampolicy.go | 315 ++++ pcf_producer/pcf_bdtpolicy.go | 193 ++ pcf_producer/pcf_policyauthorization.go | 1571 +++++++++++++++++ pcf_producer/pcf_smpolicy.go | 789 +++++++++ pcf_service/pcf_init.go | 224 +++ pcf_util/convert.go | 63 + pcf_util/initContext.go | 48 + pcf_util/pcc_rule.go | 217 +++ pcf_util/pcf_util.go | 250 +++ pcf_util/search_nfService.go | 50 + version/version.go | 7 + 59 files changed, 8626 insertions(+) create mode 100644 .gitignore create mode 100644 AMPolicy/api_default.go create mode 100644 AMPolicy/api_default_test.go create mode 100644 AMPolicy/routers.go create mode 100644 BDTPolicy/api_bdt_policies_collection_routers.go create mode 100644 BDTPolicy/api_bdt_policies_collection_routers_test.go create mode 100644 BDTPolicy/api_individual_bdt_policy_document_routers.go create mode 100644 BDTPolicy/api_individual_bdt_policy_document_routers_test.go create mode 100644 BDTPolicy/routers.go create mode 100644 CHANGELOG.md create mode 100644 HttpCallback/AMFStatusChangeNotify.go create mode 100644 HttpCallback/SMPolicyNotify.go create mode 100644 HttpCallback/router.go create mode 100644 OAM/api_get_am_policy.go create mode 100644 OAM/routers.go create mode 100644 PolicyAuthorization/api_application_sessions_collection.go create mode 100644 PolicyAuthorization/api_application_sessions_collection_test.go create mode 100644 PolicyAuthorization/api_events_subscription_document.go create mode 100644 PolicyAuthorization/api_events_subscription_document_test.go create mode 100644 PolicyAuthorization/api_individual_application_session_context_document.go create mode 100644 PolicyAuthorization/api_individual_application_session_context_document_test.go create mode 100644 PolicyAuthorization/routers.go create mode 100644 SMPolicy/api_default.go create mode 100644 SMPolicy/api_default_test.go create mode 100644 SMPolicy/routers.go create mode 100644 UEPolicy/api_default.go create mode 100644 UEPolicy/routers.go create mode 100644 factory/config_config.go create mode 100644 factory/config_configuration.go create mode 100644 factory/config_info.go create mode 100644 factory/config_sbi.go create mode 100644 factory/factory.go create mode 100644 logger/logger.go create mode 100644 pcf.go create mode 100644 pcf_consumer/Communication.go create mode 100644 pcf_consumer/NFDiscovery.go create mode 100644 pcf_consumer/NFManagement.go create mode 100644 pcf_consumer/NFManagement_test.go create mode 100644 pcf_context/context.go create mode 100644 pcf_context/ue.go create mode 100644 pcf_handler/handler.go create mode 100644 pcf_handler/handler_test.go create mode 100644 pcf_handler/pcf_message/channel.go create mode 100644 pcf_handler/pcf_message/event.go create mode 100644 pcf_handler/pcf_message/message.go create mode 100644 pcf_producer/HandleSmPolicyNotify.go create mode 100644 pcf_producer/callback.go create mode 100644 pcf_producer/oam.go create mode 100644 pcf_producer/pcf_ampolicy.go create mode 100644 pcf_producer/pcf_bdtpolicy.go create mode 100644 pcf_producer/pcf_policyauthorization.go create mode 100644 pcf_producer/pcf_smpolicy.go create mode 100644 pcf_service/pcf_init.go create mode 100644 pcf_util/convert.go create mode 100644 pcf_util/initContext.go create mode 100644 pcf_util/pcc_rule.go create mode 100644 pcf_util/pcf_util.go create mode 100644 pcf_util/search_nfService.go create mode 100644 version/version.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6729600 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Toolchain +# Goland project folder +.idea/ +# Visual Studio Code +.vscode/ +# emacs/vim +GPATH +GRTAGS +GTAGS +TAGS +tags +cscope.* +# mac +.DS_Store + +# debug +*.log +*.pcap + diff --git a/AMPolicy/api_default.go b/AMPolicy/api_default.go new file mode 100644 index 0000000..095d0d4 --- /dev/null +++ b/AMPolicy/api_default.go @@ -0,0 +1,93 @@ +/* + * Npcf_AMPolicyControl + * + * Access and Mobility Policy Control Service API + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package AMPolicy + +import ( + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/pcf_util" + + "github.com/gin-gonic/gin" +) + +func PoliciesPolAssoIdDelete(c *gin.Context) { + req := http_wrapper.NewRequest(c.Request, nil) + req.Params["polAssoId"], _ = c.Params.Get("polAssoId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMPolicyDelete, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} + +// PoliciesPolAssoIdGet - +func PoliciesPolAssoIdGet(c *gin.Context) { + req := http_wrapper.NewRequest(c.Request, nil) + req.Params["polAssoId"], _ = c.Params.Get("polAssoId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMPolicyGet, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) + +} + +// PoliciesPolAssoIdUpdatePost - +func PoliciesPolAssoIdUpdatePost(c *gin.Context) { + var policyAssociationUpdateRequest models.PolicyAssociationUpdateRequest + err := c.ShouldBindJSON(&policyAssociationUpdateRequest) + if err != nil { + rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.HandlerLog.Errorln(rsp.Detail) + c.JSON(int(rsp.Status), rsp) + return + } + req := http_wrapper.NewRequest(c.Request, policyAssociationUpdateRequest) + req.Params["polAssoId"], _ = c.Params.Get("polAssoId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMPolicyUpdate, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} + +// PoliciesPost - +func PoliciesPost(c *gin.Context) { + var policyAssociationRequest models.PolicyAssociationRequest + err := c.ShouldBindJSON(&policyAssociationRequest) + if err != nil { + rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.HandlerLog.Errorln(rsp.Detail) + c.JSON(int(rsp.Status), rsp) + return + } + if policyAssociationRequest.Supi == "" || policyAssociationRequest.NotificationUri == "" { + rsp := pcf_util.GetProblemDetail("Miss Mandotory IE", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.HandlerLog.Errorln(rsp.Detail) + c.JSON(int(rsp.Status), rsp) + return + } + req := http_wrapper.NewRequest(c.Request, policyAssociationRequest) + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMPolicyCreate, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + for key, val := range HTTPResponse.Header { + c.Header(key, val[0]) + } + c.JSON(HTTPResponse.Status, HTTPResponse.Body) + +} diff --git a/AMPolicy/api_default_test.go b/AMPolicy/api_default_test.go new file mode 100644 index 0000000..6a30f7d --- /dev/null +++ b/AMPolicy/api_default_test.go @@ -0,0 +1,340 @@ +package AMPolicy_test + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "github.com/gin-gonic/gin" + "go.mongodb.org/mongo-driver/bson" + "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" + "free5gc/lib/MongoDBLibrary" + "free5gc/lib/Npcf_AMPolicy" + "free5gc/lib/http2_util" + "free5gc/lib/openapi/common" + "free5gc/lib/openapi/models" + "free5gc/lib/path_util" + "free5gc/src/amf/amf_service" + "free5gc/src/app" + "free5gc/src/nrf/nrf_service" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_producer" + "free5gc/src/pcf/pcf_service" + "free5gc/src/udr/udr_service" + "net/http" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/urfave/cli" +) + +const amPolicyDataColl = "policyData.ues.amData" + +var NFs = []app.NetworkFunction{ + &nrf_service.NRF{}, + &amf_service.AMF{}, + &udr_service.UDR{}, + &pcf_service.PCF{}, +} + +var filterUeIdOnly bson.M + +func init() { + app.AppInitializeWillInitialize("") + flag := flag.FlagSet{} + cli := cli.NewContext(nil, &flag, nil) + for _, service := range NFs { + service.Initialize(cli) + go service.Start() + time.Sleep(300 * time.Millisecond) + } + insertDefaultAmPolicyToDb("imsi-2089300007487") + +} +func toBsonM(data interface{}) bson.M { + tmp, _ := json.Marshal(data) + var putData = bson.M{} + _ = json.Unmarshal(tmp, &putData) + return putData +} +func insertDefaultAmPolicyToDb(ueId string) { + amPolicyData := models.AmPolicyData{ + SubscCats: []string{ + "free5gc", + }, + } + filterUeIdOnly = bson.M{"ueId": ueId} + amPolicyDataBsonM := toBsonM(amPolicyData) + amPolicyDataBsonM["ueId"] = ueId + MongoDBLibrary.RestfulAPIPutOne(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM) +} +func TestCreateAMPolicy(t *testing.T) { + + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + client := Npcf_AMPolicy.NewAPIClient(configuration) + + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + { + amCreateReqData := TestAMPolicy.GetamCreatefailnotifyURIData() + _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err != nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) + problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + assert.Equal(t, "ERROR_REQUEST_PARAMETERS", problem.Cause) + assert.Equal(t, "Miss Mandotory IE", problem.Detail) + } + } + { + amCreateReqData := TestAMPolicy.GetamCreatefailsupiData() + _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err != nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) + problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + assert.Equal(t, "ERROR_REQUEST_PARAMETERS", problem.Cause) + assert.Equal(t, "Supi Format Error", problem.Detail) + } + } + +} + +func TestGetAMPolicy(t *testing.T) { + + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + client := Npcf_AMPolicy.NewAPIClient(configuration) + + amCreateReqData := TestAMPolicy.GetAMreqdata() + polAssoId := "imsi-2089300007487-1" + //Test PostPolicies + { + _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId = locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + { + //Test GetPoliciesPolAssoId + rsp, httpRsp, err := client.DefaultApi.PoliciesPolAssoIdGet(context.Background(), polAssoId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + assert.Equal(t, amCreateReqData.SuppFeat, rsp.SuppFeat) + assert.Equal(t, amCreateReqData.ServAreaRes, rsp.ServAreaRes) + assert.Equal(t, amCreateReqData.Rfsp, rsp.Rfsp) + assert.True(t, rsp.Triggers == nil) + assert.True(t, rsp.Pras == nil) + } + } + +} + +func TestDelAMPolicy(t *testing.T) { + + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + client := Npcf_AMPolicy.NewAPIClient(configuration) + + amCreateReqData := TestAMPolicy.GetAMreqdata() + polAssoId := "imsi-2089300007487-1" + //Test PostPolicies + { + _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId = locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + { + //Test DelPoliciesPolAssoId + httpRsp, err := client.DefaultApi.PoliciesPolAssoIdDelete(context.Background(), polAssoId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) + } + } + { + //Test GetPoliciesPolAssoId + _, httpRsp, err := client.DefaultApi.PoliciesPolAssoIdGet(context.Background(), polAssoId) + assert.True(t, err != nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusNotFound, httpRsp.StatusCode) + problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + assert.Equal(t, "CONTEXT_NOT_FOUND", problem.Cause) + } + } + +} + +func TestUpdateAMPolicy(t *testing.T) { + + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + client := Npcf_AMPolicy.NewAPIClient(configuration) + + amCreateReqData := TestAMPolicy.GetAMreqdata() + polAssoId := "imsi-2089300007487-1" + //Test PostPolicies + { + _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId = locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + updateReq := TestAMPolicy.GetAMUpdateReqData() + { + //Test UpdatePoliciesPolAssoId + rsp, httpRsp, err := client.DefaultApi.PoliciesPolAssoIdUpdatePost(context.Background(), polAssoId, updateReq) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + assert.Equal(t, updateReq.ServAreaRes, rsp.ServAreaRes) + assert.Equal(t, updateReq.Rfsp, rsp.Rfsp) + assert.True(t, rsp.Triggers == nil) + assert.True(t, rsp.Pras == nil) + } + } +} + +func TestAMPolicyNotification(t *testing.T) { + + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + client := Npcf_AMPolicy.NewAPIClient(configuration) + go func() { // fake udr server + router := gin.Default() + + router.POST("/namf-callback/v1/am-policy/:polAssoId/update", func(c *gin.Context) { + polAssoId := c.Param("polAssoId") + fmt.Println("==========AMF Policy Association Update Callback=============") + fmt.Println("polAssoId: ", polAssoId) + + var policyUpdate models.PolicyUpdate + if err := c.ShouldBindJSON(&policyUpdate); err != nil { + fmt.Println("fake amf server error") + c.JSON(http.StatusInternalServerError, gin.H{}) + return + } + c.JSON(http.StatusNoContent, gin.H{}) + }) + + router.POST("/namf-callback/v1/am-policy/:polAssoId/terminate", func(c *gin.Context) { + polAssoId := c.Param("polAssoId") + fmt.Println("==========AMF Policy Association Terminate Callback=============") + fmt.Println("polAssoId: ", polAssoId) + + var terminationNotification models.TerminationNotification + if err := c.ShouldBindJSON(&terminationNotification); err != nil { + fmt.Println("fake amf server error") + c.JSON(http.StatusInternalServerError, gin.H{}) + return + } + c.JSON(http.StatusNoContent, gin.H{}) + httpRsp, err := client.DefaultApi.PoliciesPolAssoIdDelete(context.Background(), polAssoId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) + } + }) + + amfLogPath := path_util.Gofree5gcPath("free5gc/amfsslkey.log") + amfPemPath := path_util.Gofree5gcPath("free5gc/support/TLS/amf.pem") + amfKeyPath := path_util.Gofree5gcPath("free5gc/support/TLS/amf.key") + + server, err := http2_util.NewServer(":8888", amfLogPath, router) + if err == nil && server != nil { + logger.InitLog.Infoln(server.ListenAndServeTLS(amfPemPath, amfKeyPath)) + } + assert.True(t, err == nil) + }() + + time.Sleep(100 * time.Millisecond) + + var polAssoId string + amCreateReqData := TestAMPolicy.GetAMreqdata() + amCreateReqData.NotificationUri = "https://127.0.0.1:8888/namf-callback/v1/am-policy/imsi-2089300007487-1" + //Test PostPolicies + { + _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId = locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] + //Test Policies Update Notify + policyUpdate := models.PolicyUpdate{ + ResourceUri: amCreateReqData.NotificationUri, + } + pcf_producer.SendAMPolicyUpdateNotification(ue, polAssoId, policyUpdate) + + //Test Policies Termination Notify + notification := models.TerminationNotification{ + ResourceUri: amCreateReqData.NotificationUri, + Cause: models.PolicyAssociationReleaseCause_UNSPECIFIED, + } + pcf_producer.SendAMPolicyTerminationRequestNotification(ue, polAssoId, notification) + + time.Sleep(200 * time.Millisecond) +} diff --git a/AMPolicy/routers.go b/AMPolicy/routers.go new file mode 100644 index 0000000..eaba30f --- /dev/null +++ b/AMPolicy/routers.go @@ -0,0 +1,101 @@ +/* + * Npcf_AMPolicyControl + * + * Access and Mobility Policy Control Service API + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package AMPolicy + +import ( + "net/http" + "strings" + + "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() + AddService(router) + return router +} + +func AddService(engine *gin.Engine) *gin.RouterGroup { + group := engine.Group("/npcf-am-policy-control/v1") + + for _, route := range routes { + switch route.Method { + case "GET": + group.GET(route.Pattern, route.HandlerFunc) + case "POST": + group.POST(route.Pattern, route.HandlerFunc) + case "PUT": + group.PUT(route.Pattern, route.HandlerFunc) + case "DELETE": + group.DELETE(route.Pattern, route.HandlerFunc) + case "PATCH": + group.PATCH(route.Pattern, route.HandlerFunc) + } + } + return group +} + +// Index is the index handler. +func Index(c *gin.Context) { + c.String(http.StatusOK, "Hello World!") +} + +var routes = Routes{ + { + "Index", + "GET", + "/", + Index, + }, + + { + "PoliciesPolAssoIdDelete", + strings.ToUpper("Delete"), + "/policies/:polAssoId", + PoliciesPolAssoIdDelete, + }, + + { + "PoliciesPolAssoIdGet", + strings.ToUpper("Get"), + "/policies/:polAssoId", + PoliciesPolAssoIdGet, + }, + + { + "PoliciesPolAssoIdUpdatePost", + strings.ToUpper("Post"), + "/policies/:polAssoId/update", + PoliciesPolAssoIdUpdatePost, + }, + + { + "PoliciesPost", + strings.ToUpper("Post"), + "/policies", + PoliciesPost, + }, +} diff --git a/BDTPolicy/api_bdt_policies_collection_routers.go b/BDTPolicy/api_bdt_policies_collection_routers.go new file mode 100644 index 0000000..662db20 --- /dev/null +++ b/BDTPolicy/api_bdt_policies_collection_routers.go @@ -0,0 +1,37 @@ +/* + * Npcf_BDTPolicyControl Service API + * + * The Npcf_BDTPolicyControl Service is used by an NF service consumer to retrieve background data transfer policies from the PCF and to update the PCF with the background data transfer policy selected by the NF service consumer. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package BDTPolicy + +import ( + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/pcf_handler/pcf_message" + + "github.com/gin-gonic/gin" +) + +//CreateBDTPolicy - Create a new Individual BDT policy +func CreateBDTPolicy(c *gin.Context) { + var bdtReqData models.BdtReqData + c.ShouldBindJSON(&bdtReqData) + + req := http_wrapper.NewRequest(c.Request, bdtReqData) + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventBDTPolicyCreate, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + + for key, val := range HTTPResponse.Header { + c.Header(key, val[0]) + } + + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} diff --git a/BDTPolicy/api_bdt_policies_collection_routers_test.go b/BDTPolicy/api_bdt_policies_collection_routers_test.go new file mode 100644 index 0000000..a704ffe --- /dev/null +++ b/BDTPolicy/api_bdt_policies_collection_routers_test.go @@ -0,0 +1,140 @@ +package BDTPolicy_test + +import ( + "context" + "flag" + "fmt" + "github.com/davecgh/go-spew/spew" + "github.com/gin-gonic/gin" + "go.mongodb.org/mongo-driver/bson" + TestBDTPolicy "free5gc/lib/CommonConsumerTestData/PCF/TestBDTPolicy" + "free5gc/lib/MongoDBLibrary" + "free5gc/lib/Npcf_BDTPolicyControl" + "free5gc/lib/http2_util" + "free5gc/lib/openapi/models" + "free5gc/lib/path_util" + "free5gc/src/app" + "free5gc/src/nrf/nrf_service" + "free5gc/src/pcf/pcf_service" + "free5gc/src/udr/DataRepository" + "free5gc/src/udr/factory" + "free5gc/src/udr/logger" + "free5gc/src/udr/udr_consumer" + "free5gc/src/udr/udr_service" + "free5gc/src/udr/udr_util" + "log" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/urfave/cli" +) + +var NFs = []app.NetworkFunction{ + &nrf_service.NRF{}, + &udr_service.UDR{}, + &pcf_service.PCF{}, +} + +func fakeudrInit() { + config := factory.UdrConfig + sbi := config.Configuration.Sbi + mongodb := config.Configuration.Mongodb + nrfUri := config.Configuration.NrfUri + + // Connect to MongoDB + DataRepository.SetMongoDB(mongodb.Name, mongodb.Url) + + udrLogPath := udr_util.UdrLogPath + udrPemPath := udr_util.UdrPemPath + udrKeyPath := udr_util.UdrKeyPath + if sbi.Tls != nil { + udrLogPath = path_util.Gofree5gcPath(sbi.Tls.Log) + udrPemPath = path_util.Gofree5gcPath(sbi.Tls.Pem) + udrKeyPath = path_util.Gofree5gcPath(sbi.Tls.Key) + } + + profile := udr_consumer.BuildNFInstance() + newNrfUri, _, err := udr_consumer.SendRegisterNFInstance(nrfUri, profile.NfInstanceId, profile) + if err == nil { + config.Configuration.NrfUri = newNrfUri + } else { + fmt.Errorf("Send Register NFInstance Error[%s]", err.Error()) + } + go func() { // fake udr server + router := gin.Default() + + router.GET("/nudr-dr/v1/policy-data/bdt-data", func(c *gin.Context) { + fmt.Println("==========GET BDT Policy Data==========") + rsp := []models.BdtData{} + c.JSON(http.StatusOK, rsp) + }) + router.PUT("/nudr-dr/v1/policy-data/bdt-data/:bdtReferenceId", func(c *gin.Context) { + bdtReferenceId := c.Param("bdtReferenceId") + fmt.Println("==========PUT BDT Policy Data==========") + fmt.Println("bdtReferenceId: ", bdtReferenceId) + var bdtData models.BdtData + + if err := c.ShouldBindJSON(&bdtData); err != nil { + log.Panic(err.Error()) + } + spew.Dump(bdtData) + }) + server, err := http2_util.NewServer(":29504", udrLogPath, router) + if err == nil && server != nil { + logger.InitLog.Infoln(server.ListenAndServeTLS(udrPemPath, udrKeyPath)) + } + }() +} + +func init() { + app.AppInitializeWillInitialize("") + flag := flag.FlagSet{} + cli := cli.NewContext(nil, &flag, nil) + for i, service := range NFs { + if i == 1 { + service.Initialize(cli) + fakeudrInit() + } else { + service.Initialize(cli) + go service.Start() + } + time.Sleep(300 * time.Millisecond) + if i == 0 { + MongoDBLibrary.RestfulAPIDeleteMany("NfProfile", bson.M{}) + time.Sleep(300 * time.Millisecond) + } + } +} +func TestCreateBDTPolicy(t *testing.T) { + + configuration := Npcf_BDTPolicyControl.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + client := Npcf_BDTPolicyControl.NewAPIClient(configuration) + + // get test data + bdtReqData := TestBDTPolicy.GetCreateTestData() + + // test create service + rsp, httpRsp, err := client.BDTPoliciesCollectionApi.CreateBDTPolicy(context.Background(), bdtReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) { + if assert.NotNil(t, rsp.BdtReqData) { + assert.Equal(t, *rsp.BdtReqData, bdtReqData) + } + if assert.NotNil(t, rsp.BdtPolData) { + assert.True(t, rsp.BdtPolData.SelTransPolicyId == 1) + assert.Equal(t, rsp.BdtPolData.SuppFeat, "") + if assert.True(t, len(rsp.BdtPolData.TransfPolicies) == 1) { + assert.Equal(t, rsp.BdtPolData.TransfPolicies[0], models.TransferPolicy{ + RatingGroup: 1, + RecTimeInt: bdtReqData.DesTimeInt, + TransPolicyId: 1, + }) + } + } + } + time.Sleep(30 * time.Millisecond) +} diff --git a/BDTPolicy/api_individual_bdt_policy_document_routers.go b/BDTPolicy/api_individual_bdt_policy_document_routers.go new file mode 100644 index 0000000..5e3e0c9 --- /dev/null +++ b/BDTPolicy/api_individual_bdt_policy_document_routers.go @@ -0,0 +1,45 @@ +/* + * Npcf_BDTPolicyControl Service API + * + * The Npcf_BDTPolicyControl Service is used by an NF service consumer to retrieve background data transfer policies from the PCF and to update the PCF with the background data transfer policy selected by the NF service consumer. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package BDTPolicy + +import ( + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/pcf_handler/pcf_message" + + "github.com/gin-gonic/gin" +) + +// GetBDTPolicy - Read an Individual BDT policy +func GetBDTPolicy(c *gin.Context) { + req := http_wrapper.NewRequest(c.Request, nil) + req.Params["bdtPolicyId"] = c.Params.ByName("bdtPolicyId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventBDTPolicyGet, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} + +// UpdateBDTPolicy - Update an Individual BDT policy +func UpdateBDTPolicy(c *gin.Context) { + var bdtPolicyDataPatch models.BdtPolicyDataPatch + c.ShouldBindJSON(&bdtPolicyDataPatch) + + req := http_wrapper.NewRequest(c.Request, bdtPolicyDataPatch) + req.Params["bdtPolicyId"] = c.Params.ByName("bdtPolicyId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventBDTPolicyUpdate, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} diff --git a/BDTPolicy/api_individual_bdt_policy_document_routers_test.go b/BDTPolicy/api_individual_bdt_policy_document_routers_test.go new file mode 100644 index 0000000..c3fb074 --- /dev/null +++ b/BDTPolicy/api_individual_bdt_policy_document_routers_test.go @@ -0,0 +1,87 @@ +package BDTPolicy_test + +import ( + "context" + "github.com/stretchr/testify/assert" + TestBDTPolicy "free5gc/lib/CommonConsumerTestData/PCF/TestBDTPolicy" + "free5gc/lib/Npcf_BDTPolicyControl" + "free5gc/lib/openapi/models" + "net/http" + "strings" + "testing" + "time" +) + +func TestGetUpdateBDTPolicy(t *testing.T) { + + configuration := Npcf_BDTPolicyControl.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + client := Npcf_BDTPolicyControl.NewAPIClient(configuration) + + var bdtPolicyId string + // get test data + bdtReqData := TestBDTPolicy.GetCreateTestData() + + // test create service + { + rsp, httpRsp, err := client.BDTPoliciesCollectionApi.CreateBDTPolicy(context.Background(), bdtReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) { + if assert.NotNil(t, rsp.BdtReqData) { + assert.Equal(t, *rsp.BdtReqData, bdtReqData) + } + if assert.NotNil(t, rsp.BdtPolData) { + assert.True(t, rsp.BdtPolData.SelTransPolicyId == 1) + assert.Equal(t, rsp.BdtPolData.SuppFeat, "") + if assert.True(t, len(rsp.BdtPolData.TransfPolicies) == 1) { + assert.Equal(t, rsp.BdtPolData.TransfPolicies[0], models.TransferPolicy{ + RatingGroup: 1, + RecTimeInt: bdtReqData.DesTimeInt, + TransPolicyId: 1, + }) + } + } + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + bdtPolicyId = locationHeader[index+1:] + assert.True(t, strings.HasPrefix(bdtPolicyId, "BdtPolicyId-1")) + + } + } + + time.Sleep(30 * time.Millisecond) + // test update service + { + bdtPolicyDataPatch := TestBDTPolicy.GetUpdateTestData() + _, httpRsp, err := client.IndividualBDTPolicyDocumentApi.UpdateBDTPolicy(context.Background(), bdtPolicyId, bdtPolicyDataPatch) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + } + time.Sleep(30 * time.Millisecond) + // test get service + { + rsp, httpRsp, err := client.IndividualBDTPolicyDocumentApi.GetBDTPolicy(context.Background(), bdtPolicyId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { + if assert.NotNil(t, rsp.BdtReqData) { + assert.Equal(t, *rsp.BdtReqData, bdtReqData) + } + if assert.NotNil(t, rsp.BdtPolData) { + assert.True(t, rsp.BdtPolData.SelTransPolicyId == 1) + assert.Equal(t, rsp.BdtPolData.SuppFeat, "") + if assert.True(t, len(rsp.BdtPolData.TransfPolicies) == 1) { + assert.Equal(t, rsp.BdtPolData.TransfPolicies[0], models.TransferPolicy{ + RatingGroup: 1, + RecTimeInt: bdtReqData.DesTimeInt, + TransPolicyId: 1, + }) + } + } + } + } + +} diff --git a/BDTPolicy/routers.go b/BDTPolicy/routers.go new file mode 100644 index 0000000..dfabaf7 --- /dev/null +++ b/BDTPolicy/routers.go @@ -0,0 +1,94 @@ +/* + * Npcf_BDTPolicyControl Service API + * + * The Npcf_BDTPolicyControl Service is used by an NF service consumer to retrieve background data transfer policies from the PCF and to update the PCF with the background data transfer policy selected by the NF service consumer. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package BDTPolicy + +import ( + "net/http" + "strings" + + "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() + AddService(router) + return router +} + +func AddService(engine *gin.Engine) *gin.RouterGroup { + group := engine.Group("/npcf-bdtpolicycontrol/v1") + + for _, route := range routes { + switch route.Method { + case "GET": + group.GET(route.Pattern, route.HandlerFunc) + case "POST": + group.POST(route.Pattern, route.HandlerFunc) + case "PUT": + group.PUT(route.Pattern, route.HandlerFunc) + case "DELETE": + group.DELETE(route.Pattern, route.HandlerFunc) + case "PATCH": + group.PATCH(route.Pattern, route.HandlerFunc) + } + } + return group +} + +// Index is the index handler. +func Index(c *gin.Context) { + c.String(http.StatusOK, "Hello World!") +} + +var routes = Routes{ + { + "Index", + "GET", + "/", + Index, + }, + + { + "CreateBDTPolicy", + strings.ToUpper("Post"), + "/bdtpolicies", + CreateBDTPolicy, + }, + + { + "GetBDTPolicy", + strings.ToUpper("Get"), + "/bdtpolicies/:bdtPolicyId", + GetBDTPolicy, + }, + + { + "UpdateBDTPolicy", + strings.ToUpper("Patch"), + "/bdtpolicies/:bdtPolicyId", + UpdateBDTPolicy, + }, +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f465a20 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log +--- +2020-03-xx-xx +--- +- Implemented enchacements: + +- Fixed bugs: + +- Closed issues: diff --git a/HttpCallback/AMFStatusChangeNotify.go b/HttpCallback/AMFStatusChangeNotify.go new file mode 100644 index 0000000..a7ad174 --- /dev/null +++ b/HttpCallback/AMFStatusChangeNotify.go @@ -0,0 +1,36 @@ +package Npcf_Callback + +import ( + "github.com/gin-gonic/gin" + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_handler/pcf_message" + "net/http" +) + +func AmfStatusChangeNotify(c *gin.Context) { + var request models.AmfStatusChangeNotification + + err := c.ShouldBindJSON(&request) + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.CallbackLog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) + return + } + + req := http_wrapper.NewRequest(c.Request, request) + + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMFStatusChangeNotify, req) + pcf_message.SendMessage(channelMsg) + + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} diff --git a/HttpCallback/SMPolicyNotify.go b/HttpCallback/SMPolicyNotify.go new file mode 100644 index 0000000..bb30336 --- /dev/null +++ b/HttpCallback/SMPolicyNotify.go @@ -0,0 +1,27 @@ +package Npcf_Callback + +import ( + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_handler/pcf_message" + + "github.com/gin-gonic/gin" +) + +// Nudr-Notify-smpolicy +func NudrNotify(c *gin.Context) { + var policyDataChangeNotification models.PolicyDataChangeNotification + if err := c.ShouldBindJSON(&policyDataChangeNotification); err != nil { + logger.SMpolicylog.Warnln("Nudr Notify fail error message is : ", err) + } + + req := http_wrapper.NewRequest(c.Request, policyDataChangeNotification) + req.Params["ReqURI"] = c.Params.ByName("supi") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyNotify, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} diff --git a/HttpCallback/router.go b/HttpCallback/router.go new file mode 100644 index 0000000..407c0f3 --- /dev/null +++ b/HttpCallback/router.go @@ -0,0 +1,70 @@ +package Npcf_Callback + +import ( + "net/http" + "strings" + + "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() + AddService(router) + return router +} + +func AddService(engine *gin.Engine) *gin.RouterGroup { + group := engine.Group("/npcf-callback/v1") + // https://localhost:29507/npcf-callback/v1/route + for _, route := range routes { + switch route.Method { + case "POST": + group.POST(route.Pattern, route.HandlerFunc) + } + } + return group +} + +// Index is the index handler. +func Index(c *gin.Context) { + c.String(http.StatusOK, "Hello World!") +} + +var routes = Routes{ + { + "Index", + "GET", + "/", + Index, + }, + + { + "NudrNotify", + strings.ToUpper("Post"), + "/nudr-notify/:supi", + NudrNotify, + }, + + { + "AmfStatusChangeNotify", + strings.ToUpper("Post"), + "/amfstatus", + AmfStatusChangeNotify, + }, +} diff --git a/OAM/api_get_am_policy.go b/OAM/api_get_am_policy.go new file mode 100644 index 0000000..f6e7288 --- /dev/null +++ b/OAM/api_get_am_policy.go @@ -0,0 +1,30 @@ +package Npcf_OAM + +import ( + "github.com/gin-gonic/gin" + "free5gc/lib/http_wrapper" + "free5gc/src/pcf/pcf_handler/pcf_message" +) + +func setCorsHeader(c *gin.Context) { + c.Writer.Header().Set("Access-Control-Allow-Origin", "*") + c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") + c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") + c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, PATCH, DELETE") +} + +func OAMGetAmPolicy(c *gin.Context) { + setCorsHeader(c) + + req := http_wrapper.NewRequest(c.Request, nil) + req.Params["supi"] = c.Params.ByName("supi") + + handlerMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventOAMGetAmPolicy, req) + pcf_message.SendMessage(handlerMsg) + + rsp := <-handlerMsg.HttpChannel + + HTTPResponse := rsp.HTTPResponse + + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} diff --git a/OAM/routers.go b/OAM/routers.go new file mode 100644 index 0000000..5e759be --- /dev/null +++ b/OAM/routers.go @@ -0,0 +1,62 @@ +package Npcf_OAM + +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() + AddService(router) + return router +} + +func AddService(engine *gin.Engine) *gin.RouterGroup { + group := engine.Group("/npcf-oam/v1") + + for _, route := range routes { + switch route.Method { + case "GET": + group.GET(route.Pattern, route.HandlerFunc) + } + } + return group +} + +// Index is the index handler. +func Index(c *gin.Context) { + c.String(http.StatusOK, "Hello World!") +} + +var routes = Routes{ + { + "Index", + http.MethodGet, + "/", + Index, + }, + + { + "Get UE AM Policy Data", + http.MethodGet, + "/am-policy/:supi", + OAMGetAmPolicy, + }, +} diff --git a/PolicyAuthorization/api_application_sessions_collection.go b/PolicyAuthorization/api_application_sessions_collection.go new file mode 100644 index 0000000..7781fdd --- /dev/null +++ b/PolicyAuthorization/api_application_sessions_collection.go @@ -0,0 +1,52 @@ +/* + * Npcf_PolicyAuthorization Service API + * + * This is the Policy Authorization Service + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package PolicyAuthorization + +import ( + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/pcf_util" + + "github.com/gin-gonic/gin" +) + +// PostAppSessions - Creates a new Individual Application Session Context resource +func PostAppSessions(c *gin.Context) { + var appSessionContext models.AppSessionContext + err := c.ShouldBindJSON(&appSessionContext) + if err != nil { + rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_INITIAL_PARAMETERS) + logger.HandlerLog.Errorln(rsp.Detail) + c.JSON(int(rsp.Status), rsp) + return + } + reqData := appSessionContext.AscReqData + if reqData == nil || reqData.SuppFeat == "" || reqData.NotifUri == "" { + // Check Mandatory IEs + rsp := pcf_util.GetProblemDetail("Errorneous/Missing Mandotory IE", pcf_util.ERROR_INITIAL_PARAMETERS) + logger.HandlerLog.Errorln(rsp.Detail) + c.JSON(int(rsp.Status), rsp) + return + } + + req := http_wrapper.NewRequest(c.Request, appSessionContext) + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventPostAppSessions, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + + for key, val := range HTTPResponse.Header { + c.Header(key, val[0]) + } + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} diff --git a/PolicyAuthorization/api_application_sessions_collection_test.go b/PolicyAuthorization/api_application_sessions_collection_test.go new file mode 100644 index 0000000..af434f0 --- /dev/null +++ b/PolicyAuthorization/api_application_sessions_collection_test.go @@ -0,0 +1,302 @@ +package PolicyAuthorization_test + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "github.com/gin-gonic/gin" + "go.mongodb.org/mongo-driver/bson" + "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" + "free5gc/lib/CommonConsumerTestData/PCF/TestPolicyAuthorization" + "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" + "free5gc/lib/MongoDBLibrary" + "free5gc/lib/Npcf_AMPolicy" + "free5gc/lib/Npcf_PolicyAuthorization" + "free5gc/lib/Npcf_SMPolicyControl" + "free5gc/lib/http2_util" + "free5gc/lib/openapi/common" + "free5gc/lib/openapi/models" + "free5gc/lib/path_util" + "free5gc/src/amf/amf_service" + "free5gc/src/app" + "free5gc/src/nrf/nrf_service" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_service" + "free5gc/src/udr/udr_service" + "net/http" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/urfave/cli" +) + +const amPolicyDataColl = "policyData.ues.amData" +const smPolicyDataColl = "policyData.ues.smData" + +var NFs = []app.NetworkFunction{ + &nrf_service.NRF{}, + &amf_service.AMF{}, + &udr_service.UDR{}, + &pcf_service.PCF{}, +} + +var filterUeIdOnly bson.M + +func toBsonM(data interface{}) bson.M { + tmp, _ := json.Marshal(data) + var putData = bson.M{} + _ = json.Unmarshal(tmp, &putData) + return putData +} +func insertDefaultPoliciesToDb(ueId string) { + amPolicyData := models.AmPolicyData{ + SubscCats: []string{ + "free5gc", + }, + } + + smPolicyData := models.SmPolicyData{ + SmPolicySnssaiData: map[string]models.SmPolicySnssaiData{ + "01010203": { + Snssai: &models.Snssai{ + Sd: "010203", + Sst: 1, + }, + SmPolicyDnnData: map[string]models.SmPolicyDnnData{ + "internet": { + Dnn: "internet", + GbrUl: "500 Mbps", + GbrDl: "500 Mbps", + AdcSupport: false, + Ipv4Index: 6, + Ipv6Index: 6, + Offline: true, + Online: false, + // ChfInfo + // RefUmDataLimitIds + // MpsPriority + // ImsSignallingPrio + // MpsPriorityLevel + // AllowedServices + // SubscCats + // SubscSpendingLimit + + }, + }, + }, + "01112233": { + Snssai: &models.Snssai{ + Sd: "112233", + Sst: 1, + }, + SmPolicyDnnData: map[string]models.SmPolicyDnnData{ + "internet": { + Dnn: "internet", + }, + }, + }, + }, + } + + filterUeIdOnly = bson.M{"ueId": ueId} + amPolicyDataBsonM := toBsonM(amPolicyData) + amPolicyDataBsonM["ueId"] = ueId + MongoDBLibrary.RestfulAPIPutOne(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM) + smPolicyDataBsonM := toBsonM(smPolicyData) + smPolicyDataBsonM["ueId"] = ueId + MongoDBLibrary.RestfulAPIPost(smPolicyDataColl, filterUeIdOnly, smPolicyDataBsonM) +} + +func fakeSmfServer(t *testing.T, port string) { + go func() { // fake smf server + router := gin.Default() + + router.POST("nsmf-callback/v1/sm-policies/:smPolicyId/update", func(c *gin.Context) { + smPolicyId := c.Param("smPolicyId") + fmt.Println("==========SM Policy Update Notification Callback=============") + fmt.Println("smPolicyId: ", smPolicyId) + + var notification models.SmPolicyNotification + if err := c.ShouldBindJSON(¬ification); err != nil { + fmt.Println("fake smf server error") + c.JSON(http.StatusInternalServerError, gin.H{}) + return + } + c.JSON(http.StatusNoContent, gin.H{}) + }) + + router.POST("nsmf-callback/v1/sm-policies/:smPolicyId/terminate", func(c *gin.Context) { + smPolicyId := c.Param("smPolicyId") + fmt.Println("==========SM Policy Terminate Callback=============") + fmt.Println("smPolicyId: ", smPolicyId) + + var terminationNotification models.TerminationNotification + if err := c.ShouldBindJSON(&terminationNotification); err != nil { + fmt.Println("fake smf server error") + c.JSON(http.StatusInternalServerError, gin.H{}) + return + } + c.JSON(http.StatusNoContent, gin.H{}) + configuration := Npcf_SMPolicyControl.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration) + httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdDeletePost(context.Background(), smPolicyId, models.SmPolicyDeleteData{}) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) + } + }) + + smfLogPath := path_util.Gofree5gcPath("free5gc/smfsslkey.log") + smfPemPath := path_util.Gofree5gcPath("free5gc/support/TLS/smf.pem") + smfKeyPath := path_util.Gofree5gcPath("free5gc/support/TLS/smf.key") + + server, err := http2_util.NewServer(port, smfLogPath, router) + if err == nil && server != nil { + fmt.Println(server.ListenAndServeTLS(smfPemPath, smfKeyPath)) + } + assert.True(t, err == nil) + }() +} + +func init() { + app.AppInitializeWillInitialize("") + flag := flag.FlagSet{} + cli := cli.NewContext(nil, &flag, nil) + for i, service := range NFs { + service.Initialize(cli) + go service.Start() + time.Sleep(300 * time.Millisecond) + if i == 0 { + MongoDBLibrary.RestfulAPIDeleteMany("NfProfile", bson.M{}) + time.Sleep(300 * time.Millisecond) + } + } + insertDefaultPoliciesToDb("imsi-2089300007487") + + time.Sleep(100 * time.Millisecond) + +} + +func TestApplicationSessionsCollection(t *testing.T) { + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) + + fakeSmfServer(t, ":29502") + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + amclient := Npcf_AMPolicy.NewAPIClient(configuration) + configuration1 := Npcf_SMPolicyControl.NewConfiguration() + configuration1.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) + configuration2 := Npcf_PolicyAuthorization.NewConfiguration() + configuration2.SetBasePath("https://127.0.0.1:29507") + afclient := Npcf_PolicyAuthorization.NewAPIClient(configuration2) + smPolicyId := "" + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] + pcfSelf := pcf_context.PCF_Self() + { + smCreateReqData := TestSMPolicy.CreateTestData() + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + smPolicyId = locationHeader[index+1:] + assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") + } + } + { + afReqData := TestPolicyAuthorization.GetPostAppSessionsData_Normal() + _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + appSessionId := fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) + header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) + assert.True(t, locationHeader == header) + appSession := pcfSelf.AppSessionPool[appSessionId] + if assert.NotNil(t, appSession) { + assert.True(t, appSession.EventUri == afReqData.AscReqData.EvSubsc.NotifUri) + assert.True(t, len(appSession.Events) == len(afReqData.AscReqData.EvSubsc.Events)) + smPolicy := ue.SmPolicyData[smPolicyId] + assert.Equal(t, smPolicy, appSession.SmPolicyData) + pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) + assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + if assert.NotNil(t, pccRule) { + assert.Equal(t, afReqData.AscReqData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) + } + } + } + } + { + afReqData := TestPolicyAuthorization.GetPostAppSessionsData_Flow3() + _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + appSessionId := fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) + header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) + assert.True(t, locationHeader == header) + appSession := pcfSelf.AppSessionPool[appSessionId] + if assert.NotNil(t, appSession) { + assert.True(t, appSession.EventUri == afReqData.AscReqData.EvSubsc.NotifUri) + assert.True(t, len(appSession.Events) == len(afReqData.AscReqData.EvSubsc.Events)) + smPolicy := ue.SmPolicyData[smPolicyId] + assert.Equal(t, smPolicy, appSession.SmPolicyData) + assert.Equal(t, 3, len(appSession.RelatedPccRuleIds)) + assert.Equal(t, 3, len(smPolicy.PolicyDecision.PccRules)) + } + } + } + { + afReqData := TestPolicyAuthorization.GetPostAppSessionsData_403Forbidden() + _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) + assert.True(t, err != nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusForbidden, httpRsp.StatusCode) + problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + assert.Equal(t, "REQUESTED_SERVICE_NOT_AUTHORIZED", problem.Cause) + } + } + { + afReqData := TestPolicyAuthorization.GetPostAppSessionsData_400() + _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) + assert.True(t, err != nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) + problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + assert.Equal(t, "ERROR_REQUEST_PARAMETERS", problem.Cause) + } + } +} diff --git a/PolicyAuthorization/api_events_subscription_document.go b/PolicyAuthorization/api_events_subscription_document.go new file mode 100644 index 0000000..424eb9e --- /dev/null +++ b/PolicyAuthorization/api_events_subscription_document.go @@ -0,0 +1,62 @@ +/* + * Npcf_PolicyAuthorization Service API + * + * This is the Policy Authorization Service + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package PolicyAuthorization + +import ( + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/pcf_util" + + "github.com/gin-gonic/gin" +) + +// DeleteEventsSubsc - deletes the Events Subscription subresource +func DeleteEventsSubsc(c *gin.Context) { + + req := http_wrapper.NewRequest(c.Request, nil) + req.Params["appSessionId"], _ = c.Params.Get("appSessionId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventDeleteEventsSubsc, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} + +// UpdateEventsSubsc - creates or modifies an Events Subscription subresource +func UpdateEventsSubsc(c *gin.Context) { + var eventsSubscReqData models.EventsSubscReqData + err := c.ShouldBindJSON(&eventsSubscReqData) + if err != nil { + rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.HandlerLog.Errorln(rsp.Detail) + c.JSON(int(rsp.Status), rsp) + return + } + if eventsSubscReqData.Events == nil || eventsSubscReqData.NotifUri == "" { + rsp := pcf_util.GetProblemDetail("Errorneous/Missing Mandotory IE", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.HandlerLog.Errorln(rsp.Detail) + c.JSON(int(rsp.Status), rsp) + return + } + + req := http_wrapper.NewRequest(c.Request, eventsSubscReqData) + req.Params["appSessionId"], _ = c.Params.Get("appSessionId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventUpdateEventsSubsc, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} diff --git a/PolicyAuthorization/api_events_subscription_document_test.go b/PolicyAuthorization/api_events_subscription_document_test.go new file mode 100644 index 0000000..1c28651 --- /dev/null +++ b/PolicyAuthorization/api_events_subscription_document_test.go @@ -0,0 +1,157 @@ +package PolicyAuthorization_test + +import ( + "context" + "fmt" + "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" + "free5gc/lib/CommonConsumerTestData/PCF/TestPolicyAuthorization" + "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" + "free5gc/lib/MongoDBLibrary" + "free5gc/lib/Npcf_AMPolicy" + "free5gc/lib/Npcf_PolicyAuthorization" + "free5gc/lib/Npcf_SMPolicyControl" + "free5gc/src/pcf/pcf_context" + "net/http" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestEventSubscription(t *testing.T) { + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) + + fakeSmfServer(t, ":29502") + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + amclient := Npcf_AMPolicy.NewAPIClient(configuration) + configuration1 := Npcf_SMPolicyControl.NewConfiguration() + configuration1.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) + configuration2 := Npcf_PolicyAuthorization.NewConfiguration() + configuration2.SetBasePath("https://127.0.0.1:29507") + afclient := Npcf_PolicyAuthorization.NewAPIClient(configuration2) + smPolicyId := "" + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] + pcfSelf := pcf_context.PCF_Self() + { + smCreateReqData := TestSMPolicy.CreateTestData() + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + smPolicyId = locationHeader[index+1:] + assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") + } + } + appSessionId := "" + { + // Create App Session + afReqData := TestPolicyAuthorization.GetPostAppSessionsData_NoEvent() + _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + appSessionId = fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) + header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) + assert.True(t, locationHeader == header) + appSession := pcfSelf.AppSessionPool[appSessionId] + if assert.NotNil(t, appSession) { + smPolicy := ue.SmPolicyData[smPolicyId] + assert.Equal(t, smPolicy, appSession.SmPolicyData) + pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) + assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + if assert.NotNil(t, pccRule) { + assert.Equal(t, afReqData.AscReqData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) + } + } + } + } + appSession := pcfSelf.AppSessionPool[appSessionId] + { + // Create App Session Subscription (201) + reqData := TestPolicyAuthorization.GetUpdateEventsSubsc201Data() + resp, httpRsp, err := afclient.EventsSubscriptionDocumentApi.UpdateEventsSubsc(context.Background(), appSessionId, reqData) + assert.True(t, err == nil) + if assert.True(t, httpRsp != nil) { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + if assert.NotNil(t, resp) { + assert.Equal(t, reqData, resp.EvSubsc) + assert.NotNil(t, resp.EvsNotif) + assert.Equal(t, 2, len(appSession.Events)) + assert.Equal(t, reqData.NotifUri, appSession.EventUri) + } + } + } + { + // Modify App Session Subscription (200) + reqData := TestPolicyAuthorization.GetUpdateEventsSubsc200Data() + resp, httpRsp, err := afclient.EventsSubscriptionDocumentApi.UpdateEventsSubsc(context.Background(), appSessionId, reqData) + assert.True(t, err == nil) + if assert.True(t, httpRsp != nil) { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + if assert.NotNil(t, resp) { + assert.Equal(t, reqData, resp.EvSubsc) + assert.NotNil(t, resp.EvsNotif) + assert.Equal(t, 1, len(appSession.Events)) + assert.Equal(t, reqData.NotifUri, appSession.EventUri) + } + } + } + { + // Modify App Session Subscription (204) + reqData := TestPolicyAuthorization.GetUpdateEventsSubsc204Data() + _, httpRsp, err := afclient.EventsSubscriptionDocumentApi.UpdateEventsSubsc(context.Background(), appSessionId, reqData) + assert.True(t, err == nil) + if assert.True(t, httpRsp != nil) { + assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) + assert.Equal(t, 1, len(appSession.Events)) + assert.Equal(t, reqData.NotifUri, appSession.EventUri) + } + } + { + // Create App Session Subscription (400) + reqData := TestPolicyAuthorization.GetUpdateEventsSubsc400Data() + _, httpRsp, err := afclient.EventsSubscriptionDocumentApi.UpdateEventsSubsc(context.Background(), appSessionId, reqData) + assert.True(t, err != nil) + if assert.True(t, httpRsp != nil) { + assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) + } + } + { + // Delete App Session Subscription (204) + httpRsp, err := afclient.EventsSubscriptionDocumentApi.DeleteEventsSubsc(context.Background(), appSessionId) + assert.True(t, err == nil) + if assert.True(t, httpRsp != nil) { + assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) + assert.Nil(t, appSession.Events) + } + } + + time.Sleep(100 * time.Millisecond) +} diff --git a/PolicyAuthorization/api_individual_application_session_context_document.go b/PolicyAuthorization/api_individual_application_session_context_document.go new file mode 100644 index 0000000..723fdd4 --- /dev/null +++ b/PolicyAuthorization/api_individual_application_session_context_document.go @@ -0,0 +1,69 @@ +/* + * Npcf_PolicyAuthorization Service API + * + * This is the Policy Authorization Service + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package PolicyAuthorization + +import ( + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/pcf_handler/pcf_message" + + "github.com/gin-gonic/gin" +) + +// DeleteAppSession - Deletes an existing Individual Application Session Context +func DeleteAppSession(c *gin.Context) { + + var eventsSubscReqData *models.EventsSubscReqData + err := c.ShouldBindJSON(eventsSubscReqData) + if err != nil { + eventsSubscReqData = nil + } + + req := http_wrapper.NewRequest(c.Request, eventsSubscReqData) + req.Params["appSessionId"], _ = c.Params.Get("appSessionId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventDeleteAppSession, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} + +// GetAppSession - Reads an existing Individual Application Session Context +func GetAppSession(c *gin.Context) { + + req := http_wrapper.NewRequest(c.Request, nil) + req.Params["appSessionId"], _ = c.Params.Get("appSessionId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventGetAppSession, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} + +// ModAppSession - Modifies an existing Individual Application Session Context +func ModAppSession(c *gin.Context) { + var appSessionContextUpdateData models.AppSessionContextUpdateData + c.ShouldBindJSON(&appSessionContextUpdateData) + + req := http_wrapper.NewRequest(c.Request, appSessionContextUpdateData) + req.Params["appSessionId"], _ = c.Params.Get("appSessionId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventModAppSession, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) + +} diff --git a/PolicyAuthorization/api_individual_application_session_context_document_test.go b/PolicyAuthorization/api_individual_application_session_context_document_test.go new file mode 100644 index 0000000..f182c8d --- /dev/null +++ b/PolicyAuthorization/api_individual_application_session_context_document_test.go @@ -0,0 +1,317 @@ +package PolicyAuthorization_test + +import ( + "context" + "fmt" + "github.com/davecgh/go-spew/spew" + "github.com/gin-gonic/gin" + "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" + "free5gc/lib/CommonConsumerTestData/PCF/TestPolicyAuthorization" + "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" + "free5gc/lib/MongoDBLibrary" + "free5gc/lib/Npcf_AMPolicy" + "free5gc/lib/Npcf_PolicyAuthorization" + "free5gc/lib/Npcf_SMPolicyControl" + "free5gc/lib/openapi/common" + "free5gc/lib/openapi/models" + "free5gc/lib/path_util" + "free5gc/src/pcf/pcf_context" + "net/http" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func fakeAfServer(t *testing.T, port string) { + go func() { // fake af server + router := gin.Default() + + router.POST("/notify", func(c *gin.Context) { + fmt.Println("==========App Session Event Notification Callback=============") + + var notification models.EventsNotification + if err := c.ShouldBindJSON(¬ification); err != nil { + fmt.Println("fake AF server error") + c.JSON(http.StatusInternalServerError, gin.H{}) + return + } + spew.Dump(notification.EvNotifs) + c.JSON(http.StatusNoContent, gin.H{}) + }) + + router.POST("/terminate", func(c *gin.Context) { + fmt.Println("==========App Session Teimination Callback=============") + + var terminationInfo models.TerminationInfo + if err := c.ShouldBindJSON(&terminationInfo); err != nil { + fmt.Println("fake AF server error") + c.JSON(http.StatusInternalServerError, gin.H{}) + return + } + spew.Dump(terminationInfo) + c.JSON(http.StatusNoContent, gin.H{}) + }) + + pcfPemPath := path_util.Gofree5gcPath("free5gc/support/TLS/pcf.pem") + pcfKeyPath := path_util.Gofree5gcPath("free5gc/support/TLS/pcf.key") + + server := &http.Server{ + Addr: port, + Handler: router, + } + + fmt.Println(server.ListenAndServeTLS(pcfPemPath, pcfKeyPath)) + }() +} + +func TestIndividualAppSessionContext(t *testing.T) { + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) + + fakeSmfServer(t, ":29502") + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + amclient := Npcf_AMPolicy.NewAPIClient(configuration) + configuration1 := Npcf_SMPolicyControl.NewConfiguration() + configuration1.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) + configuration2 := Npcf_PolicyAuthorization.NewConfiguration() + configuration2.SetBasePath("https://127.0.0.1:29507") + afclient := Npcf_PolicyAuthorization.NewAPIClient(configuration2) + smPolicyId := "" + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] + pcfSelf := pcf_context.PCF_Self() + { + smCreateReqData := TestSMPolicy.CreateTestData() + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + smPolicyId = locationHeader[index+1:] + assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") + } + } + appSessionId := "" + { + // Create App Session + afReqData := TestPolicyAuthorization.GetPostAppSessionsData_Normal() + _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + appSessionId = fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) + header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) + assert.True(t, locationHeader == header) + appSession := pcfSelf.AppSessionPool[appSessionId] + if assert.NotNil(t, appSession) { + assert.True(t, appSession.EventUri == afReqData.AscReqData.EvSubsc.NotifUri) + assert.True(t, len(appSession.Events) == len(afReqData.AscReqData.EvSubsc.Events)) + smPolicy := ue.SmPolicyData[smPolicyId] + assert.Equal(t, smPolicy, appSession.SmPolicyData) + pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) + assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + if assert.NotNil(t, pccRule) { + assert.Equal(t, afReqData.AscReqData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) + } + } + } + } + { + // Get App Session + resp, httpRsp, err := afclient.IndividualApplicationSessionContextDocumentApi.GetAppSession(context.Background(), appSessionId) + assert.True(t, err == nil) + if assert.True(t, httpRsp != nil) { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + if assert.NotNil(t, resp) { + assert.NotNil(t, resp.AscRespData) + assert.NotNil(t, resp.AscReqData) + } + } + } + appSession := pcfSelf.AppSessionPool[appSessionId] + smPolicy := ue.SmPolicyData[smPolicyId] + { + // Update App Session + modData := TestPolicyAuthorization.GetModAppSession200Data() + _, httpRsp, err := afclient.IndividualApplicationSessionContextDocumentApi.ModAppSession(context.Background(), appSessionId, modData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + if assert.NotNil(t, appSession) { + assert.True(t, appSession.EventUri == appSession.AppSessionContext.AscReqData.EvSubsc.NotifUri) + assert.True(t, len(appSession.Events) == len(modData.EvSubsc.Events)) + assert.Equal(t, smPolicy, appSession.SmPolicyData) + pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) + assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) + assert.Equal(t, 1, len(smPolicy.PolicyDecision.PccRules)) + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + if assert.NotNil(t, pccRule) { + assert.Equal(t, modData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) + } + } + } + } + { + // Delete App Session + _, httpRsp, err := afclient.IndividualApplicationSessionContextDocumentApi.DeleteAppSession(context.Background(), appSessionId, nil) + assert.True(t, err == nil) + if assert.True(t, httpRsp != nil) { + assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) + assert.Equal(t, 0, len(pcfSelf.AppSessionPool)) + assert.Equal(t, 0, len(smPolicy.AppSessions)) + assert.Equal(t, 0, len(smPolicy.PolicyDecision.PccRules)) + } + } +} + +func TestAppSessionNotification(t *testing.T) { + + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) + + fakeSmfServer(t, ":29502") + fakeAfServer(t, ":12345") + + time.Sleep(100 * time.Millisecond) + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + amclient := Npcf_AMPolicy.NewAPIClient(configuration) + configuration1 := Npcf_SMPolicyControl.NewConfiguration() + configuration1.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) + configuration2 := Npcf_PolicyAuthorization.NewConfiguration() + configuration2.SetBasePath("https://127.0.0.1:29507") + afclient := Npcf_PolicyAuthorization.NewAPIClient(configuration2) + smPolicyId := "" + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] + pcfSelf := pcf_context.PCF_Self() + { + smCreateReqData := TestSMPolicy.CreateTestData() + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + smPolicyId = locationHeader[index+1:] + assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") + } + } + appSessionId := "" + { + afReqData := TestPolicyAuthorization.GetPostAppSessionsData_Normal() + _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + appSessionId = fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) + header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) + assert.True(t, locationHeader == header) + appSession := pcfSelf.AppSessionPool[appSessionId] + if assert.NotNil(t, appSession) { + assert.True(t, appSession.EventUri == afReqData.AscReqData.EvSubsc.NotifUri) + assert.True(t, len(appSession.Events) == len(afReqData.AscReqData.EvSubsc.Events)) + smPolicy := ue.SmPolicyData[smPolicyId] + assert.Equal(t, smPolicy, appSession.SmPolicyData) + pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) + assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + if assert.NotNil(t, pccRule) { + assert.Equal(t, afReqData.AscReqData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) + } + } + } + } + time.Sleep(100 * time.Millisecond) + + // Test AppSessionEventNotify (Send SM policy Update which is related to App Session) + { + trigger := []models.PolicyControlRequestTrigger{ + models.PolicyControlRequestTrigger_PLMN_CH, + models.PolicyControlRequestTrigger_AC_TY_CH, + models.PolicyControlRequestTrigger_RAT_TY_CH, + } + updateReq := TestSMPolicy.UpdateTestData(trigger, nil) + updateReq.AccessType = models.AccessType_NON_3_GPP_ACCESS + updateReq.RatType = models.RatType_WLAN + //Test UpdatePoliciesPolAssoId + _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + } + } + time.Sleep(100 * time.Millisecond) + // Test AppSession Termination (Send SM policy Update which is related to App Session) + { + //Test DelPoliciesPolAssoId + httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdDeletePost(context.Background(), smPolicyId, models.SmPolicyDeleteData{}) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) + } + } + time.Sleep(100 * time.Millisecond) + { + // Get App Session + _, httpRsp, err := afclient.IndividualApplicationSessionContextDocumentApi.GetAppSession(context.Background(), appSessionId) + assert.True(t, err != nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusNotFound, httpRsp.StatusCode) + problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + assert.Equal(t, "APPLICATION_SESSION_CONTEXT_NOT_FOUND", problem.Cause) + } + } + assert.True(t, len(pcf_context.PCF_Self().AppSessionPool) == 0) + assert.True(t, len(ue.SmPolicyData) == 0) + +} diff --git a/PolicyAuthorization/routers.go b/PolicyAuthorization/routers.go new file mode 100644 index 0000000..d7e2f97 --- /dev/null +++ b/PolicyAuthorization/routers.go @@ -0,0 +1,115 @@ +/* + * Npcf_PolicyAuthorization Service API + * + * This is the Policy Authorization Service + * + * API version: 1.0.1 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package PolicyAuthorization + +import ( + "net/http" + "strings" + + "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() + AddService(router) + return router +} + +func AddService(engine *gin.Engine) *gin.RouterGroup { + group := engine.Group("/npcf-policyauthorization/v1") + + for _, route := range routes { + switch route.Method { + case "GET": + group.GET(route.Pattern, route.HandlerFunc) + case "POST": + group.POST(route.Pattern, route.HandlerFunc) + case "PUT": + group.PUT(route.Pattern, route.HandlerFunc) + case "DELETE": + group.DELETE(route.Pattern, route.HandlerFunc) + case "PATCH": + group.PATCH(route.Pattern, route.HandlerFunc) + } + } + return group +} + +// Index is the index handler. +func Index(c *gin.Context) { + c.String(http.StatusOK, "Hello World!") +} + +var routes = Routes{ + { + "Index", + "GET", + "/", + Index, + }, + + { + "PostAppSessions", + strings.ToUpper("Post"), + "/app-sessions", + PostAppSessions, + }, + + { + "DeleteEventsSubsc", + strings.ToUpper("Delete"), + "/app-sessions/:appSessionId/events-subscription", + DeleteEventsSubsc, + }, + + { + "UpdateEventsSubsc", + strings.ToUpper("Put"), + "/app-sessions/:appSessionId/events-subscription", + UpdateEventsSubsc, + }, + + { + "DeleteAppSession", + strings.ToUpper("Post"), + "/app-sessions/:appSessionId/delete", + DeleteAppSession, + }, + + { + "GetAppSession", + strings.ToUpper("Get"), + "/app-sessions/:appSessionId", + GetAppSession, + }, + + { + "ModAppSession", + strings.ToUpper("Patch"), + "/app-sessions/:appSessionId", + ModAppSession, + }, +} diff --git a/SMPolicy/api_default.go b/SMPolicy/api_default.go new file mode 100644 index 0000000..a1698ff --- /dev/null +++ b/SMPolicy/api_default.go @@ -0,0 +1,88 @@ +/* + * Npcf_SMPolicyControl + * + * Session Management Policy Control Service + * + * API version: 1.0.1 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package SMPolicy + +import ( + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/pcf_util" + + "github.com/gin-gonic/gin" +) + +// SmPoliciesPost - +func SmPoliciesPost(c *gin.Context) { + + var smPolicyContextData models.SmPolicyContextData + err := c.ShouldBindJSON(&smPolicyContextData) + if err != nil { + rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_INITIAL_PARAMETERS) + logger.HandlerLog.Errorln(rsp.Detail) + c.JSON(int(rsp.Status), rsp) + return + } + if smPolicyContextData.Supi == "" || smPolicyContextData.SliceInfo == nil || len(smPolicyContextData.SliceInfo.Sd) != 6 { + rsp := pcf_util.GetProblemDetail("Errorneous/Missing Mandotory IE", pcf_util.ERROR_INITIAL_PARAMETERS) + logger.HandlerLog.Errorln(rsp.Detail) + c.JSON(int(rsp.Status), rsp) + return + } + + req := http_wrapper.NewRequest(c.Request, smPolicyContextData) + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyCreate, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + + for key, val := range HTTPResponse.Header { + c.Header(key, val[0]) + } + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} + +// SmPoliciesSmPolicyIdDeletePost - +func SmPoliciesSmPolicyIdDeletePost(c *gin.Context) { + req := http_wrapper.NewRequest(c.Request, nil) + req.Params["smPolicyId"] = c.Params.ByName("smPolicyId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyDelete, req) + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} + +// SmPoliciesSmPolicyIdGet - +func SmPoliciesSmPolicyIdGet(c *gin.Context) { + req := http_wrapper.NewRequest(c.Request, nil) + req.Params["smPolicyId"] = c.Params.ByName("smPolicyId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyGet, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} + +// SmPoliciesSmPolicyIdUpdatePost - +func SmPoliciesSmPolicyIdUpdatePost(c *gin.Context) { + var smPolicyUpdateContextData models.SmPolicyUpdateContextData + c.ShouldBindJSON(&smPolicyUpdateContextData) + req := http_wrapper.NewRequest(c.Request, smPolicyUpdateContextData) + req.Params["smPolicyId"] = c.Params.ByName("smPolicyId") + channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyUpdate, req) + + pcf_message.SendMessage(channelMsg) + recvMsg := <-channelMsg.HttpChannel + HTTPResponse := recvMsg.HTTPResponse + c.JSON(HTTPResponse.Status, HTTPResponse.Body) +} diff --git a/SMPolicy/api_default_test.go b/SMPolicy/api_default_test.go new file mode 100644 index 0000000..55e8610 --- /dev/null +++ b/SMPolicy/api_default_test.go @@ -0,0 +1,658 @@ +package SMPolicy_test + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "github.com/gin-gonic/gin" + "go.mongodb.org/mongo-driver/bson" + "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" + "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" + "free5gc/lib/MongoDBLibrary" + "free5gc/lib/Npcf_AMPolicy" + "free5gc/lib/Npcf_SMPolicyControl" + "free5gc/lib/http2_util" + "free5gc/lib/openapi/common" + "free5gc/lib/openapi/models" + "free5gc/lib/path_util" + "free5gc/src/amf/amf_service" + "free5gc/src/app" + "free5gc/src/nrf/nrf_service" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_producer" + "free5gc/src/pcf/pcf_service" + "free5gc/src/udr/udr_service" + "net/http" + "reflect" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/urfave/cli" +) + +const amPolicyDataColl = "policyData.ues.amData" +const smPolicyDataColl = "policyData.ues.smData" + +var NFs = []app.NetworkFunction{ + &nrf_service.NRF{}, + &amf_service.AMF{}, + &udr_service.UDR{}, + &pcf_service.PCF{}, +} + +var filterUeIdOnly bson.M + +func toBsonM(data interface{}) bson.M { + tmp, _ := json.Marshal(data) + var putData = bson.M{} + _ = json.Unmarshal(tmp, &putData) + return putData +} +func insertDefaultPoliciesToDb(ueId string) { + amPolicyData := models.AmPolicyData{ + SubscCats: []string{ + "free5gc", + }, + } + + smPolicyData := models.SmPolicyData{ + SmPolicySnssaiData: map[string]models.SmPolicySnssaiData{ + "01010203": { + Snssai: &models.Snssai{ + Sd: "010203", + Sst: 1, + }, + SmPolicyDnnData: map[string]models.SmPolicyDnnData{ + "internet": { + Dnn: "internet", + GbrUl: "500 Mbps", + GbrDl: "500 Mbps", + AdcSupport: false, + Ipv4Index: 6, + Ipv6Index: 6, + Offline: true, + Online: false, + // ChfInfo + // RefUmDataLimitIds + // MpsPriority + // ImsSignallingPrio + // MpsPriorityLevel + // AllowedServices + // SubscCats + // SubscSpendingLimit + + }, + }, + }, + "01112233": { + Snssai: &models.Snssai{ + Sd: "112233", + Sst: 1, + }, + SmPolicyDnnData: map[string]models.SmPolicyDnnData{ + "internet": { + Dnn: "internet", + }, + }, + }, + }, + } + + filterUeIdOnly = bson.M{"ueId": ueId} + amPolicyDataBsonM := toBsonM(amPolicyData) + amPolicyDataBsonM["ueId"] = ueId + MongoDBLibrary.RestfulAPIPutOne(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM) + smPolicyDataBsonM := toBsonM(smPolicyData) + smPolicyDataBsonM["ueId"] = ueId + MongoDBLibrary.RestfulAPIPost(smPolicyDataColl, filterUeIdOnly, smPolicyDataBsonM) +} + +func init() { + app.AppInitializeWillInitialize("") + flag := flag.FlagSet{} + cli := cli.NewContext(nil, &flag, nil) + for i, service := range NFs { + service.Initialize(cli) + go service.Start() + time.Sleep(300 * time.Millisecond) + if i == 0 { + MongoDBLibrary.RestfulAPIDeleteMany("NfProfile", bson.M{}) + time.Sleep(300 * time.Millisecond) + } + } + insertDefaultPoliciesToDb("imsi-2089300007487") + +} +func TestCreateSMPolicy(t *testing.T) { + defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) + defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + amclient := Npcf_AMPolicy.NewAPIClient(configuration) + configuration1 := Npcf_SMPolicyControl.NewConfiguration() + configuration1.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + { + smCreateReqData := TestSMPolicy.CreateTestData() + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + // index := strings.LastIndex(locationHeader, "/") + assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") + } + } + { + smCreateReqData := TestSMPolicy.CreateTestData() + smCreateReqData.Supi = "" + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err != nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) + problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + assert.Equal(t, "ERROR_INITIAL_PARAMETERS", problem.Cause) + // assert.Equal(t, "Supi Format Error", problem.Detail) + } + } + { + smCreateReqData := TestSMPolicy.CreateTestData() + smCreateReqData.SliceInfo.Sd = "123" + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err != nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) + problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + assert.Equal(t, "ERROR_INITIAL_PARAMETERS", problem.Cause) + // assert.Equal(t, "Supi Format Error", problem.Detail) + } + } +} + +func TestGetSMPolicy(t *testing.T) { + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + amclient := Npcf_AMPolicy.NewAPIClient(configuration) + configuration1 := Npcf_SMPolicyControl.NewConfiguration() + configuration1.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) + smPolicyId := "imsi-2089300007487-1" + smCreateReqData := TestSMPolicy.CreateTestData() + var decision models.SmPolicyDecision + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + { + tmp, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + // index := strings.LastIndex(locationHeader, "/") + assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") + } + decision = tmp + } + { + //Test GetPoliciesPolAssoId + rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + assert.True(t, reflect.DeepEqual(smCreateReqData, *rsp.Context)) + assert.True(t, reflect.DeepEqual(decision, *rsp.Policy)) + } + } + +} + +func TestDelSMPolicy(t *testing.T) { + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + amclient := Npcf_AMPolicy.NewAPIClient(configuration) + configuration1 := Npcf_SMPolicyControl.NewConfiguration() + configuration1.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) + smPolicyId := "imsi-2089300007487-1" + smCreateReqData := TestSMPolicy.CreateTestData() + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + { + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + // index := strings.LastIndex(locationHeader, "/") + assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") + } + } + { + //Test DelPoliciesPolAssoId + httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdDeletePost(context.Background(), smPolicyId, models.SmPolicyDeleteData{}) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) + } + } + { + //Test GetPoliciesPolAssoId + _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) + assert.True(t, err != nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusNotFound, httpRsp.StatusCode) + problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + assert.Equal(t, "CONTEXT_NOT_FOUND", problem.Cause) + } + } +} + +func TestUpdateSMPolicy(t *testing.T) { + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + amclient := Npcf_AMPolicy.NewAPIClient(configuration) + configuration1 := Npcf_SMPolicyControl.NewConfiguration() + configuration1.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) + smPolicyId := "imsi-2089300007487-1" + smCreateReqData := TestSMPolicy.CreateTestData() + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + { + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + // index := strings.LastIndex(locationHeader, "/") + assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") + } + } + { + trigger := []models.PolicyControlRequestTrigger{ + models.PolicyControlRequestTrigger_PLMN_CH, + models.PolicyControlRequestTrigger_AC_TY_CH, + models.PolicyControlRequestTrigger_UE_IP_CH, + models.PolicyControlRequestTrigger_PS_DA_OFF, + models.PolicyControlRequestTrigger_DEF_QOS_CH, + models.PolicyControlRequestTrigger_SE_AMBR_CH, + models.PolicyControlRequestTrigger_SAREA_CH, + models.PolicyControlRequestTrigger_SCNN_CH, + models.PolicyControlRequestTrigger_RAT_TY_CH, + models.PolicyControlRequestTrigger_UE_TZ_CH, + } + updateReq := TestSMPolicy.UpdateTestData(trigger, nil) + updateReq.AccessType = models.AccessType_NON_3_GPP_ACCESS + updateReq.RatType = models.RatType_WLAN + //Test UpdatePoliciesPolAssoId + _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + // { + // //Test GetPoliciesPolAssoId + // rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) + // assert.True(t, err == nil) + // assert.True(t, httpRsp != nil) + // if httpRsp != nil { + // assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + // } + // } + // } + } + } + { + trigger := []models.PolicyControlRequestTrigger{ + models.PolicyControlRequestTrigger_AC_TY_CH, + models.PolicyControlRequestTrigger_RAT_TY_CH, + models.PolicyControlRequestTrigger_RES_MO_RE, + } + op := models.RuleOperation_CREATE_PCC_RULE + updateReq := TestSMPolicy.UpdateTestData(trigger, &op) + //Test UpdatePoliciesPolAssoId + _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { + { + //Test GetPoliciesPolAssoId + rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] + assert.True(t, exist) + req := updateReq.UeInitResReq + assert.Equal(t, rule.FlowInfos[0].FlowDescription, req.PackFiltInfo[0].PackFiltCont) + assert.True(t, models.FlowDirection(rule.FlowInfos[0].FlowDirection) == req.PackFiltInfo[0].FlowDirection) + assert.Equal(t, req.ReqQos.Var5qi, rsp.Policy.QosDecs[rule.RefQosData[0]].Var5qi) + assert.Equal(t, req.ReqQos.GbrUl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrUl) + assert.Equal(t, req.ReqQos.GbrDl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrDl) + } + } + } + } + } + { + trigger := []models.PolicyControlRequestTrigger{ + models.PolicyControlRequestTrigger_RES_MO_RE, + } + op := models.RuleOperation_MODIFY_PCC_RULE_AND_ADD_PACKET_FILTERS + updateReq := TestSMPolicy.UpdateTestData(trigger, &op) + //Test UpdatePoliciesPolAssoId + _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { + { + //Test GetPoliciesPolAssoId + rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] + assert.True(t, exist) + req := updateReq.UeInitResReq + assert.Equal(t, rule.FlowInfos[1].FlowDescription, req.PackFiltInfo[0].PackFiltCont) + assert.True(t, models.FlowDirection(rule.FlowInfos[1].FlowDirection) == req.PackFiltInfo[0].FlowDirection) + assert.Equal(t, req.ReqQos.Var5qi, rsp.Policy.QosDecs[rule.RefQosData[0]].Var5qi) + assert.Equal(t, req.ReqQos.GbrUl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrUl) + } + } + } + } + } + { + trigger := []models.PolicyControlRequestTrigger{ + models.PolicyControlRequestTrigger_RES_MO_RE, + } + op := models.RuleOperation_MODIFY_PCC_RULE_AND_DELETE_PACKET_FILTERS + updateReq := TestSMPolicy.UpdateTestData(trigger, &op) + //Test UpdatePoliciesPolAssoId + _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { + { + //Test GetPoliciesPolAssoId + rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] + assert.True(t, exist) + assert.True(t, len(rule.FlowInfos) == 1) + } + } + } + } + } + { + trigger := []models.PolicyControlRequestTrigger{ + models.PolicyControlRequestTrigger_RES_MO_RE, + } + op := models.RuleOperation_MODIFY_PCC_RULE_AND_REPLACE_PACKET_FILTERS + updateReq := TestSMPolicy.UpdateTestData(trigger, &op) + //Test UpdatePoliciesPolAssoId + _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { + { + //Test GetPoliciesPolAssoId + rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] + assert.True(t, exist) + assert.True(t, len(rule.FlowInfos) == 1) + req := updateReq.UeInitResReq + assert.Equal(t, rule.FlowInfos[0].FlowDescription, req.PackFiltInfo[0].PackFiltCont) + assert.True(t, models.FlowDirection(rule.FlowInfos[0].FlowDirection) == req.PackFiltInfo[0].FlowDirection) + } + } + } + } + } + { + trigger := []models.PolicyControlRequestTrigger{ + models.PolicyControlRequestTrigger_RES_MO_RE, + } + op := models.RuleOperation_MODIFY_PCC_RULE_WITHOUT_MODIFY_PACKET_FILTERS + updateReq := TestSMPolicy.UpdateTestData(trigger, &op) + //Test UpdatePoliciesPolAssoId + _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { + { + //Test GetPoliciesPolAssoId + rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] + assert.True(t, exist) + req := updateReq.UeInitResReq + assert.Equal(t, req.ReqQos.Var5qi, rsp.Policy.QosDecs[rule.RefQosData[0]].Var5qi) + assert.Equal(t, req.ReqQos.GbrUl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrUl) + assert.Equal(t, req.ReqQos.GbrDl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrDl) + } + } + } + } + } + { + trigger := []models.PolicyControlRequestTrigger{ + models.PolicyControlRequestTrigger_RES_MO_RE, + } + op := models.RuleOperation_DELETE_PCC_RULE + updateReq := TestSMPolicy.UpdateTestData(trigger, &op) + //Test UpdatePoliciesPolAssoId + _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { + { + //Test GetPoliciesPolAssoId + rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusOK, httpRsp.StatusCode) + assert.True(t, len(rsp.Policy.PccRules) == 0) + assert.True(t, len(rsp.Policy.QosDecs) == 0) + } + } + } + } + } +} + +func TestSMPolicyNotification(t *testing.T) { + + configuration := Npcf_AMPolicy.NewConfiguration() + configuration.SetBasePath("https://127.0.0.1:29507") + amclient := Npcf_AMPolicy.NewAPIClient(configuration) + configuration1 := Npcf_SMPolicyControl.NewConfiguration() + configuration1.SetBasePath("https://127.0.0.1:29507") + smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) + go func() { // fake udr server + router := gin.Default() + + router.POST("nsmf-callback/v1/sm-policies/:smPolicyId/update", func(c *gin.Context) { + smPolicyId := c.Param("smPolicyId") + fmt.Println("==========SM Policy Update Notification Callback=============") + fmt.Println("smPolicyId: ", smPolicyId) + + var notification models.SmPolicyNotification + if err := c.ShouldBindJSON(¬ification); err != nil { + fmt.Println("fake smf server error") + c.JSON(http.StatusInternalServerError, gin.H{}) + return + } + c.JSON(http.StatusNoContent, gin.H{}) + }) + + router.POST("nsmf-callback/v1/sm-policies/:smPolicyId/terminate", func(c *gin.Context) { + smPolicyId := c.Param("smPolicyId") + fmt.Println("==========SM Policy Terminate Callback=============") + fmt.Println("smPolicyId: ", smPolicyId) + + var terminationNotification models.TerminationNotification + if err := c.ShouldBindJSON(&terminationNotification); err != nil { + fmt.Println("fake smf server error") + c.JSON(http.StatusInternalServerError, gin.H{}) + return + } + c.JSON(http.StatusNoContent, gin.H{}) + httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdDeletePost(context.Background(), smPolicyId, models.SmPolicyDeleteData{}) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) + } + }) + + smfLogPath := path_util.Gofree5gcPath("free5gc/smfsslkey.log") + smfPemPath := path_util.Gofree5gcPath("free5gc/support/TLS/smf.pem") + smfKeyPath := path_util.Gofree5gcPath("free5gc/support/TLS/smf.key") + + server, err := http2_util.NewServer(":8888", smfLogPath, router) + if err == nil && server != nil { + logger.InitLog.Infoln(server.ListenAndServeTLS(smfPemPath, smfKeyPath)) + } + assert.True(t, err == nil) + }() + + time.Sleep(100 * time.Millisecond) + + //Test PostPolicies + { + amCreateReqData := TestAMPolicy.GetAMreqdata() + _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + index := strings.LastIndex(locationHeader, "/") + assert.True(t, index != -1) + polAssoId := locationHeader[index+1:] + assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) + } + } + smPolicyId := "imsi-2089300007487-1" + smCreateReqData := TestSMPolicy.CreateTestData() + smCreateReqData.NotificationUri = "https://127.0.0.1:8888/nsmf-callback/v1/sm-policies/imsi-2089300007487-1" + { + _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) + assert.True(t, err == nil) + assert.True(t, httpRsp != nil) + if httpRsp != nil { + assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) + locationHeader := httpRsp.Header.Get("Location") + // index := strings.LastIndex(locationHeader, "/") + assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") + } + } + + ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] + //Test Policies Update Notify + notification := models.SmPolicyNotification{ + ResourceUri: smCreateReqData.NotificationUri, + } + pcf_producer.SendSMPolicyUpdateNotification(ue, smPolicyId, notification) + + //Test Policies Termination Notify + termination := models.TerminationNotification{ + ResourceUri: smCreateReqData.NotificationUri, + Cause: models.PolicyAssociationReleaseCause_UNSPECIFIED, + } + pcf_producer.SendSMPolicyTerminationRequestNotification(ue, smPolicyId, termination) + + time.Sleep(200 * time.Millisecond) +} diff --git a/SMPolicy/routers.go b/SMPolicy/routers.go new file mode 100644 index 0000000..42d02cc --- /dev/null +++ b/SMPolicy/routers.go @@ -0,0 +1,101 @@ +/* + * Npcf_SMPolicyControl + * + * Session Management Policy Control Service + * + * API version: 1.0.1 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package SMPolicy + +import ( + "net/http" + "strings" + + "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() + AddService(router) + return router +} + +func AddService(engine *gin.Engine) *gin.RouterGroup { + group := engine.Group("/npcf-smpolicycontrol/v1") + + for _, route := range routes { + switch route.Method { + case "GET": + group.GET(route.Pattern, route.HandlerFunc) + case "POST": + group.POST(route.Pattern, route.HandlerFunc) + case "PUT": + group.PUT(route.Pattern, route.HandlerFunc) + case "DELETE": + group.DELETE(route.Pattern, route.HandlerFunc) + case "PATCH": + group.PATCH(route.Pattern, route.HandlerFunc) + } + } + return group +} + +// Index is the index handler. +func Index(c *gin.Context) { + c.String(http.StatusOK, "Hello World!") +} + +var routes = Routes{ + { + "Index", + "GET", + "/", + Index, + }, + + { + "SmPoliciesPost", + strings.ToUpper("Post"), + "/sm-policies", + SmPoliciesPost, + }, + + { + "SmPoliciesSmPolicyIdDeletePost", + strings.ToUpper("Post"), + "/sm-policies/:smPolicyId/delete", + SmPoliciesSmPolicyIdDeletePost, + }, + + { + "SmPoliciesSmPolicyIdGet", + strings.ToUpper("Get"), + "/sm-policies/:smPolicyId", + SmPoliciesSmPolicyIdGet, + }, + + { + "SmPoliciesSmPolicyIdUpdatePost", + strings.ToUpper("Post"), + "/sm-policies/:smPolicyId/update", + SmPoliciesSmPolicyIdUpdatePost, + }, +} diff --git a/UEPolicy/api_default.go b/UEPolicy/api_default.go new file mode 100644 index 0000000..00b0b78 --- /dev/null +++ b/UEPolicy/api_default.go @@ -0,0 +1,34 @@ +/* + * Npcf_UEPolicyControl + * + * UE Policy Control Service API + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package UEPolicy + +import ( + "github.com/gin-gonic/gin" +) + +// PoliciesPolAssoIdDelete - +func PoliciesPolAssoIdDelete(c *gin.Context) { + +} + +// PoliciesPolAssoIdGet - +func PoliciesPolAssoIdGet(c *gin.Context) { + +} + +// PoliciesPolAssoIdUpdatePost - +func PoliciesPolAssoIdUpdatePost(c *gin.Context) { + +} + +// PoliciesPost - +func PoliciesPost(c *gin.Context) { + +} diff --git a/UEPolicy/routers.go b/UEPolicy/routers.go new file mode 100644 index 0000000..8818564 --- /dev/null +++ b/UEPolicy/routers.go @@ -0,0 +1,93 @@ +/* + * Npcf_UEPolicyControl + * + * UE Policy Control Service API + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package UEPolicy + +import ( + "net/http" + "strings" + + "github.com/gin-gonic/gin" +) + +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 +} + +type Routes []Route + +func NewRouter() *gin.Engine { + router := gin.Default() + AddService(router) + return router +} + +func AddService(engine *gin.Engine) *gin.RouterGroup { + group := engine.Group("/npcf-ue-policy-control/v1/") + + for _, route := range routes { + switch route.Method { + case "GET": + group.GET(route.Pattern, route.HandlerFunc) + case "POST": + group.POST(route.Pattern, route.HandlerFunc) + case "PATCH": + group.PATCH(route.Pattern, route.HandlerFunc) + } + } + return group +} + +func Index(c *gin.Context) { + c.String(http.StatusOK, "Hello World!") +} + +var routes = Routes{ + { + "Index", + "GET", + "", + Index, + }, + + { + "PoliciesPolAssoIdDelete", + strings.ToUpper("Delete"), + "/policies/{polAssoId}", + PoliciesPolAssoIdDelete, + }, + + { + "PoliciesPolAssoIdGet", + strings.ToUpper("Get"), + "/policies/{polAssoId}", + PoliciesPolAssoIdGet, + }, + + { + "PoliciesPolAssoIdUpdatePost", + strings.ToUpper("Post"), + "/policies/{polAssoId}/update", + PoliciesPolAssoIdUpdatePost, + }, + + { + "PoliciesPost", + strings.ToUpper("Post"), + "/policies", + PoliciesPost, + }, +} diff --git a/factory/config_config.go b/factory/config_config.go new file mode 100644 index 0000000..4d90773 --- /dev/null +++ b/factory/config_config.go @@ -0,0 +1,11 @@ +/* + * PCF Configuration Factory + */ + +package factory + +type Config struct { + Info *Info `yaml:"info"` + + Configuration *Configuration `yaml:"configuration"` +} diff --git a/factory/config_configuration.go b/factory/config_configuration.go new file mode 100644 index 0000000..3612e78 --- /dev/null +++ b/factory/config_configuration.go @@ -0,0 +1,24 @@ +/* + * PCF Configuration Factory + */ + +package factory + +type Configuration struct { + PcfName string `yaml:"pcfName,omitempty"` + + Sbi *Sbi `yaml:"sbi,omitempty"` + + TimeFormat string `yaml:"timeFormat,omitempty"` + + DefaultBdtRefId string `yaml:"defaultBdtRefId,omitempty"` + + NrfUri string `yaml:"nrfUri,omitempty"` + + ServiceList []Service `yaml:"serviceList,omitempty"` +} + +type Service struct { + ServiceName string `yaml:"serviceName"` + SuppFeat string `yaml:"suppFeat,omitempty"` +} diff --git a/factory/config_info.go b/factory/config_info.go new file mode 100644 index 0000000..40976ea --- /dev/null +++ b/factory/config_info.go @@ -0,0 +1,11 @@ +/* + * PCF Configuration Factory + */ + +package factory + +type Info struct { + Version string `yaml:"version,omitempty"` + + Description string `yaml:"description,omitempty"` +} diff --git a/factory/config_sbi.go b/factory/config_sbi.go new file mode 100644 index 0000000..4350f72 --- /dev/null +++ b/factory/config_sbi.go @@ -0,0 +1,12 @@ +/* + * PCF Configuration Factory + */ + +package factory + +type Sbi struct { + Scheme string `yaml:"scheme"` + IPv4Addr string `yaml:"ipv4Addr,omitempty"` + // IPv6Addr string `yaml:"ipv6Addr,omitempty"` + Port int `yaml:"port,omitempty"` +} diff --git a/factory/factory.go b/factory/factory.go new file mode 100644 index 0000000..1b06f29 --- /dev/null +++ b/factory/factory.go @@ -0,0 +1,36 @@ +/* + * PCF Configuration Factory + */ + +package factory + +import ( + "fmt" + "io/ioutil" + + "gopkg.in/yaml.v2" + + "free5gc/src/pcf/logger" +) + +var PcfConfig Config + +func checkErr(err error) { + if err != nil { + err = fmt.Errorf("[Configuration] %s", err.Error()) + logger.AppLog.Fatal(err) + } +} + +// TODO: Support configuration update from REST api +func InitConfigFactory(f string) { + content, err := ioutil.ReadFile(f) + checkErr(err) + + PcfConfig = Config{} + + err = yaml.Unmarshal([]byte(content), &PcfConfig) + checkErr(err) + + logger.InitLog.Infof("Successfully initialize configuration %s", f) +} diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..e492044 --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,71 @@ +//+build !debug + +package logger + +import ( + "fmt" + "os" + "runtime" + "strings" + + "github.com/sirupsen/logrus" +) + +var log *logrus.Logger +var AppLog *logrus.Entry +var InitLog *logrus.Entry +var HandlerLog *logrus.Entry +var Bdtpolicylog *logrus.Entry +var PolicyAuthorizationlog *logrus.Entry +var AMpolicylog *logrus.Entry +var SMpolicylog *logrus.Entry +var Consumerlog *logrus.Entry +var UtilLog *logrus.Entry +var CallbackLog *logrus.Entry +var OamLog *logrus.Entry + +func init() { + log = logrus.New() + log.SetReportCaller(true) + + log.Formatter = &logrus.TextFormatter{ + ForceColors: true, + DisableColors: false, + EnvironmentOverrideColors: false, + DisableTimestamp: false, + FullTimestamp: true, + TimestampFormat: "", + DisableSorting: false, + SortingFunc: nil, + DisableLevelTruncation: false, + QuoteEmptyFields: false, + FieldMap: nil, + CallerPrettyfier: func(f *runtime.Frame) (string, string) { + orgFilename, _ := os.Getwd() + repopath := orgFilename + repopath = strings.Replace(repopath, "/bin", "", 1) + filename := strings.Replace(f.File, repopath, "", -1) + return fmt.Sprintf("%s()", f.Function), fmt.Sprintf("%s:%d", filename, f.Line) + }, + } + + AppLog = log.WithFields(logrus.Fields{"PCF": "app"}) + InitLog = log.WithFields(logrus.Fields{"PCF": "init"}) + HandlerLog = log.WithFields(logrus.Fields{"PCF": "Handler"}) + Bdtpolicylog = log.WithFields(logrus.Fields{"PCF": "bdtpolicy"}) + AMpolicylog = log.WithFields(logrus.Fields{"PCF": "ampolicy"}) + PolicyAuthorizationlog = log.WithFields(logrus.Fields{"PCF": "PolicyAuthorization"}) + SMpolicylog = log.WithFields(logrus.Fields{"PCF": "SMpolicy"}) + UtilLog = log.WithFields(logrus.Fields{"PCF": "Util"}) + CallbackLog = log.WithFields(logrus.Fields{"PCF": "Callback"}) + Consumerlog = log.WithFields(logrus.Fields{"PCF": "Consumer"}) + OamLog = log.WithFields(logrus.Fields{"PCF": "OAM"}) +} + +func SetLogLevel(level logrus.Level) { + log.SetLevel(level) +} + +func SetReportCaller(bool bool) { + log.SetReportCaller(bool) +} diff --git a/pcf.go b/pcf.go new file mode 100644 index 0000000..97fad07 --- /dev/null +++ b/pcf.go @@ -0,0 +1,51 @@ +/* + * Npcf_BDTPolicyControl Service API + * + * The Npcf_BDTPolicyControl Service is used by an NF service consumer to retrieve background data transfer policies from the PCF and to update the PCF with the background data transfer policy selected by the NF service consumer. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package main + +import ( + "fmt" + "free5gc/src/app" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_service" + "free5gc/src/pcf/version" + "os" + + "github.com/sirupsen/logrus" + "github.com/urfave/cli" +) + +var PCF = &pcf_service.PCF{} + +var appLog *logrus.Entry + +func init() { + appLog = logger.AppLog +} + +func main() { + app := cli.NewApp() + app.Name = "pcf" + fmt.Print(app.Name, "\n") + appLog.Infoln("PCF version: ", version.GetVersion()) + app.Usage = "-free5gccfg common configuration file -pcfcfg pcf configuration file" + app.Action = action + app.Flags = PCF.GetCliCmd() + + if err := app.Run(os.Args); err != nil { + fmt.Printf("PCF Run err: %v", err) + } + +} + +func action(c *cli.Context) { + app.AppInitializeWillInitialize(c.String("free5gccfg")) + PCF.Initialize(c) + PCF.Start() +} diff --git a/pcf_consumer/Communication.go b/pcf_consumer/Communication.go new file mode 100644 index 0000000..71d0fb3 --- /dev/null +++ b/pcf_consumer/Communication.go @@ -0,0 +1,47 @@ +package pcf_consumer + +import ( + "context" + "fmt" + "free5gc/lib/openapi/common" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_util" + "strings" +) + +func AmfStatusChangeSubscribe(amfInfo pcf_context.AMFStatusSubscriptionData) (problemDetails *models.ProblemDetails, err error) { + logger.Consumerlog.Debugf("PCF Subscribe to AMF status[%+v]", amfInfo.AmfUri) + pcfSelf := pcf_context.PCF_Self() + client := pcf_util.GetNamfClient(amfInfo.AmfUri) + + subscriptionData := models.SubscriptionData{ + AmfStatusUri: fmt.Sprintf("%s/npcf-callback/v1/amfstatus", pcfSelf.GetIPv4Uri()), + GuamiList: amfInfo.GuamiList, + } + + res, httpResp, localErr := client.SubscriptionsCollectionDocumentApi.AMFStatusChangeSubscribe(context.Background(), subscriptionData) + if localErr == nil { + locationHeader := httpResp.Header.Get("Location") + logger.Consumerlog.Debugf("location header: %+v", locationHeader) + + subscriptionId := locationHeader[strings.LastIndex(locationHeader, "/")+1:] + amfStatusSubsData := pcf_context.AMFStatusSubscriptionData{ + AmfUri: amfInfo.AmfUri, + AmfStatusUri: res.AmfStatusUri, + GuamiList: res.GuamiList, + } + pcfSelf.AMFStatusSubsData[subscriptionId] = amfStatusSubsData + } else if httpResp != nil { + if httpResp.Status != localErr.Error() { + err = localErr + return + } + problem := localErr.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problemDetails = &problem + } else { + err = common.ReportError("%s: server no response", amfInfo.AmfUri) + } + return +} diff --git a/pcf_consumer/NFDiscovery.go b/pcf_consumer/NFDiscovery.go new file mode 100644 index 0000000..50685ca --- /dev/null +++ b/pcf_consumer/NFDiscovery.go @@ -0,0 +1,105 @@ +package pcf_consumer + +import ( + "context" + "fmt" + "github.com/antihax/optional" + "free5gc/lib/Nnrf_NFDiscovery" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_util" + "net/http" +) + +func SendSearchNFInstances(nrfUri string, targetNfType, requestNfType models.NfType, param Nnrf_NFDiscovery.SearchNFInstancesParamOpts) (result models.SearchResult, err error) { + + // Set client and set url + configuration := Nnrf_NFDiscovery.NewConfiguration() + configuration.SetBasePath(nrfUri) + client := Nnrf_NFDiscovery.NewAPIClient(configuration) + + var res *http.Response + result, res, err = client.NFInstancesStoreApi.SearchNFInstances(context.TODO(), targetNfType, requestNfType, ¶m) + if res != nil && res.StatusCode == http.StatusTemporaryRedirect { + err = fmt.Errorf("Temporary Redirect For Non NRF Consumer") + } + return +} + +func SendNFIntancesUDR(nrfUri, id string) string { + targetNfType := models.NfType_UDR + requestNfType := models.NfType_PCF + localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ + // DataSet: optional.NewInterface(models.DataSetId_SUBSCRIPTION), + } + // switch types { + // case NFDiscoveryToUDRParamSupi: + // localVarOptionals.Supi = optional.NewString(id) + // case NFDiscoveryToUDRParamExtGroupId: + // localVarOptionals.ExternalGroupIdentity = optional.NewString(id) + // case NFDiscoveryToUDRParamGpsi: + // localVarOptionals.Gpsi = optional.NewString(id) + // } + + result, err := SendSearchNFInstances(nrfUri, targetNfType, requestNfType, localVarOptionals) + if err != nil { + logger.Consumerlog.Error(err.Error()) + return "" + } + for _, profile := range result.NfInstances { + if uri := pcf_util.SearchNFServiceUri(profile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED); uri != "" { + return uri + } + } + return "" +} + +func SendNFIntancesAMF(nrfUri string, guami models.Guami, serviceName models.ServiceName) string { + targetNfType := models.NfType_AMF + requestNfType := models.NfType_PCF + + localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ + Guami: optional.NewInterface(pcf_util.MarshToJsonString(guami)), + } + // switch types { + // case NFDiscoveryToUDRParamSupi: + // localVarOptionals.Supi = optional.NewString(id) + // case NFDiscoveryToUDRParamExtGroupId: + // localVarOptionals.ExternalGroupIdentity = optional.NewString(id) + // case NFDiscoveryToUDRParamGpsi: + // localVarOptionals.Gpsi = optional.NewString(id) + // } + + result, err := SendSearchNFInstances(nrfUri, targetNfType, requestNfType, localVarOptionals) + if err != nil { + logger.Consumerlog.Error(err.Error()) + return "" + } + for _, profile := range result.NfInstances { + return pcf_util.SearchNFServiceUri(profile, serviceName, models.NfServiceStatus_REGISTERED) + } + return "" +} + +func SearchAvailableAMFs(nrfUri string, serviceName models.ServiceName) (amfInfos []pcf_context.AMFStatusSubscriptionData) { + localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{} + + result, err := SendSearchNFInstances(nrfUri, models.NfType_AMF, models.NfType_PCF, localVarOptionals) + if err != nil { + logger.Consumerlog.Error(err.Error()) + return + } + + for _, profile := range result.NfInstances { + uri := pcf_util.SearchNFServiceUri(profile, serviceName, models.NfServiceStatus_REGISTERED) + if uri != "" { + item := pcf_context.AMFStatusSubscriptionData{ + AmfUri: uri, + GuamiList: *profile.AmfInfo.GuamiList, + } + amfInfos = append(amfInfos, item) + } + } + return +} diff --git a/pcf_consumer/NFManagement.go b/pcf_consumer/NFManagement.go new file mode 100644 index 0000000..bc318b1 --- /dev/null +++ b/pcf_consumer/NFManagement.go @@ -0,0 +1,73 @@ +package pcf_consumer + +import ( + "context" + "fmt" + "free5gc/lib/Nnrf_NFManagement" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/pcf_context" + "net/http" + "strings" + "time" +) + +func BuildNFInstance(context *pcf_context.PCFContext) (profile models.NfProfile, err error) { + profile.NfInstanceId = context.NfId + profile.NfType = models.NfType_PCF + profile.NfStatus = models.NfStatus_REGISTERED + profile.Ipv4Addresses = append(profile.Ipv4Addresses, context.HttpIPv4Address) + service := []models.NfService{} + for _, nfService := range context.NfService { + service = append(service, nfService) + } + profile.NfServices = &service + profile.PcfInfo = &models.PcfInfo{ + DnnList: []string{ + "free5gc", + "internet", + }, + // SupiRanges: &[]models.SupiRange{ + // { + // //from TS 29.510 6.1.6.2.9 example2 + // //no need to set supirange in this moment 2019/10/4 + // Start: "123456789040000", + // End: "123456789059999", + // Pattern: "^imsi-12345678904[0-9]{4}$", + // }, + // }, + } + return +} + +func SendRegisterNFInstance(nrfUri, nfInstanceId string, profile models.NfProfile) (resouceNrfUri string, retrieveNfInstanceID string, err error) { + + // Set client and set url + configuration := Nnrf_NFManagement.NewConfiguration() + configuration.SetBasePath(nrfUri) + client := Nnrf_NFManagement.NewAPIClient(configuration) + + var res *http.Response + for { + _, res, err = client.NFInstanceIDDocumentApi.RegisterNFInstance(context.TODO(), nfInstanceId, profile) + if err != nil || res == nil { + //TODO : add log + fmt.Println(fmt.Errorf("PCF register to NRF Error[%v]", err.Error())) + time.Sleep(2 * time.Second) + continue + } + status := res.StatusCode + if status == http.StatusOK { + // NFUpdate + break + } else if status == http.StatusCreated { + // NFRegister + resourceUri := res.Header.Get("Location") + resouceNrfUri = resourceUri[:strings.Index(resourceUri, "/nnrf-nfm/")] + retrieveNfInstanceID = resourceUri[strings.LastIndex(resourceUri, "/")+1:] + break + } else { + fmt.Println("NRF return wrong status code", status) + } + } + return +} diff --git a/pcf_consumer/NFManagement_test.go b/pcf_consumer/NFManagement_test.go new file mode 100644 index 0000000..6c5d64f --- /dev/null +++ b/pcf_consumer/NFManagement_test.go @@ -0,0 +1,50 @@ +package pcf_consumer_test + +import ( + "flag" + "free5gc/lib/MongoDBLibrary" + "free5gc/lib/Nnrf_NFDiscovery" + "free5gc/lib/openapi/models" + "free5gc/src/nrf/nrf_service" + "free5gc/src/pcf/factory" + "free5gc/src/pcf/pcf_consumer" + "free5gc/src/pcf/pcf_service" + "testing" + "time" + + "github.com/antihax/optional" + "github.com/urfave/cli" + "go.mongodb.org/mongo-driver/bson" +) + +var flags flag.FlagSet +var c = cli.NewContext(nil, &flags, nil) + +func nrfInit() { + nrf := &nrf_service.NRF{} + nrf.Initialize(c) + go nrf.Start() + time.Sleep(100 * time.Millisecond) +} +func TestRegisterNFInstance(t *testing.T) { + // init NRF + nrfInit() + // Clear DB + MongoDBLibrary.RestfulAPIDeleteMany("NfProfile", bson.M{}) + time.Sleep(50 * time.Millisecond) + // Init PCF and register to NRF + pcf := pcf_service.PCF{} + pcf.Initialize(c) + go pcf.Start() + time.Sleep(50 * time.Millisecond) + // Send NF Discovery to discover PCF + param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ + ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NPCF_AM_POLICY_CONTROL, models.ServiceName_NPCF_BDTPOLICYCONTROL, models.ServiceName_NPCF_POLICYAUTHORIZATION, models.ServiceName_NPCF_SMPOLICYCONTROL, models.ServiceName_NPCF_UE_POLICY_CONTROL}), + } + result, err := pcf_consumer.SendSearchNFInstances(factory.PcfConfig.Configuration.NrfUri, models.NfType_PCF, models.NfType_UDR, param) + if err != nil { + t.Error(err.Error()) + } else if result.NfInstances == nil { + t.Error("NF Instances is nil") + } +} diff --git a/pcf_context/context.go b/pcf_context/context.go new file mode 100644 index 0000000..1d7f31c --- /dev/null +++ b/pcf_context/context.go @@ -0,0 +1,285 @@ +package pcf_context + +import ( + "fmt" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/factory" + "strconv" + "strings" +) + +var pcfContext = PCFContext{} + +func init() { + PCF_Self().Name = "pcf" + PCF_Self().UriScheme = models.UriScheme_HTTPS + PCF_Self().TimeFormat = "2006-01-02 15:04:05" + PCF_Self().DefaultBdtRefId = "BdtPolicyId-" + PCF_Self().NfService = make(map[models.ServiceName]models.NfService) + PCF_Self().PcfServiceUris = make(map[models.ServiceName]string) + PCF_Self().PcfSuppFeats = make(map[models.ServiceName][]byte) + PCF_Self().UePool = make(map[string]*UeContext) + PCF_Self().BdtPolicyPool = make(map[string]models.BdtPolicy) + PCF_Self().BdtPolicyIdGenerator = 1 + PCF_Self().AppSessionPool = make(map[string]*AppSessionData) + PCF_Self().AMFStatusSubsData = make(map[string]AMFStatusSubscriptionData) +} + +type PCFContext struct { + NfId string + Name string + UriScheme models.UriScheme + HttpIPv4Address string + HttpIpv4Port int + TimeFormat string + DefaultBdtRefId string + NfService map[models.ServiceName]models.NfService + PcfServiceUris map[models.ServiceName]string + PcfSuppFeats map[models.ServiceName][]byte + NrfUri string + DefaultUdrUri string + UePool map[string]*UeContext + // Bdt Policy related + BdtPolicyPool map[string]models.BdtPolicy // use BdtPolicyId as key + BdtPolicyIdGenerator uint64 + // App Session related + AppSessionPool map[string]*AppSessionData // use AppSessionId(ue.Supi-%d) or (BdtRefId-%d) as key + // AMF Status Change Subscription related + AMFStatusSubsData map[string]AMFStatusSubscriptionData // subscriptionId as key +} + +type AMFStatusSubscriptionData struct { + AmfUri string + AmfStatusUri string + GuamiList []models.Guami +} + +type AppSessionData struct { + AppSessionId string + AppSessionContext *models.AppSessionContext + // (compN/compN-subCompN/appId-%s) map to PccRule + RelatedPccRuleIds map[string]string + PccRuleIdMapToCompId map[string]string + // EventSubscription + Events map[models.AfEvent]models.AfNotifMethod + EventUri string + // related Session + SmPolicyData *UeSmPolicyData +} + +// Create new PCF context +func PCF_Self() *PCFContext { + return &pcfContext +} +func GetTimeformat() string { + return pcfContext.TimeFormat +} +func GetPcfContext() PCFContext { + return pcfContext +} +func GetUri(name models.ServiceName) string { + return pcfContext.PcfServiceUris[name] +} + +var PolicyAuthorizationUri = "/npcf-policyauthorization/v1/app-sessions/" +var SmUri = "/npcf-smpolicycontrol/v1" +var IPv4Address = "192.168." +var IPv6Address = "ffab::" +var CheckNotifiUri = "/npcf-callback/v1/nudr-notify/" +var Ipv4_pool = make(map[string]string) +var Ipv6_pool = make(map[string]string) + +// BdtPolicy default value +const DefaultBdtRefId = "BdtPolicyId-" + +func (context *PCFContext) GetIPv4Uri() string { + return fmt.Sprintf("%s://%s:%d", context.UriScheme, context.HttpIPv4Address, context.HttpIpv4Port) +} + +// Init NfService with supported service list ,and version of services +func (context *PCFContext) InitNFService(serviceList []factory.Service, version string) { + tmpVersion := strings.Split(version, ".") + versionUri := "v" + tmpVersion[0] + for index, service := range serviceList { + name := models.ServiceName(service.ServiceName) + context.NfService[name] = models.NfService{ + ServiceInstanceId: strconv.Itoa(index), + ServiceName: name, + Versions: &[]models.NfServiceVersion{ + { + ApiFullVersion: version, + ApiVersionInUri: versionUri, + }, + }, + Scheme: context.UriScheme, + NfServiceStatus: models.NfServiceStatus_REGISTERED, + ApiPrefix: context.GetIPv4Uri(), + IpEndPoints: &[]models.IpEndPoint{ + { + Ipv4Address: context.HttpIPv4Address, + Transport: models.TransportProtocol_TCP, + Port: int32(context.HttpIpv4Port), + }, + }, + SupportedFeatures: service.SuppFeat, + } + } +} + +// Allocate PCF Ue with supi and add to pcf Context and returns allocated ue +func (context *PCFContext) NewPCFUe(Supi string) (*UeContext, error) { + if strings.HasPrefix(Supi, "imsi-") { + context.UePool[Supi] = &UeContext{} + context.UePool[Supi].SmPolicyData = make(map[string]*UeSmPolicyData) + context.UePool[Supi].AMPolicyData = make(map[string]*UeAMPolicyData) + context.UePool[Supi].PolAssociationIDGenerator = 1 + context.UePool[Supi].AppSessionIdGenerator = 1 + context.UePool[Supi].Supi = Supi + return context.UePool[Supi], nil + } else { + return nil, fmt.Errorf(" add Ue context fail ") + } +} + +// Return Bdt Policy Id with format "BdtPolicyId-%d" which be allocated +func (context *PCFContext) AllocBdtPolicyId() string { + bdtPolicyId := fmt.Sprintf("BdtPolicyId-%d", context.BdtPolicyIdGenerator) + _, exist := context.BdtPolicyPool[bdtPolicyId] + for exist { + context.BdtPolicyIdGenerator++ + bdtPolicyId := fmt.Sprintf("BdtPolicyId-%d", context.BdtPolicyIdGenerator) + _, exist = context.BdtPolicyPool[bdtPolicyId] + } + context.BdtPolicyIdGenerator++ + return bdtPolicyId +} + +// Find PcfUe which the policyId belongs to +func (context *PCFContext) PCFUeFindByPolicyId(PolicyId string) *UeContext { + index := strings.LastIndex(PolicyId, "-") + if index == -1 { + return nil + } + supi := PolicyId[:index] + if supi != "" { + return context.UePool[supi] + } + return nil +} + +// Find PcfUe which the AppSessionId belongs to +func (context *PCFContext) PCFUeFindByAppSessionId(appSessionId string) *UeContext { + index := strings.LastIndex(appSessionId, "-") + if index == -1 { + return nil + } + supi := appSessionId[:index] + if supi != "" { + return context.UePool[supi] + } + return nil +} + +// Find PcfUe which Ipv4 belongs to +func (context *PCFContext) PcfUeFindByIPv4(v4 string) *UeContext { + for _, ue := range context.UePool { + if ue.SMPolicyFindByIpv6(v4) != nil { + return ue + } + } + return nil +} + +// Find PcfUe which Ipv6 belongs to +func (context *PCFContext) PcfUeFindByIPv6(v6 string) *UeContext { + for _, ue := range context.UePool { + if ue.SMPolicyFindByIpv6(v6) != nil { + return ue + } + } + return nil +} + +// Session Binding from application request to get corresponding Sm policy +func (context *PCFContext) SessionBinding(req *models.AppSessionContextReqData) (policy *UeSmPolicyData, err error) { + // TODO: support dnn, snssai, ... because Ip Address is not enough with same ip address in different ip domains, details in subclause 4.2.2.2 of TS 29514 + if ue, exist := context.UePool[req.Supi]; exist { + if req.UeIpv4 != "" { + policy = ue.SMPolicyFindByIpv4(req.UeIpv4) + } else if req.UeIpv6 != "" { + policy = ue.SMPolicyFindByIpv6(req.UeIpv6) + } else { + err = fmt.Errorf("Ue finding by MAC address does not support") + } + } else if req.UeIpv4 != "" { + policy = ue.SMPolicyFindByIpv4(req.UeIpv4) + } else if req.UeIpv6 != "" { + policy = ue.SMPolicyFindByIpv6(req.UeIpv6) + } else { + err = fmt.Errorf("Ue finding by MAC address does not support") + } + if err == nil && policy == nil { + if req.UeIpv4 != "" { + err = fmt.Errorf("Can't find Ue with Ipv4[%s]", req.UeIpv4) + } else { + err = fmt.Errorf("Can't find Ue with Ipv6[%s]", req.UeIpv6) + } + } + return +} + +func Ipv4Pool(ipindex int32) string { + ipv4address := IPv4Address + fmt.Sprint((int(ipindex)/255)+1) + "." + fmt.Sprint(int(ipindex)%255) + return ipv4address +} +func Ipv4Index() int32 { + + if len(Ipv4_pool) == 0 { + Ipv4_pool["1"] = Ipv4Pool(1) + } else { + for i := 1; i <= len(Ipv4_pool); i++ { + if Ipv4_pool[fmt.Sprint(i)] == "" { + Ipv4_pool[fmt.Sprint(i)] = Ipv4Pool(int32(i)) + return int32(i) + } + } + + Ipv4_pool[fmt.Sprint(int32(len(Ipv4_pool)+1))] = Ipv4Pool(int32(len(Ipv4_pool) + 1)) + return int32(len(Ipv4_pool)) + } + return 1 +} +func GetIpv4Address(ipindex int32) string { + return Ipv4_pool[fmt.Sprint(ipindex)] +} +func DeleteIpv4index(Ipv4index int32) { + delete(Ipv4_pool, fmt.Sprint(Ipv4index)) +} +func Ipv6Pool(ipindex int32) string { + + ipv6address := IPv6Address + fmt.Sprintf("%x\n", ipindex) + return ipv6address +} +func Ipv6Index() int32 { + + if len(Ipv6_pool) == 0 { + Ipv6_pool["1"] = Ipv6Pool(1) + } else { + for i := 1; i <= len(Ipv6_pool); i++ { + if Ipv6_pool[fmt.Sprint(i)] == "" { + Ipv6_pool[fmt.Sprint(i)] = Ipv6Pool(int32(i)) + return int32(i) + } + } + + Ipv6_pool[fmt.Sprint(int32(len(Ipv6_pool)+1))] = Ipv6Pool(int32(len(Ipv6_pool) + 1)) + return int32(len(Ipv6_pool)) + } + return 1 +} +func GetIpv6Address(ipindex int32) string { + return Ipv6_pool[fmt.Sprint(ipindex)] +} +func DeleteIpv6index(Ipv6index int32) { + delete(Ipv6_pool, fmt.Sprint(Ipv6index)) +} diff --git a/pcf_context/ue.go b/pcf_context/ue.go new file mode 100644 index 0000000..e409e9c --- /dev/null +++ b/pcf_context/ue.go @@ -0,0 +1,436 @@ +package pcf_context + +import ( + "fmt" + "free5gc/lib/openapi/models" + "math" + "reflect" + "strconv" + "strings" +) + +// key is supi +type UeContext struct { + // Ue Context + Supi string + Gpsi string + Pei string + GroupIds []string + PolAssociationIDGenerator uint32 + AMPolicyData map[string]*UeAMPolicyData // use PolAssoId(ue.Supi-numPolId) as key + + // Udr Ref + UdrUri string + // SMPolicy + SmPolicyData map[string]*UeSmPolicyData // use smPolicyId(ue.Supi-pduSessionId) as key + // App Session Related + AppSessionIdGenerator uint64 + // PolicyAuth + AfRoutReq *models.AfRoutingRequirement + AspId string + // Policy Decision + AppSessionIdStore *AppSessionIdStore + PolicyDataSubscriptionStore *models.PolicyDataSubscription + PolicyDataChangeStore *models.PolicyDataChangeNotification +} + +type UeAMPolicyData struct { + PolAssoId string + AccessType models.AccessType + NotificationUri string + ServingPlmn *models.NetworkId + AltNotifIpv4Addrs []string + AltNotifIpv6Addrs []string + // TODO: AMF Status Change + AmfStatusUri string + Guami *models.Guami + ServiveName string + // TraceReq *TraceData + // Policy Association + Triggers []models.RequestTrigger + ServAreaRes *models.ServiceAreaRestriction + Rfsp int32 + UserLoc *models.UserLocation + TimeZone string + SuppFeat string + // about AF request + Pras map[string]models.PresenceInfo + // related to UDR Subscription Data + AmPolicyData *models.AmPolicyData // Svbscription Data + // Corresponding UE + PcfUe *UeContext + // AMF status change subscription + AmfStatusChangeSubscription *AMFStatusSubscriptionData +} + +type UeSmPolicyData struct { + // PduSessionId int32 + // DNN string + // NotificationUri string + // Snssai models.Snssai + // PduSessionType models.PduSessionType + // IPAddress models.IpAddress + // IPDomain string + // Var3gppPsDataOffStatus bool + // SmfId string + // TraceReq *TraceData + // RecoveryTime *time.Time + PackFiltIdGenarator int32 + PccRuleIdGenarator int32 + ChargingIdGenarator int32 + // FlowMapsToPackFiltIds map[string][]string // use Flow Description(in TS 29214) as key map to pcc rule ids + PackFiltMapToPccRuleId map[string]string // use PackFiltId as Key + // Related to GBR + RemainGbrUL *float64 + RemainGbrDL *float64 + // related to UDR Subscription Data + SmPolicyData *models.SmPolicyData // Svbscription Data + // related to Policy + PolicyContext *models.SmPolicyContextData + PolicyDecision *models.SmPolicyDecision + // related to AppSession + AppSessions map[string]bool // related appSessionId + // Corresponding UE + PcfUe *UeContext +} + +// NewUeAMPolicyData returns created UeAMPolicyData data and insert this data to Ue.AMPolicyData with assolId as key +func (ue *UeContext) NewUeAMPolicyData(assolId string, req models.PolicyAssociationRequest) *UeAMPolicyData { + ue.Gpsi = req.Gpsi + ue.Pei = req.Pei + ue.GroupIds = req.GroupIds + ue.AMPolicyData[assolId] = &UeAMPolicyData{ + PolAssoId: assolId, + ServAreaRes: req.ServAreaRes, + AltNotifIpv4Addrs: req.AltNotifIpv4Addrs, + AltNotifIpv6Addrs: req.AltNotifIpv6Addrs, + AccessType: req.AccessType, + NotificationUri: req.NotificationUri, + ServingPlmn: req.ServingPlmn, + TimeZone: req.TimeZone, + Rfsp: req.Rfsp, + Guami: req.Guami, + UserLoc: req.UserLoc, + ServiveName: req.ServiveName, + PcfUe: ue, + } + ue.AMPolicyData[assolId].Pras = make(map[string]models.PresenceInfo) + return ue.AMPolicyData[assolId] +} + +// returns UeSmPolicyData and insert related info to Ue with smPolId +func (ue *UeContext) NewUeSmPolicyData(key string, request models.SmPolicyContextData, smData *models.SmPolicyData) *UeSmPolicyData { + if smData == nil { + return nil + } + data := UeSmPolicyData{} + data.PolicyContext = &request + // data.DNN = request.Dnn + // data.Snssai = *request.SliceInfo + // data.PduSessionId = request.PduSessionId + // data.PduSessionType = request.PduSessionType + // switch request.PduSessionType { + // case models.PduSessionType_IPV4: + // data.IPAddress.Ipv4Addr = request.Ipv4Address + // data.IPDomain = request.IpDomain + // case models.PduSessionType_IPV6: + // data.IPAddress.Ipv6Prefix = request.Ipv6AddressPrefix + // case models.PduSessionType_IPV4_V6: + // data.IPAddress.Ipv4Addr = request.Ipv4Address + // data.IPAddress.Ipv6Prefix = request.Ipv6AddressPrefix + // data.IPDomain = request.IpDomain + // } + // data.NotificationUri = request.NotificationUri + // data.SmfId = request.SmfId + // data.Var3gppPsDataOffStatus = request.Var3gppPsDataOffStatus + data.SmPolicyData = smData + data.PackFiltIdGenarator = 1 + data.PackFiltMapToPccRuleId = make(map[string]string) + data.AppSessions = make(map[string]bool) + // data.RefToAmPolicy = amData + data.PccRuleIdGenarator = 1 + data.ChargingIdGenarator = 1 + data.PcfUe = ue + ue.SmPolicyData[key] = &data + return &data +} + +// Remove Pcc rule wich PccRuleId in the policy +func (policy *UeSmPolicyData) RemovePccRule(pccRuleId string) error { + decision := policy.PolicyDecision + if decision == nil { + return fmt.Errorf("Can't find the Policy Decision") + } + if rule, exist := decision.PccRules[pccRuleId]; exist { + for _, info := range rule.FlowInfos { + delete(policy.PackFiltMapToPccRuleId, info.PackFiltId) + } + for _, id := range rule.RefQosData { + if decision.QosDecs != nil { + policy.IncreaseRemainGBR(id) + delete(decision.QosDecs, id) + if len(decision.QosDecs) == 0 { + decision.QosDecs = nil + } + } else { + break + } + } + if rule.RefCondData != "" { + if decision.Conds != nil { + delete(decision.Conds, rule.RefCondData) + if len(decision.Conds) == 0 { + decision.Conds = nil + } + } + } + for _, id := range rule.RefChgData { + if decision.ChgDecs != nil { + delete(decision.ChgDecs, id) + if len(decision.ChgDecs) == 0 { + decision.ChgDecs = nil + } + } else { + break + } + } + for _, id := range rule.RefTcData { + if decision.TraffContDecs != nil { + delete(decision.TraffContDecs, id) + if len(decision.TraffContDecs) == 0 { + decision.TraffContDecs = nil + } + } else { + break + } + } + for _, id := range rule.RefUmData { + if decision.UmDecs != nil { + delete(decision.UmDecs, id) + if len(decision.UmDecs) == 0 { + decision.UmDecs = nil + } + } else { + break + } + } + delete(decision.PccRules, pccRuleId) + } else { + return fmt.Errorf("Can't find the pccRuleId[%s] in Session[%d]", pccRuleId, policy.PolicyContext.PduSessionId) + } + return nil +} + +// Check if the afEvent exists in smPolicy +func (policy *UeSmPolicyData) CheckRelatedAfEvent(event models.AfEvent) (found bool) { + for appSessionId := range policy.AppSessions { + if appSession, exist := PCF_Self().AppSessionPool[appSessionId]; exist { + for afEvent := range appSession.Events { + if afEvent == event { + return true + } + } + } + } + return false +} + +// Arrange Exist Event policy Sm policy about afevents and return if it changes or not and +func (policy *UeSmPolicyData) ArrangeExistEventSubscription() (changed bool) { + triggers := []models.PolicyControlRequestTrigger{} + for _, trigger := range policy.PolicyDecision.PolicyCtrlReqTriggers { + var afEvent models.AfEvent + switch trigger { + case models.PolicyControlRequestTrigger_PLMN_CH: // PLMN Change + afEvent = models.AfEvent_PLMN_CHG + case models.PolicyControlRequestTrigger_QOS_NOTIF: // SMF notify PCF when receiving from RAN that QoS can/can't be guaranteed (subsclause 4.2.4.20 in TS29512) (always) + afEvent = models.AfEvent_QOS_NOTIF + case models.PolicyControlRequestTrigger_SUCC_RES_ALLO: // Successful resource allocation (subsclause 4.2.6.5.5, 4.2.4.14 in TS29512) + afEvent = models.AfEvent_SUCCESSFUL_RESOURCES_ALLOCATION + case models.PolicyControlRequestTrigger_AC_TY_CH: // Change of RatType + afEvent = models.AfEvent_ACCESS_TYPE_CHANGE + case models.PolicyControlRequestTrigger_US_RE: // UMC + afEvent = models.AfEvent_USAGE_REPORT + } + if afEvent != "" && !policy.CheckRelatedAfEvent(afEvent) { + changed = true + } else { + triggers = append(triggers, trigger) + } + } + policy.PolicyDecision.PolicyCtrlReqTriggers = triggers + return +} + +// Increase remain GBR of this policy and returns original UL DL GBR for resume case +func (policy *UeSmPolicyData) IncreaseRemainGBR(qosId string) (origUl, origDl *float64) { + decision := policy.PolicyDecision + if decision == nil { + return + } + if qos, exist := decision.QosDecs[qosId]; exist { + if qos.Var5qi <= 4 { + // Add GBR + origUl = IncreaseRamainBitRate(policy.RemainGbrUL, qos.GbrUl) + origDl = IncreaseRamainBitRate(policy.RemainGbrDL, qos.GbrDl) + } + } + return +} + +// Increase remain Bit Rate and returns original Bit Rate +func IncreaseRamainBitRate(remainBitRate *float64, reqBitRate string) (orig *float64) { + if remainBitRate != nil && reqBitRate != "" { + bitRate, err := ConvertBitRateToKbps(reqBitRate) + if err == nil { + orig = new(float64) + *orig = *remainBitRate + *remainBitRate += bitRate + } + } + return +} + +// Decrease remain GBR of this policy and returns UL DL GBR +func (policy *UeSmPolicyData) DecreaseRemainGBR(req *models.RequestedQos) (gbrDl, gbrUl string, err error) { + if req == nil { + return "", "", nil + } + if req.Var5qi <= 4 { + err = DecreaseRamainBitRate(policy.RemainGbrDL, req.GbrDl) + if err != nil { + return + } + gbrDl = req.GbrDl + err = DecreaseRamainBitRate(policy.RemainGbrUL, req.GbrUl) + if err != nil { + return + } + gbrUl = req.GbrUl + } + return +} + +// Decrease remain Bit Rate +func DecreaseRamainBitRate(remainBitRate *float64, reqBitRate string) error { + if reqBitRate != "" { + bitRate, err := ConvertBitRateToKbps(reqBitRate) + if err != nil { + return err + } + if remainBitRate != nil { + if *remainBitRate < bitRate { + return fmt.Errorf("Request BitRate exceed Dnn Aggregate BitRate of UE") + } + *remainBitRate -= bitRate + } + } + return nil +} + +// Returns remin Bit rate string and decrease ir to zero +func DecreaseRamainBitRateToZero(remainBitRate *float64) string { + if remainBitRate != nil { + bitRate := ConvertBitRateToString(*remainBitRate) + *remainBitRate = 0 + return bitRate + } + return "" +} + +// returns AM Policy which AccessType and plmnId match +func (ue *UeContext) FindAMPolicy(anType models.AccessType, plmnId *models.NetworkId) *UeAMPolicyData { + if ue == nil || plmnId == nil { + return nil + } + for _, amPolicy := range ue.AMPolicyData { + if amPolicy.AccessType == anType && reflect.DeepEqual(*amPolicy.ServingPlmn, *plmnId) { + return amPolicy + } + } + return nil +} + +// Return App Session Id with format "ue.Supi-%d" which be allocated +func (ue *UeContext) AllocUeAppSessionId(context *PCFContext) string { + appSessionId := fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator) + _, exist := context.AppSessionPool[appSessionId] + for exist { + ue.AppSessionIdGenerator++ + appSessionId = fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator) + _, exist = context.AppSessionPool[appSessionId] + } + ue.AppSessionIdGenerator++ + return appSessionId +} + +// returns SM Policy by IPv4 +func (ue *UeContext) SMPolicyFindByIpv4(v4 string) *UeSmPolicyData { + for _, smPolicy := range ue.SmPolicyData { + if smPolicy.PolicyContext.Ipv4Address == v4 { + return smPolicy + } + } + return nil +} + +// returns SM Policy by IPv6 +func (ue *UeContext) SMPolicyFindByIpv6(v6 string) *UeSmPolicyData { + for _, smPolicy := range ue.SmPolicyData { + if smPolicy.PolicyContext.Ipv6AddressPrefix == v6 { + return smPolicy + } + } + return nil +} + +// AppSessionIdStore - +type AppSessionIdStore struct { + AppSessionId string + AppSessionContext models.AppSessionContext +} + +var AppSessionContextStore []AppSessionIdStore + +// BdtPolicyData_store - +var BdtPolicyData_store []models.BdtPolicyData +var CreateFailBdtDateStore []models.BdtData + +// Convert bitRate string to float64 with uint Kbps +func ConvertBitRateToKbps(bitRate string) (kBitRate float64, err error) { + list := strings.Split(bitRate, " ") + if len(list) != 2 { + err := fmt.Errorf("bitRate format error") + return 0, err + } + // parse exponential value with 2 as base + exp := 0.0 + switch list[1] { + case "Tbps": + exp = 30.0 + case "Gbps": + exp = 20.0 + case "Mbps": + exp = 10.0 + case "Kbps": + exp = 0.0 + case "bps": + exp = -10.0 + default: + err := fmt.Errorf("bitRate format error") + return 0, err + } + // parse value from string to float64 + kBitRate, err = strconv.ParseFloat(list[0], 64) + if err == nil { + kBitRate = kBitRate * math.Pow(2, exp) + } else { + kBitRate = 0.0 + } + return +} + +// Convert bitRate from float64 to String +func ConvertBitRateToString(kBitRate float64) (bitRate string) { + return fmt.Sprintf("%f Kbps", kBitRate) +} diff --git a/pcf_handler/handler.go b/pcf_handler/handler.go new file mode 100644 index 0000000..3ded339 --- /dev/null +++ b/pcf_handler/handler.go @@ -0,0 +1,93 @@ +package pcf_handler + +import ( + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/pcf_producer" + "time" + + "github.com/sirupsen/logrus" +) + +var HandlerLog *logrus.Entry + +func init() { + // init Pool + HandlerLog = logger.HandlerLog +} + +func Handle() { + for { + select { + case msg, ok := <-pcf_message.PCFChannel: + if ok { + switch msg.Event { + case pcf_message.EventBDTPolicyCreate: + pcf_producer.CreateBDTPolicyContext(msg.HttpChannel, msg.HTTPRequest.Body.(models.BdtReqData)) + case pcf_message.EventBDTPolicyGet: + bdtPolicyId := msg.HTTPRequest.Params["bdtPolicyId"] + pcf_producer.GetBDTPolicyContext(msg.HttpChannel, bdtPolicyId) + case pcf_message.EventBDTPolicyUpdate: + bdtPolicyId := msg.HTTPRequest.Params["bdtPolicyId"] + pcf_producer.UpdateBDTPolicyContext(msg.HttpChannel, bdtPolicyId, msg.HTTPRequest.Body.(models.BdtPolicyDataPatch)) + case pcf_message.EventPostAppSessions: + pcf_producer.PostAppSessionsContext(msg.HttpChannel, msg.HTTPRequest.Body.(models.AppSessionContext)) + case pcf_message.EventGetAppSession: + appSessionId := msg.HTTPRequest.Params["appSessionId"] + pcf_producer.GetAppSessionContext(msg.HttpChannel, appSessionId) + case pcf_message.EventDeleteAppSession: + appSessionId := msg.HTTPRequest.Params["appSessionId"] + pcf_producer.DeleteAppSessionContext(msg.HttpChannel, appSessionId, msg.HTTPRequest.Body.(*models.EventsSubscReqData)) + case pcf_message.EventModAppSession: + appSessionId := msg.HTTPRequest.Params["appSessionId"] + pcf_producer.ModAppSessionContext(msg.HttpChannel, appSessionId, msg.HTTPRequest.Body.(models.AppSessionContextUpdateData)) + case pcf_message.EventDeleteEventsSubsc: + appSessionId := msg.HTTPRequest.Params["appSessionId"] + pcf_producer.DeleteEventsSubscContext(msg.HttpChannel, appSessionId) + case pcf_message.EventUpdateEventsSubsc: + appSessionId := msg.HTTPRequest.Params["appSessionId"] + pcf_producer.UpdateEventsSubscContext(msg.HttpChannel, appSessionId, msg.HTTPRequest.Body.(models.EventsSubscReqData)) + case pcf_message.EventAMPolicyGet: + PolAssoId := msg.HTTPRequest.Params["polAssoId"] + pcf_producer.GetPoliciesPolAssoId(msg.HttpChannel, PolAssoId) + case pcf_message.EventAMPolicyDelete: + PolAssoId := msg.HTTPRequest.Params["polAssoId"] + pcf_producer.DeletePoliciesPolAssoId(msg.HttpChannel, PolAssoId) + case pcf_message.EventAMPolicyCreate: + pcf_producer.PostPolicies(msg.HttpChannel, msg.HTTPRequest.Body.(models.PolicyAssociationRequest)) + case pcf_message.EventAMPolicyUpdate: + PolAssoId := msg.HTTPRequest.Params["polAssoId"] + pcf_producer.UpdatePostPoliciesPolAssoId(msg.HttpChannel, PolAssoId, msg.HTTPRequest.Body.(models.PolicyAssociationUpdateRequest)) + case pcf_message.EventSMPolicyCreate: + pcf_producer.CreateSmPolicy(msg.HttpChannel, msg.HTTPRequest.Body.(models.SmPolicyContextData)) + case pcf_message.EventSMPolicyGet: + smPolicyId := msg.HTTPRequest.Params["smPolicyId"] + pcf_producer.GetSmPolicyContext(msg.HttpChannel, smPolicyId) + case pcf_message.EventSMPolicyUpdate: + smPolicyId := msg.HTTPRequest.Params["smPolicyId"] + pcf_producer.UpdateSmPolicyContext(msg.HttpChannel, smPolicyId, msg.HTTPRequest.Body.(models.SmPolicyUpdateContextData)) + case pcf_message.EventSMPolicyDelete: + smPolicyId := msg.HTTPRequest.Params["smPolicyId"] + pcf_producer.DeleteSmPolicyContext(msg.HttpChannel, smPolicyId) + case pcf_message.EventSMPolicyNotify: + ReqURI := msg.HTTPRequest.Params["ReqURI"] + pcf_producer.HandleSmPolicyNotify(msg.HttpChannel, ReqURI, msg.HTTPRequest.Body.(models.PolicyDataChangeNotification)) + case pcf_message.EventAMFStatusChangeNotify: + pcf_producer.HandleAmfStatusChangeNotify(msg.HttpChannel, msg.HTTPRequest.Body.(models.AmfStatusChangeNotification)) + // TODO: http event dispatcher + case pcf_message.EventOAMGetAmPolicy: + supi := msg.HTTPRequest.Params["supi"] + pcf_producer.HandleOAMGetAmPolicy(msg.HttpChannel, supi) + default: + HandlerLog.Warnf("Event[%s] has not implemented", msg.Event) + } + } else { + HandlerLog.Errorln("Channel closed!") + } + + case <-time.After(time.Second * 1): + + } + } +} diff --git a/pcf_handler/handler_test.go b/pcf_handler/handler_test.go new file mode 100644 index 0000000..40a155c --- /dev/null +++ b/pcf_handler/handler_test.go @@ -0,0 +1,40 @@ +package pcf_handler_test + +import ( + // "free5gc/lib/CommonConsumerTestData/AMF/TestAmf" + // "free5gc/lib/ngap" + // "free5gc/src/test/ngapTestpacket" + // "free5gc/src/amf/amf_handler" + // "free5gc/src/amf/amf_handler/amf_message" + // "free5gc/src/amf/amf_ngap" + "testing" + // "time" +) + +func TestHandler(t *testing.T) { + // go amf_handler.Handle() + // TestAmf.AmfInit() + // testConn := &TestAmf.TestConn{ + // LAddr: &TestAmf.TestAddr{ + // Net: "tcp", + // Value: "192.188.2.2:12345", + // }, + // RAddr: &TestAmf.TestAddr{ + // Net: "tcp", + // Value: "192.188.2.1:9487", + // }, + // } + // message := ngapTestpacket.BuildNGSetupRequest() + // ngapMsg, err := ngap.Encoder(message) + // if err != nil { + // amf_ngap.Ngaplog.Errorln(err) + // } + // msg := amf_message.HandlerMessage{} + // msg.Event = amf_message.EventNGAPMessage + // msg.NgapConn = testConn + // msg.Value = ngapMsg + // amf_handler.SendMessage(msg) + + // time.Sleep(100 * time.Millisecond) + +} diff --git a/pcf_handler/pcf_message/channel.go b/pcf_handler/pcf_message/channel.go new file mode 100644 index 0000000..ed0030c --- /dev/null +++ b/pcf_handler/pcf_message/channel.go @@ -0,0 +1,23 @@ +package pcf_message + +import ( + "sync" +) + +var PCFChannel chan ChannelMessage +var mtx sync.Mutex + +const ( + MaxChannel int = 100000 +) + +func init() { + // init Pool + PCFChannel = make(chan ChannelMessage, MaxChannel) +} + +func SendMessage(msg ChannelMessage) { + mtx.Lock() + PCFChannel <- msg + mtx.Unlock() +} diff --git a/pcf_handler/pcf_message/event.go b/pcf_handler/pcf_message/event.go new file mode 100644 index 0000000..dad51ac --- /dev/null +++ b/pcf_handler/pcf_message/event.go @@ -0,0 +1,24 @@ +package pcf_message + +const ( + EventBDTPolicyCreate = "BDTPolicyCreate Message" + EventBDTPolicyGet = "BDTPolicyGet Message" + EventBDTPolicyUpdate = "BDTPolicyUpdate Message" + EventPostAppSessions = "PolicyAuthorizationPostAppSessions Message" + EventGetAppSession = "PolicyAuthorizationGetAppSession Message" + EventDeleteAppSession = "PolicyAuthorizationDeleteAppSession Message" + EventModAppSession = "PolicyAuthorizationModAppSession Message" + EventDeleteEventsSubsc = "PolicyAuthorizationDeleteEventsSubsc Message" + EventUpdateEventsSubsc = "PolicyAuthorizationUpdateEventsSubsc Message" + EventAMPolicyCreate = "AMPolicyCreate Message" + EventAMPolicyGet = "AMPolicyGet Message" + EventAMPolicyUpdate = "AMPolicyUpdate Message" + EventAMPolicyDelete = "AMPolicyDelete Message" + EventSMPolicyCreate = "EventSMPolicyCreate Message" + EventSMPolicyGet = "EventSMPolicyGet Message" + EventSMPolicyUpdate = "EventSMPolicyUpdate Message" + EventSMPolicyDelete = "EventSMPolicyDelete Message" + EventSMPolicyNotify = "EventSMPolicyNotify Message" + EventAMFStatusChangeNotify = "EventAMFStatusChangeNotify Message" + EventOAMGetAmPolicy = "EventOAMGetAmPolicy Message" +) diff --git a/pcf_handler/pcf_message/message.go b/pcf_handler/pcf_message/message.go new file mode 100644 index 0000000..ad3775a --- /dev/null +++ b/pcf_handler/pcf_message/message.go @@ -0,0 +1,125 @@ +package pcf_message + +import ( + "free5gc/lib/http_wrapper" + "free5gc/lib/openapi/models" + "net/http" +) + +type HttpResponseMessageType string + +const ( + HttpResponseMessageResponse HttpResponseMessageType = "HTTP Response" + HttpResponseMessageAddition HttpResponseMessageType = "HTTP Response Addition" + HttpResponseMessageResponseError HttpResponseMessageType = "HTTP Response Error" + HttpResponseMessageProblemDetails HttpResponseMessageType = "Problem Details" +) + +type ChannelMessage struct { + Event string + HTTPRequest *http_wrapper.Request + HttpChannel chan HttpResponseMessage // return Http response + Value interface{} // input/request value +} + +func NewHttpChannelMessage(event string, httpRequest *http_wrapper.Request) (msg ChannelMessage) { + msg = ChannelMessage{} + msg.Event = event + msg.HttpChannel = make(chan HttpResponseMessage) + if httpRequest != nil { + msg.HTTPRequest = httpRequest + } + return msg +} + +type HttpResponseMessage struct { + HTTPResponse *http_wrapper.Response +} + +/* Send HTTP Response to HTTP handler thread through HTTP channel, args[0] is response payload and args[1:] is Additional Value*/ +func SendHttpResponseMessage(channel chan HttpResponseMessage, header http.Header, status int, body interface{}) { + responseMsg := HttpResponseMessage{} + responseMsg.HTTPResponse = http_wrapper.NewResponse(status, header, body) + channel <- responseMsg +} + +/* +type EventCreateBDTPolicyCreateValue struct { + Request models.BdtReqData + RequestUri string +} + +type EventGetBDTPolicyCreateValue struct { + RequestUri string +} + +type EventUpdateBDTPolicyCreateValue struct { + Request models.BdtPolicyDataPatch + RequestUri string +} + +type EventPostAppSessionsCreateValue struct { + Request models.AppSessionContext + RequestUri string +} +*/ +type EventGetAppSessionCreateValue struct { + RequestUri string +} + +type EventDeleteAppSessionCreateValue struct { + RequestUri string +} + +type EventModAppSessionCreateValue struct { + Request models.AppSessionContextUpdateData + RequestUri string +} + +type EventDeleteEventsSubscCreateValue struct { + RequestUri string +} + +type EventUpdateEventsSubscCreateValue struct { + Request models.EventsSubscReqData + RequestUri string +} + +type EventCreateAMPolicyCreateValue struct { + Request models.PolicyAssociationRequest + RequestUri string +} + +type EventGetAMPolicyCreateValue struct { + RequestUri string +} + +type EventUpdateAMPolicyCreateValue struct { + Request models.PolicyAssociationUpdateRequest + RequestUri string +} + +type EventDeleteAMPolicyCreateValue struct { + RequestUri string +} +type EventCreateSMPolicyCreateValue struct { + Request models.SmPolicyContextData + RequestUri string +} + +type EventGetSMPolicyCreateValue struct { + RequestUri string +} + +type EventUpdateSMPolicyCreateValue struct { + Request models.SmPolicyUpdateContextData + RequestUri string +} + +type EventDeleteSMPolicyCreateValue struct { + RequestUri string +} +type EventNotifySMPolicyCreateValue struct { + Request models.PolicyDataChangeNotification + RequestUri string +} diff --git a/pcf_producer/HandleSmPolicyNotify.go b/pcf_producer/HandleSmPolicyNotify.go new file mode 100644 index 0000000..a02fead --- /dev/null +++ b/pcf_producer/HandleSmPolicyNotify.go @@ -0,0 +1,74 @@ +package pcf_producer + +import ( + // "context" + // "fmt" + "free5gc/lib/openapi/models" + // "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_handler/pcf_message" + // "free5gc/src/pcf/pcf_util" + // "github.com/gin-gonic/gin" +) + +func HandleSmPolicyNotify(httpChannel chan pcf_message.HttpResponseMessage, supi string, body models.PolicyDataChangeNotification) { + // policyDataChangeNotification := body + // var problem models.ProblemDetails + // var smPolicyDecision models.SmPolicyDecision + // pcfUeContext := pcf_context.PCF_Self().UePool + // counter := false + // client := pcf_util.GetNudrClient("https://localhost:29504") + // UeContext := pcf_context.PCF_Self().UePool + // if UeContext[supi] == nil { + // problem.Status = 404 + // problem.Cause = "CONTEXT_NOT_FOUND" + // pcf_message.SendHttpResponseMessage(httpChannel, nil, 404, problem) + // } + // _, resp, err := client.DefaultApi.PolicyDataUesUeIdSmDataGet(context.Background(), supi, nil) + // if err != nil { + // problem.Status = 404 + // problem.Cause = "CONTEXT_NOT_FOUND" + // pcf_message.SendHttpResponseMessage(httpChannel, nil, 404, problem) + // } + // if resp.StatusCode == 204 { + // UeContext[supi].SmPolicyControlStore = nil + // // pcf_producer_callback.CreateSmPolicyNotifyContext(fmt.Sprint(UeContext[supi].SmPolicyControlStore.Context.PduSessionId), "terminate", nil) + // pcf_message.SendHttpResponseMessage(httpChannel, nil, 204, nil) + // } + // if resp.StatusCode == 200 { + // for key := range pcfUeContext { + + // SupiTemp := fmt.Sprint(pcfUeContext[key].Supi) + // if supi == SupiTemp { + // snssai := fmt.Sprint(pcfUeContext[key].SmPolicyControlStore.Context.SliceInfo.Sst) + pcfUeContext[key].SmPolicyControlStore.Context.SliceInfo.Sd + // dnn := pcfUeContext[key].SmPolicyControlStore.Context.Dnn + // if policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Ipv4Index != 0 { + // smPolicyDecision.Ipv4Index = policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Ipv4Index + // pcfUeContext[key].SmPolicyControlStore.Policy.Ipv4Index = smPolicyDecision.Ipv4Index + // counter = true + // } + // if policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Ipv6Index != 0 { + // smPolicyDecision.Ipv6Index = policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Ipv6Index + // pcfUeContext[key].SmPolicyControlStore.Policy.Ipv6Index = smPolicyDecision.Ipv6Index + // counter = true + // } + // if pcfUeContext[key].SmPolicyControlStore.Policy.Online != policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Online { + // smPolicyDecision.Online = policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Online + // pcfUeContext[key].SmPolicyControlStore.Policy.Online = smPolicyDecision.Online + // counter = true + // } + // if pcfUeContext[key].SmPolicyControlStore.Policy.Offline != policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Offline { + // smPolicyDecision.Offline = policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Offline + // pcfUeContext[key].SmPolicyControlStore.Policy.Offline = smPolicyDecision.Offline + // counter = true + // } + // pcf_message.SendHttpResponseMessage(httpChannel, nil, 204, gin.H{}) + // if counter { + // // pcf_producer_callback.CreateSmPolicyNotifyContext(fmt.Sprint(UeContext[supi].SmPolicyControlStore.Context.PduSessionId), "update", &smPolicyDecision) + // pcf_message.SendHttpResponseMessage(httpChannel, nil, 204, nil) + // } + + // } + + // } + // } +} diff --git a/pcf_producer/callback.go b/pcf_producer/callback.go new file mode 100644 index 0000000..4d30ec5 --- /dev/null +++ b/pcf_producer/callback.go @@ -0,0 +1,15 @@ +package pcf_producer + +import ( + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_handler/pcf_message" + "net/http" +) + +func HandleAmfStatusChangeNotify(httpChannel chan pcf_message.HttpResponseMessage, notification models.AmfStatusChangeNotification) { + logger.CallbackLog.Warnf("[PCF] Handle Amf Status Change Notify is not implemented.") + logger.CallbackLog.Debugf("receive AMF status change notification[%+v]", notification) + // TODO: handle AMF Status Change Notify + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) +} diff --git a/pcf_producer/oam.go b/pcf_producer/oam.go new file mode 100644 index 0000000..93a3bd6 --- /dev/null +++ b/pcf_producer/oam.go @@ -0,0 +1,55 @@ +package pcf_producer + +import ( + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_handler/pcf_message" + "net/http" + "strconv" +) + +type UEAmPolicy struct { + PolicyAssociationID string + AccessType models.AccessType + Rfsp string + Triggers []models.RequestTrigger + /*Service Area Restriction */ + RestrictionType models.RestrictionType + Areas []models.Area + MaxNumOfTAs int32 +} + +type UEAmPolicys []UEAmPolicy + +func HandleOAMGetAmPolicy(httpChannel chan pcf_message.HttpResponseMessage, supi string) { + logger.OamLog.Infof("Handle OAM Get Am Policy") + + var response UEAmPolicys + pcfSelf := pcf_context.PCF_Self() + + if ue, exists := pcfSelf.UePool[supi]; exists { + for _, amPolicy := range ue.AMPolicyData { + ueAmPolicy := UEAmPolicy{ + PolicyAssociationID: amPolicy.PolAssoId, + AccessType: amPolicy.AccessType, + Rfsp: strconv.Itoa(int(amPolicy.Rfsp)), + Triggers: amPolicy.Triggers, + } + if amPolicy.ServAreaRes != nil { + servAreaRes := amPolicy.ServAreaRes + ueAmPolicy.RestrictionType = servAreaRes.RestrictionType + ueAmPolicy.Areas = servAreaRes.Areas + ueAmPolicy.MaxNumOfTAs = servAreaRes.MaxNumOfTAs + } + response = append(response, ueAmPolicy) + } + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, response) + } else { + problem := models.ProblemDetails{ + Status: http.StatusNotFound, + Cause: "CONTEXT_NOT_FOUND", + } + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNotFound, problem) + } +} diff --git a/pcf_producer/pcf_ampolicy.go b/pcf_producer/pcf_ampolicy.go new file mode 100644 index 0000000..bf1d584 --- /dev/null +++ b/pcf_producer/pcf_ampolicy.go @@ -0,0 +1,315 @@ +package pcf_producer + +import ( + "context" + "fmt" + "github.com/mohae/deepcopy" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_consumer" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/pcf_util" + "net/http" + "reflect" +) + +func DeletePoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessage, polAssoId string) { + + logger.AMpolicylog.Traceln("Handle Policy Association Delete") + + ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(polAssoId) + if ue == nil || ue.AMPolicyData[polAssoId] == nil { + rsp := pcf_util.GetProblemDetail("polAssoId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + delete(ue.AMPolicyData, polAssoId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) +} + +// PoliciesPolAssoIdGet - +func GetPoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessage, polAssoId string) { + + logger.AMpolicylog.Traceln("Handle Policy Association Get") + + ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(polAssoId) + if ue == nil || ue.AMPolicyData[polAssoId] == nil { + rsp := pcf_util.GetProblemDetail("polAssoId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + amPolicyData := ue.AMPolicyData[polAssoId] + rsp := models.PolicyAssociation{ + SuppFeat: amPolicyData.SuppFeat, + } + if amPolicyData.Rfsp != 0 { + rsp.Rfsp = amPolicyData.Rfsp + } + if amPolicyData.ServAreaRes != nil { + rsp.ServAreaRes = amPolicyData.ServAreaRes + } + if amPolicyData.Triggers != nil { + rsp.Triggers = amPolicyData.Triggers + for _, trigger := range amPolicyData.Triggers { + if trigger == models.RequestTrigger_PRA_CH { + rsp.Pras = amPolicyData.Pras + break + } + } + } + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) + +} +func UpdatePostPoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessage, polAssoId string, request models.PolicyAssociationUpdateRequest) { + + logger.AMpolicylog.Traceln("Handle Policy Association Update") + + ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(polAssoId) + if ue == nil || ue.AMPolicyData[polAssoId] == nil { + rsp := pcf_util.GetProblemDetail("polAssoId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + + amPolicyData := ue.AMPolicyData[polAssoId] + var rsp models.PolicyUpdate + if request.NotificationUri != "" { + amPolicyData.NotificationUri = request.NotificationUri + } + if request.AltNotifIpv4Addrs != nil { + amPolicyData.AltNotifIpv4Addrs = request.AltNotifIpv4Addrs + } + if request.AltNotifIpv6Addrs != nil { + amPolicyData.AltNotifIpv6Addrs = request.AltNotifIpv6Addrs + } + for _, trigger := range request.Triggers { + //TODO: Modify the value according to policies + switch trigger { + case models.RequestTrigger_LOC_CH: + //TODO: report to AF subscriber + if request.UserLoc == nil { + rsp := pcf_util.GetProblemDetail("UserLoc are nli", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.AMpolicylog.Warnln("UserLoc doesn't exist in Policy Association Requset Update while Triggers include LOC_CH") + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + amPolicyData.UserLoc = request.UserLoc + logger.AMpolicylog.Infof("Ue[%s] UserLocation %+v", ue.Supi, amPolicyData.UserLoc) + case models.RequestTrigger_PRA_CH: + if request.PraStatuses == nil { + rsp := pcf_util.GetProblemDetail("PraStatuses are nli", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.AMpolicylog.Warnln("PraStatuses doesn't exist in Policy Association Requset Update while Triggers include PRA_CH") + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + for praId, praInfo := range request.PraStatuses { + //TODO: report to AF subscriber + logger.AMpolicylog.Infof("Policy Association Presence Id[%s] change state to %s", praId, praInfo.PresenceState) + } + case models.RequestTrigger_SERV_AREA_CH: + if request.ServAreaRes == nil { + rsp := pcf_util.GetProblemDetail("ServAreaRes are nli", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.AMpolicylog.Warnln("ServAreaRes doesn't exist in Policy Association Requset Update while Triggers include SERV_AREA_CH") + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } else { + amPolicyData.ServAreaRes = request.ServAreaRes + rsp.ServAreaRes = request.ServAreaRes + } + case models.RequestTrigger_RFSP_CH: + if request.Rfsp == 0 { + rsp := pcf_util.GetProblemDetail("Rfsp are nli", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.AMpolicylog.Warnln("Rfsp doesn't exist in Policy Association Requset Update while Triggers include RFSP_CH") + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } else { + amPolicyData.Rfsp = request.Rfsp + rsp.Rfsp = request.Rfsp + } + } + } + //TODO: handle TraceReq + //TODO: Change Request Trigger Policies if needed + rsp.Triggers = amPolicyData.Triggers + //TODO: Change Policies if needed + // rsp.Pras + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) + +} + +// Create AM Policy +func PostPolicies(httpChannel chan pcf_message.HttpResponseMessage, request models.PolicyAssociationRequest) { + var rsp models.PolicyAssociation + var err error + + logger.AMpolicylog.Traceln("Handle Policy Association Request") + + pcfSelf := pcf_context.PCF_Self() + ue := pcfSelf.UePool[request.Supi] + if ue == nil { + ue, err = pcfSelf.NewPCFUe(request.Supi) + if err != nil { + // supi format dose not match "imsi-..." + rsp := pcf_util.GetProblemDetail("Supi Format Error", pcf_util.ERROR_REQUEST_PARAMETERS) + logger.AMpolicylog.Errorln(err.Error()) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + } + udrUri := getUdrUri(ue) + if udrUri == "" { + // Can't find any UDR support this Ue + delete(pcfSelf.UePool, ue.Supi) + rsp := pcf_util.GetProblemDetail("Ue is not supported in PCF", pcf_util.USER_UNKNOWN) + logger.AMpolicylog.Errorf("Ue[%s] is not supported in PCF", ue.Supi) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + ue.UdrUri = udrUri + + rsp.Request = deepcopy.Copy(&request).(*models.PolicyAssociationRequest) + assolId := fmt.Sprintf("%s-%d", ue.Supi, ue.PolAssociationIDGenerator) + amPolicy := ue.AMPolicyData[assolId] + + if amPolicy == nil || amPolicy.AmPolicyData == nil { + client := pcf_util.GetNudrClient(udrUri) + var response *http.Response + amData, response, err := client.DefaultApi.PolicyDataUesUeIdAmDataGet(context.Background(), ue.Supi) + if err != nil || response == nil || response.StatusCode != http.StatusOK { + rsp := pcf_util.GetProblemDetail("Can't find UE AM Policy Data in UDR", pcf_util.USER_UNKNOWN) + logger.AMpolicylog.Errorf("Can't find UE[%s] AM Policy Data in UDR", ue.Supi) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + if amPolicy == nil { + amPolicy = ue.NewUeAMPolicyData(assolId, request) + } + amPolicy.AmPolicyData = &amData + } + + // TODO: according to PCF Policy to determine ServAreaRes, Rfsp, SuppFeat + // amPolicy.ServAreaRes = + // amPolicy.Rfsp = + amPolicy.SuppFeat = pcf_util.GetNegotiateSuppFeat(request.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_AM_POLICY_CONTROL]) + if amPolicy.Rfsp != 0 { + rsp.Rfsp = amPolicy.Rfsp + } + rsp.SuppFeat = amPolicy.SuppFeat + // TODO: add Reports + // rsp.Triggers + // rsp.Pras + ue.PolAssociationIDGenerator++ + // Create location header for update, delete, get + locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_AM_POLICY_CONTROL, assolId) + headers := http.Header{ + "Location": {locationHeader}, + } + logger.AMpolicylog.Tracef("AMPolicy association Id[%s] Create", assolId) + pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, rsp) + + if request.Guami != nil { + // if consumer is AMF then subscribe this AMF Status + for _, statusSubsData := range pcfSelf.AMFStatusSubsData { + for _, guami := range statusSubsData.GuamiList { + if reflect.DeepEqual(guami, request.Guami) { + amPolicy.AmfStatusChangeSubscription = &statusSubsData + } + } + } + } +} + +// Send AM Policy Update to AMF if policy has changed +func SendAMPolicyUpdateNotification(ue *pcf_context.UeContext, PolId string, request models.PolicyUpdate) { + if ue == nil { + logger.AMpolicylog.Warnln("Policy Update Notification Error[Ue is nil]") + return + } + amPolicyData := ue.AMPolicyData[PolId] + if amPolicyData == nil { + logger.AMpolicylog.Warnf("Policy Update Notification Error[Can't find polAssoId[%s] in UE(%s)]", PolId, ue.Supi) + return + } + client := pcf_util.GetNpcfAMPolicyCallbackClient() + uri := amPolicyData.NotificationUri + for uri != "" { + + rsp, err := client.DefaultCallbackApi.PolicyUpdateNotification(context.Background(), uri, request) + if err != nil { + if rsp != nil && rsp.StatusCode != http.StatusNoContent { + logger.AMpolicylog.Warnf("Policy Update Notification Error[%s]", rsp.Status) + } else { + logger.AMpolicylog.Warnf("Policy Update Notification Failed[%s]", err.Error()) + } + return + } else if rsp == nil { + logger.AMpolicylog.Warnln("Policy Update Notification Failed[HTTP Response is nil]") + return + } + if rsp.StatusCode == http.StatusTemporaryRedirect { + // for redirect case, resend the notification to redirect target + uRI, err := rsp.Location() + if err != nil { + logger.AMpolicylog.Warnln("Policy Update Notification Redirect Need Supply URI") + return + } + uri = uRI.String() + continue + } + + logger.AMpolicylog.Infoln("Policy Update Notification Success") + return + } + +} + +// Send AM Policy Update to AMF if policy has been terminated +func SendAMPolicyTerminationRequestNotification(ue *pcf_context.UeContext, PolId string, request models.TerminationNotification) { + if ue == nil { + logger.AMpolicylog.Warnln("Policy Assocition Termination Request Notification Error[Ue is nil]") + return + } + amPolicyData := ue.AMPolicyData[PolId] + if amPolicyData == nil { + logger.AMpolicylog.Warnf("Policy Assocition Termination Request Notification Error[Can't find polAssoId[%s] in UE(%s)]", PolId, ue.Supi) + return + } + client := pcf_util.GetNpcfAMPolicyCallbackClient() + uri := amPolicyData.NotificationUri + for uri != "" { + + rsp, err := client.DefaultCallbackApi.PolicyAssocitionTerminationRequestNotification(context.Background(), uri, request) + if err != nil { + if rsp != nil && rsp.StatusCode != http.StatusNoContent { + logger.AMpolicylog.Warnf("Policy Assocition Termination Request Notification Error[%s]", rsp.Status) + } else { + logger.AMpolicylog.Warnf("Policy Assocition Termination Request Notification Failed[%s]", err.Error()) + } + return + } else if rsp == nil { + logger.AMpolicylog.Warnln("Policy Assocition Termination Request Notification Failed[HTTP Response is nil]") + return + } + if rsp.StatusCode == http.StatusTemporaryRedirect { + // for redirect case, resend the notification to redirect target + uRI, err := rsp.Location() + if err != nil { + logger.AMpolicylog.Warnln("Policy Assocition Termination Request Notification Redirect Need Supply URI") + return + } + uri = uRI.String() + continue + } + return + } + +} + +// returns UDR Uri of Ue, if ue.UdrUri dose not exist, query NRF to get supported Udr Uri +func getUdrUri(ue *pcf_context.UeContext) string { + if ue.UdrUri != "" { + return ue.UdrUri + } + return pcf_consumer.SendNFIntancesUDR(pcf_context.PCF_Self().NrfUri, ue.Supi) +} diff --git a/pcf_producer/pcf_bdtpolicy.go b/pcf_producer/pcf_bdtpolicy.go new file mode 100644 index 0000000..c4487ca --- /dev/null +++ b/pcf_producer/pcf_bdtpolicy.go @@ -0,0 +1,193 @@ +package pcf_producer + +import ( + "context" + "fmt" + "github.com/google/uuid" + "github.com/mohae/deepcopy" + "free5gc/lib/Nnrf_NFDiscovery" + "free5gc/lib/Nudr_DataRepository" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_consumer" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/pcf_util" + "net/http" + + "github.com/antihax/optional" +) + +func GetBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, bdtPolicyId string) { + + logger.Bdtpolicylog.Traceln("Handle BDT Policy GET") + // check BdtPolicyId from pcfUeContext + bdtPolicy, exist := pcf_context.PCF_Self().BdtPolicyPool[bdtPolicyId] + if !exist { + // not found + rsp := pcf_util.GetProblemDetail("Can't find BDTPolicyId related resource", pcf_util.CONTEXT_NOT_FOUND) + logger.Bdtpolicylog.Warnf(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, bdtPolicy) + +} + +// UpdateBDTPolicy - Update an Individual BDT policy (choose policy data) +func UpdateBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, bdtPolicyId string, request models.BdtPolicyDataPatch) { + + logger.Bdtpolicylog.Traceln("Handle BDT Policy Update") + // check BdtPolicyId from pcfUeContext + pcfSelf := pcf_context.PCF_Self() + bdtPolicy, exist := pcfSelf.BdtPolicyPool[bdtPolicyId] + if !exist { + // not found + rsp := pcf_util.GetProblemDetail("Can't find BDTPolicyId related resource", pcf_util.CONTEXT_NOT_FOUND) + logger.Bdtpolicylog.Warnf(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + for _, policy := range bdtPolicy.BdtPolData.TransfPolicies { + if policy.TransPolicyId == request.SelTransPolicyId { + polData := bdtPolicy.BdtPolData + polReq := bdtPolicy.BdtReqData + polData.SelTransPolicyId = request.SelTransPolicyId + bdtData := models.BdtData{ + AspId: polReq.AspId, + TransPolicy: policy, + BdtRefId: polData.BdtRefId, + } + if polReq.NwAreaInfo != nil { + bdtData.NwAreaInfo = *polReq.NwAreaInfo + } + param := Nudr_DataRepository.PolicyDataBdtDataBdtReferenceIdPutParamOpts{ + BdtData: optional.NewInterface(bdtData), + } + client := pcf_util.GetNudrClient(getDefaultUdrUri(pcfSelf)) + _, err := client.DefaultApi.PolicyDataBdtDataBdtReferenceIdPut(context.Background(), bdtData.BdtRefId, ¶m) + if err != nil { + logger.Bdtpolicylog.Warnf("UDR Put BdtDate error[%s]", err.Error()) + } + logger.Bdtpolicylog.Tracef("BDTPolicyId[%s] has Updated with SelTransPolicyId[%d]", bdtPolicyId, request.SelTransPolicyId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, bdtPolicy) + return + } + } + rsp := pcf_util.GetProblemDetail(fmt.Sprintf("Can't find TransPolicyId[%d] in TransfPolicies with BDTPolicyId[%s]", request.SelTransPolicyId, bdtPolicyId), pcf_util.CONTEXT_NOT_FOUND) + logger.Bdtpolicylog.Warnf(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) +} + +//CreateBDTPolicy - Create a new Individual BDT policy +func CreateBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, request models.BdtReqData) { + var rsp models.BdtPolicy + + logger.Bdtpolicylog.Traceln("Handle BDT Policy Create") + + pcfSelf := pcf_context.PCF_Self() + udrUri := getDefaultUdrUri(pcfSelf) + if udrUri == "" { + // Can't find any UDR support this Ue + rsp := models.ProblemDetails{ + Status: http.StatusServiceUnavailable, + Detail: "Can't find any UDR which supported to this PCF", + } + logger.Bdtpolicylog.Warnf(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + pcfSelf.DefaultUdrUri = udrUri + + // Query BDT DATA array from UDR + client := pcf_util.GetNudrClient(udrUri) + bdtDatas, response, err := client.DefaultApi.PolicyDataBdtDataGet(context.Background()) + if err != nil || response == nil || response.StatusCode != http.StatusOK { + rsp := models.ProblemDetails{ + Status: http.StatusServiceUnavailable, + Detail: "Query to UDR failed", + } + logger.Bdtpolicylog.Warnf("Query to UDR failed") + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + // TODO: decide BDT Policy from other bdt policy data + rsp.BdtReqData = deepcopy.Copy(&request).(*models.BdtReqData) + var bdtData *models.BdtData + var bdtPolicyData models.BdtPolicyData + for _, data := range bdtDatas { + // If ASP has exist, use its background data policy + if request.AspId == data.AspId { + bdtData = &data + break + } + } + // Only support one bdt policy, TODO: more policy for decision + if bdtData != nil { + // found + // modify policy according to new request + bdtData.TransPolicy.RecTimeInt = request.DesTimeInt + } else { + // use default bdt policy, TODO: decide bdt transfer data policy + bdtData = &models.BdtData{ + AspId: request.AspId, + BdtRefId: uuid.New().String(), + TransPolicy: getDefaultTransferPolicy(1, *request.DesTimeInt), + } + } + if request.NwAreaInfo != nil { + bdtData.NwAreaInfo = *request.NwAreaInfo + } + bdtPolicyData.SelTransPolicyId = bdtData.TransPolicy.TransPolicyId + // no support feature in subclause 5.8 of TS29554 + bdtPolicyData.BdtRefId = bdtData.BdtRefId + bdtPolicyData.TransfPolicies = append(bdtPolicyData.TransfPolicies, bdtData.TransPolicy) + rsp.BdtPolData = &bdtPolicyData + bdtPolicyId := pcfSelf.AllocBdtPolicyId() + pcfSelf.BdtPolicyPool[bdtPolicyId] = rsp + + locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_BDTPOLICYCONTROL, bdtPolicyId) + headers := http.Header{ + "Location": {locationHeader}, + } + logger.Bdtpolicylog.Tracef("BDT Policy Id[%s] Create", bdtPolicyId) + pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, rsp) + + // Update UDR BDT Data(PUT) + param := Nudr_DataRepository.PolicyDataBdtDataBdtReferenceIdPutParamOpts{ + BdtData: optional.NewInterface(*bdtData), + } + _, err = client.DefaultApi.PolicyDataBdtDataBdtReferenceIdPut(context.Background(), bdtPolicyData.BdtRefId, ¶m) + if err != nil { + logger.Bdtpolicylog.Warnf("UDR Put BdtDate error[%s]", err.Error()) + } +} + +func getDefaultUdrUri(context *pcf_context.PCFContext) string { + if context.DefaultUdrUri != "" { + return context.DefaultUdrUri + } + param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ + ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NUDR_DR}), + } + resp, err := pcf_consumer.SendSearchNFInstances(context.NrfUri, models.NfType_UDR, models.NfType_PCF, param) + if err != nil { + return "" + } + for _, nfProfile := range resp.NfInstances { + udruri := pcf_util.SearchNFServiceUri(nfProfile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED) + if udruri != "" { + return udruri + } + } + return "" +} + +// get default background data transfer policy +func getDefaultTransferPolicy(transferPolicyId int32, timeWindow models.TimeWindow) models.TransferPolicy { + return models.TransferPolicy{ + TransPolicyId: transferPolicyId, + RecTimeInt: &timeWindow, + RatingGroup: 1, + } +} diff --git a/pcf_producer/pcf_policyauthorization.go b/pcf_producer/pcf_policyauthorization.go new file mode 100644 index 0000000..b45e22b --- /dev/null +++ b/pcf_producer/pcf_policyauthorization.go @@ -0,0 +1,1571 @@ +package pcf_producer + +import ( + "context" + "fmt" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/pcf_util" + "net/http" + "strings" + "time" + + "github.com/cydev/zero" +) + +// Initial provisioning of service information (DONE) +// Gate control (DONE) +// Initial provisioning of sponsored connectivity information (DONE) +// Subscriptions to Service Data Flow QoS notification control (DONE) +// Subscription to Service Data Flow Deactivation (DONE) +// Initial provisioning of traffic routing information (DONE) +// Subscription to resources allocation outcome (DONE) +// Invocation of Multimedia Priority Services (TODO) +// Support of content versioning (TODO) +// PostAppSessions - Creates a new Individual Application Session Context resource +func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, request models.AppSessionContext) { + logger.PolicyAuthorizationlog.Traceln("Handle Create AppSessions") + reqData := request.AscReqData + pcfSelf := pcf_context.PCF_Self() + // Initial BDT policy indication(the only one which is not related to session) + if reqData.BdtRefId != "" { + err := handleBackgroundDataTransferPolicyIndication(pcfSelf, &request) + if err != nil { + sendProblemDetail(httpChannel, err.Error(), pcf_util.ERROR_REQUEST_PARAMETERS) + return + } + appSessionId := fmt.Sprintf("BdtRefId-%s", reqData.BdtRefId) + data := pcf_context.AppSessionData{ + AppSessionId: appSessionId, + AppSessionContext: &request, + } + pcfSelf.AppSessionPool[appSessionId] = &data + locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId) + headers := http.Header{ + "Location": {locationHeader}, + } + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create", appSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, request) + return + } + if request.AscReqData.UeIpv4 == "" && request.AscReqData.UeIpv6 == "" && request.AscReqData.UeMac == "" { + sendProblemDetail(httpChannel, "Ue UeIpv4 and UeIpv6 and UeMac are all empty", pcf_util.ERROR_REQUEST_PARAMETERS) + return + } + smPolicy, err := pcfSelf.SessionBinding(request.AscReqData) + if err != nil { + sendProblemDetail(httpChannel, fmt.Sprintf("Session Binding failed[%s]", err.Error()), pcf_util.PDU_SESSION_NOT_AVAILABLE) + return + } + ue := smPolicy.PcfUe + updateSMpolicy := false + nSuppFeat := pcf_util.GetNegotiateSuppFeat(reqData.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION]) + traffRoutSupp := pcf_util.CheckSuppFeat(nSuppFeat, 1) && pcf_util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 + relatedPccRuleIds := make(map[string]string) + + if reqData.MedComponents != nil { + // Handle Pcc rules + maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) + for _, mediaComponent := range reqData.MedComponents { + var pccRule *models.PccRule + // TODO: use specific algorithm instead of default, details in subsclause 7.3.3 of TS 29513 + var var5qi int32 = 9 + if mediaComponent.MedType != "" { + var5qi = pcf_util.MediaTypeTo5qiMap[mediaComponent.MedType] + } + + if mediaComponent.MedSubComps != nil { + for _, mediaSubComponent := range mediaComponent.MedSubComps { + flowInfos, err := getFlowInfos(mediaSubComponent) + if err != nil { + sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + pccRule = pcf_util.GetPccRuleByFlowInfos(smPolicy.PolicyDecision.PccRules, flowInfos) + if pccRule == nil { + pccRule = pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + // Set QoS Data + // TODO: use real arp + qosData := pcf_util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) + if var5qi <= 4 { + // update Qos Data accroding to request BitRate + var ul, dl bool + qosData, ul, dl = updateQos_subComp(qosData, mediaComponent, mediaSubComponent) + err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) + if err != nil { + return + } + } + // Set PackfiltId + for i := range flowInfos { + flowInfos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + smPolicy.PackFiltMapToPccRuleId[flowInfos[i].PackFiltId] = pccRule.PccRuleId + smPolicy.PackFiltIdGenarator++ + } + // Set flowsInfo in Pcc Rule + pccRule.FlowInfos = flowInfos + // Set Traffic Control Data + tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaSubComponent.FStatus) + pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + smPolicy.PccRuleIdGenarator++ + maxPrecedence++ + } else { + // update qos + var qosData models.QosData + for _, qosId := range pccRule.RefQosData { + qosData = smPolicy.PolicyDecision.QosDecs[qosId] + if qosData.Var5qi == var5qi && qosData.Var5qi <= 4 { + var ul, dl bool + qosData, ul, dl = updateQos_subComp(smPolicy.PolicyDecision.QosDecs[qosId], mediaComponent, mediaSubComponent) + err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) + if err != nil { + fmt.Println(err.Error()) + return + } + smPolicy.PolicyDecision.QosDecs[qosData.QosId] = qosData + } + } + } + // Initial provisioning of traffic routing information + if traffRoutSupp { + InitialProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, reqData.AfRoutReq) + } + smPolicy.PolicyDecision.PccRules[pccRule.PccRuleId] = *pccRule + key := fmt.Sprintf("%d-%d", mediaComponent.MedCompN, mediaSubComponent.FNum) + relatedPccRuleIds[key] = pccRule.PccRuleId + updateSMpolicy = true + } + continue + } else if mediaComponent.AfAppId != "" { + // if mediaComponent.AfAppId has value -> find pccRule by reqData.AfAppId, otherwise create a new pcc rule + pccRule = pcf_util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, mediaComponent.AfAppId) + if pccRule != nil { + pccRule.AppId = mediaComponent.AfAppId + } + } else if reqData.AfAppId != "" { + pccRule = pcf_util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, reqData.AfAppId) + if pccRule != nil { + pccRule.AppId = reqData.AfAppId + } + } else { + sendProblemDetail(httpChannel, "Media Component needs flows of subComp or afAppId", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + + if pccRule == nil { // create new pcc rule + pccRule = pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + if mediaComponent.AfAppId != "" { + pccRule.AppId = mediaComponent.AfAppId + } else { + pccRule.AppId = reqData.AfAppId + } + // Set QoS Data + // TODO: use real arp + qosData := pcf_util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) + if var5qi <= 4 { + // update Qos Data accroding to request BitRate + var ul, dl bool + qosData, ul, dl = updateQos_Comp(qosData, mediaComponent) + err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) + if err != nil { + return + } + } + + // Set Traffic Control Data + tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaComponent.FStatus) + pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + smPolicy.PccRuleIdGenarator++ + maxPrecedence++ + } else { + // update qos + var qosData models.QosData + for _, qosId := range pccRule.RefQosData { + qosData = smPolicy.PolicyDecision.QosDecs[qosId] + if qosData.Var5qi == var5qi && qosData.Var5qi <= 4 { + var ul, dl bool + qosData, ul, dl = updateQos_Comp(smPolicy.PolicyDecision.QosDecs[qosId], mediaComponent) + err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) + if err != nil { + return + } + smPolicy.PolicyDecision.QosDecs[qosData.QosId] = qosData + } + } + } + key := fmt.Sprintf("%d", mediaComponent.MedCompN) + relatedPccRuleIds[key] = pccRule.PccRuleId + // TODO : handle temporal or spatial validity + // Initial provisioning of traffic routing information + if traffRoutSupp { + InitialProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, reqData.AfRoutReq) + } + updateSMpolicy = true + } + } else if reqData.AfAppId != "" { + // Initial provisioning of traffic routing information + if reqData.AfRoutReq != nil && traffRoutSupp { + decision := smPolicy.PolicyDecision + cnt := 0 + for _, rule := range smPolicy.PolicyDecision.PccRules { + if rule.AppId == reqData.AfAppId { + tcData := models.TrafficControlData{ + TcId: strings.ReplaceAll(rule.PccRuleId, "PccRule", "Tc"), + FlowStatus: models.FlowStatus_ENABLED, + } + tcData.RouteToLocs = append(tcData.RouteToLocs, reqData.AfRoutReq.RouteToLocs...) + tcData.UpPathChgEvent = reqData.AfRoutReq.UpPathChgSub + rule.RefTcData = []string{tcData.TcId} + rule.AppReloc = reqData.AfRoutReq.AppReloc + pcf_util.SetPccRuleRelatedData(decision, &rule, &tcData, nil, nil, nil) + updateSMpolicy = true + key := fmt.Sprintf("appId-%s-%d", reqData.AfAppId, cnt) + relatedPccRuleIds[key] = rule.PccRuleId + cnt++ + } + } + // Create a Pcc Rule if afappId dose not match any pcc rule + if !updateSMpolicy { + maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) + pccRule := pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + pccRule.AppId = reqData.AfAppId + qosData := models.QosData{ + QosId: pcf_util.GetQosId(smPolicy.PccRuleIdGenarator), + DefQosFlowIndication: true, + } + tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, "") + pccRule.RefTcData = []string{tcData.TcId} + pccRule.RefQosData = []string{qosData.QosId} + pcf_util.SetPccRuleRelatedData(decision, pccRule, &tcData, &qosData, nil, nil) + smPolicy.PccRuleIdGenarator++ + updateSMpolicy = true + key := fmt.Sprintf("appId-%s", reqData.AfAppId) + relatedPccRuleIds[key] = pccRule.PccRuleId + } + } else { + sendProblemDetail(httpChannel, "Traffic routing not supported", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + } else { + sendProblemDetail(httpChannel, "AF Request need AfAppId or Media Component to match Service Data Flow", pcf_util.ERROR_REQUEST_PARAMETERS) + return + } + + // Event Subscription + eventSubs := make(map[models.AfEvent]models.AfNotifMethod) + if reqData.EvSubsc != nil { + for _, subs := range reqData.EvSubsc.Events { + if subs.NotifMethod == "" { + // default value "EVENT_DETECTION" + subs.NotifMethod = models.AfNotifMethod_EVENT_DETECTION + } + eventSubs[subs.Event] = subs.NotifMethod + var trig models.PolicyControlRequestTrigger + switch subs.Event { + case models.AfEvent_ACCESS_TYPE_CHANGE: + trig = models.PolicyControlRequestTrigger_AC_TY_CH + // case models.AfEvent_FAILED_RESOURCES_ALLOCATION: + // // Subscription to Service Data Flow Deactivation + // trig = models.PolicyControlRequestTrigger_RES_RELEASE + case models.AfEvent_PLMN_CHG: + trig = models.PolicyControlRequestTrigger_PLMN_CH + case models.AfEvent_QOS_NOTIF: + // Subscriptions to Service Data Flow QoS notification control + for _, pccRuleId := range relatedPccRuleIds { + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + for _, qosId := range pccRule.RefQosData { + qosData := smPolicy.PolicyDecision.QosDecs[qosId] + qosData.Qnc = true + smPolicy.PolicyDecision.QosDecs[qosId] = qosData + } + } + trig = models.PolicyControlRequestTrigger_QOS_NOTIF + case models.AfEvent_SUCCESSFUL_RESOURCES_ALLOCATION: + // Subscription to resources allocation outcome + trig = models.PolicyControlRequestTrigger_SUCC_RES_ALLO + case models.AfEvent_USAGE_REPORT: + trig = models.PolicyControlRequestTrigger_US_RE + default: + logger.PolicyAuthorizationlog.Warn("AF Event is unknown") + continue + } + if !pcf_util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { + smPolicy.PolicyDecision.PolicyCtrlReqTriggers = append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) + updateSMpolicy = true + } + + } + } + + // Initial provisioning of sponsored connectivity information + if reqData.AspId != "" && reqData.SponId != "" { + supp := pcf_util.CheckSuppFeat(nSuppFeat, 2) && pcf_util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 12) // SponsoredConnectivity = 2 in 29514 & SponsoredConnectivity support = 12 in 29512 + if !supp { + sendProblemDetail(httpChannel, "Sponsored Connectivity not supported", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + umId := pcf_util.GetUmId(reqData.AspId, reqData.SponId) + umData, err := extractUmData(umId, eventSubs, reqData.EvSubsc.UsgThres) + if err != nil { + sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + err = handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, reqData.AspId, reqData.SponId, reqData.SponStatus, umData, &updateSMpolicy) + if err != nil { + return + } + } + + // Allocate App Session Id + appSessionId := ue.AllocUeAppSessionId(pcfSelf) + request.AscRespData = &models.AppSessionContextRespData{ + SuppFeat: nSuppFeat, + } + // Associate App Session to SMPolicy + smPolicy.AppSessions[appSessionId] = true + data := pcf_context.AppSessionData{ + AppSessionId: appSessionId, + AppSessionContext: &request, + SmPolicyData: smPolicy, + } + if len(relatedPccRuleIds) > 0 { + data.RelatedPccRuleIds = relatedPccRuleIds + data.PccRuleIdMapToCompId = reverseStringMap(relatedPccRuleIds) + } + request.EvsNotif = &models.EventsNotification{} + // Set Event Subsciption related Data + if len(eventSubs) > 0 { + data.Events = eventSubs + data.EventUri = reqData.EvSubsc.NotifUri + if _, exist := eventSubs[models.AfEvent_PLMN_CHG]; exist { + afNotif := models.AfEventNotification{ + Event: models.AfEvent_PLMN_CHG, + } + request.EvsNotif.EvNotifs = append(request.EvsNotif.EvNotifs, afNotif) + plmnId := smPolicy.PolicyContext.ServingNetwork + if plmnId != nil { + request.EvsNotif.PlmnId = &models.PlmnId{ + Mcc: plmnId.Mcc, + Mnc: plmnId.Mnc, + } + } + } + if _, exist := eventSubs[models.AfEvent_ACCESS_TYPE_CHANGE]; exist { + afNotif := models.AfEventNotification{ + Event: models.AfEvent_ACCESS_TYPE_CHANGE, + } + request.EvsNotif.EvNotifs = append(request.EvsNotif.EvNotifs, afNotif) + request.EvsNotif.AccessType = smPolicy.PolicyContext.AccessType + request.EvsNotif.RatType = smPolicy.PolicyContext.RatType + } + } + if request.EvsNotif.EvNotifs == nil { + request.EvsNotif = nil + } + pcfSelf.AppSessionPool[appSessionId] = &data + locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId) + headers := http.Header{ + "Location": {locationHeader}, + } + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create", appSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, request) + // Send Notification to SMF + if updateSMpolicy { + smPolicyId := fmt.Sprintf("%s-%d", ue.Supi, smPolicy.PolicyContext.PduSessionId) + notification := models.SmPolicyNotification{ + ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + SmPolicyDecision: smPolicy.PolicyDecision, + } + SendSMPolicyUpdateNotification(ue, smPolicyId, notification) + logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) + } +} + +// DeleteAppSession - Deletes an existing Individual Application Session Context +func DeleteAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string, requset *models.EventsSubscReqData) { + + logger.PolicyAuthorizationlog.Tracef("Handle Del AppSessions, AppSessionId[%s]", appSessionId) + pcfSelf := pcf_context.PCF_Self() + + appSession := pcfSelf.AppSessionPool[appSessionId] + if appSession == nil { + sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return + } + if requset != nil { + logger.PolicyAuthorizationlog.Warnf("Delete AppSessions does not support with Event Subscription") + } + // Remove related pcc rule resourse + smPolicy := appSession.SmPolicyData + for _, pccRuleId := range appSession.RelatedPccRuleIds { + err := smPolicy.RemovePccRule(pccRuleId) + if err != nil { + logger.PolicyAuthorizationlog.Warnf(err.Error()) + } + } + + delete(smPolicy.AppSessions, appSessionId) + + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Del", appSessionId) + + // TODO: AccUsageReport + // if appSession.AccUsage != nil { + + // resp := models.AppSessionContext{ + // EvsNotif: &models.EventsNotification{ + // UsgRep: appSession.AccUsage, + // }, + // } + // pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, resp) + // } else { + // } + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + + delete(pcfSelf.AppSessionPool, appSessionId) + + smPolicy.ArrangeExistEventSubscription() + + // Notify SMF About Pcc Rule moval + smPolicyId := fmt.Sprintf("%s-%d", smPolicy.PcfUe.Supi, smPolicy.PolicyContext.PduSessionId) + notification := models.SmPolicyNotification{ + ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + SmPolicyDecision: smPolicy.PolicyDecision, + } + SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) + logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) + +} + +// GetAppSession - Reads an existing Individual Application Session Context +func GetAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string) { + logger.PolicyAuthorizationlog.Tracef("Handle Get AppSessions, AppSessionId[%s]", appSessionId) + pcfSelf := pcf_context.PCF_Self() + + appSession := pcfSelf.AppSessionPool[appSessionId] + if appSession == nil { + sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return + } + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Get", appSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appSession.AppSessionContext) +} + +// ModAppSession - Modifies an existing Individual Application Session Context +func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string, request models.AppSessionContextUpdateData) { + + logger.PolicyAuthorizationlog.Tracef("Handle Modi AppSessions, AppSessionId[%s]", appSessionId) + pcfSelf := pcf_context.PCF_Self() + appSession := pcfSelf.AppSessionPool[appSessionId] + if appSession == nil { + sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return + } + appContext := appSession.AppSessionContext + if request.BdtRefId != "" { + appContext.AscReqData.BdtRefId = request.BdtRefId + err := handleBackgroundDataTransferPolicyIndication(pcfSelf, appContext) + if err != nil { + sendProblemDetail(httpChannel, err.Error(), pcf_util.ERROR_REQUEST_PARAMETERS) + return + } + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Updated", appSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appContext) + return + + } + smPolicy := appSession.SmPolicyData + if smPolicy == nil { + sendProblemDetail(httpChannel, "Can't find related PDU Session", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + traffRoutSupp := pcf_util.CheckSuppFeat(appContext.AscRespData.SuppFeat, 1) && pcf_util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 + relatedPccRuleIds := make(map[string]string) + // Event Subscription + eventSubs := make(map[models.AfEvent]models.AfNotifMethod) + updateSMpolicy := false + + if request.MedComponents != nil { + maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) + for compN, mediaComponent := range request.MedComponents { + removeMediaComp(appSession, compN) + if zero.IsZero(mediaComponent) { + // remove MediaComp(media Comp is null) + continue + } + // modify MediaComp(remove and reinstall again) + var pccRule *models.PccRule + // TODO: use specific algorithm instead of default, details in subsclause 7.3.3 of TS 29513 + var var5qi int32 = 9 + if mediaComponent.MedType != "" { + var5qi = pcf_util.MediaTypeTo5qiMap[mediaComponent.MedType] + } + qosMediaComp := models.MediaComponent{ + MarBwDl: mediaComponent.MarBwDl, + MarBwUl: mediaComponent.MarBwUl, + MirBwDl: mediaComponent.MirBwDl, + MirBwUl: mediaComponent.MirBwUl, + } + if mediaComponent.MedSubComps != nil { + for _, mediaSubComponentRm := range mediaComponent.MedSubComps { + mediaSubComponent := models.MediaSubComponent(mediaSubComponentRm) + flowInfos, err := getFlowInfos(mediaSubComponent) + if err != nil { + sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + pccRule = pcf_util.GetPccRuleByFlowInfos(smPolicy.PolicyDecision.PccRules, flowInfos) + if pccRule == nil { + pccRule = pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + // Set QoS Data + // TODO: use real arp + qosData := pcf_util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) + if var5qi <= 4 { + // update Qos Data accroding to request BitRate + var ul, dl bool + + qosData, ul, dl = updateQos_subComp(qosData, qosMediaComp, mediaSubComponent) + err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) + if err != nil { + return + } + } + // Set PackfiltId + for i := range flowInfos { + flowInfos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + smPolicy.PackFiltMapToPccRuleId[flowInfos[i].PackFiltId] = pccRule.PccRuleId + smPolicy.PackFiltIdGenarator++ + } + // Set flowsInfo in Pcc Rule + pccRule.FlowInfos = flowInfos + // Set Traffic Control Data + tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaSubComponent.FStatus) + pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + smPolicy.PccRuleIdGenarator++ + maxPrecedence++ + } else { + // update qos + var qosData models.QosData + for _, qosId := range pccRule.RefQosData { + qosData = smPolicy.PolicyDecision.QosDecs[qosId] + if qosData.Var5qi == var5qi && qosData.Var5qi <= 4 { + var ul, dl bool + qosData, ul, dl = updateQos_subComp(smPolicy.PolicyDecision.QosDecs[qosId], qosMediaComp, mediaSubComponent) + err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) + if err != nil { + fmt.Println(err.Error()) + return + } + smPolicy.PolicyDecision.QosDecs[qosData.QosId] = qosData + } + } + } + // Modify provisioning of traffic routing information + if traffRoutSupp { + ModifyProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, request.AfRoutReq) + } + smPolicy.PolicyDecision.PccRules[pccRule.PccRuleId] = *pccRule + key := fmt.Sprintf("%d-%d", mediaComponent.MedCompN, mediaSubComponent.FNum) + relatedPccRuleIds[key] = pccRule.PccRuleId + updateSMpolicy = true + } + continue + } else if mediaComponent.AfAppId != "" { + // if mediaComponent.AfAppId has value -> find pccRule by reqData.AfAppId, otherwise create a new pcc rule + pccRule = pcf_util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, mediaComponent.AfAppId) + if pccRule != nil { + pccRule.AppId = mediaComponent.AfAppId + } + } else if request.AfAppId != "" { + pccRule = pcf_util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, request.AfAppId) + if pccRule != nil { + pccRule.AppId = request.AfAppId + } + } else { + sendProblemDetail(httpChannel, "Media Component needs flows of subComp or afAppId", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + + if pccRule == nil { // create new pcc rule + pccRule = pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + if mediaComponent.AfAppId != "" { + pccRule.AppId = mediaComponent.AfAppId + } else { + pccRule.AppId = request.AfAppId + } + // Set QoS Data + // TODO: use real arp + qosData := pcf_util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) + if var5qi <= 4 { + // update Qos Data accroding to request BitRate + var ul, dl bool + qosData, ul, dl = updateQos_Comp(qosData, qosMediaComp) + err := modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) + if err != nil { + return + } + } + + // Set Traffic Control Data + tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaComponent.FStatus) + pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + smPolicy.PccRuleIdGenarator++ + maxPrecedence++ + } else { + // update qos + var qosData models.QosData + for _, qosId := range pccRule.RefQosData { + qosData = smPolicy.PolicyDecision.QosDecs[qosId] + if qosData.Var5qi == var5qi && qosData.Var5qi <= 4 { + var ul, dl bool + qosData, ul, dl = updateQos_Comp(smPolicy.PolicyDecision.QosDecs[qosId], qosMediaComp) + err := modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) + if err != nil { + return + } + smPolicy.PolicyDecision.QosDecs[qosData.QosId] = qosData + } + } + } + key := fmt.Sprintf("%d", mediaComponent.MedCompN) + relatedPccRuleIds[key] = pccRule.PccRuleId + // TODO : handle temporal or spatial validity + // Modify provisioning of traffic routing information + if traffRoutSupp { + ModifyProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, request.AfRoutReq) + } + updateSMpolicy = true + + } + } + + // Merge Original PccRuleId and new + for key, pccRuleId := range appSession.RelatedPccRuleIds { + relatedPccRuleIds[key] = pccRuleId + } + + if request.EvSubsc != nil { + for _, subs := range request.EvSubsc.Events { + if subs.NotifMethod == "" { + // default value "EVENT_DETECTION" + subs.NotifMethod = models.AfNotifMethod_EVENT_DETECTION + } + eventSubs[subs.Event] = subs.NotifMethod + var trig models.PolicyControlRequestTrigger + switch subs.Event { + case models.AfEvent_ACCESS_TYPE_CHANGE: + trig = models.PolicyControlRequestTrigger_AC_TY_CH + // case models.AfEvent_FAILED_RESOURCES_ALLOCATION: + // // Subscription to Service Data Flow Deactivation + // trig = models.PolicyControlRequestTrigger_SUCC_RES_ALLO + case models.AfEvent_PLMN_CHG: + trig = models.PolicyControlRequestTrigger_PLMN_CH + case models.AfEvent_QOS_NOTIF: + // Subscriptions to Service Data Flow QoS notification control + for _, pccRuleId := range relatedPccRuleIds { + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + for _, qosId := range pccRule.RefQosData { + qosData := smPolicy.PolicyDecision.QosDecs[qosId] + qosData.Qnc = true + smPolicy.PolicyDecision.QosDecs[qosId] = qosData + } + } + trig = models.PolicyControlRequestTrigger_QOS_NOTIF + case models.AfEvent_SUCCESSFUL_RESOURCES_ALLOCATION: + // Subscription to resources allocation outcome + trig = models.PolicyControlRequestTrigger_SUCC_RES_ALLO + case models.AfEvent_USAGE_REPORT: + trig = models.PolicyControlRequestTrigger_US_RE + default: + logger.PolicyAuthorizationlog.Warn("AF Event is unknown") + continue + } + if !pcf_util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { + smPolicy.PolicyDecision.PolicyCtrlReqTriggers = append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) + updateSMpolicy = true + } + + } + // update Context + if appContext.AscReqData.EvSubsc == nil { + appContext.AscReqData.EvSubsc = new(models.EventsSubscReqData) + } + appContext.AscReqData.EvSubsc.Events = request.EvSubsc.Events + if request.EvSubsc.NotifUri != "" { + appContext.AscReqData.EvSubsc.NotifUri = request.EvSubsc.NotifUri + appSession.EventUri = request.EvSubsc.NotifUri + } + if request.EvSubsc.UsgThres != nil { + appContext.AscReqData.EvSubsc.UsgThres = threshRmToThresh(request.EvSubsc.UsgThres) + } + + } else { + // remove eventSubs + appSession.Events = nil + appSession.EventUri = "" + appContext.AscReqData.EvSubsc = nil + } + + // Moification provisioning of sponsored connectivity information + if request.AspId != "" && request.SponId != "" { + umId := pcf_util.GetUmId(request.AspId, request.SponId) + umData, err := extractUmData(umId, eventSubs, threshRmToThresh(request.EvSubsc.UsgThres)) + if err != nil { + sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + err = handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, request.AspId, request.SponId, request.SponStatus, umData, &updateSMpolicy) + if err != nil { + return + } + } + + if len(relatedPccRuleIds) > 0 { + appSession.RelatedPccRuleIds = relatedPccRuleIds + appSession.PccRuleIdMapToCompId = reverseStringMap(relatedPccRuleIds) + + } + appContext.EvsNotif = &models.EventsNotification{} + // Set Event Subsciption related Data + if len(eventSubs) > 0 { + appSession.Events = eventSubs + if _, exist := eventSubs[models.AfEvent_PLMN_CHG]; exist { + afNotif := models.AfEventNotification{ + Event: models.AfEvent_PLMN_CHG, + } + appContext.EvsNotif.EvNotifs = append(appContext.EvsNotif.EvNotifs, afNotif) + plmnId := smPolicy.PolicyContext.ServingNetwork + if plmnId != nil { + appContext.EvsNotif.PlmnId = &models.PlmnId{ + Mcc: plmnId.Mcc, + Mnc: plmnId.Mnc, + } + } + } + if _, exist := eventSubs[models.AfEvent_ACCESS_TYPE_CHANGE]; exist { + afNotif := models.AfEventNotification{ + Event: models.AfEvent_ACCESS_TYPE_CHANGE, + } + appContext.EvsNotif.EvNotifs = append(appContext.EvsNotif.EvNotifs, afNotif) + appContext.EvsNotif.AccessType = smPolicy.PolicyContext.AccessType + appContext.EvsNotif.RatType = smPolicy.PolicyContext.RatType + } + } + if appContext.EvsNotif.EvNotifs == nil { + appContext.EvsNotif = nil + } + + // TODO: MPS Sevice + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Updated", appSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appContext) + + smPolicy.ArrangeExistEventSubscription() + + // Send Notification to SMF + if updateSMpolicy { + smPolicyId := fmt.Sprintf("%s-%d", smPolicy.PcfUe.Supi, smPolicy.PolicyContext.PduSessionId) + notification := models.SmPolicyNotification{ + ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + SmPolicyDecision: smPolicy.PolicyDecision, + } + SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) + logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) + } + +} + +// DeleteEventsSubsc - deletes the Events Subscription subresource +func DeleteEventsSubscContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string) { + + logger.PolicyAuthorizationlog.Tracef("Handle Del AppSessions Events Subsc, AppSessionId[%s]", appSessionId) + pcfSelf := pcf_context.PCF_Self() + + appSession := pcfSelf.AppSessionPool[appSessionId] + if appSession == nil { + sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return + } + appSession.Events = nil + appSession.EventUri = "" + appSession.AppSessionContext.EvsNotif = nil + appSession.AppSessionContext.AscReqData.EvSubsc = nil + + changed := appSession.SmPolicyData.ArrangeExistEventSubscription() + + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Del Events Subsc success", appSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + + smPolicy := appSession.SmPolicyData + // Send Notification to SMF + if changed { + smPolicyId := fmt.Sprintf("%s-%d", smPolicy.PcfUe.Supi, smPolicy.PolicyContext.PduSessionId) + notification := models.SmPolicyNotification{ + ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + SmPolicyDecision: smPolicy.PolicyDecision, + } + SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) + logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) + } +} + +// UpdateEventsSubsc - creates or modifies an Events Subscription subresource +func UpdateEventsSubscContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string, request models.EventsSubscReqData) { + + logger.PolicyAuthorizationlog.Tracef("Handle Put AppSessions Events Subsc, AppSessionId[%s]", appSessionId) + pcfSelf := pcf_context.PCF_Self() + + appSession := pcfSelf.AppSessionPool[appSessionId] + if appSession == nil { + sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return + } + smPolicy := appSession.SmPolicyData + eventSubs := make(map[models.AfEvent]models.AfNotifMethod) + + updataSmPolicy := false + created := false + if appSession.Events == nil { + created = true + } + + for _, subs := range request.Events { + if subs.NotifMethod == "" { + // default value "EVENT_DETECTION" + subs.NotifMethod = models.AfNotifMethod_EVENT_DETECTION + } + eventSubs[subs.Event] = subs.NotifMethod + var trig models.PolicyControlRequestTrigger + switch subs.Event { + case models.AfEvent_ACCESS_TYPE_CHANGE: + trig = models.PolicyControlRequestTrigger_AC_TY_CH + // case models.AfEvent_FAILED_RESOURCES_ALLOCATION: + // // Subscription to Service Data Flow Deactivation + // trig = models.PolicyControlRequestTrigger_SUCC_RES_ALLO + case models.AfEvent_PLMN_CHG: + trig = models.PolicyControlRequestTrigger_PLMN_CH + case models.AfEvent_QOS_NOTIF: + // Subscriptions to Service Data Flow QoS notification control + for _, pccRuleId := range appSession.RelatedPccRuleIds { + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + for _, qosId := range pccRule.RefQosData { + qosData := smPolicy.PolicyDecision.QosDecs[qosId] + qosData.Qnc = true + smPolicy.PolicyDecision.QosDecs[qosId] = qosData + } + } + trig = models.PolicyControlRequestTrigger_QOS_NOTIF + case models.AfEvent_SUCCESSFUL_RESOURCES_ALLOCATION: + // Subscription to resources allocation outcome + trig = models.PolicyControlRequestTrigger_SUCC_RES_ALLO + case models.AfEvent_USAGE_REPORT: + trig = models.PolicyControlRequestTrigger_US_RE + default: + logger.PolicyAuthorizationlog.Warn("AF Event is unknown") + continue + } + if !pcf_util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { + smPolicy.PolicyDecision.PolicyCtrlReqTriggers = append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) + updataSmPolicy = true + } + + } + appContext := appSession.AppSessionContext + // update Context + if appContext.AscReqData.EvSubsc == nil { + appContext.AscReqData.EvSubsc = new(models.EventsSubscReqData) + } + appContext.AscReqData.EvSubsc.Events = request.Events + appContext.AscReqData.EvSubsc.UsgThres = request.UsgThres + appContext.AscReqData.EvSubsc.NotifUri = request.NotifUri + appContext.EvsNotif = nil + // update app Session + appSession.EventUri = request.NotifUri + appSession.Events = eventSubs + + resp := models.UpdateEventsSubscResponse{ + EvSubsc: request, + } + appContext.EvsNotif = &models.EventsNotification{ + EvSubsUri: request.NotifUri, + } + // Set Event Subsciption related Data + if len(eventSubs) > 0 { + if _, exist := eventSubs[models.AfEvent_PLMN_CHG]; exist { + afNotif := models.AfEventNotification{ + Event: models.AfEvent_PLMN_CHG, + } + appContext.EvsNotif.EvNotifs = append(appContext.EvsNotif.EvNotifs, afNotif) + plmnId := smPolicy.PolicyContext.ServingNetwork + if plmnId != nil { + appContext.EvsNotif.PlmnId = &models.PlmnId{ + Mcc: plmnId.Mcc, + Mnc: plmnId.Mnc, + } + } + } + if _, exist := eventSubs[models.AfEvent_ACCESS_TYPE_CHANGE]; exist { + afNotif := models.AfEventNotification{ + Event: models.AfEvent_ACCESS_TYPE_CHANGE, + } + appContext.EvsNotif.EvNotifs = append(appContext.EvsNotif.EvNotifs, afNotif) + appContext.EvsNotif.AccessType = smPolicy.PolicyContext.AccessType + appContext.EvsNotif.RatType = smPolicy.PolicyContext.RatType + } + } + if appContext.EvsNotif.EvNotifs == nil { + appContext.EvsNotif = nil + } + + resp.EvsNotif = appContext.EvsNotif + + if created { + locationHeader := fmt.Sprintf("%s/events-subscription", pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId)) + headers := http.Header{ + "Location": {locationHeader}, + } + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create Subscription", appSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, resp) + } else if resp.EvsNotif != nil { + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Modify Subscription", appSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, resp) + } else { + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Modify Subscription", appSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, resp) + } + + changed := appSession.SmPolicyData.ArrangeExistEventSubscription() + + // Send Notification to SMF + if updataSmPolicy || changed { + smPolicyId := fmt.Sprintf("%s-%d", smPolicy.PcfUe.Supi, smPolicy.PolicyContext.PduSessionId) + notification := models.SmPolicyNotification{ + ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + SmPolicyDecision: smPolicy.PolicyDecision, + } + SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) + logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) + } +} + +func SendAppSessionEventNotification(appSession *pcf_context.AppSessionData, request models.EventsNotification) { + logger.PolicyAuthorizationlog.Tracef("Send App Session Event Notification") + if appSession == nil { + logger.PolicyAuthorizationlog.Warnln("Send App Session Event Notification Error[appSession is nil]") + return + } + uri := appSession.EventUri + if uri != "" { + request.EvSubsUri = fmt.Sprintf("%s/events-subscription", pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSession.AppSessionId)) + client := pcf_util.GetNpcfPolicyAuthorizationCallbackClient() + httpResponse, err := client.PolicyAuthorizationEventNotificationApi.PolicyAuthorizationEventNotification(context.Background(), uri, request) + if err != nil { + if httpResponse != nil { + logger.PolicyAuthorizationlog.Warnf("Send App Session Event Notification Error[%s]", httpResponse.Status) + } else { + logger.PolicyAuthorizationlog.Warnf("Send App Session Event Notification Failed[%s]", err.Error()) + } + return + } else if httpResponse == nil { + logger.PolicyAuthorizationlog.Warnln("Send App Session Event Notification Failed[HTTP Response is nil]") + return + } + if httpResponse.StatusCode != http.StatusOK && httpResponse.StatusCode != http.StatusNoContent { + logger.PolicyAuthorizationlog.Warnf("Send App Session Event Notification Failed") + } else { + logger.PolicyAuthorizationlog.Tracef("Send App Session Event Notification Success") + } + } +} + +func SendAppSessionTermination(appSession *pcf_context.AppSessionData, request models.TerminationInfo) { + logger.PolicyAuthorizationlog.Tracef("Send App Session Termination") + if appSession == nil { + logger.PolicyAuthorizationlog.Warnln("Send App Session Termination Error[appSession is nil]") + return + } + uri := appSession.AppSessionContext.AscReqData.NotifUri + if uri != "" { + request.ResUri = pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSession.AppSessionId) + client := pcf_util.GetNpcfPolicyAuthorizationCallbackClient() + httpResponse, err := client.PolicyAuthorizationTerminateRequestApi.PolicyAuthorizationTerminateRequest(context.Background(), uri, request) + if err != nil { + if httpResponse != nil { + logger.PolicyAuthorizationlog.Warnf("Send App Session Termination Error[%s]", httpResponse.Status) + } else { + logger.PolicyAuthorizationlog.Warnf("Send App Session Termination Failed[%s]", err.Error()) + } + return + } else if httpResponse == nil { + logger.PolicyAuthorizationlog.Warnln("Send App Session Termination Failed[HTTP Response is nil]") + return + } + if httpResponse.StatusCode != http.StatusOK && httpResponse.StatusCode != http.StatusNoContent { + logger.PolicyAuthorizationlog.Warnf("Send App Session Termination Failed") + } else { + logger.PolicyAuthorizationlog.Tracef("Send App Session Termination Success") + } + } +} + +// Handle Create/ Modify Background Data Transfer Policy Indication +func handleBackgroundDataTransferPolicyIndication(pcfSelf *pcf_context.PCFContext, appContext *models.AppSessionContext) (err error) { + req := appContext.AscReqData + respData := models.AppSessionContextRespData{ + ServAuthInfo: models.ServAuthInfo_NOT_KNOWN, + SuppFeat: pcf_util.GetNegotiateSuppFeat(req.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION]), + } + client := pcf_util.GetNudrClient(getDefaultUdrUri(pcfSelf)) + bdtData, resp, err1 := client.DefaultApi.PolicyDataBdtDataBdtReferenceIdGet(context.Background(), req.BdtRefId) + if err1 != nil { + return fmt.Errorf("UDR Get BdtDate error[%s]", err1.Error()) + } else if resp == nil || resp.StatusCode != http.StatusOK { + return fmt.Errorf("UDR Get BdtDate error") + } else { + startTime, err1 := time.Parse(pcf_util.TimeFormat, bdtData.TransPolicy.RecTimeInt.StartTime) + if err1 != nil { + return err1 + } + stopTime, err1 := time.Parse(pcf_util.TimeFormat, bdtData.TransPolicy.RecTimeInt.StopTime) + if err1 != nil { + return err1 + } + if startTime.After(time.Now()) { + respData.ServAuthInfo = models.ServAuthInfo_NOT_YET_OCURRED + } else if stopTime.Before(time.Now()) { + respData.ServAuthInfo = models.ServAuthInfo_EXPIRED + } + } + appContext.AscRespData = &respData + return nil +} + +// provisioning of sponsored connectivity information +func handleSponsoredConnectivityInformation(smPolicy *pcf_context.UeSmPolicyData, relatedPccRuleIds map[string]string, aspId, sponId string, sponStatus models.SponsoringStatus, umData *models.UsageMonitoringData, updateSMpolicy *bool) (err error) { + if sponStatus == models.SponsoringStatus_DISABLED { + logger.PolicyAuthorizationlog.Debugf("Sponsored Connectivity is disabled by AF") + umId := pcf_util.GetUmId(aspId, sponId) + for _, pccRuleId := range relatedPccRuleIds { + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + for _, chgId := range pccRule.RefChgData { + // disables sponsoring a service + chgData := smPolicy.PolicyDecision.ChgDecs[chgId] + if chgData.AppSvcProvId == aspId && chgData.SponsorId == sponId { + chgData.SponsorId = "" + chgData.AppSvcProvId = "" + chgData.ReportingLevel = models.ReportingLevel_SER_ID_LEVEL + smPolicy.PolicyDecision.ChgDecs[chgId] = chgData + *updateSMpolicy = true + } + } + if pccRule.RefUmData != nil { + pccRule.RefUmData = nil + smPolicy.PolicyDecision.PccRules[pccRuleId] = pccRule + } + // disable the usage monitoring + // TODO: As a result, PCF gets the accumulated usage of the sponsored data connectivity + delete(smPolicy.PolicyDecision.UmDecs, umId) + } + } else { + + if umData != nil { + supp := pcf_util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 5) // UMC support = 5 in 29512 + if !supp { + err = fmt.Errorf("Usage Monitor Control is not supported in SMF") + return + } + } + chgIdUsed := false + chgId := pcf_util.GetChgId(smPolicy.ChargingIdGenarator) + for _, pccRuleId := range relatedPccRuleIds { + pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] + chgData := models.ChargingData{ + ChgId: chgId, + } + if pccRule.RefChgData != nil { + chgId := pccRule.RefChgData[0] + chgData = smPolicy.PolicyDecision.ChgDecs[chgId] + } else { + chgIdUsed = true + } + // TODO: PCF, based on operator policies, shall check whether it is required to validate the sponsored connectivity data. + // If it is required, it shall perform the authorizations based on sponsored data connectivity profiles. + // If the authorization fails, the PCF shall send HTTP "403 Forbidden" with the "cause" attribute set to "UNAUTHORIZED_SPONSORED_DATA_CONNECTIVITY" + pccRule.RefChgData = []string{chgData.ChgId} + chgData.ReportingLevel = models.ReportingLevel_SPON_CON_LEVEL + chgData.SponsorId = sponId + chgData.AppSvcProvId = aspId + if umData != nil { + pccRule.RefUmData = []string{umData.UmId} + } + pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, &pccRule, nil, nil, &chgData, umData) + *updateSMpolicy = true + } + if chgIdUsed { + smPolicy.ChargingIdGenarator++ + } + // TODO: handling UE is roaming in VPLMN case + } + return +} + +func getMaxPrecedence(pccRules map[string]models.PccRule) (maxVaule int32) { + maxVaule = 0 + for _, rule := range pccRules { + if rule.Precedence > maxVaule { + maxVaule = rule.Precedence + } + } + return +} + +/* +func getFlowInfos(comp models.MediaComponent) (flows []models.FlowInformation, err error) { + for _, subComp := range comp.MedSubComps { + if subComp.EthfDescs != nil { + return nil, fmt.Errorf("Flow Description with Mac Address does not support") + } + fStatus := subComp.FStatus + if subComp.FlowUsage == models.FlowUsage_RTCP { + fStatus = models.FlowStatus_ENABLED + } else if fStatus == "" { + fStatus = comp.FStatus + } + if fStatus == models.FlowStatus_REMOVED { + continue + } + // gate control + statusUsage := map[models.FlowDirection]bool{ + models.FlowDirection_UPLINK: true, + models.FlowDirection_DOWNLINK: true, + } + switch fStatus { + case models.FlowStatus_ENABLED_UPLINK: + statusUsage[models.FlowDirection_DOWNLINK] = false + case models.FlowStatus_ENABLED_DOWNLINK: + statusUsage[models.FlowDirection_UPLINK] = false + case models.FlowStatus_DISABLED: + statusUsage[models.FlowDirection_DOWNLINK] = false + statusUsage[models.FlowDirection_UPLINK] = false + } + for _, desc := range subComp.FDescs { + flowDesc, flowDir, err := flowDescriptionFromN5toN7(desc) + if err != nil { + return nil, err + } + flowInfo := models.FlowInformation{ + FlowDescription: flowDesc, + FlowDirection: models.FlowDirectionRm(flowDir), + PacketFilterUsage: statusUsage[flowDir], + TosTrafficClass: subComp.TosTrCl, + } + flows = append(flows, flowInfo) + } + } + return +} +*/ + +func getFlowInfos(subComp models.MediaSubComponent) (flows []models.FlowInformation, err error) { + if subComp.EthfDescs != nil { + return nil, fmt.Errorf("Flow Description with Mac Address does not support") + } + fStatus := subComp.FStatus + if subComp.FlowUsage == models.FlowUsage_RTCP { + fStatus = models.FlowStatus_ENABLED + } + if fStatus == models.FlowStatus_REMOVED { + return nil, nil + } + // gate control + statusUsage := map[models.FlowDirection]bool{ + models.FlowDirection_UPLINK: true, + models.FlowDirection_DOWNLINK: true, + } + switch fStatus { + case models.FlowStatus_ENABLED_UPLINK: + statusUsage[models.FlowDirection_DOWNLINK] = false + case models.FlowStatus_ENABLED_DOWNLINK: + statusUsage[models.FlowDirection_UPLINK] = false + case models.FlowStatus_DISABLED: + statusUsage[models.FlowDirection_DOWNLINK] = false + statusUsage[models.FlowDirection_UPLINK] = false + } + for _, desc := range subComp.FDescs { + flowDesc, flowDir, err := flowDescriptionFromN5toN7(desc) + if err != nil { + return nil, err + } + flowInfo := models.FlowInformation{ + FlowDescription: flowDesc, + FlowDirection: models.FlowDirectionRm(flowDir), + PacketFilterUsage: statusUsage[flowDir], + TosTrafficClass: subComp.TosTrCl, + } + flows = append(flows, flowInfo) + } + return +} + +func flowDescriptionFromN5toN7(n5Flow string) (n7Flow string, direction models.FlowDirection, err error) { + if strings.HasPrefix(n5Flow, "permit out") { + n7Flow = n5Flow + direction = models.FlowDirection_DOWNLINK + } else if strings.HasPrefix(n5Flow, "permit in") { + n7Flow = strings.Replace(n5Flow, "permit in", "permit out", -1) + direction = models.FlowDirection_UPLINK + } else if strings.HasPrefix(n5Flow, "permit inout") { + n7Flow = strings.Replace(n5Flow, "permit inout", "permit out", -1) + direction = models.FlowDirection_BIDIRECTIONAL + } else { + err = fmt.Errorf("Invaild flow Description[%s]", n5Flow) + } + return +} +func updateQos_Comp(qosData models.QosData, comp models.MediaComponent) (updatedQosData models.QosData, ulExist, dlExist bool) { + updatedQosData = qosData + if comp.FStatus == models.FlowStatus_REMOVED { + updatedQosData.MaxbrDl = "" + updatedQosData.MaxbrUl = "" + return + } + maxBwUl := 0.0 + maxBwDl := 0.0 + minBwUl := 0.0 + minBwDl := 0.0 + for _, subsComp := range comp.MedSubComps { + for _, flow := range subsComp.FDescs { + _, dir, _ := flowDescriptionFromN5toN7(flow) + both := false + if dir == models.FlowDirection_BIDIRECTIONAL { + both = true + } + if subsComp.FlowUsage != models.FlowUsage_RTCP { + // not RTCP + if both || dir == models.FlowDirection_UPLINK { + ulExist = true + if comp.MarBwUl != "" { + bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + maxBwUl += bwUl + } + if comp.MirBwUl != "" { + bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MirBwUl) + minBwUl += bwUl + } + } + if both || dir == models.FlowDirection_DOWNLINK { + dlExist = true + if comp.MarBwDl != "" { + bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + maxBwDl += bwDl + } + if comp.MirBwDl != "" { + bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MirBwDl) + minBwDl += bwDl + } + } + } else { + if both || dir == models.FlowDirection_UPLINK { + ulExist = true + if subsComp.MarBwUl != "" { + bwUl, _ := pcf_context.ConvertBitRateToKbps(subsComp.MarBwUl) + maxBwUl += bwUl + } else if comp.MarBwUl != "" { + bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + maxBwUl += (0.05 * bwUl) + } + } + if both || dir == models.FlowDirection_DOWNLINK { + dlExist = true + if subsComp.MarBwDl != "" { + bwDl, _ := pcf_context.ConvertBitRateToKbps(subsComp.MarBwDl) + maxBwDl += bwDl + } else if comp.MarBwDl != "" { + bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + maxBwDl += (0.05 * bwDl) + } + } + } + } + } + // update Downlink MBR + if maxBwDl == 0.0 { + updatedQosData.MaxbrDl = comp.MarBwDl + } else { + updatedQosData.MaxbrDl = pcf_context.ConvertBitRateToString(maxBwDl) + } + // update Uplink MBR + if maxBwUl == 0.0 { + updatedQosData.MaxbrUl = comp.MarBwUl + } else { + updatedQosData.MaxbrUl = pcf_context.ConvertBitRateToString(maxBwUl) + } + // if gbr == 0 then assign gbr = mbr + + // update Downlink GBR + if minBwDl != 0.0 { + updatedQosData.GbrDl = pcf_context.ConvertBitRateToString(minBwDl) + } + // update Uplink GBR + if minBwUl != 0.0 { + updatedQosData.GbrUl = pcf_context.ConvertBitRateToString(minBwUl) + } + return +} + +func updateQos_subComp(qosData models.QosData, comp models.MediaComponent, subsComp models.MediaSubComponent) (updatedQosData models.QosData, ulExist, dlExist bool) { + updatedQosData = qosData + if comp.FStatus == models.FlowStatus_REMOVED { + updatedQosData.MaxbrDl = "" + updatedQosData.MaxbrUl = "" + return + } + maxBwUl := 0.0 + maxBwDl := 0.0 + minBwUl := 0.0 + minBwDl := 0.0 + for _, flow := range subsComp.FDescs { + _, dir, _ := flowDescriptionFromN5toN7(flow) + both := false + if dir == models.FlowDirection_BIDIRECTIONAL { + both = true + } + if subsComp.FlowUsage != models.FlowUsage_RTCP { + // not RTCP + if both || dir == models.FlowDirection_UPLINK { + ulExist = true + if comp.MarBwUl != "" { + bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + maxBwUl += bwUl + } + if comp.MirBwUl != "" { + bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MirBwUl) + minBwUl += bwUl + } + } + if both || dir == models.FlowDirection_DOWNLINK { + dlExist = true + if comp.MarBwDl != "" { + bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + maxBwDl += bwDl + } + if comp.MirBwDl != "" { + bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MirBwDl) + minBwDl += bwDl + } + } + } else { + if both || dir == models.FlowDirection_UPLINK { + ulExist = true + if subsComp.MarBwUl != "" { + bwUl, _ := pcf_context.ConvertBitRateToKbps(subsComp.MarBwUl) + maxBwUl += bwUl + } else if comp.MarBwUl != "" { + bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + maxBwUl += (0.05 * bwUl) + } + } + if both || dir == models.FlowDirection_DOWNLINK { + dlExist = true + if subsComp.MarBwDl != "" { + bwDl, _ := pcf_context.ConvertBitRateToKbps(subsComp.MarBwDl) + maxBwDl += bwDl + } else if comp.MarBwDl != "" { + bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + maxBwDl += (0.05 * bwDl) + } + } + } + } + + // update Downlink MBR + if maxBwDl == 0.0 { + updatedQosData.MaxbrDl = comp.MarBwDl + } else { + updatedQosData.MaxbrDl = pcf_context.ConvertBitRateToString(maxBwDl) + } + // update Uplink MBR + if maxBwUl == 0.0 { + updatedQosData.MaxbrUl = comp.MarBwUl + } else { + updatedQosData.MaxbrUl = pcf_context.ConvertBitRateToString(maxBwUl) + } + // if gbr == 0 then assign gbr = mbr + // update Downlink GBR + if minBwDl != 0.0 { + updatedQosData.GbrDl = pcf_context.ConvertBitRateToString(minBwDl) + } + // update Uplink GBR + if minBwUl != 0.0 { + updatedQosData.GbrUl = pcf_context.ConvertBitRateToString(minBwUl) + } + return +} + +func removeMediaComp(appSession *pcf_context.AppSessionData, compN string) { + idMaps := appSession.RelatedPccRuleIds + smPolicy := appSession.SmPolicyData + if idMaps != nil { + if appSession.AppSessionContext.AscReqData.MedComponents == nil { + return + } + comp, exist := appSession.AppSessionContext.AscReqData.MedComponents[compN] + if !exist { + return + } + if comp.MedSubComps != nil { + for fNum := range comp.MedSubComps { + key := fmt.Sprintf("%s-%s", compN, fNum) + pccRuleId := idMaps[key] + err := smPolicy.RemovePccRule(pccRuleId) + if err != nil { + logger.PolicyAuthorizationlog.Warnf(err.Error()) + } + delete(appSession.RelatedPccRuleIds, key) + delete(appSession.PccRuleIdMapToCompId, pccRuleId) + } + } else { + pccRuleId := idMaps[compN] + err := smPolicy.RemovePccRule(pccRuleId) + if err != nil { + logger.PolicyAuthorizationlog.Warnf(err.Error()) + } + delete(appSession.RelatedPccRuleIds, compN) + delete(appSession.PccRuleIdMapToCompId, pccRuleId) + } + delete(appSession.AppSessionContext.AscReqData.MedComponents, compN) + } +} + +// func removeMediaSubComp(appSession *pcf_context.AppSessionData, compN, fNum string) { +// key := fmt.Sprintf("%s-%s", compN, fNum) +// idMaps := appSession.RelatedPccRuleIds +// smPolicy := appSession.SmPolicyData +// if idMaps != nil { +// if appSession.AppSessionContext.AscReqData.MedComponents == nil { +// return +// } +// if comp, exist := appSession.AppSessionContext.AscReqData.MedComponents[compN]; exist { +// pccRuleId := idMaps[key] +// smPolicy.RemovePccRule(pccRuleId) +// delete(appSession.RelatedPccRuleIds, key) +// delete(comp.MedSubComps, fNum) +// appSession.AppSessionContext.AscReqData.MedComponents[compN] = comp +// } +// } +// return +// } + +func threshRmToThresh(threshrm *models.UsageThresholdRm) *models.UsageThreshold { + if threshrm == nil { + return nil + } + return &models.UsageThreshold{ + Duration: threshrm.Duration, + TotalVolume: threshrm.TotalVolume, + DownlinkVolume: threshrm.DownlinkVolume, + UplinkVolume: threshrm.UplinkVolume, + } +} + +func extractUmData(umId string, eventSubs map[models.AfEvent]models.AfNotifMethod, threshold *models.UsageThreshold) (umData *models.UsageMonitoringData, err error) { + if _, umExist := eventSubs[models.AfEvent_USAGE_REPORT]; umExist { + if threshold == nil { + return nil, fmt.Errorf("UsageThreshold is nil in USAGE REPORT Subscription") + + } else { + tmp := pcf_util.CreateUmData(umId, *threshold) + umData = &tmp + } + } + return +} + +func modifyRemainBitRate(httpChannel chan pcf_message.HttpResponseMessage, smPolicy *pcf_context.UeSmPolicyData, qosData *models.QosData, ulExist, dlExist bool) (err error) { + // if request GBR == 0, qos GBR = MBR + // if request GBR > remain GBR, qos GBR = remain GBR + if ulExist { + if qosData.GbrUl == "" { + err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.MaxbrUl) + if err != nil { + qosData.GbrUl = pcf_context.DecreaseRamainBitRateToZero(smPolicy.RemainGbrUL) + } else { + qosData.GbrUl = qosData.MaxbrUl + } + } else { + err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.GbrUl) + if err != nil { + sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + } + } + if dlExist { + if qosData.GbrDl == "" { + err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrDL, qosData.MaxbrDl) + if err != nil { + qosData.GbrDl = pcf_context.DecreaseRamainBitRateToZero(smPolicy.RemainGbrDL) + } else { + qosData.GbrDl = qosData.MaxbrDl + } + } else { + err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrDL, qosData.GbrDl) + if err != nil { + // if Policy failed, revert remain GBR to original GBR + pcf_context.IncreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.GbrUl) + sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return + } + } + } + return nil +} + +func InitialProvisioningOfTrafficRoutingInformation(smPolicy *pcf_context.UeSmPolicyData, pccRule *models.PccRule, compAfRoutReq, reqAfRoutReq *models.AfRoutingRequirement) { + for _, tcId := range pccRule.RefTcData { + tcData := smPolicy.PolicyDecision.TraffContDecs[tcId] + if compAfRoutReq != nil { + tcData.RouteToLocs = append(tcData.RouteToLocs, compAfRoutReq.RouteToLocs...) + tcData.UpPathChgEvent = compAfRoutReq.UpPathChgSub + pccRule.AppReloc = compAfRoutReq.AppReloc + } else if reqAfRoutReq != nil { + tcData.RouteToLocs = append(tcData.RouteToLocs, reqAfRoutReq.RouteToLocs...) + tcData.UpPathChgEvent = reqAfRoutReq.UpPathChgSub + pccRule.AppReloc = reqAfRoutReq.AppReloc + } + smPolicy.PolicyDecision.TraffContDecs[tcData.TcId] = tcData + } +} + +func ModifyProvisioningOfTrafficRoutingInformation(smPolicy *pcf_context.UeSmPolicyData, pccRule *models.PccRule, compAfRoutReq, reqAfRoutReq *models.AfRoutingRequirementRm) { + for _, tcId := range pccRule.RefTcData { + tcData := smPolicy.PolicyDecision.TraffContDecs[tcId] + if compAfRoutReq != nil { + tcData.RouteToLocs = append(tcData.RouteToLocs, compAfRoutReq.RouteToLocs...) + tcData.UpPathChgEvent = compAfRoutReq.UpPathChgSub + pccRule.AppReloc = compAfRoutReq.AppReloc + } else if reqAfRoutReq != nil { + tcData.RouteToLocs = append(tcData.RouteToLocs, reqAfRoutReq.RouteToLocs...) + tcData.UpPathChgEvent = reqAfRoutReq.UpPathChgSub + pccRule.AppReloc = reqAfRoutReq.AppReloc + } + smPolicy.PolicyDecision.TraffContDecs[tcData.TcId] = tcData + } +} + +func reverseStringMap(srcMap map[string]string) map[string]string { + if srcMap == nil { + return nil + } + reverseMap := make(map[string]string) + for key, value := range srcMap { + reverseMap[value] = key + } + return reverseMap +} + +func sendProblemDetail(httpChannel chan pcf_message.HttpResponseMessage, errDetail, errCause string) { + rsp := pcf_util.GetProblemDetail(errDetail, errCause) + logger.PolicyAuthorizationlog.Error(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) +} diff --git a/pcf_producer/pcf_smpolicy.go b/pcf_producer/pcf_smpolicy.go new file mode 100644 index 0000000..9d498ff --- /dev/null +++ b/pcf_producer/pcf_smpolicy.go @@ -0,0 +1,789 @@ +package pcf_producer + +import ( + "context" + "fmt" + "free5gc/lib/Nudr_DataRepository" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/pcf_util" + "net/http" + "strconv" + "strings" + + "github.com/antihax/optional" +) + +// SmPoliciesPost - +func CreateSmPolicy(httpChannel chan pcf_message.HttpResponseMessage, request models.SmPolicyContextData) { + var err error + + logger.SMpolicylog.Tracef("Handle Create SM Policy Request") + pcfSelf := pcf_context.PCF_Self() + ue := pcfSelf.UePool[request.Supi] + if ue == nil { + rsp := pcf_util.GetProblemDetail("Supi is not supported in PCF", pcf_util.USER_UNKNOWN) + logger.SMpolicylog.Warnf("Supi[%s] is not supported in PCF", request.Supi) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + } + udrUri := getUdrUri(ue) + if udrUri == "" { + rsp := pcf_util.GetProblemDetail("Can't find corresponding UDR with UE", pcf_util.USER_UNKNOWN) + logger.SMpolicylog.Warnf("Can't find corresponding UDR with UE[%s]", ue.Supi) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + var smData models.SmPolicyData + smPolicyId := fmt.Sprintf("%s-%d", ue.Supi, request.PduSessionId) + smPolicyData := ue.SmPolicyData[smPolicyId] + if smPolicyData == nil || smPolicyData.SmPolicyData == nil { + client := pcf_util.GetNudrClient(udrUri) + param := Nudr_DataRepository.PolicyDataUesUeIdSmDataGetParamOpts{ + Snssai: optional.NewInterface(pcf_util.MarshToJsonString(*request.SliceInfo)), + Dnn: optional.NewString(request.Dnn), + } + var response *http.Response + smData, response, err = client.DefaultApi.PolicyDataUesUeIdSmDataGet(context.Background(), ue.Supi, ¶m) + if err != nil || response == nil || response.StatusCode != http.StatusOK { + rsp := pcf_util.GetProblemDetail("Can't find UE SM Policy Data in UDR", pcf_util.USER_UNKNOWN) + logger.SMpolicylog.Warnf("Can't find UE[%s] SM Policy Data in UDR", ue.Supi) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + // logger.SMpolicylog.Warnln("Nudr Query failed [%s]", err.Error()) + } + //TODO: subscribe to UDR + } else { + smData = *smPolicyData.SmPolicyData + } + amPolicy := ue.FindAMPolicy(request.AccessType, request.ServingNetwork) + if amPolicy == nil { + rsp := pcf_util.GetProblemDetail("Can't find corresponding AM Policy", pcf_util.POLICY_CONTEXT_DENIED) + logger.SMpolicylog.Warnf("Can't find corresponding AM Policy") + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + // TODO: check service restrict + if ue.Gpsi == "" { + ue.Gpsi = request.Gpsi + } + if ue.Pei == "" { + ue.Pei = request.Pei + } + if smPolicyData != nil { + delete(ue.SmPolicyData, smPolicyId) + } + smPolicyData = ue.NewUeSmPolicyData(smPolicyId, request, &smData) + // Policy Decision + decision := models.SmPolicyDecision{ + SessRules: make(map[string]models.SessionRule), + } + SessRuleId := fmt.Sprintf("SessRuleId-%d", request.PduSessionId) + sessRule := models.SessionRule{ + AuthSessAmbr: request.SubsSessAmbr, + SessRuleId: SessRuleId, + // RefUmData + // RefCondData + } + defQos := request.SubsDefQos + if defQos != nil { + sessRule.AuthDefQos = &models.AuthorizedDefaultQos{ + Var5qi: defQos.Var5qi, + Arp: defQos.Arp, + PriorityLevel: defQos.PriorityLevel, + // AverWindow + // MaxDataBurstVol + } + } + decision.SessRules[SessRuleId] = sessRule + // TODO: See how UDR used + dnnData := pcf_util.GetSMPolicyDnnData(smData, request.SliceInfo, request.Dnn) + if dnnData != nil { + decision.Online = dnnData.Online + decision.Offline = dnnData.Offline + decision.Ipv4Index = dnnData.Ipv4Index + decision.Ipv6Index = dnnData.Ipv6Index + // Set Aggregate GBR if exist + if dnnData.GbrDl != "" { + gbrDL, err := pcf_context.ConvertBitRateToKbps(dnnData.GbrDl) + if err != nil { + logger.SMpolicylog.Warnf(err.Error()) + } else { + smPolicyData.RemainGbrDL = &gbrDL + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate DL GBR[%.2f Kbps]", request.Dnn, gbrDL) + } + } + if dnnData.GbrUl != "" { + gbrUL, err := pcf_context.ConvertBitRateToKbps(dnnData.GbrUl) + if err != nil { + logger.SMpolicylog.Warnf(err.Error()) + } else { + smPolicyData.RemainGbrUL = &gbrUL + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate UL GBR[%.2f Kbps]", request.Dnn, gbrUL) + + } + } + } else { + logger.SMpolicylog.Warnf("Policy Subscription Info: SMPolicyDnnData is null for dnn[%s] in UE[%s]", request.Dnn, ue.Supi) + decision.Online = request.Online + decision.Offline = request.Offline + } + decision.SuppFeat = pcf_util.GetNegotiateSuppFeat(request.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_SMPOLICYCONTROL]) + decision.QosFlowUsage = request.QosFlowUsage + // TODO: Trigger about UMC, ADC, NetLoc,... + decision.PolicyCtrlReqTriggers = pcf_util.PolicyControlReqTrigToArray(0x40780f) + smPolicyData.PolicyDecision = &decision + // TODO: PCC rule, PraInfo ... + locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId) + headers := http.Header{ + "Location": {locationHeader}, + } + logger.SMpolicylog.Tracef("SMPolicy PduSessionId[%d] Create", request.PduSessionId) + pcf_message.SendHttpResponseMessage(httpChannel, headers, 201, decision) +} + +// SmPoliciesSmPolicyIdDeletePost - +func DeleteSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smPolicyId string) { + logger.AMpolicylog.Traceln("Handle SM Policy Delete") + + ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyId) + if ue == nil || ue.SmPolicyData[smPolicyId] == nil { + rsp := pcf_util.GetProblemDetail("smPolicyId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) + logger.SMpolicylog.Warnf(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + + pcfSelf := pcf_context.PCF_Self() + smPolicy := ue.SmPolicyData[smPolicyId] + + // Unsubscrice UDR + delete(ue.SmPolicyData, smPolicyId) + logger.SMpolicylog.Tracef("SMPolicy SmPolicyId[%s] DELETE", smPolicyId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + + // Release related App Session + terminationInfo := models.TerminationInfo{ + TermCause: models.TerminationCause_PDU_SESSION_TERMINATION, + } + for appSessionId := range smPolicy.AppSessions { + if appSession, exist := pcfSelf.AppSessionPool[appSessionId]; exist { + SendAppSessionTermination(appSession, terminationInfo) + delete(pcfSelf.AppSessionPool, appSessionId) + logger.SMpolicylog.Tracef("SMPolicy[%s] DELETE Related AppSession[%s]", smPolicyId, appSessionId) + + } + } + +} + +// SmPoliciesSmPolicyIdGet - +func GetSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smPolicyId string) { + logger.SMpolicylog.Traceln("Handle GET SM Policy Request") + + ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyId) + if ue == nil || ue.SmPolicyData[smPolicyId] == nil { + rsp := pcf_util.GetProblemDetail("smPolicyId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) + logger.SMpolicylog.Warnf(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + smPolicyData := ue.SmPolicyData[smPolicyId] + rsp := models.SmPolicyControl{ + Policy: smPolicyData.PolicyDecision, + Context: smPolicyData.PolicyContext, + } + logger.SMpolicylog.Tracef("SMPolicy SmPolicyId[%s] GET", smPolicyId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) +} + +// SmPoliciesSmPolicyIdUpdatePost - +func UpdateSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smPolicyId string, request models.SmPolicyUpdateContextData) { + + logger.SMpolicylog.Traceln("Handle SM Policy Update") + + ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyId) + if ue == nil || ue.SmPolicyData[smPolicyId] == nil { + rsp := pcf_util.GetProblemDetail("smPolicyId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) + logger.SMpolicylog.Warnf(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + smPolicy := ue.SmPolicyData[smPolicyId] + smPolicyDecision := smPolicy.PolicyDecision + smPolicyContext := smPolicy.PolicyContext + errCause := "" + + // For App Session Notification + afEventsNotification := models.EventsNotification{} + for _, trigger := range request.RepPolicyCtrlReqTriggers { + switch trigger { + case models.PolicyControlRequestTrigger_PLMN_CH: // PLMN Change + if request.ServingNetwork == nil { + errCause = "Serving Network is nil in Trigger PLMN_CH" + break + } + smPolicyContext.ServingNetwork = request.ServingNetwork + afEventsNotification.PlmnId = &models.PlmnId{ + Mcc: request.ServingNetwork.Mcc, + Mnc: request.ServingNetwork.Mnc, + } + afNotif := models.AfEventNotification{ + Event: models.AfEvent_PLMN_CHG, + } + afEventsNotification.EvNotifs = append(afEventsNotification.EvNotifs, afNotif) + + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + case models.PolicyControlRequestTrigger_RES_MO_RE: // UE intiate resource modification to SMF (subsclause 4.2.4.17 in TS29512) + req := request.UeInitResReq + if req == nil { + errCause = "UeInitResReq is nil in Trigger RES_MO_RE" + break + } + switch req.RuleOp { + case models.RuleOperation_CREATE_PCC_RULE: + if req.ReqQos == nil || len(req.PackFiltInfo) < 1 { + errCause = "Parameter Erroneous/Missing in Create Pcc Rule" + break + } + // TODO: Packet Filters are covered by outstanding pcc rule + id := smPolicy.PccRuleIdGenarator + infos := pcf_util.ConvertPacketInfoToFlowInformation(req.PackFiltInfo) + // Set PackFiltId + for i := range infos { + infos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + smPolicy.PackFiltIdGenarator++ + } + pccRule := pcf_util.CreatePccRule(id, req.Precedence, infos, false) + // Add Traffic control Data + tcData := pcf_util.CreateTcData(id, "") + // TODO: ARP use real Data + qosData := pcf_util.CreateQosData(id, int32(req.ReqQos.Var5qi), 15) + // TODO: Set MBR + var err error + // Set GBR + qosData.GbrDl, qosData.GbrUl, err = smPolicy.DecreaseRemainGBR(req.ReqQos) + if err != nil { + rsp := pcf_util.GetProblemDetail(err.Error(), pcf_util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) + logger.SMpolicylog.Warnf(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + if qosData.GbrDl != "" { + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then DL GBR remain[%.2f Kbps]", smPolicyContext.Dnn, qosData.GbrDl, *smPolicy.RemainGbrDL) + } + if qosData.GbrUl != "" { + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then UL GBR remain[%.2f Kbps]", smPolicyContext.Dnn, qosData.GbrUl, *smPolicy.RemainGbrUL) + } + pcf_util.SetPccRuleRelatedData(smPolicyDecision, pccRule, &tcData, &qosData, nil, nil) + // link Packet filters to PccRule + for _, info := range infos { + smPolicy.PackFiltMapToPccRuleId[info.PackFiltId] = pccRule.PccRuleId + } + smPolicy.PccRuleIdGenarator++ + case models.RuleOperation_DELETE_PCC_RULE: + if req.PccRuleId == "" { + errCause = "Parameter Erroneous/Missing in Create Pcc Rule" + break + } + err := smPolicy.RemovePccRule(req.PccRuleId) + if err != nil { + errCause = err.Error() + } + case models.RuleOperation_MODIFY_PCC_RULE_AND_ADD_PACKET_FILTERS, + models.RuleOperation_MODIFY_PCC_RULE_AND_REPLACE_PACKET_FILTERS, + models.RuleOperation_MODIFY_PCC_RULE_AND_DELETE_PACKET_FILTERS, + models.RuleOperation_MODIFY_PCC_RULE_WITHOUT_MODIFY_PACKET_FILTERS: + if req.PccRuleId == "" || (req.RuleOp != models.RuleOperation_MODIFY_PCC_RULE_WITHOUT_MODIFY_PACKET_FILTERS && len(req.PackFiltInfo) < 1) { + errCause = "Parameter Erroneous/Missing in Modify Pcc Rule" + break + } + if rule, exist := smPolicyDecision.PccRules[req.PccRuleId]; exist { + // Modify Qos if included + rule.Precedence = req.Precedence + if req.ReqQos != nil && len(rule.RefQosData) != 0 { + qosId := rule.RefQosData[0] + if qosData, exist := smPolicyDecision.QosDecs[qosId]; exist { + origUl, origDl := smPolicy.IncreaseRemainGBR(qosId) + gbrDl, gbrUl, err := smPolicy.DecreaseRemainGBR(req.ReqQos) + if err != nil { + smPolicy.RemainGbrDL = origDl + smPolicy.RemainGbrUL = origUl + rsp := pcf_util.GetProblemDetail(err.Error(), pcf_util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) + logger.SMpolicylog.Warnf(rsp.Detail) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + qosData.Var5qi = req.ReqQos.Var5qi + qosData.GbrDl = gbrDl + qosData.GbrUl = gbrUl + if qosData.GbrDl != "" { + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then DL GBR remain[%.2f Kbps]", smPolicyContext.Dnn, qosData.GbrDl, *smPolicy.RemainGbrDL) + } + if qosData.GbrUl != "" { + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then UL GBR remain[%.2f Kbps]", smPolicyContext.Dnn, qosData.GbrUl, *smPolicy.RemainGbrUL) + } + smPolicyDecision.QosDecs[qosId] = qosData + } else { + errCause = "Parameter Erroneous/Missing in Modify Pcc Rule" + break + } + } + infos := pcf_util.ConvertPacketInfoToFlowInformation(req.PackFiltInfo) + switch req.RuleOp { + case models.RuleOperation_MODIFY_PCC_RULE_AND_ADD_PACKET_FILTERS: + // Set PackFiltId + for i := range infos { + infos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + smPolicy.PackFiltMapToPccRuleId[infos[i].PackFiltId] = req.PccRuleId + smPolicy.PackFiltIdGenarator++ + } + rule.FlowInfos = append(rule.FlowInfos, infos...) + case models.RuleOperation_MODIFY_PCC_RULE_AND_REPLACE_PACKET_FILTERS: + // Replace all Packet Filters + for _, info := range rule.FlowInfos { + delete(smPolicy.PackFiltMapToPccRuleId, info.PackFiltId) + } + // Set PackFiltId + for i := range infos { + infos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + smPolicy.PackFiltMapToPccRuleId[infos[i].PackFiltId] = req.PccRuleId + smPolicy.PackFiltIdGenarator++ + } + rule.FlowInfos = infos + case models.RuleOperation_MODIFY_PCC_RULE_AND_DELETE_PACKET_FILTERS: + removeId := make(map[string]bool) + for _, info := range infos { + delete(smPolicy.PackFiltMapToPccRuleId, info.PackFiltId) + removeId[info.PackFiltId] = true + } + result := []models.FlowInformation{} + for _, info := range rule.FlowInfos { + if _, exist := removeId[info.PackFiltId]; !exist { + result = append(result, info) + } + } + rule.FlowInfos = result + } + smPolicyDecision.PccRules[req.PccRuleId] = rule + } else { + errCause = fmt.Sprintf("Can't find the pccRuleId[%s] in Session[%d]", req.PccRuleId, smPolicyContext.PduSessionId) + } + + } + + case models.PolicyControlRequestTrigger_AC_TY_CH: // UE Access Type Change (subsclause 4.2.4.8 in TS29512) + if request.AccessType == "" { + errCause = "Access Type is empty in Trigger AC_TY_CH" + break + } + if request.AccessType == models.AccessType__3_GPP_ACCESS && smPolicyContext.Var3gppPsDataOffStatus { + // TODO: Handle Data off Status + // Block Session Service except for Exempt Serice which is described in TS22011, TS 23221 + } + smPolicyContext.AccessType = request.AccessType + afEventsNotification.AccessType = request.AccessType + if request.RatType != "" { + smPolicyContext.RatType = request.RatType + afEventsNotification.RatType = request.RatType + } + afNotif := models.AfEventNotification{ + Event: models.AfEvent_ACCESS_TYPE_CHANGE, + } + afEventsNotification.EvNotifs = append(afEventsNotification.EvNotifs, afNotif) + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + case models.PolicyControlRequestTrigger_UE_IP_CH: // SMF notice PCF "ipv4Address" & ipv6AddressPrefix (always) + // TODO: Decide new Session Rule / Pcc rule + if request.RelIpv4Address == smPolicyContext.Ipv4Address { + smPolicyContext.Ipv4Address = "" + } + if request.RelIpv6AddressPrefix == smPolicyContext.Ipv6AddressPrefix { + smPolicyContext.Ipv6AddressPrefix = "" + } + if request.Ipv4Address != "" { + smPolicyContext.Ipv4Address = request.Ipv4Address + } + if request.Ipv6AddressPrefix != "" { + smPolicyContext.Ipv6AddressPrefix = request.Ipv6AddressPrefix + } + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + case models.PolicyControlRequestTrigger_UE_MAC_CH: // SMF notice PCF when SMF detect new UE MAC + case models.PolicyControlRequestTrigger_AN_CH_COR: // Access Network Charging Correlation Info (subsclause 4.2.6.5.1, 4.2.4.13 in TS29512) + // request.AccNetChIds + case models.PolicyControlRequestTrigger_US_RE: // UMC (subsclause 4.2.4.10, 5.8 in TS29512) + afNotif := models.AfEventNotification{ + Event: models.AfEvent_USAGE_REPORT, + } + afEventsNotification.EvNotifs = append(afEventsNotification.EvNotifs, afNotif) + case models.PolicyControlRequestTrigger_APP_STA: // ADC (subsclause 4.2.4.6, 5.8 in TS29512) + // request.AppDetectionInfos + case models.PolicyControlRequestTrigger_APP_STO: // ADC (subsclause 4.2.4.6, 5.8 in TS29512) + // request.AppDetectionInfos + case models.PolicyControlRequestTrigger_AN_INFO: // NetLoc (subsclause 4.2.4.9, 5.8 in TS29512) + case models.PolicyControlRequestTrigger_CM_SES_FAIL: // Credit Management Session Failure + // request.CreditManageStatus + case models.PolicyControlRequestTrigger_PS_DA_OFF: // 3GPP PS Data Off status changed (subsclause 4.2.4.8, 5.8 in TS29512) (always) + if smPolicyContext.Var3gppPsDataOffStatus != request.Var3gppPsDataOffStatus { + // TODO: Handle Data off Status + if request.Var3gppPsDataOffStatus { + // Block Session Service except for Exempt Serice which is described in TS22011, TS 23221 + } else { + // UnBlock Session Sevice + } + smPolicyContext.Var3gppPsDataOffStatus = request.Var3gppPsDataOffStatus + } + case models.PolicyControlRequestTrigger_DEF_QOS_CH: // Default QoS Change (subsclause 4.2.4.5 in TS29512) (always) + if request.SubsDefQos == nil { + errCause = "SubsDefQos is nil in Trigger DEF_QOS_CH" + break + } + smPolicyContext.SubsDefQos = request.SubsDefQos + sessRuleId := fmt.Sprintf("SessRuleId-%d", smPolicyContext.PduSessionId) + if smPolicyDecision.SessRules[sessRuleId].AuthDefQos == nil { + tmp := smPolicyDecision.SessRules[sessRuleId] + tmp.AuthDefQos = new(models.AuthorizedDefaultQos) + smPolicyDecision.SessRules[sessRuleId] = tmp + } + authQos := smPolicyDecision.SessRules[sessRuleId].AuthDefQos + authQos.Var5qi = request.SubsDefQos.Var5qi + authQos.Arp = request.SubsDefQos.Arp + authQos.PriorityLevel = request.SubsDefQos.PriorityLevel + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + case models.PolicyControlRequestTrigger_SE_AMBR_CH: // Session Ambr Change (subsclause 4.2.4.4 in TS29512) (always) + if request.SubsSessAmbr == nil { + errCause = "SubsSessAmbr is nil in Trigger SE_AMBR_CH" + break + } + smPolicyContext.SubsSessAmbr = request.SubsSessAmbr + sessRuleId := fmt.Sprintf("SessRuleId-%d", smPolicyContext.PduSessionId) + if smPolicyDecision.SessRules[sessRuleId].AuthSessAmbr == nil { + tmp := smPolicyDecision.SessRules[sessRuleId] + tmp.AuthSessAmbr = new(models.Ambr) + smPolicyDecision.SessRules[sessRuleId] = tmp + } + *smPolicyDecision.SessRules[sessRuleId].AuthSessAmbr = *request.SubsSessAmbr + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + case models.PolicyControlRequestTrigger_QOS_NOTIF: // SMF notify PCF when receiving from RAN that QoS can/can't be guaranteed (subsclause 4.2.4.20 in TS29512) (always) + // request.QncReports + afNotif := models.AfEventNotification{ + Event: models.AfEvent_QOS_NOTIF, + } + afEventsNotification.EvNotifs = append(afEventsNotification.EvNotifs, afNotif) + afEventsNotification.QncReports = request.QncReports + case models.PolicyControlRequestTrigger_NO_CREDIT: // Out of Credit + case models.PolicyControlRequestTrigger_PRA_CH: // Presence Reporting (subsclause 4.2.6.5.6, 4.2.4.16, 5.8 in TS29512) + // request.RepPraInfos + case models.PolicyControlRequestTrigger_SAREA_CH: // Change Of Service Area + if request.UserLocationInfo == nil { + errCause = "UserLocationInfo is nil in Trigger SAREA_CH" + break + } + smPolicyContext.UserLocationInfo = request.UserLocationInfo + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + case models.PolicyControlRequestTrigger_SCNN_CH: // Change of Serving Network Function + if request.ServNfId == nil { + errCause = "ServNfId is nil in Trigger SCNN_CH" + break + } + smPolicyContext.ServNfId = request.ServNfId + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + case models.PolicyControlRequestTrigger_RE_TIMEOUT: // Revalidation TimeOut (subsclause 4.2.4.13 in TS29512) + // formatTimeStr := time.Now() + // formatTimeStr = formatTimeStr.Add(time.Second * 60) + // formatTimeStrAdd := formatTimeStr.Format(pcf_context.GetTimeformat()) + // formatTime, err := time.Parse(pcf_context.GetTimeformat(), formatTimeStrAdd) + // if err == nil { + // smPolicyDecision.RevalidationTime = &formatTime + // } + case models.PolicyControlRequestTrigger_RES_RELEASE: // Outcome of request Pcc rule removal (subsclause 4.2.6.5.2, 5.8 in TS29512) + case models.PolicyControlRequestTrigger_SUCC_RES_ALLO: // Successful resource allocation (subsclause 4.2.6.5.5, 4.2.4.14 in TS29512) + afNotif := models.AfEventNotification{ + Event: models.AfEvent_SUCCESSFUL_RESOURCES_ALLOCATION, + } + afEventsNotification.EvNotifs = append(afEventsNotification.EvNotifs, afNotif) + case models.PolicyControlRequestTrigger_RAT_TY_CH: // Change of RatType + if request.RatType == "" { + errCause = "RatType is empty in Trigger RAT_TY_CH" + break + } + smPolicyContext.RatType = request.RatType + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + case models.PolicyControlRequestTrigger_REF_QOS_IND_CH: // Change of reflective Qos Indication from UE + smPolicyContext.RefQosIndication = request.RefQosIndication + // TODO: modify Decision about RefQos in Pcc rule + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + case models.PolicyControlRequestTrigger_NUM_OF_PACKET_FILTER: // Interworking Only (always) + case models.PolicyControlRequestTrigger_UE_STATUS_RESUME: // UE State Resume + // TODO + case models.PolicyControlRequestTrigger_UE_TZ_CH: // UE TimeZome Change + if request.UeTimeZone == "" { + errCause = "Ue TimeZone is empty in Trigger UE_TZ_CH" + break + } + smPolicyContext.UeTimeZone = request.UeTimeZone + logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) + } + } + + var successRules, failRules []models.RuleReport + for _, rule := range request.RuleReports { + if rule.RuleStatus == models.RuleStatus_ACTIVE { + successRules = append(successRules, rule) + } else { + failRules = append(failRules, rule) + // release fail pccRules in SmPolicy + for _, pccRuleId := range rule.PccRuleIds { + if err := smPolicy.RemovePccRule(pccRuleId); err != nil { + logger.SMpolicylog.Warnf("SM Policy Notification about failed installing PccRule[%s]", err.Error()) + } + } + } + } + if len(failRules) > 0 { + afNotif := models.AfEventNotification{ + Event: models.AfEvent_FAILED_RESOURCES_ALLOCATION, + } + afEventsNotification.EvNotifs = append(afEventsNotification.EvNotifs, afNotif) + } + if afEventsNotification.EvNotifs != nil { + sendSmPolicyRelatedAppSessionNotification(smPolicy, afEventsNotification, request.AccuUsageReports, successRules, failRules) + } + + if errCause != "" { + rsp := pcf_util.GetProblemDetail(errCause, pcf_util.ERROR_TRIGGER_EVENT) + logger.SMpolicylog.Warnf(errCause) + pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return + } + logger.SMpolicylog.Tracef("SMPolicy SmPolicyId[%s] Update", smPolicyId) + pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *smPolicyDecision) + +} + +func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyData, notification models.EventsNotification, usageReports []models.AccuUsageReport, successRules, failRules []models.RuleReport) { + + for appSessionId := range smPolicy.AppSessions { + if appSession, exist := pcf_context.PCF_Self().AppSessionPool[appSessionId]; exist { + if len(appSession.Events) == 0 { + continue + } + sessionNotif := models.EventsNotification{} + for _, notif := range notification.EvNotifs { + if _, found := appSession.Events[notif.Event]; found { + switch notif.Event { + case models.AfEvent_ACCESS_TYPE_CHANGE: + sessionNotif.AccessType = notification.AccessType + sessionNotif.RatType = notification.RatType + case models.AfEvent_FAILED_RESOURCES_ALLOCATION: + failItem := models.ResourcesAllocationInfo{ + McResourcStatus: models.MediaComponentResourcesStatus_INACTIVE, + } + flows := make(map[int32]models.Flows) + for _, report := range failRules { + for _, pccRuleId := range report.PccRuleIds { + if key, exist := appSession.PccRuleIdMapToCompId[pccRuleId]; exist { + items := strings.Split(key, "-") + if items[0] != "appId" { + compN, _ := strconv.Atoi(items[0]) + compN32 := int32(compN) + if len(items) == 1 { + // Comp + flow := models.Flows{ + MedCompN: compN32, + } + failItem.Flows = append(failItem.Flows, flow) + } else if len(items) == 2 { + // have subComp + fNum, _ := strconv.Atoi(items[1]) + fNum32 := int32(fNum) + + flow, exist := flows[compN32] + if !exist { + flow = models.Flows{ + MedCompN: compN32, + FNums: []int32{fNum32}, + } + } else { + flow.FNums = append(flow.FNums, fNum32) + } + flows[compN32] = flow + } + } + // Release related resource + delete(appSession.PccRuleIdMapToCompId, pccRuleId) + delete(appSession.RelatedPccRuleIds, key) + } + } + } + for _, flow := range flows { + failItem.Flows = append(failItem.Flows, flow) + } + if failItem.Flows != nil { + sessionNotif.FailedResourcAllocReports = append(sessionNotif.FailedResourcAllocReports, failItem) + } else { + continue + } + case models.AfEvent_PLMN_CHG: + sessionNotif.PlmnId = notification.PlmnId + case models.AfEvent_QOS_NOTIF: + for _, report := range sessionNotif.QncReports { + for _, pccRuleId := range report.RefPccRuleIds { + if _, exist := appSession.PccRuleIdMapToCompId[pccRuleId]; exist { + sessionNotif.QncReports = append(sessionNotif.QncReports, report) + break + } + } + } + if sessionNotif.QncReports == nil { + continue + } + case models.AfEvent_SUCCESSFUL_RESOURCES_ALLOCATION: + // Subscription to resources allocation outcome + if successRules == nil { + continue + } + flows := make(map[int32]models.Flows) + for _, report := range successRules { + for _, pccRuleId := range report.PccRuleIds { + if key, exist := appSession.PccRuleIdMapToCompId[pccRuleId]; exist { + items := strings.Split(key, "-") + if items[0] != "appId" { + compN, _ := strconv.Atoi(items[0]) + compN32 := int32(compN) + if len(items) == 1 { + // Comp + flow := models.Flows{ + MedCompN: compN32, + } + notif.Flows = append(notif.Flows, flow) + } else if len(items) == 2 { + // have subComp + fNum, _ := strconv.Atoi(items[1]) + fNum32 := int32(fNum) + flow, exist := flows[compN32] + if !exist { + flow = models.Flows{ + MedCompN: compN32, + FNums: []int32{fNum32}, + } + } else { + flow.FNums = append(flow.FNums, fNum32) + } + flows[compN32] = flow + } + } + + } + } + } + for _, flow := range flows { + notif.Flows = append(notif.Flows, flow) + } + if notif.Flows == nil { + continue + } + case models.AfEvent_USAGE_REPORT: + for _, report := range usageReports { + for _, pccRuleId := range appSession.RelatedPccRuleIds { + if pccRule, exist := appSession.SmPolicyData.PolicyDecision.PccRules[pccRuleId]; exist { + if pccRule.RefUmData != nil && pccRule.RefUmData[0] == report.RefUmIds { + sessionNotif.UsgRep = &models.AccumulatedUsage{ + Duration: report.TimeUsage, + TotalVolume: report.VolUsage, + UplinkVolume: report.VolUsageUplink, + DownlinkVolume: report.VolUsageDownlink, + } + break + } + } + } + if sessionNotif.UsgRep != nil { + sessionNotif.EvNotifs = append(sessionNotif.EvNotifs, notif) + break + } + } + fallthrough + default: + continue + } + sessionNotif.EvNotifs = append(sessionNotif.EvNotifs, notif) + } + } + if sessionNotif.EvNotifs != nil { + SendAppSessionEventNotification(appSession, sessionNotif) + } + + } + } +} + +func SendSMPolicyUpdateNotification(ue *pcf_context.UeContext, smPolId string, request models.SmPolicyNotification) { + logger.SMpolicylog.Tracef("Send SM Policy Update Notification") + if ue == nil { + logger.SMpolicylog.Warnln("SM Policy Update Notification Error[Ue is nil]") + return + } + smPolicyData := ue.SmPolicyData[smPolId] + if smPolicyData == nil || smPolicyData.PolicyContext == nil { + logger.SMpolicylog.Warnf("SM Policy Update Notification Error[Can't find smPolId[%s] in UE(%s)]", smPolId, ue.Supi) + return + } + client := pcf_util.GetNpcfSMPolicyCallbackClient() + uri := smPolicyData.PolicyContext.NotificationUri + if uri != "" { + _, httpResponse, err := client.DefaultCallbackApi.SmPolicyUpdateNotification(context.Background(), uri, request) + if err != nil { + if httpResponse != nil { + logger.SMpolicylog.Warnf("SM Policy Update Notification Error[%s]", httpResponse.Status) + } else { + logger.SMpolicylog.Warnf("SM Policy Update Notification Failed[%s]", err.Error()) + } + return + } else if httpResponse == nil { + logger.SMpolicylog.Warnln("SM Policy Update Notification Failed[HTTP Response is nil]") + return + } + if httpResponse.StatusCode != http.StatusOK && httpResponse.StatusCode != http.StatusNoContent { + logger.SMpolicylog.Warnf("SM Policy Update Notification Failed") + } else { + logger.SMpolicylog.Tracef("SM Policy Update Notification Success") + } + } + +} + +func SendSMPolicyTerminationRequestNotification(ue *pcf_context.UeContext, smPolId string, request models.TerminationNotification) { + logger.SMpolicylog.Tracef("Send SM Policy Termination Request Notification") + if ue == nil { + logger.SMpolicylog.Warnln("SM Policy Termination Request Notification Error[Ue is nil]") + return + } + smPolicyData := ue.SmPolicyData[smPolId] + if smPolicyData == nil || smPolicyData.PolicyContext == nil { + logger.SMpolicylog.Warnf("SM Policy Update Notification Error[Can't find smPolId[%s] in UE(%s)]", smPolId, ue.Supi) + return + } + client := pcf_util.GetNpcfSMPolicyCallbackClient() + uri := smPolicyData.PolicyContext.NotificationUri + if uri != "" { + rsp, err := client.DefaultCallbackApi.SmPolicyControlTerminationRequestNotification(context.Background(), uri, request) + if err != nil { + if rsp != nil { + logger.AMpolicylog.Warnf("SM Policy Termination Request Notification Error[%s]", rsp.Status) + } else { + logger.AMpolicylog.Warnf("SM Policy Termination Request Notification Error[%s]", err.Error()) + } + return + } else if rsp == nil { + logger.AMpolicylog.Warnln("SM Policy Termination Request Notification Error[HTTP Response is nil]") + return + } + if rsp.StatusCode != http.StatusNoContent { + logger.SMpolicylog.Warnf("SM Policy Termination Request Notification Failed") + } else { + logger.SMpolicylog.Tracef("SM Policy Termination Request Notification Success") + } + } + +} diff --git a/pcf_service/pcf_init.go b/pcf_service/pcf_init.go new file mode 100644 index 0000000..968ebab --- /dev/null +++ b/pcf_service/pcf_init.go @@ -0,0 +1,224 @@ +package pcf_service + +import ( + "bufio" + "fmt" + "github.com/gin-contrib/cors" + "free5gc/lib/Nnrf_NFDiscovery" + "free5gc/lib/http2_util" + "free5gc/lib/openapi/models" + "free5gc/lib/path_util" + "free5gc/src/app" + "free5gc/src/pcf/AMPolicy" + "free5gc/src/pcf/BDTPolicy" + "free5gc/src/pcf/HttpCallback" + "free5gc/src/pcf/OAM" + "free5gc/src/pcf/PolicyAuthorization" + "free5gc/src/pcf/SMPolicy" + "free5gc/src/pcf/UEPolicy" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_consumer" + "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/pcf_handler" + "free5gc/src/pcf/pcf_util" + "os/exec" + "sync" + + "free5gc/src/pcf/factory" + + "github.com/antihax/optional" + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" + "github.com/urfave/cli" +) + +type PCF struct{} + +type ( + // Config information. + Config struct { + pcfcfg string + } +) + +var config Config + +var pcfCLi = []cli.Flag{ + cli.StringFlag{ + Name: "free5gccfg", + Usage: "common config file", + }, + cli.StringFlag{ + Name: "pcfcfg", + Usage: "config file", + }, +} + +var initLog *logrus.Entry + +func init() { + initLog = logger.InitLog +} + +func (*PCF) GetCliCmd() (flags []cli.Flag) { + return pcfCLi +} + +func (*PCF) Initialize(c *cli.Context) { + + config = Config{ + pcfcfg: c.String("pcfcfg"), + } + if config.pcfcfg != "" { + factory.InitConfigFactory(config.pcfcfg) + } else { + DefaultPcfConfigPath := path_util.Gofree5gcPath("free5gc/config/pcfcfg.conf") + factory.InitConfigFactory(DefaultPcfConfigPath) + } + + initLog.Traceln("PCF debug level(string):", app.ContextSelf().Logger.PCF.DebugLevel) + if app.ContextSelf().Logger.PCF.DebugLevel != "" { + initLog.Infoln("PCF debug level(string):", app.ContextSelf().Logger.PCF.DebugLevel) + level, err := logrus.ParseLevel(app.ContextSelf().Logger.PCF.DebugLevel) + if err != nil { + logger.SetLogLevel(level) + } + } + + logger.SetReportCaller(app.ContextSelf().Logger.PCF.ReportCaller) +} + +func (pcf *PCF) FilterCli(c *cli.Context) (args []string) { + for _, flag := range pcf.GetCliCmd() { + name := flag.GetName() + value := fmt.Sprint(c.Generic(name)) + if value == "" { + continue + } + + args = append(args, "--"+name, value) + } + return args +} + +func (pcf *PCF) Start() { + initLog.Infoln("Server started") + router := gin.Default() + + BDTPolicy.AddService(router) + SMPolicy.AddService(router) + AMPolicy.AddService(router) + UEPolicy.AddService(router) + PolicyAuthorization.AddService(router) + Npcf_Callback.AddService(router) + Npcf_OAM.AddService(router) + + router.Use(cors.New(cors.Config{ + AllowMethods: []string{"GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE"}, + AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "User-Agent", "Referrer", "Host", "Token", "X-Requested-With"}, + ExposeHeaders: []string{"Content-Length"}, + AllowCredentials: true, + AllowAllOrigins: true, + MaxAge: 86400, + })) + + self := pcf_context.PCF_Self() + pcf_util.InitpcfContext(self) + + addr := fmt.Sprintf("%s:%d", self.HttpIPv4Address, self.HttpIpv4Port) + + profile, err := pcf_consumer.BuildNFInstance(self) + if err != nil { + initLog.Error("Build PCF Profile Error") + } + _, self.NfId, err = pcf_consumer.SendRegisterNFInstance(self.NrfUri, self.NfId, profile) + if err != nil { + initLog.Errorf("PCF register to NRF Error[%s]", err.Error()) + } + + // subscribe to all Amfs' status change + amfInfos := pcf_consumer.SearchAvailableAMFs(self.NrfUri, models.ServiceName_NAMF_COMM) + for _, amfInfo := range amfInfos { + guamiList := pcf_util.GetNotSubscribedGuamis(amfInfo.GuamiList) + if len(guamiList) == 0 { + continue + } + problemDetails, err := pcf_consumer.AmfStatusChangeSubscribe(amfInfo) + if problemDetails != nil { + logger.InitLog.Warnf("AMF status subscribe Failed[%+v]", problemDetails) + } else if err != nil { + logger.InitLog.Warnf("AMF status subscribe Error[%+v]", err) + } + } + + // TODO: subscribe NRF NFstatus + + go pcf_handler.Handle() + param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ + ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NUDR_DR}), + } + resp, err := pcf_consumer.SendSearchNFInstances(self.NrfUri, models.NfType_UDR, models.NfType_PCF, param) + for _, nfProfile := range resp.NfInstances { + udruri := pcf_util.SearchNFServiceUri(nfProfile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED) + if udruri != "" { + self.DefaultUdrUri = udruri + break + } + } + if err != nil { + initLog.Errorln(err) + } + server, err := http2_util.NewServer(addr, pcf_util.PCF_LOG_PATH, router) + if err == nil && server != nil { + initLog.Infoln(server.ListenAndServeTLS(pcf_util.PCF_PEM_PATH, pcf_util.PCF_KEY_PATH)) + } else { + initLog.Fatalf("Initialize http2 server failed: %+v", err) + } +} + +func (pcf *PCF) Exec(c *cli.Context) error { + initLog.Traceln("args:", c.String("pcfcfg")) + args := pcf.FilterCli(c) + initLog.Traceln("filter: ", args) + command := exec.Command("./pcf", args...) + + stdout, err := command.StdoutPipe() + if err != nil { + initLog.Fatalln(err) + } + wg := sync.WaitGroup{} + wg.Add(4) + go func() { + in := bufio.NewScanner(stdout) + for in.Scan() { + fmt.Println(in.Text()) + } + wg.Done() + }() + + stderr, err := command.StderrPipe() + if err != nil { + initLog.Fatalln(err) + } + go func() { + in := bufio.NewScanner(stderr) + fmt.Println("PCF log start") + for in.Scan() { + fmt.Println(in.Text()) + } + wg.Done() + }() + + go func() { + fmt.Println("PCF start") + if err := command.Start(); err != nil { + fmt.Printf("command.Start() error: %v", err) + } + fmt.Println("PCF end") + wg.Done() + }() + + wg.Wait() + + return err +} diff --git a/pcf_util/convert.go b/pcf_util/convert.go new file mode 100644 index 0000000..bcb00cc --- /dev/null +++ b/pcf_util/convert.go @@ -0,0 +1,63 @@ +package pcf_util + +import ( + "fmt" + "free5gc/lib/openapi/models" +) + +var policyTriggerArray = []models.PolicyControlRequestTrigger{ + models.PolicyControlRequestTrigger_PLMN_CH, + models.PolicyControlRequestTrigger_RES_MO_RE, + models.PolicyControlRequestTrigger_AC_TY_CH, + models.PolicyControlRequestTrigger_UE_IP_CH, + models.PolicyControlRequestTrigger_UE_MAC_CH, + models.PolicyControlRequestTrigger_AN_CH_COR, + models.PolicyControlRequestTrigger_US_RE, + models.PolicyControlRequestTrigger_APP_STA, + models.PolicyControlRequestTrigger_APP_STO, + models.PolicyControlRequestTrigger_AN_INFO, + models.PolicyControlRequestTrigger_CM_SES_FAIL, + models.PolicyControlRequestTrigger_PS_DA_OFF, + models.PolicyControlRequestTrigger_DEF_QOS_CH, + models.PolicyControlRequestTrigger_SE_AMBR_CH, + models.PolicyControlRequestTrigger_QOS_NOTIF, + models.PolicyControlRequestTrigger_NO_CREDIT, + models.PolicyControlRequestTrigger_PRA_CH, + models.PolicyControlRequestTrigger_SAREA_CH, + models.PolicyControlRequestTrigger_SCNN_CH, + models.PolicyControlRequestTrigger_RE_TIMEOUT, + models.PolicyControlRequestTrigger_RES_RELEASE, + models.PolicyControlRequestTrigger_SUCC_RES_ALLO, + models.PolicyControlRequestTrigger_RAT_TY_CH, + models.PolicyControlRequestTrigger_REF_QOS_IND_CH, + models.PolicyControlRequestTrigger_NUM_OF_PACKET_FILTER, + models.PolicyControlRequestTrigger_UE_STATUS_RESUME, + models.PolicyControlRequestTrigger_UE_TZ_CH, +} + +// func GetSMPolicyKey(snssai *models.Snssai, dnn string) string { +// if snssai == nil || len(snssai.Sd) != 6 || dnn == "" { +// return "" +// } +// return fmt.Sprintf("%02x%s-%s", snssai.Sst, snssai.Sd, dnn) +// } + +// Convert Snssai form models to hexString(sst(2)+sd(6)) +func SnssaiModelsToHex(snssai models.Snssai) string { + sst := fmt.Sprintf("%02x", snssai.Sst) + return sst + snssai.Sd +} + +// Use BitMap to generate requested policy control triggers, 1 means yes, 0 means no, see subscaulse 5.6.3.6-1 in TS29512 +func PolicyControlReqTrigToArray(bitMap uint64) (trigger []models.PolicyControlRequestTrigger) { + cnt := 0 + size := len(policyTriggerArray) + for bitMap > 0 && cnt < size { + if (bitMap & 0x01) > 0 { + trigger = append(trigger, policyTriggerArray[cnt]) + } + bitMap >>= 1 + cnt++ + } + return +} diff --git a/pcf_util/initContext.go b/pcf_util/initContext.go new file mode 100644 index 0000000..d2e1368 --- /dev/null +++ b/pcf_util/initContext.go @@ -0,0 +1,48 @@ +package pcf_util + +import ( + "encoding/hex" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/factory" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/pcf_context" + + "github.com/google/uuid" +) + +// Init PCF Context from config flie +func InitpcfContext(context *pcf_context.PCFContext) { + config := factory.PcfConfig + logger.UtilLog.Infof("pcfconfig Info: Version[%s] Description[%s]", config.Info.Version, config.Info.Description) + configuration := config.Configuration + context.NfId = uuid.New().String() + if configuration.PcfName != "" { + context.Name = configuration.PcfName + } + sbi := configuration.Sbi + context.NrfUri = configuration.NrfUri + context.UriScheme = models.UriScheme(sbi.Scheme) + context.HttpIPv4Address = "127.0.0.1" // default localhost + context.HttpIpv4Port = 29507 // default port + if sbi != nil { + if sbi.IPv4Addr != "" { + context.HttpIPv4Address = sbi.IPv4Addr + } + if sbi.Port != 0 { + context.HttpIpv4Port = sbi.Port + } + if sbi.Scheme == "https" { + context.UriScheme = models.UriScheme_HTTPS + } else { + context.UriScheme = models.UriScheme_HTTP + } + } + serviceList := configuration.ServiceList + context.InitNFService(serviceList, config.Info.Version) + context.TimeFormat = configuration.TimeFormat + context.DefaultBdtRefId = configuration.DefaultBdtRefId + for _, service := range context.NfService { + context.PcfServiceUris[service.ServiceName] = service.ApiPrefix + "/" + string(service.ServiceName) + "/" + (*service.Versions)[0].ApiVersionInUri + context.PcfSuppFeats[service.ServiceName], _ = hex.DecodeString(service.SupportedFeatures) + } +} diff --git a/pcf_util/pcc_rule.go b/pcf_util/pcc_rule.go new file mode 100644 index 0000000..90787a2 --- /dev/null +++ b/pcf_util/pcc_rule.go @@ -0,0 +1,217 @@ +package pcf_util + +import ( + "fmt" + "free5gc/lib/openapi/models" + "time" + // "free5gc/lib/path_util" + // "free5gc/src/pcf/factory" +) + +var MediaTypeTo5qiMap = map[models.MediaType]int32{ + models.MediaType_AUDIO: 1, + models.MediaType_VIDEO: 2, + models.MediaType_APPLICATION: 2, + models.MediaType_DATA: 9, + models.MediaType_CONTROL: 9, + models.MediaType_TEXT: 9, + models.MediaType_MESSAGE: 9, + models.MediaType_OTHER: 9, +} + +// Create default pcc rule in PCF, +// TODO: use config file to pass default pcc rule +func CreateDefalutPccRules(id int32) *models.PccRule { + flowInfo := []models.FlowInformation{ + { + FlowDescription: "permit out ip from any to assigned", + FlowDirection: models.FlowDirectionRm_DOWNLINK, + PacketFilterUsage: true, + PackFiltId: "PackFiltId-0", + }, + { + FlowDescription: "permit out ip from any to assigned", + FlowDirection: models.FlowDirectionRm_DOWNLINK, + PacketFilterUsage: true, + PackFiltId: "PackFiltId-1", + }, + } + return CreatePccRule(id, 10, flowInfo, true) +} + +// Get pcc rule Identity(PccRuleId-%d) +func GetPccRuleId(id int32) string { + return fmt.Sprintf("PccRuleId-%d", id) +} + +// Get qos Identity(QosId-%d) +func GetQosId(id int32) string { + return fmt.Sprintf("QosId-%d", id) +} + +// Get Cond Identity(CondId-%d) +func GetCondId(id int32) string { + return fmt.Sprintf("CondId-%d", id) +} + +// Get Traffic Control Identity(TcId-%d) +func GetTcId(id int32) string { + return fmt.Sprintf("TcId-%d", id) +} + +// Get Charging Identity(ChgId-%d) +func GetChgId(id int32) string { + return fmt.Sprintf("ChgId-%d", id) +} + +// Get Charging Identity(ChgId-%d) +func GetUmId(sponId, aspId string) string { + return fmt.Sprintf("umId-%s-%s", sponId, aspId) +} + +// Get Packet Filter Identity(PackFiltId-%d) +func GetPackFiltId(id int32) string { + return fmt.Sprintf("PackFiltId-%d", id) +} + +// Create Pcc Rule with param id, precedence, flow infomation, cond flag(included or not) +func CreatePccRule(id, precedence int32, flowInfo []models.FlowInformation, cond bool) *models.PccRule { + rule := models.PccRule{ + FlowInfos: flowInfo, + PccRuleId: GetPccRuleId(id), + Precedence: precedence, + RefQosData: []string{ + GetQosId(id), + }, + RefTcData: []string{ + GetTcId(id), + }, + } + if cond { + rule.RefCondData = GetCondId(id) + } + return &rule +} + +func CreateCondData(id int32) models.ConditionData { + activationTime := time.Now() + return models.ConditionData{ + CondId: GetCondId(id), + ActivationTime: &activationTime, + } +} + +func CreateQosData(id, var5qi, arp int32) models.QosData { + return models.QosData{ + QosId: GetQosId(id), + Var5qi: var5qi, + Arp: &models.Arp{ + PriorityLevel: arp, + }, + } +} + +func CreateTcData(id int32, flowStatus models.FlowStatus) models.TrafficControlData { + if flowStatus == "" { + flowStatus = models.FlowStatus_ENABLED + } + return models.TrafficControlData{ + TcId: GetTcId(id), + FlowStatus: flowStatus, + } +} + +func CreateUmData(umId string, thresh models.UsageThreshold) models.UsageMonitoringData { + return models.UsageMonitoringData{ + UmId: umId, + VolumeThreshold: thresh.TotalVolume, + VolumeThresholdUplink: thresh.UplinkVolume, + VolumeThresholdDownlink: thresh.DownlinkVolume, + TimeThreshold: thresh.Duration, + } +} + +// Convert Packet Filter information list to Flow Information List(Packet Filter Usage always true), +// EthDescription is Not Supported +func ConvertPacketInfoToFlowInformation(infos []models.PacketFilterInfo) (flowInfos []models.FlowInformation) { + for _, info := range infos { + flowInfo := models.FlowInformation{ + FlowDescription: info.PackFiltCont, + PackFiltId: info.PackFiltId, + PacketFilterUsage: true, + TosTrafficClass: info.TosTrafficClass, + Spi: info.Spi, + FlowLabel: info.FlowLabel, + FlowDirection: models.FlowDirectionRm(info.FlowDirection), + } + flowInfos = append(flowInfos, flowInfo) + } + return +} + +func GetPccRuleByAfAppId(pccRules map[string]models.PccRule, afAppId string) (result *models.PccRule) { + for _, pccRule := range pccRules { + if pccRule.AppId == afAppId { + result = &pccRule + return + } + } + return +} + +func GetPccRuleByFlowInfos(pccRules map[string]models.PccRule, flowInfos []models.FlowInformation) (result *models.PccRule) { + found := false + set := make(map[string]models.FlowInformation) + + for _, flowInfo := range flowInfos { + set[flowInfo.FlowDescription] = flowInfo + } + + for _, pccRule := range pccRules { + found = true + for _, flowInfo := range pccRule.FlowInfos { + if _, exists := set[flowInfo.FlowDescription]; !exists { + found = false + break + } + } + if found { + result = &pccRule + return + } + } + return +} + +func SetPccRuleRelatedData(decicion *models.SmPolicyDecision, pccRule *models.PccRule, tcData *models.TrafficControlData, qosData *models.QosData, chgData *models.ChargingData, umData *models.UsageMonitoringData) { + if tcData != nil { + if decicion.TraffContDecs == nil { + decicion.TraffContDecs = make(map[string]models.TrafficControlData) + } + decicion.TraffContDecs[tcData.TcId] = *tcData + } + if qosData != nil { + if decicion.QosDecs == nil { + decicion.QosDecs = make(map[string]models.QosData) + } + decicion.QosDecs[qosData.QosId] = *qosData + } + if chgData != nil { + if decicion.ChgDecs == nil { + decicion.ChgDecs = make(map[string]models.ChargingData) + } + decicion.ChgDecs[chgData.ChgId] = *chgData + } + if umData != nil { + if decicion.UmDecs == nil { + decicion.UmDecs = make(map[string]models.UsageMonitoringData) + } + decicion.UmDecs[umData.UmId] = *umData + } + if pccRule != nil { + if decicion.PccRules == nil { + decicion.PccRules = make(map[string]models.PccRule) + } + decicion.PccRules[pccRule.PccRuleId] = *pccRule + } +} diff --git a/pcf_util/pcf_util.go b/pcf_util/pcf_util.go new file mode 100644 index 0000000..9a7bdd2 --- /dev/null +++ b/pcf_util/pcf_util.go @@ -0,0 +1,250 @@ +package pcf_util + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "free5gc/lib/Namf_Communication" + "free5gc/lib/Npcf_AMPolicy" + "free5gc/lib/Npcf_PolicyAuthorization" + "free5gc/lib/Npcf_SMPolicyControl" + "free5gc/lib/Nudr_DataRepository" + "free5gc/lib/openapi/models" + "free5gc/lib/path_util" + "free5gc/src/pcf/pcf_context" + "net/http" + "reflect" + "time" +) + +const TimeFormat = time.RFC3339 + +// Path of HTTP2 key and log file +var ( + PCF_LOG_PATH = path_util.Gofree5gcPath("free5gc/pcfsslkey.log") + PCF_PEM_PATH = path_util.Gofree5gcPath("free5gc/support/TLS/pcf.pem") + PCF_KEY_PATH = path_util.Gofree5gcPath("free5gc/support/TLS/pcf.key") + PCF_CONFIG_PATH = path_util.Gofree5gcPath("free5gc/config/pcfcfg.conf") + PCF_BASIC_PATH = "https://localhost:29507" + ERROR_REQUEST_PARAMETERS = "ERROR_REQUEST_PARAMETERS" + USER_UNKNOWN = "USER_UNKNOWN" + CONTEXT_NOT_FOUND = "CONTEXT_NOT_FOUND" + ERROR_INITIAL_PARAMETERS = "ERROR_INITIAL_PARAMETERS" + POLICY_CONTEXT_DENIED = "POLICY_CONTEXT_DENIED" + ERROR_TRIGGER_EVENT = "ERROR_TRIGGER_EVENT" + ERROR_TRAFFIC_MAPPING_INFO_REJECTED = "ERROR_TRAFFIC_MAPPING_INFO_REJECTED" + BDT_POLICY_NOT_FOUND = "BDT_POLICY_NOT_FOUND" + REQUESTED_SERVICE_NOT_AUTHORIZED = "REQUESTED_SERVICE_NOT_AUTHORIZED" + REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED = "REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED" //NWDAF + UNAUTHORIZED_SPONSORED_DATA_CONNECTIVITY = "UNAUTHORIZED_SPONSORED_DATA_CONNECTIVITY" + PDU_SESSION_NOT_AVAILABLE = "PDU_SESSION_NOT_AVAILABLE" + APPLICATION_SESSION_CONTEXT_NOT_FOUND = "APPLICATION_SESSION_CONTEXT_NOT_FOUND" + PcpErrHttpStatusMap = map[string]int32{ + ERROR_REQUEST_PARAMETERS: http.StatusBadRequest, + USER_UNKNOWN: http.StatusBadRequest, + ERROR_INITIAL_PARAMETERS: http.StatusBadRequest, + ERROR_TRIGGER_EVENT: http.StatusBadRequest, + POLICY_CONTEXT_DENIED: http.StatusForbidden, + ERROR_TRAFFIC_MAPPING_INFO_REJECTED: http.StatusForbidden, + REQUESTED_SERVICE_NOT_AUTHORIZED: http.StatusForbidden, + REQUESTED_SERVICE_TEMPORARILY_NOT_AUTHORIZED: http.StatusForbidden, + UNAUTHORIZED_SPONSORED_DATA_CONNECTIVITY: http.StatusForbidden, + CONTEXT_NOT_FOUND: http.StatusNotFound, + BDT_POLICY_NOT_FOUND: http.StatusNotFound, + APPLICATION_SESSION_CONTEXT_NOT_FOUND: http.StatusNotFound, + PDU_SESSION_NOT_AVAILABLE: http.StatusInternalServerError, + } +) + +func GetNpcfAMPolicyCallbackClient() *Npcf_AMPolicy.APIClient { + configuration := Npcf_AMPolicy.NewConfiguration() + client := Npcf_AMPolicy.NewAPIClient(configuration) + return client +} + +func GetNpcfSMPolicyCallbackClient() *Npcf_SMPolicyControl.APIClient { + configuration := Npcf_SMPolicyControl.NewConfiguration() + client := Npcf_SMPolicyControl.NewAPIClient(configuration) + return client +} + +func GetNpcfPolicyAuthorizationCallbackClient() *Npcf_PolicyAuthorization.APIClient { + configuration := Npcf_PolicyAuthorization.NewConfiguration() + client := Npcf_PolicyAuthorization.NewAPIClient(configuration) + return client +} + +func GetNudrClient(uri string) *Nudr_DataRepository.APIClient { + configuration := Nudr_DataRepository.NewConfiguration() + configuration.SetBasePath(uri) + client := Nudr_DataRepository.NewAPIClient(configuration) + return client +} +func GetNamfClient(uri string) *Namf_Communication.APIClient { + configuration := Namf_Communication.NewConfiguration() + configuration.SetBasePath(uri) + client := Namf_Communication.NewAPIClient(configuration) + return client +} + +func GetDefaultDataRate() models.UsageThreshold { + var usageThreshold models.UsageThreshold + usageThreshold.DownlinkVolume = 1024 * 1024 / 8 // 1 Mbps + usageThreshold.UplinkVolume = 1024 * 1024 / 8 // 1 Mbps + return usageThreshold +} + +func GetDefaultTime() models.TimeWindow { + var timeWindow models.TimeWindow + timeWindow.StartTime = time.Now().Format(time.RFC3339) + lease, _ := time.ParseDuration("720h") + timeWindow.StopTime = time.Now().Add(lease).Format(time.RFC3339) + return timeWindow +} + +func CheckStopTime(StopTime time.Time) bool { + if StopTime.Before(time.Now()) { + return false + } else { + return true + } +} + +// Convert int data rate bytes to string data rate bits +func Convert(bytes int64) (DateRate string) { + BitDateRate := float64(bytes) * 8 + if BitDateRate/1024 > 0 && BitDateRate/1024/1024 < 0 { + DateRate = fmt.Sprintf("%.2f", BitDateRate/1024) + " Kbps" + } else if BitDateRate/1024/1024 > 0 { + DateRate = fmt.Sprintf("%.2f", BitDateRate/1024/1024) + " Mbps" + } else { + DateRate = fmt.Sprintf("%.2f", BitDateRate) + " bps" + } + return DateRate +} + +// Return ProblemDatail, errString represent Detail, cause represent Cause of the fields +func GetProblemDetail(errString, cause string) models.ProblemDetails { + return models.ProblemDetails{ + Status: PcpErrHttpStatusMap[cause], + Detail: errString, + Cause: cause, + } +} + +// GetSMPolicyDnnData returns SMPolicyDnnData derived from SmPolicy data which snssai and dnn match +func GetSMPolicyDnnData(data models.SmPolicyData, snssai *models.Snssai, dnn string) (result *models.SmPolicyDnnData) { + if snssai == nil || dnn == "" || data.SmPolicySnssaiData == nil { + return + } + snssaiString := SnssaiModelsToHex(*snssai) + if snssaiData, exist := data.SmPolicySnssaiData[snssaiString]; exist { + if snssaiData.SmPolicyDnnData == nil { + return + } + if dnnInfo, exist := snssaiData.SmPolicyDnnData[dnn]; exist { + result = &dnnInfo + return + } + } + return + +} + +// MarshToJsonString returns value which can put into NewInterface() +func MarshToJsonString(v interface{}) (result []string) { + types := reflect.TypeOf(v) + val := reflect.ValueOf(v) + if types.Kind() == reflect.Slice { + for i := 0; i < val.Len(); i++ { + tmp, _ := json.Marshal(val.Index(i).Interface()) + result = append(result, string(tmp)) + + } + } else { + tmp, _ := json.Marshal(v) + result = append(result, string(tmp)) + } + return +} + +// do AND on two byte array +func AndBytes(bytes1, bytes2 []byte) []byte { + if bytes1 != nil && len(bytes1) == len(bytes2) { + bytes3 := []byte{} + for i, b := range bytes1 { + bytes3 = append(bytes3, b&bytes2[i]) + } + return bytes3 + } + return nil +} + +// Negotiate Support Feture with PCF +func GetNegotiateSuppFeat(suppFeat string, serviceSuppFeat []byte) string { + if serviceSuppFeat == nil { + return "" + } + bytes, _ := hex.DecodeString(suppFeat) + negoSuppFeat := AndBytes(bytes, serviceSuppFeat) + return hex.EncodeToString(negoSuppFeat) +} + +var serviceUriMap = map[models.ServiceName]string{ + models.ServiceName_NPCF_AM_POLICY_CONTROL: "policies", + models.ServiceName_NPCF_SMPOLICYCONTROL: "sm-policies", + models.ServiceName_NPCF_BDTPOLICYCONTROL: "bdtpolicies", + models.ServiceName_NPCF_POLICYAUTHORIZATION: "app-sessions", +} + +// Get Resource Uri (location Header) with param id string +func GetResourceUri(name models.ServiceName, id string) string { + return fmt.Sprintf("%s/%s/%s", pcf_context.GetUri(name), serviceUriMap[name], id) +} + +// Check if Feature is Supported or not +func CheckSuppFeat(suppFeat string, number int) bool { + bytes, err := hex.DecodeString(suppFeat) + if err != nil || len(bytes) < 1 { + return false + } + index := len(bytes) - ((number - 1) / 8) - 1 + shift := uint8((number - 1) % 8) + if index < 0 { + return false + } + if bytes[index]&(0x01< 0 { + return true + } + return false +} + +func CheckPolicyControlReqTrig(triggers []models.PolicyControlRequestTrigger, reqTrigger models.PolicyControlRequestTrigger) bool { + for _, trigger := range triggers { + if trigger == reqTrigger { + return true + } + } + return false +} + +func GetNotSubscribedGuamis(guamisIn []models.Guami) (guamisOut []models.Guami) { + for _, guami := range guamisIn { + if !guamiInSubscriptionData(guami) { + guamisOut = append(guamisOut, guami) + } + } + return +} + +func guamiInSubscriptionData(guami models.Guami) bool { + pcfSelf := pcf_context.PCF_Self() + for _, subscriptionData := range pcfSelf.AMFStatusSubsData { + for _, sGuami := range subscriptionData.GuamiList { + if reflect.DeepEqual(sGuami, guami) { + return true + } + } + } + return false +} diff --git a/pcf_util/search_nfService.go b/pcf_util/search_nfService.go new file mode 100644 index 0000000..442a11e --- /dev/null +++ b/pcf_util/search_nfService.go @@ -0,0 +1,50 @@ +package pcf_util + +import ( + "fmt" + "free5gc/lib/openapi/models" +) + +// SearchNFServiceUri returns NF Uri derived from NfProfile with corresponding service +func SearchNFServiceUri(nfProfile models.NfProfile, serviceName models.ServiceName, nfServiceStatus models.NfServiceStatus) (nfUri string) { + + if nfProfile.NfServices != nil { + for _, service := range *nfProfile.NfServices { + if service.ServiceName == serviceName && service.NfServiceStatus == nfServiceStatus { + if nfProfile.Fqdn != "" { + nfUri = nfProfile.Fqdn + } else if service.Fqdn != "" { + nfUri = service.Fqdn + } else if service.ApiPrefix != "" { + nfUri = service.ApiPrefix + } else if service.IpEndPoints != nil { + point := (*service.IpEndPoints)[0] + if point.Ipv4Address != "" { + nfUri = getSbiUri(service.Scheme, point.Ipv4Address, point.Port) + } else if len(nfProfile.Ipv4Addresses) != 0 { + nfUri = getSbiUri(service.Scheme, nfProfile.Ipv4Addresses[0], point.Port) + } + } + } + if nfUri != "" { + break + } + } + } + + return +} + +func getSbiUri(scheme models.UriScheme, ipv4Address string, port int32) (uri string) { + if port != 0 { + uri = fmt.Sprintf("%s://%s:%d", scheme, ipv4Address, port) + } else { + switch scheme { + case models.UriScheme_HTTP: + uri = fmt.Sprintf("%s://%s:80", scheme, ipv4Address) + case models.UriScheme_HTTPS: + uri = fmt.Sprintf("%s://%s:443", scheme, ipv4Address) + } + } + return +} diff --git a/version/version.go b/version/version.go new file mode 100644 index 0000000..f89f034 --- /dev/null +++ b/version/version.go @@ -0,0 +1,7 @@ +package version + +var VERSION = "2020-03-31-01" + +func GetVersion() (version string) { + return VERSION +} From 29a577f07605c8e813cdef634a5f9bfd5c023866 Mon Sep 17 00:00:00 2001 From: free5gc-org Date: Sun, 24 May 2020 21:45:27 +0000 Subject: [PATCH 2/7] v2020-05-25-01 --- {AMPolicy => ampolicy}/api_default.go | 28 +-- {AMPolicy => ampolicy}/api_default_test.go | 32 +-- {AMPolicy => ampolicy}/routers.go | 2 +- .../api_bdt_policies_collection_routers.go | 8 +- ...pi_bdt_policies_collection_routers_test.go | 35 +-- ..._individual_bdt_policy_document_routers.go | 12 +- ...vidual_bdt_policy_document_routers_test.go | 7 +- {BDTPolicy => bdtpolicy}/routers.go | 2 +- .../communication.go | 14 +- .../nf_discovery.go | 19 +- .../nf_management.go | 6 +- .../nf_management_test.go | 12 +- {pcf_context => context}/context.go | 2 +- {pcf_context => context}/ue.go | 2 +- .../{config_configuration.go => config.go} | 19 ++ factory/config_config.go | 11 - factory/config_info.go | 11 - factory/config_sbi.go | 12 - {pcf_handler => handler}/handler.go | 48 ++-- {pcf_handler => handler}/handler_test.go | 2 +- .../message}/channel.go | 2 +- .../pcf_message => handler/message}/event.go | 2 +- .../message}/message.go | 2 +- .../amf_status_change_notify.go | 10 +- {HttpCallback => httpcallback}/router.go | 2 +- .../sm_policy_notify.go | 8 +- logger/logger.go | 15 +- {OAM => oam}/api_get_am_policy.go | 8 +- {OAM => oam}/routers.go | 2 +- pcf.go | 4 +- .../api_application_sessions_collection.go | 14 +- ...pi_application_sessions_collection_test.go | 29 +-- .../api_events_subscription_document.go | 18 +- .../api_events_subscription_document_test.go | 10 +- ...al_application_session_context_document.go | 16 +- ...plication_session_context_document_test.go | 19 +- .../routers.go | 2 +- .../pcf_ampolicy.go => producer/ampolicy.go | 78 +++---- .../pcf_bdtpolicy.go => producer/bdtpolicy.go | 55 ++--- {pcf_producer => producer}/callback.go | 6 +- .../handle_sm_policy_notify.go | 20 +- {pcf_producer => producer}/oam.go | 12 +- .../policyauthorization.go | 212 +++++++++--------- .../pcf_smpolicy.go => producer/smpolicy.go | 98 ++++---- pcf_service/pcf_init.go => service/init.go | 87 ++++--- {SMPolicy => smpolicy}/api_default.go | 26 +-- {SMPolicy => smpolicy}/api_default_test.go | 34 +-- {SMPolicy => smpolicy}/routers.go | 2 +- {UEPolicy => uepolicy}/api_default.go | 2 +- {UEPolicy => uepolicy}/routers.go | 2 +- {pcf_util => util}/convert.go | 2 +- .../initContext.go => util/init_context.go | 6 +- {pcf_util => util}/pcc_rule.go | 2 +- {pcf_util => util}/pcf_util.go | 18 +- .../search_nf_service.go | 2 +- 55 files changed, 564 insertions(+), 547 deletions(-) rename {AMPolicy => ampolicy}/api_default.go (71%) rename {AMPolicy => ampolicy}/api_default_test.go (94%) rename {AMPolicy => ampolicy}/routers.go (99%) rename {BDTPolicy => bdtpolicy}/api_bdt_policies_collection_routers.go (82%) rename {BDTPolicy => bdtpolicy}/api_bdt_policies_collection_routers_test.go (86%) rename {BDTPolicy => bdtpolicy}/api_individual_bdt_policy_document_routers.go (79%) rename {BDTPolicy => bdtpolicy}/api_individual_bdt_policy_document_routers_test.go (97%) rename {BDTPolicy => bdtpolicy}/routers.go (99%) rename pcf_consumer/Communication.go => consumer/communication.go (80%) rename pcf_consumer/NFDiscovery.go => consumer/nf_discovery.go (85%) rename pcf_consumer/NFManagement.go => consumer/nf_management.go (95%) rename pcf_consumer/NFManagement_test.go => consumer/nf_management_test.go (79%) rename {pcf_context => context}/context.go (99%) rename {pcf_context => context}/ue.go (99%) rename factory/{config_configuration.go => config.go} (54%) delete mode 100644 factory/config_config.go delete mode 100644 factory/config_info.go delete mode 100644 factory/config_sbi.go rename {pcf_handler => handler}/handler.go (76%) rename {pcf_handler => handler}/handler_test.go (97%) rename {pcf_handler/pcf_message => handler/message}/channel.go (93%) rename {pcf_handler/pcf_message => handler/message}/event.go (98%) rename {pcf_handler/pcf_message => handler/message}/message.go (99%) rename HttpCallback/AMFStatusChangeNotify.go => httpcallback/amf_status_change_notify.go (79%) rename {HttpCallback => httpcallback}/router.go (98%) rename HttpCallback/SMPolicyNotify.go => httpcallback/sm_policy_notify.go (77%) rename {OAM => oam}/api_get_am_policy.go (81%) rename {OAM => oam}/routers.go (98%) rename {PolicyAuthorization => policyauthorization}/api_application_sessions_collection.go (72%) rename {PolicyAuthorization => policyauthorization}/api_application_sessions_collection_test.go (94%) rename {PolicyAuthorization => policyauthorization}/api_events_subscription_document.go (71%) rename {PolicyAuthorization => policyauthorization}/api_events_subscription_document_test.go (96%) rename {PolicyAuthorization => policyauthorization}/api_individual_application_session_context_document.go (78%) rename {PolicyAuthorization => policyauthorization}/api_individual_application_session_context_document_test.go (97%) rename {PolicyAuthorization => policyauthorization}/routers.go (98%) rename pcf_producer/pcf_ampolicy.go => producer/ampolicy.go (73%) rename pcf_producer/pcf_bdtpolicy.go => producer/bdtpolicy.go (71%) rename {pcf_producer => producer}/callback.go (55%) rename pcf_producer/HandleSmPolicyNotify.go => producer/handle_sm_policy_notify.go (82%) rename {pcf_producer => producer}/oam.go (77%) rename pcf_producer/pcf_policyauthorization.go => producer/policyauthorization.go (83%) rename pcf_producer/pcf_smpolicy.go => producer/smpolicy.go (87%) rename pcf_service/pcf_init.go => service/init.go (69%) rename {SMPolicy => smpolicy}/api_default.go (72%) rename {SMPolicy => smpolicy}/api_default_test.go (97%) rename {SMPolicy => smpolicy}/routers.go (99%) rename {UEPolicy => uepolicy}/api_default.go (96%) rename {UEPolicy => uepolicy}/routers.go (98%) rename {pcf_util => util}/convert.go (99%) rename pcf_util/initContext.go => util/init_context.go (93%) rename {pcf_util => util}/pcc_rule.go (99%) rename {pcf_util => util}/pcf_util.go (95%) rename pcf_util/search_nfService.go => util/search_nf_service.go (98%) diff --git a/AMPolicy/api_default.go b/ampolicy/api_default.go similarity index 71% rename from AMPolicy/api_default.go rename to ampolicy/api_default.go index 095d0d4..93c5b8f 100644 --- a/AMPolicy/api_default.go +++ b/ampolicy/api_default.go @@ -7,14 +7,14 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package AMPolicy +package ampolicy import ( "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_handler/pcf_message" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/handler/message" + "free5gc/src/pcf/util" "github.com/gin-gonic/gin" ) @@ -22,9 +22,9 @@ import ( func PoliciesPolAssoIdDelete(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["polAssoId"], _ = c.Params.Get("polAssoId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMPolicyDelete, req) + channelMsg := message.NewHttpChannelMessage(message.EventAMPolicyDelete, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse c.JSON(HTTPResponse.Status, HTTPResponse.Body) @@ -34,9 +34,9 @@ func PoliciesPolAssoIdDelete(c *gin.Context) { func PoliciesPolAssoIdGet(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["polAssoId"], _ = c.Params.Get("polAssoId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMPolicyGet, req) + channelMsg := message.NewHttpChannelMessage(message.EventAMPolicyGet, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse c.JSON(HTTPResponse.Status, HTTPResponse.Body) @@ -48,16 +48,16 @@ func PoliciesPolAssoIdUpdatePost(c *gin.Context) { var policyAssociationUpdateRequest models.PolicyAssociationUpdateRequest err := c.ShouldBindJSON(&policyAssociationUpdateRequest) if err != nil { - rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_REQUEST_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return } req := http_wrapper.NewRequest(c.Request, policyAssociationUpdateRequest) req.Params["polAssoId"], _ = c.Params.Get("polAssoId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMPolicyUpdate, req) + channelMsg := message.NewHttpChannelMessage(message.EventAMPolicyUpdate, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse c.JSON(HTTPResponse.Status, HTTPResponse.Body) @@ -68,21 +68,21 @@ func PoliciesPost(c *gin.Context) { var policyAssociationRequest models.PolicyAssociationRequest err := c.ShouldBindJSON(&policyAssociationRequest) if err != nil { - rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_REQUEST_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return } if policyAssociationRequest.Supi == "" || policyAssociationRequest.NotificationUri == "" { - rsp := pcf_util.GetProblemDetail("Miss Mandotory IE", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("Miss Mandotory IE", util.ERROR_REQUEST_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return } req := http_wrapper.NewRequest(c.Request, policyAssociationRequest) - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMPolicyCreate, req) + channelMsg := message.NewHttpChannelMessage(message.EventAMPolicyCreate, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse for key, val := range HTTPResponse.Header { diff --git a/AMPolicy/api_default_test.go b/ampolicy/api_default_test.go similarity index 94% rename from AMPolicy/api_default_test.go rename to ampolicy/api_default_test.go index 6a30f7d..1df4827 100644 --- a/AMPolicy/api_default_test.go +++ b/ampolicy/api_default_test.go @@ -1,32 +1,32 @@ -package AMPolicy_test +package ampolicy_test import ( "context" "encoding/json" "flag" "fmt" - "github.com/gin-gonic/gin" - "go.mongodb.org/mongo-driver/bson" "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" "free5gc/lib/MongoDBLibrary" - "free5gc/lib/Npcf_AMPolicy" "free5gc/lib/http2_util" - "free5gc/lib/openapi/common" + "free5gc/lib/openapi" + "free5gc/lib/openapi/Npcf_AMPolicy" "free5gc/lib/openapi/models" "free5gc/lib/path_util" - "free5gc/src/amf/amf_service" + amf_service "free5gc/src/amf/service" "free5gc/src/app" - "free5gc/src/nrf/nrf_service" + nrf_service "free5gc/src/nrf/service" + pcf_context "free5gc/src/pcf/context" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_producer" - "free5gc/src/pcf/pcf_service" - "free5gc/src/udr/udr_service" + pcf_service "free5gc/src/pcf/service" + udr_service "free5gc/src/udr/service" "net/http" "strings" "testing" "time" + "github.com/gin-gonic/gin" + "go.mongodb.org/mongo-driver/bson" + "github.com/stretchr/testify/assert" "github.com/urfave/cli" ) @@ -101,7 +101,7 @@ func TestCreateAMPolicy(t *testing.T) { assert.True(t, httpRsp != nil) if httpRsp != nil { assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) assert.Equal(t, "ERROR_REQUEST_PARAMETERS", problem.Cause) assert.Equal(t, "Miss Mandotory IE", problem.Detail) } @@ -113,7 +113,7 @@ func TestCreateAMPolicy(t *testing.T) { assert.True(t, httpRsp != nil) if httpRsp != nil { assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) assert.Equal(t, "ERROR_REQUEST_PARAMETERS", problem.Cause) assert.Equal(t, "Supi Format Error", problem.Detail) } @@ -202,7 +202,7 @@ func TestDelAMPolicy(t *testing.T) { assert.True(t, httpRsp != nil) if httpRsp != nil { assert.Equal(t, http.StatusNotFound, httpRsp.StatusCode) - problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) assert.Equal(t, "CONTEXT_NOT_FOUND", problem.Cause) } } @@ -327,14 +327,14 @@ func TestAMPolicyNotification(t *testing.T) { policyUpdate := models.PolicyUpdate{ ResourceUri: amCreateReqData.NotificationUri, } - pcf_producer.SendAMPolicyUpdateNotification(ue, polAssoId, policyUpdate) + producer.SendAMPolicyUpdateNotification(ue, polAssoId, policyUpdate) //Test Policies Termination Notify notification := models.TerminationNotification{ ResourceUri: amCreateReqData.NotificationUri, Cause: models.PolicyAssociationReleaseCause_UNSPECIFIED, } - pcf_producer.SendAMPolicyTerminationRequestNotification(ue, polAssoId, notification) + producer.SendAMPolicyTerminationRequestNotification(ue, polAssoId, notification) time.Sleep(200 * time.Millisecond) } diff --git a/AMPolicy/routers.go b/ampolicy/routers.go similarity index 99% rename from AMPolicy/routers.go rename to ampolicy/routers.go index eaba30f..d67df3f 100644 --- a/AMPolicy/routers.go +++ b/ampolicy/routers.go @@ -7,7 +7,7 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package AMPolicy +package ampolicy import ( "net/http" diff --git a/BDTPolicy/api_bdt_policies_collection_routers.go b/bdtpolicy/api_bdt_policies_collection_routers.go similarity index 82% rename from BDTPolicy/api_bdt_policies_collection_routers.go rename to bdtpolicy/api_bdt_policies_collection_routers.go index 662db20..e0fb758 100644 --- a/BDTPolicy/api_bdt_policies_collection_routers.go +++ b/bdtpolicy/api_bdt_policies_collection_routers.go @@ -7,12 +7,12 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package BDTPolicy +package bdtpolicy import ( "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" - "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/handler/message" "github.com/gin-gonic/gin" ) @@ -23,9 +23,9 @@ func CreateBDTPolicy(c *gin.Context) { c.ShouldBindJSON(&bdtReqData) req := http_wrapper.NewRequest(c.Request, bdtReqData) - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventBDTPolicyCreate, req) + channelMsg := message.NewHttpChannelMessage(message.EventBDTPolicyCreate, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse diff --git a/BDTPolicy/api_bdt_policies_collection_routers_test.go b/bdtpolicy/api_bdt_policies_collection_routers_test.go similarity index 86% rename from BDTPolicy/api_bdt_policies_collection_routers_test.go rename to bdtpolicy/api_bdt_policies_collection_routers_test.go index a704ffe..6bd5250 100644 --- a/BDTPolicy/api_bdt_policies_collection_routers_test.go +++ b/bdtpolicy/api_bdt_policies_collection_routers_test.go @@ -1,32 +1,33 @@ -package BDTPolicy_test +package bdtpolicy_test import ( "context" "flag" "fmt" - "github.com/davecgh/go-spew/spew" - "github.com/gin-gonic/gin" - "go.mongodb.org/mongo-driver/bson" TestBDTPolicy "free5gc/lib/CommonConsumerTestData/PCF/TestBDTPolicy" "free5gc/lib/MongoDBLibrary" - "free5gc/lib/Npcf_BDTPolicyControl" "free5gc/lib/http2_util" + "free5gc/lib/openapi/Npcf_BDTPolicyControl" "free5gc/lib/openapi/models" "free5gc/lib/path_util" "free5gc/src/app" - "free5gc/src/nrf/nrf_service" - "free5gc/src/pcf/pcf_service" - "free5gc/src/udr/DataRepository" + nrf_service "free5gc/src/nrf/service" + pcf_service "free5gc/src/pcf/service" + "free5gc/src/udr/consumer" + "free5gc/src/udr/datarepository" "free5gc/src/udr/factory" "free5gc/src/udr/logger" - "free5gc/src/udr/udr_consumer" - "free5gc/src/udr/udr_service" - "free5gc/src/udr/udr_util" + udr_service "free5gc/src/udr/service" + "free5gc/src/udr/util" "log" "net/http" "testing" "time" + "github.com/davecgh/go-spew/spew" + "github.com/gin-gonic/gin" + "go.mongodb.org/mongo-driver/bson" + "github.com/stretchr/testify/assert" "github.com/urfave/cli" ) @@ -44,19 +45,19 @@ func fakeudrInit() { nrfUri := config.Configuration.NrfUri // Connect to MongoDB - DataRepository.SetMongoDB(mongodb.Name, mongodb.Url) + datarepository.SetMongoDB(mongodb.Name, mongodb.Url) - udrLogPath := udr_util.UdrLogPath - udrPemPath := udr_util.UdrPemPath - udrKeyPath := udr_util.UdrKeyPath + udrLogPath := util.UdrLogPath + udrPemPath := util.UdrPemPath + udrKeyPath := util.UdrKeyPath if sbi.Tls != nil { udrLogPath = path_util.Gofree5gcPath(sbi.Tls.Log) udrPemPath = path_util.Gofree5gcPath(sbi.Tls.Pem) udrKeyPath = path_util.Gofree5gcPath(sbi.Tls.Key) } - profile := udr_consumer.BuildNFInstance() - newNrfUri, _, err := udr_consumer.SendRegisterNFInstance(nrfUri, profile.NfInstanceId, profile) + profile := consumer.BuildNFInstance() + newNrfUri, _, err := consumer.SendRegisterNFInstance(nrfUri, profile.NfInstanceId, profile) if err == nil { config.Configuration.NrfUri = newNrfUri } else { diff --git a/BDTPolicy/api_individual_bdt_policy_document_routers.go b/bdtpolicy/api_individual_bdt_policy_document_routers.go similarity index 79% rename from BDTPolicy/api_individual_bdt_policy_document_routers.go rename to bdtpolicy/api_individual_bdt_policy_document_routers.go index 5e3e0c9..0a8bf4b 100644 --- a/BDTPolicy/api_individual_bdt_policy_document_routers.go +++ b/bdtpolicy/api_individual_bdt_policy_document_routers.go @@ -7,12 +7,12 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package BDTPolicy +package bdtpolicy import ( "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" - "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/handler/message" "github.com/gin-gonic/gin" ) @@ -21,9 +21,9 @@ import ( func GetBDTPolicy(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["bdtPolicyId"] = c.Params.ByName("bdtPolicyId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventBDTPolicyGet, req) + channelMsg := message.NewHttpChannelMessage(message.EventBDTPolicyGet, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse c.JSON(HTTPResponse.Status, HTTPResponse.Body) @@ -36,9 +36,9 @@ func UpdateBDTPolicy(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, bdtPolicyDataPatch) req.Params["bdtPolicyId"] = c.Params.ByName("bdtPolicyId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventBDTPolicyUpdate, req) + channelMsg := message.NewHttpChannelMessage(message.EventBDTPolicyUpdate, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse c.JSON(HTTPResponse.Status, HTTPResponse.Body) diff --git a/BDTPolicy/api_individual_bdt_policy_document_routers_test.go b/bdtpolicy/api_individual_bdt_policy_document_routers_test.go similarity index 97% rename from BDTPolicy/api_individual_bdt_policy_document_routers_test.go rename to bdtpolicy/api_individual_bdt_policy_document_routers_test.go index c3fb074..a27e018 100644 --- a/BDTPolicy/api_individual_bdt_policy_document_routers_test.go +++ b/bdtpolicy/api_individual_bdt_policy_document_routers_test.go @@ -1,15 +1,16 @@ -package BDTPolicy_test +package bdtpolicy_test import ( "context" - "github.com/stretchr/testify/assert" TestBDTPolicy "free5gc/lib/CommonConsumerTestData/PCF/TestBDTPolicy" - "free5gc/lib/Npcf_BDTPolicyControl" + "free5gc/lib/openapi/Npcf_BDTPolicyControl" "free5gc/lib/openapi/models" "net/http" "strings" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestGetUpdateBDTPolicy(t *testing.T) { diff --git a/BDTPolicy/routers.go b/bdtpolicy/routers.go similarity index 99% rename from BDTPolicy/routers.go rename to bdtpolicy/routers.go index dfabaf7..2c336f2 100644 --- a/BDTPolicy/routers.go +++ b/bdtpolicy/routers.go @@ -7,7 +7,7 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package BDTPolicy +package bdtpolicy import ( "net/http" diff --git a/pcf_consumer/Communication.go b/consumer/communication.go similarity index 80% rename from pcf_consumer/Communication.go rename to consumer/communication.go index 71d0fb3..3ab3593 100644 --- a/pcf_consumer/Communication.go +++ b/consumer/communication.go @@ -1,20 +1,20 @@ -package pcf_consumer +package consumer import ( "context" "fmt" - "free5gc/lib/openapi/common" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" + pcf_context "free5gc/src/pcf/context" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/util" "strings" ) func AmfStatusChangeSubscribe(amfInfo pcf_context.AMFStatusSubscriptionData) (problemDetails *models.ProblemDetails, err error) { logger.Consumerlog.Debugf("PCF Subscribe to AMF status[%+v]", amfInfo.AmfUri) pcfSelf := pcf_context.PCF_Self() - client := pcf_util.GetNamfClient(amfInfo.AmfUri) + client := util.GetNamfClient(amfInfo.AmfUri) subscriptionData := models.SubscriptionData{ AmfStatusUri: fmt.Sprintf("%s/npcf-callback/v1/amfstatus", pcfSelf.GetIPv4Uri()), @@ -38,10 +38,10 @@ func AmfStatusChangeSubscribe(amfInfo pcf_context.AMFStatusSubscriptionData) (pr err = localErr return } - problem := localErr.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := localErr.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) problemDetails = &problem } else { - err = common.ReportError("%s: server no response", amfInfo.AmfUri) + err = openapi.ReportError("%s: server no response", amfInfo.AmfUri) } return } diff --git a/pcf_consumer/NFDiscovery.go b/consumer/nf_discovery.go similarity index 85% rename from pcf_consumer/NFDiscovery.go rename to consumer/nf_discovery.go index 50685ca..005c64a 100644 --- a/pcf_consumer/NFDiscovery.go +++ b/consumer/nf_discovery.go @@ -1,15 +1,16 @@ -package pcf_consumer +package consumer import ( "context" "fmt" - "github.com/antihax/optional" - "free5gc/lib/Nnrf_NFDiscovery" + "free5gc/lib/openapi/Nnrf_NFDiscovery" "free5gc/lib/openapi/models" + pcf_context "free5gc/src/pcf/context" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/util" "net/http" + + "github.com/antihax/optional" ) func SendSearchNFInstances(nrfUri string, targetNfType, requestNfType models.NfType, param Nnrf_NFDiscovery.SearchNFInstancesParamOpts) (result models.SearchResult, err error) { @@ -48,7 +49,7 @@ func SendNFIntancesUDR(nrfUri, id string) string { return "" } for _, profile := range result.NfInstances { - if uri := pcf_util.SearchNFServiceUri(profile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED); uri != "" { + if uri := util.SearchNFServiceUri(profile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED); uri != "" { return uri } } @@ -60,7 +61,7 @@ func SendNFIntancesAMF(nrfUri string, guami models.Guami, serviceName models.Ser requestNfType := models.NfType_PCF localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ - Guami: optional.NewInterface(pcf_util.MarshToJsonString(guami)), + Guami: optional.NewInterface(util.MarshToJsonString(guami)), } // switch types { // case NFDiscoveryToUDRParamSupi: @@ -77,7 +78,7 @@ func SendNFIntancesAMF(nrfUri string, guami models.Guami, serviceName models.Ser return "" } for _, profile := range result.NfInstances { - return pcf_util.SearchNFServiceUri(profile, serviceName, models.NfServiceStatus_REGISTERED) + return util.SearchNFServiceUri(profile, serviceName, models.NfServiceStatus_REGISTERED) } return "" } @@ -92,7 +93,7 @@ func SearchAvailableAMFs(nrfUri string, serviceName models.ServiceName) (amfInfo } for _, profile := range result.NfInstances { - uri := pcf_util.SearchNFServiceUri(profile, serviceName, models.NfServiceStatus_REGISTERED) + uri := util.SearchNFServiceUri(profile, serviceName, models.NfServiceStatus_REGISTERED) if uri != "" { item := pcf_context.AMFStatusSubscriptionData{ AmfUri: uri, diff --git a/pcf_consumer/NFManagement.go b/consumer/nf_management.go similarity index 95% rename from pcf_consumer/NFManagement.go rename to consumer/nf_management.go index bc318b1..12b9833 100644 --- a/pcf_consumer/NFManagement.go +++ b/consumer/nf_management.go @@ -1,11 +1,11 @@ -package pcf_consumer +package consumer import ( "context" "fmt" - "free5gc/lib/Nnrf_NFManagement" + "free5gc/lib/openapi/Nnrf_NFManagement" "free5gc/lib/openapi/models" - "free5gc/src/pcf/pcf_context" + pcf_context "free5gc/src/pcf/context" "net/http" "strings" "time" diff --git a/pcf_consumer/NFManagement_test.go b/consumer/nf_management_test.go similarity index 79% rename from pcf_consumer/NFManagement_test.go rename to consumer/nf_management_test.go index 6c5d64f..a18e048 100644 --- a/pcf_consumer/NFManagement_test.go +++ b/consumer/nf_management_test.go @@ -1,14 +1,14 @@ -package pcf_consumer_test +package consumer_test import ( "flag" "free5gc/lib/MongoDBLibrary" - "free5gc/lib/Nnrf_NFDiscovery" + "free5gc/lib/openapi/Nnrf_NFDiscovery" "free5gc/lib/openapi/models" - "free5gc/src/nrf/nrf_service" + nrf_service "free5gc/src/nrf/service" + "free5gc/src/pcf/consumer" "free5gc/src/pcf/factory" - "free5gc/src/pcf/pcf_consumer" - "free5gc/src/pcf/pcf_service" + pcf_service "free5gc/src/pcf/service" "testing" "time" @@ -41,7 +41,7 @@ func TestRegisterNFInstance(t *testing.T) { param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NPCF_AM_POLICY_CONTROL, models.ServiceName_NPCF_BDTPOLICYCONTROL, models.ServiceName_NPCF_POLICYAUTHORIZATION, models.ServiceName_NPCF_SMPOLICYCONTROL, models.ServiceName_NPCF_UE_POLICY_CONTROL}), } - result, err := pcf_consumer.SendSearchNFInstances(factory.PcfConfig.Configuration.NrfUri, models.NfType_PCF, models.NfType_UDR, param) + result, err := consumer.SendSearchNFInstances(factory.PcfConfig.Configuration.NrfUri, models.NfType_PCF, models.NfType_UDR, param) if err != nil { t.Error(err.Error()) } else if result.NfInstances == nil { diff --git a/pcf_context/context.go b/context/context.go similarity index 99% rename from pcf_context/context.go rename to context/context.go index 1d7f31c..267e9b1 100644 --- a/pcf_context/context.go +++ b/context/context.go @@ -1,4 +1,4 @@ -package pcf_context +package context import ( "fmt" diff --git a/pcf_context/ue.go b/context/ue.go similarity index 99% rename from pcf_context/ue.go rename to context/ue.go index e409e9c..cc2a36f 100644 --- a/pcf_context/ue.go +++ b/context/ue.go @@ -1,4 +1,4 @@ -package pcf_context +package context import ( "fmt" diff --git a/factory/config_configuration.go b/factory/config.go similarity index 54% rename from factory/config_configuration.go rename to factory/config.go index 3612e78..ff808e0 100644 --- a/factory/config_configuration.go +++ b/factory/config.go @@ -4,6 +4,18 @@ package factory +type Config struct { + Info *Info `yaml:"info"` + + Configuration *Configuration `yaml:"configuration"` +} + +type Info struct { + Version string `yaml:"version,omitempty"` + + Description string `yaml:"description,omitempty"` +} + type Configuration struct { PcfName string `yaml:"pcfName,omitempty"` @@ -22,3 +34,10 @@ type Service struct { ServiceName string `yaml:"serviceName"` SuppFeat string `yaml:"suppFeat,omitempty"` } + +type Sbi struct { + Scheme string `yaml:"scheme"` + IPv4Addr string `yaml:"ipv4Addr,omitempty"` + // IPv6Addr string `yaml:"ipv6Addr,omitempty"` + Port int `yaml:"port,omitempty"` +} diff --git a/factory/config_config.go b/factory/config_config.go deleted file mode 100644 index 4d90773..0000000 --- a/factory/config_config.go +++ /dev/null @@ -1,11 +0,0 @@ -/* - * PCF Configuration Factory - */ - -package factory - -type Config struct { - Info *Info `yaml:"info"` - - Configuration *Configuration `yaml:"configuration"` -} diff --git a/factory/config_info.go b/factory/config_info.go deleted file mode 100644 index 40976ea..0000000 --- a/factory/config_info.go +++ /dev/null @@ -1,11 +0,0 @@ -/* - * PCF Configuration Factory - */ - -package factory - -type Info struct { - Version string `yaml:"version,omitempty"` - - Description string `yaml:"description,omitempty"` -} diff --git a/factory/config_sbi.go b/factory/config_sbi.go deleted file mode 100644 index 4350f72..0000000 --- a/factory/config_sbi.go +++ /dev/null @@ -1,12 +0,0 @@ -/* - * PCF Configuration Factory - */ - -package factory - -type Sbi struct { - Scheme string `yaml:"scheme"` - IPv4Addr string `yaml:"ipv4Addr,omitempty"` - // IPv6Addr string `yaml:"ipv6Addr,omitempty"` - Port int `yaml:"port,omitempty"` -} diff --git a/pcf_handler/handler.go b/handler/handler.go similarity index 76% rename from pcf_handler/handler.go rename to handler/handler.go index 3ded339..cac7220 100644 --- a/pcf_handler/handler.go +++ b/handler/handler.go @@ -1,10 +1,10 @@ -package pcf_handler +package handler import ( "free5gc/lib/openapi/models" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_handler/pcf_message" - "free5gc/src/pcf/pcf_producer" + "free5gc/src/pcf/producer" "time" "github.com/sirupsen/logrus" @@ -20,63 +20,63 @@ func init() { func Handle() { for { select { - case msg, ok := <-pcf_message.PCFChannel: + case msg, ok := <-message.PCFChannel: if ok { switch msg.Event { - case pcf_message.EventBDTPolicyCreate: + case message.EventBDTPolicyCreate: pcf_producer.CreateBDTPolicyContext(msg.HttpChannel, msg.HTTPRequest.Body.(models.BdtReqData)) - case pcf_message.EventBDTPolicyGet: + case message.EventBDTPolicyGet: bdtPolicyId := msg.HTTPRequest.Params["bdtPolicyId"] pcf_producer.GetBDTPolicyContext(msg.HttpChannel, bdtPolicyId) - case pcf_message.EventBDTPolicyUpdate: + case message.EventBDTPolicyUpdate: bdtPolicyId := msg.HTTPRequest.Params["bdtPolicyId"] pcf_producer.UpdateBDTPolicyContext(msg.HttpChannel, bdtPolicyId, msg.HTTPRequest.Body.(models.BdtPolicyDataPatch)) - case pcf_message.EventPostAppSessions: + case message.EventPostAppSessions: pcf_producer.PostAppSessionsContext(msg.HttpChannel, msg.HTTPRequest.Body.(models.AppSessionContext)) - case pcf_message.EventGetAppSession: + case message.EventGetAppSession: appSessionId := msg.HTTPRequest.Params["appSessionId"] pcf_producer.GetAppSessionContext(msg.HttpChannel, appSessionId) - case pcf_message.EventDeleteAppSession: + case message.EventDeleteAppSession: appSessionId := msg.HTTPRequest.Params["appSessionId"] pcf_producer.DeleteAppSessionContext(msg.HttpChannel, appSessionId, msg.HTTPRequest.Body.(*models.EventsSubscReqData)) - case pcf_message.EventModAppSession: + case message.EventModAppSession: appSessionId := msg.HTTPRequest.Params["appSessionId"] pcf_producer.ModAppSessionContext(msg.HttpChannel, appSessionId, msg.HTTPRequest.Body.(models.AppSessionContextUpdateData)) - case pcf_message.EventDeleteEventsSubsc: + case message.EventDeleteEventsSubsc: appSessionId := msg.HTTPRequest.Params["appSessionId"] pcf_producer.DeleteEventsSubscContext(msg.HttpChannel, appSessionId) - case pcf_message.EventUpdateEventsSubsc: + case message.EventUpdateEventsSubsc: appSessionId := msg.HTTPRequest.Params["appSessionId"] pcf_producer.UpdateEventsSubscContext(msg.HttpChannel, appSessionId, msg.HTTPRequest.Body.(models.EventsSubscReqData)) - case pcf_message.EventAMPolicyGet: + case message.EventAMPolicyGet: PolAssoId := msg.HTTPRequest.Params["polAssoId"] pcf_producer.GetPoliciesPolAssoId(msg.HttpChannel, PolAssoId) - case pcf_message.EventAMPolicyDelete: + case message.EventAMPolicyDelete: PolAssoId := msg.HTTPRequest.Params["polAssoId"] pcf_producer.DeletePoliciesPolAssoId(msg.HttpChannel, PolAssoId) - case pcf_message.EventAMPolicyCreate: + case message.EventAMPolicyCreate: pcf_producer.PostPolicies(msg.HttpChannel, msg.HTTPRequest.Body.(models.PolicyAssociationRequest)) - case pcf_message.EventAMPolicyUpdate: + case message.EventAMPolicyUpdate: PolAssoId := msg.HTTPRequest.Params["polAssoId"] pcf_producer.UpdatePostPoliciesPolAssoId(msg.HttpChannel, PolAssoId, msg.HTTPRequest.Body.(models.PolicyAssociationUpdateRequest)) - case pcf_message.EventSMPolicyCreate: + case message.EventSMPolicyCreate: pcf_producer.CreateSmPolicy(msg.HttpChannel, msg.HTTPRequest.Body.(models.SmPolicyContextData)) - case pcf_message.EventSMPolicyGet: + case message.EventSMPolicyGet: smPolicyId := msg.HTTPRequest.Params["smPolicyId"] pcf_producer.GetSmPolicyContext(msg.HttpChannel, smPolicyId) - case pcf_message.EventSMPolicyUpdate: + case message.EventSMPolicyUpdate: smPolicyId := msg.HTTPRequest.Params["smPolicyId"] pcf_producer.UpdateSmPolicyContext(msg.HttpChannel, smPolicyId, msg.HTTPRequest.Body.(models.SmPolicyUpdateContextData)) - case pcf_message.EventSMPolicyDelete: + case message.EventSMPolicyDelete: smPolicyId := msg.HTTPRequest.Params["smPolicyId"] pcf_producer.DeleteSmPolicyContext(msg.HttpChannel, smPolicyId) - case pcf_message.EventSMPolicyNotify: + case message.EventSMPolicyNotify: ReqURI := msg.HTTPRequest.Params["ReqURI"] pcf_producer.HandleSmPolicyNotify(msg.HttpChannel, ReqURI, msg.HTTPRequest.Body.(models.PolicyDataChangeNotification)) - case pcf_message.EventAMFStatusChangeNotify: + case message.EventAMFStatusChangeNotify: pcf_producer.HandleAmfStatusChangeNotify(msg.HttpChannel, msg.HTTPRequest.Body.(models.AmfStatusChangeNotification)) // TODO: http event dispatcher - case pcf_message.EventOAMGetAmPolicy: + case message.EventOAMGetAmPolicy: supi := msg.HTTPRequest.Params["supi"] pcf_producer.HandleOAMGetAmPolicy(msg.HttpChannel, supi) default: diff --git a/pcf_handler/handler_test.go b/handler/handler_test.go similarity index 97% rename from pcf_handler/handler_test.go rename to handler/handler_test.go index 40a155c..f0ef8a1 100644 --- a/pcf_handler/handler_test.go +++ b/handler/handler_test.go @@ -1,4 +1,4 @@ -package pcf_handler_test +package handler_test import ( // "free5gc/lib/CommonConsumerTestData/AMF/TestAmf" diff --git a/pcf_handler/pcf_message/channel.go b/handler/message/channel.go similarity index 93% rename from pcf_handler/pcf_message/channel.go rename to handler/message/channel.go index ed0030c..1f9362d 100644 --- a/pcf_handler/pcf_message/channel.go +++ b/handler/message/channel.go @@ -1,4 +1,4 @@ -package pcf_message +package message import ( "sync" diff --git a/pcf_handler/pcf_message/event.go b/handler/message/event.go similarity index 98% rename from pcf_handler/pcf_message/event.go rename to handler/message/event.go index dad51ac..a764ca9 100644 --- a/pcf_handler/pcf_message/event.go +++ b/handler/message/event.go @@ -1,4 +1,4 @@ -package pcf_message +package message const ( EventBDTPolicyCreate = "BDTPolicyCreate Message" diff --git a/pcf_handler/pcf_message/message.go b/handler/message/message.go similarity index 99% rename from pcf_handler/pcf_message/message.go rename to handler/message/message.go index ad3775a..493ee9c 100644 --- a/pcf_handler/pcf_message/message.go +++ b/handler/message/message.go @@ -1,4 +1,4 @@ -package pcf_message +package message import ( "free5gc/lib/http_wrapper" diff --git a/HttpCallback/AMFStatusChangeNotify.go b/httpcallback/amf_status_change_notify.go similarity index 79% rename from HttpCallback/AMFStatusChangeNotify.go rename to httpcallback/amf_status_change_notify.go index a7ad174..d9641e0 100644 --- a/HttpCallback/AMFStatusChangeNotify.go +++ b/httpcallback/amf_status_change_notify.go @@ -1,11 +1,11 @@ -package Npcf_Callback +package httpcallback import ( - "github.com/gin-gonic/gin" "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_handler/pcf_message" + "github.com/gin-gonic/gin" "net/http" ) @@ -27,8 +27,8 @@ func AmfStatusChangeNotify(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, request) - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventAMFStatusChangeNotify, req) - pcf_message.SendMessage(channelMsg) + channelMsg := message.NewHttpChannelMessage(message.EventAMFStatusChangeNotify, req) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse diff --git a/HttpCallback/router.go b/httpcallback/router.go similarity index 98% rename from HttpCallback/router.go rename to httpcallback/router.go index 407c0f3..50faa04 100644 --- a/HttpCallback/router.go +++ b/httpcallback/router.go @@ -1,4 +1,4 @@ -package Npcf_Callback +package httpcallback import ( "net/http" diff --git a/HttpCallback/SMPolicyNotify.go b/httpcallback/sm_policy_notify.go similarity index 77% rename from HttpCallback/SMPolicyNotify.go rename to httpcallback/sm_policy_notify.go index bb30336..bdb78a0 100644 --- a/HttpCallback/SMPolicyNotify.go +++ b/httpcallback/sm_policy_notify.go @@ -1,10 +1,10 @@ -package Npcf_Callback +package httpcallback import ( "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_handler/pcf_message" "github.com/gin-gonic/gin" ) @@ -18,9 +18,9 @@ func NudrNotify(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, policyDataChangeNotification) req.Params["ReqURI"] = c.Params.ByName("supi") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyNotify, req) + channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyNotify, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse c.JSON(HTTPResponse.Status, HTTPResponse.Body) diff --git a/logger/logger.go b/logger/logger.go index e492044..8e64185 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,5 +1,3 @@ -//+build !debug - package logger import ( @@ -9,6 +7,9 @@ import ( "strings" "github.com/sirupsen/logrus" + + "free5gc/lib/logger_conf" + "free5gc/lib/logger_util" ) var log *logrus.Logger @@ -49,6 +50,16 @@ func init() { }, } + free5gcLogHook, err := logger_util.NewFileHook(logger_conf.Free5gcLogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) + if err == nil { + log.Hooks.Add(free5gcLogHook) + } + + selfLogHook, err := logger_util.NewFileHook(logger_conf.NfLogDir+"pcf.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) + if err == nil { + log.Hooks.Add(selfLogHook) + } + AppLog = log.WithFields(logrus.Fields{"PCF": "app"}) InitLog = log.WithFields(logrus.Fields{"PCF": "init"}) HandlerLog = log.WithFields(logrus.Fields{"PCF": "Handler"}) diff --git a/OAM/api_get_am_policy.go b/oam/api_get_am_policy.go similarity index 81% rename from OAM/api_get_am_policy.go rename to oam/api_get_am_policy.go index f6e7288..54c29c0 100644 --- a/OAM/api_get_am_policy.go +++ b/oam/api_get_am_policy.go @@ -1,9 +1,9 @@ -package Npcf_OAM +package oam import ( "github.com/gin-gonic/gin" "free5gc/lib/http_wrapper" - "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/handler/message" ) func setCorsHeader(c *gin.Context) { @@ -19,8 +19,8 @@ func OAMGetAmPolicy(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["supi"] = c.Params.ByName("supi") - handlerMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventOAMGetAmPolicy, req) - pcf_message.SendMessage(handlerMsg) + handlerMsg := message.NewHttpChannelMessage(message.EventOAMGetAmPolicy, req) + message.SendMessage(handlerMsg) rsp := <-handlerMsg.HttpChannel diff --git a/OAM/routers.go b/oam/routers.go similarity index 98% rename from OAM/routers.go rename to oam/routers.go index 5e759be..1b9996a 100644 --- a/OAM/routers.go +++ b/oam/routers.go @@ -1,4 +1,4 @@ -package Npcf_OAM +package oam import ( "net/http" diff --git a/pcf.go b/pcf.go index 97fad07..0b365f0 100644 --- a/pcf.go +++ b/pcf.go @@ -13,7 +13,7 @@ import ( "fmt" "free5gc/src/app" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_service" + "free5gc/src/pcf/service" "free5gc/src/pcf/version" "os" @@ -21,7 +21,7 @@ import ( "github.com/urfave/cli" ) -var PCF = &pcf_service.PCF{} +var PCF = &service.PCF{} var appLog *logrus.Entry diff --git a/PolicyAuthorization/api_application_sessions_collection.go b/policyauthorization/api_application_sessions_collection.go similarity index 72% rename from PolicyAuthorization/api_application_sessions_collection.go rename to policyauthorization/api_application_sessions_collection.go index 7781fdd..16c7e42 100644 --- a/PolicyAuthorization/api_application_sessions_collection.go +++ b/policyauthorization/api_application_sessions_collection.go @@ -7,14 +7,14 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package PolicyAuthorization +package policyauthorization import ( "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_handler/pcf_message" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/handler/message" + "free5gc/src/pcf/util" "github.com/gin-gonic/gin" ) @@ -24,7 +24,7 @@ func PostAppSessions(c *gin.Context) { var appSessionContext models.AppSessionContext err := c.ShouldBindJSON(&appSessionContext) if err != nil { - rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_INITIAL_PARAMETERS) + rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_INITIAL_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return @@ -32,16 +32,16 @@ func PostAppSessions(c *gin.Context) { reqData := appSessionContext.AscReqData if reqData == nil || reqData.SuppFeat == "" || reqData.NotifUri == "" { // Check Mandatory IEs - rsp := pcf_util.GetProblemDetail("Errorneous/Missing Mandotory IE", pcf_util.ERROR_INITIAL_PARAMETERS) + rsp := util.GetProblemDetail("Errorneous/Missing Mandotory IE", util.ERROR_INITIAL_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return } req := http_wrapper.NewRequest(c.Request, appSessionContext) - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventPostAppSessions, req) + channelMsg := message.NewHttpChannelMessage(message.EventPostAppSessions, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse diff --git a/PolicyAuthorization/api_application_sessions_collection_test.go b/policyauthorization/api_application_sessions_collection_test.go similarity index 94% rename from PolicyAuthorization/api_application_sessions_collection_test.go rename to policyauthorization/api_application_sessions_collection_test.go index af434f0..9ff0749 100644 --- a/PolicyAuthorization/api_application_sessions_collection_test.go +++ b/policyauthorization/api_application_sessions_collection_test.go @@ -1,34 +1,35 @@ -package PolicyAuthorization_test +package policyauthorization_test import ( "context" "encoding/json" "flag" "fmt" - "github.com/gin-gonic/gin" - "go.mongodb.org/mongo-driver/bson" "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" "free5gc/lib/CommonConsumerTestData/PCF/TestPolicyAuthorization" "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" "free5gc/lib/MongoDBLibrary" - "free5gc/lib/Npcf_AMPolicy" - "free5gc/lib/Npcf_PolicyAuthorization" - "free5gc/lib/Npcf_SMPolicyControl" "free5gc/lib/http2_util" - "free5gc/lib/openapi/common" + "free5gc/lib/openapi" + "free5gc/lib/openapi/Npcf_AMPolicy" + "free5gc/lib/openapi/Npcf_PolicyAuthorization" + "free5gc/lib/openapi/Npcf_SMPolicyControl" "free5gc/lib/openapi/models" "free5gc/lib/path_util" - "free5gc/src/amf/amf_service" + amf_service "free5gc/src/amf/service" "free5gc/src/app" - "free5gc/src/nrf/nrf_service" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_service" - "free5gc/src/udr/udr_service" + nrf_service "free5gc/src/nrf/service" + pcf_context "free5gc/src/pcf/context" + pcf_service "free5gc/src/pcf/service" + udr_service "free5gc/src/udr/service" "net/http" "strings" "testing" "time" + "github.com/gin-gonic/gin" + "go.mongodb.org/mongo-driver/bson" + "github.com/stretchr/testify/assert" "github.com/urfave/cli" ) @@ -284,7 +285,7 @@ func TestApplicationSessionsCollection(t *testing.T) { assert.True(t, httpRsp != nil) if httpRsp != nil { assert.Equal(t, http.StatusForbidden, httpRsp.StatusCode) - problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) assert.Equal(t, "REQUESTED_SERVICE_NOT_AUTHORIZED", problem.Cause) } } @@ -295,7 +296,7 @@ func TestApplicationSessionsCollection(t *testing.T) { assert.True(t, httpRsp != nil) if httpRsp != nil { assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) assert.Equal(t, "ERROR_REQUEST_PARAMETERS", problem.Cause) } } diff --git a/PolicyAuthorization/api_events_subscription_document.go b/policyauthorization/api_events_subscription_document.go similarity index 71% rename from PolicyAuthorization/api_events_subscription_document.go rename to policyauthorization/api_events_subscription_document.go index 424eb9e..7c3f0d4 100644 --- a/PolicyAuthorization/api_events_subscription_document.go +++ b/policyauthorization/api_events_subscription_document.go @@ -7,14 +7,14 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package PolicyAuthorization +package policyauthorization import ( "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_handler/pcf_message" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/handler/message" + "free5gc/src/pcf/util" "github.com/gin-gonic/gin" ) @@ -24,9 +24,9 @@ func DeleteEventsSubsc(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventDeleteEventsSubsc, req) + channelMsg := message.NewHttpChannelMessage(message.EventDeleteEventsSubsc, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse @@ -38,13 +38,13 @@ func UpdateEventsSubsc(c *gin.Context) { var eventsSubscReqData models.EventsSubscReqData err := c.ShouldBindJSON(&eventsSubscReqData) if err != nil { - rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_REQUEST_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return } if eventsSubscReqData.Events == nil || eventsSubscReqData.NotifUri == "" { - rsp := pcf_util.GetProblemDetail("Errorneous/Missing Mandotory IE", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("Errorneous/Missing Mandotory IE", util.ERROR_REQUEST_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return @@ -52,9 +52,9 @@ func UpdateEventsSubsc(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, eventsSubscReqData) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventUpdateEventsSubsc, req) + channelMsg := message.NewHttpChannelMessage(message.EventUpdateEventsSubsc, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse diff --git a/PolicyAuthorization/api_events_subscription_document_test.go b/policyauthorization/api_events_subscription_document_test.go similarity index 96% rename from PolicyAuthorization/api_events_subscription_document_test.go rename to policyauthorization/api_events_subscription_document_test.go index 1c28651..191fdd0 100644 --- a/PolicyAuthorization/api_events_subscription_document_test.go +++ b/policyauthorization/api_events_subscription_document_test.go @@ -1,4 +1,4 @@ -package PolicyAuthorization_test +package policyauthorization_test import ( "context" @@ -7,10 +7,10 @@ import ( "free5gc/lib/CommonConsumerTestData/PCF/TestPolicyAuthorization" "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" "free5gc/lib/MongoDBLibrary" - "free5gc/lib/Npcf_AMPolicy" - "free5gc/lib/Npcf_PolicyAuthorization" - "free5gc/lib/Npcf_SMPolicyControl" - "free5gc/src/pcf/pcf_context" + "free5gc/lib/openapi/Npcf_AMPolicy" + "free5gc/lib/openapi/Npcf_PolicyAuthorization" + "free5gc/lib/openapi/Npcf_SMPolicyControl" + pcf_context "free5gc/src/pcf/context" "net/http" "strings" "testing" diff --git a/PolicyAuthorization/api_individual_application_session_context_document.go b/policyauthorization/api_individual_application_session_context_document.go similarity index 78% rename from PolicyAuthorization/api_individual_application_session_context_document.go rename to policyauthorization/api_individual_application_session_context_document.go index 723fdd4..9821685 100644 --- a/PolicyAuthorization/api_individual_application_session_context_document.go +++ b/policyauthorization/api_individual_application_session_context_document.go @@ -7,12 +7,12 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package PolicyAuthorization +package policyauthorization import ( "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" - "free5gc/src/pcf/pcf_handler/pcf_message" + "free5gc/src/pcf/handler/message" "github.com/gin-gonic/gin" ) @@ -28,9 +28,9 @@ func DeleteAppSession(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, eventsSubscReqData) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventDeleteAppSession, req) + channelMsg := message.NewHttpChannelMessage(message.EventDeleteAppSession, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse @@ -42,9 +42,9 @@ func GetAppSession(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventGetAppSession, req) + channelMsg := message.NewHttpChannelMessage(message.EventGetAppSession, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse @@ -58,9 +58,9 @@ func ModAppSession(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, appSessionContextUpdateData) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventModAppSession, req) + channelMsg := message.NewHttpChannelMessage(message.EventModAppSession, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse diff --git a/PolicyAuthorization/api_individual_application_session_context_document_test.go b/policyauthorization/api_individual_application_session_context_document_test.go similarity index 97% rename from PolicyAuthorization/api_individual_application_session_context_document_test.go rename to policyauthorization/api_individual_application_session_context_document_test.go index f182c8d..493b09b 100644 --- a/PolicyAuthorization/api_individual_application_session_context_document_test.go +++ b/policyauthorization/api_individual_application_session_context_document_test.go @@ -1,26 +1,27 @@ -package PolicyAuthorization_test +package policyauthorization_test import ( "context" "fmt" - "github.com/davecgh/go-spew/spew" - "github.com/gin-gonic/gin" "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" "free5gc/lib/CommonConsumerTestData/PCF/TestPolicyAuthorization" "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" "free5gc/lib/MongoDBLibrary" - "free5gc/lib/Npcf_AMPolicy" - "free5gc/lib/Npcf_PolicyAuthorization" - "free5gc/lib/Npcf_SMPolicyControl" - "free5gc/lib/openapi/common" + "free5gc/lib/openapi" + "free5gc/lib/openapi/Npcf_AMPolicy" + "free5gc/lib/openapi/Npcf_PolicyAuthorization" + "free5gc/lib/openapi/Npcf_SMPolicyControl" "free5gc/lib/openapi/models" "free5gc/lib/path_util" - "free5gc/src/pcf/pcf_context" + pcf_context "free5gc/src/pcf/context" "net/http" "strings" "testing" "time" + "github.com/davecgh/go-spew/spew" + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" ) @@ -307,7 +308,7 @@ func TestAppSessionNotification(t *testing.T) { assert.True(t, httpRsp != nil) if httpRsp != nil { assert.Equal(t, http.StatusNotFound, httpRsp.StatusCode) - problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) assert.Equal(t, "APPLICATION_SESSION_CONTEXT_NOT_FOUND", problem.Cause) } } diff --git a/PolicyAuthorization/routers.go b/policyauthorization/routers.go similarity index 98% rename from PolicyAuthorization/routers.go rename to policyauthorization/routers.go index d7e2f97..91cc1c9 100644 --- a/PolicyAuthorization/routers.go +++ b/policyauthorization/routers.go @@ -7,7 +7,7 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package PolicyAuthorization +package policyauthorization import ( "net/http" diff --git a/pcf_producer/pcf_ampolicy.go b/producer/ampolicy.go similarity index 73% rename from pcf_producer/pcf_ampolicy.go rename to producer/ampolicy.go index bf1d584..2cf9ff7 100644 --- a/pcf_producer/pcf_ampolicy.go +++ b/producer/ampolicy.go @@ -3,40 +3,40 @@ package pcf_producer import ( "context" "fmt" - "github.com/mohae/deepcopy" "free5gc/lib/openapi/models" + "free5gc/src/pcf/consumer" + pcf_context "free5gc/src/pcf/context" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_consumer" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_handler/pcf_message" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/util" + "github.com/mohae/deepcopy" "net/http" "reflect" ) -func DeletePoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessage, polAssoId string) { +func DeletePoliciesPolAssoId(httpChannel chan message.HttpResponseMessage, polAssoId string) { logger.AMpolicylog.Traceln("Handle Policy Association Delete") ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(polAssoId) if ue == nil || ue.AMPolicyData[polAssoId] == nil { - rsp := pcf_util.GetProblemDetail("polAssoId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + rsp := util.GetProblemDetail("polAssoId not found in PCF", util.CONTEXT_NOT_FOUND) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } delete(ue.AMPolicyData, polAssoId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) } // PoliciesPolAssoIdGet - -func GetPoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessage, polAssoId string) { +func GetPoliciesPolAssoId(httpChannel chan message.HttpResponseMessage, polAssoId string) { logger.AMpolicylog.Traceln("Handle Policy Association Get") ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(polAssoId) if ue == nil || ue.AMPolicyData[polAssoId] == nil { - rsp := pcf_util.GetProblemDetail("polAssoId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + rsp := util.GetProblemDetail("polAssoId not found in PCF", util.CONTEXT_NOT_FOUND) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } amPolicyData := ue.AMPolicyData[polAssoId] @@ -58,17 +58,17 @@ func GetPoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessage, polA } } } - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) } -func UpdatePostPoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessage, polAssoId string, request models.PolicyAssociationUpdateRequest) { +func UpdatePostPoliciesPolAssoId(httpChannel chan message.HttpResponseMessage, polAssoId string, request models.PolicyAssociationUpdateRequest) { logger.AMpolicylog.Traceln("Handle Policy Association Update") ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(polAssoId) if ue == nil || ue.AMPolicyData[polAssoId] == nil { - rsp := pcf_util.GetProblemDetail("polAssoId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + rsp := util.GetProblemDetail("polAssoId not found in PCF", util.CONTEXT_NOT_FOUND) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } @@ -89,18 +89,18 @@ func UpdatePostPoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessag case models.RequestTrigger_LOC_CH: //TODO: report to AF subscriber if request.UserLoc == nil { - rsp := pcf_util.GetProblemDetail("UserLoc are nli", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("UserLoc are nli", util.ERROR_REQUEST_PARAMETERS) logger.AMpolicylog.Warnln("UserLoc doesn't exist in Policy Association Requset Update while Triggers include LOC_CH") - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } amPolicyData.UserLoc = request.UserLoc logger.AMpolicylog.Infof("Ue[%s] UserLocation %+v", ue.Supi, amPolicyData.UserLoc) case models.RequestTrigger_PRA_CH: if request.PraStatuses == nil { - rsp := pcf_util.GetProblemDetail("PraStatuses are nli", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("PraStatuses are nli", util.ERROR_REQUEST_PARAMETERS) logger.AMpolicylog.Warnln("PraStatuses doesn't exist in Policy Association Requset Update while Triggers include PRA_CH") - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } for praId, praInfo := range request.PraStatuses { @@ -109,9 +109,9 @@ func UpdatePostPoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessag } case models.RequestTrigger_SERV_AREA_CH: if request.ServAreaRes == nil { - rsp := pcf_util.GetProblemDetail("ServAreaRes are nli", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("ServAreaRes are nli", util.ERROR_REQUEST_PARAMETERS) logger.AMpolicylog.Warnln("ServAreaRes doesn't exist in Policy Association Requset Update while Triggers include SERV_AREA_CH") - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } else { amPolicyData.ServAreaRes = request.ServAreaRes @@ -119,9 +119,9 @@ func UpdatePostPoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessag } case models.RequestTrigger_RFSP_CH: if request.Rfsp == 0 { - rsp := pcf_util.GetProblemDetail("Rfsp are nli", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("Rfsp are nli", util.ERROR_REQUEST_PARAMETERS) logger.AMpolicylog.Warnln("Rfsp doesn't exist in Policy Association Requset Update while Triggers include RFSP_CH") - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } else { amPolicyData.Rfsp = request.Rfsp @@ -134,12 +134,12 @@ func UpdatePostPoliciesPolAssoId(httpChannel chan pcf_message.HttpResponseMessag rsp.Triggers = amPolicyData.Triggers //TODO: Change Policies if needed // rsp.Pras - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) } // Create AM Policy -func PostPolicies(httpChannel chan pcf_message.HttpResponseMessage, request models.PolicyAssociationRequest) { +func PostPolicies(httpChannel chan message.HttpResponseMessage, request models.PolicyAssociationRequest) { var rsp models.PolicyAssociation var err error @@ -151,9 +151,9 @@ func PostPolicies(httpChannel chan pcf_message.HttpResponseMessage, request mode ue, err = pcfSelf.NewPCFUe(request.Supi) if err != nil { // supi format dose not match "imsi-..." - rsp := pcf_util.GetProblemDetail("Supi Format Error", pcf_util.ERROR_REQUEST_PARAMETERS) + rsp := util.GetProblemDetail("Supi Format Error", util.ERROR_REQUEST_PARAMETERS) logger.AMpolicylog.Errorln(err.Error()) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } } @@ -161,9 +161,9 @@ func PostPolicies(httpChannel chan pcf_message.HttpResponseMessage, request mode if udrUri == "" { // Can't find any UDR support this Ue delete(pcfSelf.UePool, ue.Supi) - rsp := pcf_util.GetProblemDetail("Ue is not supported in PCF", pcf_util.USER_UNKNOWN) + rsp := util.GetProblemDetail("Ue is not supported in PCF", util.USER_UNKNOWN) logger.AMpolicylog.Errorf("Ue[%s] is not supported in PCF", ue.Supi) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } ue.UdrUri = udrUri @@ -173,13 +173,13 @@ func PostPolicies(httpChannel chan pcf_message.HttpResponseMessage, request mode amPolicy := ue.AMPolicyData[assolId] if amPolicy == nil || amPolicy.AmPolicyData == nil { - client := pcf_util.GetNudrClient(udrUri) + client := util.GetNudrClient(udrUri) var response *http.Response amData, response, err := client.DefaultApi.PolicyDataUesUeIdAmDataGet(context.Background(), ue.Supi) if err != nil || response == nil || response.StatusCode != http.StatusOK { - rsp := pcf_util.GetProblemDetail("Can't find UE AM Policy Data in UDR", pcf_util.USER_UNKNOWN) + rsp := util.GetProblemDetail("Can't find UE AM Policy Data in UDR", util.USER_UNKNOWN) logger.AMpolicylog.Errorf("Can't find UE[%s] AM Policy Data in UDR", ue.Supi) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } if amPolicy == nil { @@ -191,7 +191,7 @@ func PostPolicies(httpChannel chan pcf_message.HttpResponseMessage, request mode // TODO: according to PCF Policy to determine ServAreaRes, Rfsp, SuppFeat // amPolicy.ServAreaRes = // amPolicy.Rfsp = - amPolicy.SuppFeat = pcf_util.GetNegotiateSuppFeat(request.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_AM_POLICY_CONTROL]) + amPolicy.SuppFeat = util.GetNegotiateSuppFeat(request.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_AM_POLICY_CONTROL]) if amPolicy.Rfsp != 0 { rsp.Rfsp = amPolicy.Rfsp } @@ -201,12 +201,12 @@ func PostPolicies(httpChannel chan pcf_message.HttpResponseMessage, request mode // rsp.Pras ue.PolAssociationIDGenerator++ // Create location header for update, delete, get - locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_AM_POLICY_CONTROL, assolId) + locationHeader := util.GetResourceUri(models.ServiceName_NPCF_AM_POLICY_CONTROL, assolId) headers := http.Header{ "Location": {locationHeader}, } logger.AMpolicylog.Tracef("AMPolicy association Id[%s] Create", assolId) - pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, rsp) + message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, rsp) if request.Guami != nil { // if consumer is AMF then subscribe this AMF Status @@ -231,7 +231,7 @@ func SendAMPolicyUpdateNotification(ue *pcf_context.UeContext, PolId string, req logger.AMpolicylog.Warnf("Policy Update Notification Error[Can't find polAssoId[%s] in UE(%s)]", PolId, ue.Supi) return } - client := pcf_util.GetNpcfAMPolicyCallbackClient() + client := util.GetNpcfAMPolicyCallbackClient() uri := amPolicyData.NotificationUri for uri != "" { @@ -275,7 +275,7 @@ func SendAMPolicyTerminationRequestNotification(ue *pcf_context.UeContext, PolId logger.AMpolicylog.Warnf("Policy Assocition Termination Request Notification Error[Can't find polAssoId[%s] in UE(%s)]", PolId, ue.Supi) return } - client := pcf_util.GetNpcfAMPolicyCallbackClient() + client := util.GetNpcfAMPolicyCallbackClient() uri := amPolicyData.NotificationUri for uri != "" { @@ -311,5 +311,5 @@ func getUdrUri(ue *pcf_context.UeContext) string { if ue.UdrUri != "" { return ue.UdrUri } - return pcf_consumer.SendNFIntancesUDR(pcf_context.PCF_Self().NrfUri, ue.Supi) + return consumer.SendNFIntancesUDR(pcf_context.PCF_Self().NrfUri, ue.Supi) } diff --git a/pcf_producer/pcf_bdtpolicy.go b/producer/bdtpolicy.go similarity index 71% rename from pcf_producer/pcf_bdtpolicy.go rename to producer/bdtpolicy.go index c4487ca..59f5945 100644 --- a/pcf_producer/pcf_bdtpolicy.go +++ b/producer/bdtpolicy.go @@ -3,39 +3,40 @@ package pcf_producer import ( "context" "fmt" - "github.com/google/uuid" - "github.com/mohae/deepcopy" - "free5gc/lib/Nnrf_NFDiscovery" - "free5gc/lib/Nudr_DataRepository" + "free5gc/lib/openapi/Nnrf_NFDiscovery" + "free5gc/lib/openapi/Nudr_DataRepository" "free5gc/lib/openapi/models" + "free5gc/src/pcf/consumer" + pcf_context "free5gc/src/pcf/context" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_consumer" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_handler/pcf_message" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/util" "net/http" + "github.com/google/uuid" + "github.com/mohae/deepcopy" + "github.com/antihax/optional" ) -func GetBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, bdtPolicyId string) { +func GetBDTPolicyContext(httpChannel chan message.HttpResponseMessage, bdtPolicyId string) { logger.Bdtpolicylog.Traceln("Handle BDT Policy GET") // check BdtPolicyId from pcfUeContext bdtPolicy, exist := pcf_context.PCF_Self().BdtPolicyPool[bdtPolicyId] if !exist { // not found - rsp := pcf_util.GetProblemDetail("Can't find BDTPolicyId related resource", pcf_util.CONTEXT_NOT_FOUND) + rsp := util.GetProblemDetail("Can't find BDTPolicyId related resource", util.CONTEXT_NOT_FOUND) logger.Bdtpolicylog.Warnf(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, bdtPolicy) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, bdtPolicy) } // UpdateBDTPolicy - Update an Individual BDT policy (choose policy data) -func UpdateBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, bdtPolicyId string, request models.BdtPolicyDataPatch) { +func UpdateBDTPolicyContext(httpChannel chan message.HttpResponseMessage, bdtPolicyId string, request models.BdtPolicyDataPatch) { logger.Bdtpolicylog.Traceln("Handle BDT Policy Update") // check BdtPolicyId from pcfUeContext @@ -43,9 +44,9 @@ func UpdateBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, bd bdtPolicy, exist := pcfSelf.BdtPolicyPool[bdtPolicyId] if !exist { // not found - rsp := pcf_util.GetProblemDetail("Can't find BDTPolicyId related resource", pcf_util.CONTEXT_NOT_FOUND) + rsp := util.GetProblemDetail("Can't find BDTPolicyId related resource", util.CONTEXT_NOT_FOUND) logger.Bdtpolicylog.Warnf(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } for _, policy := range bdtPolicy.BdtPolData.TransfPolicies { @@ -64,23 +65,23 @@ func UpdateBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, bd param := Nudr_DataRepository.PolicyDataBdtDataBdtReferenceIdPutParamOpts{ BdtData: optional.NewInterface(bdtData), } - client := pcf_util.GetNudrClient(getDefaultUdrUri(pcfSelf)) + client := util.GetNudrClient(getDefaultUdrUri(pcfSelf)) _, err := client.DefaultApi.PolicyDataBdtDataBdtReferenceIdPut(context.Background(), bdtData.BdtRefId, ¶m) if err != nil { logger.Bdtpolicylog.Warnf("UDR Put BdtDate error[%s]", err.Error()) } logger.Bdtpolicylog.Tracef("BDTPolicyId[%s] has Updated with SelTransPolicyId[%d]", bdtPolicyId, request.SelTransPolicyId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, bdtPolicy) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, bdtPolicy) return } } - rsp := pcf_util.GetProblemDetail(fmt.Sprintf("Can't find TransPolicyId[%d] in TransfPolicies with BDTPolicyId[%s]", request.SelTransPolicyId, bdtPolicyId), pcf_util.CONTEXT_NOT_FOUND) + rsp := util.GetProblemDetail(fmt.Sprintf("Can't find TransPolicyId[%d] in TransfPolicies with BDTPolicyId[%s]", request.SelTransPolicyId, bdtPolicyId), util.CONTEXT_NOT_FOUND) logger.Bdtpolicylog.Warnf(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) } //CreateBDTPolicy - Create a new Individual BDT policy -func CreateBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, request models.BdtReqData) { +func CreateBDTPolicyContext(httpChannel chan message.HttpResponseMessage, request models.BdtReqData) { var rsp models.BdtPolicy logger.Bdtpolicylog.Traceln("Handle BDT Policy Create") @@ -94,13 +95,13 @@ func CreateBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, re Detail: "Can't find any UDR which supported to this PCF", } logger.Bdtpolicylog.Warnf(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } pcfSelf.DefaultUdrUri = udrUri // Query BDT DATA array from UDR - client := pcf_util.GetNudrClient(udrUri) + client := util.GetNudrClient(udrUri) bdtDatas, response, err := client.DefaultApi.PolicyDataBdtDataGet(context.Background()) if err != nil || response == nil || response.StatusCode != http.StatusOK { rsp := models.ProblemDetails{ @@ -108,7 +109,7 @@ func CreateBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, re Detail: "Query to UDR failed", } logger.Bdtpolicylog.Warnf("Query to UDR failed") - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } // TODO: decide BDT Policy from other bdt policy data @@ -146,12 +147,12 @@ func CreateBDTPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, re bdtPolicyId := pcfSelf.AllocBdtPolicyId() pcfSelf.BdtPolicyPool[bdtPolicyId] = rsp - locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_BDTPOLICYCONTROL, bdtPolicyId) + locationHeader := util.GetResourceUri(models.ServiceName_NPCF_BDTPOLICYCONTROL, bdtPolicyId) headers := http.Header{ "Location": {locationHeader}, } logger.Bdtpolicylog.Tracef("BDT Policy Id[%s] Create", bdtPolicyId) - pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, rsp) + message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, rsp) // Update UDR BDT Data(PUT) param := Nudr_DataRepository.PolicyDataBdtDataBdtReferenceIdPutParamOpts{ @@ -170,12 +171,12 @@ func getDefaultUdrUri(context *pcf_context.PCFContext) string { param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NUDR_DR}), } - resp, err := pcf_consumer.SendSearchNFInstances(context.NrfUri, models.NfType_UDR, models.NfType_PCF, param) + resp, err := consumer.SendSearchNFInstances(context.NrfUri, models.NfType_UDR, models.NfType_PCF, param) if err != nil { return "" } for _, nfProfile := range resp.NfInstances { - udruri := pcf_util.SearchNFServiceUri(nfProfile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED) + udruri := util.SearchNFServiceUri(nfProfile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED) if udruri != "" { return udruri } diff --git a/pcf_producer/callback.go b/producer/callback.go similarity index 55% rename from pcf_producer/callback.go rename to producer/callback.go index 4d30ec5..cdcab41 100644 --- a/pcf_producer/callback.go +++ b/producer/callback.go @@ -2,14 +2,14 @@ package pcf_producer import ( "free5gc/lib/openapi/models" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_handler/pcf_message" "net/http" ) -func HandleAmfStatusChangeNotify(httpChannel chan pcf_message.HttpResponseMessage, notification models.AmfStatusChangeNotification) { +func HandleAmfStatusChangeNotify(httpChannel chan message.HttpResponseMessage, notification models.AmfStatusChangeNotification) { logger.CallbackLog.Warnf("[PCF] Handle Amf Status Change Notify is not implemented.") logger.CallbackLog.Debugf("receive AMF status change notification[%+v]", notification) // TODO: handle AMF Status Change Notify - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) } diff --git a/pcf_producer/HandleSmPolicyNotify.go b/producer/handle_sm_policy_notify.go similarity index 82% rename from pcf_producer/HandleSmPolicyNotify.go rename to producer/handle_sm_policy_notify.go index a02fead..0d2f7ce 100644 --- a/pcf_producer/HandleSmPolicyNotify.go +++ b/producer/handle_sm_policy_notify.go @@ -4,35 +4,35 @@ import ( // "context" // "fmt" "free5gc/lib/openapi/models" - // "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_handler/pcf_message" - // "free5gc/src/pcf/pcf_util" + // pcf_context "free5gc/src/pcf/context" + "free5gc/src/pcf/handler/message" + // "free5gc/src/pcf/util" // "github.com/gin-gonic/gin" ) -func HandleSmPolicyNotify(httpChannel chan pcf_message.HttpResponseMessage, supi string, body models.PolicyDataChangeNotification) { +func HandleSmPolicyNotify(httpChannel chan message.HttpResponseMessage, supi string, body models.PolicyDataChangeNotification) { // policyDataChangeNotification := body // var problem models.ProblemDetails // var smPolicyDecision models.SmPolicyDecision // pcfUeContext := pcf_context.PCF_Self().UePool // counter := false - // client := pcf_util.GetNudrClient("https://localhost:29504") + // client := util.GetNudrClient("https://localhost:29504") // UeContext := pcf_context.PCF_Self().UePool // if UeContext[supi] == nil { // problem.Status = 404 // problem.Cause = "CONTEXT_NOT_FOUND" - // pcf_message.SendHttpResponseMessage(httpChannel, nil, 404, problem) + // message.SendHttpResponseMessage(httpChannel, nil, 404, problem) // } // _, resp, err := client.DefaultApi.PolicyDataUesUeIdSmDataGet(context.Background(), supi, nil) // if err != nil { // problem.Status = 404 // problem.Cause = "CONTEXT_NOT_FOUND" - // pcf_message.SendHttpResponseMessage(httpChannel, nil, 404, problem) + // message.SendHttpResponseMessage(httpChannel, nil, 404, problem) // } // if resp.StatusCode == 204 { // UeContext[supi].SmPolicyControlStore = nil // // pcf_producer_callback.CreateSmPolicyNotifyContext(fmt.Sprint(UeContext[supi].SmPolicyControlStore.Context.PduSessionId), "terminate", nil) - // pcf_message.SendHttpResponseMessage(httpChannel, nil, 204, nil) + // message.SendHttpResponseMessage(httpChannel, nil, 204, nil) // } // if resp.StatusCode == 200 { // for key := range pcfUeContext { @@ -61,10 +61,10 @@ func HandleSmPolicyNotify(httpChannel chan pcf_message.HttpResponseMessage, supi // pcfUeContext[key].SmPolicyControlStore.Policy.Offline = smPolicyDecision.Offline // counter = true // } - // pcf_message.SendHttpResponseMessage(httpChannel, nil, 204, gin.H{}) + // message.SendHttpResponseMessage(httpChannel, nil, 204, gin.H{}) // if counter { // // pcf_producer_callback.CreateSmPolicyNotifyContext(fmt.Sprint(UeContext[supi].SmPolicyControlStore.Context.PduSessionId), "update", &smPolicyDecision) - // pcf_message.SendHttpResponseMessage(httpChannel, nil, 204, nil) + // message.SendHttpResponseMessage(httpChannel, nil, 204, nil) // } // } diff --git a/pcf_producer/oam.go b/producer/oam.go similarity index 77% rename from pcf_producer/oam.go rename to producer/oam.go index 93a3bd6..f6c221a 100644 --- a/pcf_producer/oam.go +++ b/producer/oam.go @@ -2,9 +2,9 @@ package pcf_producer import ( "free5gc/lib/openapi/models" + "free5gc/src/pcf/context" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_handler/pcf_message" "net/http" "strconv" ) @@ -22,11 +22,11 @@ type UEAmPolicy struct { type UEAmPolicys []UEAmPolicy -func HandleOAMGetAmPolicy(httpChannel chan pcf_message.HttpResponseMessage, supi string) { +func HandleOAMGetAmPolicy(httpChannel chan message.HttpResponseMessage, supi string) { logger.OamLog.Infof("Handle OAM Get Am Policy") var response UEAmPolicys - pcfSelf := pcf_context.PCF_Self() + pcfSelf := context.PCF_Self() if ue, exists := pcfSelf.UePool[supi]; exists { for _, amPolicy := range ue.AMPolicyData { @@ -44,12 +44,12 @@ func HandleOAMGetAmPolicy(httpChannel chan pcf_message.HttpResponseMessage, supi } response = append(response, ueAmPolicy) } - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, response) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, response) } else { problem := models.ProblemDetails{ Status: http.StatusNotFound, Cause: "CONTEXT_NOT_FOUND", } - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNotFound, problem) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusNotFound, problem) } } diff --git a/pcf_producer/pcf_policyauthorization.go b/producer/policyauthorization.go similarity index 83% rename from pcf_producer/pcf_policyauthorization.go rename to producer/policyauthorization.go index b45e22b..5396dd1 100644 --- a/pcf_producer/pcf_policyauthorization.go +++ b/producer/policyauthorization.go @@ -4,10 +4,10 @@ import ( "context" "fmt" "free5gc/lib/openapi/models" + pcf_context "free5gc/src/pcf/context" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_handler/pcf_message" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/util" "net/http" "strings" "time" @@ -25,7 +25,7 @@ import ( // Invocation of Multimedia Priority Services (TODO) // Support of content versioning (TODO) // PostAppSessions - Creates a new Individual Application Session Context resource -func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, request models.AppSessionContext) { +func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, request models.AppSessionContext) { logger.PolicyAuthorizationlog.Traceln("Handle Create AppSessions") reqData := request.AscReqData pcfSelf := pcf_context.PCF_Self() @@ -33,7 +33,7 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re if reqData.BdtRefId != "" { err := handleBackgroundDataTransferPolicyIndication(pcfSelf, &request) if err != nil { - sendProblemDetail(httpChannel, err.Error(), pcf_util.ERROR_REQUEST_PARAMETERS) + sendProblemDetail(httpChannel, err.Error(), util.ERROR_REQUEST_PARAMETERS) return } appSessionId := fmt.Sprintf("BdtRefId-%s", reqData.BdtRefId) @@ -42,27 +42,27 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re AppSessionContext: &request, } pcfSelf.AppSessionPool[appSessionId] = &data - locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId) + locationHeader := util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId) headers := http.Header{ "Location": {locationHeader}, } logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create", appSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, request) + message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, request) return } if request.AscReqData.UeIpv4 == "" && request.AscReqData.UeIpv6 == "" && request.AscReqData.UeMac == "" { - sendProblemDetail(httpChannel, "Ue UeIpv4 and UeIpv6 and UeMac are all empty", pcf_util.ERROR_REQUEST_PARAMETERS) + sendProblemDetail(httpChannel, "Ue UeIpv4 and UeIpv6 and UeMac are all empty", util.ERROR_REQUEST_PARAMETERS) return } smPolicy, err := pcfSelf.SessionBinding(request.AscReqData) if err != nil { - sendProblemDetail(httpChannel, fmt.Sprintf("Session Binding failed[%s]", err.Error()), pcf_util.PDU_SESSION_NOT_AVAILABLE) + sendProblemDetail(httpChannel, fmt.Sprintf("Session Binding failed[%s]", err.Error()), util.PDU_SESSION_NOT_AVAILABLE) return } ue := smPolicy.PcfUe updateSMpolicy := false - nSuppFeat := pcf_util.GetNegotiateSuppFeat(reqData.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION]) - traffRoutSupp := pcf_util.CheckSuppFeat(nSuppFeat, 1) && pcf_util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 + nSuppFeat := util.GetNegotiateSuppFeat(reqData.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION]) + traffRoutSupp := util.CheckSuppFeat(nSuppFeat, 1) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 relatedPccRuleIds := make(map[string]string) if reqData.MedComponents != nil { @@ -73,22 +73,22 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re // TODO: use specific algorithm instead of default, details in subsclause 7.3.3 of TS 29513 var var5qi int32 = 9 if mediaComponent.MedType != "" { - var5qi = pcf_util.MediaTypeTo5qiMap[mediaComponent.MedType] + var5qi = util.MediaTypeTo5qiMap[mediaComponent.MedType] } if mediaComponent.MedSubComps != nil { for _, mediaSubComponent := range mediaComponent.MedSubComps { flowInfos, err := getFlowInfos(mediaSubComponent) if err != nil { - sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } - pccRule = pcf_util.GetPccRuleByFlowInfos(smPolicy.PolicyDecision.PccRules, flowInfos) + pccRule = util.GetPccRuleByFlowInfos(smPolicy.PolicyDecision.PccRules, flowInfos) if pccRule == nil { - pccRule = pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) // Set QoS Data // TODO: use real arp - qosData := pcf_util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) + qosData := util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) if var5qi <= 4 { // update Qos Data accroding to request BitRate var ul, dl bool @@ -100,15 +100,15 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re } // Set PackfiltId for i := range flowInfos { - flowInfos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + flowInfos[i].PackFiltId = util.GetPackFiltId(smPolicy.PackFiltIdGenarator) smPolicy.PackFiltMapToPccRuleId[flowInfos[i].PackFiltId] = pccRule.PccRuleId smPolicy.PackFiltIdGenarator++ } // Set flowsInfo in Pcc Rule pccRule.FlowInfos = flowInfos // Set Traffic Control Data - tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaSubComponent.FStatus) - pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaSubComponent.FStatus) + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) smPolicy.PccRuleIdGenarator++ maxPrecedence++ } else { @@ -140,22 +140,22 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re continue } else if mediaComponent.AfAppId != "" { // if mediaComponent.AfAppId has value -> find pccRule by reqData.AfAppId, otherwise create a new pcc rule - pccRule = pcf_util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, mediaComponent.AfAppId) + pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, mediaComponent.AfAppId) if pccRule != nil { pccRule.AppId = mediaComponent.AfAppId } } else if reqData.AfAppId != "" { - pccRule = pcf_util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, reqData.AfAppId) + pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, reqData.AfAppId) if pccRule != nil { pccRule.AppId = reqData.AfAppId } } else { - sendProblemDetail(httpChannel, "Media Component needs flows of subComp or afAppId", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, "Media Component needs flows of subComp or afAppId", util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } if pccRule == nil { // create new pcc rule - pccRule = pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) if mediaComponent.AfAppId != "" { pccRule.AppId = mediaComponent.AfAppId } else { @@ -163,7 +163,7 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re } // Set QoS Data // TODO: use real arp - qosData := pcf_util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) + qosData := util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) if var5qi <= 4 { // update Qos Data accroding to request BitRate var ul, dl bool @@ -175,8 +175,8 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re } // Set Traffic Control Data - tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaComponent.FStatus) - pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaComponent.FStatus) + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) smPolicy.PccRuleIdGenarator++ maxPrecedence++ } else { @@ -219,7 +219,7 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re tcData.UpPathChgEvent = reqData.AfRoutReq.UpPathChgSub rule.RefTcData = []string{tcData.TcId} rule.AppReloc = reqData.AfRoutReq.AppReloc - pcf_util.SetPccRuleRelatedData(decision, &rule, &tcData, nil, nil, nil) + util.SetPccRuleRelatedData(decision, &rule, &tcData, nil, nil, nil) updateSMpolicy = true key := fmt.Sprintf("appId-%s-%d", reqData.AfAppId, cnt) relatedPccRuleIds[key] = rule.PccRuleId @@ -229,27 +229,27 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re // Create a Pcc Rule if afappId dose not match any pcc rule if !updateSMpolicy { maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) - pccRule := pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + pccRule := util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) pccRule.AppId = reqData.AfAppId qosData := models.QosData{ - QosId: pcf_util.GetQosId(smPolicy.PccRuleIdGenarator), + QosId: util.GetQosId(smPolicy.PccRuleIdGenarator), DefQosFlowIndication: true, } - tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, "") + tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, "") pccRule.RefTcData = []string{tcData.TcId} pccRule.RefQosData = []string{qosData.QosId} - pcf_util.SetPccRuleRelatedData(decision, pccRule, &tcData, &qosData, nil, nil) + util.SetPccRuleRelatedData(decision, pccRule, &tcData, &qosData, nil, nil) smPolicy.PccRuleIdGenarator++ updateSMpolicy = true key := fmt.Sprintf("appId-%s", reqData.AfAppId) relatedPccRuleIds[key] = pccRule.PccRuleId } } else { - sendProblemDetail(httpChannel, "Traffic routing not supported", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, "Traffic routing not supported", util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } } else { - sendProblemDetail(httpChannel, "AF Request need AfAppId or Media Component to match Service Data Flow", pcf_util.ERROR_REQUEST_PARAMETERS) + sendProblemDetail(httpChannel, "AF Request need AfAppId or Media Component to match Service Data Flow", util.ERROR_REQUEST_PARAMETERS) return } @@ -291,7 +291,7 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re logger.PolicyAuthorizationlog.Warn("AF Event is unknown") continue } - if !pcf_util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { + if !util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { smPolicy.PolicyDecision.PolicyCtrlReqTriggers = append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) updateSMpolicy = true } @@ -301,15 +301,15 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re // Initial provisioning of sponsored connectivity information if reqData.AspId != "" && reqData.SponId != "" { - supp := pcf_util.CheckSuppFeat(nSuppFeat, 2) && pcf_util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 12) // SponsoredConnectivity = 2 in 29514 & SponsoredConnectivity support = 12 in 29512 + supp := util.CheckSuppFeat(nSuppFeat, 2) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 12) // SponsoredConnectivity = 2 in 29514 & SponsoredConnectivity support = 12 in 29512 if !supp { - sendProblemDetail(httpChannel, "Sponsored Connectivity not supported", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, "Sponsored Connectivity not supported", util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } - umId := pcf_util.GetUmId(reqData.AspId, reqData.SponId) + umId := util.GetUmId(reqData.AspId, reqData.SponId) umData, err := extractUmData(umId, eventSubs, reqData.EvSubsc.UsgThres) if err != nil { - sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } err = handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, reqData.AspId, reqData.SponId, reqData.SponStatus, umData, &updateSMpolicy) @@ -365,17 +365,17 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re request.EvsNotif = nil } pcfSelf.AppSessionPool[appSessionId] = &data - locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId) + locationHeader := util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId) headers := http.Header{ "Location": {locationHeader}, } logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create", appSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, request) + message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, request) // Send Notification to SMF if updateSMpolicy { smPolicyId := fmt.Sprintf("%s-%d", ue.Supi, smPolicy.PolicyContext.PduSessionId) notification := models.SmPolicyNotification{ - ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + ResourceUri: util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), SmPolicyDecision: smPolicy.PolicyDecision, } SendSMPolicyUpdateNotification(ue, smPolicyId, notification) @@ -384,14 +384,14 @@ func PostAppSessionsContext(httpChannel chan pcf_message.HttpResponseMessage, re } // DeleteAppSession - Deletes an existing Individual Application Session Context -func DeleteAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string, requset *models.EventsSubscReqData) { +func DeleteAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessionId string, requset *models.EventsSubscReqData) { logger.PolicyAuthorizationlog.Tracef("Handle Del AppSessions, AppSessionId[%s]", appSessionId) pcfSelf := pcf_context.PCF_Self() appSession := pcfSelf.AppSessionPool[appSessionId] if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) return } if requset != nil { @@ -418,10 +418,10 @@ func DeleteAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, a // UsgRep: appSession.AccUsage, // }, // } - // pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, resp) + // message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, resp) // } else { // } - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) delete(pcfSelf.AppSessionPool, appSessionId) @@ -430,7 +430,7 @@ func DeleteAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, a // Notify SMF About Pcc Rule moval smPolicyId := fmt.Sprintf("%s-%d", smPolicy.PcfUe.Supi, smPolicy.PolicyContext.PduSessionId) notification := models.SmPolicyNotification{ - ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + ResourceUri: util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), SmPolicyDecision: smPolicy.PolicyDecision, } SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) @@ -439,27 +439,27 @@ func DeleteAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, a } // GetAppSession - Reads an existing Individual Application Session Context -func GetAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string) { +func GetAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessionId string) { logger.PolicyAuthorizationlog.Tracef("Handle Get AppSessions, AppSessionId[%s]", appSessionId) pcfSelf := pcf_context.PCF_Self() appSession := pcfSelf.AppSessionPool[appSessionId] if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) return } logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Get", appSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appSession.AppSessionContext) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appSession.AppSessionContext) } // ModAppSession - Modifies an existing Individual Application Session Context -func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string, request models.AppSessionContextUpdateData) { +func ModAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessionId string, request models.AppSessionContextUpdateData) { logger.PolicyAuthorizationlog.Tracef("Handle Modi AppSessions, AppSessionId[%s]", appSessionId) pcfSelf := pcf_context.PCF_Self() appSession := pcfSelf.AppSessionPool[appSessionId] if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) return } appContext := appSession.AppSessionContext @@ -467,20 +467,20 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS appContext.AscReqData.BdtRefId = request.BdtRefId err := handleBackgroundDataTransferPolicyIndication(pcfSelf, appContext) if err != nil { - sendProblemDetail(httpChannel, err.Error(), pcf_util.ERROR_REQUEST_PARAMETERS) + sendProblemDetail(httpChannel, err.Error(), util.ERROR_REQUEST_PARAMETERS) return } logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Updated", appSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appContext) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appContext) return } smPolicy := appSession.SmPolicyData if smPolicy == nil { - sendProblemDetail(httpChannel, "Can't find related PDU Session", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, "Can't find related PDU Session", util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } - traffRoutSupp := pcf_util.CheckSuppFeat(appContext.AscRespData.SuppFeat, 1) && pcf_util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 + traffRoutSupp := util.CheckSuppFeat(appContext.AscRespData.SuppFeat, 1) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 relatedPccRuleIds := make(map[string]string) // Event Subscription eventSubs := make(map[models.AfEvent]models.AfNotifMethod) @@ -499,7 +499,7 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS // TODO: use specific algorithm instead of default, details in subsclause 7.3.3 of TS 29513 var var5qi int32 = 9 if mediaComponent.MedType != "" { - var5qi = pcf_util.MediaTypeTo5qiMap[mediaComponent.MedType] + var5qi = util.MediaTypeTo5qiMap[mediaComponent.MedType] } qosMediaComp := models.MediaComponent{ MarBwDl: mediaComponent.MarBwDl, @@ -512,15 +512,15 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS mediaSubComponent := models.MediaSubComponent(mediaSubComponentRm) flowInfos, err := getFlowInfos(mediaSubComponent) if err != nil { - sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } - pccRule = pcf_util.GetPccRuleByFlowInfos(smPolicy.PolicyDecision.PccRules, flowInfos) + pccRule = util.GetPccRuleByFlowInfos(smPolicy.PolicyDecision.PccRules, flowInfos) if pccRule == nil { - pccRule = pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) // Set QoS Data // TODO: use real arp - qosData := pcf_util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) + qosData := util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) if var5qi <= 4 { // update Qos Data accroding to request BitRate var ul, dl bool @@ -533,15 +533,15 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS } // Set PackfiltId for i := range flowInfos { - flowInfos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + flowInfos[i].PackFiltId = util.GetPackFiltId(smPolicy.PackFiltIdGenarator) smPolicy.PackFiltMapToPccRuleId[flowInfos[i].PackFiltId] = pccRule.PccRuleId smPolicy.PackFiltIdGenarator++ } // Set flowsInfo in Pcc Rule pccRule.FlowInfos = flowInfos // Set Traffic Control Data - tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaSubComponent.FStatus) - pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaSubComponent.FStatus) + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) smPolicy.PccRuleIdGenarator++ maxPrecedence++ } else { @@ -573,22 +573,22 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS continue } else if mediaComponent.AfAppId != "" { // if mediaComponent.AfAppId has value -> find pccRule by reqData.AfAppId, otherwise create a new pcc rule - pccRule = pcf_util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, mediaComponent.AfAppId) + pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, mediaComponent.AfAppId) if pccRule != nil { pccRule.AppId = mediaComponent.AfAppId } } else if request.AfAppId != "" { - pccRule = pcf_util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, request.AfAppId) + pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, request.AfAppId) if pccRule != nil { pccRule.AppId = request.AfAppId } } else { - sendProblemDetail(httpChannel, "Media Component needs flows of subComp or afAppId", pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, "Media Component needs flows of subComp or afAppId", util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } if pccRule == nil { // create new pcc rule - pccRule = pcf_util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) + pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) if mediaComponent.AfAppId != "" { pccRule.AppId = mediaComponent.AfAppId } else { @@ -596,7 +596,7 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS } // Set QoS Data // TODO: use real arp - qosData := pcf_util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) + qosData := util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) if var5qi <= 4 { // update Qos Data accroding to request BitRate var ul, dl bool @@ -608,8 +608,8 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS } // Set Traffic Control Data - tcData := pcf_util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaComponent.FStatus) - pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaComponent.FStatus) + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) smPolicy.PccRuleIdGenarator++ maxPrecedence++ } else { @@ -681,7 +681,7 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS logger.PolicyAuthorizationlog.Warn("AF Event is unknown") continue } - if !pcf_util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { + if !util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { smPolicy.PolicyDecision.PolicyCtrlReqTriggers = append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) updateSMpolicy = true } @@ -709,10 +709,10 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS // Moification provisioning of sponsored connectivity information if request.AspId != "" && request.SponId != "" { - umId := pcf_util.GetUmId(request.AspId, request.SponId) + umId := util.GetUmId(request.AspId, request.SponId) umData, err := extractUmData(umId, eventSubs, threshRmToThresh(request.EvSubsc.UsgThres)) if err != nil { - sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } err = handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, request.AspId, request.SponId, request.SponStatus, umData, &updateSMpolicy) @@ -758,7 +758,7 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS // TODO: MPS Sevice logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Updated", appSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appContext) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appContext) smPolicy.ArrangeExistEventSubscription() @@ -766,7 +766,7 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS if updateSMpolicy { smPolicyId := fmt.Sprintf("%s-%d", smPolicy.PcfUe.Supi, smPolicy.PolicyContext.PduSessionId) notification := models.SmPolicyNotification{ - ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + ResourceUri: util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), SmPolicyDecision: smPolicy.PolicyDecision, } SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) @@ -776,14 +776,14 @@ func ModAppSessionContext(httpChannel chan pcf_message.HttpResponseMessage, appS } // DeleteEventsSubsc - deletes the Events Subscription subresource -func DeleteEventsSubscContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string) { +func DeleteEventsSubscContext(httpChannel chan message.HttpResponseMessage, appSessionId string) { logger.PolicyAuthorizationlog.Tracef("Handle Del AppSessions Events Subsc, AppSessionId[%s]", appSessionId) pcfSelf := pcf_context.PCF_Self() appSession := pcfSelf.AppSessionPool[appSessionId] if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) return } appSession.Events = nil @@ -794,14 +794,14 @@ func DeleteEventsSubscContext(httpChannel chan pcf_message.HttpResponseMessage, changed := appSession.SmPolicyData.ArrangeExistEventSubscription() logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Del Events Subsc success", appSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) smPolicy := appSession.SmPolicyData // Send Notification to SMF if changed { smPolicyId := fmt.Sprintf("%s-%d", smPolicy.PcfUe.Supi, smPolicy.PolicyContext.PduSessionId) notification := models.SmPolicyNotification{ - ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + ResourceUri: util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), SmPolicyDecision: smPolicy.PolicyDecision, } SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) @@ -810,14 +810,14 @@ func DeleteEventsSubscContext(httpChannel chan pcf_message.HttpResponseMessage, } // UpdateEventsSubsc - creates or modifies an Events Subscription subresource -func UpdateEventsSubscContext(httpChannel chan pcf_message.HttpResponseMessage, appSessionId string, request models.EventsSubscReqData) { +func UpdateEventsSubscContext(httpChannel chan message.HttpResponseMessage, appSessionId string, request models.EventsSubscReqData) { logger.PolicyAuthorizationlog.Tracef("Handle Put AppSessions Events Subsc, AppSessionId[%s]", appSessionId) pcfSelf := pcf_context.PCF_Self() appSession := pcfSelf.AppSessionPool[appSessionId] if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", pcf_util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) return } smPolicy := appSession.SmPolicyData @@ -864,7 +864,7 @@ func UpdateEventsSubscContext(httpChannel chan pcf_message.HttpResponseMessage, logger.PolicyAuthorizationlog.Warn("AF Event is unknown") continue } - if !pcf_util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { + if !util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { smPolicy.PolicyDecision.PolicyCtrlReqTriggers = append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) updataSmPolicy = true } @@ -920,18 +920,18 @@ func UpdateEventsSubscContext(httpChannel chan pcf_message.HttpResponseMessage, resp.EvsNotif = appContext.EvsNotif if created { - locationHeader := fmt.Sprintf("%s/events-subscription", pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId)) + locationHeader := fmt.Sprintf("%s/events-subscription", util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId)) headers := http.Header{ "Location": {locationHeader}, } logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create Subscription", appSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, resp) + message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, resp) } else if resp.EvsNotif != nil { logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Modify Subscription", appSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, resp) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, resp) } else { logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Modify Subscription", appSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, resp) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, resp) } changed := appSession.SmPolicyData.ArrangeExistEventSubscription() @@ -940,7 +940,7 @@ func UpdateEventsSubscContext(httpChannel chan pcf_message.HttpResponseMessage, if updataSmPolicy || changed { smPolicyId := fmt.Sprintf("%s-%d", smPolicy.PcfUe.Supi, smPolicy.PolicyContext.PduSessionId) notification := models.SmPolicyNotification{ - ResourceUri: pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), + ResourceUri: util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), SmPolicyDecision: smPolicy.PolicyDecision, } SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) @@ -956,8 +956,8 @@ func SendAppSessionEventNotification(appSession *pcf_context.AppSessionData, req } uri := appSession.EventUri if uri != "" { - request.EvSubsUri = fmt.Sprintf("%s/events-subscription", pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSession.AppSessionId)) - client := pcf_util.GetNpcfPolicyAuthorizationCallbackClient() + request.EvSubsUri = fmt.Sprintf("%s/events-subscription", util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSession.AppSessionId)) + client := util.GetNpcfPolicyAuthorizationCallbackClient() httpResponse, err := client.PolicyAuthorizationEventNotificationApi.PolicyAuthorizationEventNotification(context.Background(), uri, request) if err != nil { if httpResponse != nil { @@ -986,8 +986,8 @@ func SendAppSessionTermination(appSession *pcf_context.AppSessionData, request m } uri := appSession.AppSessionContext.AscReqData.NotifUri if uri != "" { - request.ResUri = pcf_util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSession.AppSessionId) - client := pcf_util.GetNpcfPolicyAuthorizationCallbackClient() + request.ResUri = util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSession.AppSessionId) + client := util.GetNpcfPolicyAuthorizationCallbackClient() httpResponse, err := client.PolicyAuthorizationTerminateRequestApi.PolicyAuthorizationTerminateRequest(context.Background(), uri, request) if err != nil { if httpResponse != nil { @@ -1013,20 +1013,20 @@ func handleBackgroundDataTransferPolicyIndication(pcfSelf *pcf_context.PCFContex req := appContext.AscReqData respData := models.AppSessionContextRespData{ ServAuthInfo: models.ServAuthInfo_NOT_KNOWN, - SuppFeat: pcf_util.GetNegotiateSuppFeat(req.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION]), + SuppFeat: util.GetNegotiateSuppFeat(req.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION]), } - client := pcf_util.GetNudrClient(getDefaultUdrUri(pcfSelf)) + client := util.GetNudrClient(getDefaultUdrUri(pcfSelf)) bdtData, resp, err1 := client.DefaultApi.PolicyDataBdtDataBdtReferenceIdGet(context.Background(), req.BdtRefId) if err1 != nil { return fmt.Errorf("UDR Get BdtDate error[%s]", err1.Error()) } else if resp == nil || resp.StatusCode != http.StatusOK { return fmt.Errorf("UDR Get BdtDate error") } else { - startTime, err1 := time.Parse(pcf_util.TimeFormat, bdtData.TransPolicy.RecTimeInt.StartTime) + startTime, err1 := time.Parse(util.TimeFormat, bdtData.TransPolicy.RecTimeInt.StartTime) if err1 != nil { return err1 } - stopTime, err1 := time.Parse(pcf_util.TimeFormat, bdtData.TransPolicy.RecTimeInt.StopTime) + stopTime, err1 := time.Parse(util.TimeFormat, bdtData.TransPolicy.RecTimeInt.StopTime) if err1 != nil { return err1 } @@ -1044,7 +1044,7 @@ func handleBackgroundDataTransferPolicyIndication(pcfSelf *pcf_context.PCFContex func handleSponsoredConnectivityInformation(smPolicy *pcf_context.UeSmPolicyData, relatedPccRuleIds map[string]string, aspId, sponId string, sponStatus models.SponsoringStatus, umData *models.UsageMonitoringData, updateSMpolicy *bool) (err error) { if sponStatus == models.SponsoringStatus_DISABLED { logger.PolicyAuthorizationlog.Debugf("Sponsored Connectivity is disabled by AF") - umId := pcf_util.GetUmId(aspId, sponId) + umId := util.GetUmId(aspId, sponId) for _, pccRuleId := range relatedPccRuleIds { pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] for _, chgId := range pccRule.RefChgData { @@ -1069,14 +1069,14 @@ func handleSponsoredConnectivityInformation(smPolicy *pcf_context.UeSmPolicyData } else { if umData != nil { - supp := pcf_util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 5) // UMC support = 5 in 29512 + supp := util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 5) // UMC support = 5 in 29512 if !supp { err = fmt.Errorf("Usage Monitor Control is not supported in SMF") return } } chgIdUsed := false - chgId := pcf_util.GetChgId(smPolicy.ChargingIdGenarator) + chgId := util.GetChgId(smPolicy.ChargingIdGenarator) for _, pccRuleId := range relatedPccRuleIds { pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] chgData := models.ChargingData{ @@ -1098,7 +1098,7 @@ func handleSponsoredConnectivityInformation(smPolicy *pcf_context.UeSmPolicyData if umData != nil { pccRule.RefUmData = []string{umData.UmId} } - pcf_util.SetPccRuleRelatedData(smPolicy.PolicyDecision, &pccRule, nil, nil, &chgData, umData) + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, &pccRule, nil, nil, &chgData, umData) *updateSMpolicy = true } if chgIdUsed { @@ -1474,14 +1474,14 @@ func extractUmData(umId string, eventSubs map[models.AfEvent]models.AfNotifMetho return nil, fmt.Errorf("UsageThreshold is nil in USAGE REPORT Subscription") } else { - tmp := pcf_util.CreateUmData(umId, *threshold) + tmp := util.CreateUmData(umId, *threshold) umData = &tmp } } return } -func modifyRemainBitRate(httpChannel chan pcf_message.HttpResponseMessage, smPolicy *pcf_context.UeSmPolicyData, qosData *models.QosData, ulExist, dlExist bool) (err error) { +func modifyRemainBitRate(httpChannel chan message.HttpResponseMessage, smPolicy *pcf_context.UeSmPolicyData, qosData *models.QosData, ulExist, dlExist bool) (err error) { // if request GBR == 0, qos GBR = MBR // if request GBR > remain GBR, qos GBR = remain GBR if ulExist { @@ -1495,7 +1495,7 @@ func modifyRemainBitRate(httpChannel chan pcf_message.HttpResponseMessage, smPol } else { err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.GbrUl) if err != nil { - sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } } @@ -1513,7 +1513,7 @@ func modifyRemainBitRate(httpChannel chan pcf_message.HttpResponseMessage, smPol if err != nil { // if Policy failed, revert remain GBR to original GBR pcf_context.IncreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.GbrUl) - sendProblemDetail(httpChannel, err.Error(), pcf_util.REQUESTED_SERVICE_NOT_AUTHORIZED) + sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } } @@ -1564,8 +1564,8 @@ func reverseStringMap(srcMap map[string]string) map[string]string { return reverseMap } -func sendProblemDetail(httpChannel chan pcf_message.HttpResponseMessage, errDetail, errCause string) { - rsp := pcf_util.GetProblemDetail(errDetail, errCause) +func sendProblemDetail(httpChannel chan message.HttpResponseMessage, errDetail, errCause string) { + rsp := util.GetProblemDetail(errDetail, errCause) logger.PolicyAuthorizationlog.Error(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) } diff --git a/pcf_producer/pcf_smpolicy.go b/producer/smpolicy.go similarity index 87% rename from pcf_producer/pcf_smpolicy.go rename to producer/smpolicy.go index 9d498ff..ab3280c 100644 --- a/pcf_producer/pcf_smpolicy.go +++ b/producer/smpolicy.go @@ -3,12 +3,12 @@ package pcf_producer import ( "context" "fmt" - "free5gc/lib/Nudr_DataRepository" + "free5gc/lib/openapi/Nudr_DataRepository" "free5gc/lib/openapi/models" + pcf_context "free5gc/src/pcf/context" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_handler/pcf_message" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/util" "net/http" "strconv" "strings" @@ -17,39 +17,39 @@ import ( ) // SmPoliciesPost - -func CreateSmPolicy(httpChannel chan pcf_message.HttpResponseMessage, request models.SmPolicyContextData) { +func CreateSmPolicy(httpChannel chan message.HttpResponseMessage, request models.SmPolicyContextData) { var err error logger.SMpolicylog.Tracef("Handle Create SM Policy Request") pcfSelf := pcf_context.PCF_Self() ue := pcfSelf.UePool[request.Supi] if ue == nil { - rsp := pcf_util.GetProblemDetail("Supi is not supported in PCF", pcf_util.USER_UNKNOWN) + rsp := util.GetProblemDetail("Supi is not supported in PCF", util.USER_UNKNOWN) logger.SMpolicylog.Warnf("Supi[%s] is not supported in PCF", request.Supi) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) } udrUri := getUdrUri(ue) if udrUri == "" { - rsp := pcf_util.GetProblemDetail("Can't find corresponding UDR with UE", pcf_util.USER_UNKNOWN) + rsp := util.GetProblemDetail("Can't find corresponding UDR with UE", util.USER_UNKNOWN) logger.SMpolicylog.Warnf("Can't find corresponding UDR with UE[%s]", ue.Supi) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } var smData models.SmPolicyData smPolicyId := fmt.Sprintf("%s-%d", ue.Supi, request.PduSessionId) smPolicyData := ue.SmPolicyData[smPolicyId] if smPolicyData == nil || smPolicyData.SmPolicyData == nil { - client := pcf_util.GetNudrClient(udrUri) + client := util.GetNudrClient(udrUri) param := Nudr_DataRepository.PolicyDataUesUeIdSmDataGetParamOpts{ - Snssai: optional.NewInterface(pcf_util.MarshToJsonString(*request.SliceInfo)), + Snssai: optional.NewInterface(util.MarshToJsonString(*request.SliceInfo)), Dnn: optional.NewString(request.Dnn), } var response *http.Response smData, response, err = client.DefaultApi.PolicyDataUesUeIdSmDataGet(context.Background(), ue.Supi, ¶m) if err != nil || response == nil || response.StatusCode != http.StatusOK { - rsp := pcf_util.GetProblemDetail("Can't find UE SM Policy Data in UDR", pcf_util.USER_UNKNOWN) + rsp := util.GetProblemDetail("Can't find UE SM Policy Data in UDR", util.USER_UNKNOWN) logger.SMpolicylog.Warnf("Can't find UE[%s] SM Policy Data in UDR", ue.Supi) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return // logger.SMpolicylog.Warnln("Nudr Query failed [%s]", err.Error()) } @@ -59,9 +59,9 @@ func CreateSmPolicy(httpChannel chan pcf_message.HttpResponseMessage, request mo } amPolicy := ue.FindAMPolicy(request.AccessType, request.ServingNetwork) if amPolicy == nil { - rsp := pcf_util.GetProblemDetail("Can't find corresponding AM Policy", pcf_util.POLICY_CONTEXT_DENIED) + rsp := util.GetProblemDetail("Can't find corresponding AM Policy", util.POLICY_CONTEXT_DENIED) logger.SMpolicylog.Warnf("Can't find corresponding AM Policy") - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } // TODO: check service restrict @@ -98,7 +98,7 @@ func CreateSmPolicy(httpChannel chan pcf_message.HttpResponseMessage, request mo } decision.SessRules[SessRuleId] = sessRule // TODO: See how UDR used - dnnData := pcf_util.GetSMPolicyDnnData(smData, request.SliceInfo, request.Dnn) + dnnData := util.GetSMPolicyDnnData(smData, request.SliceInfo, request.Dnn) if dnnData != nil { decision.Online = dnnData.Online decision.Offline = dnnData.Offline @@ -129,29 +129,29 @@ func CreateSmPolicy(httpChannel chan pcf_message.HttpResponseMessage, request mo decision.Online = request.Online decision.Offline = request.Offline } - decision.SuppFeat = pcf_util.GetNegotiateSuppFeat(request.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_SMPOLICYCONTROL]) + decision.SuppFeat = util.GetNegotiateSuppFeat(request.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_SMPOLICYCONTROL]) decision.QosFlowUsage = request.QosFlowUsage // TODO: Trigger about UMC, ADC, NetLoc,... - decision.PolicyCtrlReqTriggers = pcf_util.PolicyControlReqTrigToArray(0x40780f) + decision.PolicyCtrlReqTriggers = util.PolicyControlReqTrigToArray(0x40780f) smPolicyData.PolicyDecision = &decision // TODO: PCC rule, PraInfo ... - locationHeader := pcf_util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId) + locationHeader := util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId) headers := http.Header{ "Location": {locationHeader}, } logger.SMpolicylog.Tracef("SMPolicy PduSessionId[%d] Create", request.PduSessionId) - pcf_message.SendHttpResponseMessage(httpChannel, headers, 201, decision) + message.SendHttpResponseMessage(httpChannel, headers, 201, decision) } // SmPoliciesSmPolicyIdDeletePost - -func DeleteSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smPolicyId string) { +func DeleteSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolicyId string) { logger.AMpolicylog.Traceln("Handle SM Policy Delete") ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyId) if ue == nil || ue.SmPolicyData[smPolicyId] == nil { - rsp := pcf_util.GetProblemDetail("smPolicyId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) + rsp := util.GetProblemDetail("smPolicyId not found in PCF", util.CONTEXT_NOT_FOUND) logger.SMpolicylog.Warnf(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } @@ -161,7 +161,7 @@ func DeleteSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smP // Unsubscrice UDR delete(ue.SmPolicyData, smPolicyId) logger.SMpolicylog.Tracef("SMPolicy SmPolicyId[%s] DELETE", smPolicyId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) // Release related App Session terminationInfo := models.TerminationInfo{ @@ -179,14 +179,14 @@ func DeleteSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smP } // SmPoliciesSmPolicyIdGet - -func GetSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smPolicyId string) { +func GetSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolicyId string) { logger.SMpolicylog.Traceln("Handle GET SM Policy Request") ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyId) if ue == nil || ue.SmPolicyData[smPolicyId] == nil { - rsp := pcf_util.GetProblemDetail("smPolicyId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) + rsp := util.GetProblemDetail("smPolicyId not found in PCF", util.CONTEXT_NOT_FOUND) logger.SMpolicylog.Warnf(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } smPolicyData := ue.SmPolicyData[smPolicyId] @@ -195,19 +195,19 @@ func GetSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smPoli Context: smPolicyData.PolicyContext, } logger.SMpolicylog.Tracef("SMPolicy SmPolicyId[%s] GET", smPolicyId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) } // SmPoliciesSmPolicyIdUpdatePost - -func UpdateSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smPolicyId string, request models.SmPolicyUpdateContextData) { +func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolicyId string, request models.SmPolicyUpdateContextData) { logger.SMpolicylog.Traceln("Handle SM Policy Update") ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyId) if ue == nil || ue.SmPolicyData[smPolicyId] == nil { - rsp := pcf_util.GetProblemDetail("smPolicyId not found in PCF", pcf_util.CONTEXT_NOT_FOUND) + rsp := util.GetProblemDetail("smPolicyId not found in PCF", util.CONTEXT_NOT_FOUND) logger.SMpolicylog.Warnf(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } smPolicy := ue.SmPolicyData[smPolicyId] @@ -249,25 +249,25 @@ func UpdateSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smP } // TODO: Packet Filters are covered by outstanding pcc rule id := smPolicy.PccRuleIdGenarator - infos := pcf_util.ConvertPacketInfoToFlowInformation(req.PackFiltInfo) + infos := util.ConvertPacketInfoToFlowInformation(req.PackFiltInfo) // Set PackFiltId for i := range infos { - infos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + infos[i].PackFiltId = util.GetPackFiltId(smPolicy.PackFiltIdGenarator) smPolicy.PackFiltIdGenarator++ } - pccRule := pcf_util.CreatePccRule(id, req.Precedence, infos, false) + pccRule := util.CreatePccRule(id, req.Precedence, infos, false) // Add Traffic control Data - tcData := pcf_util.CreateTcData(id, "") + tcData := util.CreateTcData(id, "") // TODO: ARP use real Data - qosData := pcf_util.CreateQosData(id, int32(req.ReqQos.Var5qi), 15) + qosData := util.CreateQosData(id, int32(req.ReqQos.Var5qi), 15) // TODO: Set MBR var err error // Set GBR qosData.GbrDl, qosData.GbrUl, err = smPolicy.DecreaseRemainGBR(req.ReqQos) if err != nil { - rsp := pcf_util.GetProblemDetail(err.Error(), pcf_util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) + rsp := util.GetProblemDetail(err.Error(), util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) logger.SMpolicylog.Warnf(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } if qosData.GbrDl != "" { @@ -276,7 +276,7 @@ func UpdateSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smP if qosData.GbrUl != "" { logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then UL GBR remain[%.2f Kbps]", smPolicyContext.Dnn, qosData.GbrUl, *smPolicy.RemainGbrUL) } - pcf_util.SetPccRuleRelatedData(smPolicyDecision, pccRule, &tcData, &qosData, nil, nil) + util.SetPccRuleRelatedData(smPolicyDecision, pccRule, &tcData, &qosData, nil, nil) // link Packet filters to PccRule for _, info := range infos { smPolicy.PackFiltMapToPccRuleId[info.PackFiltId] = pccRule.PccRuleId @@ -310,9 +310,9 @@ func UpdateSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smP if err != nil { smPolicy.RemainGbrDL = origDl smPolicy.RemainGbrUL = origUl - rsp := pcf_util.GetProblemDetail(err.Error(), pcf_util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) + rsp := util.GetProblemDetail(err.Error(), util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) logger.SMpolicylog.Warnf(rsp.Detail) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } qosData.Var5qi = req.ReqQos.Var5qi @@ -330,12 +330,12 @@ func UpdateSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smP break } } - infos := pcf_util.ConvertPacketInfoToFlowInformation(req.PackFiltInfo) + infos := util.ConvertPacketInfoToFlowInformation(req.PackFiltInfo) switch req.RuleOp { case models.RuleOperation_MODIFY_PCC_RULE_AND_ADD_PACKET_FILTERS: // Set PackFiltId for i := range infos { - infos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + infos[i].PackFiltId = util.GetPackFiltId(smPolicy.PackFiltIdGenarator) smPolicy.PackFiltMapToPccRuleId[infos[i].PackFiltId] = req.PccRuleId smPolicy.PackFiltIdGenarator++ } @@ -347,7 +347,7 @@ func UpdateSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smP } // Set PackFiltId for i := range infos { - infos[i].PackFiltId = pcf_util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + infos[i].PackFiltId = util.GetPackFiltId(smPolicy.PackFiltIdGenarator) smPolicy.PackFiltMapToPccRuleId[infos[i].PackFiltId] = req.PccRuleId smPolicy.PackFiltIdGenarator++ } @@ -551,13 +551,13 @@ func UpdateSmPolicyContext(httpChannel chan pcf_message.HttpResponseMessage, smP } if errCause != "" { - rsp := pcf_util.GetProblemDetail(errCause, pcf_util.ERROR_TRIGGER_EVENT) + rsp := util.GetProblemDetail(errCause, util.ERROR_TRIGGER_EVENT) logger.SMpolicylog.Warnf(errCause) - pcf_message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) return } logger.SMpolicylog.Tracef("SMPolicy SmPolicyId[%s] Update", smPolicyId) - pcf_message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *smPolicyDecision) + message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *smPolicyDecision) } @@ -729,7 +729,7 @@ func SendSMPolicyUpdateNotification(ue *pcf_context.UeContext, smPolId string, r logger.SMpolicylog.Warnf("SM Policy Update Notification Error[Can't find smPolId[%s] in UE(%s)]", smPolId, ue.Supi) return } - client := pcf_util.GetNpcfSMPolicyCallbackClient() + client := util.GetNpcfSMPolicyCallbackClient() uri := smPolicyData.PolicyContext.NotificationUri if uri != "" { _, httpResponse, err := client.DefaultCallbackApi.SmPolicyUpdateNotification(context.Background(), uri, request) @@ -764,7 +764,7 @@ func SendSMPolicyTerminationRequestNotification(ue *pcf_context.UeContext, smPol logger.SMpolicylog.Warnf("SM Policy Update Notification Error[Can't find smPolId[%s] in UE(%s)]", smPolId, ue.Supi) return } - client := pcf_util.GetNpcfSMPolicyCallbackClient() + client := util.GetNpcfSMPolicyCallbackClient() uri := smPolicyData.PolicyContext.NotificationUri if uri != "" { rsp, err := client.DefaultCallbackApi.SmPolicyControlTerminationRequestNotification(context.Background(), uri, request) diff --git a/pcf_service/pcf_init.go b/service/init.go similarity index 69% rename from pcf_service/pcf_init.go rename to service/init.go index 968ebab..0597c44 100644 --- a/pcf_service/pcf_init.go +++ b/service/init.go @@ -1,29 +1,30 @@ -package pcf_service +package service import ( "bufio" "fmt" - "github.com/gin-contrib/cors" - "free5gc/lib/Nnrf_NFDiscovery" "free5gc/lib/http2_util" + "free5gc/lib/openapi/Nnrf_NFDiscovery" "free5gc/lib/openapi/models" "free5gc/lib/path_util" "free5gc/src/app" - "free5gc/src/pcf/AMPolicy" - "free5gc/src/pcf/BDTPolicy" - "free5gc/src/pcf/HttpCallback" - "free5gc/src/pcf/OAM" - "free5gc/src/pcf/PolicyAuthorization" - "free5gc/src/pcf/SMPolicy" - "free5gc/src/pcf/UEPolicy" + "free5gc/src/pcf/ampolicy" + "free5gc/src/pcf/bdtpolicy" + "free5gc/src/pcf/consumer" + "free5gc/src/pcf/context" + "free5gc/src/pcf/handler" + "free5gc/src/pcf/httpcallback" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_consumer" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_handler" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/oam" + "free5gc/src/pcf/policyauthorization" + "free5gc/src/pcf/smpolicy" + "free5gc/src/pcf/uepolicy" + "free5gc/src/pcf/util" "os/exec" "sync" + "github.com/gin-contrib/cors" + "free5gc/src/pcf/factory" "github.com/antihax/optional" @@ -105,13 +106,13 @@ func (pcf *PCF) Start() { initLog.Infoln("Server started") router := gin.Default() - BDTPolicy.AddService(router) - SMPolicy.AddService(router) - AMPolicy.AddService(router) - UEPolicy.AddService(router) - PolicyAuthorization.AddService(router) - Npcf_Callback.AddService(router) - Npcf_OAM.AddService(router) + bdtpolicy.AddService(router) + smpolicy.AddService(router) + ampolicy.AddService(router) + uepolicy.AddService(router) + policyauthorization.AddService(router) + httpcallback.AddService(router) + oam.AddService(router) router.Use(cors.New(cors.Config{ AllowMethods: []string{"GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE"}, @@ -122,28 +123,28 @@ func (pcf *PCF) Start() { MaxAge: 86400, })) - self := pcf_context.PCF_Self() - pcf_util.InitpcfContext(self) + self := context.PCF_Self() + util.InitpcfContext(self) addr := fmt.Sprintf("%s:%d", self.HttpIPv4Address, self.HttpIpv4Port) - profile, err := pcf_consumer.BuildNFInstance(self) + profile, err := consumer.BuildNFInstance(self) if err != nil { initLog.Error("Build PCF Profile Error") } - _, self.NfId, err = pcf_consumer.SendRegisterNFInstance(self.NrfUri, self.NfId, profile) + _, self.NfId, err = consumer.SendRegisterNFInstance(self.NrfUri, self.NfId, profile) if err != nil { initLog.Errorf("PCF register to NRF Error[%s]", err.Error()) } // subscribe to all Amfs' status change - amfInfos := pcf_consumer.SearchAvailableAMFs(self.NrfUri, models.ServiceName_NAMF_COMM) + amfInfos := consumer.SearchAvailableAMFs(self.NrfUri, models.ServiceName_NAMF_COMM) for _, amfInfo := range amfInfos { - guamiList := pcf_util.GetNotSubscribedGuamis(amfInfo.GuamiList) + guamiList := util.GetNotSubscribedGuamis(amfInfo.GuamiList) if len(guamiList) == 0 { continue } - problemDetails, err := pcf_consumer.AmfStatusChangeSubscribe(amfInfo) + problemDetails, err := consumer.AmfStatusChangeSubscribe(amfInfo) if problemDetails != nil { logger.InitLog.Warnf("AMF status subscribe Failed[%+v]", problemDetails) } else if err != nil { @@ -153,13 +154,13 @@ func (pcf *PCF) Start() { // TODO: subscribe NRF NFstatus - go pcf_handler.Handle() + go handler.Handle() param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NUDR_DR}), } - resp, err := pcf_consumer.SendSearchNFInstances(self.NrfUri, models.NfType_UDR, models.NfType_PCF, param) + resp, err := consumer.SendSearchNFInstances(self.NrfUri, models.NfType_UDR, models.NfType_PCF, param) for _, nfProfile := range resp.NfInstances { - udruri := pcf_util.SearchNFServiceUri(nfProfile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED) + udruri := util.SearchNFServiceUri(nfProfile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED) if udruri != "" { self.DefaultUdrUri = udruri break @@ -168,11 +169,25 @@ func (pcf *PCF) Start() { if err != nil { initLog.Errorln(err) } - server, err := http2_util.NewServer(addr, pcf_util.PCF_LOG_PATH, router) - if err == nil && server != nil { - initLog.Infoln(server.ListenAndServeTLS(pcf_util.PCF_PEM_PATH, pcf_util.PCF_KEY_PATH)) - } else { - initLog.Fatalf("Initialize http2 server failed: %+v", err) + server, err := http2_util.NewServer(addr, util.PCF_LOG_PATH, router) + if server == nil { + initLog.Errorln("Initialize HTTP server failed: %+v", err) + return + } + + if err != nil { + initLog.Warnln("Initialize HTTP server: +%v", err) + } + + serverScheme := factory.PcfConfig.Configuration.Sbi.Scheme + if serverScheme == "http" { + err = server.ListenAndServe() + } else if serverScheme == "https" { + err = server.ListenAndServeTLS(util.PCF_PEM_PATH, util.PCF_KEY_PATH) + } + + if err != nil { + initLog.Fatalln("HTTP server setup failed: %+v", err) } } diff --git a/SMPolicy/api_default.go b/smpolicy/api_default.go similarity index 72% rename from SMPolicy/api_default.go rename to smpolicy/api_default.go index a1698ff..abe0b2f 100644 --- a/SMPolicy/api_default.go +++ b/smpolicy/api_default.go @@ -7,14 +7,14 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package SMPolicy +package smpolicy import ( "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" + "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_handler/pcf_message" - "free5gc/src/pcf/pcf_util" + "free5gc/src/pcf/util" "github.com/gin-gonic/gin" ) @@ -25,22 +25,22 @@ func SmPoliciesPost(c *gin.Context) { var smPolicyContextData models.SmPolicyContextData err := c.ShouldBindJSON(&smPolicyContextData) if err != nil { - rsp := pcf_util.GetProblemDetail("Malformed request syntax", pcf_util.ERROR_INITIAL_PARAMETERS) + rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_INITIAL_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return } if smPolicyContextData.Supi == "" || smPolicyContextData.SliceInfo == nil || len(smPolicyContextData.SliceInfo.Sd) != 6 { - rsp := pcf_util.GetProblemDetail("Errorneous/Missing Mandotory IE", pcf_util.ERROR_INITIAL_PARAMETERS) + rsp := util.GetProblemDetail("Errorneous/Missing Mandotory IE", util.ERROR_INITIAL_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return } req := http_wrapper.NewRequest(c.Request, smPolicyContextData) - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyCreate, req) + channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyCreate, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse @@ -54,8 +54,8 @@ func SmPoliciesPost(c *gin.Context) { func SmPoliciesSmPolicyIdDeletePost(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["smPolicyId"] = c.Params.ByName("smPolicyId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyDelete, req) - pcf_message.SendMessage(channelMsg) + channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyDelete, req) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse c.JSON(HTTPResponse.Status, HTTPResponse.Body) @@ -65,9 +65,9 @@ func SmPoliciesSmPolicyIdDeletePost(c *gin.Context) { func SmPoliciesSmPolicyIdGet(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["smPolicyId"] = c.Params.ByName("smPolicyId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyGet, req) + channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyGet, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse c.JSON(HTTPResponse.Status, HTTPResponse.Body) @@ -79,9 +79,9 @@ func SmPoliciesSmPolicyIdUpdatePost(c *gin.Context) { c.ShouldBindJSON(&smPolicyUpdateContextData) req := http_wrapper.NewRequest(c.Request, smPolicyUpdateContextData) req.Params["smPolicyId"] = c.Params.ByName("smPolicyId") - channelMsg := pcf_message.NewHttpChannelMessage(pcf_message.EventSMPolicyUpdate, req) + channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyUpdate, req) - pcf_message.SendMessage(channelMsg) + message.SendMessage(channelMsg) recvMsg := <-channelMsg.HttpChannel HTTPResponse := recvMsg.HTTPResponse c.JSON(HTTPResponse.Status, HTTPResponse.Body) diff --git a/SMPolicy/api_default_test.go b/smpolicy/api_default_test.go similarity index 97% rename from SMPolicy/api_default_test.go rename to smpolicy/api_default_test.go index 55e8610..16432ef 100644 --- a/SMPolicy/api_default_test.go +++ b/smpolicy/api_default_test.go @@ -1,35 +1,35 @@ -package SMPolicy_test +package smpolicy_test import ( "context" "encoding/json" "flag" "fmt" - "github.com/gin-gonic/gin" - "go.mongodb.org/mongo-driver/bson" "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" "free5gc/lib/MongoDBLibrary" - "free5gc/lib/Npcf_AMPolicy" - "free5gc/lib/Npcf_SMPolicyControl" "free5gc/lib/http2_util" - "free5gc/lib/openapi/common" + "free5gc/lib/openapi" + "free5gc/lib/openapi/Npcf_AMPolicy" + "free5gc/lib/openapi/Npcf_SMPolicyControl" "free5gc/lib/openapi/models" "free5gc/lib/path_util" - "free5gc/src/amf/amf_service" + amf_service "free5gc/src/amf/service" "free5gc/src/app" - "free5gc/src/nrf/nrf_service" + nrf_service "free5gc/src/nrf/service" + pcf_context "free5gc/src/pcf/context" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_context" - "free5gc/src/pcf/pcf_producer" - "free5gc/src/pcf/pcf_service" - "free5gc/src/udr/udr_service" + pcf_service "free5gc/src/pcf/service" + udr_service "free5gc/src/udr/service" "net/http" "reflect" "strings" "testing" "time" + "github.com/gin-gonic/gin" + "go.mongodb.org/mongo-driver/bson" + "github.com/stretchr/testify/assert" "github.com/urfave/cli" ) @@ -172,7 +172,7 @@ func TestCreateSMPolicy(t *testing.T) { assert.True(t, httpRsp != nil) if httpRsp != nil { assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) assert.Equal(t, "ERROR_INITIAL_PARAMETERS", problem.Cause) // assert.Equal(t, "Supi Format Error", problem.Detail) } @@ -185,7 +185,7 @@ func TestCreateSMPolicy(t *testing.T) { assert.True(t, httpRsp != nil) if httpRsp != nil { assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) assert.Equal(t, "ERROR_INITIAL_PARAMETERS", problem.Cause) // assert.Equal(t, "Supi Format Error", problem.Detail) } @@ -296,7 +296,7 @@ func TestDelSMPolicy(t *testing.T) { assert.True(t, httpRsp != nil) if httpRsp != nil { assert.Equal(t, http.StatusNotFound, httpRsp.StatusCode) - problem := err.(common.GenericOpenAPIError).Model().(models.ProblemDetails) + problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) assert.Equal(t, "CONTEXT_NOT_FOUND", problem.Cause) } } @@ -645,14 +645,14 @@ func TestSMPolicyNotification(t *testing.T) { notification := models.SmPolicyNotification{ ResourceUri: smCreateReqData.NotificationUri, } - pcf_producer.SendSMPolicyUpdateNotification(ue, smPolicyId, notification) + producer.SendSMPolicyUpdateNotification(ue, smPolicyId, notification) //Test Policies Termination Notify termination := models.TerminationNotification{ ResourceUri: smCreateReqData.NotificationUri, Cause: models.PolicyAssociationReleaseCause_UNSPECIFIED, } - pcf_producer.SendSMPolicyTerminationRequestNotification(ue, smPolicyId, termination) + producer.SendSMPolicyTerminationRequestNotification(ue, smPolicyId, termination) time.Sleep(200 * time.Millisecond) } diff --git a/SMPolicy/routers.go b/smpolicy/routers.go similarity index 99% rename from SMPolicy/routers.go rename to smpolicy/routers.go index 42d02cc..075142c 100644 --- a/SMPolicy/routers.go +++ b/smpolicy/routers.go @@ -7,7 +7,7 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package SMPolicy +package smpolicy import ( "net/http" diff --git a/UEPolicy/api_default.go b/uepolicy/api_default.go similarity index 96% rename from UEPolicy/api_default.go rename to uepolicy/api_default.go index 00b0b78..dba0818 100644 --- a/UEPolicy/api_default.go +++ b/uepolicy/api_default.go @@ -7,7 +7,7 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package UEPolicy +package uepolicy import ( "github.com/gin-gonic/gin" diff --git a/UEPolicy/routers.go b/uepolicy/routers.go similarity index 98% rename from UEPolicy/routers.go rename to uepolicy/routers.go index 8818564..866c88b 100644 --- a/UEPolicy/routers.go +++ b/uepolicy/routers.go @@ -7,7 +7,7 @@ * Generated by: OpenAPI Generator (https://openapi-generator.tech) */ -package UEPolicy +package uepolicy import ( "net/http" diff --git a/pcf_util/convert.go b/util/convert.go similarity index 99% rename from pcf_util/convert.go rename to util/convert.go index bcb00cc..dc3fd67 100644 --- a/pcf_util/convert.go +++ b/util/convert.go @@ -1,4 +1,4 @@ -package pcf_util +package util import ( "fmt" diff --git a/pcf_util/initContext.go b/util/init_context.go similarity index 93% rename from pcf_util/initContext.go rename to util/init_context.go index d2e1368..52b2e5c 100644 --- a/pcf_util/initContext.go +++ b/util/init_context.go @@ -1,17 +1,17 @@ -package pcf_util +package util import ( "encoding/hex" "free5gc/lib/openapi/models" + "free5gc/src/pcf/context" "free5gc/src/pcf/factory" "free5gc/src/pcf/logger" - "free5gc/src/pcf/pcf_context" "github.com/google/uuid" ) // Init PCF Context from config flie -func InitpcfContext(context *pcf_context.PCFContext) { +func InitpcfContext(context *context.PCFContext) { config := factory.PcfConfig logger.UtilLog.Infof("pcfconfig Info: Version[%s] Description[%s]", config.Info.Version, config.Info.Description) configuration := config.Configuration diff --git a/pcf_util/pcc_rule.go b/util/pcc_rule.go similarity index 99% rename from pcf_util/pcc_rule.go rename to util/pcc_rule.go index 90787a2..2a16de0 100644 --- a/pcf_util/pcc_rule.go +++ b/util/pcc_rule.go @@ -1,4 +1,4 @@ -package pcf_util +package util import ( "fmt" diff --git a/pcf_util/pcf_util.go b/util/pcf_util.go similarity index 95% rename from pcf_util/pcf_util.go rename to util/pcf_util.go index 9a7bdd2..a24682c 100644 --- a/pcf_util/pcf_util.go +++ b/util/pcf_util.go @@ -1,17 +1,17 @@ -package pcf_util +package util import ( "encoding/hex" "encoding/json" "fmt" - "free5gc/lib/Namf_Communication" - "free5gc/lib/Npcf_AMPolicy" - "free5gc/lib/Npcf_PolicyAuthorization" - "free5gc/lib/Npcf_SMPolicyControl" - "free5gc/lib/Nudr_DataRepository" + "free5gc/lib/openapi/Namf_Communication" + "free5gc/lib/openapi/Npcf_AMPolicy" + "free5gc/lib/openapi/Npcf_PolicyAuthorization" + "free5gc/lib/openapi/Npcf_SMPolicyControl" + "free5gc/lib/openapi/Nudr_DataRepository" "free5gc/lib/openapi/models" "free5gc/lib/path_util" - "free5gc/src/pcf/pcf_context" + "free5gc/src/pcf/context" "net/http" "reflect" "time" @@ -199,7 +199,7 @@ var serviceUriMap = map[models.ServiceName]string{ // Get Resource Uri (location Header) with param id string func GetResourceUri(name models.ServiceName, id string) string { - return fmt.Sprintf("%s/%s/%s", pcf_context.GetUri(name), serviceUriMap[name], id) + return fmt.Sprintf("%s/%s/%s", context.GetUri(name), serviceUriMap[name], id) } // Check if Feature is Supported or not @@ -238,7 +238,7 @@ func GetNotSubscribedGuamis(guamisIn []models.Guami) (guamisOut []models.Guami) } func guamiInSubscriptionData(guami models.Guami) bool { - pcfSelf := pcf_context.PCF_Self() + pcfSelf := context.PCF_Self() for _, subscriptionData := range pcfSelf.AMFStatusSubsData { for _, sGuami := range subscriptionData.GuamiList { if reflect.DeepEqual(sGuami, guami) { diff --git a/pcf_util/search_nfService.go b/util/search_nf_service.go similarity index 98% rename from pcf_util/search_nfService.go rename to util/search_nf_service.go index 442a11e..aa00b73 100644 --- a/pcf_util/search_nfService.go +++ b/util/search_nf_service.go @@ -1,4 +1,4 @@ -package pcf_util +package util import ( "fmt" From 0b068dbc8461e4587bcdb019bbb4eb8427439209 Mon Sep 17 00:00:00 2001 From: Endri Goshi Date: Tue, 16 Jun 2020 19:07:37 +0200 Subject: [PATCH 3/7] [ADD] Added ServiceIPv4 config field to specify where the service will run. --- context/context.go | 1 + factory/config.go | 2 ++ service/init.go | 2 +- util/init_context.go | 10 ++++++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/context/context.go b/context/context.go index 267e9b1..835b3f8 100644 --- a/context/context.go +++ b/context/context.go @@ -28,6 +28,7 @@ func init() { type PCFContext struct { NfId string Name string + ServerIPv4 string UriScheme models.UriScheme HttpIPv4Address string HttpIpv4Port int diff --git a/factory/config.go b/factory/config.go index ff808e0..0269ff4 100644 --- a/factory/config.go +++ b/factory/config.go @@ -19,6 +19,8 @@ type Info struct { type Configuration struct { PcfName string `yaml:"pcfName,omitempty"` + ServerIPv4 string `yaml:"serverIPv4,omitempty"` + Sbi *Sbi `yaml:"sbi,omitempty"` TimeFormat string `yaml:"timeFormat,omitempty"` diff --git a/service/init.go b/service/init.go index 0597c44..e85c8fb 100644 --- a/service/init.go +++ b/service/init.go @@ -126,7 +126,7 @@ func (pcf *PCF) Start() { self := context.PCF_Self() util.InitpcfContext(self) - addr := fmt.Sprintf("%s:%d", self.HttpIPv4Address, self.HttpIpv4Port) + addr := fmt.Sprintf("%s:%d", self.ServerIPv4, self.HttpIpv4Port) profile, err := consumer.BuildNFInstance(self) if err != nil { diff --git a/util/init_context.go b/util/init_context.go index 52b2e5c..c8b1563 100644 --- a/util/init_context.go +++ b/util/init_context.go @@ -6,6 +6,7 @@ import ( "free5gc/src/pcf/context" "free5gc/src/pcf/factory" "free5gc/src/pcf/logger" + "os" "github.com/google/uuid" ) @@ -19,6 +20,15 @@ func InitpcfContext(context *context.PCFContext) { if configuration.PcfName != "" { context.Name = configuration.PcfName } + context.ServerIPv4 = os.Getenv(configuration.ServerIPv4) + if context.ServerIPv4 == "" { + logger.UtilLog.Warn("Problem parsing ServerIPv4 address from ENV Variable. Trying to parse it as string.") + context.ServerIPv4 = configuration.ServerIPv4 + if context.ServerIPv4 == "" { + logger.UtilLog.Warn("Error parsing ServerIPv4 address as string. Using the localhost address as default.") + context.ServerIPv4 = "127.0.0.1" + } + } sbi := configuration.Sbi context.NrfUri = configuration.NrfUri context.UriScheme = models.UriScheme(sbi.Scheme) From 93c6e816590ed083e0f7ff8e3f98022e733ba449 Mon Sep 17 00:00:00 2001 From: free5gc-org Date: Tue, 21 Jul 2020 04:59:29 +0000 Subject: [PATCH 4/7] v2020-07-21-01 --- ampolicy/api_default_test.go | 340 --------- ...pi_bdt_policies_collection_routers_test.go | 141 ---- ...vidual_bdt_policy_document_routers_test.go | 88 --- consumer/nf_management_test.go | 50 -- context/context.go | 32 +- context/ue.go | 22 + handler/handler_test.go | 40 -- .../api_application_sessions_collection.go | 6 +- ...pi_application_sessions_collection_test.go | 303 -------- .../api_events_subscription_document_test.go | 157 ----- ...plication_session_context_document_test.go | 318 --------- producer/ampolicy.go | 7 +- producer/policyauthorization.go | 92 +-- producer/smpolicy.go | 5 +- service/init.go | 9 +- smpolicy/api_default_test.go | 658 ------------------ util/init_context.go | 4 +- 17 files changed, 115 insertions(+), 2157 deletions(-) delete mode 100644 ampolicy/api_default_test.go delete mode 100644 bdtpolicy/api_bdt_policies_collection_routers_test.go delete mode 100644 bdtpolicy/api_individual_bdt_policy_document_routers_test.go delete mode 100644 consumer/nf_management_test.go delete mode 100644 handler/handler_test.go delete mode 100644 policyauthorization/api_application_sessions_collection_test.go delete mode 100644 policyauthorization/api_events_subscription_document_test.go delete mode 100644 policyauthorization/api_individual_application_session_context_document_test.go delete mode 100644 smpolicy/api_default_test.go diff --git a/ampolicy/api_default_test.go b/ampolicy/api_default_test.go deleted file mode 100644 index 1df4827..0000000 --- a/ampolicy/api_default_test.go +++ /dev/null @@ -1,340 +0,0 @@ -package ampolicy_test - -import ( - "context" - "encoding/json" - "flag" - "fmt" - "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" - "free5gc/lib/MongoDBLibrary" - "free5gc/lib/http2_util" - "free5gc/lib/openapi" - "free5gc/lib/openapi/Npcf_AMPolicy" - "free5gc/lib/openapi/models" - "free5gc/lib/path_util" - amf_service "free5gc/src/amf/service" - "free5gc/src/app" - nrf_service "free5gc/src/nrf/service" - pcf_context "free5gc/src/pcf/context" - "free5gc/src/pcf/logger" - pcf_service "free5gc/src/pcf/service" - udr_service "free5gc/src/udr/service" - "net/http" - "strings" - "testing" - "time" - - "github.com/gin-gonic/gin" - "go.mongodb.org/mongo-driver/bson" - - "github.com/stretchr/testify/assert" - "github.com/urfave/cli" -) - -const amPolicyDataColl = "policyData.ues.amData" - -var NFs = []app.NetworkFunction{ - &nrf_service.NRF{}, - &amf_service.AMF{}, - &udr_service.UDR{}, - &pcf_service.PCF{}, -} - -var filterUeIdOnly bson.M - -func init() { - app.AppInitializeWillInitialize("") - flag := flag.FlagSet{} - cli := cli.NewContext(nil, &flag, nil) - for _, service := range NFs { - service.Initialize(cli) - go service.Start() - time.Sleep(300 * time.Millisecond) - } - insertDefaultAmPolicyToDb("imsi-2089300007487") - -} -func toBsonM(data interface{}) bson.M { - tmp, _ := json.Marshal(data) - var putData = bson.M{} - _ = json.Unmarshal(tmp, &putData) - return putData -} -func insertDefaultAmPolicyToDb(ueId string) { - amPolicyData := models.AmPolicyData{ - SubscCats: []string{ - "free5gc", - }, - } - filterUeIdOnly = bson.M{"ueId": ueId} - amPolicyDataBsonM := toBsonM(amPolicyData) - amPolicyDataBsonM["ueId"] = ueId - MongoDBLibrary.RestfulAPIPutOne(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM) -} -func TestCreateAMPolicy(t *testing.T) { - - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - client := Npcf_AMPolicy.NewAPIClient(configuration) - - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - { - amCreateReqData := TestAMPolicy.GetamCreatefailnotifyURIData() - _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err != nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - assert.Equal(t, "ERROR_REQUEST_PARAMETERS", problem.Cause) - assert.Equal(t, "Miss Mandotory IE", problem.Detail) - } - } - { - amCreateReqData := TestAMPolicy.GetamCreatefailsupiData() - _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err != nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - assert.Equal(t, "ERROR_REQUEST_PARAMETERS", problem.Cause) - assert.Equal(t, "Supi Format Error", problem.Detail) - } - } - -} - -func TestGetAMPolicy(t *testing.T) { - - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - client := Npcf_AMPolicy.NewAPIClient(configuration) - - amCreateReqData := TestAMPolicy.GetAMreqdata() - polAssoId := "imsi-2089300007487-1" - //Test PostPolicies - { - _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId = locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - { - //Test GetPoliciesPolAssoId - rsp, httpRsp, err := client.DefaultApi.PoliciesPolAssoIdGet(context.Background(), polAssoId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - assert.Equal(t, amCreateReqData.SuppFeat, rsp.SuppFeat) - assert.Equal(t, amCreateReqData.ServAreaRes, rsp.ServAreaRes) - assert.Equal(t, amCreateReqData.Rfsp, rsp.Rfsp) - assert.True(t, rsp.Triggers == nil) - assert.True(t, rsp.Pras == nil) - } - } - -} - -func TestDelAMPolicy(t *testing.T) { - - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - client := Npcf_AMPolicy.NewAPIClient(configuration) - - amCreateReqData := TestAMPolicy.GetAMreqdata() - polAssoId := "imsi-2089300007487-1" - //Test PostPolicies - { - _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId = locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - { - //Test DelPoliciesPolAssoId - httpRsp, err := client.DefaultApi.PoliciesPolAssoIdDelete(context.Background(), polAssoId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) - } - } - { - //Test GetPoliciesPolAssoId - _, httpRsp, err := client.DefaultApi.PoliciesPolAssoIdGet(context.Background(), polAssoId) - assert.True(t, err != nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusNotFound, httpRsp.StatusCode) - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - assert.Equal(t, "CONTEXT_NOT_FOUND", problem.Cause) - } - } - -} - -func TestUpdateAMPolicy(t *testing.T) { - - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - client := Npcf_AMPolicy.NewAPIClient(configuration) - - amCreateReqData := TestAMPolicy.GetAMreqdata() - polAssoId := "imsi-2089300007487-1" - //Test PostPolicies - { - _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId = locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - updateReq := TestAMPolicy.GetAMUpdateReqData() - { - //Test UpdatePoliciesPolAssoId - rsp, httpRsp, err := client.DefaultApi.PoliciesPolAssoIdUpdatePost(context.Background(), polAssoId, updateReq) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - assert.Equal(t, updateReq.ServAreaRes, rsp.ServAreaRes) - assert.Equal(t, updateReq.Rfsp, rsp.Rfsp) - assert.True(t, rsp.Triggers == nil) - assert.True(t, rsp.Pras == nil) - } - } -} - -func TestAMPolicyNotification(t *testing.T) { - - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - client := Npcf_AMPolicy.NewAPIClient(configuration) - go func() { // fake udr server - router := gin.Default() - - router.POST("/namf-callback/v1/am-policy/:polAssoId/update", func(c *gin.Context) { - polAssoId := c.Param("polAssoId") - fmt.Println("==========AMF Policy Association Update Callback=============") - fmt.Println("polAssoId: ", polAssoId) - - var policyUpdate models.PolicyUpdate - if err := c.ShouldBindJSON(&policyUpdate); err != nil { - fmt.Println("fake amf server error") - c.JSON(http.StatusInternalServerError, gin.H{}) - return - } - c.JSON(http.StatusNoContent, gin.H{}) - }) - - router.POST("/namf-callback/v1/am-policy/:polAssoId/terminate", func(c *gin.Context) { - polAssoId := c.Param("polAssoId") - fmt.Println("==========AMF Policy Association Terminate Callback=============") - fmt.Println("polAssoId: ", polAssoId) - - var terminationNotification models.TerminationNotification - if err := c.ShouldBindJSON(&terminationNotification); err != nil { - fmt.Println("fake amf server error") - c.JSON(http.StatusInternalServerError, gin.H{}) - return - } - c.JSON(http.StatusNoContent, gin.H{}) - httpRsp, err := client.DefaultApi.PoliciesPolAssoIdDelete(context.Background(), polAssoId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) - } - }) - - amfLogPath := path_util.Gofree5gcPath("free5gc/amfsslkey.log") - amfPemPath := path_util.Gofree5gcPath("free5gc/support/TLS/amf.pem") - amfKeyPath := path_util.Gofree5gcPath("free5gc/support/TLS/amf.key") - - server, err := http2_util.NewServer(":8888", amfLogPath, router) - if err == nil && server != nil { - logger.InitLog.Infoln(server.ListenAndServeTLS(amfPemPath, amfKeyPath)) - } - assert.True(t, err == nil) - }() - - time.Sleep(100 * time.Millisecond) - - var polAssoId string - amCreateReqData := TestAMPolicy.GetAMreqdata() - amCreateReqData.NotificationUri = "https://127.0.0.1:8888/namf-callback/v1/am-policy/imsi-2089300007487-1" - //Test PostPolicies - { - _, httpRsp, err := client.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId = locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] - //Test Policies Update Notify - policyUpdate := models.PolicyUpdate{ - ResourceUri: amCreateReqData.NotificationUri, - } - producer.SendAMPolicyUpdateNotification(ue, polAssoId, policyUpdate) - - //Test Policies Termination Notify - notification := models.TerminationNotification{ - ResourceUri: amCreateReqData.NotificationUri, - Cause: models.PolicyAssociationReleaseCause_UNSPECIFIED, - } - producer.SendAMPolicyTerminationRequestNotification(ue, polAssoId, notification) - - time.Sleep(200 * time.Millisecond) -} diff --git a/bdtpolicy/api_bdt_policies_collection_routers_test.go b/bdtpolicy/api_bdt_policies_collection_routers_test.go deleted file mode 100644 index 6bd5250..0000000 --- a/bdtpolicy/api_bdt_policies_collection_routers_test.go +++ /dev/null @@ -1,141 +0,0 @@ -package bdtpolicy_test - -import ( - "context" - "flag" - "fmt" - TestBDTPolicy "free5gc/lib/CommonConsumerTestData/PCF/TestBDTPolicy" - "free5gc/lib/MongoDBLibrary" - "free5gc/lib/http2_util" - "free5gc/lib/openapi/Npcf_BDTPolicyControl" - "free5gc/lib/openapi/models" - "free5gc/lib/path_util" - "free5gc/src/app" - nrf_service "free5gc/src/nrf/service" - pcf_service "free5gc/src/pcf/service" - "free5gc/src/udr/consumer" - "free5gc/src/udr/datarepository" - "free5gc/src/udr/factory" - "free5gc/src/udr/logger" - udr_service "free5gc/src/udr/service" - "free5gc/src/udr/util" - "log" - "net/http" - "testing" - "time" - - "github.com/davecgh/go-spew/spew" - "github.com/gin-gonic/gin" - "go.mongodb.org/mongo-driver/bson" - - "github.com/stretchr/testify/assert" - "github.com/urfave/cli" -) - -var NFs = []app.NetworkFunction{ - &nrf_service.NRF{}, - &udr_service.UDR{}, - &pcf_service.PCF{}, -} - -func fakeudrInit() { - config := factory.UdrConfig - sbi := config.Configuration.Sbi - mongodb := config.Configuration.Mongodb - nrfUri := config.Configuration.NrfUri - - // Connect to MongoDB - datarepository.SetMongoDB(mongodb.Name, mongodb.Url) - - udrLogPath := util.UdrLogPath - udrPemPath := util.UdrPemPath - udrKeyPath := util.UdrKeyPath - if sbi.Tls != nil { - udrLogPath = path_util.Gofree5gcPath(sbi.Tls.Log) - udrPemPath = path_util.Gofree5gcPath(sbi.Tls.Pem) - udrKeyPath = path_util.Gofree5gcPath(sbi.Tls.Key) - } - - profile := consumer.BuildNFInstance() - newNrfUri, _, err := consumer.SendRegisterNFInstance(nrfUri, profile.NfInstanceId, profile) - if err == nil { - config.Configuration.NrfUri = newNrfUri - } else { - fmt.Errorf("Send Register NFInstance Error[%s]", err.Error()) - } - go func() { // fake udr server - router := gin.Default() - - router.GET("/nudr-dr/v1/policy-data/bdt-data", func(c *gin.Context) { - fmt.Println("==========GET BDT Policy Data==========") - rsp := []models.BdtData{} - c.JSON(http.StatusOK, rsp) - }) - router.PUT("/nudr-dr/v1/policy-data/bdt-data/:bdtReferenceId", func(c *gin.Context) { - bdtReferenceId := c.Param("bdtReferenceId") - fmt.Println("==========PUT BDT Policy Data==========") - fmt.Println("bdtReferenceId: ", bdtReferenceId) - var bdtData models.BdtData - - if err := c.ShouldBindJSON(&bdtData); err != nil { - log.Panic(err.Error()) - } - spew.Dump(bdtData) - }) - server, err := http2_util.NewServer(":29504", udrLogPath, router) - if err == nil && server != nil { - logger.InitLog.Infoln(server.ListenAndServeTLS(udrPemPath, udrKeyPath)) - } - }() -} - -func init() { - app.AppInitializeWillInitialize("") - flag := flag.FlagSet{} - cli := cli.NewContext(nil, &flag, nil) - for i, service := range NFs { - if i == 1 { - service.Initialize(cli) - fakeudrInit() - } else { - service.Initialize(cli) - go service.Start() - } - time.Sleep(300 * time.Millisecond) - if i == 0 { - MongoDBLibrary.RestfulAPIDeleteMany("NfProfile", bson.M{}) - time.Sleep(300 * time.Millisecond) - } - } -} -func TestCreateBDTPolicy(t *testing.T) { - - configuration := Npcf_BDTPolicyControl.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - client := Npcf_BDTPolicyControl.NewAPIClient(configuration) - - // get test data - bdtReqData := TestBDTPolicy.GetCreateTestData() - - // test create service - rsp, httpRsp, err := client.BDTPoliciesCollectionApi.CreateBDTPolicy(context.Background(), bdtReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) { - if assert.NotNil(t, rsp.BdtReqData) { - assert.Equal(t, *rsp.BdtReqData, bdtReqData) - } - if assert.NotNil(t, rsp.BdtPolData) { - assert.True(t, rsp.BdtPolData.SelTransPolicyId == 1) - assert.Equal(t, rsp.BdtPolData.SuppFeat, "") - if assert.True(t, len(rsp.BdtPolData.TransfPolicies) == 1) { - assert.Equal(t, rsp.BdtPolData.TransfPolicies[0], models.TransferPolicy{ - RatingGroup: 1, - RecTimeInt: bdtReqData.DesTimeInt, - TransPolicyId: 1, - }) - } - } - } - time.Sleep(30 * time.Millisecond) -} diff --git a/bdtpolicy/api_individual_bdt_policy_document_routers_test.go b/bdtpolicy/api_individual_bdt_policy_document_routers_test.go deleted file mode 100644 index a27e018..0000000 --- a/bdtpolicy/api_individual_bdt_policy_document_routers_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package bdtpolicy_test - -import ( - "context" - TestBDTPolicy "free5gc/lib/CommonConsumerTestData/PCF/TestBDTPolicy" - "free5gc/lib/openapi/Npcf_BDTPolicyControl" - "free5gc/lib/openapi/models" - "net/http" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestGetUpdateBDTPolicy(t *testing.T) { - - configuration := Npcf_BDTPolicyControl.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - client := Npcf_BDTPolicyControl.NewAPIClient(configuration) - - var bdtPolicyId string - // get test data - bdtReqData := TestBDTPolicy.GetCreateTestData() - - // test create service - { - rsp, httpRsp, err := client.BDTPoliciesCollectionApi.CreateBDTPolicy(context.Background(), bdtReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) { - if assert.NotNil(t, rsp.BdtReqData) { - assert.Equal(t, *rsp.BdtReqData, bdtReqData) - } - if assert.NotNil(t, rsp.BdtPolData) { - assert.True(t, rsp.BdtPolData.SelTransPolicyId == 1) - assert.Equal(t, rsp.BdtPolData.SuppFeat, "") - if assert.True(t, len(rsp.BdtPolData.TransfPolicies) == 1) { - assert.Equal(t, rsp.BdtPolData.TransfPolicies[0], models.TransferPolicy{ - RatingGroup: 1, - RecTimeInt: bdtReqData.DesTimeInt, - TransPolicyId: 1, - }) - } - } - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - bdtPolicyId = locationHeader[index+1:] - assert.True(t, strings.HasPrefix(bdtPolicyId, "BdtPolicyId-1")) - - } - } - - time.Sleep(30 * time.Millisecond) - // test update service - { - bdtPolicyDataPatch := TestBDTPolicy.GetUpdateTestData() - _, httpRsp, err := client.IndividualBDTPolicyDocumentApi.UpdateBDTPolicy(context.Background(), bdtPolicyId, bdtPolicyDataPatch) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - } - time.Sleep(30 * time.Millisecond) - // test get service - { - rsp, httpRsp, err := client.IndividualBDTPolicyDocumentApi.GetBDTPolicy(context.Background(), bdtPolicyId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { - if assert.NotNil(t, rsp.BdtReqData) { - assert.Equal(t, *rsp.BdtReqData, bdtReqData) - } - if assert.NotNil(t, rsp.BdtPolData) { - assert.True(t, rsp.BdtPolData.SelTransPolicyId == 1) - assert.Equal(t, rsp.BdtPolData.SuppFeat, "") - if assert.True(t, len(rsp.BdtPolData.TransfPolicies) == 1) { - assert.Equal(t, rsp.BdtPolData.TransfPolicies[0], models.TransferPolicy{ - RatingGroup: 1, - RecTimeInt: bdtReqData.DesTimeInt, - TransPolicyId: 1, - }) - } - } - } - } - -} diff --git a/consumer/nf_management_test.go b/consumer/nf_management_test.go deleted file mode 100644 index a18e048..0000000 --- a/consumer/nf_management_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package consumer_test - -import ( - "flag" - "free5gc/lib/MongoDBLibrary" - "free5gc/lib/openapi/Nnrf_NFDiscovery" - "free5gc/lib/openapi/models" - nrf_service "free5gc/src/nrf/service" - "free5gc/src/pcf/consumer" - "free5gc/src/pcf/factory" - pcf_service "free5gc/src/pcf/service" - "testing" - "time" - - "github.com/antihax/optional" - "github.com/urfave/cli" - "go.mongodb.org/mongo-driver/bson" -) - -var flags flag.FlagSet -var c = cli.NewContext(nil, &flags, nil) - -func nrfInit() { - nrf := &nrf_service.NRF{} - nrf.Initialize(c) - go nrf.Start() - time.Sleep(100 * time.Millisecond) -} -func TestRegisterNFInstance(t *testing.T) { - // init NRF - nrfInit() - // Clear DB - MongoDBLibrary.RestfulAPIDeleteMany("NfProfile", bson.M{}) - time.Sleep(50 * time.Millisecond) - // Init PCF and register to NRF - pcf := pcf_service.PCF{} - pcf.Initialize(c) - go pcf.Start() - time.Sleep(50 * time.Millisecond) - // Send NF Discovery to discover PCF - param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ - ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NPCF_AM_POLICY_CONTROL, models.ServiceName_NPCF_BDTPOLICYCONTROL, models.ServiceName_NPCF_POLICYAUTHORIZATION, models.ServiceName_NPCF_SMPOLICYCONTROL, models.ServiceName_NPCF_UE_POLICY_CONTROL}), - } - result, err := consumer.SendSearchNFInstances(factory.PcfConfig.Configuration.NrfUri, models.NfType_PCF, models.NfType_UDR, param) - if err != nil { - t.Error(err.Error()) - } else if result.NfInstances == nil { - t.Error("NF Instances is nil") - } -} diff --git a/context/context.go b/context/context.go index 267e9b1..b4fce51 100644 --- a/context/context.go +++ b/context/context.go @@ -2,6 +2,7 @@ package context import ( "fmt" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" "free5gc/src/pcf/factory" "strconv" @@ -17,7 +18,7 @@ func init() { PCF_Self().DefaultBdtRefId = "BdtPolicyId-" PCF_Self().NfService = make(map[models.ServiceName]models.NfService) PCF_Self().PcfServiceUris = make(map[models.ServiceName]string) - PCF_Self().PcfSuppFeats = make(map[models.ServiceName][]byte) + PCF_Self().PcfSuppFeats = make(map[models.ServiceName]openapi.SupportedFeature) PCF_Self().UePool = make(map[string]*UeContext) PCF_Self().BdtPolicyPool = make(map[string]models.BdtPolicy) PCF_Self().BdtPolicyIdGenerator = 1 @@ -35,7 +36,7 @@ type PCFContext struct { DefaultBdtRefId string NfService map[models.ServiceName]models.NfService PcfServiceUris map[models.ServiceName]string - PcfSuppFeats map[models.ServiceName][]byte + PcfSuppFeats map[models.ServiceName]openapi.SupportedFeature NrfUri string DefaultUdrUri string UePool map[string]*UeContext @@ -200,24 +201,33 @@ func (context *PCFContext) PcfUeFindByIPv6(v6 string) *UeContext { return nil } -// Session Binding from application request to get corresponding Sm policy +// SessionBinding from application request to get corresponding Sm policy func (context *PCFContext) SessionBinding(req *models.AppSessionContextReqData) (policy *UeSmPolicyData, err error) { // TODO: support dnn, snssai, ... because Ip Address is not enough with same ip address in different ip domains, details in subclause 4.2.2.2 of TS 29514 + var selectedUE *UeContext + if ue, exist := context.UePool[req.Supi]; exist { + selectedUE = ue + } + + if req.Gpsi != "" && selectedUE == nil { + for _, ue := range context.UePool { + if ue.Gpsi == req.Gpsi { + selectedUE = ue + } + } + } + + if selectedUE != nil { if req.UeIpv4 != "" { - policy = ue.SMPolicyFindByIpv4(req.UeIpv4) + policy = selectedUE.SMPolicyFindByIdentifiersIpv4(req.UeIpv4, req.SliceInfo, req.Dnn) } else if req.UeIpv6 != "" { - policy = ue.SMPolicyFindByIpv6(req.UeIpv6) + policy = selectedUE.SMPolicyFindByIdentifiersIpv6(req.UeIpv6, req.SliceInfo, req.Dnn) } else { err = fmt.Errorf("Ue finding by MAC address does not support") } - } else if req.UeIpv4 != "" { - policy = ue.SMPolicyFindByIpv4(req.UeIpv4) - } else if req.UeIpv6 != "" { - policy = ue.SMPolicyFindByIpv6(req.UeIpv6) - } else { - err = fmt.Errorf("Ue finding by MAC address does not support") } + if err == nil && policy == nil { if req.UeIpv4 != "" { err = fmt.Errorf("Can't find Ue with Ipv4[%s]", req.UeIpv4) diff --git a/context/ue.go b/context/ue.go index cc2a36f..2dcc145 100644 --- a/context/ue.go +++ b/context/ue.go @@ -384,6 +384,28 @@ func (ue *UeContext) SMPolicyFindByIpv6(v6 string) *UeSmPolicyData { return nil } +// returns SM Policy by IPv6 +func (ue *UeContext) SMPolicyFindByIdentifiersIpv4(v4 string, sNssai *models.Snssai, dnn string) *UeSmPolicyData { + for _, smPolicy := range ue.SmPolicyData { + policyContext := smPolicy.PolicyContext + if policyContext.Ipv4Address == v4 && reflect.DeepEqual(sNssai, policyContext.SliceInfo) && policyContext.Dnn == dnn { + return smPolicy + } + } + return nil +} + +// returns SM Policy by IPv6 +func (ue *UeContext) SMPolicyFindByIdentifiersIpv6(v6 string, sNssai *models.Snssai, dnn string) *UeSmPolicyData { + for _, smPolicy := range ue.SmPolicyData { + policyContext := smPolicy.PolicyContext + if policyContext.Ipv6AddressPrefix == v6 && reflect.DeepEqual(sNssai, policyContext.SliceInfo) && policyContext.Dnn == dnn { + return smPolicy + } + } + return nil +} + // AppSessionIdStore - type AppSessionIdStore struct { AppSessionId string diff --git a/handler/handler_test.go b/handler/handler_test.go deleted file mode 100644 index f0ef8a1..0000000 --- a/handler/handler_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package handler_test - -import ( - // "free5gc/lib/CommonConsumerTestData/AMF/TestAmf" - // "free5gc/lib/ngap" - // "free5gc/src/test/ngapTestpacket" - // "free5gc/src/amf/amf_handler" - // "free5gc/src/amf/amf_handler/amf_message" - // "free5gc/src/amf/amf_ngap" - "testing" - // "time" -) - -func TestHandler(t *testing.T) { - // go amf_handler.Handle() - // TestAmf.AmfInit() - // testConn := &TestAmf.TestConn{ - // LAddr: &TestAmf.TestAddr{ - // Net: "tcp", - // Value: "192.188.2.2:12345", - // }, - // RAddr: &TestAmf.TestAddr{ - // Net: "tcp", - // Value: "192.188.2.1:9487", - // }, - // } - // message := ngapTestpacket.BuildNGSetupRequest() - // ngapMsg, err := ngap.Encoder(message) - // if err != nil { - // amf_ngap.Ngaplog.Errorln(err) - // } - // msg := amf_message.HandlerMessage{} - // msg.Event = amf_message.EventNGAPMessage - // msg.NgapConn = testConn - // msg.Value = ngapMsg - // amf_handler.SendMessage(msg) - - // time.Sleep(100 * time.Millisecond) - -} diff --git a/policyauthorization/api_application_sessions_collection.go b/policyauthorization/api_application_sessions_collection.go index 16c7e42..707da06 100644 --- a/policyauthorization/api_application_sessions_collection.go +++ b/policyauthorization/api_application_sessions_collection.go @@ -12,8 +12,8 @@ package policyauthorization import ( "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" - "free5gc/src/pcf/logger" "free5gc/src/pcf/handler/message" + "free5gc/src/pcf/logger" "free5gc/src/pcf/util" "github.com/gin-gonic/gin" @@ -29,8 +29,8 @@ func PostAppSessions(c *gin.Context) { c.JSON(int(rsp.Status), rsp) return } - reqData := appSessionContext.AscReqData - if reqData == nil || reqData.SuppFeat == "" || reqData.NotifUri == "" { + ascReqData := appSessionContext.AscReqData + if ascReqData == nil || ascReqData.SuppFeat == "" || ascReqData.NotifUri == "" { // Check Mandatory IEs rsp := util.GetProblemDetail("Errorneous/Missing Mandotory IE", util.ERROR_INITIAL_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) diff --git a/policyauthorization/api_application_sessions_collection_test.go b/policyauthorization/api_application_sessions_collection_test.go deleted file mode 100644 index 9ff0749..0000000 --- a/policyauthorization/api_application_sessions_collection_test.go +++ /dev/null @@ -1,303 +0,0 @@ -package policyauthorization_test - -import ( - "context" - "encoding/json" - "flag" - "fmt" - "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" - "free5gc/lib/CommonConsumerTestData/PCF/TestPolicyAuthorization" - "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" - "free5gc/lib/MongoDBLibrary" - "free5gc/lib/http2_util" - "free5gc/lib/openapi" - "free5gc/lib/openapi/Npcf_AMPolicy" - "free5gc/lib/openapi/Npcf_PolicyAuthorization" - "free5gc/lib/openapi/Npcf_SMPolicyControl" - "free5gc/lib/openapi/models" - "free5gc/lib/path_util" - amf_service "free5gc/src/amf/service" - "free5gc/src/app" - nrf_service "free5gc/src/nrf/service" - pcf_context "free5gc/src/pcf/context" - pcf_service "free5gc/src/pcf/service" - udr_service "free5gc/src/udr/service" - "net/http" - "strings" - "testing" - "time" - - "github.com/gin-gonic/gin" - "go.mongodb.org/mongo-driver/bson" - - "github.com/stretchr/testify/assert" - "github.com/urfave/cli" -) - -const amPolicyDataColl = "policyData.ues.amData" -const smPolicyDataColl = "policyData.ues.smData" - -var NFs = []app.NetworkFunction{ - &nrf_service.NRF{}, - &amf_service.AMF{}, - &udr_service.UDR{}, - &pcf_service.PCF{}, -} - -var filterUeIdOnly bson.M - -func toBsonM(data interface{}) bson.M { - tmp, _ := json.Marshal(data) - var putData = bson.M{} - _ = json.Unmarshal(tmp, &putData) - return putData -} -func insertDefaultPoliciesToDb(ueId string) { - amPolicyData := models.AmPolicyData{ - SubscCats: []string{ - "free5gc", - }, - } - - smPolicyData := models.SmPolicyData{ - SmPolicySnssaiData: map[string]models.SmPolicySnssaiData{ - "01010203": { - Snssai: &models.Snssai{ - Sd: "010203", - Sst: 1, - }, - SmPolicyDnnData: map[string]models.SmPolicyDnnData{ - "internet": { - Dnn: "internet", - GbrUl: "500 Mbps", - GbrDl: "500 Mbps", - AdcSupport: false, - Ipv4Index: 6, - Ipv6Index: 6, - Offline: true, - Online: false, - // ChfInfo - // RefUmDataLimitIds - // MpsPriority - // ImsSignallingPrio - // MpsPriorityLevel - // AllowedServices - // SubscCats - // SubscSpendingLimit - - }, - }, - }, - "01112233": { - Snssai: &models.Snssai{ - Sd: "112233", - Sst: 1, - }, - SmPolicyDnnData: map[string]models.SmPolicyDnnData{ - "internet": { - Dnn: "internet", - }, - }, - }, - }, - } - - filterUeIdOnly = bson.M{"ueId": ueId} - amPolicyDataBsonM := toBsonM(amPolicyData) - amPolicyDataBsonM["ueId"] = ueId - MongoDBLibrary.RestfulAPIPutOne(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM) - smPolicyDataBsonM := toBsonM(smPolicyData) - smPolicyDataBsonM["ueId"] = ueId - MongoDBLibrary.RestfulAPIPost(smPolicyDataColl, filterUeIdOnly, smPolicyDataBsonM) -} - -func fakeSmfServer(t *testing.T, port string) { - go func() { // fake smf server - router := gin.Default() - - router.POST("nsmf-callback/v1/sm-policies/:smPolicyId/update", func(c *gin.Context) { - smPolicyId := c.Param("smPolicyId") - fmt.Println("==========SM Policy Update Notification Callback=============") - fmt.Println("smPolicyId: ", smPolicyId) - - var notification models.SmPolicyNotification - if err := c.ShouldBindJSON(¬ification); err != nil { - fmt.Println("fake smf server error") - c.JSON(http.StatusInternalServerError, gin.H{}) - return - } - c.JSON(http.StatusNoContent, gin.H{}) - }) - - router.POST("nsmf-callback/v1/sm-policies/:smPolicyId/terminate", func(c *gin.Context) { - smPolicyId := c.Param("smPolicyId") - fmt.Println("==========SM Policy Terminate Callback=============") - fmt.Println("smPolicyId: ", smPolicyId) - - var terminationNotification models.TerminationNotification - if err := c.ShouldBindJSON(&terminationNotification); err != nil { - fmt.Println("fake smf server error") - c.JSON(http.StatusInternalServerError, gin.H{}) - return - } - c.JSON(http.StatusNoContent, gin.H{}) - configuration := Npcf_SMPolicyControl.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration) - httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdDeletePost(context.Background(), smPolicyId, models.SmPolicyDeleteData{}) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) - } - }) - - smfLogPath := path_util.Gofree5gcPath("free5gc/smfsslkey.log") - smfPemPath := path_util.Gofree5gcPath("free5gc/support/TLS/smf.pem") - smfKeyPath := path_util.Gofree5gcPath("free5gc/support/TLS/smf.key") - - server, err := http2_util.NewServer(port, smfLogPath, router) - if err == nil && server != nil { - fmt.Println(server.ListenAndServeTLS(smfPemPath, smfKeyPath)) - } - assert.True(t, err == nil) - }() -} - -func init() { - app.AppInitializeWillInitialize("") - flag := flag.FlagSet{} - cli := cli.NewContext(nil, &flag, nil) - for i, service := range NFs { - service.Initialize(cli) - go service.Start() - time.Sleep(300 * time.Millisecond) - if i == 0 { - MongoDBLibrary.RestfulAPIDeleteMany("NfProfile", bson.M{}) - time.Sleep(300 * time.Millisecond) - } - } - insertDefaultPoliciesToDb("imsi-2089300007487") - - time.Sleep(100 * time.Millisecond) - -} - -func TestApplicationSessionsCollection(t *testing.T) { - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) - - fakeSmfServer(t, ":29502") - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - amclient := Npcf_AMPolicy.NewAPIClient(configuration) - configuration1 := Npcf_SMPolicyControl.NewConfiguration() - configuration1.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) - configuration2 := Npcf_PolicyAuthorization.NewConfiguration() - configuration2.SetBasePath("https://127.0.0.1:29507") - afclient := Npcf_PolicyAuthorization.NewAPIClient(configuration2) - smPolicyId := "" - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] - pcfSelf := pcf_context.PCF_Self() - { - smCreateReqData := TestSMPolicy.CreateTestData() - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - smPolicyId = locationHeader[index+1:] - assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") - } - } - { - afReqData := TestPolicyAuthorization.GetPostAppSessionsData_Normal() - _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - appSessionId := fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) - header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) - assert.True(t, locationHeader == header) - appSession := pcfSelf.AppSessionPool[appSessionId] - if assert.NotNil(t, appSession) { - assert.True(t, appSession.EventUri == afReqData.AscReqData.EvSubsc.NotifUri) - assert.True(t, len(appSession.Events) == len(afReqData.AscReqData.EvSubsc.Events)) - smPolicy := ue.SmPolicyData[smPolicyId] - assert.Equal(t, smPolicy, appSession.SmPolicyData) - pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) - assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) - pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] - if assert.NotNil(t, pccRule) { - assert.Equal(t, afReqData.AscReqData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) - } - } - } - } - { - afReqData := TestPolicyAuthorization.GetPostAppSessionsData_Flow3() - _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - appSessionId := fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) - header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) - assert.True(t, locationHeader == header) - appSession := pcfSelf.AppSessionPool[appSessionId] - if assert.NotNil(t, appSession) { - assert.True(t, appSession.EventUri == afReqData.AscReqData.EvSubsc.NotifUri) - assert.True(t, len(appSession.Events) == len(afReqData.AscReqData.EvSubsc.Events)) - smPolicy := ue.SmPolicyData[smPolicyId] - assert.Equal(t, smPolicy, appSession.SmPolicyData) - assert.Equal(t, 3, len(appSession.RelatedPccRuleIds)) - assert.Equal(t, 3, len(smPolicy.PolicyDecision.PccRules)) - } - } - } - { - afReqData := TestPolicyAuthorization.GetPostAppSessionsData_403Forbidden() - _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) - assert.True(t, err != nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusForbidden, httpRsp.StatusCode) - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - assert.Equal(t, "REQUESTED_SERVICE_NOT_AUTHORIZED", problem.Cause) - } - } - { - afReqData := TestPolicyAuthorization.GetPostAppSessionsData_400() - _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) - assert.True(t, err != nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - assert.Equal(t, "ERROR_REQUEST_PARAMETERS", problem.Cause) - } - } -} diff --git a/policyauthorization/api_events_subscription_document_test.go b/policyauthorization/api_events_subscription_document_test.go deleted file mode 100644 index 191fdd0..0000000 --- a/policyauthorization/api_events_subscription_document_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package policyauthorization_test - -import ( - "context" - "fmt" - "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" - "free5gc/lib/CommonConsumerTestData/PCF/TestPolicyAuthorization" - "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" - "free5gc/lib/MongoDBLibrary" - "free5gc/lib/openapi/Npcf_AMPolicy" - "free5gc/lib/openapi/Npcf_PolicyAuthorization" - "free5gc/lib/openapi/Npcf_SMPolicyControl" - pcf_context "free5gc/src/pcf/context" - "net/http" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestEventSubscription(t *testing.T) { - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) - - fakeSmfServer(t, ":29502") - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - amclient := Npcf_AMPolicy.NewAPIClient(configuration) - configuration1 := Npcf_SMPolicyControl.NewConfiguration() - configuration1.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) - configuration2 := Npcf_PolicyAuthorization.NewConfiguration() - configuration2.SetBasePath("https://127.0.0.1:29507") - afclient := Npcf_PolicyAuthorization.NewAPIClient(configuration2) - smPolicyId := "" - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] - pcfSelf := pcf_context.PCF_Self() - { - smCreateReqData := TestSMPolicy.CreateTestData() - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - smPolicyId = locationHeader[index+1:] - assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") - } - } - appSessionId := "" - { - // Create App Session - afReqData := TestPolicyAuthorization.GetPostAppSessionsData_NoEvent() - _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - appSessionId = fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) - header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) - assert.True(t, locationHeader == header) - appSession := pcfSelf.AppSessionPool[appSessionId] - if assert.NotNil(t, appSession) { - smPolicy := ue.SmPolicyData[smPolicyId] - assert.Equal(t, smPolicy, appSession.SmPolicyData) - pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) - assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) - pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] - if assert.NotNil(t, pccRule) { - assert.Equal(t, afReqData.AscReqData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) - } - } - } - } - appSession := pcfSelf.AppSessionPool[appSessionId] - { - // Create App Session Subscription (201) - reqData := TestPolicyAuthorization.GetUpdateEventsSubsc201Data() - resp, httpRsp, err := afclient.EventsSubscriptionDocumentApi.UpdateEventsSubsc(context.Background(), appSessionId, reqData) - assert.True(t, err == nil) - if assert.True(t, httpRsp != nil) { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - if assert.NotNil(t, resp) { - assert.Equal(t, reqData, resp.EvSubsc) - assert.NotNil(t, resp.EvsNotif) - assert.Equal(t, 2, len(appSession.Events)) - assert.Equal(t, reqData.NotifUri, appSession.EventUri) - } - } - } - { - // Modify App Session Subscription (200) - reqData := TestPolicyAuthorization.GetUpdateEventsSubsc200Data() - resp, httpRsp, err := afclient.EventsSubscriptionDocumentApi.UpdateEventsSubsc(context.Background(), appSessionId, reqData) - assert.True(t, err == nil) - if assert.True(t, httpRsp != nil) { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - if assert.NotNil(t, resp) { - assert.Equal(t, reqData, resp.EvSubsc) - assert.NotNil(t, resp.EvsNotif) - assert.Equal(t, 1, len(appSession.Events)) - assert.Equal(t, reqData.NotifUri, appSession.EventUri) - } - } - } - { - // Modify App Session Subscription (204) - reqData := TestPolicyAuthorization.GetUpdateEventsSubsc204Data() - _, httpRsp, err := afclient.EventsSubscriptionDocumentApi.UpdateEventsSubsc(context.Background(), appSessionId, reqData) - assert.True(t, err == nil) - if assert.True(t, httpRsp != nil) { - assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) - assert.Equal(t, 1, len(appSession.Events)) - assert.Equal(t, reqData.NotifUri, appSession.EventUri) - } - } - { - // Create App Session Subscription (400) - reqData := TestPolicyAuthorization.GetUpdateEventsSubsc400Data() - _, httpRsp, err := afclient.EventsSubscriptionDocumentApi.UpdateEventsSubsc(context.Background(), appSessionId, reqData) - assert.True(t, err != nil) - if assert.True(t, httpRsp != nil) { - assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - } - } - { - // Delete App Session Subscription (204) - httpRsp, err := afclient.EventsSubscriptionDocumentApi.DeleteEventsSubsc(context.Background(), appSessionId) - assert.True(t, err == nil) - if assert.True(t, httpRsp != nil) { - assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) - assert.Nil(t, appSession.Events) - } - } - - time.Sleep(100 * time.Millisecond) -} diff --git a/policyauthorization/api_individual_application_session_context_document_test.go b/policyauthorization/api_individual_application_session_context_document_test.go deleted file mode 100644 index 493b09b..0000000 --- a/policyauthorization/api_individual_application_session_context_document_test.go +++ /dev/null @@ -1,318 +0,0 @@ -package policyauthorization_test - -import ( - "context" - "fmt" - "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" - "free5gc/lib/CommonConsumerTestData/PCF/TestPolicyAuthorization" - "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" - "free5gc/lib/MongoDBLibrary" - "free5gc/lib/openapi" - "free5gc/lib/openapi/Npcf_AMPolicy" - "free5gc/lib/openapi/Npcf_PolicyAuthorization" - "free5gc/lib/openapi/Npcf_SMPolicyControl" - "free5gc/lib/openapi/models" - "free5gc/lib/path_util" - pcf_context "free5gc/src/pcf/context" - "net/http" - "strings" - "testing" - "time" - - "github.com/davecgh/go-spew/spew" - "github.com/gin-gonic/gin" - - "github.com/stretchr/testify/assert" -) - -func fakeAfServer(t *testing.T, port string) { - go func() { // fake af server - router := gin.Default() - - router.POST("/notify", func(c *gin.Context) { - fmt.Println("==========App Session Event Notification Callback=============") - - var notification models.EventsNotification - if err := c.ShouldBindJSON(¬ification); err != nil { - fmt.Println("fake AF server error") - c.JSON(http.StatusInternalServerError, gin.H{}) - return - } - spew.Dump(notification.EvNotifs) - c.JSON(http.StatusNoContent, gin.H{}) - }) - - router.POST("/terminate", func(c *gin.Context) { - fmt.Println("==========App Session Teimination Callback=============") - - var terminationInfo models.TerminationInfo - if err := c.ShouldBindJSON(&terminationInfo); err != nil { - fmt.Println("fake AF server error") - c.JSON(http.StatusInternalServerError, gin.H{}) - return - } - spew.Dump(terminationInfo) - c.JSON(http.StatusNoContent, gin.H{}) - }) - - pcfPemPath := path_util.Gofree5gcPath("free5gc/support/TLS/pcf.pem") - pcfKeyPath := path_util.Gofree5gcPath("free5gc/support/TLS/pcf.key") - - server := &http.Server{ - Addr: port, - Handler: router, - } - - fmt.Println(server.ListenAndServeTLS(pcfPemPath, pcfKeyPath)) - }() -} - -func TestIndividualAppSessionContext(t *testing.T) { - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) - - fakeSmfServer(t, ":29502") - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - amclient := Npcf_AMPolicy.NewAPIClient(configuration) - configuration1 := Npcf_SMPolicyControl.NewConfiguration() - configuration1.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) - configuration2 := Npcf_PolicyAuthorization.NewConfiguration() - configuration2.SetBasePath("https://127.0.0.1:29507") - afclient := Npcf_PolicyAuthorization.NewAPIClient(configuration2) - smPolicyId := "" - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] - pcfSelf := pcf_context.PCF_Self() - { - smCreateReqData := TestSMPolicy.CreateTestData() - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - smPolicyId = locationHeader[index+1:] - assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") - } - } - appSessionId := "" - { - // Create App Session - afReqData := TestPolicyAuthorization.GetPostAppSessionsData_Normal() - _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - appSessionId = fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) - header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) - assert.True(t, locationHeader == header) - appSession := pcfSelf.AppSessionPool[appSessionId] - if assert.NotNil(t, appSession) { - assert.True(t, appSession.EventUri == afReqData.AscReqData.EvSubsc.NotifUri) - assert.True(t, len(appSession.Events) == len(afReqData.AscReqData.EvSubsc.Events)) - smPolicy := ue.SmPolicyData[smPolicyId] - assert.Equal(t, smPolicy, appSession.SmPolicyData) - pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) - assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) - pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] - if assert.NotNil(t, pccRule) { - assert.Equal(t, afReqData.AscReqData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) - } - } - } - } - { - // Get App Session - resp, httpRsp, err := afclient.IndividualApplicationSessionContextDocumentApi.GetAppSession(context.Background(), appSessionId) - assert.True(t, err == nil) - if assert.True(t, httpRsp != nil) { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - if assert.NotNil(t, resp) { - assert.NotNil(t, resp.AscRespData) - assert.NotNil(t, resp.AscReqData) - } - } - } - appSession := pcfSelf.AppSessionPool[appSessionId] - smPolicy := ue.SmPolicyData[smPolicyId] - { - // Update App Session - modData := TestPolicyAuthorization.GetModAppSession200Data() - _, httpRsp, err := afclient.IndividualApplicationSessionContextDocumentApi.ModAppSession(context.Background(), appSessionId, modData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - if assert.NotNil(t, appSession) { - assert.True(t, appSession.EventUri == appSession.AppSessionContext.AscReqData.EvSubsc.NotifUri) - assert.True(t, len(appSession.Events) == len(modData.EvSubsc.Events)) - assert.Equal(t, smPolicy, appSession.SmPolicyData) - pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) - assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) - assert.Equal(t, 1, len(smPolicy.PolicyDecision.PccRules)) - pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] - if assert.NotNil(t, pccRule) { - assert.Equal(t, modData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) - } - } - } - } - { - // Delete App Session - _, httpRsp, err := afclient.IndividualApplicationSessionContextDocumentApi.DeleteAppSession(context.Background(), appSessionId, nil) - assert.True(t, err == nil) - if assert.True(t, httpRsp != nil) { - assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) - assert.Equal(t, 0, len(pcfSelf.AppSessionPool)) - assert.Equal(t, 0, len(smPolicy.AppSessions)) - assert.Equal(t, 0, len(smPolicy.PolicyDecision.PccRules)) - } - } -} - -func TestAppSessionNotification(t *testing.T) { - - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) - - fakeSmfServer(t, ":29502") - fakeAfServer(t, ":12345") - - time.Sleep(100 * time.Millisecond) - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - amclient := Npcf_AMPolicy.NewAPIClient(configuration) - configuration1 := Npcf_SMPolicyControl.NewConfiguration() - configuration1.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) - configuration2 := Npcf_PolicyAuthorization.NewConfiguration() - configuration2.SetBasePath("https://127.0.0.1:29507") - afclient := Npcf_PolicyAuthorization.NewAPIClient(configuration2) - smPolicyId := "" - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] - pcfSelf := pcf_context.PCF_Self() - { - smCreateReqData := TestSMPolicy.CreateTestData() - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - smPolicyId = locationHeader[index+1:] - assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") - } - } - appSessionId := "" - { - afReqData := TestPolicyAuthorization.GetPostAppSessionsData_Normal() - _, httpRsp, err := afclient.ApplicationSessionsCollectionApi.PostAppSessions(context.Background(), afReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - appSessionId = fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator-1) - header := fmt.Sprintf("https://127.0.0.1:29507/npcf-policyauthorization/v1/app-sessions/%s", appSessionId) - assert.True(t, locationHeader == header) - appSession := pcfSelf.AppSessionPool[appSessionId] - if assert.NotNil(t, appSession) { - assert.True(t, appSession.EventUri == afReqData.AscReqData.EvSubsc.NotifUri) - assert.True(t, len(appSession.Events) == len(afReqData.AscReqData.EvSubsc.Events)) - smPolicy := ue.SmPolicyData[smPolicyId] - assert.Equal(t, smPolicy, appSession.SmPolicyData) - pccRuleId := fmt.Sprintf("PccRuleId-%d", smPolicy.PccRuleIdGenarator-1) - assert.Equal(t, 1, len(appSession.RelatedPccRuleIds)) - pccRule := smPolicy.PolicyDecision.PccRules[pccRuleId] - if assert.NotNil(t, pccRule) { - assert.Equal(t, afReqData.AscReqData.MedComponents["1"].MedSubComps["1"].FDescs[0], pccRule.FlowInfos[0].FlowDescription) - } - } - } - } - time.Sleep(100 * time.Millisecond) - - // Test AppSessionEventNotify (Send SM policy Update which is related to App Session) - { - trigger := []models.PolicyControlRequestTrigger{ - models.PolicyControlRequestTrigger_PLMN_CH, - models.PolicyControlRequestTrigger_AC_TY_CH, - models.PolicyControlRequestTrigger_RAT_TY_CH, - } - updateReq := TestSMPolicy.UpdateTestData(trigger, nil) - updateReq.AccessType = models.AccessType_NON_3_GPP_ACCESS - updateReq.RatType = models.RatType_WLAN - //Test UpdatePoliciesPolAssoId - _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - } - } - time.Sleep(100 * time.Millisecond) - // Test AppSession Termination (Send SM policy Update which is related to App Session) - { - //Test DelPoliciesPolAssoId - httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdDeletePost(context.Background(), smPolicyId, models.SmPolicyDeleteData{}) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) - } - } - time.Sleep(100 * time.Millisecond) - { - // Get App Session - _, httpRsp, err := afclient.IndividualApplicationSessionContextDocumentApi.GetAppSession(context.Background(), appSessionId) - assert.True(t, err != nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusNotFound, httpRsp.StatusCode) - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - assert.Equal(t, "APPLICATION_SESSION_CONTEXT_NOT_FOUND", problem.Cause) - } - } - assert.True(t, len(pcf_context.PCF_Self().AppSessionPool) == 0) - assert.True(t, len(ue.SmPolicyData) == 0) - -} diff --git a/producer/ampolicy.go b/producer/ampolicy.go index 2cf9ff7..fceaf90 100644 --- a/producer/ampolicy.go +++ b/producer/ampolicy.go @@ -3,15 +3,17 @@ package pcf_producer import ( "context" "fmt" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" "free5gc/src/pcf/consumer" pcf_context "free5gc/src/pcf/context" "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" "free5gc/src/pcf/util" - "github.com/mohae/deepcopy" "net/http" "reflect" + + "github.com/mohae/deepcopy" ) func DeletePoliciesPolAssoId(httpChannel chan message.HttpResponseMessage, polAssoId string) { @@ -191,7 +193,8 @@ func PostPolicies(httpChannel chan message.HttpResponseMessage, request models.P // TODO: according to PCF Policy to determine ServAreaRes, Rfsp, SuppFeat // amPolicy.ServAreaRes = // amPolicy.Rfsp = - amPolicy.SuppFeat = util.GetNegotiateSuppFeat(request.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_AM_POLICY_CONTROL]) + requestSuppFeat, _ := openapi.NewSupportedFeature(request.SuppFeat) + amPolicy.SuppFeat = pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_AM_POLICY_CONTROL].NegotiateWith(requestSuppFeat).String() if amPolicy.Rfsp != 0 { rsp.Rfsp = amPolicy.Rfsp } diff --git a/producer/policyauthorization.go b/producer/policyauthorization.go index 5396dd1..1e286bc 100644 --- a/producer/policyauthorization.go +++ b/producer/policyauthorization.go @@ -3,6 +3,7 @@ package pcf_producer import ( "context" "fmt" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" pcf_context "free5gc/src/pcf/context" "free5gc/src/pcf/handler/message" @@ -27,16 +28,16 @@ import ( // PostAppSessions - Creates a new Individual Application Session Context resource func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, request models.AppSessionContext) { logger.PolicyAuthorizationlog.Traceln("Handle Create AppSessions") - reqData := request.AscReqData + ascReqData := request.AscReqData pcfSelf := pcf_context.PCF_Self() // Initial BDT policy indication(the only one which is not related to session) - if reqData.BdtRefId != "" { + if ascReqData.BdtRefId != "" { err := handleBackgroundDataTransferPolicyIndication(pcfSelf, &request) if err != nil { sendProblemDetail(httpChannel, err.Error(), util.ERROR_REQUEST_PARAMETERS) return } - appSessionId := fmt.Sprintf("BdtRefId-%s", reqData.BdtRefId) + appSessionId := fmt.Sprintf("BdtRefId-%s", ascReqData.BdtRefId) data := pcf_context.AppSessionData{ AppSessionId: appSessionId, AppSessionContext: &request, @@ -50,25 +51,31 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, request) return } - if request.AscReqData.UeIpv4 == "" && request.AscReqData.UeIpv6 == "" && request.AscReqData.UeMac == "" { + if ascReqData.UeIpv4 == "" && ascReqData.UeIpv6 == "" && ascReqData.UeMac == "" { sendProblemDetail(httpChannel, "Ue UeIpv4 and UeIpv6 and UeMac are all empty", util.ERROR_REQUEST_PARAMETERS) return } - smPolicy, err := pcfSelf.SessionBinding(request.AscReqData) + if ascReqData.AfRoutReq != nil && ascReqData.Dnn == "" { + sendProblemDetail(httpChannel, "DNN shall be present", util.ERROR_REQUEST_PARAMETERS) + return + } + smPolicy, err := pcfSelf.SessionBinding(ascReqData) if err != nil { sendProblemDetail(httpChannel, fmt.Sprintf("Session Binding failed[%s]", err.Error()), util.PDU_SESSION_NOT_AVAILABLE) return } ue := smPolicy.PcfUe updateSMpolicy := false - nSuppFeat := util.GetNegotiateSuppFeat(reqData.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION]) + + requestSuppFeat, _ := openapi.NewSupportedFeature(ascReqData.SuppFeat) + nSuppFeat := pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION].NegotiateWith(requestSuppFeat).String() traffRoutSupp := util.CheckSuppFeat(nSuppFeat, 1) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 relatedPccRuleIds := make(map[string]string) - if reqData.MedComponents != nil { + if ascReqData.MedComponents != nil { // Handle Pcc rules maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) - for _, mediaComponent := range reqData.MedComponents { + for _, mediaComponent := range ascReqData.MedComponents { var pccRule *models.PccRule // TODO: use specific algorithm instead of default, details in subsclause 7.3.3 of TS 29513 var var5qi int32 = 9 @@ -130,7 +137,7 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques } // Initial provisioning of traffic routing information if traffRoutSupp { - InitialProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, reqData.AfRoutReq) + InitialProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, ascReqData.AfRoutReq) } smPolicy.PolicyDecision.PccRules[pccRule.PccRuleId] = *pccRule key := fmt.Sprintf("%d-%d", mediaComponent.MedCompN, mediaSubComponent.FNum) @@ -139,15 +146,15 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques } continue } else if mediaComponent.AfAppId != "" { - // if mediaComponent.AfAppId has value -> find pccRule by reqData.AfAppId, otherwise create a new pcc rule + // if mediaComponent.AfAppId has value -> find pccRule by ascReqData.AfAppId, otherwise create a new pcc rule pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, mediaComponent.AfAppId) if pccRule != nil { pccRule.AppId = mediaComponent.AfAppId } - } else if reqData.AfAppId != "" { - pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, reqData.AfAppId) + } else if ascReqData.AfAppId != "" { + pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, ascReqData.AfAppId) if pccRule != nil { - pccRule.AppId = reqData.AfAppId + pccRule.AppId = ascReqData.AfAppId } } else { sendProblemDetail(httpChannel, "Media Component needs flows of subComp or afAppId", util.REQUESTED_SERVICE_NOT_AUTHORIZED) @@ -159,7 +166,7 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques if mediaComponent.AfAppId != "" { pccRule.AppId = mediaComponent.AfAppId } else { - pccRule.AppId = reqData.AfAppId + pccRule.AppId = ascReqData.AfAppId } // Set QoS Data // TODO: use real arp @@ -200,28 +207,29 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques // TODO : handle temporal or spatial validity // Initial provisioning of traffic routing information if traffRoutSupp { - InitialProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, reqData.AfRoutReq) + InitialProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, ascReqData.AfRoutReq) } updateSMpolicy = true } - } else if reqData.AfAppId != "" { + } else if ascReqData.AfAppId != "" { // Initial provisioning of traffic routing information - if reqData.AfRoutReq != nil && traffRoutSupp { + if ascReqData.AfRoutReq != nil && traffRoutSupp { decision := smPolicy.PolicyDecision cnt := 0 + createdTcData := models.TrafficControlData{ + FlowStatus: models.FlowStatus_ENABLED, + RouteToLocs: ascReqData.AfRoutReq.RouteToLocs, + UpPathChgEvent: ascReqData.AfRoutReq.UpPathChgSub, + } + for _, rule := range smPolicy.PolicyDecision.PccRules { - if rule.AppId == reqData.AfAppId { - tcData := models.TrafficControlData{ - TcId: strings.ReplaceAll(rule.PccRuleId, "PccRule", "Tc"), - FlowStatus: models.FlowStatus_ENABLED, - } - tcData.RouteToLocs = append(tcData.RouteToLocs, reqData.AfRoutReq.RouteToLocs...) - tcData.UpPathChgEvent = reqData.AfRoutReq.UpPathChgSub - rule.RefTcData = []string{tcData.TcId} - rule.AppReloc = reqData.AfRoutReq.AppReloc - util.SetPccRuleRelatedData(decision, &rule, &tcData, nil, nil, nil) + if rule.AppId == ascReqData.AfAppId { + createdTcData.TcId = strings.ReplaceAll(rule.PccRuleId, "PccRule", "Tc") + rule.RefTcData = []string{createdTcData.TcId} + rule.AppReloc = ascReqData.AfRoutReq.AppReloc + util.SetPccRuleRelatedData(decision, &rule, &createdTcData, nil, nil, nil) updateSMpolicy = true - key := fmt.Sprintf("appId-%s-%d", reqData.AfAppId, cnt) + key := fmt.Sprintf("appId-%s-%d", ascReqData.AfAppId, cnt) relatedPccRuleIds[key] = rule.PccRuleId cnt++ } @@ -230,18 +238,18 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques if !updateSMpolicy { maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) pccRule := util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) - pccRule.AppId = reqData.AfAppId + pccRule.AppId = ascReqData.AfAppId qosData := models.QosData{ QosId: util.GetQosId(smPolicy.PccRuleIdGenarator), DefQosFlowIndication: true, } - tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, "") - pccRule.RefTcData = []string{tcData.TcId} + createdTcData.TcId = util.GetTcId(smPolicy.PccRuleIdGenarator) + pccRule.RefTcData = []string{createdTcData.TcId} pccRule.RefQosData = []string{qosData.QosId} - util.SetPccRuleRelatedData(decision, pccRule, &tcData, &qosData, nil, nil) + util.SetPccRuleRelatedData(decision, pccRule, &createdTcData, &qosData, nil, nil) smPolicy.PccRuleIdGenarator++ updateSMpolicy = true - key := fmt.Sprintf("appId-%s", reqData.AfAppId) + key := fmt.Sprintf("appId-%s", ascReqData.AfAppId) relatedPccRuleIds[key] = pccRule.PccRuleId } } else { @@ -255,8 +263,8 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques // Event Subscription eventSubs := make(map[models.AfEvent]models.AfNotifMethod) - if reqData.EvSubsc != nil { - for _, subs := range reqData.EvSubsc.Events { + if ascReqData.EvSubsc != nil { + for _, subs := range ascReqData.EvSubsc.Events { if subs.NotifMethod == "" { // default value "EVENT_DETECTION" subs.NotifMethod = models.AfNotifMethod_EVENT_DETECTION @@ -300,19 +308,19 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques } // Initial provisioning of sponsored connectivity information - if reqData.AspId != "" && reqData.SponId != "" { + if ascReqData.AspId != "" && ascReqData.SponId != "" { supp := util.CheckSuppFeat(nSuppFeat, 2) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 12) // SponsoredConnectivity = 2 in 29514 & SponsoredConnectivity support = 12 in 29512 if !supp { sendProblemDetail(httpChannel, "Sponsored Connectivity not supported", util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } - umId := util.GetUmId(reqData.AspId, reqData.SponId) - umData, err := extractUmData(umId, eventSubs, reqData.EvSubsc.UsgThres) + umId := util.GetUmId(ascReqData.AspId, ascReqData.SponId) + umData, err := extractUmData(umId, eventSubs, ascReqData.EvSubsc.UsgThres) if err != nil { sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) return } - err = handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, reqData.AspId, reqData.SponId, reqData.SponStatus, umData, &updateSMpolicy) + err = handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, ascReqData.AspId, ascReqData.SponId, ascReqData.SponStatus, umData, &updateSMpolicy) if err != nil { return } @@ -338,7 +346,7 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques // Set Event Subsciption related Data if len(eventSubs) > 0 { data.Events = eventSubs - data.EventUri = reqData.EvSubsc.NotifUri + data.EventUri = ascReqData.EvSubsc.NotifUri if _, exist := eventSubs[models.AfEvent_PLMN_CHG]; exist { afNotif := models.AfEventNotification{ Event: models.AfEvent_PLMN_CHG, @@ -1011,9 +1019,11 @@ func SendAppSessionTermination(appSession *pcf_context.AppSessionData, request m // Handle Create/ Modify Background Data Transfer Policy Indication func handleBackgroundDataTransferPolicyIndication(pcfSelf *pcf_context.PCFContext, appContext *models.AppSessionContext) (err error) { req := appContext.AscReqData + + requestSuppFeat, _ := openapi.NewSupportedFeature(req.SuppFeat) respData := models.AppSessionContextRespData{ ServAuthInfo: models.ServAuthInfo_NOT_KNOWN, - SuppFeat: util.GetNegotiateSuppFeat(req.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION]), + SuppFeat: pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION].NegotiateWith(requestSuppFeat).String(), } client := util.GetNudrClient(getDefaultUdrUri(pcfSelf)) bdtData, resp, err1 := client.DefaultApi.PolicyDataBdtDataBdtReferenceIdGet(context.Background(), req.BdtRefId) diff --git a/producer/smpolicy.go b/producer/smpolicy.go index ab3280c..f9970d2 100644 --- a/producer/smpolicy.go +++ b/producer/smpolicy.go @@ -3,6 +3,7 @@ package pcf_producer import ( "context" "fmt" + "free5gc/lib/openapi" "free5gc/lib/openapi/Nudr_DataRepository" "free5gc/lib/openapi/models" pcf_context "free5gc/src/pcf/context" @@ -129,7 +130,9 @@ func CreateSmPolicy(httpChannel chan message.HttpResponseMessage, request models decision.Online = request.Online decision.Offline = request.Offline } - decision.SuppFeat = util.GetNegotiateSuppFeat(request.SuppFeat, pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_SMPOLICYCONTROL]) + + requestSuppFeat, _ := openapi.NewSupportedFeature(request.SuppFeat) + decision.SuppFeat = pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_SMPOLICYCONTROL].NegotiateWith(requestSuppFeat).String() decision.QosFlowUsage = request.QosFlowUsage // TODO: Trigger about UMC, ADC, NetLoc,... decision.PolicyCtrlReqTriggers = util.PolicyControlReqTrigToArray(0x40780f) diff --git a/service/init.go b/service/init.go index 0597c44..807d9d2 100644 --- a/service/init.go +++ b/service/init.go @@ -77,13 +77,18 @@ func (*PCF) Initialize(c *cli.Context) { factory.InitConfigFactory(DefaultPcfConfigPath) } - initLog.Traceln("PCF debug level(string):", app.ContextSelf().Logger.PCF.DebugLevel) if app.ContextSelf().Logger.PCF.DebugLevel != "" { - initLog.Infoln("PCF debug level(string):", app.ContextSelf().Logger.PCF.DebugLevel) level, err := logrus.ParseLevel(app.ContextSelf().Logger.PCF.DebugLevel) if err != nil { + initLog.Warnf("Log level [%s] is not valid, set to [info] level", app.ContextSelf().Logger.PCF.DebugLevel) + logger.SetLogLevel(logrus.InfoLevel) + } else { logger.SetLogLevel(level) + initLog.Infof("Log level is set to [%s] level", level) } + } else { + initLog.Infoln("Log level is default set to [info] level") + logger.SetLogLevel(logrus.InfoLevel) } logger.SetReportCaller(app.ContextSelf().Logger.PCF.ReportCaller) diff --git a/smpolicy/api_default_test.go b/smpolicy/api_default_test.go deleted file mode 100644 index 16432ef..0000000 --- a/smpolicy/api_default_test.go +++ /dev/null @@ -1,658 +0,0 @@ -package smpolicy_test - -import ( - "context" - "encoding/json" - "flag" - "fmt" - "free5gc/lib/CommonConsumerTestData/PCF/TestAMPolicy" - "free5gc/lib/CommonConsumerTestData/PCF/TestSMPolicy" - "free5gc/lib/MongoDBLibrary" - "free5gc/lib/http2_util" - "free5gc/lib/openapi" - "free5gc/lib/openapi/Npcf_AMPolicy" - "free5gc/lib/openapi/Npcf_SMPolicyControl" - "free5gc/lib/openapi/models" - "free5gc/lib/path_util" - amf_service "free5gc/src/amf/service" - "free5gc/src/app" - nrf_service "free5gc/src/nrf/service" - pcf_context "free5gc/src/pcf/context" - "free5gc/src/pcf/logger" - pcf_service "free5gc/src/pcf/service" - udr_service "free5gc/src/udr/service" - "net/http" - "reflect" - "strings" - "testing" - "time" - - "github.com/gin-gonic/gin" - "go.mongodb.org/mongo-driver/bson" - - "github.com/stretchr/testify/assert" - "github.com/urfave/cli" -) - -const amPolicyDataColl = "policyData.ues.amData" -const smPolicyDataColl = "policyData.ues.smData" - -var NFs = []app.NetworkFunction{ - &nrf_service.NRF{}, - &amf_service.AMF{}, - &udr_service.UDR{}, - &pcf_service.PCF{}, -} - -var filterUeIdOnly bson.M - -func toBsonM(data interface{}) bson.M { - tmp, _ := json.Marshal(data) - var putData = bson.M{} - _ = json.Unmarshal(tmp, &putData) - return putData -} -func insertDefaultPoliciesToDb(ueId string) { - amPolicyData := models.AmPolicyData{ - SubscCats: []string{ - "free5gc", - }, - } - - smPolicyData := models.SmPolicyData{ - SmPolicySnssaiData: map[string]models.SmPolicySnssaiData{ - "01010203": { - Snssai: &models.Snssai{ - Sd: "010203", - Sst: 1, - }, - SmPolicyDnnData: map[string]models.SmPolicyDnnData{ - "internet": { - Dnn: "internet", - GbrUl: "500 Mbps", - GbrDl: "500 Mbps", - AdcSupport: false, - Ipv4Index: 6, - Ipv6Index: 6, - Offline: true, - Online: false, - // ChfInfo - // RefUmDataLimitIds - // MpsPriority - // ImsSignallingPrio - // MpsPriorityLevel - // AllowedServices - // SubscCats - // SubscSpendingLimit - - }, - }, - }, - "01112233": { - Snssai: &models.Snssai{ - Sd: "112233", - Sst: 1, - }, - SmPolicyDnnData: map[string]models.SmPolicyDnnData{ - "internet": { - Dnn: "internet", - }, - }, - }, - }, - } - - filterUeIdOnly = bson.M{"ueId": ueId} - amPolicyDataBsonM := toBsonM(amPolicyData) - amPolicyDataBsonM["ueId"] = ueId - MongoDBLibrary.RestfulAPIPutOne(amPolicyDataColl, filterUeIdOnly, amPolicyDataBsonM) - smPolicyDataBsonM := toBsonM(smPolicyData) - smPolicyDataBsonM["ueId"] = ueId - MongoDBLibrary.RestfulAPIPost(smPolicyDataColl, filterUeIdOnly, smPolicyDataBsonM) -} - -func init() { - app.AppInitializeWillInitialize("") - flag := flag.FlagSet{} - cli := cli.NewContext(nil, &flag, nil) - for i, service := range NFs { - service.Initialize(cli) - go service.Start() - time.Sleep(300 * time.Millisecond) - if i == 0 { - MongoDBLibrary.RestfulAPIDeleteMany("NfProfile", bson.M{}) - time.Sleep(300 * time.Millisecond) - } - } - insertDefaultPoliciesToDb("imsi-2089300007487") - -} -func TestCreateSMPolicy(t *testing.T) { - defer MongoDBLibrary.RestfulAPIDeleteMany(amPolicyDataColl, filterUeIdOnly) - defer MongoDBLibrary.RestfulAPIDeleteMany(smPolicyDataColl, filterUeIdOnly) - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - amclient := Npcf_AMPolicy.NewAPIClient(configuration) - configuration1 := Npcf_SMPolicyControl.NewConfiguration() - configuration1.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - { - smCreateReqData := TestSMPolicy.CreateTestData() - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - // index := strings.LastIndex(locationHeader, "/") - assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") - } - } - { - smCreateReqData := TestSMPolicy.CreateTestData() - smCreateReqData.Supi = "" - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err != nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - assert.Equal(t, "ERROR_INITIAL_PARAMETERS", problem.Cause) - // assert.Equal(t, "Supi Format Error", problem.Detail) - } - } - { - smCreateReqData := TestSMPolicy.CreateTestData() - smCreateReqData.SliceInfo.Sd = "123" - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err != nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusBadRequest, httpRsp.StatusCode) - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - assert.Equal(t, "ERROR_INITIAL_PARAMETERS", problem.Cause) - // assert.Equal(t, "Supi Format Error", problem.Detail) - } - } -} - -func TestGetSMPolicy(t *testing.T) { - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - amclient := Npcf_AMPolicy.NewAPIClient(configuration) - configuration1 := Npcf_SMPolicyControl.NewConfiguration() - configuration1.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) - smPolicyId := "imsi-2089300007487-1" - smCreateReqData := TestSMPolicy.CreateTestData() - var decision models.SmPolicyDecision - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - { - tmp, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - // index := strings.LastIndex(locationHeader, "/") - assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") - } - decision = tmp - } - { - //Test GetPoliciesPolAssoId - rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - assert.True(t, reflect.DeepEqual(smCreateReqData, *rsp.Context)) - assert.True(t, reflect.DeepEqual(decision, *rsp.Policy)) - } - } - -} - -func TestDelSMPolicy(t *testing.T) { - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - amclient := Npcf_AMPolicy.NewAPIClient(configuration) - configuration1 := Npcf_SMPolicyControl.NewConfiguration() - configuration1.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) - smPolicyId := "imsi-2089300007487-1" - smCreateReqData := TestSMPolicy.CreateTestData() - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - { - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - // index := strings.LastIndex(locationHeader, "/") - assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") - } - } - { - //Test DelPoliciesPolAssoId - httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdDeletePost(context.Background(), smPolicyId, models.SmPolicyDeleteData{}) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) - } - } - { - //Test GetPoliciesPolAssoId - _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) - assert.True(t, err != nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusNotFound, httpRsp.StatusCode) - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - assert.Equal(t, "CONTEXT_NOT_FOUND", problem.Cause) - } - } -} - -func TestUpdateSMPolicy(t *testing.T) { - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - amclient := Npcf_AMPolicy.NewAPIClient(configuration) - configuration1 := Npcf_SMPolicyControl.NewConfiguration() - configuration1.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) - smPolicyId := "imsi-2089300007487-1" - smCreateReqData := TestSMPolicy.CreateTestData() - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - { - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - // index := strings.LastIndex(locationHeader, "/") - assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") - } - } - { - trigger := []models.PolicyControlRequestTrigger{ - models.PolicyControlRequestTrigger_PLMN_CH, - models.PolicyControlRequestTrigger_AC_TY_CH, - models.PolicyControlRequestTrigger_UE_IP_CH, - models.PolicyControlRequestTrigger_PS_DA_OFF, - models.PolicyControlRequestTrigger_DEF_QOS_CH, - models.PolicyControlRequestTrigger_SE_AMBR_CH, - models.PolicyControlRequestTrigger_SAREA_CH, - models.PolicyControlRequestTrigger_SCNN_CH, - models.PolicyControlRequestTrigger_RAT_TY_CH, - models.PolicyControlRequestTrigger_UE_TZ_CH, - } - updateReq := TestSMPolicy.UpdateTestData(trigger, nil) - updateReq.AccessType = models.AccessType_NON_3_GPP_ACCESS - updateReq.RatType = models.RatType_WLAN - //Test UpdatePoliciesPolAssoId - _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - // { - // //Test GetPoliciesPolAssoId - // rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) - // assert.True(t, err == nil) - // assert.True(t, httpRsp != nil) - // if httpRsp != nil { - // assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - // } - // } - // } - } - } - { - trigger := []models.PolicyControlRequestTrigger{ - models.PolicyControlRequestTrigger_AC_TY_CH, - models.PolicyControlRequestTrigger_RAT_TY_CH, - models.PolicyControlRequestTrigger_RES_MO_RE, - } - op := models.RuleOperation_CREATE_PCC_RULE - updateReq := TestSMPolicy.UpdateTestData(trigger, &op) - //Test UpdatePoliciesPolAssoId - _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { - { - //Test GetPoliciesPolAssoId - rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] - assert.True(t, exist) - req := updateReq.UeInitResReq - assert.Equal(t, rule.FlowInfos[0].FlowDescription, req.PackFiltInfo[0].PackFiltCont) - assert.True(t, models.FlowDirection(rule.FlowInfos[0].FlowDirection) == req.PackFiltInfo[0].FlowDirection) - assert.Equal(t, req.ReqQos.Var5qi, rsp.Policy.QosDecs[rule.RefQosData[0]].Var5qi) - assert.Equal(t, req.ReqQos.GbrUl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrUl) - assert.Equal(t, req.ReqQos.GbrDl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrDl) - } - } - } - } - } - { - trigger := []models.PolicyControlRequestTrigger{ - models.PolicyControlRequestTrigger_RES_MO_RE, - } - op := models.RuleOperation_MODIFY_PCC_RULE_AND_ADD_PACKET_FILTERS - updateReq := TestSMPolicy.UpdateTestData(trigger, &op) - //Test UpdatePoliciesPolAssoId - _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { - { - //Test GetPoliciesPolAssoId - rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] - assert.True(t, exist) - req := updateReq.UeInitResReq - assert.Equal(t, rule.FlowInfos[1].FlowDescription, req.PackFiltInfo[0].PackFiltCont) - assert.True(t, models.FlowDirection(rule.FlowInfos[1].FlowDirection) == req.PackFiltInfo[0].FlowDirection) - assert.Equal(t, req.ReqQos.Var5qi, rsp.Policy.QosDecs[rule.RefQosData[0]].Var5qi) - assert.Equal(t, req.ReqQos.GbrUl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrUl) - } - } - } - } - } - { - trigger := []models.PolicyControlRequestTrigger{ - models.PolicyControlRequestTrigger_RES_MO_RE, - } - op := models.RuleOperation_MODIFY_PCC_RULE_AND_DELETE_PACKET_FILTERS - updateReq := TestSMPolicy.UpdateTestData(trigger, &op) - //Test UpdatePoliciesPolAssoId - _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { - { - //Test GetPoliciesPolAssoId - rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] - assert.True(t, exist) - assert.True(t, len(rule.FlowInfos) == 1) - } - } - } - } - } - { - trigger := []models.PolicyControlRequestTrigger{ - models.PolicyControlRequestTrigger_RES_MO_RE, - } - op := models.RuleOperation_MODIFY_PCC_RULE_AND_REPLACE_PACKET_FILTERS - updateReq := TestSMPolicy.UpdateTestData(trigger, &op) - //Test UpdatePoliciesPolAssoId - _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { - { - //Test GetPoliciesPolAssoId - rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] - assert.True(t, exist) - assert.True(t, len(rule.FlowInfos) == 1) - req := updateReq.UeInitResReq - assert.Equal(t, rule.FlowInfos[0].FlowDescription, req.PackFiltInfo[0].PackFiltCont) - assert.True(t, models.FlowDirection(rule.FlowInfos[0].FlowDirection) == req.PackFiltInfo[0].FlowDirection) - } - } - } - } - } - { - trigger := []models.PolicyControlRequestTrigger{ - models.PolicyControlRequestTrigger_RES_MO_RE, - } - op := models.RuleOperation_MODIFY_PCC_RULE_WITHOUT_MODIFY_PACKET_FILTERS - updateReq := TestSMPolicy.UpdateTestData(trigger, &op) - //Test UpdatePoliciesPolAssoId - _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { - { - //Test GetPoliciesPolAssoId - rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - rule, exist := rsp.Policy.PccRules[updateReq.UeInitResReq.PccRuleId] - assert.True(t, exist) - req := updateReq.UeInitResReq - assert.Equal(t, req.ReqQos.Var5qi, rsp.Policy.QosDecs[rule.RefQosData[0]].Var5qi) - assert.Equal(t, req.ReqQos.GbrUl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrUl) - assert.Equal(t, req.ReqQos.GbrDl, rsp.Policy.QosDecs[rule.RefQosData[0]].GbrDl) - } - } - } - } - } - { - trigger := []models.PolicyControlRequestTrigger{ - models.PolicyControlRequestTrigger_RES_MO_RE, - } - op := models.RuleOperation_DELETE_PCC_RULE - updateReq := TestSMPolicy.UpdateTestData(trigger, &op) - //Test UpdatePoliciesPolAssoId - _, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdUpdatePost(context.Background(), smPolicyId, updateReq) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - if assert.Equal(t, http.StatusOK, httpRsp.StatusCode) { - { - //Test GetPoliciesPolAssoId - rsp, httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdGet(context.Background(), smPolicyId) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusOK, httpRsp.StatusCode) - assert.True(t, len(rsp.Policy.PccRules) == 0) - assert.True(t, len(rsp.Policy.QosDecs) == 0) - } - } - } - } - } -} - -func TestSMPolicyNotification(t *testing.T) { - - configuration := Npcf_AMPolicy.NewConfiguration() - configuration.SetBasePath("https://127.0.0.1:29507") - amclient := Npcf_AMPolicy.NewAPIClient(configuration) - configuration1 := Npcf_SMPolicyControl.NewConfiguration() - configuration1.SetBasePath("https://127.0.0.1:29507") - smclient := Npcf_SMPolicyControl.NewAPIClient(configuration1) - go func() { // fake udr server - router := gin.Default() - - router.POST("nsmf-callback/v1/sm-policies/:smPolicyId/update", func(c *gin.Context) { - smPolicyId := c.Param("smPolicyId") - fmt.Println("==========SM Policy Update Notification Callback=============") - fmt.Println("smPolicyId: ", smPolicyId) - - var notification models.SmPolicyNotification - if err := c.ShouldBindJSON(¬ification); err != nil { - fmt.Println("fake smf server error") - c.JSON(http.StatusInternalServerError, gin.H{}) - return - } - c.JSON(http.StatusNoContent, gin.H{}) - }) - - router.POST("nsmf-callback/v1/sm-policies/:smPolicyId/terminate", func(c *gin.Context) { - smPolicyId := c.Param("smPolicyId") - fmt.Println("==========SM Policy Terminate Callback=============") - fmt.Println("smPolicyId: ", smPolicyId) - - var terminationNotification models.TerminationNotification - if err := c.ShouldBindJSON(&terminationNotification); err != nil { - fmt.Println("fake smf server error") - c.JSON(http.StatusInternalServerError, gin.H{}) - return - } - c.JSON(http.StatusNoContent, gin.H{}) - httpRsp, err := smclient.DefaultApi.SmPoliciesSmPolicyIdDeletePost(context.Background(), smPolicyId, models.SmPolicyDeleteData{}) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusNoContent, httpRsp.StatusCode) - } - }) - - smfLogPath := path_util.Gofree5gcPath("free5gc/smfsslkey.log") - smfPemPath := path_util.Gofree5gcPath("free5gc/support/TLS/smf.pem") - smfKeyPath := path_util.Gofree5gcPath("free5gc/support/TLS/smf.key") - - server, err := http2_util.NewServer(":8888", smfLogPath, router) - if err == nil && server != nil { - logger.InitLog.Infoln(server.ListenAndServeTLS(smfPemPath, smfKeyPath)) - } - assert.True(t, err == nil) - }() - - time.Sleep(100 * time.Millisecond) - - //Test PostPolicies - { - amCreateReqData := TestAMPolicy.GetAMreqdata() - _, httpRsp, err := amclient.DefaultApi.PoliciesPost(context.Background(), amCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - index := strings.LastIndex(locationHeader, "/") - assert.True(t, index != -1) - polAssoId := locationHeader[index+1:] - assert.True(t, strings.HasPrefix(polAssoId, "imsi-2089300007487")) - } - } - smPolicyId := "imsi-2089300007487-1" - smCreateReqData := TestSMPolicy.CreateTestData() - smCreateReqData.NotificationUri = "https://127.0.0.1:8888/nsmf-callback/v1/sm-policies/imsi-2089300007487-1" - { - _, httpRsp, err := smclient.DefaultApi.SmPoliciesPost(context.Background(), smCreateReqData) - assert.True(t, err == nil) - assert.True(t, httpRsp != nil) - if httpRsp != nil { - assert.Equal(t, http.StatusCreated, httpRsp.StatusCode) - locationHeader := httpRsp.Header.Get("Location") - // index := strings.LastIndex(locationHeader, "/") - assert.True(t, locationHeader == "https://127.0.0.1:29507/npcf-smpolicycontrol/v1/sm-policies/imsi-2089300007487-1") - } - } - - ue := pcf_context.PCF_Self().UePool["imsi-2089300007487"] - //Test Policies Update Notify - notification := models.SmPolicyNotification{ - ResourceUri: smCreateReqData.NotificationUri, - } - producer.SendSMPolicyUpdateNotification(ue, smPolicyId, notification) - - //Test Policies Termination Notify - termination := models.TerminationNotification{ - ResourceUri: smCreateReqData.NotificationUri, - Cause: models.PolicyAssociationReleaseCause_UNSPECIFIED, - } - producer.SendSMPolicyTerminationRequestNotification(ue, smPolicyId, termination) - - time.Sleep(200 * time.Millisecond) -} diff --git a/util/init_context.go b/util/init_context.go index 52b2e5c..bc4236d 100644 --- a/util/init_context.go +++ b/util/init_context.go @@ -1,7 +1,7 @@ package util import ( - "encoding/hex" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" "free5gc/src/pcf/context" "free5gc/src/pcf/factory" @@ -43,6 +43,6 @@ func InitpcfContext(context *context.PCFContext) { context.DefaultBdtRefId = configuration.DefaultBdtRefId for _, service := range context.NfService { context.PcfServiceUris[service.ServiceName] = service.ApiPrefix + "/" + string(service.ServiceName) + "/" + (*service.Versions)[0].ApiVersionInUri - context.PcfSuppFeats[service.ServiceName], _ = hex.DecodeString(service.SupportedFeatures) + context.PcfSuppFeats[service.ServiceName], _ = openapi.NewSupportedFeature(service.SupportedFeatures) } } From 0090384c6b38ec79a344d7fd25cb09ce634d2db4 Mon Sep 17 00:00:00 2001 From: Endri Goshi Date: Thu, 20 Aug 2020 16:17:17 +0200 Subject: [PATCH 5/7] [UPDATE] Updated to latest code and made the changes of BindingIPv4 and RegisterIPv4. --- context/context.go | 2 +- factory/config.go | 5 ++--- service/init.go | 2 +- util/init_context.go | 22 +++++++++++----------- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/context/context.go b/context/context.go index 9eb438e..b4247ef 100644 --- a/context/context.go +++ b/context/context.go @@ -29,8 +29,8 @@ func init() { type PCFContext struct { NfId string Name string - ServerIPv4 string UriScheme models.UriScheme + BindingIPv4 string HttpIPv4Address string HttpIpv4Port int TimeFormat string diff --git a/factory/config.go b/factory/config.go index 0269ff4..10e97a9 100644 --- a/factory/config.go +++ b/factory/config.go @@ -19,8 +19,6 @@ type Info struct { type Configuration struct { PcfName string `yaml:"pcfName,omitempty"` - ServerIPv4 string `yaml:"serverIPv4,omitempty"` - Sbi *Sbi `yaml:"sbi,omitempty"` TimeFormat string `yaml:"timeFormat,omitempty"` @@ -39,7 +37,8 @@ type Service struct { type Sbi struct { Scheme string `yaml:"scheme"` - IPv4Addr string `yaml:"ipv4Addr,omitempty"` + RegisterIPv4 string `yaml:"registerIPv4,omitempty"` // IP that is registered at NRF. // IPv6Addr string `yaml:"ipv6Addr,omitempty"` + BindingIPv4 string `yaml:"bindingIPv4,omitempty"` // IP used to run the server in the node. Port int `yaml:"port,omitempty"` } diff --git a/service/init.go b/service/init.go index dce7c7f..1854fc6 100644 --- a/service/init.go +++ b/service/init.go @@ -131,7 +131,7 @@ func (pcf *PCF) Start() { self := context.PCF_Self() util.InitpcfContext(self) - addr := fmt.Sprintf("%s:%d", self.ServerIPv4, self.HttpIpv4Port) + addr := fmt.Sprintf("%s:%d", self.BindingIPv4, self.HttpIpv4Port) profile, err := consumer.BuildNFInstance(self) if err != nil { diff --git a/util/init_context.go b/util/init_context.go index 93684ac..7155fa9 100644 --- a/util/init_context.go +++ b/util/init_context.go @@ -20,23 +20,14 @@ func InitpcfContext(context *context.PCFContext) { if configuration.PcfName != "" { context.Name = configuration.PcfName } - context.ServerIPv4 = os.Getenv(configuration.ServerIPv4) - if context.ServerIPv4 == "" { - logger.UtilLog.Warn("Problem parsing ServerIPv4 address from ENV Variable. Trying to parse it as string.") - context.ServerIPv4 = configuration.ServerIPv4 - if context.ServerIPv4 == "" { - logger.UtilLog.Warn("Error parsing ServerIPv4 address as string. Using the localhost address as default.") - context.ServerIPv4 = "127.0.0.1" - } - } sbi := configuration.Sbi context.NrfUri = configuration.NrfUri context.UriScheme = models.UriScheme(sbi.Scheme) context.HttpIPv4Address = "127.0.0.1" // default localhost context.HttpIpv4Port = 29507 // default port if sbi != nil { - if sbi.IPv4Addr != "" { - context.HttpIPv4Address = sbi.IPv4Addr + if sbi.RegisterIPv4 != "" { + context.HttpIPv4Address = sbi.RegisterIPv4 } if sbi.Port != 0 { context.HttpIpv4Port = sbi.Port @@ -46,6 +37,15 @@ func InitpcfContext(context *context.PCFContext) { } else { context.UriScheme = models.UriScheme_HTTP } + context.BindingIPv4 = os.Getenv(sbi.BindingIPv4) + if context.BindingIPv4 == "" { + logger.UtilLog.Info("Problem parsing ServerIPv4 address from ENV Variable. Trying to parse it as string.") + context.BindingIPv4 = sbi.BindingIPv4 + if context.BindingIPv4 == "" { + logger.UtilLog.Info("Error parsing ServerIPv4 address as string. Using the 0.0.0.0 address as default.") + context.BindingIPv4 = "0.0.0.0" + } + } } serviceList := configuration.ServiceList context.InitNFService(serviceList, config.Info.Version) From 182b9a7310491c45e65b8a4cbe9195ad5441d0d2 Mon Sep 17 00:00:00 2001 From: free5gc-org Date: Mon, 28 Sep 2020 21:09:52 +0800 Subject: [PATCH 6/7] v2020-09-28-01 --- ampolicy/api_default.go | 153 ++- ampolicy/routers.go | 20 +- .../api_bdt_policies_collection_routers.go | 60 +- ..._individual_bdt_policy_document_routers.go | 76 +- bdtpolicy/routers.go | 10 +- consumer/communication.go | 8 +- consumer/nf_discovery.go | 7 +- consumer/nf_management.go | 7 +- context/context.go | 177 ++- context/ue.go | 62 +- factory/config.go | 2 +- handler/handler.go | 93 -- handler/message/channel.go | 23 - handler/message/event.go | 24 - handler/message/message.go | 125 -- httpcallback/amf_status_change_notify.go | 49 +- httpcallback/router.go | 12 +- httpcallback/sm_policy_notify.go | 52 +- logger/logger.go | 58 +- oam/api_get_am_policy.go | 32 +- oam/routers.go | 6 +- pcf.go | 4 +- .../api_application_sessions_collection.go | 59 +- .../api_events_subscription_document.go | 83 +- ...al_application_session_context_document.go | 127 +- policyauthorization/routers.go | 28 +- producer/ampolicy.go | 240 ++-- producer/bdtpolicy.go | 187 ++- producer/callback.go | 33 +- producer/handle_sm_policy_notify.go | 74 -- producer/oam.go | 44 +- producer/policyauthorization.go | 1138 +++++++++-------- producer/smpolicy.go | 379 ++++-- service/init.go | 45 +- smpolicy/api_default.go | 153 ++- smpolicy/routers.go | 12 +- uepolicy/routers.go | 4 +- util/convert.go | 3 +- util/init_context.go | 32 +- util/pcc_rule.go | 25 +- util/pcf_util.go | 24 +- util/search_nf_service.go | 3 +- version/version.go | 32 +- version/version_test.go | 47 + 44 files changed, 2294 insertions(+), 1538 deletions(-) delete mode 100644 handler/handler.go delete mode 100644 handler/message/channel.go delete mode 100644 handler/message/event.go delete mode 100644 handler/message/message.go delete mode 100644 producer/handle_sm_policy_notify.go create mode 100644 version/version_test.go diff --git a/ampolicy/api_default.go b/ampolicy/api_default.go index 93c5b8f..f4e768a 100644 --- a/ampolicy/api_default.go +++ b/ampolicy/api_default.go @@ -11,83 +11,162 @@ package ampolicy import ( "free5gc/lib/http_wrapper" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" "free5gc/src/pcf/logger" - "free5gc/src/pcf/handler/message" + "free5gc/src/pcf/producer" "free5gc/src/pcf/util" + "net/http" "github.com/gin-gonic/gin" ) -func PoliciesPolAssoIdDelete(c *gin.Context) { +func HTTPPoliciesPolAssoIdDelete(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["polAssoId"], _ = c.Params.Get("polAssoId") - channelMsg := message.NewHttpChannelMessage(message.EventAMPolicyDelete, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleDeletePoliciesPolAssoId(req) + + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.AMpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } -// PoliciesPolAssoIdGet - -func PoliciesPolAssoIdGet(c *gin.Context) { +// HTTPPoliciesPolAssoIdGet - +func HTTPPoliciesPolAssoIdGet(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["polAssoId"], _ = c.Params.Get("polAssoId") - channelMsg := message.NewHttpChannelMessage(message.EventAMPolicyGet, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleGetPoliciesPolAssoId(req) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.AMpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } -// PoliciesPolAssoIdUpdatePost - -func PoliciesPolAssoIdUpdatePost(c *gin.Context) { +// HTTPPoliciesPolAssoIdUpdatePost - +func HTTPPoliciesPolAssoIdUpdatePost(c *gin.Context) { var policyAssociationUpdateRequest models.PolicyAssociationUpdateRequest - err := c.ShouldBindJSON(&policyAssociationUpdateRequest) + + requestBody, err := c.GetRawData() if err != nil { - rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_REQUEST_PARAMETERS) - logger.HandlerLog.Errorln(rsp.Detail) - c.JSON(int(rsp.Status), rsp) + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.AMpolicylog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) return } + + err = openapi.Deserialize(&policyAssociationUpdateRequest, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.AMpolicylog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) + return + } + req := http_wrapper.NewRequest(c.Request, policyAssociationUpdateRequest) req.Params["polAssoId"], _ = c.Params.Get("polAssoId") - channelMsg := message.NewHttpChannelMessage(message.EventAMPolicyUpdate, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleUpdatePostPoliciesPolAssoId(req) + + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.AMpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } -// PoliciesPost - -func PoliciesPost(c *gin.Context) { +// HTTPPoliciesPost - +func HTTPPoliciesPost(c *gin.Context) { var policyAssociationRequest models.PolicyAssociationRequest - err := c.ShouldBindJSON(&policyAssociationRequest) + + requestBody, err := c.GetRawData() if err != nil { - rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_REQUEST_PARAMETERS) - logger.HandlerLog.Errorln(rsp.Detail) - c.JSON(int(rsp.Status), rsp) + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.AMpolicylog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) + return + } + + err = openapi.Deserialize(&policyAssociationRequest, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.AMpolicylog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) return } + if policyAssociationRequest.Supi == "" || policyAssociationRequest.NotificationUri == "" { rsp := util.GetProblemDetail("Miss Mandotory IE", util.ERROR_REQUEST_PARAMETERS) logger.HandlerLog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return } + req := http_wrapper.NewRequest(c.Request, policyAssociationRequest) - channelMsg := message.NewHttpChannelMessage(message.EventAMPolicyCreate, req) + req.Params["polAssoId"], _ = c.Params.Get("polAssoId") - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - for key, val := range HTTPResponse.Header { + rsp := producer.HandlePostPolicies(req) + + for key, val := range rsp.Header { c.Header(key, val[0]) } - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.AMpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } diff --git a/ampolicy/routers.go b/ampolicy/routers.go index d67df3f..8e54af9 100644 --- a/ampolicy/routers.go +++ b/ampolicy/routers.go @@ -10,6 +10,8 @@ package ampolicy import ( + "free5gc/lib/logger_util" + "free5gc/src/pcf/logger" "net/http" "strings" @@ -33,7 +35,7 @@ type Routes []Route // NewRouter returns a new router. func NewRouter() *gin.Engine { - router := gin.Default() + router := logger_util.NewGinWithLogrus(logger.GinLog) AddService(router) return router } @@ -72,30 +74,30 @@ var routes = Routes{ }, { - "PoliciesPolAssoIdDelete", + "HTTPPoliciesPolAssoIdDelete", strings.ToUpper("Delete"), "/policies/:polAssoId", - PoliciesPolAssoIdDelete, + HTTPPoliciesPolAssoIdDelete, }, { - "PoliciesPolAssoIdGet", + "HTTPPoliciesPolAssoIdGet", strings.ToUpper("Get"), "/policies/:polAssoId", - PoliciesPolAssoIdGet, + HTTPPoliciesPolAssoIdGet, }, { - "PoliciesPolAssoIdUpdatePost", + "HTTPPoliciesPolAssoIdUpdatePost", strings.ToUpper("Post"), "/policies/:polAssoId/update", - PoliciesPolAssoIdUpdatePost, + HTTPPoliciesPolAssoIdUpdatePost, }, { - "PoliciesPost", + "HTTPPoliciesPost", strings.ToUpper("Post"), "/policies", - PoliciesPost, + HTTPPoliciesPost, }, } diff --git a/bdtpolicy/api_bdt_policies_collection_routers.go b/bdtpolicy/api_bdt_policies_collection_routers.go index e0fb758..06efa53 100644 --- a/bdtpolicy/api_bdt_policies_collection_routers.go +++ b/bdtpolicy/api_bdt_policies_collection_routers.go @@ -11,27 +11,61 @@ package bdtpolicy import ( "free5gc/lib/http_wrapper" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" - "free5gc/src/pcf/handler/message" - + "free5gc/src/pcf/logger" + "free5gc/src/pcf/producer" "github.com/gin-gonic/gin" + "net/http" ) //CreateBDTPolicy - Create a new Individual BDT policy -func CreateBDTPolicy(c *gin.Context) { +func HTTPCreateBDTPolicy(c *gin.Context) { var bdtReqData models.BdtReqData - c.ShouldBindJSON(&bdtReqData) - - req := http_wrapper.NewRequest(c.Request, bdtReqData) - channelMsg := message.NewHttpChannelMessage(message.EventBDTPolicyCreate, req) + // step 1: retrieve http request body + requestBody, err := c.GetRawData() + if err != nil { + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.Bdtpolicylog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) + return + } - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse + // step 2: convert requestBody to openapi models + err = openapi.Deserialize(&bdtReqData, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.Bdtpolicylog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) + return + } - for key, val := range HTTPResponse.Header { + req := http_wrapper.NewRequest(c.Request, bdtReqData) + rsp := producer.HandleCreateBDTPolicyContextRequest(req) + // step 5: response + for key, val := range rsp.Header { // header response is optional c.Header(key, val[0]) } - - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.Bdtpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } diff --git a/bdtpolicy/api_individual_bdt_policy_document_routers.go b/bdtpolicy/api_individual_bdt_policy_document_routers.go index 0a8bf4b..eee779f 100644 --- a/bdtpolicy/api_individual_bdt_policy_document_routers.go +++ b/bdtpolicy/api_individual_bdt_policy_document_routers.go @@ -11,35 +11,81 @@ package bdtpolicy import ( "free5gc/lib/http_wrapper" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" - "free5gc/src/pcf/handler/message" - + "free5gc/src/pcf/logger" + "free5gc/src/pcf/producer" "github.com/gin-gonic/gin" + "net/http" ) // GetBDTPolicy - Read an Individual BDT policy -func GetBDTPolicy(c *gin.Context) { +func HTTPGetBDTPolicy(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["bdtPolicyId"] = c.Params.ByName("bdtPolicyId") - channelMsg := message.NewHttpChannelMessage(message.EventBDTPolicyGet, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleGetBDTPolicyContextRequest(req) + + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.Bdtpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } // UpdateBDTPolicy - Update an Individual BDT policy -func UpdateBDTPolicy(c *gin.Context) { +func HTTPUpdateBDTPolicy(c *gin.Context) { var bdtPolicyDataPatch models.BdtPolicyDataPatch - c.ShouldBindJSON(&bdtPolicyDataPatch) + // step 1: retrieve http request body + requestBody, err := c.GetRawData() + if err != nil { + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.Bdtpolicylog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) + return + } + + // step 2: convert requestBody to openapi models + err = openapi.Deserialize(&bdtPolicyDataPatch, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.Bdtpolicylog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) + return + } req := http_wrapper.NewRequest(c.Request, bdtPolicyDataPatch) req.Params["bdtPolicyId"] = c.Params.ByName("bdtPolicyId") - channelMsg := message.NewHttpChannelMessage(message.EventBDTPolicyUpdate, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleUpdateBDTPolicyContextProcedure(req) + + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.Bdtpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } diff --git a/bdtpolicy/routers.go b/bdtpolicy/routers.go index 2c336f2..b73e98b 100644 --- a/bdtpolicy/routers.go +++ b/bdtpolicy/routers.go @@ -10,6 +10,8 @@ package bdtpolicy import ( + "free5gc/lib/logger_util" + "free5gc/src/pcf/logger" "net/http" "strings" @@ -33,7 +35,7 @@ type Routes []Route // NewRouter returns a new router. func NewRouter() *gin.Engine { - router := gin.Default() + router := logger_util.NewGinWithLogrus(logger.GinLog) AddService(router) return router } @@ -75,20 +77,20 @@ var routes = Routes{ "CreateBDTPolicy", strings.ToUpper("Post"), "/bdtpolicies", - CreateBDTPolicy, + HTTPCreateBDTPolicy, }, { "GetBDTPolicy", strings.ToUpper("Get"), "/bdtpolicies/:bdtPolicyId", - GetBDTPolicy, + HTTPGetBDTPolicy, }, { "UpdateBDTPolicy", strings.ToUpper("Patch"), "/bdtpolicies/:bdtPolicyId", - UpdateBDTPolicy, + HTTPUpdateBDTPolicy, }, } diff --git a/consumer/communication.go b/consumer/communication.go index 3ab3593..50b9d7e 100644 --- a/consumer/communication.go +++ b/consumer/communication.go @@ -11,7 +11,8 @@ import ( "strings" ) -func AmfStatusChangeSubscribe(amfInfo pcf_context.AMFStatusSubscriptionData) (problemDetails *models.ProblemDetails, err error) { +func AmfStatusChangeSubscribe(amfInfo pcf_context.AMFStatusSubscriptionData) ( + problemDetails *models.ProblemDetails, err error) { logger.Consumerlog.Debugf("PCF Subscribe to AMF status[%+v]", amfInfo.AmfUri) pcfSelf := pcf_context.PCF_Self() client := util.GetNamfClient(amfInfo.AmfUri) @@ -21,7 +22,8 @@ func AmfStatusChangeSubscribe(amfInfo pcf_context.AMFStatusSubscriptionData) (pr GuamiList: amfInfo.GuamiList, } - res, httpResp, localErr := client.SubscriptionsCollectionDocumentApi.AMFStatusChangeSubscribe(context.Background(), subscriptionData) + res, httpResp, localErr := + client.SubscriptionsCollectionDocumentApi.AMFStatusChangeSubscribe(context.Background(), subscriptionData) if localErr == nil { locationHeader := httpResp.Header.Get("Location") logger.Consumerlog.Debugf("location header: %+v", locationHeader) @@ -43,5 +45,5 @@ func AmfStatusChangeSubscribe(amfInfo pcf_context.AMFStatusSubscriptionData) (pr } else { err = openapi.ReportError("%s: server no response", amfInfo.AmfUri) } - return + return problemDetails, err } diff --git a/consumer/nf_discovery.go b/consumer/nf_discovery.go index 005c64a..c3e0563 100644 --- a/consumer/nf_discovery.go +++ b/consumer/nf_discovery.go @@ -13,7 +13,9 @@ import ( "github.com/antihax/optional" ) -func SendSearchNFInstances(nrfUri string, targetNfType, requestNfType models.NfType, param Nnrf_NFDiscovery.SearchNFInstancesParamOpts) (result models.SearchResult, err error) { +func SendSearchNFInstances( + nrfUri string, targetNfType, requestNfType models.NfType, param Nnrf_NFDiscovery.SearchNFInstancesParamOpts) ( + result models.SearchResult, err error) { // Set client and set url configuration := Nnrf_NFDiscovery.NewConfiguration() @@ -83,7 +85,8 @@ func SendNFIntancesAMF(nrfUri string, guami models.Guami, serviceName models.Ser return "" } -func SearchAvailableAMFs(nrfUri string, serviceName models.ServiceName) (amfInfos []pcf_context.AMFStatusSubscriptionData) { +func SearchAvailableAMFs(nrfUri string, serviceName models.ServiceName) ( + amfInfos []pcf_context.AMFStatusSubscriptionData) { localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{} result, err := SendSearchNFInstances(nrfUri, models.NfType_AMF, models.NfType_PCF, localVarOptionals) diff --git a/consumer/nf_management.go b/consumer/nf_management.go index 12b9833..0c23174 100644 --- a/consumer/nf_management.go +++ b/consumer/nf_management.go @@ -15,7 +15,7 @@ func BuildNFInstance(context *pcf_context.PCFContext) (profile models.NfProfile, profile.NfInstanceId = context.NfId profile.NfType = models.NfType_PCF profile.NfStatus = models.NfStatus_REGISTERED - profile.Ipv4Addresses = append(profile.Ipv4Addresses, context.HttpIPv4Address) + profile.Ipv4Addresses = append(profile.Ipv4Addresses, context.RegisterIPv4) service := []models.NfService{} for _, nfService := range context.NfService { service = append(service, nfService) @@ -39,7 +39,8 @@ func BuildNFInstance(context *pcf_context.PCFContext) (profile models.NfProfile, return } -func SendRegisterNFInstance(nrfUri, nfInstanceId string, profile models.NfProfile) (resouceNrfUri string, retrieveNfInstanceID string, err error) { +func SendRegisterNFInstance(nrfUri, nfInstanceId string, profile models.NfProfile) ( + resouceNrfUri string, retrieveNfInstanceID string, err error) { // Set client and set url configuration := Nnrf_NFManagement.NewConfiguration() @@ -69,5 +70,5 @@ func SendRegisterNFInstance(nrfUri, nfInstanceId string, profile models.NfProfil fmt.Println("NRF return wrong status code", status) } } - return + return resouceNrfUri, retrieveNfInstanceID, err } diff --git a/context/context.go b/context/context.go index 5714049..c028c7d 100644 --- a/context/context.go +++ b/context/context.go @@ -2,11 +2,15 @@ package context import ( "fmt" + "free5gc/lib/idgenerator" "free5gc/lib/openapi" "free5gc/lib/openapi/models" "free5gc/src/pcf/factory" + "free5gc/src/pcf/logger" + "math" "strconv" "strings" + "sync" ) var pcfContext = PCFContext{} @@ -19,10 +23,7 @@ func init() { PCF_Self().NfService = make(map[models.ServiceName]models.NfService) PCF_Self().PcfServiceUris = make(map[models.ServiceName]string) PCF_Self().PcfSuppFeats = make(map[models.ServiceName]openapi.SupportedFeature) - PCF_Self().UePool = make(map[string]*UeContext) - PCF_Self().BdtPolicyPool = make(map[string]models.BdtPolicy) - PCF_Self().BdtPolicyIdGenerator = 1 - PCF_Self().AppSessionPool = make(map[string]*AppSessionData) + PCF_Self().BdtPolicyIDGenerator = idgenerator.NewGenerator(1, math.MaxInt64) PCF_Self().AMFStatusSubsData = make(map[string]AMFStatusSubscriptionData) } @@ -31,23 +32,27 @@ type PCFContext struct { Name string UriScheme models.UriScheme BindingIPv4 string - HttpIPv4Address string // IP register to NRF - HttpIpv4Port int + RegisterIPv4 string + SBIPort int TimeFormat string DefaultBdtRefId string NfService map[models.ServiceName]models.NfService PcfServiceUris map[models.ServiceName]string PcfSuppFeats map[models.ServiceName]openapi.SupportedFeature NrfUri string - DefaultUdrUri string - UePool map[string]*UeContext + DefaultUdrURI string + //UePool map[string]*UeContext + UePool sync.Map // Bdt Policy related - BdtPolicyPool map[string]models.BdtPolicy // use BdtPolicyId as key - BdtPolicyIdGenerator uint64 + BdtPolicyPool sync.Map + BdtPolicyIDGenerator *idgenerator.IDGenerator // App Session related - AppSessionPool map[string]*AppSessionData // use AppSessionId(ue.Supi-%d) or (BdtRefId-%d) as key + AppSessionPool sync.Map // AMF Status Change Subscription related AMFStatusSubsData map[string]AMFStatusSubscriptionData // subscriptionId as key + + //lock + DefaultUdrURILock sync.RWMutex } type AMFStatusSubscriptionData struct { @@ -76,9 +81,6 @@ func PCF_Self() *PCFContext { func GetTimeformat() string { return pcfContext.TimeFormat } -func GetPcfContext() PCFContext { - return pcfContext -} func GetUri(name models.ServiceName) string { return pcfContext.PcfServiceUris[name] } @@ -95,7 +97,7 @@ var Ipv6_pool = make(map[string]string) const DefaultBdtRefId = "BdtPolicyId-" func (context *PCFContext) GetIPv4Uri() string { - return fmt.Sprintf("%s://%s:%d", context.UriScheme, context.HttpIPv4Address, context.HttpIpv4Port) + return fmt.Sprintf("%s://%s:%d", context.UriScheme, context.RegisterIPv4, context.SBIPort) } // Init NfService with supported service list ,and version of services @@ -118,9 +120,9 @@ func (context *PCFContext) InitNFService(serviceList []factory.Service, version ApiPrefix: context.GetIPv4Uri(), IpEndPoints: &[]models.IpEndPoint{ { - Ipv4Address: context.HttpIPv4Address, + Ipv4Address: context.RegisterIPv4, Transport: models.TransportProtocol_TCP, - Port: int32(context.HttpIpv4Port), + Port: int32(context.SBIPort), }, }, SupportedFeatures: service.SuppFeat, @@ -131,29 +133,29 @@ func (context *PCFContext) InitNFService(serviceList []factory.Service, version // Allocate PCF Ue with supi and add to pcf Context and returns allocated ue func (context *PCFContext) NewPCFUe(Supi string) (*UeContext, error) { if strings.HasPrefix(Supi, "imsi-") { - context.UePool[Supi] = &UeContext{} - context.UePool[Supi].SmPolicyData = make(map[string]*UeSmPolicyData) - context.UePool[Supi].AMPolicyData = make(map[string]*UeAMPolicyData) - context.UePool[Supi].PolAssociationIDGenerator = 1 - context.UePool[Supi].AppSessionIdGenerator = 1 - context.UePool[Supi].Supi = Supi - return context.UePool[Supi], nil + newUeContext := &UeContext{} + newUeContext.SmPolicyData = make(map[string]*UeSmPolicyData) + newUeContext.AMPolicyData = make(map[string]*UeAMPolicyData) + newUeContext.PolAssociationIDGenerator = 1 + newUeContext.AppSessionIDGenerator = idgenerator.NewGenerator(1, math.MaxInt64) + newUeContext.Supi = Supi + context.UePool.Store(Supi, newUeContext) + return newUeContext, nil } else { return nil, fmt.Errorf(" add Ue context fail ") } } // Return Bdt Policy Id with format "BdtPolicyId-%d" which be allocated -func (context *PCFContext) AllocBdtPolicyId() string { - bdtPolicyId := fmt.Sprintf("BdtPolicyId-%d", context.BdtPolicyIdGenerator) - _, exist := context.BdtPolicyPool[bdtPolicyId] - for exist { - context.BdtPolicyIdGenerator++ - bdtPolicyId := fmt.Sprintf("BdtPolicyId-%d", context.BdtPolicyIdGenerator) - _, exist = context.BdtPolicyPool[bdtPolicyId] +func (context *PCFContext) AllocBdtPolicyID() (bdtPolicyID string, err error) { + var allocID int64 + if allocID, err = context.BdtPolicyIDGenerator.Allocate(); err != nil { + logger.CtxLog.Warnf("Allocate pathID error: %+v", err) + return "", err } - context.BdtPolicyIdGenerator++ - return bdtPolicyId + + bdtPolicyID = fmt.Sprintf("BdtPolicyId-%d", allocID) + return bdtPolicyID, nil } // Find PcfUe which the policyId belongs to @@ -164,7 +166,10 @@ func (context *PCFContext) PCFUeFindByPolicyId(PolicyId string) *UeContext { } supi := PolicyId[:index] if supi != "" { - return context.UePool[supi] + if value, ok := context.UePool.Load(supi); ok { + ueContext := value.(*UeContext) + return ueContext + } } return nil } @@ -177,66 +182,110 @@ func (context *PCFContext) PCFUeFindByAppSessionId(appSessionId string) *UeConte } supi := appSessionId[:index] if supi != "" { - return context.UePool[supi] + if value, ok := context.UePool.Load(supi); ok { + ueContext := value.(*UeContext) + return ueContext + } } return nil } // Find PcfUe which Ipv4 belongs to func (context *PCFContext) PcfUeFindByIPv4(v4 string) *UeContext { - for _, ue := range context.UePool { - if ue.SMPolicyFindByIpv6(v4) != nil { - return ue + var ue *UeContext + context.UePool.Range(func(key, value interface{}) bool { + ue = value.(*UeContext) + if ue.SMPolicyFindByIpv4(v4) != nil { + return false + } else { + return true } - } - return nil + }) + + return ue } // Find PcfUe which Ipv6 belongs to func (context *PCFContext) PcfUeFindByIPv6(v6 string) *UeContext { - for _, ue := range context.UePool { + var ue *UeContext + context.UePool.Range(func(key, value interface{}) bool { + ue = value.(*UeContext) if ue.SMPolicyFindByIpv6(v6) != nil { - return ue + return false + } else { + return true + } + }) + + return ue +} + +// Find SMPolicy with AppSessionContext +func ueSMPolicyFindByAppSessionContext(ue *UeContext, req *models.AppSessionContextReqData) (*UeSmPolicyData, error) { + var policy *UeSmPolicyData + var err error + + if req.UeIpv4 != "" { + policy = ue.SMPolicyFindByIdentifiersIpv4(req.UeIpv4, req.SliceInfo, req.Dnn, req.IpDomain) + if policy == nil { + err = fmt.Errorf("Can't find Ue with Ipv4[%s]", req.UeIpv4) + } + } else if req.UeIpv6 != "" { + policy = ue.SMPolicyFindByIdentifiersIpv6(req.UeIpv6, req.SliceInfo, req.Dnn) + if policy == nil { + err = fmt.Errorf("Can't find Ue with Ipv6 prefix[%s]", req.UeIpv6) } + } else { + //TODO: find by MAC address + err = fmt.Errorf("Ue finding by MAC address does not support") } - return nil + return policy, err } // SessionBinding from application request to get corresponding Sm policy -func (context *PCFContext) SessionBinding(req *models.AppSessionContextReqData) (policy *UeSmPolicyData, err error) { - // TODO: support dnn, snssai, ... because Ip Address is not enough with same ip address in different ip domains, details in subclause 4.2.2.2 of TS 29514 +func (context *PCFContext) SessionBinding(req *models.AppSessionContextReqData) (*UeSmPolicyData, error) { var selectedUE *UeContext + var policy *UeSmPolicyData + var err error - if ue, exist := context.UePool[req.Supi]; exist { - selectedUE = ue + if req.Supi != "" { + if val, exist := context.UePool.Load(req.Supi); exist { + selectedUE = val.(*UeContext) + } } if req.Gpsi != "" && selectedUE == nil { - for _, ue := range context.UePool { + context.UePool.Range(func(key, value interface{}) bool { + ue := value.(*UeContext) if ue.Gpsi == req.Gpsi { selectedUE = ue + return false + } else { + return true } - } + }) } if selectedUE != nil { - if req.UeIpv4 != "" { - policy = selectedUE.SMPolicyFindByIdentifiersIpv4(req.UeIpv4, req.SliceInfo, req.Dnn) - } else if req.UeIpv6 != "" { - policy = selectedUE.SMPolicyFindByIdentifiersIpv6(req.UeIpv6, req.SliceInfo, req.Dnn) - } else { - err = fmt.Errorf("Ue finding by MAC address does not support") - } + policy, err = ueSMPolicyFindByAppSessionContext(selectedUE, req) + } else { + context.UePool.Range(func(key, value interface{}) bool { + ue := value.(*UeContext) + policy, err = ueSMPolicyFindByAppSessionContext(ue, req) + return true + }) } - - if err == nil && policy == nil { - if req.UeIpv4 != "" { - err = fmt.Errorf("Can't find Ue with Ipv4[%s]", req.UeIpv4) - } else { - err = fmt.Errorf("Can't find Ue with Ipv6[%s]", req.UeIpv6) - } + if policy == nil && err == nil { + err = fmt.Errorf("No SM policy found") } - return + return policy, err +} + +//SetDefaultUdrURI ... function to set DefaultUdrURI +func (context *PCFContext) SetDefaultUdrURI(uri string) { + context.DefaultUdrURILock.Lock() + defer context.DefaultUdrURILock.Unlock() + context.DefaultUdrURI = uri } func Ipv4Pool(ipindex int32) string { diff --git a/context/ue.go b/context/ue.go index 2dcc145..a29deb2 100644 --- a/context/ue.go +++ b/context/ue.go @@ -2,7 +2,9 @@ package context import ( "fmt" + "free5gc/lib/idgenerator" "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" "math" "reflect" "strconv" @@ -24,7 +26,8 @@ type UeContext struct { // SMPolicy SmPolicyData map[string]*UeSmPolicyData // use smPolicyId(ue.Supi-pduSessionId) as key // App Session Related - AppSessionIdGenerator uint64 + //AppSessionIDGenerator uint64 + AppSessionIDGenerator *idgenerator.IDGenerator // PolicyAuth AfRoutReq *models.AfRoutingRequirement AspId string @@ -119,7 +122,8 @@ func (ue *UeContext) NewUeAMPolicyData(assolId string, req models.PolicyAssociat } // returns UeSmPolicyData and insert related info to Ue with smPolId -func (ue *UeContext) NewUeSmPolicyData(key string, request models.SmPolicyContextData, smData *models.SmPolicyData) *UeSmPolicyData { +func (ue *UeContext) NewUeSmPolicyData( + key string, request models.SmPolicyContextData, smData *models.SmPolicyData) *UeSmPolicyData { if smData == nil { return nil } @@ -224,7 +228,8 @@ func (policy *UeSmPolicyData) RemovePccRule(pccRuleId string) error { // Check if the afEvent exists in smPolicy func (policy *UeSmPolicyData) CheckRelatedAfEvent(event models.AfEvent) (found bool) { for appSessionId := range policy.AppSessions { - if appSession, exist := PCF_Self().AppSessionPool[appSessionId]; exist { + if val, ok := PCF_Self().AppSessionPool.Load(appSessionId); ok { + appSession := val.(*AppSessionData) for afEvent := range appSession.Events { if afEvent == event { return true @@ -243,9 +248,11 @@ func (policy *UeSmPolicyData) ArrangeExistEventSubscription() (changed bool) { switch trigger { case models.PolicyControlRequestTrigger_PLMN_CH: // PLMN Change afEvent = models.AfEvent_PLMN_CHG - case models.PolicyControlRequestTrigger_QOS_NOTIF: // SMF notify PCF when receiving from RAN that QoS can/can't be guaranteed (subsclause 4.2.4.20 in TS29512) (always) + case models.PolicyControlRequestTrigger_QOS_NOTIF: + // SMF notify PCF when receiving from RAN that QoS can/can't be guaranteed (subsclause 4.2.4.20 in TS29512) (always) afEvent = models.AfEvent_QOS_NOTIF - case models.PolicyControlRequestTrigger_SUCC_RES_ALLO: // Successful resource allocation (subsclause 4.2.6.5.5, 4.2.4.14 in TS29512) + case models.PolicyControlRequestTrigger_SUCC_RES_ALLO: + // Successful resource allocation (subsclause 4.2.6.5.5, 4.2.4.14 in TS29512) afEvent = models.AfEvent_SUCCESSFUL_RESOURCES_ALLOCATION case models.PolicyControlRequestTrigger_AC_TY_CH: // Change of RatType afEvent = models.AfEvent_ACCESS_TYPE_CHANGE @@ -353,15 +360,14 @@ func (ue *UeContext) FindAMPolicy(anType models.AccessType, plmnId *models.Netwo // Return App Session Id with format "ue.Supi-%d" which be allocated func (ue *UeContext) AllocUeAppSessionId(context *PCFContext) string { - appSessionId := fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator) - _, exist := context.AppSessionPool[appSessionId] - for exist { - ue.AppSessionIdGenerator++ - appSessionId = fmt.Sprintf("%s-%d", ue.Supi, ue.AppSessionIdGenerator) - _, exist = context.AppSessionPool[appSessionId] + var allocID int64 + var err error + if allocID, err = ue.AppSessionIDGenerator.Allocate(); err != nil { + logger.CtxLog.Warnf("Allocate AppSessionId error: %+v", err) + return "" } - ue.AppSessionIdGenerator++ - return appSessionId + appSessionID := fmt.Sprintf("%s-%d", ue.Supi, allocID) + return appSessionID } // returns SM Policy by IPv4 @@ -384,11 +390,21 @@ func (ue *UeContext) SMPolicyFindByIpv6(v6 string) *UeSmPolicyData { return nil } -// returns SM Policy by IPv6 -func (ue *UeContext) SMPolicyFindByIdentifiersIpv4(v4 string, sNssai *models.Snssai, dnn string) *UeSmPolicyData { +// returns SM Policy by IPv4 +func (ue *UeContext) SMPolicyFindByIdentifiersIpv4( + v4 string, sNssai *models.Snssai, dnn string, ipDomain string) *UeSmPolicyData { for _, smPolicy := range ue.SmPolicyData { policyContext := smPolicy.PolicyContext - if policyContext.Ipv4Address == v4 && reflect.DeepEqual(sNssai, policyContext.SliceInfo) && policyContext.Dnn == dnn { + if policyContext.Ipv4Address == v4 { + if dnn != "" && policyContext.Dnn != dnn { + continue + } + if ipDomain != "" && policyContext.IpDomain != "" && policyContext.IpDomain != ipDomain { + continue + } + if sNssai != nil && !reflect.DeepEqual(sNssai, policyContext.SliceInfo) { + continue + } return smPolicy } } @@ -399,7 +415,13 @@ func (ue *UeContext) SMPolicyFindByIdentifiersIpv4(v4 string, sNssai *models.Sns func (ue *UeContext) SMPolicyFindByIdentifiersIpv6(v6 string, sNssai *models.Snssai, dnn string) *UeSmPolicyData { for _, smPolicy := range ue.SmPolicyData { policyContext := smPolicy.PolicyContext - if policyContext.Ipv6AddressPrefix == v6 && reflect.DeepEqual(sNssai, policyContext.SliceInfo) && policyContext.Dnn == dnn { + if policyContext.Ipv6AddressPrefix == v6 { + if dnn != "" && policyContext.Dnn != dnn { + continue + } + if sNssai != nil && !reflect.DeepEqual(sNssai, policyContext.SliceInfo) { + continue + } return smPolicy } } @@ -422,7 +444,7 @@ var CreateFailBdtDateStore []models.BdtData func ConvertBitRateToKbps(bitRate string) (kBitRate float64, err error) { list := strings.Split(bitRate, " ") if len(list) != 2 { - err := fmt.Errorf("bitRate format error") + err = fmt.Errorf("bitRate format error") return 0, err } // parse exponential value with 2 as base @@ -439,7 +461,7 @@ func ConvertBitRateToKbps(bitRate string) (kBitRate float64, err error) { case "bps": exp = -10.0 default: - err := fmt.Errorf("bitRate format error") + err = fmt.Errorf("bitRate format error") return 0, err } // parse value from string to float64 @@ -449,7 +471,7 @@ func ConvertBitRateToKbps(bitRate string) (kBitRate float64, err error) { } else { kBitRate = 0.0 } - return + return kBitRate, err } // Convert bitRate from float64 to String diff --git a/factory/config.go b/factory/config.go index 13d4a3e..93757a3 100644 --- a/factory/config.go +++ b/factory/config.go @@ -38,7 +38,7 @@ type Service struct { type Sbi struct { Scheme string `yaml:"scheme"` RegisterIPv4 string `yaml:"registerIPv4,omitempty"` // IP that is registered at NRF. - // IPv6Addr string `yaml:"ipv6Addr,omitempty"` + // IPv6Addr string `yaml:"ipv6Addr,omitempty"` BindingIPv4 string `yaml:"bindingIPv4,omitempty"` // IP used to run the server in the node. Port int `yaml:"port,omitempty"` } diff --git a/handler/handler.go b/handler/handler.go deleted file mode 100644 index cac7220..0000000 --- a/handler/handler.go +++ /dev/null @@ -1,93 +0,0 @@ -package handler - -import ( - "free5gc/lib/openapi/models" - "free5gc/src/pcf/handler/message" - "free5gc/src/pcf/logger" - "free5gc/src/pcf/producer" - "time" - - "github.com/sirupsen/logrus" -) - -var HandlerLog *logrus.Entry - -func init() { - // init Pool - HandlerLog = logger.HandlerLog -} - -func Handle() { - for { - select { - case msg, ok := <-message.PCFChannel: - if ok { - switch msg.Event { - case message.EventBDTPolicyCreate: - pcf_producer.CreateBDTPolicyContext(msg.HttpChannel, msg.HTTPRequest.Body.(models.BdtReqData)) - case message.EventBDTPolicyGet: - bdtPolicyId := msg.HTTPRequest.Params["bdtPolicyId"] - pcf_producer.GetBDTPolicyContext(msg.HttpChannel, bdtPolicyId) - case message.EventBDTPolicyUpdate: - bdtPolicyId := msg.HTTPRequest.Params["bdtPolicyId"] - pcf_producer.UpdateBDTPolicyContext(msg.HttpChannel, bdtPolicyId, msg.HTTPRequest.Body.(models.BdtPolicyDataPatch)) - case message.EventPostAppSessions: - pcf_producer.PostAppSessionsContext(msg.HttpChannel, msg.HTTPRequest.Body.(models.AppSessionContext)) - case message.EventGetAppSession: - appSessionId := msg.HTTPRequest.Params["appSessionId"] - pcf_producer.GetAppSessionContext(msg.HttpChannel, appSessionId) - case message.EventDeleteAppSession: - appSessionId := msg.HTTPRequest.Params["appSessionId"] - pcf_producer.DeleteAppSessionContext(msg.HttpChannel, appSessionId, msg.HTTPRequest.Body.(*models.EventsSubscReqData)) - case message.EventModAppSession: - appSessionId := msg.HTTPRequest.Params["appSessionId"] - pcf_producer.ModAppSessionContext(msg.HttpChannel, appSessionId, msg.HTTPRequest.Body.(models.AppSessionContextUpdateData)) - case message.EventDeleteEventsSubsc: - appSessionId := msg.HTTPRequest.Params["appSessionId"] - pcf_producer.DeleteEventsSubscContext(msg.HttpChannel, appSessionId) - case message.EventUpdateEventsSubsc: - appSessionId := msg.HTTPRequest.Params["appSessionId"] - pcf_producer.UpdateEventsSubscContext(msg.HttpChannel, appSessionId, msg.HTTPRequest.Body.(models.EventsSubscReqData)) - case message.EventAMPolicyGet: - PolAssoId := msg.HTTPRequest.Params["polAssoId"] - pcf_producer.GetPoliciesPolAssoId(msg.HttpChannel, PolAssoId) - case message.EventAMPolicyDelete: - PolAssoId := msg.HTTPRequest.Params["polAssoId"] - pcf_producer.DeletePoliciesPolAssoId(msg.HttpChannel, PolAssoId) - case message.EventAMPolicyCreate: - pcf_producer.PostPolicies(msg.HttpChannel, msg.HTTPRequest.Body.(models.PolicyAssociationRequest)) - case message.EventAMPolicyUpdate: - PolAssoId := msg.HTTPRequest.Params["polAssoId"] - pcf_producer.UpdatePostPoliciesPolAssoId(msg.HttpChannel, PolAssoId, msg.HTTPRequest.Body.(models.PolicyAssociationUpdateRequest)) - case message.EventSMPolicyCreate: - pcf_producer.CreateSmPolicy(msg.HttpChannel, msg.HTTPRequest.Body.(models.SmPolicyContextData)) - case message.EventSMPolicyGet: - smPolicyId := msg.HTTPRequest.Params["smPolicyId"] - pcf_producer.GetSmPolicyContext(msg.HttpChannel, smPolicyId) - case message.EventSMPolicyUpdate: - smPolicyId := msg.HTTPRequest.Params["smPolicyId"] - pcf_producer.UpdateSmPolicyContext(msg.HttpChannel, smPolicyId, msg.HTTPRequest.Body.(models.SmPolicyUpdateContextData)) - case message.EventSMPolicyDelete: - smPolicyId := msg.HTTPRequest.Params["smPolicyId"] - pcf_producer.DeleteSmPolicyContext(msg.HttpChannel, smPolicyId) - case message.EventSMPolicyNotify: - ReqURI := msg.HTTPRequest.Params["ReqURI"] - pcf_producer.HandleSmPolicyNotify(msg.HttpChannel, ReqURI, msg.HTTPRequest.Body.(models.PolicyDataChangeNotification)) - case message.EventAMFStatusChangeNotify: - pcf_producer.HandleAmfStatusChangeNotify(msg.HttpChannel, msg.HTTPRequest.Body.(models.AmfStatusChangeNotification)) - // TODO: http event dispatcher - case message.EventOAMGetAmPolicy: - supi := msg.HTTPRequest.Params["supi"] - pcf_producer.HandleOAMGetAmPolicy(msg.HttpChannel, supi) - default: - HandlerLog.Warnf("Event[%s] has not implemented", msg.Event) - } - } else { - HandlerLog.Errorln("Channel closed!") - } - - case <-time.After(time.Second * 1): - - } - } -} diff --git a/handler/message/channel.go b/handler/message/channel.go deleted file mode 100644 index 1f9362d..0000000 --- a/handler/message/channel.go +++ /dev/null @@ -1,23 +0,0 @@ -package message - -import ( - "sync" -) - -var PCFChannel chan ChannelMessage -var mtx sync.Mutex - -const ( - MaxChannel int = 100000 -) - -func init() { - // init Pool - PCFChannel = make(chan ChannelMessage, MaxChannel) -} - -func SendMessage(msg ChannelMessage) { - mtx.Lock() - PCFChannel <- msg - mtx.Unlock() -} diff --git a/handler/message/event.go b/handler/message/event.go deleted file mode 100644 index a764ca9..0000000 --- a/handler/message/event.go +++ /dev/null @@ -1,24 +0,0 @@ -package message - -const ( - EventBDTPolicyCreate = "BDTPolicyCreate Message" - EventBDTPolicyGet = "BDTPolicyGet Message" - EventBDTPolicyUpdate = "BDTPolicyUpdate Message" - EventPostAppSessions = "PolicyAuthorizationPostAppSessions Message" - EventGetAppSession = "PolicyAuthorizationGetAppSession Message" - EventDeleteAppSession = "PolicyAuthorizationDeleteAppSession Message" - EventModAppSession = "PolicyAuthorizationModAppSession Message" - EventDeleteEventsSubsc = "PolicyAuthorizationDeleteEventsSubsc Message" - EventUpdateEventsSubsc = "PolicyAuthorizationUpdateEventsSubsc Message" - EventAMPolicyCreate = "AMPolicyCreate Message" - EventAMPolicyGet = "AMPolicyGet Message" - EventAMPolicyUpdate = "AMPolicyUpdate Message" - EventAMPolicyDelete = "AMPolicyDelete Message" - EventSMPolicyCreate = "EventSMPolicyCreate Message" - EventSMPolicyGet = "EventSMPolicyGet Message" - EventSMPolicyUpdate = "EventSMPolicyUpdate Message" - EventSMPolicyDelete = "EventSMPolicyDelete Message" - EventSMPolicyNotify = "EventSMPolicyNotify Message" - EventAMFStatusChangeNotify = "EventAMFStatusChangeNotify Message" - EventOAMGetAmPolicy = "EventOAMGetAmPolicy Message" -) diff --git a/handler/message/message.go b/handler/message/message.go deleted file mode 100644 index 493ee9c..0000000 --- a/handler/message/message.go +++ /dev/null @@ -1,125 +0,0 @@ -package message - -import ( - "free5gc/lib/http_wrapper" - "free5gc/lib/openapi/models" - "net/http" -) - -type HttpResponseMessageType string - -const ( - HttpResponseMessageResponse HttpResponseMessageType = "HTTP Response" - HttpResponseMessageAddition HttpResponseMessageType = "HTTP Response Addition" - HttpResponseMessageResponseError HttpResponseMessageType = "HTTP Response Error" - HttpResponseMessageProblemDetails HttpResponseMessageType = "Problem Details" -) - -type ChannelMessage struct { - Event string - HTTPRequest *http_wrapper.Request - HttpChannel chan HttpResponseMessage // return Http response - Value interface{} // input/request value -} - -func NewHttpChannelMessage(event string, httpRequest *http_wrapper.Request) (msg ChannelMessage) { - msg = ChannelMessage{} - msg.Event = event - msg.HttpChannel = make(chan HttpResponseMessage) - if httpRequest != nil { - msg.HTTPRequest = httpRequest - } - return msg -} - -type HttpResponseMessage struct { - HTTPResponse *http_wrapper.Response -} - -/* Send HTTP Response to HTTP handler thread through HTTP channel, args[0] is response payload and args[1:] is Additional Value*/ -func SendHttpResponseMessage(channel chan HttpResponseMessage, header http.Header, status int, body interface{}) { - responseMsg := HttpResponseMessage{} - responseMsg.HTTPResponse = http_wrapper.NewResponse(status, header, body) - channel <- responseMsg -} - -/* -type EventCreateBDTPolicyCreateValue struct { - Request models.BdtReqData - RequestUri string -} - -type EventGetBDTPolicyCreateValue struct { - RequestUri string -} - -type EventUpdateBDTPolicyCreateValue struct { - Request models.BdtPolicyDataPatch - RequestUri string -} - -type EventPostAppSessionsCreateValue struct { - Request models.AppSessionContext - RequestUri string -} -*/ -type EventGetAppSessionCreateValue struct { - RequestUri string -} - -type EventDeleteAppSessionCreateValue struct { - RequestUri string -} - -type EventModAppSessionCreateValue struct { - Request models.AppSessionContextUpdateData - RequestUri string -} - -type EventDeleteEventsSubscCreateValue struct { - RequestUri string -} - -type EventUpdateEventsSubscCreateValue struct { - Request models.EventsSubscReqData - RequestUri string -} - -type EventCreateAMPolicyCreateValue struct { - Request models.PolicyAssociationRequest - RequestUri string -} - -type EventGetAMPolicyCreateValue struct { - RequestUri string -} - -type EventUpdateAMPolicyCreateValue struct { - Request models.PolicyAssociationUpdateRequest - RequestUri string -} - -type EventDeleteAMPolicyCreateValue struct { - RequestUri string -} -type EventCreateSMPolicyCreateValue struct { - Request models.SmPolicyContextData - RequestUri string -} - -type EventGetSMPolicyCreateValue struct { - RequestUri string -} - -type EventUpdateSMPolicyCreateValue struct { - Request models.SmPolicyUpdateContextData - RequestUri string -} - -type EventDeleteSMPolicyCreateValue struct { - RequestUri string -} -type EventNotifySMPolicyCreateValue struct { - Request models.PolicyDataChangeNotification - RequestUri string -} diff --git a/httpcallback/amf_status_change_notify.go b/httpcallback/amf_status_change_notify.go index d9641e0..7317ec1 100644 --- a/httpcallback/amf_status_change_notify.go +++ b/httpcallback/amf_status_change_notify.go @@ -2,17 +2,32 @@ package httpcallback import ( "free5gc/lib/http_wrapper" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "github.com/gin-gonic/gin" + "free5gc/src/pcf/producer" "net/http" + + "github.com/gin-gonic/gin" ) -func AmfStatusChangeNotify(c *gin.Context) { - var request models.AmfStatusChangeNotification +func HTTPAmfStatusChangeNotify(c *gin.Context) { + var amfStatusChangeNotification models.AmfStatusChangeNotification + + requestBody, err := c.GetRawData() + if err != nil { + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.CallbackLog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) + return + } - err := c.ShouldBindJSON(&request) + err = openapi.Deserialize(&amfStatusChangeNotification, requestBody, "application/json") if err != nil { problemDetail := "[Request Body] " + err.Error() rsp := models.ProblemDetails{ @@ -25,12 +40,24 @@ func AmfStatusChangeNotify(c *gin.Context) { return } - req := http_wrapper.NewRequest(c.Request, request) + req := http_wrapper.NewRequest(c.Request, amfStatusChangeNotification) - channelMsg := message.NewHttpChannelMessage(message.EventAMFStatusChangeNotify, req) - message.SendMessage(channelMsg) + rsp := producer.HandleAmfStatusChangeNotify(req) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + if rsp.Status == http.StatusNoContent { + c.Status(rsp.Status) + } else { + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.CallbackLog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } + } } diff --git a/httpcallback/router.go b/httpcallback/router.go index 50faa04..4360b8a 100644 --- a/httpcallback/router.go +++ b/httpcallback/router.go @@ -1,6 +1,8 @@ package httpcallback import ( + "free5gc/lib/logger_util" + "free5gc/src/pcf/logger" "net/http" "strings" @@ -24,7 +26,7 @@ type Routes []Route // NewRouter returns a new router. func NewRouter() *gin.Engine { - router := gin.Default() + router := logger_util.NewGinWithLogrus(logger.GinLog) AddService(router) return router } @@ -55,16 +57,16 @@ var routes = Routes{ }, { - "NudrNotify", + "HTTPNudrNotify", strings.ToUpper("Post"), "/nudr-notify/:supi", - NudrNotify, + HTTPNudrNotify, }, { - "AmfStatusChangeNotify", + "HTTPAmfStatusChangeNotify", strings.ToUpper("Post"), "/amfstatus", - AmfStatusChangeNotify, + HTTPAmfStatusChangeNotify, }, } diff --git a/httpcallback/sm_policy_notify.go b/httpcallback/sm_policy_notify.go index bdb78a0..1fcd1fd 100644 --- a/httpcallback/sm_policy_notify.go +++ b/httpcallback/sm_policy_notify.go @@ -2,26 +2,60 @@ package httpcallback import ( "free5gc/lib/http_wrapper" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" + "free5gc/src/pcf/producer" + "net/http" "github.com/gin-gonic/gin" ) // Nudr-Notify-smpolicy -func NudrNotify(c *gin.Context) { +func HTTPNudrNotify(c *gin.Context) { var policyDataChangeNotification models.PolicyDataChangeNotification - if err := c.ShouldBindJSON(&policyDataChangeNotification); err != nil { - logger.SMpolicylog.Warnln("Nudr Notify fail error message is : ", err) + + requestBody, err := c.GetRawData() + if err != nil { + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.CallbackLog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) + return + } + + err = openapi.Deserialize(&policyDataChangeNotification, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.CallbackLog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) + return } req := http_wrapper.NewRequest(c.Request, policyDataChangeNotification) req.Params["ReqURI"] = c.Params.ByName("supi") - channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyNotify, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleSmPolicyNotify(req) + + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.CallbackLog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } diff --git a/logger/logger.go b/logger/logger.go index 8e64185..8c8f515 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,11 +1,10 @@ package logger import ( - "fmt" "os" - "runtime" - "strings" + "time" + formatter "github.com/antonfisher/nested-logrus-formatter" "github.com/sirupsen/logrus" "free5gc/lib/logger_conf" @@ -24,30 +23,19 @@ var Consumerlog *logrus.Entry var UtilLog *logrus.Entry var CallbackLog *logrus.Entry var OamLog *logrus.Entry +var CtxLog *logrus.Entry +var GinLog *logrus.Entry func init() { log = logrus.New() - log.SetReportCaller(true) + log.SetReportCaller(false) - log.Formatter = &logrus.TextFormatter{ - ForceColors: true, - DisableColors: false, - EnvironmentOverrideColors: false, - DisableTimestamp: false, - FullTimestamp: true, - TimestampFormat: "", - DisableSorting: false, - SortingFunc: nil, - DisableLevelTruncation: false, - QuoteEmptyFields: false, - FieldMap: nil, - CallerPrettyfier: func(f *runtime.Frame) (string, string) { - orgFilename, _ := os.Getwd() - repopath := orgFilename - repopath = strings.Replace(repopath, "/bin", "", 1) - filename := strings.Replace(f.File, repopath, "", -1) - return fmt.Sprintf("%s()", f.Function), fmt.Sprintf("%s:%d", filename, f.Line) - }, + log.Formatter = &formatter.Formatter{ + TimestampFormat: time.RFC3339, + TrimMessages: true, + NoFieldsSpace: true, + HideKeys: true, + FieldsOrder: []string{"component", "category"}, } free5gcLogHook, err := logger_util.NewFileHook(logger_conf.Free5gcLogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) @@ -60,17 +48,19 @@ func init() { log.Hooks.Add(selfLogHook) } - AppLog = log.WithFields(logrus.Fields{"PCF": "app"}) - InitLog = log.WithFields(logrus.Fields{"PCF": "init"}) - HandlerLog = log.WithFields(logrus.Fields{"PCF": "Handler"}) - Bdtpolicylog = log.WithFields(logrus.Fields{"PCF": "bdtpolicy"}) - AMpolicylog = log.WithFields(logrus.Fields{"PCF": "ampolicy"}) - PolicyAuthorizationlog = log.WithFields(logrus.Fields{"PCF": "PolicyAuthorization"}) - SMpolicylog = log.WithFields(logrus.Fields{"PCF": "SMpolicy"}) - UtilLog = log.WithFields(logrus.Fields{"PCF": "Util"}) - CallbackLog = log.WithFields(logrus.Fields{"PCF": "Callback"}) - Consumerlog = log.WithFields(logrus.Fields{"PCF": "Consumer"}) - OamLog = log.WithFields(logrus.Fields{"PCF": "OAM"}) + AppLog = log.WithFields(logrus.Fields{"component": "PCF", "category": "App"}) + InitLog = log.WithFields(logrus.Fields{"component": "PCF", "category": "Init"}) + HandlerLog = log.WithFields(logrus.Fields{"component": "PCF", "category": "Handler"}) + Bdtpolicylog = log.WithFields(logrus.Fields{"component": "PCF", "category": "Bdtpolicy"}) + AMpolicylog = log.WithFields(logrus.Fields{"component": "PCF", "category": "Ampolicy"}) + PolicyAuthorizationlog = log.WithFields(logrus.Fields{"component": "PCF", "category": "PolicyAuth"}) + SMpolicylog = log.WithFields(logrus.Fields{"component": "PCF", "category": "SMpolicy"}) + UtilLog = log.WithFields(logrus.Fields{"component": "PCF", "category": "Util"}) + CallbackLog = log.WithFields(logrus.Fields{"component": "PCF", "category": "Callback"}) + Consumerlog = log.WithFields(logrus.Fields{"component": "PCF", "category": "Consumer"}) + OamLog = log.WithFields(logrus.Fields{"component": "PCF", "category": "OAM"}) + CtxLog = log.WithFields(logrus.Fields{"component": "PCF", "category": "Context"}) + GinLog = log.WithFields(logrus.Fields{"component": "PCF", "category": "GIN"}) } func SetLogLevel(level logrus.Level) { diff --git a/oam/api_get_am_policy.go b/oam/api_get_am_policy.go index 54c29c0..43e7538 100644 --- a/oam/api_get_am_policy.go +++ b/oam/api_get_am_policy.go @@ -1,9 +1,13 @@ package oam import ( - "github.com/gin-gonic/gin" "free5gc/lib/http_wrapper" - "free5gc/src/pcf/handler/message" + "free5gc/lib/openapi" + "free5gc/lib/openapi/models" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/producer" + "github.com/gin-gonic/gin" + "net/http" ) func setCorsHeader(c *gin.Context) { @@ -13,18 +17,24 @@ func setCorsHeader(c *gin.Context) { c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, PATCH, DELETE") } -func OAMGetAmPolicy(c *gin.Context) { +func HTTPOAMGetAmPolicy(c *gin.Context) { setCorsHeader(c) req := http_wrapper.NewRequest(c.Request, nil) req.Params["supi"] = c.Params.ByName("supi") - handlerMsg := message.NewHttpChannelMessage(message.EventOAMGetAmPolicy, req) - message.SendMessage(handlerMsg) - - rsp := <-handlerMsg.HttpChannel - - HTTPResponse := rsp.HTTPResponse - - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleOAMGetAmPolicyRequest(req) + + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.OamLog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } diff --git a/oam/routers.go b/oam/routers.go index 1b9996a..6a5f568 100644 --- a/oam/routers.go +++ b/oam/routers.go @@ -1,6 +1,8 @@ package oam import ( + "free5gc/lib/logger_util" + "free5gc/src/pcf/logger" "net/http" "github.com/gin-gonic/gin" @@ -23,7 +25,7 @@ type Routes []Route // NewRouter returns a new router. func NewRouter() *gin.Engine { - router := gin.Default() + router := logger_util.NewGinWithLogrus(logger.GinLog) AddService(router) return router } @@ -57,6 +59,6 @@ var routes = Routes{ "Get UE AM Policy Data", http.MethodGet, "/am-policy/:supi", - OAMGetAmPolicy, + HTTPOAMGetAmPolicy, }, } diff --git a/pcf.go b/pcf.go index 0b365f0..82e087b 100644 --- a/pcf.go +++ b/pcf.go @@ -1,7 +1,9 @@ /* * Npcf_BDTPolicyControl Service API * - * The Npcf_BDTPolicyControl Service is used by an NF service consumer to retrieve background data transfer policies from the PCF and to update the PCF with the background data transfer policy selected by the NF service consumer. + * The Npcf_BDTPolicyControl Service is used by an NF service consumer to + * retrieve background data transfer policies from the PCF and to update the PCF with + * the background data transfer policy selected by the NF service consumer. * * API version: 1.0.0 * Generated by: OpenAPI Generator (https://openapi-generator.tech) diff --git a/policyauthorization/api_application_sessions_collection.go b/policyauthorization/api_application_sessions_collection.go index 707da06..b75fd8d 100644 --- a/policyauthorization/api_application_sessions_collection.go +++ b/policyauthorization/api_application_sessions_collection.go @@ -11,42 +11,71 @@ package policyauthorization import ( "free5gc/lib/http_wrapper" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" + "free5gc/src/pcf/producer" "free5gc/src/pcf/util" + "net/http" "github.com/gin-gonic/gin" ) -// PostAppSessions - Creates a new Individual Application Session Context resource -func PostAppSessions(c *gin.Context) { +// HTTPPostAppSessions - Creates a new Individual Application Session Context resource +func HTTPPostAppSessions(c *gin.Context) { var appSessionContext models.AppSessionContext - err := c.ShouldBindJSON(&appSessionContext) + + requestBody, err := c.GetRawData() if err != nil { - rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_INITIAL_PARAMETERS) - logger.HandlerLog.Errorln(rsp.Detail) - c.JSON(int(rsp.Status), rsp) + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.PolicyAuthorizationlog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) + return + } + + err = openapi.Deserialize(&appSessionContext, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.PolicyAuthorizationlog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) return } + ascReqData := appSessionContext.AscReqData if ascReqData == nil || ascReqData.SuppFeat == "" || ascReqData.NotifUri == "" { // Check Mandatory IEs rsp := util.GetProblemDetail("Errorneous/Missing Mandotory IE", util.ERROR_INITIAL_PARAMETERS) - logger.HandlerLog.Errorln(rsp.Detail) + logger.PolicyAuthorizationlog.Errorln(rsp.Detail) c.JSON(int(rsp.Status), rsp) return } req := http_wrapper.NewRequest(c.Request, appSessionContext) - channelMsg := message.NewHttpChannelMessage(message.EventPostAppSessions, req) - - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse + rsp := producer.HandlePostAppSessionsContext(req) - for key, val := range HTTPResponse.Header { + for key, val := range rsp.Header { c.Header(key, val[0]) } - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.PolicyAuthorizationlog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } diff --git a/policyauthorization/api_events_subscription_document.go b/policyauthorization/api_events_subscription_document.go index 7c3f0d4..8ebdfbb 100644 --- a/policyauthorization/api_events_subscription_document.go +++ b/policyauthorization/api_events_subscription_document.go @@ -11,52 +11,89 @@ package policyauthorization import ( "free5gc/lib/http_wrapper" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" "free5gc/src/pcf/logger" - "free5gc/src/pcf/handler/message" + "free5gc/src/pcf/producer" "free5gc/src/pcf/util" + "net/http" "github.com/gin-gonic/gin" ) -// DeleteEventsSubsc - deletes the Events Subscription subresource -func DeleteEventsSubsc(c *gin.Context) { - +// HTTPDeleteEventsSubsc - deletes the Events Subscription subresource +func HTTPDeleteEventsSubsc(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := message.NewHttpChannelMessage(message.EventDeleteEventsSubsc, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel + rsp := producer.HandleDeleteEventsSubscContext(req) - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.PolicyAuthorizationlog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } -// UpdateEventsSubsc - creates or modifies an Events Subscription subresource -func UpdateEventsSubsc(c *gin.Context) { +// HTTPUpdateEventsSubsc - creates or modifies an Events Subscription subresource +func HTTPUpdateEventsSubsc(c *gin.Context) { var eventsSubscReqData models.EventsSubscReqData - err := c.ShouldBindJSON(&eventsSubscReqData) + + requestBody, err := c.GetRawData() if err != nil { - rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_REQUEST_PARAMETERS) - logger.HandlerLog.Errorln(rsp.Detail) - c.JSON(int(rsp.Status), rsp) + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.PolicyAuthorizationlog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) return } + + err = openapi.Deserialize(&eventsSubscReqData, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.PolicyAuthorizationlog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) + return + } + if eventsSubscReqData.Events == nil || eventsSubscReqData.NotifUri == "" { - rsp := util.GetProblemDetail("Errorneous/Missing Mandotory IE", util.ERROR_REQUEST_PARAMETERS) - logger.HandlerLog.Errorln(rsp.Detail) - c.JSON(int(rsp.Status), rsp) + problemDetail := util.GetProblemDetail("Errorneous/Missing Mandotory IE", util.ERROR_REQUEST_PARAMETERS) + logger.PolicyAuthorizationlog.Errorln(problemDetail.Detail) + c.JSON(int(problemDetail.Status), problemDetail) return } req := http_wrapper.NewRequest(c.Request, eventsSubscReqData) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := message.NewHttpChannelMessage(message.EventUpdateEventsSubsc, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel + rsp := producer.HandleUpdateEventsSubscContext(req) - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.PolicyAuthorizationlog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } diff --git a/policyauthorization/api_individual_application_session_context_document.go b/policyauthorization/api_individual_application_session_context_document.go index 9821685..d81c96c 100644 --- a/policyauthorization/api_individual_application_session_context_document.go +++ b/policyauthorization/api_individual_application_session_context_document.go @@ -11,59 +11,130 @@ package policyauthorization import ( "free5gc/lib/http_wrapper" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" - "free5gc/src/pcf/handler/message" + "free5gc/src/pcf/logger" + "free5gc/src/pcf/producer" + "net/http" "github.com/gin-gonic/gin" ) -// DeleteAppSession - Deletes an existing Individual Application Session Context -func DeleteAppSession(c *gin.Context) { - +// HTTPDeleteAppSession - Deletes an existing Individual Application Session Context +func HTTPDeleteAppSession(c *gin.Context) { var eventsSubscReqData *models.EventsSubscReqData - err := c.ShouldBindJSON(eventsSubscReqData) + + requestBody, err := c.GetRawData() + if err != nil { + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.PolicyAuthorizationlog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) + return + } + + err = openapi.Deserialize(&eventsSubscReqData, requestBody, "application/json") if err != nil { - eventsSubscReqData = nil + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.PolicyAuthorizationlog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) + return } req := http_wrapper.NewRequest(c.Request, eventsSubscReqData) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := message.NewHttpChannelMessage(message.EventDeleteAppSession, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel + rsp := producer.HandleDeleteAppSessionContext(req) - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.PolicyAuthorizationlog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } -// GetAppSession - Reads an existing Individual Application Session Context -func GetAppSession(c *gin.Context) { - +// HTTPGetAppSession - Reads an existing Individual Application Session Context +func HTTPGetAppSession(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := message.NewHttpChannelMessage(message.EventGetAppSession, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel + rsp := producer.HandleGetAppSessionContext(req) - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.PolicyAuthorizationlog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } -// ModAppSession - Modifies an existing Individual Application Session Context -func ModAppSession(c *gin.Context) { +// HTTPModAppSession - Modifies an existing Individual Application Session Context +func HTTPModAppSession(c *gin.Context) { var appSessionContextUpdateData models.AppSessionContextUpdateData - c.ShouldBindJSON(&appSessionContextUpdateData) + + requestBody, err := c.GetRawData() + if err != nil { + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.PolicyAuthorizationlog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) + return + } + + err = openapi.Deserialize(&appSessionContextUpdateData, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.PolicyAuthorizationlog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) + return + } req := http_wrapper.NewRequest(c.Request, appSessionContextUpdateData) req.Params["appSessionId"], _ = c.Params.Get("appSessionId") - channelMsg := message.NewHttpChannelMessage(message.EventModAppSession, req) - - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleModAppSessionContext(req) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.PolicyAuthorizationlog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } diff --git a/policyauthorization/routers.go b/policyauthorization/routers.go index 91cc1c9..410c19d 100644 --- a/policyauthorization/routers.go +++ b/policyauthorization/routers.go @@ -10,6 +10,8 @@ package policyauthorization import ( + "free5gc/lib/logger_util" + "free5gc/src/pcf/logger" "net/http" "strings" @@ -33,7 +35,7 @@ type Routes []Route // NewRouter returns a new router. func NewRouter() *gin.Engine { - router := gin.Default() + router := logger_util.NewGinWithLogrus(logger.GinLog) AddService(router) return router } @@ -72,44 +74,44 @@ var routes = Routes{ }, { - "PostAppSessions", + "HTTPPostAppSessions", strings.ToUpper("Post"), "/app-sessions", - PostAppSessions, + HTTPPostAppSessions, }, { - "DeleteEventsSubsc", + "HTTPDeleteEventsSubsc", strings.ToUpper("Delete"), "/app-sessions/:appSessionId/events-subscription", - DeleteEventsSubsc, + HTTPDeleteEventsSubsc, }, { - "UpdateEventsSubsc", + "HTTPUpdateEventsSubsc", strings.ToUpper("Put"), "/app-sessions/:appSessionId/events-subscription", - UpdateEventsSubsc, + HTTPUpdateEventsSubsc, }, { - "DeleteAppSession", + "HTTPDeleteAppSession", strings.ToUpper("Post"), "/app-sessions/:appSessionId/delete", - DeleteAppSession, + HTTPDeleteAppSession, }, { - "GetAppSession", + "HTTPGetAppSession", strings.ToUpper("Get"), "/app-sessions/:appSessionId", - GetAppSession, + HTTPGetAppSession, }, { - "ModAppSession", + "HTTPModAppSession", strings.ToUpper("Patch"), "/app-sessions/:appSessionId", - ModAppSession, + HTTPModAppSession, }, } diff --git a/producer/ampolicy.go b/producer/ampolicy.go index fceaf90..9ae06f3 100644 --- a/producer/ampolicy.go +++ b/producer/ampolicy.go @@ -1,13 +1,13 @@ -package pcf_producer +package producer import ( "context" "fmt" + "free5gc/lib/http_wrapper" "free5gc/lib/openapi" "free5gc/lib/openapi/models" "free5gc/src/pcf/consumer" pcf_context "free5gc/src/pcf/context" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" "free5gc/src/pcf/util" "net/http" @@ -16,30 +16,53 @@ import ( "github.com/mohae/deepcopy" ) -func DeletePoliciesPolAssoId(httpChannel chan message.HttpResponseMessage, polAssoId string) { +func HandleDeletePoliciesPolAssoId(request *http_wrapper.Request) *http_wrapper.Response { + logger.AMpolicylog.Infof("Handle Policy Association Delete") - logger.AMpolicylog.Traceln("Handle Policy Association Delete") + polAssoId := request.Params["polAssoId"] + problemDetails := DeletePoliciesPolAssoIdProcedure(polAssoId) + if problemDetails == nil { + return http_wrapper.NewResponse(http.StatusNoContent, nil, nil) + } else { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } +} + +func DeletePoliciesPolAssoIdProcedure(polAssoId string) *models.ProblemDetails { ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(polAssoId) if ue == nil || ue.AMPolicyData[polAssoId] == nil { - rsp := util.GetProblemDetail("polAssoId not found in PCF", util.CONTEXT_NOT_FOUND) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + problemDetails := util.GetProblemDetail("polAssoId not found in PCF", util.CONTEXT_NOT_FOUND) + return &problemDetails } delete(ue.AMPolicyData, polAssoId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + return nil } // PoliciesPolAssoIdGet - -func GetPoliciesPolAssoId(httpChannel chan message.HttpResponseMessage, polAssoId string) { +func HandleGetPoliciesPolAssoId(request *http_wrapper.Request) *http_wrapper.Response { + logger.AMpolicylog.Infof("Handle Policy Association Get") + + polAssoId := request.Params["polAssoId"] - logger.AMpolicylog.Traceln("Handle Policy Association Get") + response, problemDetails := GetPoliciesPolAssoIdProcedure(polAssoId) + if response != nil { + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) +} +func GetPoliciesPolAssoIdProcedure(polAssoId string) (*models.PolicyAssociation, *models.ProblemDetails) { ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(polAssoId) if ue == nil || ue.AMPolicyData[polAssoId] == nil { - rsp := util.GetProblemDetail("polAssoId not found in PCF", util.CONTEXT_NOT_FOUND) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + problemDetails := util.GetProblemDetail("polAssoId not found in PCF", util.CONTEXT_NOT_FOUND) + return nil, &problemDetails } amPolicyData := ue.AMPolicyData[polAssoId] rsp := models.PolicyAssociation{ @@ -60,117 +83,152 @@ func GetPoliciesPolAssoId(httpChannel chan message.HttpResponseMessage, polAssoI } } } - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) - + return &rsp, nil } -func UpdatePostPoliciesPolAssoId(httpChannel chan message.HttpResponseMessage, polAssoId string, request models.PolicyAssociationUpdateRequest) { - logger.AMpolicylog.Traceln("Handle Policy Association Update") +func HandleUpdatePostPoliciesPolAssoId(request *http_wrapper.Request) *http_wrapper.Response { + logger.AMpolicylog.Infof("Handle Policy Association Update") + polAssoId := request.Params["polAssoId"] + policyAssociationUpdateRequest := request.Body.(models.PolicyAssociationUpdateRequest) + + response, problemDetails := UpdatePostPoliciesPolAssoIdProcedure(polAssoId, policyAssociationUpdateRequest) + if response != nil { + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) +} + +func UpdatePostPoliciesPolAssoIdProcedure(polAssoId string, + policyAssociationUpdateRequest models.PolicyAssociationUpdateRequest) (*models.PolicyUpdate, *models.ProblemDetails) { ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(polAssoId) if ue == nil || ue.AMPolicyData[polAssoId] == nil { - rsp := util.GetProblemDetail("polAssoId not found in PCF", util.CONTEXT_NOT_FOUND) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + problemDetails := util.GetProblemDetail("polAssoId not found in PCF", util.CONTEXT_NOT_FOUND) + return nil, &problemDetails } amPolicyData := ue.AMPolicyData[polAssoId] - var rsp models.PolicyUpdate - if request.NotificationUri != "" { - amPolicyData.NotificationUri = request.NotificationUri + var response models.PolicyUpdate + if policyAssociationUpdateRequest.NotificationUri != "" { + amPolicyData.NotificationUri = policyAssociationUpdateRequest.NotificationUri } - if request.AltNotifIpv4Addrs != nil { - amPolicyData.AltNotifIpv4Addrs = request.AltNotifIpv4Addrs + if policyAssociationUpdateRequest.AltNotifIpv4Addrs != nil { + amPolicyData.AltNotifIpv4Addrs = policyAssociationUpdateRequest.AltNotifIpv4Addrs } - if request.AltNotifIpv6Addrs != nil { - amPolicyData.AltNotifIpv6Addrs = request.AltNotifIpv6Addrs + if policyAssociationUpdateRequest.AltNotifIpv6Addrs != nil { + amPolicyData.AltNotifIpv6Addrs = policyAssociationUpdateRequest.AltNotifIpv6Addrs } - for _, trigger := range request.Triggers { + for _, trigger := range policyAssociationUpdateRequest.Triggers { //TODO: Modify the value according to policies switch trigger { case models.RequestTrigger_LOC_CH: //TODO: report to AF subscriber - if request.UserLoc == nil { - rsp := util.GetProblemDetail("UserLoc are nli", util.ERROR_REQUEST_PARAMETERS) - logger.AMpolicylog.Warnln("UserLoc doesn't exist in Policy Association Requset Update while Triggers include LOC_CH") - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + if policyAssociationUpdateRequest.UserLoc == nil { + problemDetail := util.GetProblemDetail("UserLoc are nli", util.ERROR_REQUEST_PARAMETERS) + logger.AMpolicylog.Warnln( + "UserLoc doesn't exist in Policy Association Requset Update while Triggers include LOC_CH") + return nil, &problemDetail } - amPolicyData.UserLoc = request.UserLoc + amPolicyData.UserLoc = policyAssociationUpdateRequest.UserLoc logger.AMpolicylog.Infof("Ue[%s] UserLocation %+v", ue.Supi, amPolicyData.UserLoc) case models.RequestTrigger_PRA_CH: - if request.PraStatuses == nil { - rsp := util.GetProblemDetail("PraStatuses are nli", util.ERROR_REQUEST_PARAMETERS) - logger.AMpolicylog.Warnln("PraStatuses doesn't exist in Policy Association Requset Update while Triggers include PRA_CH") - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + if policyAssociationUpdateRequest.PraStatuses == nil { + problemDetail := util.GetProblemDetail("PraStatuses are nli", util.ERROR_REQUEST_PARAMETERS) + logger.AMpolicylog.Warnln("PraStatuses doesn't exist in Policy Association", + "Requset Update while Triggers include PRA_CH") + return nil, &problemDetail } - for praId, praInfo := range request.PraStatuses { + for praId, praInfo := range policyAssociationUpdateRequest.PraStatuses { //TODO: report to AF subscriber logger.AMpolicylog.Infof("Policy Association Presence Id[%s] change state to %s", praId, praInfo.PresenceState) } case models.RequestTrigger_SERV_AREA_CH: - if request.ServAreaRes == nil { - rsp := util.GetProblemDetail("ServAreaRes are nli", util.ERROR_REQUEST_PARAMETERS) - logger.AMpolicylog.Warnln("ServAreaRes doesn't exist in Policy Association Requset Update while Triggers include SERV_AREA_CH") - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + if policyAssociationUpdateRequest.ServAreaRes == nil { + problemDetail := util.GetProblemDetail("ServAreaRes are nli", util.ERROR_REQUEST_PARAMETERS) + logger.AMpolicylog.Warnln("ServAreaRes doesn't exist in Policy Association", + "Requset Update while Triggers include SERV_AREA_CH") + return nil, &problemDetail } else { - amPolicyData.ServAreaRes = request.ServAreaRes - rsp.ServAreaRes = request.ServAreaRes + amPolicyData.ServAreaRes = policyAssociationUpdateRequest.ServAreaRes + response.ServAreaRes = policyAssociationUpdateRequest.ServAreaRes } case models.RequestTrigger_RFSP_CH: - if request.Rfsp == 0 { - rsp := util.GetProblemDetail("Rfsp are nli", util.ERROR_REQUEST_PARAMETERS) + if policyAssociationUpdateRequest.Rfsp == 0 { + problemDetail := util.GetProblemDetail("Rfsp are nli", util.ERROR_REQUEST_PARAMETERS) logger.AMpolicylog.Warnln("Rfsp doesn't exist in Policy Association Requset Update while Triggers include RFSP_CH") - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + return nil, &problemDetail } else { - amPolicyData.Rfsp = request.Rfsp - rsp.Rfsp = request.Rfsp + amPolicyData.Rfsp = policyAssociationUpdateRequest.Rfsp + response.Rfsp = policyAssociationUpdateRequest.Rfsp } } } //TODO: handle TraceReq //TODO: Change Request Trigger Policies if needed - rsp.Triggers = amPolicyData.Triggers + response.Triggers = amPolicyData.Triggers //TODO: Change Policies if needed // rsp.Pras - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) - + return &response, nil } // Create AM Policy -func PostPolicies(httpChannel chan message.HttpResponseMessage, request models.PolicyAssociationRequest) { - var rsp models.PolicyAssociation - var err error +func HandlePostPolicies(request *http_wrapper.Request) *http_wrapper.Response { + logger.AMpolicylog.Infof("Handle Policy Association Request") + + polAssoId := request.Params["polAssoId"] + policyAssociationRequest := request.Body.(models.PolicyAssociationRequest) - logger.AMpolicylog.Traceln("Handle Policy Association Request") + response, locationHeader, problemDetails := PostPoliciesProcedure(polAssoId, policyAssociationRequest) + headers := http.Header{ + "Location": {locationHeader}, + } + if response != nil { + return http_wrapper.NewResponse(http.StatusCreated, headers, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) +} +func PostPoliciesProcedure(polAssoId string, + policyAssociationRequest models.PolicyAssociationRequest) (*models.PolicyAssociation, string, *models.ProblemDetails) { + var response models.PolicyAssociation pcfSelf := pcf_context.PCF_Self() - ue := pcfSelf.UePool[request.Supi] + var ue *pcf_context.UeContext + if val, ok := pcfSelf.UePool.Load(policyAssociationRequest.Supi); ok { + ue = val.(*pcf_context.UeContext) + } if ue == nil { - ue, err = pcfSelf.NewPCFUe(request.Supi) - if err != nil { + if newUe, err := pcfSelf.NewPCFUe(policyAssociationRequest.Supi); err != nil { // supi format dose not match "imsi-..." - rsp := util.GetProblemDetail("Supi Format Error", util.ERROR_REQUEST_PARAMETERS) + problemDetail := util.GetProblemDetail("Supi Format Error", util.ERROR_REQUEST_PARAMETERS) logger.AMpolicylog.Errorln(err.Error()) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + return nil, "", &problemDetail + } else { + ue = newUe } } udrUri := getUdrUri(ue) if udrUri == "" { // Can't find any UDR support this Ue - delete(pcfSelf.UePool, ue.Supi) - rsp := util.GetProblemDetail("Ue is not supported in PCF", util.USER_UNKNOWN) + pcfSelf.UePool.Delete(ue.Supi) + problemDetail := util.GetProblemDetail("Ue is not supported in PCF", util.USER_UNKNOWN) logger.AMpolicylog.Errorf("Ue[%s] is not supported in PCF", ue.Supi) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + return nil, "", &problemDetail } ue.UdrUri = udrUri - rsp.Request = deepcopy.Copy(&request).(*models.PolicyAssociationRequest) + response.Request = deepcopy.Copy(&policyAssociationRequest).(*models.PolicyAssociationRequest) assolId := fmt.Sprintf("%s-%d", ue.Supi, ue.PolAssociationIDGenerator) amPolicy := ue.AMPolicyData[assolId] @@ -179,13 +237,12 @@ func PostPolicies(httpChannel chan message.HttpResponseMessage, request models.P var response *http.Response amData, response, err := client.DefaultApi.PolicyDataUesUeIdAmDataGet(context.Background(), ue.Supi) if err != nil || response == nil || response.StatusCode != http.StatusOK { - rsp := util.GetProblemDetail("Can't find UE AM Policy Data in UDR", util.USER_UNKNOWN) + problemDetail := util.GetProblemDetail("Can't find UE AM Policy Data in UDR", util.USER_UNKNOWN) logger.AMpolicylog.Errorf("Can't find UE[%s] AM Policy Data in UDR", ue.Supi) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + return nil, "", &problemDetail } if amPolicy == nil { - amPolicy = ue.NewUeAMPolicyData(assolId, request) + amPolicy = ue.NewUeAMPolicyData(assolId, policyAssociationRequest) } amPolicy.AmPolicyData = &amData } @@ -193,34 +250,38 @@ func PostPolicies(httpChannel chan message.HttpResponseMessage, request models.P // TODO: according to PCF Policy to determine ServAreaRes, Rfsp, SuppFeat // amPolicy.ServAreaRes = // amPolicy.Rfsp = - requestSuppFeat, _ := openapi.NewSupportedFeature(request.SuppFeat) - amPolicy.SuppFeat = pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_AM_POLICY_CONTROL].NegotiateWith(requestSuppFeat).String() + var requestSuppFeat openapi.SupportedFeature + if suppFeat, err := openapi.NewSupportedFeature(policyAssociationRequest.SuppFeat); err != nil { + logger.AMpolicylog.Warnln(err) + } else { + requestSuppFeat = suppFeat + } + amPolicy.SuppFeat = pcfSelf.PcfSuppFeats[models. + ServiceName_NPCF_AM_POLICY_CONTROL].NegotiateWith( + requestSuppFeat).String() if amPolicy.Rfsp != 0 { - rsp.Rfsp = amPolicy.Rfsp + response.Rfsp = amPolicy.Rfsp } - rsp.SuppFeat = amPolicy.SuppFeat + response.SuppFeat = amPolicy.SuppFeat // TODO: add Reports // rsp.Triggers // rsp.Pras ue.PolAssociationIDGenerator++ // Create location header for update, delete, get locationHeader := util.GetResourceUri(models.ServiceName_NPCF_AM_POLICY_CONTROL, assolId) - headers := http.Header{ - "Location": {locationHeader}, - } logger.AMpolicylog.Tracef("AMPolicy association Id[%s] Create", assolId) - message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, rsp) - if request.Guami != nil { + if policyAssociationRequest.Guami != nil { // if consumer is AMF then subscribe this AMF Status for _, statusSubsData := range pcfSelf.AMFStatusSubsData { for _, guami := range statusSubsData.GuamiList { - if reflect.DeepEqual(guami, request.Guami) { + if reflect.DeepEqual(guami, policyAssociationRequest.Guami) { amPolicy.AmfStatusChangeSubscription = &statusSubsData } } } } + return &response, locationHeader, nil } // Send AM Policy Update to AMF if policy has changed @@ -268,21 +329,24 @@ func SendAMPolicyUpdateNotification(ue *pcf_context.UeContext, PolId string, req } // Send AM Policy Update to AMF if policy has been terminated -func SendAMPolicyTerminationRequestNotification(ue *pcf_context.UeContext, PolId string, request models.TerminationNotification) { +func SendAMPolicyTerminationRequestNotification(ue *pcf_context.UeContext, + PolId string, request models.TerminationNotification) { if ue == nil { logger.AMpolicylog.Warnln("Policy Assocition Termination Request Notification Error[Ue is nil]") return } amPolicyData := ue.AMPolicyData[PolId] if amPolicyData == nil { - logger.AMpolicylog.Warnf("Policy Assocition Termination Request Notification Error[Can't find polAssoId[%s] in UE(%s)]", PolId, ue.Supi) + logger.AMpolicylog.Warnf( + "Policy Assocition Termination Request Notification Error[Can't find polAssoId[%s] in UE(%s)]", PolId, ue.Supi) return } client := util.GetNpcfAMPolicyCallbackClient() uri := amPolicyData.NotificationUri for uri != "" { - rsp, err := client.DefaultCallbackApi.PolicyAssocitionTerminationRequestNotification(context.Background(), uri, request) + rsp, err := client.DefaultCallbackApi.PolicyAssocitionTerminationRequestNotification( + context.Background(), uri, request) if err != nil { if rsp != nil && rsp.StatusCode != http.StatusNoContent { logger.AMpolicylog.Warnf("Policy Assocition Termination Request Notification Error[%s]", rsp.Status) diff --git a/producer/bdtpolicy.go b/producer/bdtpolicy.go index 59f5945..da4f57e 100644 --- a/producer/bdtpolicy.go +++ b/producer/bdtpolicy.go @@ -1,14 +1,14 @@ -package pcf_producer +package producer import ( "context" "fmt" + "free5gc/lib/http_wrapper" "free5gc/lib/openapi/Nnrf_NFDiscovery" "free5gc/lib/openapi/Nudr_DataRepository" "free5gc/lib/openapi/models" "free5gc/src/pcf/consumer" pcf_context "free5gc/src/pcf/context" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" "free5gc/src/pcf/util" "net/http" @@ -19,36 +19,87 @@ import ( "github.com/antihax/optional" ) -func GetBDTPolicyContext(httpChannel chan message.HttpResponseMessage, bdtPolicyId string) { +func HandleGetBDTPolicyContextRequest(request *http_wrapper.Request) *http_wrapper.Response { + // step 1: log + logger.Bdtpolicylog.Infof("Handle GetBDTPolicyContext") + // step 2: retrieve request + bdtPolicyID := request.Params["bdtPolicyId"] + + // step 3: handle the message + response, problemDetails := getBDTPolicyContextProcedure(bdtPolicyID) + + // step 4: process the return value from step 3 + if response != nil { + // status code is based on SPEC, and option headers + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(http.StatusForbidden, nil, problemDetails) +} + +func getBDTPolicyContextProcedure(bdtPolicyID string) ( + response *models.BdtPolicy, problemDetails *models.ProblemDetails) { logger.Bdtpolicylog.Traceln("Handle BDT Policy GET") - // check BdtPolicyId from pcfUeContext - bdtPolicy, exist := pcf_context.PCF_Self().BdtPolicyPool[bdtPolicyId] - if !exist { + // check bdtPolicyID from pcfUeContext + if value, ok := pcf_context.PCF_Self().BdtPolicyPool.Load(bdtPolicyID); ok { + bdtPolicy := value.(*models.BdtPolicy) + return bdtPolicy, nil + } else { // not found - rsp := util.GetProblemDetail("Can't find BDTPolicyId related resource", util.CONTEXT_NOT_FOUND) - logger.Bdtpolicylog.Warnf(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + problemDetail := util.GetProblemDetail("Can't find bdtPolicyID related resource", util.CONTEXT_NOT_FOUND) + logger.Bdtpolicylog.Warnf(problemDetail.Detail) + return nil, &problemDetail } - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, bdtPolicy) - } // UpdateBDTPolicy - Update an Individual BDT policy (choose policy data) -func UpdateBDTPolicyContext(httpChannel chan message.HttpResponseMessage, bdtPolicyId string, request models.BdtPolicyDataPatch) { +func HandleUpdateBDTPolicyContextProcedure(request *http_wrapper.Request) *http_wrapper.Response { + // step 1: log + logger.Bdtpolicylog.Infof("Handle UpdateBDTPolicyContext") - logger.Bdtpolicylog.Traceln("Handle BDT Policy Update") - // check BdtPolicyId from pcfUeContext + // step 2: retrieve request + requestDataType := request.Body.(models.BdtPolicyDataPatch) + bdtPolicyID := request.Params["bdtPolicyId"] + + // step 3: handle the message + response, problemDetails := updateBDTPolicyContextProcedure(requestDataType, bdtPolicyID) + + // step 4: process the return value from step 3 + if response != nil { + // status code is based on SPEC, and option headers + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(http.StatusForbidden, nil, problemDetails) +} + +func updateBDTPolicyContextProcedure(request models.BdtPolicyDataPatch, bdtPolicyID string) ( + response *models.BdtPolicy, problemDetails *models.ProblemDetails) { + logger.Bdtpolicylog.Infoln("Handle BDTPolicyUpdate") + // check bdtPolicyID from pcfUeContext pcfSelf := pcf_context.PCF_Self() - bdtPolicy, exist := pcfSelf.BdtPolicyPool[bdtPolicyId] - if !exist { + + var bdtPolicy *models.BdtPolicy + if value, ok := pcf_context.PCF_Self().BdtPolicyPool.Load(bdtPolicyID); ok { + bdtPolicy = value.(*models.BdtPolicy) + } else { // not found - rsp := util.GetProblemDetail("Can't find BDTPolicyId related resource", util.CONTEXT_NOT_FOUND) - logger.Bdtpolicylog.Warnf(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + problemDetail := util.GetProblemDetail("Can't find bdtPolicyID related resource", util.CONTEXT_NOT_FOUND) + logger.Bdtpolicylog.Warnf(problemDetail.Detail) + return nil, &problemDetail } + for _, policy := range bdtPolicy.BdtPolData.TransfPolicies { if policy.TransPolicyId == request.SelTransPolicyId { polData := bdtPolicy.BdtPolData @@ -70,50 +121,74 @@ func UpdateBDTPolicyContext(httpChannel chan message.HttpResponseMessage, bdtPol if err != nil { logger.Bdtpolicylog.Warnf("UDR Put BdtDate error[%s]", err.Error()) } - logger.Bdtpolicylog.Tracef("BDTPolicyId[%s] has Updated with SelTransPolicyId[%d]", bdtPolicyId, request.SelTransPolicyId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, bdtPolicy) - return + logger.Bdtpolicylog.Tracef("bdtPolicyID[%s] has Updated with SelTransPolicyId[%d]", + bdtPolicyID, request.SelTransPolicyId) + return bdtPolicy, nil } } - rsp := util.GetProblemDetail(fmt.Sprintf("Can't find TransPolicyId[%d] in TransfPolicies with BDTPolicyId[%s]", request.SelTransPolicyId, bdtPolicyId), util.CONTEXT_NOT_FOUND) - logger.Bdtpolicylog.Warnf(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + problemDetail := util.GetProblemDetail( + fmt.Sprintf("Can't find TransPolicyId[%d] in TransfPolicies with bdtPolicyID[%s]", + request.SelTransPolicyId, bdtPolicyID), + util.CONTEXT_NOT_FOUND) + logger.Bdtpolicylog.Warnf(problemDetail.Detail) + return nil, &problemDetail } //CreateBDTPolicy - Create a new Individual BDT policy -func CreateBDTPolicyContext(httpChannel chan message.HttpResponseMessage, request models.BdtReqData) { - var rsp models.BdtPolicy +func HandleCreateBDTPolicyContextRequest(request *http_wrapper.Request) *http_wrapper.Response { + // step 1: log + logger.Bdtpolicylog.Infof("Handle CreateBDTPolicyContext") + + // step 2: retrieve request + requestMsg := request.Body.(models.BdtReqData) + + // step 3: handle the message + header, response, problemDetails := createBDTPolicyContextProcedure(&requestMsg) + + // step 4: process the return value from step 3 + if response != nil { + // status code is based on SPEC, and option headers + return http_wrapper.NewResponse(http.StatusCreated, header, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } else { + return http_wrapper.NewResponse(http.StatusNotFound, nil, nil) + } +} + +func createBDTPolicyContextProcedure(request *models.BdtReqData) ( + header http.Header, response *models.BdtPolicy, problemDetails *models.ProblemDetails) { + response = &models.BdtPolicy{} logger.Bdtpolicylog.Traceln("Handle BDT Policy Create") pcfSelf := pcf_context.PCF_Self() udrUri := getDefaultUdrUri(pcfSelf) if udrUri == "" { // Can't find any UDR support this Ue - rsp := models.ProblemDetails{ + problemDetails = &models.ProblemDetails{ Status: http.StatusServiceUnavailable, Detail: "Can't find any UDR which supported to this PCF", } - logger.Bdtpolicylog.Warnf(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + logger.Bdtpolicylog.Warnf(problemDetails.Detail) + return nil, nil, problemDetails } - pcfSelf.DefaultUdrUri = udrUri + pcfSelf.DefaultUdrURI = udrUri + pcfSelf.SetDefaultUdrURI(udrUri) // Query BDT DATA array from UDR client := util.GetNudrClient(udrUri) - bdtDatas, response, err := client.DefaultApi.PolicyDataBdtDataGet(context.Background()) - if err != nil || response == nil || response.StatusCode != http.StatusOK { - rsp := models.ProblemDetails{ + bdtDatas, httpResponse, err := client.DefaultApi.PolicyDataBdtDataGet(context.Background()) + if err != nil || httpResponse == nil || httpResponse.StatusCode != http.StatusOK { + problemDetails = &models.ProblemDetails{ Status: http.StatusServiceUnavailable, Detail: "Query to UDR failed", } logger.Bdtpolicylog.Warnf("Query to UDR failed") - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + return nil, nil, problemDetails } // TODO: decide BDT Policy from other bdt policy data - rsp.BdtReqData = deepcopy.Copy(&request).(*models.BdtReqData) + response.BdtReqData = deepcopy.Copy(&request).(*models.BdtReqData) var bdtData *models.BdtData var bdtPolicyData models.BdtPolicyData for _, data := range bdtDatas { @@ -143,16 +218,19 @@ func CreateBDTPolicyContext(httpChannel chan message.HttpResponseMessage, reques // no support feature in subclause 5.8 of TS29554 bdtPolicyData.BdtRefId = bdtData.BdtRefId bdtPolicyData.TransfPolicies = append(bdtPolicyData.TransfPolicies, bdtData.TransPolicy) - rsp.BdtPolData = &bdtPolicyData - bdtPolicyId := pcfSelf.AllocBdtPolicyId() - pcfSelf.BdtPolicyPool[bdtPolicyId] = rsp + response.BdtPolData = &bdtPolicyData + bdtPolicyID, err := pcfSelf.AllocBdtPolicyID() - locationHeader := util.GetResourceUri(models.ServiceName_NPCF_BDTPOLICYCONTROL, bdtPolicyId) - headers := http.Header{ - "Location": {locationHeader}, + if err != nil { + problemDetails = &models.ProblemDetails{ + Status: http.StatusServiceUnavailable, + Detail: "Allocate bdtPolicyID failed", + } + logger.Bdtpolicylog.Warnf("Allocate bdtPolicyID failed") + return nil, nil, problemDetails } - logger.Bdtpolicylog.Tracef("BDT Policy Id[%s] Create", bdtPolicyId) - message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, rsp) + + pcfSelf.BdtPolicyPool.Store(bdtPolicyID, response) // Update UDR BDT Data(PUT) param := Nudr_DataRepository.PolicyDataBdtDataBdtReferenceIdPutParamOpts{ @@ -162,11 +240,20 @@ func CreateBDTPolicyContext(httpChannel chan message.HttpResponseMessage, reques if err != nil { logger.Bdtpolicylog.Warnf("UDR Put BdtDate error[%s]", err.Error()) } + + locationHeader := util.GetResourceUri(models.ServiceName_NPCF_BDTPOLICYCONTROL, bdtPolicyID) + header = http.Header{ + "Location": {locationHeader}, + } + logger.Bdtpolicylog.Tracef("BDT Policy Id[%s] Create", bdtPolicyID) + return header, response, problemDetails } func getDefaultUdrUri(context *pcf_context.PCFContext) string { - if context.DefaultUdrUri != "" { - return context.DefaultUdrUri + context.DefaultUdrURILock.RLock() + defer context.DefaultUdrURILock.RUnlock() + if context.DefaultUdrURI != "" { + return context.DefaultUdrURI } param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NUDR_DR}), diff --git a/producer/callback.go b/producer/callback.go index cdcab41..7a14845 100644 --- a/producer/callback.go +++ b/producer/callback.go @@ -1,15 +1,38 @@ -package pcf_producer +package producer import ( + "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" "net/http" ) -func HandleAmfStatusChangeNotify(httpChannel chan message.HttpResponseMessage, notification models.AmfStatusChangeNotification) { +func HandleAmfStatusChangeNotify(request *http_wrapper.Request) *http_wrapper.Response { logger.CallbackLog.Warnf("[PCF] Handle Amf Status Change Notify is not implemented.") + + notification := request.Body.(models.AmfStatusChangeNotification) + + AmfStatusChangeNotifyProcedure(notification) + + return http_wrapper.NewResponse(http.StatusNoContent, nil, nil) +} + +// TODO: handle AMF Status Change Notify +func AmfStatusChangeNotifyProcedure(notification models.AmfStatusChangeNotification) { logger.CallbackLog.Debugf("receive AMF status change notification[%+v]", notification) - // TODO: handle AMF Status Change Notify - message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) +} + +func HandleSmPolicyNotify(request *http_wrapper.Request) *http_wrapper.Response { + logger.CallbackLog.Warnf("[PCF] Handle Sm Policy Notify is not implemented.") + + notification := request.Body.(models.PolicyDataChangeNotification) + supi := request.Params["ReqURI"] + + SmPolicyNotifyProcedure(supi, notification) + + return http_wrapper.NewResponse(http.StatusNotImplemented, nil, nil) +} + +// TODO: handle SM Policy Notify +func SmPolicyNotifyProcedure(supi string, notification models.PolicyDataChangeNotification) { } diff --git a/producer/handle_sm_policy_notify.go b/producer/handle_sm_policy_notify.go deleted file mode 100644 index 0d2f7ce..0000000 --- a/producer/handle_sm_policy_notify.go +++ /dev/null @@ -1,74 +0,0 @@ -package pcf_producer - -import ( - // "context" - // "fmt" - "free5gc/lib/openapi/models" - // pcf_context "free5gc/src/pcf/context" - "free5gc/src/pcf/handler/message" - // "free5gc/src/pcf/util" - // "github.com/gin-gonic/gin" -) - -func HandleSmPolicyNotify(httpChannel chan message.HttpResponseMessage, supi string, body models.PolicyDataChangeNotification) { - // policyDataChangeNotification := body - // var problem models.ProblemDetails - // var smPolicyDecision models.SmPolicyDecision - // pcfUeContext := pcf_context.PCF_Self().UePool - // counter := false - // client := util.GetNudrClient("https://localhost:29504") - // UeContext := pcf_context.PCF_Self().UePool - // if UeContext[supi] == nil { - // problem.Status = 404 - // problem.Cause = "CONTEXT_NOT_FOUND" - // message.SendHttpResponseMessage(httpChannel, nil, 404, problem) - // } - // _, resp, err := client.DefaultApi.PolicyDataUesUeIdSmDataGet(context.Background(), supi, nil) - // if err != nil { - // problem.Status = 404 - // problem.Cause = "CONTEXT_NOT_FOUND" - // message.SendHttpResponseMessage(httpChannel, nil, 404, problem) - // } - // if resp.StatusCode == 204 { - // UeContext[supi].SmPolicyControlStore = nil - // // pcf_producer_callback.CreateSmPolicyNotifyContext(fmt.Sprint(UeContext[supi].SmPolicyControlStore.Context.PduSessionId), "terminate", nil) - // message.SendHttpResponseMessage(httpChannel, nil, 204, nil) - // } - // if resp.StatusCode == 200 { - // for key := range pcfUeContext { - - // SupiTemp := fmt.Sprint(pcfUeContext[key].Supi) - // if supi == SupiTemp { - // snssai := fmt.Sprint(pcfUeContext[key].SmPolicyControlStore.Context.SliceInfo.Sst) + pcfUeContext[key].SmPolicyControlStore.Context.SliceInfo.Sd - // dnn := pcfUeContext[key].SmPolicyControlStore.Context.Dnn - // if policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Ipv4Index != 0 { - // smPolicyDecision.Ipv4Index = policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Ipv4Index - // pcfUeContext[key].SmPolicyControlStore.Policy.Ipv4Index = smPolicyDecision.Ipv4Index - // counter = true - // } - // if policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Ipv6Index != 0 { - // smPolicyDecision.Ipv6Index = policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Ipv6Index - // pcfUeContext[key].SmPolicyControlStore.Policy.Ipv6Index = smPolicyDecision.Ipv6Index - // counter = true - // } - // if pcfUeContext[key].SmPolicyControlStore.Policy.Online != policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Online { - // smPolicyDecision.Online = policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Online - // pcfUeContext[key].SmPolicyControlStore.Policy.Online = smPolicyDecision.Online - // counter = true - // } - // if pcfUeContext[key].SmPolicyControlStore.Policy.Offline != policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Offline { - // smPolicyDecision.Offline = policyDataChangeNotification.SmPolicyData.SmPolicySnssaiData[snssai].SmPolicyDnnData[dnn].Offline - // pcfUeContext[key].SmPolicyControlStore.Policy.Offline = smPolicyDecision.Offline - // counter = true - // } - // message.SendHttpResponseMessage(httpChannel, nil, 204, gin.H{}) - // if counter { - // // pcf_producer_callback.CreateSmPolicyNotifyContext(fmt.Sprint(UeContext[supi].SmPolicyControlStore.Context.PduSessionId), "update", &smPolicyDecision) - // message.SendHttpResponseMessage(httpChannel, nil, 204, nil) - // } - - // } - - // } - // } -} diff --git a/producer/oam.go b/producer/oam.go index f6c221a..b5e1157 100644 --- a/producer/oam.go +++ b/producer/oam.go @@ -1,9 +1,9 @@ -package pcf_producer +package producer import ( + "free5gc/lib/http_wrapper" "free5gc/lib/openapi/models" "free5gc/src/pcf/context" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" "net/http" "strconv" @@ -22,13 +22,37 @@ type UEAmPolicy struct { type UEAmPolicys []UEAmPolicy -func HandleOAMGetAmPolicy(httpChannel chan message.HttpResponseMessage, supi string) { - logger.OamLog.Infof("Handle OAM Get Am Policy") +func HandleOAMGetAmPolicyRequest(request *http_wrapper.Request) *http_wrapper.Response { + // step 1: log + logger.OamLog.Infof("Handle OAMGetAmPolicy") + + // step 2: retrieve request + supi := request.Params["supi"] + + // step 3: handle the message + response, problemDetails := OAMGetAmPolicyProcedure(supi) + + // step 4: process the return value from step 3 + if response != nil { + // status code is based on SPEC, and option headers + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(http.StatusForbidden, nil, problemDetails) +} - var response UEAmPolicys +func OAMGetAmPolicyProcedure(supi string) (response *UEAmPolicys, problemDetails *models.ProblemDetails) { + logger.OamLog.Infof("Handle OAM Get Am Policy") + response = &UEAmPolicys{} pcfSelf := context.PCF_Self() - if ue, exists := pcfSelf.UePool[supi]; exists { + if val, exists := pcfSelf.UePool.Load(supi); exists { + ue := val.(*context.UeContext) for _, amPolicy := range ue.AMPolicyData { ueAmPolicy := UEAmPolicy{ PolicyAssociationID: amPolicy.PolAssoId, @@ -42,14 +66,14 @@ func HandleOAMGetAmPolicy(httpChannel chan message.HttpResponseMessage, supi str ueAmPolicy.Areas = servAreaRes.Areas ueAmPolicy.MaxNumOfTAs = servAreaRes.MaxNumOfTAs } - response = append(response, ueAmPolicy) + *response = append(*response, ueAmPolicy) } - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, response) + return response, nil } else { - problem := models.ProblemDetails{ + problemDetails = &models.ProblemDetails{ Status: http.StatusNotFound, Cause: "CONTEXT_NOT_FOUND", } - message.SendHttpResponseMessage(httpChannel, nil, http.StatusNotFound, problem) + return nil, problemDetails } } diff --git a/producer/policyauthorization.go b/producer/policyauthorization.go index 1e286bc..c227819 100644 --- a/producer/policyauthorization.go +++ b/producer/policyauthorization.go @@ -1,12 +1,12 @@ -package pcf_producer +package producer import ( "context" "fmt" + "free5gc/lib/http_wrapper" "free5gc/lib/openapi" "free5gc/lib/openapi/models" pcf_context "free5gc/src/pcf/context" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" "free5gc/src/pcf/util" "net/http" @@ -16,6 +16,97 @@ import ( "github.com/cydev/zero" ) +func transferMediaComponentRmToMediaComponent(medCompRm *models.MediaComponentRm) *models.MediaComponent { + spVal := models.SpatialValidity{ + PresenceInfoList: medCompRm.AfRoutReq.SpVal.PresenceInfoList, + } + afRoutReq := models.AfRoutingRequirement{ + AppReloc: medCompRm.AfRoutReq.AppReloc, + RouteToLocs: medCompRm.AfRoutReq.RouteToLocs, + SpVal: &spVal, + TempVals: medCompRm.AfRoutReq.TempVals, + UpPathChgSub: medCompRm.AfRoutReq.UpPathChgSub, + } + medSubComps := make(map[string]models.MediaSubComponent) + for id, medSubCompRm := range medCompRm.MedSubComps { + medSubComps[id] = models.MediaSubComponent(medSubCompRm) + } + medComp := models.MediaComponent{ + AfAppId: medCompRm.AfAppId, + AfRoutReq: &afRoutReq, + ContVer: medCompRm.ContVer, + Codecs: medCompRm.Codecs, + FStatus: medCompRm.FStatus, + MarBwDl: medCompRm.MarBwDl, + MarBwUl: medCompRm.MarBwUl, + MedCompN: medCompRm.MedCompN, + MedSubComps: medSubComps, + MedType: medCompRm.MedType, + MirBwDl: medCompRm.MirBwDl, + MirBwUl: medCompRm.MirBwUl, + ResPrio: medCompRm.ResPrio, + } + return &medComp +} + +// Handle Create/ Modify Media SubComponent +func handleMediaSubComponent(smPolicy *pcf_context.UeSmPolicyData, medComp *models.MediaComponent, + medSubComp *models.MediaSubComponent, var5qi int32) (*models.PccRule, *models.ProblemDetails) { + var flowInfos []models.FlowInformation + if tempFlowInfos, err := getFlowInfos(medSubComp); err != nil { + problemDetail := util.GetProblemDetail(err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return nil, &problemDetail + } else { + flowInfos = tempFlowInfos + } + pccRule := util.GetPccRuleByFlowInfos(smPolicy.PolicyDecision.PccRules, flowInfos) + if pccRule == nil { + maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) + pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, "", false) + // Set QoS Data + // TODO: use real arp + qosData := util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) + if var5qi <= 4 { + // update Qos Data accroding to request BitRate + var ul, dl bool + + qosData, ul, dl = updateQos_subComp(qosData, medComp, medSubComp) + if problemDetails := modifyRemainBitRate(smPolicy, &qosData, ul, dl); problemDetails != nil { + return nil, problemDetails + } + } + // Set PackfiltId + for i := range flowInfos { + flowInfos[i].PackFiltId = util.GetPackFiltId(smPolicy.PackFiltIdGenarator) + smPolicy.PackFiltMapToPccRuleId[flowInfos[i].PackFiltId] = pccRule.PccRuleId + smPolicy.PackFiltIdGenarator++ + } + // Set flowsInfo in Pcc Rule + pccRule.FlowInfos = flowInfos + // Set Traffic Control Data + tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, medSubComp.FStatus) + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + smPolicy.PccRuleIdGenarator++ + } else { + // update qos + var qosData models.QosData + for _, qosId := range pccRule.RefQosData { + qosData = smPolicy.PolicyDecision.QosDecs[qosId] + if qosData.Var5qi == var5qi && qosData.Var5qi <= 4 { + var ul, dl bool + qosData, ul, dl = updateQos_subComp(smPolicy.PolicyDecision.QosDecs[qosId], medComp, medSubComp) + if problemDetails := modifyRemainBitRate(smPolicy, &qosData, ul, dl); problemDetails != nil { + logger.PolicyAuthorizationlog.Errorf(problemDetails.Detail) + return nil, problemDetails + } + smPolicy.PolicyDecision.QosDecs[qosData.QosId] = qosData + } + } + } + smPolicy.PolicyDecision.PccRules[pccRule.PccRuleId] = *pccRule + return pccRule, nil +} + // Initial provisioning of service information (DONE) // Gate control (DONE) // Initial provisioning of sponsored connectivity information (DONE) @@ -25,165 +116,137 @@ import ( // Subscription to resources allocation outcome (DONE) // Invocation of Multimedia Priority Services (TODO) // Support of content versioning (TODO) -// PostAppSessions - Creates a new Individual Application Session Context resource -func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, request models.AppSessionContext) { +// HandlePostAppSessions - Creates a new Individual Application Session Context resource +func HandlePostAppSessionsContext(request *http_wrapper.Request) *http_wrapper.Response { logger.PolicyAuthorizationlog.Traceln("Handle Create AppSessions") - ascReqData := request.AscReqData + + appSessionContext := request.Body.(models.AppSessionContext) + // ascReqData := AppSessionContext.AscReqData + + response, locationHeader, problemDetails := PostAppSessionsContextProcedure(appSessionContext) + + if response != nil { + headers := http.Header{ + "Location": {locationHeader}, + } + return http_wrapper.NewResponse(http.StatusCreated, headers, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) +} + +func PostAppSessionsContextProcedure(appSessionContext models.AppSessionContext) (*models.AppSessionContext, + string, *models.ProblemDetails) { + ascReqData := appSessionContext.AscReqData pcfSelf := pcf_context.PCF_Self() // Initial BDT policy indication(the only one which is not related to session) if ascReqData.BdtRefId != "" { - err := handleBackgroundDataTransferPolicyIndication(pcfSelf, &request) - if err != nil { - sendProblemDetail(httpChannel, err.Error(), util.ERROR_REQUEST_PARAMETERS) - return + if err := handleBackgroundDataTransferPolicyIndication(pcfSelf, &appSessionContext); err != nil { + problemDetail := util.GetProblemDetail(err.Error(), util.ERROR_REQUEST_PARAMETERS) + return nil, "", &problemDetail } appSessionId := fmt.Sprintf("BdtRefId-%s", ascReqData.BdtRefId) data := pcf_context.AppSessionData{ AppSessionId: appSessionId, - AppSessionContext: &request, + AppSessionContext: &appSessionContext, } - pcfSelf.AppSessionPool[appSessionId] = &data + pcfSelf.AppSessionPool.Store(appSessionId, &data) locationHeader := util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId) - headers := http.Header{ - "Location": {locationHeader}, - } logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create", appSessionId) - message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, request) - return + return &appSessionContext, locationHeader, nil } if ascReqData.UeIpv4 == "" && ascReqData.UeIpv6 == "" && ascReqData.UeMac == "" { - sendProblemDetail(httpChannel, "Ue UeIpv4 and UeIpv6 and UeMac are all empty", util.ERROR_REQUEST_PARAMETERS) - return + problemDetail := util.GetProblemDetail("Ue UeIpv4 and UeIpv6 and UeMac are all empty", util.ERROR_REQUEST_PARAMETERS) + return nil, "", &problemDetail } if ascReqData.AfRoutReq != nil && ascReqData.Dnn == "" { - sendProblemDetail(httpChannel, "DNN shall be present", util.ERROR_REQUEST_PARAMETERS) - return - } - smPolicy, err := pcfSelf.SessionBinding(ascReqData) - if err != nil { - sendProblemDetail(httpChannel, fmt.Sprintf("Session Binding failed[%s]", err.Error()), util.PDU_SESSION_NOT_AVAILABLE) - return + problemDetail := util.GetProblemDetail("DNN shall be present", util.ERROR_REQUEST_PARAMETERS) + return nil, "", &problemDetail + } + var smPolicy *pcf_context.UeSmPolicyData + if tempSmPolicy, err := pcfSelf.SessionBinding(ascReqData); err != nil { + problemDetail := util.GetProblemDetail(fmt.Sprintf("Session Binding failed[%s]", + err.Error()), util.PDU_SESSION_NOT_AVAILABLE) + return nil, "", &problemDetail + } else { + smPolicy = tempSmPolicy } + logger.PolicyAuthorizationlog.Infof("Session Binding Success - UeIpv4[%s], UeIpv6[%s], UeMac[%s]", + ascReqData.UeIpv4, ascReqData.UeIpv6, ascReqData.UeMac) ue := smPolicy.PcfUe updateSMpolicy := false - requestSuppFeat, _ := openapi.NewSupportedFeature(ascReqData.SuppFeat) + var requestSuppFeat openapi.SupportedFeature + if tempRequestSuppFeat, err := openapi.NewSupportedFeature(ascReqData.SuppFeat); err != nil { + logger.PolicyAuthorizationlog.Errorf(err.Error()) + } else { + requestSuppFeat = tempRequestSuppFeat + } + nSuppFeat := pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION].NegotiateWith(requestSuppFeat).String() - traffRoutSupp := util.CheckSuppFeat(nSuppFeat, 1) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 + // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 + traffRoutSupp := util.CheckSuppFeat(nSuppFeat, 1) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) relatedPccRuleIds := make(map[string]string) if ascReqData.MedComponents != nil { // Handle Pcc rules maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) - for _, mediaComponent := range ascReqData.MedComponents { + for _, medComp := range ascReqData.MedComponents { var pccRule *models.PccRule + var appId string + var routeReq *models.AfRoutingRequirement // TODO: use specific algorithm instead of default, details in subsclause 7.3.3 of TS 29513 var var5qi int32 = 9 - if mediaComponent.MedType != "" { - var5qi = util.MediaTypeTo5qiMap[mediaComponent.MedType] + if medComp.MedType != "" { + var5qi = util.MediaTypeTo5qiMap[medComp.MedType] } - if mediaComponent.MedSubComps != nil { - for _, mediaSubComponent := range mediaComponent.MedSubComps { - flowInfos, err := getFlowInfos(mediaSubComponent) - if err != nil { - sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return - } - pccRule = util.GetPccRuleByFlowInfos(smPolicy.PolicyDecision.PccRules, flowInfos) - if pccRule == nil { - pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) - // Set QoS Data - // TODO: use real arp - qosData := util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) - if var5qi <= 4 { - // update Qos Data accroding to request BitRate - var ul, dl bool - qosData, ul, dl = updateQos_subComp(qosData, mediaComponent, mediaSubComponent) - err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) - if err != nil { - return - } - } - // Set PackfiltId - for i := range flowInfos { - flowInfos[i].PackFiltId = util.GetPackFiltId(smPolicy.PackFiltIdGenarator) - smPolicy.PackFiltMapToPccRuleId[flowInfos[i].PackFiltId] = pccRule.PccRuleId - smPolicy.PackFiltIdGenarator++ - } - // Set flowsInfo in Pcc Rule - pccRule.FlowInfos = flowInfos - // Set Traffic Control Data - tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaSubComponent.FStatus) - util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) - smPolicy.PccRuleIdGenarator++ - maxPrecedence++ + if medComp.MedSubComps != nil { + for _, medSubComp := range medComp.MedSubComps { + if tempPccRule, problemDetail := handleMediaSubComponent(smPolicy, + &medComp, &medSubComp, var5qi); problemDetail != nil { + return nil, "", problemDetail } else { - // update qos - var qosData models.QosData - for _, qosId := range pccRule.RefQosData { - qosData = smPolicy.PolicyDecision.QosDecs[qosId] - if qosData.Var5qi == var5qi && qosData.Var5qi <= 4 { - var ul, dl bool - qosData, ul, dl = updateQos_subComp(smPolicy.PolicyDecision.QosDecs[qosId], mediaComponent, mediaSubComponent) - err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) - if err != nil { - fmt.Println(err.Error()) - return - } - smPolicy.PolicyDecision.QosDecs[qosData.QosId] = qosData - } - } + pccRule = tempPccRule } - // Initial provisioning of traffic routing information - if traffRoutSupp { - InitialProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, ascReqData.AfRoutReq) - } - smPolicy.PolicyDecision.PccRules[pccRule.PccRuleId] = *pccRule - key := fmt.Sprintf("%d-%d", mediaComponent.MedCompN, mediaSubComponent.FNum) + key := fmt.Sprintf("%d-%d", medComp.MedCompN, medSubComp.FNum) relatedPccRuleIds[key] = pccRule.PccRuleId updateSMpolicy = true } continue - } else if mediaComponent.AfAppId != "" { - // if mediaComponent.AfAppId has value -> find pccRule by ascReqData.AfAppId, otherwise create a new pcc rule - pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, mediaComponent.AfAppId) - if pccRule != nil { - pccRule.AppId = mediaComponent.AfAppId - } + } else if medComp.AfAppId != "" { + // if medComp.AfAppId has value -> find pccRule by ascReqData.AfAppId, otherwise create a new pcc rule + appId = medComp.AfAppId + routeReq = medComp.AfRoutReq } else if ascReqData.AfAppId != "" { - pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, ascReqData.AfAppId) - if pccRule != nil { - pccRule.AppId = ascReqData.AfAppId - } + appId = ascReqData.AfAppId + routeReq = ascReqData.AfRoutReq } else { - sendProblemDetail(httpChannel, "Media Component needs flows of subComp or afAppId", util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return + problemDetail := util.GetProblemDetail("Media Component needs flows of subComp or afAppId", + util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return nil, "", &problemDetail } + pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, appId) if pccRule == nil { // create new pcc rule - pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) - if mediaComponent.AfAppId != "" { - pccRule.AppId = mediaComponent.AfAppId - } else { - pccRule.AppId = ascReqData.AfAppId - } + pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, appId, false) // Set QoS Data // TODO: use real arp qosData := util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) if var5qi <= 4 { // update Qos Data accroding to request BitRate var ul, dl bool - qosData, ul, dl = updateQos_Comp(qosData, mediaComponent) - err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) - if err != nil { - return + qosData, ul, dl = updateQos_Comp(qosData, &medComp) + if problemDetails := modifyRemainBitRate(smPolicy, &qosData, ul, dl); problemDetails != nil { + return nil, "", problemDetails } } - - // Set Traffic Control Data - tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaComponent.FStatus) - util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, nil, &qosData, nil, nil) smPolicy.PccRuleIdGenarator++ maxPrecedence++ } else { @@ -193,72 +256,38 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques qosData = smPolicy.PolicyDecision.QosDecs[qosId] if qosData.Var5qi == var5qi && qosData.Var5qi <= 4 { var ul, dl bool - qosData, ul, dl = updateQos_Comp(smPolicy.PolicyDecision.QosDecs[qosId], mediaComponent) - err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) - if err != nil { - return + qosData, ul, dl = updateQos_Comp(smPolicy.PolicyDecision.QosDecs[qosId], &medComp) + if problemDetails := modifyRemainBitRate(smPolicy, &qosData, ul, dl); problemDetails != nil { + return nil, "", problemDetails } smPolicy.PolicyDecision.QosDecs[qosData.QosId] = qosData } } } - key := fmt.Sprintf("%d", mediaComponent.MedCompN) - relatedPccRuleIds[key] = pccRule.PccRuleId - // TODO : handle temporal or spatial validity // Initial provisioning of traffic routing information if traffRoutSupp { - InitialProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, ascReqData.AfRoutReq) + pccRule = provisioningOfTrafficRoutingInfo(smPolicy, appId, routeReq, medComp.FStatus) } + key := fmt.Sprintf("%d", medComp.MedCompN) + relatedPccRuleIds[key] = pccRule.PccRuleId updateSMpolicy = true } } else if ascReqData.AfAppId != "" { // Initial provisioning of traffic routing information if ascReqData.AfRoutReq != nil && traffRoutSupp { - decision := smPolicy.PolicyDecision - cnt := 0 - createdTcData := models.TrafficControlData{ - FlowStatus: models.FlowStatus_ENABLED, - RouteToLocs: ascReqData.AfRoutReq.RouteToLocs, - UpPathChgEvent: ascReqData.AfRoutReq.UpPathChgSub, - } - - for _, rule := range smPolicy.PolicyDecision.PccRules { - if rule.AppId == ascReqData.AfAppId { - createdTcData.TcId = strings.ReplaceAll(rule.PccRuleId, "PccRule", "Tc") - rule.RefTcData = []string{createdTcData.TcId} - rule.AppReloc = ascReqData.AfRoutReq.AppReloc - util.SetPccRuleRelatedData(decision, &rule, &createdTcData, nil, nil, nil) - updateSMpolicy = true - key := fmt.Sprintf("appId-%s-%d", ascReqData.AfAppId, cnt) - relatedPccRuleIds[key] = rule.PccRuleId - cnt++ - } - } - // Create a Pcc Rule if afappId dose not match any pcc rule - if !updateSMpolicy { - maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) - pccRule := util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) - pccRule.AppId = ascReqData.AfAppId - qosData := models.QosData{ - QosId: util.GetQosId(smPolicy.PccRuleIdGenarator), - DefQosFlowIndication: true, - } - createdTcData.TcId = util.GetTcId(smPolicy.PccRuleIdGenarator) - pccRule.RefTcData = []string{createdTcData.TcId} - pccRule.RefQosData = []string{qosData.QosId} - util.SetPccRuleRelatedData(decision, pccRule, &createdTcData, &qosData, nil, nil) - smPolicy.PccRuleIdGenarator++ - updateSMpolicy = true - key := fmt.Sprintf("appId-%s", ascReqData.AfAppId) - relatedPccRuleIds[key] = pccRule.PccRuleId - } + logger.PolicyAuthorizationlog.Infof("AF influence on Traffic Routing - AppId[%s]", ascReqData.AfAppId) + pccRule := provisioningOfTrafficRoutingInfo(smPolicy, ascReqData.AfAppId, ascReqData.AfRoutReq, "") + key := fmt.Sprintf("appId-%s", ascReqData.AfAppId) + relatedPccRuleIds[key] = pccRule.PccRuleId + updateSMpolicy = true } else { - sendProblemDetail(httpChannel, "Traffic routing not supported", util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return + problemDetail := util.GetProblemDetail("Traffic routing not supported", util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return nil, "", &problemDetail } } else { - sendProblemDetail(httpChannel, "AF Request need AfAppId or Media Component to match Service Data Flow", util.ERROR_REQUEST_PARAMETERS) - return + problemDetail := util.GetProblemDetail("AF Request need AfAppId or Media Component to match Service Data Flow", + util.ERROR_REQUEST_PARAMETERS) + return nil, "", &problemDetail } // Event Subscription @@ -309,40 +338,44 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques // Initial provisioning of sponsored connectivity information if ascReqData.AspId != "" && ascReqData.SponId != "" { - supp := util.CheckSuppFeat(nSuppFeat, 2) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 12) // SponsoredConnectivity = 2 in 29514 & SponsoredConnectivity support = 12 in 29512 + // SponsoredConnectivity = 2 in 29514 & SponsoredConnectivity support = 12 in 29512 + supp := util.CheckSuppFeat(nSuppFeat, 2) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 12) if !supp { - sendProblemDetail(httpChannel, "Sponsored Connectivity not supported", util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return + problemDetail := util.GetProblemDetail("Sponsored Connectivity not supported", util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return nil, "", &problemDetail } umId := util.GetUmId(ascReqData.AspId, ascReqData.SponId) - umData, err := extractUmData(umId, eventSubs, ascReqData.EvSubsc.UsgThres) - if err != nil { - sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return + var umData *models.UsageMonitoringData + if tempUmData, err := extractUmData(umId, eventSubs, ascReqData.EvSubsc.UsgThres); err != nil { + problemDetail := util.GetProblemDetail(err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return nil, "", &problemDetail + } else { + umData = tempUmData } - err = handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, ascReqData.AspId, ascReqData.SponId, ascReqData.SponStatus, umData, &updateSMpolicy) - if err != nil { - return + if err := handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, ascReqData.AspId, + ascReqData.SponId, ascReqData.SponStatus, umData, &updateSMpolicy); err != nil { + problemDetail := util.GetProblemDetail(err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return nil, "", &problemDetail } } // Allocate App Session Id appSessionId := ue.AllocUeAppSessionId(pcfSelf) - request.AscRespData = &models.AppSessionContextRespData{ + appSessionContext.AscRespData = &models.AppSessionContextRespData{ SuppFeat: nSuppFeat, } // Associate App Session to SMPolicy smPolicy.AppSessions[appSessionId] = true data := pcf_context.AppSessionData{ AppSessionId: appSessionId, - AppSessionContext: &request, + AppSessionContext: &appSessionContext, SmPolicyData: smPolicy, } if len(relatedPccRuleIds) > 0 { data.RelatedPccRuleIds = relatedPccRuleIds data.PccRuleIdMapToCompId = reverseStringMap(relatedPccRuleIds) } - request.EvsNotif = &models.EventsNotification{} + appSessionContext.EvsNotif = &models.EventsNotification{} // Set Event Subsciption related Data if len(eventSubs) > 0 { data.Events = eventSubs @@ -351,10 +384,10 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques afNotif := models.AfEventNotification{ Event: models.AfEvent_PLMN_CHG, } - request.EvsNotif.EvNotifs = append(request.EvsNotif.EvNotifs, afNotif) + appSessionContext.EvsNotif.EvNotifs = append(appSessionContext.EvsNotif.EvNotifs, afNotif) plmnId := smPolicy.PolicyContext.ServingNetwork if plmnId != nil { - request.EvsNotif.PlmnId = &models.PlmnId{ + appSessionContext.EvsNotif.PlmnId = &models.PlmnId{ Mcc: plmnId.Mcc, Mnc: plmnId.Mnc, } @@ -364,21 +397,17 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques afNotif := models.AfEventNotification{ Event: models.AfEvent_ACCESS_TYPE_CHANGE, } - request.EvsNotif.EvNotifs = append(request.EvsNotif.EvNotifs, afNotif) - request.EvsNotif.AccessType = smPolicy.PolicyContext.AccessType - request.EvsNotif.RatType = smPolicy.PolicyContext.RatType + appSessionContext.EvsNotif.EvNotifs = append(appSessionContext.EvsNotif.EvNotifs, afNotif) + appSessionContext.EvsNotif.AccessType = smPolicy.PolicyContext.AccessType + appSessionContext.EvsNotif.RatType = smPolicy.PolicyContext.RatType } } - if request.EvsNotif.EvNotifs == nil { - request.EvsNotif = nil + if appSessionContext.EvsNotif.EvNotifs == nil { + appSessionContext.EvsNotif = nil } - pcfSelf.AppSessionPool[appSessionId] = &data + pcfSelf.AppSessionPool.Store(appSessionId, &data) locationHeader := util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId) - headers := http.Header{ - "Location": {locationHeader}, - } logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create", appSessionId) - message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, request) // Send Notification to SMF if updateSMpolicy { smPolicyId := fmt.Sprintf("%s-%d", ue.Supi, smPolicy.PolicyContext.PduSessionId) @@ -387,29 +416,42 @@ func PostAppSessionsContext(httpChannel chan message.HttpResponseMessage, reques SmPolicyDecision: smPolicy.PolicyDecision, } SendSMPolicyUpdateNotification(ue, smPolicyId, notification) - logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) } + return &appSessionContext, locationHeader, nil } -// DeleteAppSession - Deletes an existing Individual Application Session Context -func DeleteAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessionId string, requset *models.EventsSubscReqData) { - +// HandleDeleteAppSession - Deletes an existing Individual Application Session Context +func HandleDeleteAppSessionContext(request *http_wrapper.Request) *http_wrapper.Response { + eventsSubscReqData := request.Body.(*models.EventsSubscReqData) + appSessionId := request.Params["appSessionId"] logger.PolicyAuthorizationlog.Tracef("Handle Del AppSessions, AppSessionId[%s]", appSessionId) - pcfSelf := pcf_context.PCF_Self() - appSession := pcfSelf.AppSessionPool[appSessionId] + problemDetails := DeleteAppSessionContextProcedure(appSessionId, eventsSubscReqData) + if problemDetails == nil { + return http_wrapper.NewResponse(http.StatusNoContent, nil, nil) + } else { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } +} + +func DeleteAppSessionContextProcedure(appSessionId string, + eventsSubscReqData *models.EventsSubscReqData) *models.ProblemDetails { + pcfSelf := pcf_context.PCF_Self() + var appSession *pcf_context.AppSessionData + if val, ok := pcfSelf.AppSessionPool.Load(appSessionId); ok { + appSession = val.(*pcf_context.AppSessionData) + } if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) - return + problemDetail := util.GetProblemDetail("can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return &problemDetail } - if requset != nil { + if eventsSubscReqData != nil { logger.PolicyAuthorizationlog.Warnf("Delete AppSessions does not support with Event Subscription") } // Remove related pcc rule resourse smPolicy := appSession.SmPolicyData for _, pccRuleId := range appSession.RelatedPccRuleIds { - err := smPolicy.RemovePccRule(pccRuleId) - if err != nil { + if err := smPolicy.RemovePccRule(pccRuleId); err != nil { logger.PolicyAuthorizationlog.Warnf(err.Error()) } } @@ -429,9 +471,8 @@ func DeleteAppSessionContext(httpChannel chan message.HttpResponseMessage, appSe // message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, resp) // } else { // } - message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) - delete(pcfSelf.AppSessionPool, appSessionId) + pcfSelf.AppSessionPool.Delete(appSessionId) smPolicy.ArrangeExistEventSubscription() @@ -443,181 +484,145 @@ func DeleteAppSessionContext(httpChannel chan message.HttpResponseMessage, appSe } SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) - + return nil } -// GetAppSession - Reads an existing Individual Application Session Context -func GetAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessionId string) { +// HandleGetAppSession - Reads an existing Individual Application Session Context +func HandleGetAppSessionContext(request *http_wrapper.Request) *http_wrapper.Response { + appSessionId := request.Params["appSessionId"] logger.PolicyAuthorizationlog.Tracef("Handle Get AppSessions, AppSessionId[%s]", appSessionId) + + problemDetails, response := GetAppSessionContextProcedure(appSessionId) + if problemDetails == nil { + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } +} + +func GetAppSessionContextProcedure(appSessionId string) (*models.ProblemDetails, *models.AppSessionContext) { pcfSelf := pcf_context.PCF_Self() - appSession := pcfSelf.AppSessionPool[appSessionId] + var appSession *pcf_context.AppSessionData + if val, ok := pcfSelf.AppSessionPool.Load(appSessionId); ok { + appSession = val.(*pcf_context.AppSessionData) + } if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) - return + problemDetail := util.GetProblemDetail("can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return &problemDetail, nil } logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Get", appSessionId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appSession.AppSessionContext) + return nil, appSession.AppSessionContext } -// ModAppSession - Modifies an existing Individual Application Session Context -func ModAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessionId string, request models.AppSessionContextUpdateData) { +// HandleModAppSession - Modifies an existing Individual Application Session Context +func HandleModAppSessionContext(request *http_wrapper.Request) *http_wrapper.Response { + appSessionId := request.Params["appSessionId"] + appSessionContextUpdateData := request.Body.(models.AppSessionContextUpdateData) + logger.PolicyAuthorizationlog.Tracef("Handle Modify AppSessions, AppSessionId[%s]", appSessionId) + + problemDetails, response := ModAppSessionContextProcedure(appSessionId, appSessionContextUpdateData) + if problemDetails == nil { + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } +} - logger.PolicyAuthorizationlog.Tracef("Handle Modi AppSessions, AppSessionId[%s]", appSessionId) +func ModAppSessionContextProcedure(appSessionId string, + appSessionContextUpdateData models.AppSessionContextUpdateData) (*models.ProblemDetails, *models.AppSessionContext) { pcfSelf := pcf_context.PCF_Self() - appSession := pcfSelf.AppSessionPool[appSessionId] + var appSession *pcf_context.AppSessionData + if val, ok := pcfSelf.AppSessionPool.Load(appSessionId); ok { + appSession = val.(*pcf_context.AppSessionData) + } if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) - return + problemDetail := util.GetProblemDetail("can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return &problemDetail, nil } appContext := appSession.AppSessionContext - if request.BdtRefId != "" { - appContext.AscReqData.BdtRefId = request.BdtRefId - err := handleBackgroundDataTransferPolicyIndication(pcfSelf, appContext) - if err != nil { - sendProblemDetail(httpChannel, err.Error(), util.ERROR_REQUEST_PARAMETERS) - return + if appSessionContextUpdateData.BdtRefId != "" { + appContext.AscReqData.BdtRefId = appSessionContextUpdateData.BdtRefId + if err := handleBackgroundDataTransferPolicyIndication(pcfSelf, appContext); err != nil { + problemDetail := util.GetProblemDetail(err.Error(), util.ERROR_REQUEST_PARAMETERS) + return &problemDetail, nil } logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Updated", appSessionId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appContext) - return + return nil, appContext } smPolicy := appSession.SmPolicyData if smPolicy == nil { - sendProblemDetail(httpChannel, "Can't find related PDU Session", util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return + problemDetail := util.GetProblemDetail("Can't find related PDU Session", util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return &problemDetail, nil } - traffRoutSupp := util.CheckSuppFeat(appContext.AscRespData.SuppFeat, 1) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 + // InfluenceOnTrafficRouting = 1 in 29514 & Traffic Steering Control support = 1 in 29512 + traffRoutSupp := util.CheckSuppFeat(appContext.AscRespData.SuppFeat, + 1) && util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 1) relatedPccRuleIds := make(map[string]string) // Event Subscription eventSubs := make(map[models.AfEvent]models.AfNotifMethod) updateSMpolicy := false - if request.MedComponents != nil { + if appSessionContextUpdateData.MedComponents != nil { maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) - for compN, mediaComponent := range request.MedComponents { + for compN, medCompRm := range appSessionContextUpdateData.MedComponents { + medComp := transferMediaComponentRmToMediaComponent(&medCompRm) removeMediaComp(appSession, compN) - if zero.IsZero(mediaComponent) { + if zero.IsZero(medComp) { // remove MediaComp(media Comp is null) continue } // modify MediaComp(remove and reinstall again) var pccRule *models.PccRule + var appId string + var routeReq *models.AfRoutingRequirement // TODO: use specific algorithm instead of default, details in subsclause 7.3.3 of TS 29513 var var5qi int32 = 9 - if mediaComponent.MedType != "" { - var5qi = util.MediaTypeTo5qiMap[mediaComponent.MedType] + if medComp.MedType != "" { + var5qi = util.MediaTypeTo5qiMap[medComp.MedType] } - qosMediaComp := models.MediaComponent{ - MarBwDl: mediaComponent.MarBwDl, - MarBwUl: mediaComponent.MarBwUl, - MirBwDl: mediaComponent.MirBwDl, - MirBwUl: mediaComponent.MirBwUl, - } - if mediaComponent.MedSubComps != nil { - for _, mediaSubComponentRm := range mediaComponent.MedSubComps { - mediaSubComponent := models.MediaSubComponent(mediaSubComponentRm) - flowInfos, err := getFlowInfos(mediaSubComponent) - if err != nil { - sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return - } - pccRule = util.GetPccRuleByFlowInfos(smPolicy.PolicyDecision.PccRules, flowInfos) - if pccRule == nil { - pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) - // Set QoS Data - // TODO: use real arp - qosData := util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) - if var5qi <= 4 { - // update Qos Data accroding to request BitRate - var ul, dl bool - - qosData, ul, dl = updateQos_subComp(qosData, qosMediaComp, mediaSubComponent) - err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) - if err != nil { - return - } - } - // Set PackfiltId - for i := range flowInfos { - flowInfos[i].PackFiltId = util.GetPackFiltId(smPolicy.PackFiltIdGenarator) - smPolicy.PackFiltMapToPccRuleId[flowInfos[i].PackFiltId] = pccRule.PccRuleId - smPolicy.PackFiltIdGenarator++ - } - // Set flowsInfo in Pcc Rule - pccRule.FlowInfos = flowInfos - // Set Traffic Control Data - tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaSubComponent.FStatus) - util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) - smPolicy.PccRuleIdGenarator++ - maxPrecedence++ + if medComp.MedSubComps != nil { + for _, medSubComp := range medComp.MedSubComps { + if tempPccRule, problemDetail := handleMediaSubComponent(smPolicy, medComp, + &medSubComp, var5qi); problemDetail != nil { + return problemDetail, nil } else { - // update qos - var qosData models.QosData - for _, qosId := range pccRule.RefQosData { - qosData = smPolicy.PolicyDecision.QosDecs[qosId] - if qosData.Var5qi == var5qi && qosData.Var5qi <= 4 { - var ul, dl bool - qosData, ul, dl = updateQos_subComp(smPolicy.PolicyDecision.QosDecs[qosId], qosMediaComp, mediaSubComponent) - err = modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) - if err != nil { - fmt.Println(err.Error()) - return - } - smPolicy.PolicyDecision.QosDecs[qosData.QosId] = qosData - } - } - } - // Modify provisioning of traffic routing information - if traffRoutSupp { - ModifyProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, request.AfRoutReq) + pccRule = tempPccRule } - smPolicy.PolicyDecision.PccRules[pccRule.PccRuleId] = *pccRule - key := fmt.Sprintf("%d-%d", mediaComponent.MedCompN, mediaSubComponent.FNum) + key := fmt.Sprintf("%d-%d", medComp.MedCompN, medSubComp.FNum) relatedPccRuleIds[key] = pccRule.PccRuleId updateSMpolicy = true } continue - } else if mediaComponent.AfAppId != "" { - // if mediaComponent.AfAppId has value -> find pccRule by reqData.AfAppId, otherwise create a new pcc rule - pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, mediaComponent.AfAppId) - if pccRule != nil { - pccRule.AppId = mediaComponent.AfAppId - } - } else if request.AfAppId != "" { - pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, request.AfAppId) - if pccRule != nil { - pccRule.AppId = request.AfAppId - } + } else if medComp.AfAppId != "" { + // if medComp.AfAppId has value -> find pccRule by reqData.AfAppId, otherwise create a new pcc rule + appId = medComp.AfAppId + routeReq = medComp.AfRoutReq + } else if appSessionContextUpdateData.AfAppId != "" { + appId = appSessionContextUpdateData.AfAppId + routeReq = medComp.AfRoutReq } else { - sendProblemDetail(httpChannel, "Media Component needs flows of subComp or afAppId", util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return + problemDetail := util.GetProblemDetail("Media Component needs flows of subComp or afAppId", + util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return &problemDetail, nil } + pccRule = util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, appId) if pccRule == nil { // create new pcc rule - pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, false) - if mediaComponent.AfAppId != "" { - pccRule.AppId = mediaComponent.AfAppId - } else { - pccRule.AppId = request.AfAppId - } + pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, appId, false) // Set QoS Data // TODO: use real arp qosData := util.CreateQosData(smPolicy.PccRuleIdGenarator, var5qi, 8) if var5qi <= 4 { // update Qos Data accroding to request BitRate var ul, dl bool - qosData, ul, dl = updateQos_Comp(qosData, qosMediaComp) - err := modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) - if err != nil { - return + qosData, ul, dl = updateQos_Comp(qosData, medComp) + if problemDetail := modifyRemainBitRate(smPolicy, &qosData, ul, dl); problemDetail != nil { + return problemDetail, nil } } - - // Set Traffic Control Data - tcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, mediaComponent.FStatus) - util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &tcData, &qosData, nil, nil) + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, nil, &qosData, nil, nil) smPolicy.PccRuleIdGenarator++ maxPrecedence++ } else { @@ -627,24 +632,22 @@ func ModAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessi qosData = smPolicy.PolicyDecision.QosDecs[qosId] if qosData.Var5qi == var5qi && qosData.Var5qi <= 4 { var ul, dl bool - qosData, ul, dl = updateQos_Comp(smPolicy.PolicyDecision.QosDecs[qosId], qosMediaComp) - err := modifyRemainBitRate(httpChannel, smPolicy, &qosData, ul, dl) - if err != nil { - return + qosData, ul, dl = updateQos_Comp(smPolicy.PolicyDecision.QosDecs[qosId], medComp) + if problemDetail := modifyRemainBitRate(smPolicy, &qosData, ul, dl); problemDetail != nil { + return problemDetail, nil } smPolicy.PolicyDecision.QosDecs[qosData.QosId] = qosData } } } - key := fmt.Sprintf("%d", mediaComponent.MedCompN) + key := fmt.Sprintf("%d", medComp.MedCompN) relatedPccRuleIds[key] = pccRule.PccRuleId - // TODO : handle temporal or spatial validity // Modify provisioning of traffic routing information if traffRoutSupp { - ModifyProvisioningOfTrafficRoutingInformation(smPolicy, pccRule, mediaComponent.AfRoutReq, request.AfRoutReq) + pccRule = provisioningOfTrafficRoutingInfo(smPolicy, appId, routeReq, medComp.FStatus) + _ = pccRule // pccRule unused } updateSMpolicy = true - } } @@ -653,8 +656,8 @@ func ModAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessi relatedPccRuleIds[key] = pccRuleId } - if request.EvSubsc != nil { - for _, subs := range request.EvSubsc.Events { + if appSessionContextUpdateData.EvSubsc != nil { + for _, subs := range appSessionContextUpdateData.EvSubsc.Events { if subs.NotifMethod == "" { // default value "EVENT_DETECTION" subs.NotifMethod = models.AfNotifMethod_EVENT_DETECTION @@ -690,24 +693,23 @@ func ModAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessi continue } if !util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { - smPolicy.PolicyDecision.PolicyCtrlReqTriggers = append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) + smPolicy.PolicyDecision.PolicyCtrlReqTriggers = + append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) updateSMpolicy = true } - } // update Context if appContext.AscReqData.EvSubsc == nil { appContext.AscReqData.EvSubsc = new(models.EventsSubscReqData) } - appContext.AscReqData.EvSubsc.Events = request.EvSubsc.Events - if request.EvSubsc.NotifUri != "" { - appContext.AscReqData.EvSubsc.NotifUri = request.EvSubsc.NotifUri - appSession.EventUri = request.EvSubsc.NotifUri + appContext.AscReqData.EvSubsc.Events = appSessionContextUpdateData.EvSubsc.Events + if appSessionContextUpdateData.EvSubsc.NotifUri != "" { + appContext.AscReqData.EvSubsc.NotifUri = appSessionContextUpdateData.EvSubsc.NotifUri + appSession.EventUri = appSessionContextUpdateData.EvSubsc.NotifUri } - if request.EvSubsc.UsgThres != nil { - appContext.AscReqData.EvSubsc.UsgThres = threshRmToThresh(request.EvSubsc.UsgThres) + if appSessionContextUpdateData.EvSubsc.UsgThres != nil { + appContext.AscReqData.EvSubsc.UsgThres = threshRmToThresh(appSessionContextUpdateData.EvSubsc.UsgThres) } - } else { // remove eventSubs appSession.Events = nil @@ -716,16 +718,20 @@ func ModAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessi } // Moification provisioning of sponsored connectivity information - if request.AspId != "" && request.SponId != "" { - umId := util.GetUmId(request.AspId, request.SponId) - umData, err := extractUmData(umId, eventSubs, threshRmToThresh(request.EvSubsc.UsgThres)) - if err != nil { - sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return + if appSessionContextUpdateData.AspId != "" && appSessionContextUpdateData.SponId != "" { + umId := util.GetUmId(appSessionContextUpdateData.AspId, appSessionContextUpdateData.SponId) + var umData *models.UsageMonitoringData + if tempUmData, err := extractUmData(umId, eventSubs, + threshRmToThresh(appSessionContextUpdateData.EvSubsc.UsgThres)); err != nil { + problemDetail := util.GetProblemDetail(err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return &problemDetail, nil + } else { + umData = tempUmData } - err = handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, request.AspId, request.SponId, request.SponStatus, umData, &updateSMpolicy) - if err != nil { - return + if err := handleSponsoredConnectivityInformation(smPolicy, relatedPccRuleIds, appSessionContextUpdateData.AspId, + appSessionContextUpdateData.SponId, appSessionContextUpdateData.SponStatus, umData, &updateSMpolicy); err != nil { + problemDetail := util.GetProblemDetail(err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return &problemDetail, nil } } @@ -766,7 +772,6 @@ func ModAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessi // TODO: MPS Sevice logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Updated", appSessionId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *appContext) smPolicy.ArrangeExistEventSubscription() @@ -780,33 +785,44 @@ func ModAppSessionContext(httpChannel chan message.HttpResponseMessage, appSessi SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) } - + return nil, appContext } -// DeleteEventsSubsc - deletes the Events Subscription subresource -func DeleteEventsSubscContext(httpChannel chan message.HttpResponseMessage, appSessionId string) { - +// HandleDeleteEventsSubsc - deletes the Events Subscription subresource +func HandleDeleteEventsSubscContext(request *http_wrapper.Request) *http_wrapper.Response { + appSessionId := request.Params["appSessionId"] logger.PolicyAuthorizationlog.Tracef("Handle Del AppSessions Events Subsc, AppSessionId[%s]", appSessionId) - pcfSelf := pcf_context.PCF_Self() - appSession := pcfSelf.AppSessionPool[appSessionId] + problemDetails := DeleteEventsSubscContextProcedure(appSessionId) + if problemDetails == nil { + return http_wrapper.NewResponse(http.StatusNoContent, nil, nil) + } else { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } +} + +func DeleteEventsSubscContextProcedure(appSessionId string) *models.ProblemDetails { + pcfSelf := pcf_context.PCF_Self() + var appSession *pcf_context.AppSessionData + if val, ok := pcfSelf.AppSessionPool.Load(appSessionId); ok { + appSession = val.(*pcf_context.AppSessionData) + } if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) - return + problemDetail := util.GetProblemDetail("can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return &problemDetail } appSession.Events = nil appSession.EventUri = "" appSession.AppSessionContext.EvsNotif = nil appSession.AppSessionContext.AscReqData.EvSubsc = nil - changed := appSession.SmPolicyData.ArrangeExistEventSubscription() + // changed := appSession.SmPolicyData.ArrangeExistEventSubscription() logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Del Events Subsc success", appSessionId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) smPolicy := appSession.SmPolicyData // Send Notification to SMF - if changed { + if changed := appSession.SmPolicyData.ArrangeExistEventSubscription(); changed { smPolicyId := fmt.Sprintf("%s-%d", smPolicy.PcfUe.Supi, smPolicy.PolicyContext.PduSessionId) notification := models.SmPolicyNotification{ ResourceUri: util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId), @@ -815,19 +831,79 @@ func DeleteEventsSubscContext(httpChannel chan message.HttpResponseMessage, appS SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) } + return nil } -// UpdateEventsSubsc - creates or modifies an Events Subscription subresource -func UpdateEventsSubscContext(httpChannel chan message.HttpResponseMessage, appSessionId string, request models.EventsSubscReqData) { - +// HandleUpdateEventsSubsc - creates or modifies an Events Subscription subresource +func HandleUpdateEventsSubscContext(request *http_wrapper.Request) *http_wrapper.Response { + EventsSubscReqData := request.Body.(models.EventsSubscReqData) + appSessionId := request.Params["appSessionId"] logger.PolicyAuthorizationlog.Tracef("Handle Put AppSessions Events Subsc, AppSessionId[%s]", appSessionId) - pcfSelf := pcf_context.PCF_Self() - appSession := pcfSelf.AppSessionPool[appSessionId] + response, locationHeader, status, problemDetails := UpdateEventsSubscContextProcedure(appSessionId, EventsSubscReqData) + if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } else if status == http.StatusCreated { + headers := http.Header{ + "Location": {locationHeader}, + } + return http_wrapper.NewResponse(http.StatusCreated, headers, response) + } else if status == http.StatusOK { + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else if status == http.StatusNoContent { + return http_wrapper.NewResponse(http.StatusNoContent, nil, response) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) +} + +func SendAppSessionEventNotification(appSession *pcf_context.AppSessionData, request models.EventsNotification) { + logger.PolicyAuthorizationlog.Tracef("Send App Session Event Notification") if appSession == nil { - sendProblemDetail(httpChannel, "can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + logger.PolicyAuthorizationlog.Warnln("Send App Session Event Notification Error[appSession is nil]") return } + uri := appSession.EventUri + if uri != "" { + request.EvSubsUri = fmt.Sprintf("%s/events-subscription", + util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSession.AppSessionId)) + client := util.GetNpcfPolicyAuthorizationCallbackClient() + httpResponse, err := client.PolicyAuthorizationEventNotificationApi.PolicyAuthorizationEventNotification( + context.Background(), uri, request) + if err != nil { + if httpResponse != nil { + logger.PolicyAuthorizationlog.Warnf("Send App Session Event Notification Error[%s]", httpResponse.Status) + } else { + logger.PolicyAuthorizationlog.Warnf("Send App Session Event Notification Failed[%s]", err.Error()) + } + return + } else if httpResponse == nil { + logger.PolicyAuthorizationlog.Warnln("Send App Session Event Notification Failed[HTTP Response is nil]") + return + } + if httpResponse.StatusCode != http.StatusOK && httpResponse.StatusCode != http.StatusNoContent { + logger.PolicyAuthorizationlog.Warnf("Send App Session Event Notification Failed") + } else { + logger.PolicyAuthorizationlog.Tracef("Send App Session Event Notification Success") + } + } +} + +func UpdateEventsSubscContextProcedure(appSessionId string, eventsSubscReqData models.EventsSubscReqData) ( + *models.UpdateEventsSubscResponse, string, int, *models.ProblemDetails) { + pcfSelf := pcf_context.PCF_Self() + + var appSession *pcf_context.AppSessionData + if val, ok := pcfSelf.AppSessionPool.Load(appSessionId); ok { + appSession = val.(*pcf_context.AppSessionData) + } + if appSession == nil { + problemDetail := util.GetProblemDetail("can't find app session", util.APPLICATION_SESSION_CONTEXT_NOT_FOUND) + return nil, "", int(problemDetail.Status), &problemDetail + } smPolicy := appSession.SmPolicyData eventSubs := make(map[models.AfEvent]models.AfNotifMethod) @@ -837,7 +913,7 @@ func UpdateEventsSubscContext(httpChannel chan message.HttpResponseMessage, appS created = true } - for _, subs := range request.Events { + for _, subs := range eventsSubscReqData.Events { if subs.NotifMethod == "" { // default value "EVENT_DETECTION" subs.NotifMethod = models.AfNotifMethod_EVENT_DETECTION @@ -873,7 +949,8 @@ func UpdateEventsSubscContext(httpChannel chan message.HttpResponseMessage, appS continue } if !util.CheckPolicyControlReqTrig(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) { - smPolicy.PolicyDecision.PolicyCtrlReqTriggers = append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) + smPolicy.PolicyDecision.PolicyCtrlReqTriggers = + append(smPolicy.PolicyDecision.PolicyCtrlReqTriggers, trig) updataSmPolicy = true } @@ -883,19 +960,19 @@ func UpdateEventsSubscContext(httpChannel chan message.HttpResponseMessage, appS if appContext.AscReqData.EvSubsc == nil { appContext.AscReqData.EvSubsc = new(models.EventsSubscReqData) } - appContext.AscReqData.EvSubsc.Events = request.Events - appContext.AscReqData.EvSubsc.UsgThres = request.UsgThres - appContext.AscReqData.EvSubsc.NotifUri = request.NotifUri + appContext.AscReqData.EvSubsc.Events = eventsSubscReqData.Events + appContext.AscReqData.EvSubsc.UsgThres = eventsSubscReqData.UsgThres + appContext.AscReqData.EvSubsc.NotifUri = eventsSubscReqData.NotifUri appContext.EvsNotif = nil // update app Session - appSession.EventUri = request.NotifUri + appSession.EventUri = eventsSubscReqData.NotifUri appSession.Events = eventSubs resp := models.UpdateEventsSubscResponse{ - EvSubsc: request, + EvSubsc: eventsSubscReqData, } appContext.EvsNotif = &models.EventsNotification{ - EvSubsUri: request.NotifUri, + EvSubsUri: eventsSubscReqData.NotifUri, } // Set Event Subsciption related Data if len(eventSubs) > 0 { @@ -927,21 +1004,6 @@ func UpdateEventsSubscContext(httpChannel chan message.HttpResponseMessage, appS resp.EvsNotif = appContext.EvsNotif - if created { - locationHeader := fmt.Sprintf("%s/events-subscription", util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId)) - headers := http.Header{ - "Location": {locationHeader}, - } - logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create Subscription", appSessionId) - message.SendHttpResponseMessage(httpChannel, headers, http.StatusCreated, resp) - } else if resp.EvsNotif != nil { - logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Modify Subscription", appSessionId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, resp) - } else { - logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Modify Subscription", appSessionId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, resp) - } - changed := appSession.SmPolicyData.ArrangeExistEventSubscription() // Send Notification to SMF @@ -954,35 +1016,17 @@ func UpdateEventsSubscContext(httpChannel chan message.HttpResponseMessage, appS SendSMPolicyUpdateNotification(smPolicy.PcfUe, smPolicyId, notification) logger.PolicyAuthorizationlog.Tracef("Send SM Policy[%s] Update Notification", smPolicyId) } -} - -func SendAppSessionEventNotification(appSession *pcf_context.AppSessionData, request models.EventsNotification) { - logger.PolicyAuthorizationlog.Tracef("Send App Session Event Notification") - if appSession == nil { - logger.PolicyAuthorizationlog.Warnln("Send App Session Event Notification Error[appSession is nil]") - return - } - uri := appSession.EventUri - if uri != "" { - request.EvSubsUri = fmt.Sprintf("%s/events-subscription", util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSession.AppSessionId)) - client := util.GetNpcfPolicyAuthorizationCallbackClient() - httpResponse, err := client.PolicyAuthorizationEventNotificationApi.PolicyAuthorizationEventNotification(context.Background(), uri, request) - if err != nil { - if httpResponse != nil { - logger.PolicyAuthorizationlog.Warnf("Send App Session Event Notification Error[%s]", httpResponse.Status) - } else { - logger.PolicyAuthorizationlog.Warnf("Send App Session Event Notification Failed[%s]", err.Error()) - } - return - } else if httpResponse == nil { - logger.PolicyAuthorizationlog.Warnln("Send App Session Event Notification Failed[HTTP Response is nil]") - return - } - if httpResponse.StatusCode != http.StatusOK && httpResponse.StatusCode != http.StatusNoContent { - logger.PolicyAuthorizationlog.Warnf("Send App Session Event Notification Failed") - } else { - logger.PolicyAuthorizationlog.Tracef("Send App Session Event Notification Success") - } + if created { + locationHeader := fmt.Sprintf("%s/events-subscription", + util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSessionId)) + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Create Subscription", appSessionId) + return &resp, locationHeader, http.StatusCreated, nil + } else if resp.EvsNotif != nil { + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Modify Subscription", appSessionId) + return &resp, "", http.StatusOK, nil + } else { + logger.PolicyAuthorizationlog.Tracef("App Session Id[%s] Modify Subscription", appSessionId) + return &resp, "", http.StatusNoContent, nil } } @@ -996,7 +1040,8 @@ func SendAppSessionTermination(appSession *pcf_context.AppSessionData, request m if uri != "" { request.ResUri = util.GetResourceUri(models.ServiceName_NPCF_POLICYAUTHORIZATION, appSession.AppSessionId) client := util.GetNpcfPolicyAuthorizationCallbackClient() - httpResponse, err := client.PolicyAuthorizationTerminateRequestApi.PolicyAuthorizationTerminateRequest(context.Background(), uri, request) + httpResponse, err := client.PolicyAuthorizationTerminateRequestApi.PolicyAuthorizationTerminateRequest( + context.Background(), uri, request) if err != nil { if httpResponse != nil { logger.PolicyAuthorizationlog.Warnf("Send App Session Termination Error[%s]", httpResponse.Status) @@ -1017,13 +1062,20 @@ func SendAppSessionTermination(appSession *pcf_context.AppSessionData, request m } // Handle Create/ Modify Background Data Transfer Policy Indication -func handleBackgroundDataTransferPolicyIndication(pcfSelf *pcf_context.PCFContext, appContext *models.AppSessionContext) (err error) { +func handleBackgroundDataTransferPolicyIndication(pcfSelf *pcf_context.PCFContext, + appContext *models.AppSessionContext) (err error) { req := appContext.AscReqData - requestSuppFeat, _ := openapi.NewSupportedFeature(req.SuppFeat) + var requestSuppFeat openapi.SupportedFeature + if tempRequestSuppFeat, err := openapi.NewSupportedFeature(req.SuppFeat); err != nil { + logger.PolicyAuthorizationlog.Errorf("Sponsored Connectivity is disabled by AF") + } else { + requestSuppFeat = tempRequestSuppFeat + } respData := models.AppSessionContextRespData{ ServAuthInfo: models.ServAuthInfo_NOT_KNOWN, - SuppFeat: pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION].NegotiateWith(requestSuppFeat).String(), + SuppFeat: pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_POLICYAUTHORIZATION].NegotiateWith( + requestSuppFeat).String(), } client := util.GetNudrClient(getDefaultUdrUri(pcfSelf)) bdtData, resp, err1 := client.DefaultApi.PolicyDataBdtDataBdtReferenceIdGet(context.Background(), req.BdtRefId) @@ -1051,7 +1103,9 @@ func handleBackgroundDataTransferPolicyIndication(pcfSelf *pcf_context.PCFContex } // provisioning of sponsored connectivity information -func handleSponsoredConnectivityInformation(smPolicy *pcf_context.UeSmPolicyData, relatedPccRuleIds map[string]string, aspId, sponId string, sponStatus models.SponsoringStatus, umData *models.UsageMonitoringData, updateSMpolicy *bool) (err error) { +func handleSponsoredConnectivityInformation(smPolicy *pcf_context.UeSmPolicyData, relatedPccRuleIds map[string]string, + aspId, sponId string, sponStatus models.SponsoringStatus, umData *models.UsageMonitoringData, + updateSMpolicy *bool) error { if sponStatus == models.SponsoringStatus_DISABLED { logger.PolicyAuthorizationlog.Debugf("Sponsored Connectivity is disabled by AF") umId := util.GetUmId(aspId, sponId) @@ -1081,8 +1135,8 @@ func handleSponsoredConnectivityInformation(smPolicy *pcf_context.UeSmPolicyData if umData != nil { supp := util.CheckSuppFeat(smPolicy.PolicyDecision.SuppFeat, 5) // UMC support = 5 in 29512 if !supp { - err = fmt.Errorf("Usage Monitor Control is not supported in SMF") - return + err := fmt.Errorf("Usage Monitor Control is not supported in SMF") + return err } } chgIdUsed := false @@ -1098,9 +1152,11 @@ func handleSponsoredConnectivityInformation(smPolicy *pcf_context.UeSmPolicyData } else { chgIdUsed = true } - // TODO: PCF, based on operator policies, shall check whether it is required to validate the sponsored connectivity data. + // TODO: PCF, based on operator policies, shall check whether it is required to + // validate the sponsored connectivity data. // If it is required, it shall perform the authorizations based on sponsored data connectivity profiles. - // If the authorization fails, the PCF shall send HTTP "403 Forbidden" with the "cause" attribute set to "UNAUTHORIZED_SPONSORED_DATA_CONNECTIVITY" + // If the authorization fails, the PCF shall send HTTP "403 Forbidden" with the "cause" attribute set to + // "UNAUTHORIZED_SPONSORED_DATA_CONNECTIVITY" pccRule.RefChgData = []string{chgData.ChgId} chgData.ReportingLevel = models.ReportingLevel_SPON_CON_LEVEL chgData.SponsorId = sponId @@ -1116,7 +1172,7 @@ func handleSponsoredConnectivityInformation(smPolicy *pcf_context.UeSmPolicyData } // TODO: handling UE is roaming in VPLMN case } - return + return nil } func getMaxPrecedence(pccRules map[string]models.PccRule) (maxVaule int32) { @@ -1176,7 +1232,8 @@ func getFlowInfos(comp models.MediaComponent) (flows []models.FlowInformation, e } */ -func getFlowInfos(subComp models.MediaSubComponent) (flows []models.FlowInformation, err error) { +func getFlowInfos(subComp *models.MediaSubComponent) ([]models.FlowInformation, error) { + var flows []models.FlowInformation if subComp.EthfDescs != nil { return nil, fmt.Errorf("Flow Description with Mac Address does not support") } @@ -1214,7 +1271,7 @@ func getFlowInfos(subComp models.MediaSubComponent) (flows []models.FlowInformat } flows = append(flows, flowInfo) } - return + return flows, nil } func flowDescriptionFromN5toN7(n5Flow string) (n7Flow string, direction models.FlowDirection, err error) { @@ -1232,12 +1289,15 @@ func flowDescriptionFromN5toN7(n5Flow string) (n7Flow string, direction models.F } return } -func updateQos_Comp(qosData models.QosData, comp models.MediaComponent) (updatedQosData models.QosData, ulExist, dlExist bool) { - updatedQosData = qosData +func updateQos_Comp(qosData models.QosData, comp *models.MediaComponent) (models.QosData, + bool, bool) { + var dlExist bool + var ulExist bool + updatedQosData := qosData if comp.FStatus == models.FlowStatus_REMOVED { updatedQosData.MaxbrDl = "" updatedQosData.MaxbrUl = "" - return + return updatedQosData, ulExist, dlExist } maxBwUl := 0.0 maxBwDl := 0.0 @@ -1245,7 +1305,11 @@ func updateQos_Comp(qosData models.QosData, comp models.MediaComponent) (updated minBwDl := 0.0 for _, subsComp := range comp.MedSubComps { for _, flow := range subsComp.FDescs { - _, dir, _ := flowDescriptionFromN5toN7(flow) + _, dir, err := flowDescriptionFromN5toN7(flow) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "flowDescriptionFromN5toN7 error in updateQos_Comp: %+v", err) + } both := false if dir == models.FlowDirection_BIDIRECTIONAL { both = true @@ -1255,22 +1319,38 @@ func updateQos_Comp(qosData models.QosData, comp models.MediaComponent) (updated if both || dir == models.FlowDirection_UPLINK { ulExist = true if comp.MarBwUl != "" { - bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + bwUl, err := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_Comp: %+v", err) + } maxBwUl += bwUl } if comp.MirBwUl != "" { - bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MirBwUl) + bwUl, err := pcf_context.ConvertBitRateToKbps(comp.MirBwUl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_Comp: %+v", err) + } minBwUl += bwUl } } if both || dir == models.FlowDirection_DOWNLINK { dlExist = true if comp.MarBwDl != "" { - bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + bwDl, err := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_Comp: %+v", err) + } maxBwDl += bwDl } if comp.MirBwDl != "" { - bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MirBwDl) + bwDl, err := pcf_context.ConvertBitRateToKbps(comp.MirBwDl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_Comp: %+v", err) + } minBwDl += bwDl } } @@ -1278,20 +1358,36 @@ func updateQos_Comp(qosData models.QosData, comp models.MediaComponent) (updated if both || dir == models.FlowDirection_UPLINK { ulExist = true if subsComp.MarBwUl != "" { - bwUl, _ := pcf_context.ConvertBitRateToKbps(subsComp.MarBwUl) + bwUl, err := pcf_context.ConvertBitRateToKbps(subsComp.MarBwUl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_Comp: %+v", err) + } maxBwUl += bwUl } else if comp.MarBwUl != "" { - bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + bwUl, err := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_Comp: %+v", err) + } maxBwUl += (0.05 * bwUl) } } if both || dir == models.FlowDirection_DOWNLINK { dlExist = true if subsComp.MarBwDl != "" { - bwDl, _ := pcf_context.ConvertBitRateToKbps(subsComp.MarBwDl) + bwDl, err := pcf_context.ConvertBitRateToKbps(subsComp.MarBwDl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_Comp: %+v", err) + } maxBwDl += bwDl } else if comp.MarBwDl != "" { - bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + bwDl, err := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_Comp: %+v", err) + } maxBwDl += (0.05 * bwDl) } } @@ -1320,10 +1416,11 @@ func updateQos_Comp(qosData models.QosData, comp models.MediaComponent) (updated if minBwUl != 0.0 { updatedQosData.GbrUl = pcf_context.ConvertBitRateToString(minBwUl) } - return + return updatedQosData, ulExist, dlExist } -func updateQos_subComp(qosData models.QosData, comp models.MediaComponent, subsComp models.MediaSubComponent) (updatedQosData models.QosData, ulExist, dlExist bool) { +func updateQos_subComp(qosData models.QosData, comp *models.MediaComponent, + subsComp *models.MediaSubComponent) (updatedQosData models.QosData, ulExist, dlExist bool) { updatedQosData = qosData if comp.FStatus == models.FlowStatus_REMOVED { updatedQosData.MaxbrDl = "" @@ -1335,7 +1432,11 @@ func updateQos_subComp(qosData models.QosData, comp models.MediaComponent, subsC minBwUl := 0.0 minBwDl := 0.0 for _, flow := range subsComp.FDescs { - _, dir, _ := flowDescriptionFromN5toN7(flow) + _, dir, err := flowDescriptionFromN5toN7(flow) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "flowDescriptionFromN5toN7 error in updateQos_subComp: %+v", err) + } both := false if dir == models.FlowDirection_BIDIRECTIONAL { both = true @@ -1345,22 +1446,38 @@ func updateQos_subComp(qosData models.QosData, comp models.MediaComponent, subsC if both || dir == models.FlowDirection_UPLINK { ulExist = true if comp.MarBwUl != "" { - bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + bwUl, err := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_subComp: %+v", err) + } maxBwUl += bwUl } if comp.MirBwUl != "" { - bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MirBwUl) + bwUl, err := pcf_context.ConvertBitRateToKbps(comp.MirBwUl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_subComp: %+v", err) + } minBwUl += bwUl } } if both || dir == models.FlowDirection_DOWNLINK { dlExist = true if comp.MarBwDl != "" { - bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + bwDl, err := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_subComp: %+v", err) + } maxBwDl += bwDl } if comp.MirBwDl != "" { - bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MirBwDl) + bwDl, err := pcf_context.ConvertBitRateToKbps(comp.MirBwDl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_subComp: %+v", err) + } minBwDl += bwDl } } @@ -1368,20 +1485,36 @@ func updateQos_subComp(qosData models.QosData, comp models.MediaComponent, subsC if both || dir == models.FlowDirection_UPLINK { ulExist = true if subsComp.MarBwUl != "" { - bwUl, _ := pcf_context.ConvertBitRateToKbps(subsComp.MarBwUl) + bwUl, err := pcf_context.ConvertBitRateToKbps(subsComp.MarBwUl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_subComp: %+v", err) + } maxBwUl += bwUl } else if comp.MarBwUl != "" { - bwUl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + bwUl, err := pcf_context.ConvertBitRateToKbps(comp.MarBwUl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_subComp: %+v", err) + } maxBwUl += (0.05 * bwUl) } } if both || dir == models.FlowDirection_DOWNLINK { dlExist = true if subsComp.MarBwDl != "" { - bwDl, _ := pcf_context.ConvertBitRateToKbps(subsComp.MarBwDl) + bwDl, err := pcf_context.ConvertBitRateToKbps(subsComp.MarBwDl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_subComp: %+v", err) + } maxBwDl += bwDl } else if comp.MarBwDl != "" { - bwDl, _ := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + bwDl, err := pcf_context.ConvertBitRateToKbps(comp.MarBwDl) + if err != nil { + logger.PolicyAuthorizationlog.Errorf( + "pcf_context ConvertBitRateToKbps error in updateQos_subComp: %+v", err) + } maxBwDl += (0.05 * bwDl) } } @@ -1409,7 +1542,7 @@ func updateQos_subComp(qosData models.QosData, comp models.MediaComponent, subsC if minBwUl != 0.0 { updatedQosData.GbrUl = pcf_context.ConvertBitRateToString(minBwUl) } - return + return updatedQosData, ulExist, dlExist } func removeMediaComp(appSession *pcf_context.AppSessionData, compN string) { @@ -1478,7 +1611,8 @@ func threshRmToThresh(threshrm *models.UsageThresholdRm) *models.UsageThreshold } } -func extractUmData(umId string, eventSubs map[models.AfEvent]models.AfNotifMethod, threshold *models.UsageThreshold) (umData *models.UsageMonitoringData, err error) { +func extractUmData(umId string, eventSubs map[models.AfEvent]models.AfNotifMethod, + threshold *models.UsageThreshold) (umData *models.UsageMonitoringData, err error) { if _, umExist := eventSubs[models.AfEvent_USAGE_REPORT]; umExist { if threshold == nil { return nil, fmt.Errorf("UsageThreshold is nil in USAGE REPORT Subscription") @@ -1491,76 +1625,80 @@ func extractUmData(umId string, eventSubs map[models.AfEvent]models.AfNotifMetho return } -func modifyRemainBitRate(httpChannel chan message.HttpResponseMessage, smPolicy *pcf_context.UeSmPolicyData, qosData *models.QosData, ulExist, dlExist bool) (err error) { +func modifyRemainBitRate(smPolicy *pcf_context.UeSmPolicyData, qosData *models.QosData, + ulExist, dlExist bool) *models.ProblemDetails { // if request GBR == 0, qos GBR = MBR // if request GBR > remain GBR, qos GBR = remain GBR if ulExist { if qosData.GbrUl == "" { - err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.MaxbrUl) - if err != nil { + // err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.MaxbrUl) + if err := pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.MaxbrUl); err != nil { qosData.GbrUl = pcf_context.DecreaseRamainBitRateToZero(smPolicy.RemainGbrUL) } else { qosData.GbrUl = qosData.MaxbrUl } } else { - err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.GbrUl) - if err != nil { - sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return + // err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.GbrUl) + if err := pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.GbrUl); err != nil { + problemDetail := util.GetProblemDetail(err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) + // sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return &problemDetail } } } if dlExist { if qosData.GbrDl == "" { - err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrDL, qosData.MaxbrDl) - if err != nil { + // err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrDL, qosData.MaxbrDl) + if err := pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrDL, qosData.MaxbrDl); err != nil { qosData.GbrDl = pcf_context.DecreaseRamainBitRateToZero(smPolicy.RemainGbrDL) } else { qosData.GbrDl = qosData.MaxbrDl } } else { - err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrDL, qosData.GbrDl) - if err != nil { + // err = pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrDL, qosData.GbrDl) + if err := pcf_context.DecreaseRamainBitRate(smPolicy.RemainGbrDL, qosData.GbrDl); err != nil { // if Policy failed, revert remain GBR to original GBR pcf_context.IncreaseRamainBitRate(smPolicy.RemainGbrUL, qosData.GbrUl) - sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) - return + problemDetail := util.GetProblemDetail(err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) + // sendProblemDetail(httpChannel, err.Error(), util.REQUESTED_SERVICE_NOT_AUTHORIZED) + return &problemDetail } } } return nil } -func InitialProvisioningOfTrafficRoutingInformation(smPolicy *pcf_context.UeSmPolicyData, pccRule *models.PccRule, compAfRoutReq, reqAfRoutReq *models.AfRoutingRequirement) { - for _, tcId := range pccRule.RefTcData { - tcData := smPolicy.PolicyDecision.TraffContDecs[tcId] - if compAfRoutReq != nil { - tcData.RouteToLocs = append(tcData.RouteToLocs, compAfRoutReq.RouteToLocs...) - tcData.UpPathChgEvent = compAfRoutReq.UpPathChgSub - pccRule.AppReloc = compAfRoutReq.AppReloc - } else if reqAfRoutReq != nil { - tcData.RouteToLocs = append(tcData.RouteToLocs, reqAfRoutReq.RouteToLocs...) - tcData.UpPathChgEvent = reqAfRoutReq.UpPathChgSub - pccRule.AppReloc = reqAfRoutReq.AppReloc - } - smPolicy.PolicyDecision.TraffContDecs[tcData.TcId] = tcData - } -} - -func ModifyProvisioningOfTrafficRoutingInformation(smPolicy *pcf_context.UeSmPolicyData, pccRule *models.PccRule, compAfRoutReq, reqAfRoutReq *models.AfRoutingRequirementRm) { - for _, tcId := range pccRule.RefTcData { - tcData := smPolicy.PolicyDecision.TraffContDecs[tcId] - if compAfRoutReq != nil { - tcData.RouteToLocs = append(tcData.RouteToLocs, compAfRoutReq.RouteToLocs...) - tcData.UpPathChgEvent = compAfRoutReq.UpPathChgSub - pccRule.AppReloc = compAfRoutReq.AppReloc - } else if reqAfRoutReq != nil { - tcData.RouteToLocs = append(tcData.RouteToLocs, reqAfRoutReq.RouteToLocs...) - tcData.UpPathChgEvent = reqAfRoutReq.UpPathChgSub - pccRule.AppReloc = reqAfRoutReq.AppReloc +func provisioningOfTrafficRoutingInfo(smPolicy *pcf_context.UeSmPolicyData, appId string, + routeReq *models.AfRoutingRequirement, fStatus models.FlowStatus) *models.PccRule { + createdTcData := util.CreateTcData(smPolicy.PccRuleIdGenarator, fStatus) + createdTcData.RouteToLocs = routeReq.RouteToLocs + createdTcData.UpPathChgEvent = routeReq.UpPathChgSub + + //TODO : handle temporal or spatial validity + pccRule := util.GetPccRuleByAfAppId(smPolicy.PolicyDecision.PccRules, appId) + if pccRule != nil { + createdTcData.TcId = strings.ReplaceAll(pccRule.PccRuleId, "PccRule", "Tc") + pccRule.RefTcData = []string{createdTcData.TcId} + pccRule.AppReloc = routeReq.AppReloc + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &createdTcData, nil, nil, nil) + logger.PolicyAuthorizationlog.Infof("Modify PCC rule[%s] with new Traffic Control Data[%s]", + pccRule.PccRuleId, createdTcData.TcId) + } else { + // Create a Pcc Rule if afappId dose not match any pcc rule + maxPrecedence := getMaxPrecedence(smPolicy.PolicyDecision.PccRules) + pccRule = util.CreatePccRule(smPolicy.PccRuleIdGenarator, maxPrecedence+1, nil, appId, false) + qosData := models.QosData{ + QosId: util.GetQosId(smPolicy.PccRuleIdGenarator), + DefQosFlowIndication: true, } - smPolicy.PolicyDecision.TraffContDecs[tcData.TcId] = tcData - } + pccRule.RefTcData = []string{createdTcData.TcId} + pccRule.RefQosData = []string{qosData.QosId} + util.SetPccRuleRelatedData(smPolicy.PolicyDecision, pccRule, &createdTcData, &qosData, nil, nil) + smPolicy.PccRuleIdGenarator++ + logger.PolicyAuthorizationlog.Infof("Create PCC rule[%s] with new Traffic Control Data[%s]", + pccRule.PccRuleId, createdTcData.TcId) + } + return pccRule } func reverseStringMap(srcMap map[string]string) map[string]string { @@ -1573,9 +1711,3 @@ func reverseStringMap(srcMap map[string]string) map[string]string { } return reverseMap } - -func sendProblemDetail(httpChannel chan message.HttpResponseMessage, errDetail, errCause string) { - rsp := util.GetProblemDetail(errDetail, errCause) - logger.PolicyAuthorizationlog.Error(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) -} diff --git a/producer/smpolicy.go b/producer/smpolicy.go index f9970d2..92d27cd 100644 --- a/producer/smpolicy.go +++ b/producer/smpolicy.go @@ -1,13 +1,13 @@ -package pcf_producer +package producer import ( "context" "fmt" + "free5gc/lib/http_wrapper" "free5gc/lib/openapi" "free5gc/lib/openapi/Nudr_DataRepository" "free5gc/lib/openapi/models" pcf_context "free5gc/src/pcf/context" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" "free5gc/src/pcf/util" "net/http" @@ -18,27 +18,58 @@ import ( ) // SmPoliciesPost - -func CreateSmPolicy(httpChannel chan message.HttpResponseMessage, request models.SmPolicyContextData) { - var err error +func HandleCreateSmPolicyRequest(request *http_wrapper.Request) *http_wrapper.Response { + // step 1: log + logger.SMpolicylog.Infof("Handle CreateSmPolicy") + // step 2: retrieve request + requestDataType := request.Body.(models.SmPolicyContextData) + + // step 3: handle the message + header, response, problemDetails := createSMPolicyProcedure(requestDataType) + + // step 4: process the return value from step 3 + if response != nil { + // status code is based on SPEC, and option headers + return http_wrapper.NewResponse(http.StatusCreated, header, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } else { + return http_wrapper.NewResponse(http.StatusNotFound, nil, nil) + } +} +func createSMPolicyProcedure(request models.SmPolicyContextData) ( + header http.Header, response *models.SmPolicyDecision, problemDetails *models.ProblemDetails) { + var err error logger.SMpolicylog.Tracef("Handle Create SM Policy Request") + + if request.Supi == "" || request.SliceInfo == nil || len(request.SliceInfo.Sd) != 6 { + problemDetail := util.GetProblemDetail("Errorneous/Missing Mandotory IE", util.ERROR_INITIAL_PARAMETERS) + logger.SMpolicylog.Warnln("Errorneous/Missing Mandotory IE", util.ERROR_INITIAL_PARAMETERS) + return nil, nil, &problemDetail + } + pcfSelf := pcf_context.PCF_Self() - ue := pcfSelf.UePool[request.Supi] + var ue *pcf_context.UeContext + if val, exist := pcfSelf.UePool.Load(request.Supi); exist { + ue = val.(*pcf_context.UeContext) + } + if ue == nil { - rsp := util.GetProblemDetail("Supi is not supported in PCF", util.USER_UNKNOWN) + problemDetail := util.GetProblemDetail("Supi is not supported in PCF", util.USER_UNKNOWN) logger.SMpolicylog.Warnf("Supi[%s] is not supported in PCF", request.Supi) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return nil, nil, &problemDetail + } udrUri := getUdrUri(ue) if udrUri == "" { - rsp := util.GetProblemDetail("Can't find corresponding UDR with UE", util.USER_UNKNOWN) + problemDetail := util.GetProblemDetail("Can't find corresponding UDR with UE", util.USER_UNKNOWN) logger.SMpolicylog.Warnf("Can't find corresponding UDR with UE[%s]", ue.Supi) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + return nil, nil, &problemDetail } var smData models.SmPolicyData - smPolicyId := fmt.Sprintf("%s-%d", ue.Supi, request.PduSessionId) - smPolicyData := ue.SmPolicyData[smPolicyId] + smPolicyID := fmt.Sprintf("%s-%d", ue.Supi, request.PduSessionId) + smPolicyData := ue.SmPolicyData[smPolicyID] if smPolicyData == nil || smPolicyData.SmPolicyData == nil { client := util.GetNudrClient(udrUri) param := Nudr_DataRepository.PolicyDataUesUeIdSmDataGetParamOpts{ @@ -48,11 +79,9 @@ func CreateSmPolicy(httpChannel chan message.HttpResponseMessage, request models var response *http.Response smData, response, err = client.DefaultApi.PolicyDataUesUeIdSmDataGet(context.Background(), ue.Supi, ¶m) if err != nil || response == nil || response.StatusCode != http.StatusOK { - rsp := util.GetProblemDetail("Can't find UE SM Policy Data in UDR", util.USER_UNKNOWN) + problemDetail := util.GetProblemDetail("Can't find UE SM Policy Data in UDR", util.USER_UNKNOWN) logger.SMpolicylog.Warnf("Can't find UE[%s] SM Policy Data in UDR", ue.Supi) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return - // logger.SMpolicylog.Warnln("Nudr Query failed [%s]", err.Error()) + return nil, nil, &problemDetail } //TODO: subscribe to UDR } else { @@ -60,10 +89,10 @@ func CreateSmPolicy(httpChannel chan message.HttpResponseMessage, request models } amPolicy := ue.FindAMPolicy(request.AccessType, request.ServingNetwork) if amPolicy == nil { - rsp := util.GetProblemDetail("Can't find corresponding AM Policy", util.POLICY_CONTEXT_DENIED) + problemDetail := util.GetProblemDetail("Can't find corresponding AM Policy", util.POLICY_CONTEXT_DENIED) logger.SMpolicylog.Warnf("Can't find corresponding AM Policy") - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + //message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) + return nil, nil, &problemDetail } // TODO: check service restrict if ue.Gpsi == "" { @@ -73,9 +102,9 @@ func CreateSmPolicy(httpChannel chan message.HttpResponseMessage, request models ue.Pei = request.Pei } if smPolicyData != nil { - delete(ue.SmPolicyData, smPolicyId) + delete(ue.SmPolicyData, smPolicyID) } - smPolicyData = ue.NewUeSmPolicyData(smPolicyId, request, &smData) + smPolicyData = ue.NewUeSmPolicyData(smPolicyID, request, &smData) // Policy Decision decision := models.SmPolicyDecision{ SessRules: make(map[string]models.SessionRule), @@ -107,7 +136,8 @@ func CreateSmPolicy(httpChannel chan message.HttpResponseMessage, request models decision.Ipv6Index = dnnData.Ipv6Index // Set Aggregate GBR if exist if dnnData.GbrDl != "" { - gbrDL, err := pcf_context.ConvertBitRateToKbps(dnnData.GbrDl) + var gbrDL float64 + gbrDL, err = pcf_context.ConvertBitRateToKbps(dnnData.GbrDl) if err != nil { logger.SMpolicylog.Warnf(err.Error()) } else { @@ -116,7 +146,8 @@ func CreateSmPolicy(httpChannel chan message.HttpResponseMessage, request models } } if dnnData.GbrUl != "" { - gbrUL, err := pcf_context.ConvertBitRateToKbps(dnnData.GbrUl) + var gbrUL float64 + gbrUL, err = pcf_context.ConvertBitRateToKbps(dnnData.GbrUl) if err != nil { logger.SMpolicylog.Warnf(err.Error()) } else { @@ -126,94 +157,164 @@ func CreateSmPolicy(httpChannel chan message.HttpResponseMessage, request models } } } else { - logger.SMpolicylog.Warnf("Policy Subscription Info: SMPolicyDnnData is null for dnn[%s] in UE[%s]", request.Dnn, ue.Supi) + logger.SMpolicylog.Warnf( + "Policy Subscription Info: SMPolicyDnnData is null for dnn[%s] in UE[%s]", request.Dnn, ue.Supi) decision.Online = request.Online decision.Offline = request.Offline } - requestSuppFeat, _ := openapi.NewSupportedFeature(request.SuppFeat) - decision.SuppFeat = pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_SMPOLICYCONTROL].NegotiateWith(requestSuppFeat).String() + requestSuppFeat, err := openapi.NewSupportedFeature(request.SuppFeat) + if err != nil { + logger.SMpolicylog.Errorf("openapi NewSupportedFeature error: %+v", err) + } + decision.SuppFeat = + pcfSelf.PcfSuppFeats[models.ServiceName_NPCF_SMPOLICYCONTROL].NegotiateWith(requestSuppFeat).String() decision.QosFlowUsage = request.QosFlowUsage // TODO: Trigger about UMC, ADC, NetLoc,... decision.PolicyCtrlReqTriggers = util.PolicyControlReqTrigToArray(0x40780f) smPolicyData.PolicyDecision = &decision // TODO: PCC rule, PraInfo ... - locationHeader := util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyId) - headers := http.Header{ + locationHeader := util.GetResourceUri(models.ServiceName_NPCF_SMPOLICYCONTROL, smPolicyID) + header = http.Header{ "Location": {locationHeader}, } logger.SMpolicylog.Tracef("SMPolicy PduSessionId[%d] Create", request.PduSessionId) - message.SendHttpResponseMessage(httpChannel, headers, 201, decision) + + return header, &decision, nil +} + +// SmPoliciessmPolicyIDDeletePost - +func HandleDeleteSmPolicyContextRequest(request *http_wrapper.Request) *http_wrapper.Response { + // step 1: log + logger.SMpolicylog.Infof("Handle DeleteSmPolicyContext") + + // step 2: retrieve request + smPolicyID := request.Params["smPolicyID"] + + // step 3: handle the message + problemDetails := deleteSmPolicyContextProcedure(smPolicyID) + + // step 4: process the return value from step 3 + if problemDetails != nil { + // status code is based on SPEC, and option headers + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } else { + return http_wrapper.NewResponse(http.StatusNoContent, nil, nil) + } } -// SmPoliciesSmPolicyIdDeletePost - -func DeleteSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolicyId string) { +func deleteSmPolicyContextProcedure(smPolicyID string) *models.ProblemDetails { logger.AMpolicylog.Traceln("Handle SM Policy Delete") - ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyId) - if ue == nil || ue.SmPolicyData[smPolicyId] == nil { - rsp := util.GetProblemDetail("smPolicyId not found in PCF", util.CONTEXT_NOT_FOUND) - logger.SMpolicylog.Warnf(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyID) + if ue == nil || ue.SmPolicyData[smPolicyID] == nil { + problemDetail := util.GetProblemDetail("smPolicyID not found in PCF", util.CONTEXT_NOT_FOUND) + logger.SMpolicylog.Warnf(problemDetail.Detail) + return &problemDetail } pcfSelf := pcf_context.PCF_Self() - smPolicy := ue.SmPolicyData[smPolicyId] + smPolicy := ue.SmPolicyData[smPolicyID] // Unsubscrice UDR - delete(ue.SmPolicyData, smPolicyId) - logger.SMpolicylog.Tracef("SMPolicy SmPolicyId[%s] DELETE", smPolicyId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusNoContent, nil) + delete(ue.SmPolicyData, smPolicyID) + logger.SMpolicylog.Tracef("SMPolicy smPolicyID[%s] DELETE", smPolicyID) // Release related App Session terminationInfo := models.TerminationInfo{ TermCause: models.TerminationCause_PDU_SESSION_TERMINATION, } - for appSessionId := range smPolicy.AppSessions { - if appSession, exist := pcfSelf.AppSessionPool[appSessionId]; exist { + for appSessionID := range smPolicy.AppSessions { + if val, exist := pcfSelf.AppSessionPool.Load(appSessionID); exist { + appSession := val.(*pcf_context.AppSessionData) SendAppSessionTermination(appSession, terminationInfo) - delete(pcfSelf.AppSessionPool, appSessionId) - logger.SMpolicylog.Tracef("SMPolicy[%s] DELETE Related AppSession[%s]", smPolicyId, appSessionId) - + pcfSelf.AppSessionPool.Delete(appSessionID) + logger.SMpolicylog.Tracef("SMPolicy[%s] DELETE Related AppSession[%s]", smPolicyID, appSessionID) } } + return nil +} +// SmPoliciessmPolicyIDGet - +func HandleGetSmPolicyContextRequest(request *http_wrapper.Request) *http_wrapper.Response { + // step 1: log + logger.SMpolicylog.Infof("Handle GetSmPolicyContext") + + // step 2: retrieve request + smPolicyID := request.Params["smPolicyID"] + // step 3: handle the message + response, problemDetails := getSmPolicyContextProcedure(smPolicyID) + + // step 4: process the return value from step 3 + if response != nil { + // status code is based on SPEC, and option headers + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(http.StatusForbidden, nil, problemDetails) } -// SmPoliciesSmPolicyIdGet - -func GetSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolicyId string) { +func getSmPolicyContextProcedure(smPolicyID string) ( + response *models.SmPolicyControl, problemDetails *models.ProblemDetails) { logger.SMpolicylog.Traceln("Handle GET SM Policy Request") - ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyId) - if ue == nil || ue.SmPolicyData[smPolicyId] == nil { - rsp := util.GetProblemDetail("smPolicyId not found in PCF", util.CONTEXT_NOT_FOUND) - logger.SMpolicylog.Warnf(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyID) + if ue == nil || ue.SmPolicyData[smPolicyID] == nil { + problemDetail := util.GetProblemDetail("smPolicyID not found in PCF", util.CONTEXT_NOT_FOUND) + logger.SMpolicylog.Warnf(problemDetail.Detail) + return nil, &problemDetail } - smPolicyData := ue.SmPolicyData[smPolicyId] - rsp := models.SmPolicyControl{ + smPolicyData := ue.SmPolicyData[smPolicyID] + response = &models.SmPolicyControl{ Policy: smPolicyData.PolicyDecision, Context: smPolicyData.PolicyContext, } - logger.SMpolicylog.Tracef("SMPolicy SmPolicyId[%s] GET", smPolicyId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, rsp) + logger.SMpolicylog.Tracef("SMPolicy smPolicyID[%s] GET", smPolicyID) + return response, nil } -// SmPoliciesSmPolicyIdUpdatePost - -func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolicyId string, request models.SmPolicyUpdateContextData) { +// SmPoliciessmPolicyIDUpdatePost - +func HandleUpdateSmPolicyContextRequest(request *http_wrapper.Request) *http_wrapper.Response { + // step 1: log + logger.SMpolicylog.Infof("Handle UpdateSmPolicyContext") - logger.SMpolicylog.Traceln("Handle SM Policy Update") + // step 2: retrieve request + requestDataType := request.Body.(models.SmPolicyUpdateContextData) + smPolicyID := request.Params["smPolicyId"] - ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyId) - if ue == nil || ue.SmPolicyData[smPolicyId] == nil { - rsp := util.GetProblemDetail("smPolicyId not found in PCF", util.CONTEXT_NOT_FOUND) - logger.SMpolicylog.Warnf(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + // step 3: handle the message + response, problemDetails := updateSmPolicyContextProcedure(requestDataType, smPolicyID) + + // step 4: process the return value from step 3 + if response != nil { + // status code is based on SPEC, and option headers + return http_wrapper.NewResponse(http.StatusOK, nil, response) + } else if problemDetails != nil { + return http_wrapper.NewResponse(int(problemDetails.Status), nil, problemDetails) + } + problemDetails = &models.ProblemDetails{ + Status: http.StatusForbidden, + Cause: "UNSPECIFIED", + } + return http_wrapper.NewResponse(http.StatusForbidden, nil, problemDetails) +} + +func updateSmPolicyContextProcedure(request models.SmPolicyUpdateContextData, smPolicyID string) ( + response *models.SmPolicyDecision, problemDetails *models.ProblemDetails) { + logger.SMpolicylog.Traceln("Handle updateSmPolicyContext") + + ue := pcf_context.PCF_Self().PCFUeFindByPolicyId(smPolicyID) + if ue == nil || ue.SmPolicyData[smPolicyID] == nil { + problemDetail := util.GetProblemDetail("smPolicyID not found in PCF", util.CONTEXT_NOT_FOUND) + logger.SMpolicylog.Warnf(problemDetail.Detail) + return nil, &problemDetail } - smPolicy := ue.SmPolicyData[smPolicyId] + smPolicy := ue.SmPolicyData[smPolicyID] smPolicyDecision := smPolicy.PolicyDecision smPolicyContext := smPolicy.PolicyContext errCause := "" @@ -238,7 +339,8 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic afEventsNotification.EvNotifs = append(afEventsNotification.EvNotifs, afNotif) logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) - case models.PolicyControlRequestTrigger_RES_MO_RE: // UE intiate resource modification to SMF (subsclause 4.2.4.17 in TS29512) + case models.PolicyControlRequestTrigger_RES_MO_RE: + // UE intiate resource modification to SMF (subsclause 4.2.4.17 in TS29512) req := request.UeInitResReq if req == nil { errCause = "UeInitResReq is nil in Trigger RES_MO_RE" @@ -258,7 +360,7 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic infos[i].PackFiltId = util.GetPackFiltId(smPolicy.PackFiltIdGenarator) smPolicy.PackFiltIdGenarator++ } - pccRule := util.CreatePccRule(id, req.Precedence, infos, false) + pccRule := util.CreatePccRule(id, req.Precedence, infos, "", false) // Add Traffic control Data tcData := util.CreateTcData(id, "") // TODO: ARP use real Data @@ -268,16 +370,17 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic // Set GBR qosData.GbrDl, qosData.GbrUl, err = smPolicy.DecreaseRemainGBR(req.ReqQos) if err != nil { - rsp := util.GetProblemDetail(err.Error(), util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) - logger.SMpolicylog.Warnf(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + problemDetail := util.GetProblemDetail(err.Error(), util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) + logger.SMpolicylog.Warnf(problemDetail.Detail) + return nil, &problemDetail } if qosData.GbrDl != "" { - logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then DL GBR remain[%.2f Kbps]", smPolicyContext.Dnn, qosData.GbrDl, *smPolicy.RemainGbrDL) + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then DL GBR remain[%.2f Kbps]", + smPolicyContext.Dnn, qosData.GbrDl, *smPolicy.RemainGbrDL) } if qosData.GbrUl != "" { - logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then UL GBR remain[%.2f Kbps]", smPolicyContext.Dnn, qosData.GbrUl, *smPolicy.RemainGbrUL) + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then UL GBR remain[%.2f Kbps]", + smPolicyContext.Dnn, qosData.GbrUl, *smPolicy.RemainGbrUL) } util.SetPccRuleRelatedData(smPolicyDecision, pccRule, &tcData, &qosData, nil, nil) // link Packet filters to PccRule @@ -298,7 +401,9 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic models.RuleOperation_MODIFY_PCC_RULE_AND_REPLACE_PACKET_FILTERS, models.RuleOperation_MODIFY_PCC_RULE_AND_DELETE_PACKET_FILTERS, models.RuleOperation_MODIFY_PCC_RULE_WITHOUT_MODIFY_PACKET_FILTERS: - if req.PccRuleId == "" || (req.RuleOp != models.RuleOperation_MODIFY_PCC_RULE_WITHOUT_MODIFY_PACKET_FILTERS && len(req.PackFiltInfo) < 1) { + if req.PccRuleId == "" || + (req.RuleOp != models.RuleOperation_MODIFY_PCC_RULE_WITHOUT_MODIFY_PACKET_FILTERS && + len(req.PackFiltInfo) < 1) { errCause = "Parameter Erroneous/Missing in Modify Pcc Rule" break } @@ -313,19 +418,20 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic if err != nil { smPolicy.RemainGbrDL = origDl smPolicy.RemainGbrUL = origUl - rsp := util.GetProblemDetail(err.Error(), util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) - logger.SMpolicylog.Warnf(rsp.Detail) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + problemDetail := util.GetProblemDetail(err.Error(), util.ERROR_TRAFFIC_MAPPING_INFO_REJECTED) + logger.SMpolicylog.Warnf(problemDetail.Detail) + return nil, &problemDetail } qosData.Var5qi = req.ReqQos.Var5qi qosData.GbrDl = gbrDl qosData.GbrUl = gbrUl if qosData.GbrDl != "" { - logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then DL GBR remain[%.2f Kbps]", smPolicyContext.Dnn, qosData.GbrDl, *smPolicy.RemainGbrDL) + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then DL GBR remain[%.2f Kbps]", + smPolicyContext.Dnn, qosData.GbrDl, *smPolicy.RemainGbrDL) } if qosData.GbrUl != "" { - logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then UL GBR remain[%.2f Kbps]", smPolicyContext.Dnn, qosData.GbrUl, *smPolicy.RemainGbrUL) + logger.SMpolicylog.Tracef("SM Policy Dnn[%s] Data Aggregate decrease %s and then UL GBR remain[%.2f Kbps]", + smPolicyContext.Dnn, qosData.GbrUl, *smPolicy.RemainGbrUL) } smPolicyDecision.QosDecs[qosId] = qosData } else { @@ -381,10 +487,10 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic errCause = "Access Type is empty in Trigger AC_TY_CH" break } - if request.AccessType == models.AccessType__3_GPP_ACCESS && smPolicyContext.Var3gppPsDataOffStatus { - // TODO: Handle Data off Status - // Block Session Service except for Exempt Serice which is described in TS22011, TS 23221 - } + // if request.AccessType == models.AccessType__3_GPP_ACCESS && smPolicyContext.Var3gppPsDataOffStatus { + // TODO: Handle Data off Status + // Block Session Service except for Exempt Serice which is described in TS22011, TS 23221 + // } smPolicyContext.AccessType = request.AccessType afEventsNotification.AccessType = request.AccessType if request.RatType != "" { @@ -412,8 +518,9 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic } logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) case models.PolicyControlRequestTrigger_UE_MAC_CH: // SMF notice PCF when SMF detect new UE MAC - case models.PolicyControlRequestTrigger_AN_CH_COR: // Access Network Charging Correlation Info (subsclause 4.2.6.5.1, 4.2.4.13 in TS29512) - // request.AccNetChIds + case models.PolicyControlRequestTrigger_AN_CH_COR: + // Access Network Charging Correlation Info (subsclause 4.2.6.5.1, 4.2.4.13 in TS29512) + // request.AccNetChIds case models.PolicyControlRequestTrigger_US_RE: // UMC (subsclause 4.2.4.10, 5.8 in TS29512) afNotif := models.AfEventNotification{ Event: models.AfEvent_USAGE_REPORT, @@ -426,17 +533,19 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic case models.PolicyControlRequestTrigger_AN_INFO: // NetLoc (subsclause 4.2.4.9, 5.8 in TS29512) case models.PolicyControlRequestTrigger_CM_SES_FAIL: // Credit Management Session Failure // request.CreditManageStatus - case models.PolicyControlRequestTrigger_PS_DA_OFF: // 3GPP PS Data Off status changed (subsclause 4.2.4.8, 5.8 in TS29512) (always) + case models.PolicyControlRequestTrigger_PS_DA_OFF: + // 3GPP PS Data Off status changed (subsclause 4.2.4.8, 5.8 in TS29512) (always) if smPolicyContext.Var3gppPsDataOffStatus != request.Var3gppPsDataOffStatus { // TODO: Handle Data off Status - if request.Var3gppPsDataOffStatus { - // Block Session Service except for Exempt Serice which is described in TS22011, TS 23221 - } else { - // UnBlock Session Sevice - } + // if request.Var3gppPsDataOffStatus { + // Block Session Service except for Exempt Serice which is described in TS22011, TS 23221 + // } else { + // UnBlock Session Sevice + // } smPolicyContext.Var3gppPsDataOffStatus = request.Var3gppPsDataOffStatus } - case models.PolicyControlRequestTrigger_DEF_QOS_CH: // Default QoS Change (subsclause 4.2.4.5 in TS29512) (always) + case models.PolicyControlRequestTrigger_DEF_QOS_CH: + // Default QoS Change (subsclause 4.2.4.5 in TS29512) (always) if request.SubsDefQos == nil { errCause = "SubsDefQos is nil in Trigger DEF_QOS_CH" break @@ -467,7 +576,8 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic } *smPolicyDecision.SessRules[sessRuleId].AuthSessAmbr = *request.SubsSessAmbr logger.SMpolicylog.Tracef("SM Policy Update(%s) Successfully", trigger) - case models.PolicyControlRequestTrigger_QOS_NOTIF: // SMF notify PCF when receiving from RAN that QoS can/can't be guaranteed (subsclause 4.2.4.20 in TS29512) (always) + case models.PolicyControlRequestTrigger_QOS_NOTIF: + // SMF notify PCF when receiving from RAN that QoS can/can't be guaranteed (subsclause 4.2.4.20 in TS29512) (always) // request.QncReports afNotif := models.AfEventNotification{ Event: models.AfEvent_QOS_NOTIF, @@ -499,8 +609,10 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic // if err == nil { // smPolicyDecision.RevalidationTime = &formatTime // } - case models.PolicyControlRequestTrigger_RES_RELEASE: // Outcome of request Pcc rule removal (subsclause 4.2.6.5.2, 5.8 in TS29512) - case models.PolicyControlRequestTrigger_SUCC_RES_ALLO: // Successful resource allocation (subsclause 4.2.6.5.5, 4.2.4.14 in TS29512) + case models.PolicyControlRequestTrigger_RES_RELEASE: + // Outcome of request Pcc rule removal (subsclause 4.2.6.5.2, 5.8 in TS29512) + case models.PolicyControlRequestTrigger_SUCC_RES_ALLO: + // Successful resource allocation (subsclause 4.2.6.5.5, 4.2.4.14 in TS29512) afNotif := models.AfEventNotification{ Event: models.AfEvent_SUCCESSFUL_RESOURCES_ALLOCATION, } @@ -538,7 +650,8 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic // release fail pccRules in SmPolicy for _, pccRuleId := range rule.PccRuleIds { if err := smPolicy.RemovePccRule(pccRuleId); err != nil { - logger.SMpolicylog.Warnf("SM Policy Notification about failed installing PccRule[%s]", err.Error()) + logger.SMpolicylog.Warnf( + "SM Policy Notification about failed installing PccRule[%s]", err.Error()) } } } @@ -550,24 +663,28 @@ func UpdateSmPolicyContext(httpChannel chan message.HttpResponseMessage, smPolic afEventsNotification.EvNotifs = append(afEventsNotification.EvNotifs, afNotif) } if afEventsNotification.EvNotifs != nil { - sendSmPolicyRelatedAppSessionNotification(smPolicy, afEventsNotification, request.AccuUsageReports, successRules, failRules) + sendSmPolicyRelatedAppSessionNotification( + smPolicy, afEventsNotification, request.AccuUsageReports, successRules, failRules) } if errCause != "" { - rsp := util.GetProblemDetail(errCause, util.ERROR_TRIGGER_EVENT) + problemDetail := util.GetProblemDetail(errCause, util.ERROR_TRIGGER_EVENT) logger.SMpolicylog.Warnf(errCause) - message.SendHttpResponseMessage(httpChannel, nil, int(rsp.Status), rsp) - return + return nil, &problemDetail } - logger.SMpolicylog.Tracef("SMPolicy SmPolicyId[%s] Update", smPolicyId) - message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *smPolicyDecision) + logger.SMpolicylog.Tracef("SMPolicy smPolicyID[%s] Update", smPolicyID) + //message.SendHttpResponseMessage(httpChannel, nil, http.StatusOK, *smPolicyDecision) + return smPolicyDecision, nil } -func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyData, notification models.EventsNotification, usageReports []models.AccuUsageReport, successRules, failRules []models.RuleReport) { +func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyData, + notification models.EventsNotification, usageReports []models.AccuUsageReport, + successRules, failRules []models.RuleReport) { for appSessionId := range smPolicy.AppSessions { - if appSession, exist := pcf_context.PCF_Self().AppSessionPool[appSessionId]; exist { + if val, exist := pcf_context.PCF_Self().AppSessionPool.Load(appSessionId); exist { + appSession := val.(*pcf_context.AppSessionData) if len(appSession.Events) == 0 { continue } @@ -588,7 +705,10 @@ func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyD if key, exist := appSession.PccRuleIdMapToCompId[pccRuleId]; exist { items := strings.Split(key, "-") if items[0] != "appId" { - compN, _ := strconv.Atoi(items[0]) + compN, err := strconv.Atoi(items[0]) + if err != nil { + logger.SMpolicylog.Errorf("strconv Atoi error %+v", err) + } compN32 := int32(compN) if len(items) == 1 { // Comp @@ -598,7 +718,10 @@ func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyD failItem.Flows = append(failItem.Flows, flow) } else if len(items) == 2 { // have subComp - fNum, _ := strconv.Atoi(items[1]) + fNum, err := strconv.Atoi(items[1]) + if err != nil { + logger.SMpolicylog.Errorf("strconv Atoi error %+v", err) + } fNum32 := int32(fNum) flow, exist := flows[compN32] @@ -623,7 +746,8 @@ func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyD failItem.Flows = append(failItem.Flows, flow) } if failItem.Flows != nil { - sessionNotif.FailedResourcAllocReports = append(sessionNotif.FailedResourcAllocReports, failItem) + sessionNotif.FailedResourcAllocReports = + append(sessionNotif.FailedResourcAllocReports, failItem) } else { continue } @@ -652,7 +776,10 @@ func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyD if key, exist := appSession.PccRuleIdMapToCompId[pccRuleId]; exist { items := strings.Split(key, "-") if items[0] != "appId" { - compN, _ := strconv.Atoi(items[0]) + compN, err := strconv.Atoi(items[0]) + if err != nil { + logger.SMpolicylog.Errorf("strconv Atoi error %+v", err) + } compN32 := int32(compN) if len(items) == 1 { // Comp @@ -662,7 +789,10 @@ func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyD notif.Flows = append(notif.Flows, flow) } else if len(items) == 2 { // have subComp - fNum, _ := strconv.Atoi(items[1]) + fNum, err := strconv.Atoi(items[1]) + if err != nil { + logger.SMpolicylog.Errorf("strconv Atoi error %+v", err) + } fNum32 := int32(fNum) flow, exist := flows[compN32] if !exist { @@ -689,7 +819,8 @@ func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyD case models.AfEvent_USAGE_REPORT: for _, report := range usageReports { for _, pccRuleId := range appSession.RelatedPccRuleIds { - if pccRule, exist := appSession.SmPolicyData.PolicyDecision.PccRules[pccRuleId]; exist { + if pccRule, exist := + appSession.SmPolicyData.PolicyDecision.PccRules[pccRuleId]; exist { if pccRule.RefUmData != nil && pccRule.RefUmData[0] == report.RefUmIds { sessionNotif.UsgRep = &models.AccumulatedUsage{ Duration: report.TimeUsage, @@ -721,21 +852,24 @@ func sendSmPolicyRelatedAppSessionNotification(smPolicy *pcf_context.UeSmPolicyD } } -func SendSMPolicyUpdateNotification(ue *pcf_context.UeContext, smPolId string, request models.SmPolicyNotification) { - logger.SMpolicylog.Tracef("Send SM Policy Update Notification") +func SendSMPolicyUpdateNotification( + ue *pcf_context.UeContext, smPolId string, request models.SmPolicyNotification) { if ue == nil { logger.SMpolicylog.Warnln("SM Policy Update Notification Error[Ue is nil]") return } smPolicyData := ue.SmPolicyData[smPolId] if smPolicyData == nil || smPolicyData.PolicyContext == nil { - logger.SMpolicylog.Warnf("SM Policy Update Notification Error[Can't find smPolId[%s] in UE(%s)]", smPolId, ue.Supi) + logger.SMpolicylog.Warnf( + "SM Policy Update Notification Error[Can't find smPolId[%s] in UE(%s)]", smPolId, ue.Supi) return } client := util.GetNpcfSMPolicyCallbackClient() uri := smPolicyData.PolicyContext.NotificationUri if uri != "" { - _, httpResponse, err := client.DefaultCallbackApi.SmPolicyUpdateNotification(context.Background(), uri, request) + logger.SMpolicylog.Infof("Send SM Policy Update Notification to SMF") + _, httpResponse, err := + client.DefaultCallbackApi.SmPolicyUpdateNotification(context.Background(), uri, request) if err != nil { if httpResponse != nil { logger.SMpolicylog.Warnf("SM Policy Update Notification Error[%s]", httpResponse.Status) @@ -756,7 +890,8 @@ func SendSMPolicyUpdateNotification(ue *pcf_context.UeContext, smPolId string, r } -func SendSMPolicyTerminationRequestNotification(ue *pcf_context.UeContext, smPolId string, request models.TerminationNotification) { +func SendSMPolicyTerminationRequestNotification( + ue *pcf_context.UeContext, smPolId string, request models.TerminationNotification) { logger.SMpolicylog.Tracef("Send SM Policy Termination Request Notification") if ue == nil { logger.SMpolicylog.Warnln("SM Policy Termination Request Notification Error[Ue is nil]") @@ -764,13 +899,15 @@ func SendSMPolicyTerminationRequestNotification(ue *pcf_context.UeContext, smPol } smPolicyData := ue.SmPolicyData[smPolId] if smPolicyData == nil || smPolicyData.PolicyContext == nil { - logger.SMpolicylog.Warnf("SM Policy Update Notification Error[Can't find smPolId[%s] in UE(%s)]", smPolId, ue.Supi) + logger.SMpolicylog.Warnf( + "SM Policy Update Notification Error[Can't find smPolId[%s] in UE(%s)]", smPolId, ue.Supi) return } client := util.GetNpcfSMPolicyCallbackClient() uri := smPolicyData.PolicyContext.NotificationUri if uri != "" { - rsp, err := client.DefaultCallbackApi.SmPolicyControlTerminationRequestNotification(context.Background(), uri, request) + rsp, err := + client.DefaultCallbackApi.SmPolicyControlTerminationRequestNotification(context.Background(), uri, request) if err != nil { if rsp != nil { logger.AMpolicylog.Warnf("SM Policy Termination Request Notification Error[%s]", rsp.Status) diff --git a/service/init.go b/service/init.go index 1854fc6..60071a8 100644 --- a/service/init.go +++ b/service/init.go @@ -3,7 +3,16 @@ package service import ( "bufio" "fmt" + "os/exec" + "sync" + + "github.com/antihax/optional" + "github.com/gin-contrib/cors" + "github.com/sirupsen/logrus" + "github.com/urfave/cli" + "free5gc/lib/http2_util" + "free5gc/lib/logger_util" "free5gc/lib/openapi/Nnrf_NFDiscovery" "free5gc/lib/openapi/models" "free5gc/lib/path_util" @@ -12,7 +21,7 @@ import ( "free5gc/src/pcf/bdtpolicy" "free5gc/src/pcf/consumer" "free5gc/src/pcf/context" - "free5gc/src/pcf/handler" + "free5gc/src/pcf/factory" "free5gc/src/pcf/httpcallback" "free5gc/src/pcf/logger" "free5gc/src/pcf/oam" @@ -20,17 +29,6 @@ import ( "free5gc/src/pcf/smpolicy" "free5gc/src/pcf/uepolicy" "free5gc/src/pcf/util" - "os/exec" - "sync" - - "github.com/gin-contrib/cors" - - "free5gc/src/pcf/factory" - - "github.com/antihax/optional" - "github.com/gin-gonic/gin" - "github.com/sirupsen/logrus" - "github.com/urfave/cli" ) type PCF struct{} @@ -109,7 +107,7 @@ func (pcf *PCF) FilterCli(c *cli.Context) (args []string) { func (pcf *PCF) Start() { initLog.Infoln("Server started") - router := gin.Default() + router := logger_util.NewGinWithLogrus(logger.GinLog) bdtpolicy.AddService(router) smpolicy.AddService(router) @@ -120,8 +118,9 @@ func (pcf *PCF) Start() { oam.AddService(router) router.Use(cors.New(cors.Config{ - AllowMethods: []string{"GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE"}, - AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "User-Agent", "Referrer", "Host", "Token", "X-Requested-With"}, + AllowMethods: []string{"GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE"}, + AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "User-Agent", + "Referrer", "Host", "Token", "X-Requested-With"}, ExposeHeaders: []string{"Content-Length"}, AllowCredentials: true, AllowAllOrigins: true, @@ -131,7 +130,7 @@ func (pcf *PCF) Start() { self := context.PCF_Self() util.InitpcfContext(self) - addr := fmt.Sprintf("%s:%d", self.BindingIPv4, self.HttpIpv4Port) + addr := fmt.Sprintf("%s:%d", self.BindingIPv4, self.SBIPort) profile, err := consumer.BuildNFInstance(self) if err != nil { @@ -149,7 +148,8 @@ func (pcf *PCF) Start() { if len(guamiList) == 0 { continue } - problemDetails, err := consumer.AmfStatusChangeSubscribe(amfInfo) + var problemDetails *models.ProblemDetails + problemDetails, err = consumer.AmfStatusChangeSubscribe(amfInfo) if problemDetails != nil { logger.InitLog.Warnf("AMF status subscribe Failed[%+v]", problemDetails) } else if err != nil { @@ -159,7 +159,6 @@ func (pcf *PCF) Start() { // TODO: subscribe NRF NFstatus - go handler.Handle() param := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ ServiceNames: optional.NewInterface([]models.ServiceName{models.ServiceName_NUDR_DR}), } @@ -167,7 +166,7 @@ func (pcf *PCF) Start() { for _, nfProfile := range resp.NfInstances { udruri := util.SearchNFServiceUri(nfProfile, models.ServiceName_NUDR_DR, models.NfServiceStatus_REGISTERED) if udruri != "" { - self.DefaultUdrUri = udruri + self.SetDefaultUdrURI(udruri) break } } @@ -176,12 +175,12 @@ func (pcf *PCF) Start() { } server, err := http2_util.NewServer(addr, util.PCF_LOG_PATH, router) if server == nil { - initLog.Errorln("Initialize HTTP server failed: %+v", err) + initLog.Errorf("Initialize HTTP server failed: %+v", err) return } if err != nil { - initLog.Warnln("Initialize HTTP server: +%v", err) + initLog.Warnf("Initialize HTTP server: +%v", err) } serverScheme := factory.PcfConfig.Configuration.Sbi.Scheme @@ -192,7 +191,7 @@ func (pcf *PCF) Start() { } if err != nil { - initLog.Fatalln("HTTP server setup failed: %+v", err) + initLog.Fatalf("HTTP server setup failed: %+v", err) } } @@ -231,7 +230,7 @@ func (pcf *PCF) Exec(c *cli.Context) error { go func() { fmt.Println("PCF start") - if err := command.Start(); err != nil { + if err = command.Start(); err != nil { fmt.Printf("command.Start() error: %v", err) } fmt.Println("PCF end") diff --git a/smpolicy/api_default.go b/smpolicy/api_default.go index abe0b2f..37cd08d 100644 --- a/smpolicy/api_default.go +++ b/smpolicy/api_default.go @@ -11,78 +11,155 @@ package smpolicy import ( "free5gc/lib/http_wrapper" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" - "free5gc/src/pcf/handler/message" "free5gc/src/pcf/logger" - "free5gc/src/pcf/util" - + "free5gc/src/pcf/producer" "github.com/gin-gonic/gin" + "net/http" ) // SmPoliciesPost - -func SmPoliciesPost(c *gin.Context) { +func HTTPSmPoliciesPost(c *gin.Context) { var smPolicyContextData models.SmPolicyContextData - err := c.ShouldBindJSON(&smPolicyContextData) + // step 1: retrieve http request body + requestBody, err := c.GetRawData() if err != nil { - rsp := util.GetProblemDetail("Malformed request syntax", util.ERROR_INITIAL_PARAMETERS) - logger.HandlerLog.Errorln(rsp.Detail) - c.JSON(int(rsp.Status), rsp) + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.SMpolicylog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) return } - if smPolicyContextData.Supi == "" || smPolicyContextData.SliceInfo == nil || len(smPolicyContextData.SliceInfo.Sd) != 6 { - rsp := util.GetProblemDetail("Errorneous/Missing Mandotory IE", util.ERROR_INITIAL_PARAMETERS) - logger.HandlerLog.Errorln(rsp.Detail) - c.JSON(int(rsp.Status), rsp) + + // step 2: convert requestBody to openapi models + err = openapi.Deserialize(&smPolicyContextData, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.SMpolicylog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) return } req := http_wrapper.NewRequest(c.Request, smPolicyContextData) - channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyCreate, req) + rsp := producer.HandleCreateSmPolicyRequest(req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - - for key, val := range HTTPResponse.Header { + // step 5: response + for key, val := range rsp.Header { // header response is optional c.Header(key, val[0]) } - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.SMpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } // SmPoliciesSmPolicyIdDeletePost - -func SmPoliciesSmPolicyIdDeletePost(c *gin.Context) { +func HTTPSmPoliciesSmPolicyIdDeletePost(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["smPolicyId"] = c.Params.ByName("smPolicyId") - channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyDelete, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + + rsp := producer.HandleDeleteSmPolicyContextRequest(req) + + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.SMpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } // SmPoliciesSmPolicyIdGet - -func SmPoliciesSmPolicyIdGet(c *gin.Context) { +func HTTPSmPoliciesSmPolicyIDGet(c *gin.Context) { req := http_wrapper.NewRequest(c.Request, nil) req.Params["smPolicyId"] = c.Params.ByName("smPolicyId") - channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyGet, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleGetSmPolicyContextRequest(req) + + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.SMpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } // SmPoliciesSmPolicyIdUpdatePost - -func SmPoliciesSmPolicyIdUpdatePost(c *gin.Context) { +func HTTPSmPoliciesSmPolicyIdUpdatePost(c *gin.Context) { var smPolicyUpdateContextData models.SmPolicyUpdateContextData - c.ShouldBindJSON(&smPolicyUpdateContextData) + // step 1: retrieve http request body + requestBody, err := c.GetRawData() + if err != nil { + problemDetail := models.ProblemDetails{ + Title: "System failure", + Status: http.StatusInternalServerError, + Detail: err.Error(), + Cause: "SYSTEM_FAILURE", + } + logger.SMpolicylog.Errorf("Get Request Body error: %+v", err) + c.JSON(http.StatusInternalServerError, problemDetail) + return + } + + // step 2: convert requestBody to openapi models + err = openapi.Deserialize(&smPolicyUpdateContextData, requestBody, "application/json") + if err != nil { + problemDetail := "[Request Body] " + err.Error() + rsp := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: problemDetail, + } + logger.SMpolicylog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, rsp) + return + } + req := http_wrapper.NewRequest(c.Request, smPolicyUpdateContextData) req.Params["smPolicyId"] = c.Params.ByName("smPolicyId") - channelMsg := message.NewHttpChannelMessage(message.EventSMPolicyUpdate, req) - message.SendMessage(channelMsg) - recvMsg := <-channelMsg.HttpChannel - HTTPResponse := recvMsg.HTTPResponse - c.JSON(HTTPResponse.Status, HTTPResponse.Body) + rsp := producer.HandleUpdateSmPolicyContextRequest(req) + + responseBody, err := openapi.Serialize(rsp.Body, "application/json") + if err != nil { + logger.SMpolicylog.Errorln(err) + problemDetails := models.ProblemDetails{ + Status: http.StatusInternalServerError, + Cause: "SYSTEM_FAILURE", + Detail: err.Error(), + } + c.JSON(http.StatusInternalServerError, problemDetails) + } else { + c.Data(rsp.Status, "application/json", responseBody) + } } diff --git a/smpolicy/routers.go b/smpolicy/routers.go index 075142c..759442c 100644 --- a/smpolicy/routers.go +++ b/smpolicy/routers.go @@ -10,6 +10,8 @@ package smpolicy import ( + "free5gc/lib/logger_util" + "free5gc/src/pcf/logger" "net/http" "strings" @@ -33,7 +35,7 @@ type Routes []Route // NewRouter returns a new router. func NewRouter() *gin.Engine { - router := gin.Default() + router := logger_util.NewGinWithLogrus(logger.GinLog) AddService(router) return router } @@ -75,27 +77,27 @@ var routes = Routes{ "SmPoliciesPost", strings.ToUpper("Post"), "/sm-policies", - SmPoliciesPost, + HTTPSmPoliciesPost, }, { "SmPoliciesSmPolicyIdDeletePost", strings.ToUpper("Post"), "/sm-policies/:smPolicyId/delete", - SmPoliciesSmPolicyIdDeletePost, + HTTPSmPoliciesSmPolicyIdDeletePost, }, { "SmPoliciesSmPolicyIdGet", strings.ToUpper("Get"), "/sm-policies/:smPolicyId", - SmPoliciesSmPolicyIdGet, + HTTPSmPoliciesSmPolicyIDGet, }, { "SmPoliciesSmPolicyIdUpdatePost", strings.ToUpper("Post"), "/sm-policies/:smPolicyId/update", - SmPoliciesSmPolicyIdUpdatePost, + HTTPSmPoliciesSmPolicyIdUpdatePost, }, } diff --git a/uepolicy/routers.go b/uepolicy/routers.go index 866c88b..109732e 100644 --- a/uepolicy/routers.go +++ b/uepolicy/routers.go @@ -10,6 +10,8 @@ package uepolicy import ( + "free5gc/lib/logger_util" + "free5gc/src/pcf/logger" "net/http" "strings" @@ -30,7 +32,7 @@ type Route struct { type Routes []Route func NewRouter() *gin.Engine { - router := gin.Default() + router := logger_util.NewGinWithLogrus(logger.GinLog) AddService(router) return router } diff --git a/util/convert.go b/util/convert.go index dc3fd67..3b29212 100644 --- a/util/convert.go +++ b/util/convert.go @@ -48,7 +48,8 @@ func SnssaiModelsToHex(snssai models.Snssai) string { return sst + snssai.Sd } -// Use BitMap to generate requested policy control triggers, 1 means yes, 0 means no, see subscaulse 5.6.3.6-1 in TS29512 +// Use BitMap to generate requested policy control triggers, +// 1 means yes, 0 means no, see subscaulse 5.6.3.6-1 in TS29512 func PolicyControlReqTrigToArray(bitMap uint64) (trigger []models.PolicyControlRequestTrigger) { cnt := 0 size := len(policyTriggerArray) diff --git a/util/init_context.go b/util/init_context.go index bf617ff..5b1b2da 100644 --- a/util/init_context.go +++ b/util/init_context.go @@ -1,14 +1,15 @@ package util import ( + "os" + + "github.com/google/uuid" + "free5gc/lib/openapi" "free5gc/lib/openapi/models" "free5gc/src/pcf/context" "free5gc/src/pcf/factory" "free5gc/src/pcf/logger" - "os" - - "github.com/google/uuid" ) // Init PCF Context from config flie @@ -22,28 +23,32 @@ func InitpcfContext(context *context.PCFContext) { } sbi := configuration.Sbi context.NrfUri = configuration.NrfUri - context.UriScheme = models.UriScheme(sbi.Scheme) - context.HttpIPv4Address = "127.0.0.1" // default localhost - context.HttpIpv4Port = 29507 // default port + context.UriScheme = "" + context.RegisterIPv4 = "127.0.0.1" // default localhost + context.SBIPort = 29507 // default port if sbi != nil { + if sbi.Scheme != "" { + context.UriScheme = models.UriScheme(sbi.Scheme) + } if sbi.RegisterIPv4 != "" { - context.HttpIPv4Address = sbi.RegisterIPv4 + context.RegisterIPv4 = sbi.RegisterIPv4 } if sbi.Port != 0 { - context.HttpIpv4Port = sbi.Port + context.SBIPort = sbi.Port } if sbi.Scheme == "https" { context.UriScheme = models.UriScheme_HTTPS } else { context.UriScheme = models.UriScheme_HTTP } + context.BindingIPv4 = os.Getenv(sbi.BindingIPv4) if context.BindingIPv4 != "" { logger.UtilLog.Info("Parsing ServerIPv4 address from ENV Variable.") } else { context.BindingIPv4 = sbi.BindingIPv4 if context.BindingIPv4 == "" { - logger.UtilLog.Info("Error parsing ServerIPv4 address as string. Using the 0.0.0.0 address as default.") + logger.UtilLog.Warn("Error parsing ServerIPv4 address as string. Using the 0.0.0.0 address as default.") context.BindingIPv4 = "0.0.0.0" } } @@ -53,7 +58,12 @@ func InitpcfContext(context *context.PCFContext) { context.TimeFormat = configuration.TimeFormat context.DefaultBdtRefId = configuration.DefaultBdtRefId for _, service := range context.NfService { - context.PcfServiceUris[service.ServiceName] = service.ApiPrefix + "/" + string(service.ServiceName) + "/" + (*service.Versions)[0].ApiVersionInUri - context.PcfSuppFeats[service.ServiceName], _ = openapi.NewSupportedFeature(service.SupportedFeatures) + var err error + context.PcfServiceUris[service.ServiceName] = + service.ApiPrefix + "/" + string(service.ServiceName) + "/" + (*service.Versions)[0].ApiVersionInUri + context.PcfSuppFeats[service.ServiceName], err = openapi.NewSupportedFeature(service.SupportedFeatures) + if err != nil { + logger.UtilLog.Errorf("openapi NewSupportedFeature error: %+v", err) + } } } diff --git a/util/pcc_rule.go b/util/pcc_rule.go index 2a16de0..823ca8e 100644 --- a/util/pcc_rule.go +++ b/util/pcc_rule.go @@ -36,7 +36,7 @@ func CreateDefalutPccRules(id int32) *models.PccRule { PackFiltId: "PackFiltId-1", }, } - return CreatePccRule(id, 10, flowInfo, true) + return CreatePccRule(id, 10, flowInfo, "", true) } // Get pcc rule Identity(PccRuleId-%d) @@ -74,9 +74,10 @@ func GetPackFiltId(id int32) string { return fmt.Sprintf("PackFiltId-%d", id) } -// Create Pcc Rule with param id, precedence, flow infomation, cond flag(included or not) -func CreatePccRule(id, precedence int32, flowInfo []models.FlowInformation, cond bool) *models.PccRule { +// Create Pcc Rule with param id, precedence, flow infomation, appId, cond flag(included or not) +func CreatePccRule(id, precedence int32, flowInfo []models.FlowInformation, appId string, cond bool) *models.PccRule { rule := models.PccRule{ + AppId: appId, FlowInfos: flowInfo, PccRuleId: GetPccRuleId(id), Precedence: precedence, @@ -149,17 +150,16 @@ func ConvertPacketInfoToFlowInformation(infos []models.PacketFilterInfo) (flowIn return } -func GetPccRuleByAfAppId(pccRules map[string]models.PccRule, afAppId string) (result *models.PccRule) { +func GetPccRuleByAfAppId(pccRules map[string]models.PccRule, afAppId string) *models.PccRule { for _, pccRule := range pccRules { if pccRule.AppId == afAppId { - result = &pccRule - return + return &pccRule } } - return + return nil } -func GetPccRuleByFlowInfos(pccRules map[string]models.PccRule, flowInfos []models.FlowInformation) (result *models.PccRule) { +func GetPccRuleByFlowInfos(pccRules map[string]models.PccRule, flowInfos []models.FlowInformation) *models.PccRule { found := false set := make(map[string]models.FlowInformation) @@ -176,14 +176,15 @@ func GetPccRuleByFlowInfos(pccRules map[string]models.PccRule, flowInfos []model } } if found { - result = &pccRule - return + return &pccRule } } - return + return nil } -func SetPccRuleRelatedData(decicion *models.SmPolicyDecision, pccRule *models.PccRule, tcData *models.TrafficControlData, qosData *models.QosData, chgData *models.ChargingData, umData *models.UsageMonitoringData) { +func SetPccRuleRelatedData(decicion *models.SmPolicyDecision, pccRule *models.PccRule, + tcData *models.TrafficControlData, qosData *models.QosData, chgData *models.ChargingData, + umData *models.UsageMonitoringData) { if tcData != nil { if decicion.TraffContDecs == nil { decicion.TraffContDecs = make(map[string]models.TrafficControlData) diff --git a/util/pcf_util.go b/util/pcf_util.go index a24682c..48fe250 100644 --- a/util/pcf_util.go +++ b/util/pcf_util.go @@ -12,6 +12,7 @@ import ( "free5gc/lib/openapi/models" "free5gc/lib/path_util" "free5gc/src/pcf/context" + "free5gc/src/pcf/logger" "net/http" "reflect" "time" @@ -97,7 +98,10 @@ func GetDefaultDataRate() models.UsageThreshold { func GetDefaultTime() models.TimeWindow { var timeWindow models.TimeWindow timeWindow.StartTime = time.Now().Format(time.RFC3339) - lease, _ := time.ParseDuration("720h") + lease, err := time.ParseDuration("720h") + if err != nil { + logger.UtilLog.Errorf("ParseDuration error: %+v", err) + } timeWindow.StopTime = time.Now().Add(lease).Format(time.RFC3339) return timeWindow } @@ -157,12 +161,18 @@ func MarshToJsonString(v interface{}) (result []string) { val := reflect.ValueOf(v) if types.Kind() == reflect.Slice { for i := 0; i < val.Len(); i++ { - tmp, _ := json.Marshal(val.Index(i).Interface()) + tmp, err := json.Marshal(val.Index(i).Interface()) + if err != nil { + logger.UtilLog.Errorf("Marshal error: %+v", err) + } result = append(result, string(tmp)) } } else { - tmp, _ := json.Marshal(v) + tmp, err := json.Marshal(v) + if err != nil { + logger.UtilLog.Errorf("Marshal error: %+v", err) + } result = append(result, string(tmp)) } return @@ -185,7 +195,10 @@ func GetNegotiateSuppFeat(suppFeat string, serviceSuppFeat []byte) string { if serviceSuppFeat == nil { return "" } - bytes, _ := hex.DecodeString(suppFeat) + bytes, err := hex.DecodeString(suppFeat) + if err != nil { + logger.UtilLog.Errorf("DecodeString error: %+v", err) + } negoSuppFeat := AndBytes(bytes, serviceSuppFeat) return hex.EncodeToString(negoSuppFeat) } @@ -219,7 +232,8 @@ func CheckSuppFeat(suppFeat string, number int) bool { return false } -func CheckPolicyControlReqTrig(triggers []models.PolicyControlRequestTrigger, reqTrigger models.PolicyControlRequestTrigger) bool { +func CheckPolicyControlReqTrig( + triggers []models.PolicyControlRequestTrigger, reqTrigger models.PolicyControlRequestTrigger) bool { for _, trigger := range triggers { if trigger == reqTrigger { return true diff --git a/util/search_nf_service.go b/util/search_nf_service.go index aa00b73..87b1313 100644 --- a/util/search_nf_service.go +++ b/util/search_nf_service.go @@ -6,7 +6,8 @@ import ( ) // SearchNFServiceUri returns NF Uri derived from NfProfile with corresponding service -func SearchNFServiceUri(nfProfile models.NfProfile, serviceName models.ServiceName, nfServiceStatus models.NfServiceStatus) (nfUri string) { +func SearchNFServiceUri(nfProfile models.NfProfile, serviceName models.ServiceName, + nfServiceStatus models.NfServiceStatus) (nfUri string) { if nfProfile.NfServices != nil { for _, service := range *nfProfile.NfServices { diff --git a/version/version.go b/version/version.go index f89f034..812bed1 100644 --- a/version/version.go +++ b/version/version.go @@ -1,7 +1,35 @@ package version -var VERSION = "2020-03-31-01" +import ( + "fmt" + "runtime" +) + +var ( + VERSION string + BUILD_TIME string + COMMIT_HASH string + COMMIT_TIME string +) func GetVersion() (version string) { - return VERSION + if VERSION != "" { + return fmt.Sprintf( + "\n\tversion: %s\n\tbuild time: %s\n\tcommit hash: %s\n\tcommit time: %s\n\tgo version: %s %s/%s", + VERSION, + BUILD_TIME, + COMMIT_HASH, + COMMIT_TIME, + runtime.Version(), + runtime.GOOS, + runtime.GOARCH, + ) + } else { + return fmt.Sprintf( + "\n\tNot specify ldflags (which link version) during go build\n\tgo version: %s %s/%s", + runtime.Version(), + runtime.GOOS, + runtime.GOARCH, + ) + } } diff --git a/version/version_test.go b/version/version_test.go new file mode 100644 index 0000000..fbc6fd4 --- /dev/null +++ b/version/version_test.go @@ -0,0 +1,47 @@ +package version_test + +import ( + "fmt" + "free5gc/src/pcf/version" + "os/exec" + "runtime" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestVersion(t *testing.T) { + t.Run("VERSION not specified", func(t *testing.T) { + var expected = fmt.Sprintf( + "\n\tNot specify ldflags (which link version) during go build\n\tgo version: %s %s/%s", + runtime.Version(), + runtime.GOOS, + runtime.GOARCH) + assert.Equal(t, expected, version.GetVersion()) + }) + + t.Run("VERSION specified", func(t *testing.T) { + var stdout []byte + stdout, _ = exec.Command("bash", "-c", "cd ../../.. && git describe --tags").Output() + version.VERSION = strings.TrimSuffix(string(stdout), "\n") + stdout, _ = exec.Command("bash", "-c", "date -u +\"%Y-%m-%dT%H:%M:%SZ\"").Output() + version.BUILD_TIME = strings.TrimSuffix(string(stdout), "\n") + stdout, _ = exec.Command("bash", "-c", "git log --pretty=\"%H\" -1 | cut -c1-8").Output() + version.COMMIT_HASH = strings.TrimSuffix(string(stdout), "\n") + stdout, _ = exec.Command("bash", "-c", "git log --pretty=\"%ai\" -1 | awk '{time=$1\"T\"$2\"Z\"; print time}'").Output() + version.COMMIT_TIME = strings.TrimSuffix(string(stdout), "\n") + + var expected = fmt.Sprintf( + "\n\tversion: %s\n\tbuild time: %s\n\tcommit hash: %s\n\tcommit time: %s\n\tgo version: %s %s/%s", + version.VERSION, + version.BUILD_TIME, + version.COMMIT_HASH, + version.COMMIT_TIME, + runtime.Version(), + runtime.GOOS, + runtime.GOARCH) + + assert.Equal(t, expected, version.GetVersion()) + }) +} From 8151d108639fec7d1885be22242227eca4b1f715 Mon Sep 17 00:00:00 2001 From: calee_cs Date: Tue, 24 Nov 2020 20:32:59 +0800 Subject: [PATCH 7/7] Add Apache-2.0 license file --- LICENSE.txt | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..4124f39 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2019 Communication Service/Software Laboratory, National Chiao Tung University + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file