diff --git a/go.mod b/go.mod index 659c5c7f..581f6053 100644 --- a/go.mod +++ b/go.mod @@ -3,25 +3,23 @@ module github.com/free5gc/smf go 1.21 require ( - github.com/antihax/optional v1.0.0 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/davecgh/go-spew v1.1.1 github.com/free5gc/aper v1.0.5 - github.com/free5gc/nas v1.1.3 + github.com/free5gc/nas v1.1.4-0.20240801045646-998afcbf3811 github.com/free5gc/ngap v1.0.8 - github.com/free5gc/openapi v1.0.8 + github.com/free5gc/openapi v1.0.9-0.20241112160830-092c679ef6cd github.com/free5gc/pfcp v1.0.7 github.com/free5gc/util v1.0.6 github.com/gin-gonic/gin v1.9.1 github.com/google/uuid v1.3.0 - github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 + github.com/h2non/gock v1.2.0 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.8.1 + github.com/sirupsen/logrus v1.9.3 github.com/smartystreets/goconvey v1.6.4 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 github.com/urfave/cli v1.22.5 go.uber.org/mock v0.4.0 - gopkg.in/h2non/gock.v1 v1.1.2 gopkg.in/yaml.v2 v2.4.0 ) @@ -30,16 +28,18 @@ require ( github.com/bytedance/sonic v1.9.1 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/free5gc/tlv v1.0.2 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/protobuf v1.5.0 // indirect - github.com/google/go-cmp v0.6.0 // indirect github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -60,6 +60,11 @@ require ( github.com/tim-ywliu/nested-logrus-formatter v1.3.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect golang.org/x/arch v0.3.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/net v0.23.0 // indirect diff --git a/go.sum b/go.sum index b05b6d44..12ed5cea 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ= github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= @@ -61,14 +59,16 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/free5gc/aper v1.0.5 h1:sUYFFmOXDLjyL4rU6zFnq81M4YluqP90Pso5e/J4UhA= github.com/free5gc/aper v1.0.5/go.mod h1:ybHxhYnRqQ9wD4yB9r/3MZdbCYCjtqUyfLpSnJpwWd4= -github.com/free5gc/nas v1.1.3 h1:eYkvT8GGieD06MExw3JLeIPA88Yg89DFjptVBnadIyQ= -github.com/free5gc/nas v1.1.3/go.mod h1:PMyj7SQ6+JWHie/ESmy6pZJrYMlqNxowAgCnrZNyvoI= +github.com/free5gc/nas v1.1.4-0.20240801045646-998afcbf3811 h1:S/4FPVGQm4xYNxRLd487hOfz/f7S5taPFO8MFLqjADo= +github.com/free5gc/nas v1.1.4-0.20240801045646-998afcbf3811/go.mod h1:mVpI5guYTI24b9/cqnzilfHZa5nQeiLAh39/pVz9WrI= github.com/free5gc/ngap v1.0.8 h1:ffzSJW26qbZolwbL8yIjrCoEn7PUc/VE91f/zjJIFMs= github.com/free5gc/ngap v1.0.8/go.mod h1:d5u7tYsBwxmLr3zw7wyBruRjc/gbdsHVhmdGFnVmfBU= -github.com/free5gc/openapi v1.0.8 h1:QjfQdB6VVA1GRnzOJ7nILzrI7gMiY0lH64JHVW7vF34= -github.com/free5gc/openapi v1.0.8/go.mod h1:w6y9P/uySczc1d9OJZAEuB2FImR/z60Wg2BekPAVt3M= +github.com/free5gc/openapi v1.0.9-0.20241112160830-092c679ef6cd h1:VRxE3QzfL1uU8ZnR9Y1aXtslHPeMIVoHb3wU0yOz2AI= +github.com/free5gc/openapi v1.0.9-0.20241112160830-092c679ef6cd/go.mod h1:aKw6uGzEibGDrn9++w4/JpWxaaUBo7GaqsvuFKU9fl4= github.com/free5gc/pfcp v1.0.7 h1:20/4PGok8Ihy+NfYQzic39zVq3ZB4/gdZhDO1676TMQ= github.com/free5gc/pfcp v1.0.7/go.mod h1:57l3+7h2o1Sg8vbgl0kflROwuEQltx2VbULLrV9F1Ts= github.com/free5gc/tlv v1.0.2 h1:gb7PRbJFrYXlbqIKk0t3XuxJNecc4A7X2Y+CXS/FzEM= @@ -84,6 +84,11 @@ github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SU github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -94,8 +99,8 @@ github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -151,6 +156,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE= +github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -185,8 +192,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= @@ -205,8 +210,8 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= @@ -214,7 +219,6 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -222,8 +226,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tim-ywliu/nested-logrus-formatter v1.3.2 h1:jugNJ2/CNCI79SxOJCOhwUHeN3O7/7/bj+ZRGOFlCSw= github.com/tim-ywliu/nested-logrus-formatter v1.3.2/go.mod h1:oGPmcxZB65j9Wo7mCnQKSrKEJtVDqyjD666SGmyStXI= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= @@ -240,6 +245,16 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.49.0 h1:RtcvQ4iw3w9NBB5yRwgA4sSa82rfId7n4atVpvKx3bY= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.49.0/go.mod h1:f/PbKbRd4cdUICWell6DmzvVJ7QrmBgFrRHjXmAXbK4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -335,7 +350,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -352,6 +366,7 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -492,8 +507,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY= -gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/internal/context/context.go b/internal/context/context.go index e2d08ddf..84fa4f8f 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -45,7 +45,7 @@ type SMFContext struct { ExternalAddr string ListenAddr string - UDMProfile models.NfProfile + UDMProfile models.NrfNfDiscoveryNfProfile NfProfile NFProfile Key string @@ -302,13 +302,13 @@ func GetUEDefaultPathPool(groupName string) *UEDefaultPaths { return smfContext.UEDefaultPathPool[groupName] } -func (c *SMFContext) GetTokenCtx(serviceName models.ServiceName, targetNF models.NfType) ( +func (c *SMFContext) GetTokenCtx(serviceName models.ServiceName, targetNF models.NrfNfManagementNfType) ( context.Context, *models.ProblemDetails, error, ) { if !c.OAuth2Required { return context.TODO(), nil, nil } - return oauth.GetTokenCtx(models.NfType_SMF, targetNF, + return oauth.GetTokenCtx(models.NrfNfManagementNfType_SMF, targetNF, c.NfInstanceID, c.NrfUri, string(serviceName)) } diff --git a/internal/context/nf_profile.go b/internal/context/nf_profile.go index dc564f87..a872a989 100644 --- a/internal/context/nf_profile.go +++ b/internal/context/nf_profile.go @@ -9,7 +9,7 @@ import ( ) type NFProfile struct { - NFServices *[]models.NfService + NFServices *[]models.NrfNfManagementNfService NFServiceVersion *[]models.NfServiceVersion SMFInfo *models.SmfInfo PLMNList *[]models.PlmnId @@ -30,12 +30,12 @@ func (c *SMFContext) SetupNFProfile(nfProfileconfig *factory.Config) { } // set NFServices - c.NfProfile.NFServices = new([]models.NfService) + c.NfProfile.NFServices = new([]models.NrfNfManagementNfService) for _, serviceName := range nfProfileconfig.Configuration.ServiceNameList { - *c.NfProfile.NFServices = append(*c.NfProfile.NFServices, models.NfService{ + *c.NfProfile.NFServices = append(*c.NfProfile.NFServices, models.NrfNfManagementNfService{ ServiceInstanceId: GetSelf().NfInstanceID + serviceName, ServiceName: models.ServiceName(serviceName), - Versions: c.NfProfile.NFServiceVersion, + Versions: *c.NfProfile.NFServiceVersion, Scheme: models.UriScheme_HTTPS, NfServiceStatus: models.NfServiceStatus_REGISTERED, ApiPrefix: fmt.Sprintf("%s://%s:%d", GetSelf().URIScheme, GetSelf().RegisterIPv4, GetSelf().SBIPort), @@ -59,11 +59,11 @@ func (c *SMFContext) SetupNFProfile(nfProfileconfig *factory.Config) { } } -func SNssaiSmfInfo() *[]models.SnssaiSmfInfoItem { +func SNssaiSmfInfo() []models.SnssaiSmfInfoItem { snssaiInfo := make([]models.SnssaiSmfInfoItem, 0) for _, snssai := range smfContext.SnssaiInfos { var snssaiInfoModel models.SnssaiSmfInfoItem - snssaiInfoModel.SNssai = &models.Snssai{ + snssaiInfoModel.SNssai = &models.ExtSnssai{ Sst: snssai.Snssai.Sst, Sd: snssai.Snssai.Sd, } @@ -75,10 +75,10 @@ func SNssaiSmfInfo() *[]models.SnssaiSmfInfoItem { }) } - snssaiInfoModel.DnnSmfInfoList = &dnnModelList + snssaiInfoModel.DnnSmfInfoList = dnnModelList snssaiInfo = append(snssaiInfo, snssaiInfoModel) } - return &snssaiInfo + return snssaiInfo } diff --git a/internal/context/pcc_rule.go b/internal/context/pcc_rule.go index 9c42864a..3483039e 100644 --- a/internal/context/pcc_rule.go +++ b/internal/context/pcc_rule.go @@ -167,11 +167,11 @@ func createNasPacketFilter( smCtx.PacketFilterIDToNASPFID[pfInfo.PackFiltId] = uint8(pfId) switch pfInfo.FlowDirection { - case models.FlowDirectionRm_DOWNLINK: + case models.FlowDirection_DOWNLINK: pf.Direction = nasType.PacketFilterDirectionDownlink - case models.FlowDirectionRm_UPLINK: + case models.FlowDirection_UPLINK: pf.Direction = nasType.PacketFilterDirectionUplink - case models.FlowDirectionRm_BIDIRECTIONAL: + case models.FlowDirection_BIDIRECTIONAL: pf.Direction = nasType.PacketFilterDirectionBidirectional } diff --git a/internal/context/pfcp_reports.go b/internal/context/pfcp_reports.go index 8ca9d689..8aea032c 100644 --- a/internal/context/pfcp_reports.go +++ b/internal/context/pfcp_reports.go @@ -11,7 +11,7 @@ func (smContext *SMContext) HandleReports( usageReportRequest []*pfcp.UsageReportPFCPSessionReportRequest, usageReportModification []*pfcp.UsageReportPFCPSessionModificationResponse, usageReportDeletion []*pfcp.UsageReportPFCPSessionDeletionResponse, - nodeId pfcpType.NodeID, reportTpye models.TriggerType, + nodeId pfcpType.NodeID, reportTpye models.ChfConvergedChargingTriggerType, ) { var usageReport UsageReport upf := RetrieveUPFNodeByNodeID(nodeId) @@ -70,23 +70,23 @@ func (smContext *SMContext) HandleReports( } } -func identityTriggerType(usarTrigger *pfcpType.UsageReportTrigger) models.TriggerType { - var trigger models.TriggerType +func identityTriggerType(usarTrigger *pfcpType.UsageReportTrigger) models.ChfConvergedChargingTriggerType { + var trigger models.ChfConvergedChargingTriggerType switch { case usarTrigger.Volth: - trigger = models.TriggerType_QUOTA_THRESHOLD + trigger = models.ChfConvergedChargingTriggerType_QUOTA_THRESHOLD case usarTrigger.Volqu: - trigger = models.TriggerType_QUOTA_EXHAUSTED + trigger = models.ChfConvergedChargingTriggerType_QUOTA_EXHAUSTED case usarTrigger.Quvti: - trigger = models.TriggerType_VALIDITY_TIME + trigger = models.ChfConvergedChargingTriggerType_VALIDITY_TIME case usarTrigger.Start: - trigger = models.TriggerType_START_OF_SERVICE_DATA_FLOW + trigger = models.ChfConvergedChargingTriggerType_START_OF_SERVICE_DATA_FLOW case usarTrigger.Immer: logger.PduSessLog.Trace("Reports Query by SMF, trigger should be filled later") return "" case usarTrigger.Termr: - trigger = models.TriggerType_FINAL + trigger = models.ChfConvergedChargingTriggerType_FINAL default: logger.PduSessLog.Trace("Report is not a charging trigger") return "" diff --git a/internal/context/sm_context.go b/internal/context/sm_context.go index d8ac995e..f8aaaa5f 100644 --- a/internal/context/sm_context.go +++ b/internal/context/sm_context.go @@ -104,13 +104,13 @@ type UsageReport struct { UplinkPktNum uint64 DownlinkPktNum uint64 - ReportTpye models.TriggerType + ReportTpye models.ChfConvergedChargingTriggerType } var TeidGenerator *idgenerator.IDGenerator type SMContext struct { - *models.SmContextCreateData + *models.SmfPduSessionSmContextCreateData Ref string @@ -154,9 +154,9 @@ type SMContext struct { // Client CommunicationClientApiPrefix string - AMFProfile models.NfProfile - SelectedPCFProfile models.NfProfile - SelectedCHFProfile models.NfProfile + AMFProfile models.NrfNfDiscoveryNfProfile + SelectedPCFProfile models.NrfNfDiscoveryNfProfile + SelectedCHFProfile models.NrfNfDiscoveryNfProfile SmStatusNotifyUri string Tunnel *UPTunnel @@ -422,8 +422,8 @@ func (smContext *SMContext) GenerateUrrId() { } } -func (smContext *SMContext) BuildCreatedData() *models.SmContextCreatedData { - return &models.SmContextCreatedData{ +func (smContext *SMContext) BuildCreatedData() *models.SmfPduSessionSmContextCreatedData { + return &models.SmfPduSessionSmContextCreatedData{ SNssai: smContext.SNssai, } } @@ -614,7 +614,7 @@ func (c *SMContext) CreatePccRuleDataPath(pccRule *PCCRule, ) error { var targetRoute models.RouteToLocation if tcData != nil && len(tcData.RouteToLocs) > 0 { - targetRoute = tcData.RouteToLocs[0] + targetRoute = *tcData.RouteToLocs[0] } param := &UPFSelectionParams{ Dnn: c.Dnn, @@ -666,7 +666,7 @@ func (c *SMContext) BuildUpPathChgEventExposureNotification( return } - en := models.EventNotification{ + en := models.SmfEventExposureEventNotification{ Event: models.SmfEvent_UP_PATH_CH, SourceTraRouting: srcRoute, TargetTraRouting: tgtRoute, @@ -685,7 +685,7 @@ func (c *SMContext) BuildUpPathChgEventExposureNotification( v.EventNotifs = append(v.EventNotifs, en) } else { c.UpPathChgEarlyNotification[k] = newEventExposureNotification( - chgEvent.NotificationUri, chgEvent.NotifCorreId, en) + chgEvent.NotificationUri, chgEvent.NotifCorreId, &en) } } if strings.Contains(string(chgEvent.DnaiChgType), "LATE") { @@ -695,19 +695,19 @@ func (c *SMContext) BuildUpPathChgEventExposureNotification( v.EventNotifs = append(v.EventNotifs, en) } else { c.UpPathChgLateNotification[k] = newEventExposureNotification( - chgEvent.NotificationUri, chgEvent.NotifCorreId, en) + chgEvent.NotificationUri, chgEvent.NotifCorreId, &en) } } } func newEventExposureNotification( uri, id string, - en models.EventNotification, + en *models.SmfEventExposureEventNotification, ) *EventExposureNotification { return &EventExposureNotification{ NsmfEventExposureNotification: &models.NsmfEventExposureNotification{ NotifId: id, - EventNotifs: []models.EventNotification{en}, + EventNotifs: []models.SmfEventExposureEventNotification{*en}, }, Uri: uri, } diff --git a/internal/context/sm_context_policy.go b/internal/context/sm_context_policy.go index aef74c7f..5348f314 100644 --- a/internal/context/sm_context_policy.go +++ b/internal/context/sm_context_policy.go @@ -370,7 +370,7 @@ func checkUpPathChangeEvt(c *SMContext, return fmt.Errorf("No RouteToLocs in srcTcData") } // TODO: Fix always choosing the first RouteToLocs as source Route - srcRoute = srcTcData.RouteToLocs[0] + srcRoute = *srcTcData.RouteToLocs[0] // If no target TcData, the default UpPathChgEvent will be the one in source TcData upPathChgEvt = srcTcData.UpPathChgEvent } else { @@ -385,7 +385,7 @@ func checkUpPathChangeEvt(c *SMContext, return fmt.Errorf("No RouteToLocs in tgtTcData") } // TODO: Fix always choosing the first RouteToLocs as target Route - tgtRoute = tgtTcData.RouteToLocs[0] + tgtRoute = *tgtTcData.RouteToLocs[0] // If target TcData is available, change UpPathChgEvent to the one in target TcData upPathChgEvt = tgtTcData.UpPathChgEvent } else { diff --git a/internal/context/sm_context_policy_test.go b/internal/context/sm_context_policy_test.go index 58225916..1589c725 100644 --- a/internal/context/sm_context_policy_test.go +++ b/internal/context/sm_context_policy_test.go @@ -379,7 +379,7 @@ func TestApplyPccRules(t *testing.T) { TraffContDecs: map[string]*models.TrafficControlData{ "TcId-1": { TcId: "TcId-1", - RouteToLocs: []models.RouteToLocation{ + RouteToLocs: []*models.RouteToLocation{ { Dnai: "mec", }, @@ -411,7 +411,7 @@ func TestApplyPccRules(t *testing.T) { "TcId-1": { TrafficControlData: &models.TrafficControlData{ TcId: "TcId-1", - RouteToLocs: []models.RouteToLocation{ + RouteToLocs: []*models.RouteToLocation{ { Dnai: "mec", }, @@ -483,7 +483,7 @@ func TestApplyPccRules(t *testing.T) { "TcId-1": { TrafficControlData: &models.TrafficControlData{ TcId: "TcId-1", - RouteToLocs: []models.RouteToLocation{ + RouteToLocs: []*models.RouteToLocation{ { Dnai: "mec", }, @@ -555,7 +555,7 @@ func TestApplyPccRules(t *testing.T) { "TcId-1": { TrafficControlData: &models.TrafficControlData{ TcId: "TcId-1", - RouteToLocs: []models.RouteToLocation{ + RouteToLocs: []*models.RouteToLocation{ { Dnai: "mec", }, @@ -596,7 +596,7 @@ func TestApplyPccRules(t *testing.T) { "TcId-1": { TrafficControlData: &models.TrafficControlData{ TcId: "TcId-1", - RouteToLocs: []models.RouteToLocation{ + RouteToLocs: []*models.RouteToLocation{ { Dnai: "mec", }, @@ -631,7 +631,7 @@ func TestApplyPccRules(t *testing.T) { smctx.SMLock.Lock() defer smctx.SMLock.Unlock() - smctx.SmContextCreateData = &models.SmContextCreateData{ + smctx.SmfPduSessionSmContextCreateData = &models.SmfPduSessionSmContextCreateData{ Supi: "imsi-208930000000002", Pei: "imeisv-1110000000000000", Gpsi: "msisdn-0900000000", @@ -643,14 +643,14 @@ func TestApplyPccRules(t *testing.T) { }, ServingNfId: "c8d0ee65-f466-48aa-a42f-235ec771cb52", Guami: &models.Guami{ - PlmnId: &models.PlmnId{ + PlmnId: &models.PlmnIdNid{ Mcc: "208", Mnc: "93", }, AmfId: "cafe00", }, AnType: "3GPP_ACCESS", - ServingNetwork: &models.PlmnId{ + ServingNetwork: &models.PlmnIdNid{ Mcc: "208", Mnc: "93", }, diff --git a/internal/pfcp/handler/handler.go b/internal/pfcp/handler/handler.go index 7448072c..986e209b 100644 --- a/internal/pfcp/handler/handler.go +++ b/internal/pfcp/handler/handler.go @@ -161,7 +161,7 @@ func HandlePfcpSessionReportRequest(msg *pfcpUdp.Message) { SmInfo: &models.N2SmInformation{ PduSessionId: smContext.PDUSessionID, N2InfoContent: &models.N2InfoContent{ - NgapIeType: models.NgapIeType_PDU_RES_SETUP_REQ, + NgapIeType: models.AmfCommunicationNgapIeType_PDU_RES_SETUP_REQ, NgapData: &models.RefToBinaryData{ ContentId: "N2SmInformation", }, @@ -171,12 +171,12 @@ func HandlePfcpSessionReportRequest(msg *pfcpUdp.Message) { }, } - ctx, _, errToken := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NfType_AMF) + ctx, _, errToken := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NrfNfManagementNfType_AMF) if errToken != nil { logger.PfcpLog.Warnf("Get NAMF_COMM context failed: %s", errToken) return } - rspData, _, err := service.GetApp().Consumer(). + rspData, err := service.GetApp().Consumer(). N1N2MessageTransfer(ctx, smContext.Supi, n1n2Request, smContext.CommunicationClientApiPrefix) if err != nil { logger.ConsumerLog.Warnf("Send N1N2Transfer failed: %s", err) diff --git a/internal/sbi/api_callback.go b/internal/sbi/api_callback.go index bb1cd6f1..53e5c446 100644 --- a/internal/sbi/api_callback.go +++ b/internal/sbi/api_callback.go @@ -14,16 +14,19 @@ import ( func (s *Server) getCallbackRoutes() []Route { return []Route{ { + Name: "SmPolicyUpdateNotification", Method: http.MethodPost, Pattern: "/sm-policies/:smContextRef/update", APIFunc: s.HTTPSmPolicyUpdateNotification, }, { + Name: "SmPolicyControlTerminationRequestNotification", Method: http.MethodPost, Pattern: "/sm-policies/:smContextRef/terminate", APIFunc: s.SmPolicyControlTerminationRequestNotification, }, { + Name: "ChargingNotification", Method: http.MethodPost, Pattern: "/:notifyUri", APIFunc: s.HTTPChargingNotification, diff --git a/internal/sbi/api_eventexposure.go b/internal/sbi/api_eventexposure.go index 273e0020..a3d16dac 100644 --- a/internal/sbi/api_eventexposure.go +++ b/internal/sbi/api_eventexposure.go @@ -18,6 +18,7 @@ import ( func (s *Server) getEventExposureRoutes() []Route { return []Route{ { + Name: "Index", Method: http.MethodGet, Pattern: "/", APIFunc: func(c *gin.Context) { @@ -25,44 +26,48 @@ func (s *Server) getEventExposureRoutes() []Route { }, }, { + Name: "CreateIndividualSubcription", Method: http.MethodPost, - Pattern: "subscriptions", - APIFunc: s.SubscriptionsPost, + Pattern: "/subscriptions", + APIFunc: s.HTTPCreateIndividualSubcription, }, { + Name: "DeleteIndividualSubcription", Method: http.MethodDelete, - Pattern: "subscriptions/:subId", - APIFunc: s.SubscriptionsSubIdDelete, + Pattern: "/subscriptions/:subId", + APIFunc: s.HTTPDeleteIndividualSubcription, }, { + Name: "GetIndividualSubcription", Method: http.MethodGet, - Pattern: "subscriptions/:subId", - APIFunc: s.SubscriptionsSubIdGet, + Pattern: "/subscriptions/:subId", + APIFunc: s.HTTPGetIndividualSubcription, }, { + Name: "ReplaceIndividualSubcription", Method: http.MethodPut, - Pattern: "subscriptions/:subId", - APIFunc: s.SubscriptionsSubIdPut, + Pattern: "/subscriptions/:subId", + APIFunc: s.HTTPReplaceIndividualSubcription, }, } } // SubscriptionsPost - -func (s *Server) SubscriptionsPost(c *gin.Context) { +func (s *Server) HTTPCreateIndividualSubcription(c *gin.Context) { c.JSON(http.StatusNotImplemented, gin.H{}) } // SubscriptionsSubIdDelete - -func (s *Server) SubscriptionsSubIdDelete(c *gin.Context) { +func (s *Server) HTTPDeleteIndividualSubcription(c *gin.Context) { c.JSON(http.StatusNotImplemented, gin.H{}) } // SubscriptionsSubIdGet - -func (s *Server) SubscriptionsSubIdGet(c *gin.Context) { +func (s *Server) HTTPGetIndividualSubcription(c *gin.Context) { c.JSON(http.StatusNotImplemented, gin.H{}) } // SubscriptionsSubIdPut - -func (s *Server) SubscriptionsSubIdPut(c *gin.Context) { +func (s *Server) HTTPReplaceIndividualSubcription(c *gin.Context) { c.JSON(http.StatusNotImplemented, gin.H{}) } diff --git a/internal/sbi/api_oam.go b/internal/sbi/api_oam.go index 23a33069..7541c5a2 100644 --- a/internal/sbi/api_oam.go +++ b/internal/sbi/api_oam.go @@ -9,6 +9,7 @@ import ( func (s *Server) getOAMRoutes() []Route { return []Route{ { + Name: "Index", Method: http.MethodGet, Pattern: "/", APIFunc: func(c *gin.Context) { @@ -16,11 +17,13 @@ func (s *Server) getOAMRoutes() []Route { }, }, { + Name: "Get UE PDU Session Info", Method: http.MethodGet, Pattern: "/ue-pdu-session-info/:smContextRef", APIFunc: s.HTTPGetUEPDUSessionInfo, }, { + Name: "Get SMF Userplane Information", Method: http.MethodGet, Pattern: "/user-plane-info/", APIFunc: s.HTTPGetSMFUserPlaneInfo, diff --git a/internal/sbi/api_pdusession.go b/internal/sbi/api_pdusession.go index bd51ca80..66b33343 100644 --- a/internal/sbi/api_pdusession.go +++ b/internal/sbi/api_pdusession.go @@ -15,6 +15,7 @@ import ( func (s *Server) getPDUSessionRoutes() []Route { return []Route{ { + Name: "Index", Method: http.MethodGet, Pattern: "/", APIFunc: func(c *gin.Context) { @@ -22,58 +23,74 @@ func (s *Server) getPDUSessionRoutes() []Route { }, }, { + Name: "PostSmContexts", Method: http.MethodPost, - Pattern: "/pdu-sessions/:pduSessionRef/release", - APIFunc: s.ReleasePduSession, + Pattern: "/sm-contexts", + APIFunc: s.HTTPPostSmContexts, }, { + Name: "UpdateSmContext", Method: http.MethodPost, - Pattern: "/pdu-sessions/:pduSessionRef/modify", - APIFunc: s.UpdatePduSession, + Pattern: "/sm-contexts/:smContextRef/modify", + APIFunc: s.HTTPUpdateSmContext, }, { + Name: "RetrieveSmContext", Method: http.MethodPost, - Pattern: "/sm-contexts/:smContextRef/release", - APIFunc: s.HTTPReleaseSmContext, + Pattern: "/sm-contexts/:smContextRef/retrieve", + APIFunc: s.HTTPRetrieveSmContext, }, { + Name: "ReleaseSmContext", Method: http.MethodPost, - Pattern: "/sm-contexts/:smContextRef/retrieve", - APIFunc: s.RetrieveSmContext, + Pattern: "/sm-contexts/:smContextRef/release", + APIFunc: s.HTTPReleaseSmContext, }, { + Name: "SendMoData", Method: http.MethodPost, - Pattern: "/sm-contexts/:smContextRef/modify", - APIFunc: s.HTTPUpdateSmContext, + Pattern: "/sm-contexts/:smContextRef/send-mo-data", + APIFunc: s.HTTPSendMoData, }, { + Name: "PostPduSessions", Method: http.MethodPatch, Pattern: "/pdu-sessions", - APIFunc: s.PostPduSessions, + APIFunc: s.HTTPPostPduSessions, }, { + Name: "UpdatePduSession", Method: http.MethodPost, - Pattern: "/sm-contexts", - APIFunc: s.HTTPPostSmContexts, + Pattern: "/pdu-sessions/:pduSessionRef/modify", + APIFunc: s.HTTPUpdatePduSession, + }, + { + Name: "ReleasePduSession", + Method: http.MethodPost, + Pattern: "/pdu-sessions/:pduSessionRef/release", + APIFunc: s.HTTPReleasePduSession, + }, + { + Name: "RetrievePduSession", + Method: http.MethodPost, + Pattern: "/pdu-sessions/:pduSessionRef/retrieve", + APIFunc: s.HTTPRetrievePduSession, + }, + { + Name: "TransferMoData", + Method: http.MethodPost, + Pattern: "/pdu-sessions/:pduSessionRef/transfer-mo-data", + APIFunc: s.HTTPTransferMoData, }, } } -// ReleasePduSession - Release -func (s *Server) ReleasePduSession(c *gin.Context) { - c.JSON(http.StatusNotImplemented, gin.H{}) -} - -// UpdatePduSession - Update (initiated by V-SMF) -func (s *Server) UpdatePduSession(c *gin.Context) { - c.JSON(http.StatusNotImplemented, gin.H{}) -} +// HTTPPostSmContexts - Create SM Context +func (s *Server) HTTPPostSmContexts(c *gin.Context) { + logger.PduSessLog.Info("Receive Create SM Context Request") + var request models.PostSmContextsRequest -// HTTPReleaseSmContext - Release SM Context -func (s *Server) HTTPReleaseSmContext(c *gin.Context) { - logger.PduSessLog.Info("Receive Release SM Context Request") - var request models.ReleaseSmContextRequest - request.JsonData = new(models.SmContextReleaseData) + request.JsonData = new(models.SmfPduSessionSmContextCreateData) contentType := strings.Split(c.GetHeader("Content-Type"), ";") var err error @@ -83,25 +100,23 @@ func (s *Server) HTTPReleaseSmContext(c *gin.Context) { case MULTIPART_RELATED: err = c.ShouldBindWith(&request, openapi.MultipartRelatedBinding{}) } + if err != nil { - log.Print(err) + problemDetail := "[Request Body] " + err.Error() + logger.PduSessLog.Errorln(problemDetail) + c.JSON(http.StatusBadRequest, openapi.ProblemDetailsMalformedReqSyntax(problemDetail)) return } - smContextRef := c.Params.ByName("smContextRef") - s.Processor().HandlePDUSessionSMContextRelease(c, request, smContextRef) -} - -// RetrieveSmContext - Retrieve SM Context -func (s *Server) RetrieveSmContext(c *gin.Context) { - c.JSON(http.StatusNotImplemented, gin.H{}) + isDone := c.Done() + s.Processor().HandlePDUSessionSMContextCreate(c, request, isDone) } // HTTPUpdateSmContext - Update SM Context func (s *Server) HTTPUpdateSmContext(c *gin.Context) { logger.PduSessLog.Info("Receive Update SM Context Request") var request models.UpdateSmContextRequest - request.JsonData = new(models.SmContextUpdateData) + request.JsonData = new(models.SmfPduSessionSmContextUpdateData) contentType := strings.Split(c.GetHeader("Content-Type"), ";") var err error @@ -120,17 +135,16 @@ func (s *Server) HTTPUpdateSmContext(c *gin.Context) { s.Processor().HandlePDUSessionSMContextUpdate(c, request, smContextRef) } -// PostPduSessions - Create -func (s *Server) PostPduSessions(c *gin.Context) { +// HTTPRetrieveSmContext - Retrieve SM Context +func (s *Server) HTTPRetrieveSmContext(c *gin.Context) { c.JSON(http.StatusNotImplemented, gin.H{}) } -// HTTPPostSmContexts - Create SM Context -func (s *Server) HTTPPostSmContexts(c *gin.Context) { - logger.PduSessLog.Info("Receive Create SM Context Request") - var request models.PostSmContextsRequest - - request.JsonData = new(models.SmContextCreateData) +// HTTPReleaseSmContext - Release SM Context +func (s *Server) HTTPReleaseSmContext(c *gin.Context) { + logger.PduSessLog.Info("Receive Release SM Context Request") + var request models.ReleaseSmContextRequest + request.JsonData = new(models.SmfPduSessionSmContextReleaseData) contentType := strings.Split(c.GetHeader("Content-Type"), ";") var err error @@ -140,19 +154,38 @@ func (s *Server) HTTPPostSmContexts(c *gin.Context) { case MULTIPART_RELATED: err = c.ShouldBindWith(&request, openapi.MultipartRelatedBinding{}) } - if err != nil { - problemDetail := "[Request Body] " + err.Error() - rsp := models.ProblemDetails{ - Title: "Malformed request syntax", - Status: http.StatusBadRequest, - Detail: problemDetail, - } - logger.PduSessLog.Errorln(problemDetail) - c.JSON(http.StatusBadRequest, rsp) + log.Print(err) return } - isDone := c.Done() - s.Processor().HandlePDUSessionSMContextCreate(c, request, isDone) + smContextRef := c.Params.ByName("smContextRef") + s.Processor().HandlePDUSessionSMContextRelease(c, request, smContextRef) +} + +func (s *Server) HTTPSendMoData(c *gin.Context) { + c.JSON(http.StatusNotImplemented, gin.H{}) +} + +// HTTPPostPduSessions - Create +func (s *Server) HTTPPostPduSessions(c *gin.Context) { + c.JSON(http.StatusNotImplemented, gin.H{}) +} + +// HTTPUpdatePduSession - Update (initiated by V-SMF) +func (s *Server) HTTPUpdatePduSession(c *gin.Context) { + c.JSON(http.StatusNotImplemented, gin.H{}) +} + +// HTTPReleasePduSession - Release +func (s *Server) HTTPReleasePduSession(c *gin.Context) { + c.JSON(http.StatusNotImplemented, gin.H{}) +} + +func (s *Server) HTTPRetrievePduSession(c *gin.Context) { + c.JSON(http.StatusNotImplemented, gin.H{}) +} + +func (s *Server) HTTPTransferMoData(c *gin.Context) { + c.JSON(http.StatusNotImplemented, gin.H{}) } diff --git a/internal/sbi/api_upi.go b/internal/sbi/api_upi.go index 254cc78d..2e86d0ed 100644 --- a/internal/sbi/api_upi.go +++ b/internal/sbi/api_upi.go @@ -12,6 +12,7 @@ import ( func (s *Server) getUPIRoutes() []Route { return []Route{ { + Name: "Index", Method: http.MethodGet, Pattern: "/", APIFunc: func(c *gin.Context) { @@ -19,16 +20,19 @@ func (s *Server) getUPIRoutes() []Route { }, }, { + Name: "GetUpNodesLinks", Method: http.MethodGet, Pattern: "/upNodesLinks", APIFunc: s.GetUpNodesLinks, }, { + Name: "AddUpNodesLinks", Method: http.MethodPost, Pattern: "/upNodesLinks", APIFunc: s.PostUpNodesLinks, }, { + Name: "DeleteUpNodeLink", Method: http.MethodDelete, Pattern: "/upNodesLinks/:upNodeRef", APIFunc: s.DeleteUpNodeLink, diff --git a/internal/sbi/consumer/amf_service.go b/internal/sbi/consumer/amf_service.go index 537ae703..66112058 100644 --- a/internal/sbi/consumer/amf_service.go +++ b/internal/sbi/consumer/amf_service.go @@ -5,9 +5,8 @@ import ( "fmt" "sync" - "github.com/free5gc/openapi/Namf_Communication" + "github.com/free5gc/openapi/amf/Communication" "github.com/free5gc/openapi/models" - "github.com/free5gc/smf/internal/logger" ) type namfService struct { @@ -15,10 +14,10 @@ type namfService struct { CommunicationMu sync.RWMutex - CommunicationClients map[string]*Namf_Communication.APIClient + CommunicationClients map[string]*Communication.APIClient } -func (s *namfService) getCommunicationClient(uri string) *Namf_Communication.APIClient { +func (s *namfService) getCommunicationClient(uri string) *Communication.APIClient { if uri == "" { return nil } @@ -29,9 +28,9 @@ func (s *namfService) getCommunicationClient(uri string) *Namf_Communication.API return client } - configuration := Namf_Communication.NewConfiguration() + configuration := Communication.NewConfiguration() configuration.SetBasePath(uri) - client = Namf_Communication.NewAPIClient(configuration) + client = Communication.NewAPIClient(configuration) s.CommunicationMu.RUnlock() s.CommunicationMu.Lock() @@ -42,23 +41,21 @@ func (s *namfService) getCommunicationClient(uri string) *Namf_Communication.API func (s *namfService) N1N2MessageTransfer( ctx context.Context, supi string, n1n2Request models.N1N2MessageTransferRequest, apiPrefix string, -) (*models.N1N2MessageTransferRspData, *int, error) { +) (*models.N1N2MessageTransferRspData, error) { client := s.getCommunicationClient(apiPrefix) if client == nil { - return nil, nil, fmt.Errorf("N1N2MessageTransfer client is nil: (%v)", apiPrefix) + return nil, fmt.Errorf("N1N2MessageTransfer client is nil: (%v)", apiPrefix) } - rspData, rsp, err := client.N1N2MessageCollectionDocumentApi.N1N2MessageTransfer(ctx, supi, n1n2Request) - if err != nil { - return nil, nil, err + n1n2MessageTransferRequest := &Communication.N1N2MessageTransferRequest{ + UeContextId: &supi, + N1N2MessageTransferRequest: &n1n2Request, } - defer func() { - if errClose := rsp.Body.Close(); errClose != nil { - logger.ConsumerLog.Warnf("Close body failed %v", errClose) - } - }() + rsp, err := client.N1N2MessageCollectionCollectionApi.N1N2MessageTransfer(ctx, n1n2MessageTransferRequest) + if err != nil || rsp == nil { + return nil, err + } - statusCode := rsp.StatusCode - return &rspData, &statusCode, err + return &rsp.N1N2MessageTransferRspData, err } diff --git a/internal/sbi/consumer/chf_service.go b/internal/sbi/consumer/chf_service.go index 99b54645..39d3ef11 100644 --- a/internal/sbi/consumer/chf_service.go +++ b/internal/sbi/consumer/chf_service.go @@ -2,14 +2,13 @@ package consumer import ( "fmt" - "net/http" "strings" "sync" "time" "github.com/free5gc/nas/nasConvert" "github.com/free5gc/openapi" - "github.com/free5gc/openapi/Nchf_ConvergedCharging" + "github.com/free5gc/openapi/chf/ConvergedCharging" "github.com/free5gc/openapi/models" smf_context "github.com/free5gc/smf/internal/context" "github.com/free5gc/smf/internal/logger" @@ -20,10 +19,10 @@ type nchfService struct { ConvergedChargingMu sync.RWMutex - ConvergedChargingClients map[string]*Nchf_ConvergedCharging.APIClient + ConvergedChargingClients map[string]*ConvergedCharging.APIClient } -func (s *nchfService) getConvergedChargingClient(uri string) *Nchf_ConvergedCharging.APIClient { +func (s *nchfService) getConvergedChargingClient(uri string) *ConvergedCharging.APIClient { if uri == "" { return nil } @@ -34,9 +33,9 @@ func (s *nchfService) getConvergedChargingClient(uri string) *Nchf_ConvergedChar return client } - configuration := Nchf_ConvergedCharging.NewConfiguration() + configuration := ConvergedCharging.NewConfiguration() configuration.SetBasePath(uri) - client = Nchf_ConvergedCharging.NewAPIClient(configuration) + client = ConvergedCharging.NewAPIClient(configuration) s.ConvergedChargingMu.RUnlock() s.ConvergedChargingMu.Lock() @@ -46,9 +45,9 @@ func (s *nchfService) getConvergedChargingClient(uri string) *Nchf_ConvergedChar } func (s *nchfService) buildConvergedChargingRequest(smContext *smf_context.SMContext, - multipleUnitUsage []models.MultipleUnitUsage, -) *models.ChargingDataRequest { - var triggers []models.Trigger + multipleUnitUsage []models.ChfConvergedChargingMultipleUnitUsage, +) *models.ChfConvergedChargingChargingDataRequest { + var triggers []models.ChfConvergedChargingTrigger smfContext := s.consumer.Context() date := time.Now() @@ -59,33 +58,33 @@ func (s *nchfService) buildConvergedChargingRequest(smContext *smf_context.SMCon } } - req := &models.ChargingDataRequest{ + req := &models.ChfConvergedChargingChargingDataRequest{ ChargingId: smContext.ChargingID, SubscriberIdentifier: smContext.Supi, - NfConsumerIdentification: &models.NfIdentification{ - NodeFunctionality: models.NodeFunctionality_SMF, + NfConsumerIdentification: &models.ChfConvergedChargingNfIdentification{ + NodeFunctionality: models.ChfConvergedChargingNodeFunctionality_SMF, NFName: smfContext.Name, // not sure if NFIPv4Address is RegisterIPv4 or BindingIPv4 NFIPv4Address: smfContext.RegisterIPv4, }, InvocationTimeStamp: &date, Triggers: triggers, - PDUSessionChargingInformation: &models.PduSessionChargingInformation{ + PDUSessionChargingInformation: &models.ChfConvergedChargingPduSessionChargingInformation{ ChargingId: smContext.ChargingID, - UserInformation: &models.UserInformation{ + UserInformation: &models.ChfConvergedChargingUserInformation{ ServedGPSI: smContext.Gpsi, ServedPEI: smContext.Pei, }, - PduSessionInformation: &models.PduSessionInformation{ + PduSessionInformation: &models.ChfConvergedChargingPduSessionInformation{ PduSessionID: smContext.PDUSessionID, NetworkSlicingInfo: &models.NetworkSlicingInfo{ SNSSAI: smContext.SNssai, }, PduType: nasConvert.PDUSessionTypeToModels(smContext.SelectedPDUSessionType), - ServingNetworkFunctionID: &models.ServingNetworkFunctionId{ - ServingNetworkFunctionInformation: &models.NfIdentification{ - NodeFunctionality: models.NodeFunctionality_AMF, + ServingNetworkFunctionID: &models.ChfConvergedChargingServingNetworkFunctionId{ + ServingNetworkFunctionInformation: &models.ChfConvergedChargingNfIdentification{ + NodeFunctionality: models.ChfConvergedChargingNodeFunctionality_AMF, }, }, DnnId: smContext.Dnn, @@ -106,73 +105,113 @@ func (s *nchfService) buildConvergedChargingRequest(smContext *smf_context.SMCon func (s *nchfService) SendConvergedChargingRequest( smContext *smf_context.SMContext, requestType smf_context.RequestType, - multipleUnitUsage []models.MultipleUnitUsage, + multipleUnitUsage []models.ChfConvergedChargingMultipleUnitUsage, ) ( - *models.ChargingDataResponse, *models.ProblemDetails, error, + *models.ChfConvergedChargingChargingDataResponse, *models.ProblemDetails, error, ) { logger.ChargingLog.Info("Handle SendConvergedChargingRequest") req := s.buildConvergedChargingRequest(smContext, multipleUnitUsage) - var rsp models.ChargingDataResponse - var httpResponse *http.Response - var err error - - ctx, pd, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NCHF_CONVERGEDCHARGING, models.NfType_CHF) + ctx, pd, err := smf_context.GetSelf(). + GetTokenCtx(models.ServiceName_NCHF_CONVERGEDCHARGING, models.NrfNfManagementNfType_CHF) if err != nil { return nil, pd, err } if smContext.SelectedCHFProfile.NfServices == nil { - errMsg := "No CHF found" + errMsg := "no CHF found" return nil, openapi.ProblemDetailsDataNotFound(errMsg), fmt.Errorf(errMsg) } - var client *Nchf_ConvergedCharging.APIClient + var client *ConvergedCharging.APIClient // Create Converged Charging Client for this SM Context - for _, service := range *smContext.SelectedCHFProfile.NfServices { + for _, service := range smContext.SelectedCHFProfile.NfServices { if service.ServiceName == models.ServiceName_NCHF_CONVERGEDCHARGING { client = s.getConvergedChargingClient(service.ApiPrefix) } } if client == nil { - errMsg := "No CONVERGEDCHARGING-CHF found" + errMsg := "no CONVERGEDCHARGING-CHF found" return nil, openapi.ProblemDetailsDataNotFound(errMsg), fmt.Errorf(errMsg) } // select the appropriate converged charging service based on trigger type switch requestType { case smf_context.CHARGING_INIT: - rsp, httpResponse, err = client.DefaultApi.ChargingdataPost(ctx, *req) - if httpResponse != nil { - chargingDataRef := strings.Split(httpResponse.Header.Get("Location"), "/") - smContext.ChargingDataRef = chargingDataRef[len(chargingDataRef)-1] + postChargingDataRequest := &ConvergedCharging.PostChargingDataRequest{ + ChfConvergedChargingChargingDataRequest: req, + } + rspPost, localErr := client.DefaultApi.PostChargingData(ctx, postChargingDataRequest) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case ConvergedCharging.PostChargingDataError: + chargingDataRef := strings.Split(errModel.Location, "/") + smContext.ChargingDataRef = chargingDataRef[len(chargingDataRef)-1] + return nil, &errModel.ProblemDetails, nil + case error: + return nil, openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, nil, openapi.ReportError("openapi error") + } + case error: + return nil, openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: + return &rspPost.ChfConvergedChargingChargingDataResponse, nil, nil + default: + return nil, nil, openapi.ReportError("server no response") } case smf_context.CHARGING_UPDATE: - rsp, httpResponse, err = client.DefaultApi.ChargingdataChargingDataRefUpdatePost( - ctx, smContext.ChargingDataRef, *req) - case smf_context.CHARGING_RELEASE: - httpResponse, err = client.DefaultApi.ChargingdataChargingDataRefReleasePost(ctx, - smContext.ChargingDataRef, *req) - } - - defer func() { - if httpResponse != nil { - if resCloseErr := httpResponse.Body.Close(); resCloseErr != nil { - logger.ChargingLog.Errorf("RegisterNFInstance response body cannot close: %+v", resCloseErr) + updateChargingDataRequest := &ConvergedCharging.UpdateChargingDataRequest{ + ChargingDataRef: &smContext.ChargingDataRef, + ChfConvergedChargingChargingDataRequest: req, + } + rspUpdate, localErr := client.DefaultApi.UpdateChargingData(ctx, updateChargingDataRequest) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case ConvergedCharging.UpdateChargingDataError: + return nil, &errModel.ProblemDetails, nil + case error: + return nil, openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, nil, openapi.ReportError("openapi error") } + case error: + return nil, openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: + return &rspUpdate.ChfConvergedChargingChargingDataResponse, nil, nil + default: + return nil, nil, openapi.ReportError("server no response") } - }() - - if err == nil { - return &rsp, nil, nil - } else if httpResponse != nil { - if httpResponse.Status != err.Error() { - return nil, nil, err + case smf_context.CHARGING_RELEASE: + releaseChargingDataRequest := &ConvergedCharging.ReleaseChargingDataRequest{ + ChargingDataRef: &smContext.ChargingDataRef, + ChfConvergedChargingChargingDataRequest: req, + } + _, localErr := client.DefaultApi.ReleaseChargingData(ctx, releaseChargingDataRequest) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case ConvergedCharging.ReleaseChargingDataError: + return nil, &errModel.ProblemDetails, nil + case error: + return nil, openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, nil, openapi.ReportError("openapi error") + } + case error: + return nil, openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: + return nil, nil, nil + default: + return nil, nil, openapi.ReportError("server no response") } - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - return nil, &problem, nil - } else { - return nil, nil, openapi.ReportError("server no response") + default: + return nil, nil, openapi.ReportError("invalid request type") } } diff --git a/internal/sbi/consumer/consumer.go b/internal/sbi/consumer/consumer.go index bdd676e1..79c3715e 100644 --- a/internal/sbi/consumer/consumer.go +++ b/internal/sbi/consumer/consumer.go @@ -1,14 +1,14 @@ package consumer import ( - "github.com/free5gc/openapi/Namf_Communication" - "github.com/free5gc/openapi/Nchf_ConvergedCharging" - "github.com/free5gc/openapi/Nnrf_NFDiscovery" - "github.com/free5gc/openapi/Nnrf_NFManagement" - "github.com/free5gc/openapi/Npcf_SMPolicyControl" - "github.com/free5gc/openapi/Nsmf_PDUSession" - "github.com/free5gc/openapi/Nudm_SubscriberDataManagement" - "github.com/free5gc/openapi/Nudm_UEContextManagement" + "github.com/free5gc/openapi/amf/Communication" + "github.com/free5gc/openapi/chf/ConvergedCharging" + "github.com/free5gc/openapi/nrf/NFDiscovery" + "github.com/free5gc/openapi/nrf/NFManagement" + "github.com/free5gc/openapi/pcf/SMPolicyControl" + "github.com/free5gc/openapi/smf/PDUSession" + "github.com/free5gc/openapi/udm/SubscriberDataManagement" + "github.com/free5gc/openapi/udm/UEContextManagement" "github.com/free5gc/smf/pkg/app" ) @@ -31,34 +31,34 @@ func NewConsumer(smf app.App) (*Consumer, error) { c.nsmfService = &nsmfService{ consumer: c, - PDUSessionClients: make(map[string]*Nsmf_PDUSession.APIClient), + PDUSessionClients: make(map[string]*PDUSession.APIClient), } c.namfService = &namfService{ consumer: c, - CommunicationClients: make(map[string]*Namf_Communication.APIClient), + CommunicationClients: make(map[string]*Communication.APIClient), } c.nchfService = &nchfService{ consumer: c, - ConvergedChargingClients: make(map[string]*Nchf_ConvergedCharging.APIClient), + ConvergedChargingClients: make(map[string]*ConvergedCharging.APIClient), } c.nudmService = &nudmService{ consumer: c, - SubscriberDataManagementClients: make(map[string]*Nudm_SubscriberDataManagement.APIClient), - UEContextManagementClients: make(map[string]*Nudm_UEContextManagement.APIClient), + SubscriberDataManagementClients: make(map[string]*SubscriberDataManagement.APIClient), + UEContextManagementClients: make(map[string]*UEContextManagement.APIClient), } c.nnrfService = &nnrfService{ consumer: c, - NFManagementClients: make(map[string]*Nnrf_NFManagement.APIClient), - NFDiscoveryClients: make(map[string]*Nnrf_NFDiscovery.APIClient), + NFManagementClients: make(map[string]*NFManagement.APIClient), + NFDiscoveryClients: make(map[string]*NFDiscovery.APIClient), } c.npcfService = &npcfService{ consumer: c, - SMPolicyControlClients: make(map[string]*Npcf_SMPolicyControl.APIClient), + SMPolicyControlClients: make(map[string]*SMPolicyControl.APIClient), } return c, nil diff --git a/internal/sbi/consumer/nrf_service.go b/internal/sbi/consumer/nrf_service.go index 695684e1..bec522c8 100644 --- a/internal/sbi/consumer/nrf_service.go +++ b/internal/sbi/consumer/nrf_service.go @@ -3,20 +3,17 @@ package consumer import ( "context" "fmt" - "net/http" "strings" "sync" "time" - "github.com/antihax/optional" - "github.com/mohae/deepcopy" "github.com/pkg/errors" "github.com/free5gc/openapi" - "github.com/free5gc/openapi/Nnrf_NFDiscovery" - "github.com/free5gc/openapi/Nnrf_NFManagement" - "github.com/free5gc/openapi/Nudm_SubscriberDataManagement" "github.com/free5gc/openapi/models" + "github.com/free5gc/openapi/nrf/NFDiscovery" + "github.com/free5gc/openapi/nrf/NFManagement" + "github.com/free5gc/openapi/udm/SubscriberDataManagement" smf_context "github.com/free5gc/smf/internal/context" "github.com/free5gc/smf/internal/logger" ) @@ -27,11 +24,11 @@ type nnrfService struct { NFManagementgMu sync.RWMutex NFDiscoveryMu sync.RWMutex - NFManagementClients map[string]*Nnrf_NFManagement.APIClient - NFDiscoveryClients map[string]*Nnrf_NFDiscovery.APIClient + NFManagementClients map[string]*NFManagement.APIClient + NFDiscoveryClients map[string]*NFDiscovery.APIClient } -func (s *nnrfService) getNFManagementClient(uri string) *Nnrf_NFManagement.APIClient { +func (s *nnrfService) getNFManagementClient(uri string) *NFManagement.APIClient { if uri == "" { return nil } @@ -42,9 +39,9 @@ func (s *nnrfService) getNFManagementClient(uri string) *Nnrf_NFManagement.APICl return client } - configuration := Nnrf_NFManagement.NewConfiguration() + configuration := NFManagement.NewConfiguration() configuration.SetBasePath(uri) - client = Nnrf_NFManagement.NewAPIClient(configuration) + client = NFManagement.NewAPIClient(configuration) s.NFManagementgMu.RUnlock() s.NFManagementgMu.Lock() @@ -53,7 +50,7 @@ func (s *nnrfService) getNFManagementClient(uri string) *Nnrf_NFManagement.APICl return client } -func (s *nnrfService) getNFDiscoveryClient(uri string) *Nnrf_NFDiscovery.APIClient { +func (s *nnrfService) getNFDiscoveryClient(uri string) *NFDiscovery.APIClient { if uri == "" { return nil } @@ -64,9 +61,9 @@ func (s *nnrfService) getNFDiscoveryClient(uri string) *Nnrf_NFDiscovery.APIClie return client } - configuration := Nnrf_NFDiscovery.NewConfiguration() + configuration := NFDiscovery.NewConfiguration() configuration.SetBasePath(uri) - client = Nnrf_NFDiscovery.NewAPIClient(configuration) + client = NFDiscovery.NewAPIClient(configuration) s.NFDiscoveryMu.RUnlock() s.NFDiscoveryMu.Lock() @@ -83,48 +80,51 @@ func (s *nnrfService) RegisterNFInstance(ctx context.Context) error { return errors.Wrap(err, "RegisterNFInstance buildNfProfile()") } - var nf models.NfProfile - var res *http.Response + var nf models.NrfNfManagementNfProfile + var res *NFManagement.RegisterNFInstanceResponse + registerNFInstanceRequest := &NFManagement.RegisterNFInstanceRequest{ + NfInstanceID: &smfContext.NfInstanceID, + NrfNfManagementNfProfile: &nfProfile, + } // Check data (Use RESTful PUT) - for { - nf, res, err = client.NFInstanceIDDocumentApi. - RegisterNFInstance(ctx, smfContext.NfInstanceID, nfProfile) - if err != nil || res == nil { - logger.ConsumerLog.Infof("SMF register to NRF Error[%s]", err.Error()) - time.Sleep(2 * time.Second) - continue - } - defer func() { - if resCloseErr := res.Body.Close(); resCloseErr != nil { - logger.ConsumerLog.Errorf("RegisterNFInstance response body cannot close: %+v", resCloseErr) + finish := false + for !finish { + select { + case <-ctx.Done(): + return fmt.Errorf("RegisterNFInstance context done") + default: + res, err = client.NFInstanceIDDocumentApi.RegisterNFInstance(ctx, registerNFInstanceRequest) + if err != nil || res == nil { + logger.ConsumerLog.Errorf("SMF register to NRF Error[%s]", 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") - smfContext.NfInstanceID = resourceUri[strings.LastIndex(resourceUri, "/")+1:] - - oauth2 := false - if nf.CustomInfo != nil { - v, ok := nf.CustomInfo["oauth2"].(bool) - if ok { - oauth2 = v - logger.MainLog.Infoln("OAuth2 setting receive from NRF:", oauth2) + nf = res.NrfNfManagementNfProfile + + // http.StatusOK + if res.Location == "" { + // NFUpdate + finish = true + } else { // http.StatusCreated + // NFRegister + resourceUri := res.Location + smfContext.NfInstanceID = resourceUri[strings.LastIndex(resourceUri, "/")+1:] + + oauth2 := false + if nf.CustomInfo != nil { + v, ok := nf.CustomInfo["oauth2"].(bool) + if ok { + oauth2 = v + logger.MainLog.Infoln("OAuth2 setting receive from NRF:", oauth2) + } } + smfContext.OAuth2Required = oauth2 + if oauth2 && smfContext.NrfCertPem == "" { + logger.CfgLog.Error("OAuth2 enable but no nrfCertPem provided in config.") + } + finish = true } - smfContext.OAuth2Required = oauth2 - if oauth2 && smfContext.NrfCertPem == "" { - logger.CfgLog.Error("OAuth2 enable but no nrfCertPem provided in config.") - } - break - } else { - logger.ConsumerLog.Infof("handler returned wrong status code %d", status) } } @@ -132,24 +132,26 @@ func (s *nnrfService) RegisterNFInstance(ctx context.Context) error { return nil } -func (s *nnrfService) buildNfProfile(smfContext *smf_context.SMFContext) (profile models.NfProfile, err error) { +func (s *nnrfService) buildNfProfile(smfContext *smf_context.SMFContext) ( + profile models.NrfNfManagementNfProfile, err error, +) { smfProfile := smfContext.NfProfile - sNssais := []models.Snssai{} - for _, snssaiSmfInfo := range *smfProfile.SMFInfo.SNssaiSmfInfoList { + sNssais := []models.ExtSnssai{} + for _, snssaiSmfInfo := range smfProfile.SMFInfo.SNssaiSmfInfoList { sNssais = append(sNssais, *snssaiSmfInfo.SNssai) } // set nfProfile - profile = models.NfProfile{ + profile = models.NrfNfManagementNfProfile{ NfInstanceId: smfContext.NfInstanceID, - NfType: models.NfType_SMF, - NfStatus: models.NfStatus_REGISTERED, + NfType: models.NrfNfManagementNfType_SMF, + NfStatus: models.NrfNfManagementNfStatus_REGISTERED, Ipv4Addresses: []string{smfContext.RegisterIPv4}, - NfServices: smfProfile.NFServices, + NfServices: *smfProfile.NFServices, SmfInfo: smfProfile.SMFInfo, - SNssais: &sNssais, - PlmnList: smfProfile.PLMNList, + SNssais: sNssais, + PlmnList: *smfProfile.PLMNList, } if smfContext.Locality != "" { profile.Locality = smfContext.Locality @@ -157,56 +159,30 @@ func (s *nnrfService) buildNfProfile(smfContext *smf_context.SMFContext) (profil return profile, err } -func (s *nnrfService) RetrySendNFRegistration(maxRetry int) error { - retryCount := 0 - for retryCount < maxRetry { - err := s.RegisterNFInstance(context.Background()) - if err == nil { - return nil - } - logger.ConsumerLog.Warnf("Send NFRegistration Failed by %v", err) - retryCount++ - } - - return fmt.Errorf("[SMF] Retry NF Registration has meet maximum") -} - -func (s *nnrfService) SendDeregisterNFInstance() (problemDetails *models.ProblemDetails, err error) { +func (s *nnrfService) SendDeregisterNFInstance() (err error) { logger.ConsumerLog.Infof("Send Deregister NFInstance") smfContext := s.consumer.Context() - ctx, pd, err := smfContext.GetTokenCtx(models.ServiceName_NNRF_NFM, models.NfType_NRF) + ctx, pd, err := smfContext.GetTokenCtx(models.ServiceName_NNRF_NFM, models.NrfNfManagementNfType_NRF) if err != nil { - return pd, err + logger.ConsumerLog.Errorf("Get token context failed, problem details: %+v", pd) + return err } client := s.getNFManagementClient(smfContext.NrfUri) + request := &NFManagement.DeregisterNFInstanceRequest{ + NfInstanceID: &smfContext.NfInstanceID, + } - var res *http.Response - - res, err = client.NFInstanceIDDocumentApi.DeregisterNFInstance(ctx, smfContext.NfInstanceID) + _, err = client.NFInstanceIDDocumentApi.DeregisterNFInstance(ctx, request) - if err == nil { - return problemDetails, err - } else if res != nil { - defer func() { - if resCloseErr := res.Body.Close(); resCloseErr != nil { - logger.ConsumerLog.Errorf("DeregisterNFInstance response body cannot close: %+v", resCloseErr) - } - }() - if res.Status != err.Error() { - return problemDetails, err - } - problem := err.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - problemDetails = &problem - } else { - err = openapi.ReportError("server no response") - } - return problemDetails, err + return err } -func (s *nnrfService) SendSearchNFInstances(nrfUri string, targetNfType, requestNfType models.NfType, - param *Nnrf_NFDiscovery.SearchNFInstancesParamOpts, +func (s *nnrfService) SendSearchNFInstances( + nrfUri string, + targetNfType, requestNfType models.NrfNfManagementNfType, + param *NFDiscovery.SearchNFInstancesRequest, ) (*models.SearchResult, error) { // Set client and set url smfContext := s.consumer.Context() @@ -216,173 +192,185 @@ func (s *nnrfService) SendSearchNFInstances(nrfUri string, targetNfType, request return nil, openapi.ReportError("nrf not found") } - ctx, _, err := smfContext.GetTokenCtx(models.ServiceName_NNRF_DISC, models.NfType_NRF) + ctx, _, err := smfContext.GetTokenCtx(models.ServiceName_NNRF_DISC, models.NrfNfManagementNfType_NRF) if err != nil { return nil, err } - result, res, err := client.NFInstancesStoreApi.SearchNFInstances(ctx, targetNfType, requestNfType, param) - if err != nil { + res, err := client.NFInstancesStoreApi.SearchNFInstances(ctx, param) + if err != nil || res == nil { logger.ConsumerLog.Errorf("SearchNFInstances failed: %+v", err) + return nil, err } - defer func() { - if resCloseErr := res.Body.Close(); resCloseErr != nil { - logger.ConsumerLog.Errorf("NFInstancesStoreApi response body cannot close: %+v", resCloseErr) - } - }() - if res != nil && res.StatusCode == http.StatusTemporaryRedirect { - return nil, fmt.Errorf("temporary Redirect For Non NRF Consumer") - } + result := res.SearchResult return &result, err } -func (s *nnrfService) NFDiscoveryUDM(ctx context.Context) (result models.SearchResult, - httpResp *http.Response, localErr error, +func (s *nnrfService) NFDiscoveryUDM(ctx context.Context) ( + result models.SearchResult, localErr error, ) { - localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{} + targetNfType := models.NrfNfManagementNfType_UDM + requesterNfType := models.NrfNfManagementNfType_SMF + request := &NFDiscovery.SearchNFInstancesRequest{ + TargetNfType: &targetNfType, + RequesterNfType: &requesterNfType, + } smfContext := s.consumer.Context() client := s.getNFDiscoveryClient(smfContext.NrfUri) // Check data - result, httpResp, localErr = client.NFInstancesStoreApi. - SearchNFInstances(ctx, models.NfType_UDM, models.NfType_SMF, &localVarOptionals) - return result, httpResp, localErr + res, localErr := client.NFInstancesStoreApi.SearchNFInstances(ctx, request) + if res != nil { + result = res.SearchResult + } + return result, localErr } func (s *nnrfService) NFDiscoveryPCF(ctx context.Context) ( - result models.SearchResult, httpResp *http.Response, localErr error, + result models.SearchResult, localErr error, ) { - localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{} + targetNfType := models.NrfNfManagementNfType_PCF + requesterNfType := models.NrfNfManagementNfType_SMF + request := &NFDiscovery.SearchNFInstancesRequest{ + TargetNfType: &targetNfType, + RequesterNfType: &requesterNfType, + } smfContext := s.consumer.Context() client := s.getNFDiscoveryClient(smfContext.NrfUri) // Check data - result, httpResp, localErr = client.NFInstancesStoreApi. - SearchNFInstances(ctx, models.NfType_PCF, models.NfType_SMF, &localVarOptionals) - return result, httpResp, localErr + res, localErr := client.NFInstancesStoreApi.SearchNFInstances(ctx, request) + if res != nil { + result = res.SearchResult + } + return result, localErr } func (s *nnrfService) NFDiscoveryAMF(smContext *smf_context.SMContext, ctx context.Context) ( - result models.SearchResult, httpResp *http.Response, localErr error, + result models.SearchResult, localErr error, ) { - localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{} - - localVarOptionals.TargetNfInstanceId = optional.NewInterface(smContext.ServingNfId) + targetNfType := models.NrfNfManagementNfType_AMF + requesterNfType := models.NrfNfManagementNfType_SMF + request := &NFDiscovery.SearchNFInstancesRequest{ + TargetNfType: &targetNfType, + RequesterNfType: &requesterNfType, + TargetNfInstanceId: &smContext.ServingNfId, + } smfContext := s.consumer.Context() client := s.getNFDiscoveryClient(smfContext.NrfUri) // Check data - result, httpResp, localErr = client.NFInstancesStoreApi. - SearchNFInstances(ctx, models.NfType_AMF, models.NfType_SMF, &localVarOptionals) - return result, httpResp, localErr + res, localErr := client.NFInstancesStoreApi.SearchNFInstances(ctx, request) + if res != nil { + result = res.SearchResult + } + return result, localErr } func (s *nnrfService) SendNFDiscoveryUDM() (*models.ProblemDetails, error) { smfContext := s.consumer.Context() - ctx, pd, err := smfContext.GetTokenCtx(models.ServiceName_NNRF_DISC, models.NfType_NRF) + ctx, pd, err := smfContext.GetTokenCtx(models.ServiceName_NNRF_DISC, models.NrfNfManagementNfType_NRF) if err != nil { return pd, err } // Check data - result, httpResp, localErr := s.NFDiscoveryUDM(ctx) - - if localErr == nil { + result, localErr := s.NFDiscoveryUDM(ctx) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case NFDiscovery.SearchNFInstancesError: + return &errModel.ProblemDetails, nil + case error: + return openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, openapi.ReportError("openapi error") + } + case error: + return openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: smfContext.UDMProfile = result.NfInstances[0] - var client *Nudm_SubscriberDataManagement.APIClient - for _, service := range *smfContext.UDMProfile.NfServices { + var client *SubscriberDataManagement.APIClient + for _, service := range smfContext.UDMProfile.NfServices { if service.ServiceName == models.ServiceName_NUDM_SDM { client = s.consumer.nudmService.getSubscribeDataManagementClient(service.ApiPrefix) } } if client == nil { logger.ConsumerLog.Traceln("Get Subscribe Data Management Client Failed") - return nil, fmt.Errorf("Get Subscribe Data Management Client Failed") + return nil, fmt.Errorf("get Subscribe Data Management Client Failed") } - } else if httpResp != nil { - defer func() { - if resCloseErr := httpResp.Body.Close(); resCloseErr != nil { - logger.ConsumerLog.Errorf("SearchNFInstances response body cannot close: %+v", resCloseErr) - } - }() - logger.ConsumerLog.Warnln("handler returned wrong status code ", httpResp.Status) - if httpResp.Status != localErr.Error() { - return nil, localErr - } - problem := localErr.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - return &problem, nil - } else { + default: return nil, openapi.ReportError("server no response") } + return nil, nil } -func (s *nnrfService) SendNFDiscoveryPCF() (problemDetails *models.ProblemDetails, err error) { - ctx, pd, err := s.consumer.Context().GetTokenCtx(models.ServiceName_NNRF_DISC, models.NfType_NRF) +func (s *nnrfService) SendNFDiscoveryPCF() (*models.ProblemDetails, error) { + ctx, pd, err := s.consumer.Context().GetTokenCtx(models.ServiceName_NNRF_DISC, models.NrfNfManagementNfType_NRF) if err != nil { return pd, err } // Check data - result, httpResp, localErr := s.NFDiscoveryPCF(ctx) - - if localErr == nil { - logger.ConsumerLog.Traceln(result.NfInstances) - } else if httpResp != nil { - defer func() { - if resCloseErr := httpResp.Body.Close(); resCloseErr != nil { - logger.ConsumerLog.Errorf("SearchNFInstances response body cannot close: %+v", resCloseErr) - } - }() - logger.ConsumerLog.Warnln("handler returned wrong status code ", httpResp.Status) - if httpResp.Status != localErr.Error() { - err = localErr - return problemDetails, err + result, localErr := s.NFDiscoveryPCF(ctx) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case NFDiscovery.SearchNFInstancesError: + return &errModel.ProblemDetails, nil + case error: + return openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, openapi.ReportError("openapi error") } - problem := localErr.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - problemDetails = &problem - } else { - err = openapi.ReportError("server no response") + case error: + return openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: + logger.ConsumerLog.Traceln(result.NfInstances) + default: + return nil, openapi.ReportError("server no response") } - return problemDetails, err + return nil, nil } func (s *nnrfService) SendNFDiscoveryServingAMF(smContext *smf_context.SMContext) (*models.ProblemDetails, error) { - ctx, pd, err := s.consumer.Context().GetTokenCtx(models.ServiceName_NNRF_DISC, models.NfType_NRF) + ctx, pd, err := s.consumer.Context().GetTokenCtx(models.ServiceName_NNRF_DISC, models.NrfNfManagementNfType_NRF) if err != nil { return pd, err } // Check data - result, httpResp, localErr := s.NFDiscoveryAMF(smContext, ctx) - - if localErr == nil { + result, localErr := s.NFDiscoveryAMF(smContext, ctx) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case NFDiscovery.SearchNFInstancesError: + return &errModel.ProblemDetails, nil + case error: + return openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, openapi.ReportError("openapi error") + } + case error: + return openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: if result.NfInstances == nil { - if status := httpResp.StatusCode; status != http.StatusOK { - logger.ConsumerLog.Warnln("handler returned wrong status code", status) - } logger.ConsumerLog.Warnln("NfInstances is nil") return nil, openapi.ReportError("NfInstances is nil") } logger.ConsumerLog.Info("SendNFDiscoveryServingAMF ok") - smContext.AMFProfile = deepcopy.Copy(result.NfInstances[0]).(models.NfProfile) - } else if httpResp != nil { - defer func() { - if resCloseErr := httpResp; resCloseErr != nil { - logger.ConsumerLog.Errorf("SearchNFInstances response body cannot close: %+v", resCloseErr) - } - }() - if httpResp.Status != localErr.Error() { - return nil, localErr - } - problem := localErr.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - return &problem, nil - } else { + smContext.AMFProfile = result.NfInstances[0] + default: return nil, openapi.ReportError("server no response") } @@ -392,45 +380,33 @@ func (s *nnrfService) SendNFDiscoveryServingAMF(smContext *smf_context.SMContext // CHFSelection will select CHF for this SM Context func (s *nnrfService) CHFSelection(smContext *smf_context.SMContext) error { // Send NFDiscovery for find CHF - localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{ - // Supi: optional.NewString(smContext.Supi), + targetNfType := models.NrfNfManagementNfType_CHF + requesterNfType := models.NrfNfManagementNfType_SMF + request := &NFDiscovery.SearchNFInstancesRequest{ + TargetNfType: &targetNfType, + RequesterNfType: &requesterNfType, + // Supi: &smContext.Supi, } - ctx, _, err := s.consumer.Context().GetTokenCtx(models.ServiceName_NNRF_DISC, models.NfType_NRF) + ctx, _, err := s.consumer.Context().GetTokenCtx(models.ServiceName_NNRF_DISC, models.NrfNfManagementNfType_NRF) if err != nil { return err } client := s.getNFDiscoveryClient(s.consumer.Context().NrfUri) // Check data - rsp, res, err := client.NFInstancesStoreApi. - SearchNFInstances(ctx, models.NfType_CHF, models.NfType_SMF, &localVarOptionals) + res, err := client.NFInstancesStoreApi.SearchNFInstances(ctx, request) if err != nil { logger.ConsumerLog.Errorf("SearchNFInstances failed: %+v", err) return err } - defer func() { - if rspCloseErr := res.Body.Close(); rspCloseErr != nil { - logger.PduSessLog.Errorf("SmfEventExposureNotification response body cannot close: %+v", rspCloseErr) - } - }() - - if res != nil { - if status := res.StatusCode; status != http.StatusOK { - apiError := err.(openapi.GenericOpenAPIError) - problemDetails := apiError.Model().(models.ProblemDetails) - - logger.CtxLog.Warningf("NFDiscovery return status: %d\n", status) - logger.CtxLog.Warningf("Detail: %v\n", problemDetails.Title) - } - } // Select CHF from available CHF - if len(rsp.NfInstances) > 0 { - smContext.SelectedCHFProfile = rsp.NfInstances[0] + if res != nil && len(res.SearchResult.NfInstances) > 0 { + smContext.SelectedCHFProfile = res.SearchResult.NfInstances[0] return nil } - return fmt.Errorf("No CHF found in CHFSelection") + return fmt.Errorf("no CHF found in CHFSelection") } // PCFSelection will select PCF for this SM Context @@ -440,58 +416,47 @@ func (s *nnrfService) PCFSelection(smContext *smf_context.SMContext) error { return errToken } // Send NFDiscovery for find PCF - localVarOptionals := Nnrf_NFDiscovery.SearchNFInstancesParamOpts{} + targetNfType := models.NrfNfManagementNfType_PCF + requesterNfType := models.NrfNfManagementNfType_SMF + request := &NFDiscovery.SearchNFInstancesRequest{ + TargetNfType: &targetNfType, + RequesterNfType: &requesterNfType, + } if s.consumer.Context().Locality != "" { - localVarOptionals.PreferredLocality = optional.NewString(s.consumer.Context().Locality) + request.PreferredLocality = &s.consumer.Context().Locality } client := s.getNFDiscoveryClient(s.consumer.Context().NrfUri) // Check data - rsp, res, err := client.NFInstancesStoreApi. - SearchNFInstances(ctx, models.NfType_PCF, models.NfType_SMF, &localVarOptionals) + res, err := client.NFInstancesStoreApi.SearchNFInstances(ctx, request) if err != nil { return err } - defer func() { - if rspCloseErr := res.Body.Close(); rspCloseErr != nil { - logger.PduSessLog.Errorf("SmfEventExposureNotification response body cannot close: %+v", rspCloseErr) - } - }() - - if res != nil { - if status := res.StatusCode; status != http.StatusOK { - apiError := err.(openapi.GenericOpenAPIError) - problemDetails := apiError.Model().(models.ProblemDetails) - - logger.CtxLog.Warningf("NFDiscovery PCF return status: %d\n", status) - logger.CtxLog.Warningf("Detail: %v\n", problemDetails.Title) - } - } // Select PCF from available PCF - smContext.SelectedPCFProfile = rsp.NfInstances[0] + smContext.SelectedPCFProfile = res.SearchResult.NfInstances[0] return nil } -func (s *nnrfService) SearchNFInstances(ctx context.Context, targetNfType models.NfType, requesterNfType models.NfType, - localVarOptionals *Nnrf_NFDiscovery.SearchNFInstancesParamOpts, -) (*models.SearchResult, *http.Response, error) { +func (s *nnrfService) SearchNFInstances( + ctx context.Context, + targetNfType, requesterNfType models.NrfNfManagementNfType, + localVarOptionals *NFDiscovery.SearchNFInstancesRequest, +) (*models.SearchResult, error) { client := s.getNFDiscoveryClient(s.consumer.Context().NrfUri) - rsp, res, err := client.NFInstancesStoreApi. - SearchNFInstances(ctx, models.NfType_CHF, models.NfType_SMF, localVarOptionals) - if err != nil { - return nil, nil, err + request := &NFDiscovery.SearchNFInstancesRequest{ + TargetNfType: &targetNfType, + RequesterNfType: &requesterNfType, } - defer func() { - if rspCloseErr := res.Body.Close(); rspCloseErr != nil { - logger.PduSessLog.Errorf("SmfEventExposureNotification response body cannot close: %+v", rspCloseErr) - } - }() + res, err := client.NFInstancesStoreApi.SearchNFInstances(ctx, request) + if err != nil { + return nil, err + } - return &rsp, res, err + return &res.SearchResult, err } diff --git a/internal/sbi/consumer/pcf_service.go b/internal/sbi/consumer/pcf_service.go index a8cede8e..386eb76c 100644 --- a/internal/sbi/consumer/pcf_service.go +++ b/internal/sbi/consumer/pcf_service.go @@ -12,10 +12,9 @@ import ( "github.com/free5gc/nas/nasConvert" "github.com/free5gc/nas/nasType" - "github.com/free5gc/openapi/Npcf_SMPolicyControl" "github.com/free5gc/openapi/models" + "github.com/free5gc/openapi/pcf/SMPolicyControl" smf_context "github.com/free5gc/smf/internal/context" - "github.com/free5gc/smf/internal/logger" "github.com/free5gc/util/flowdesc" ) @@ -24,10 +23,10 @@ type npcfService struct { SMPolicyControlMu sync.RWMutex - SMPolicyControlClients map[string]*Npcf_SMPolicyControl.APIClient + SMPolicyControlClients map[string]*SMPolicyControl.APIClient } -func (s *npcfService) getSMPolicyControlClient(uri string) *Npcf_SMPolicyControl.APIClient { +func (s *npcfService) getSMPolicyControlClient(uri string) *SMPolicyControl.APIClient { if uri == "" { return nil } @@ -38,9 +37,9 @@ func (s *npcfService) getSMPolicyControlClient(uri string) *Npcf_SMPolicyControl return client } - configuration := Npcf_SMPolicyControl.NewConfiguration() + configuration := SMPolicyControl.NewConfiguration() configuration.SetBasePath(uri) - client = Npcf_SMPolicyControl.NewAPIClient(configuration) + client = SMPolicyControl.NewAPIClient(configuration) s.SMPolicyControlMu.RUnlock() s.SMPolicyControlMu.Lock() @@ -53,10 +52,10 @@ func (s *npcfService) getSMPolicyControlClient(uri string) *Npcf_SMPolicyControl func (s *npcfService) SendSMPolicyAssociationCreate(smContext *smf_context.SMContext) ( string, *models.SmPolicyDecision, error, ) { - var client *Npcf_SMPolicyControl.APIClient + var client *SMPolicyControl.APIClient // Create SMPolicyControl Client for this SM Context - for _, service := range *smContext.SelectedPCFProfile.NfServices { + for _, service := range smContext.SelectedPCFProfile.NfServices { if service.ServiceName == models.ServiceName_NPCF_SMPOLICYCONTROL { client = s.getSMPolicyControlClient(service.ApiPrefix) } @@ -84,34 +83,31 @@ func (s *npcfService) SendSMPolicyAssociationCreate(smContext *smf_context.SMCon smPolicyData.SubsSessAmbr = smContext.DnnConfiguration.SessionAmbr smPolicyData.SubsDefQos = smContext.DnnConfiguration.Var5gQosProfile smPolicyData.SliceInfo = smContext.SNssai - smPolicyData.ServingNetwork = &models.NetworkId{ + smPolicyData.ServingNetwork = &models.PlmnIdNid{ Mcc: smContext.ServingNetwork.Mcc, Mnc: smContext.ServingNetwork.Mnc, } smPolicyData.SuppFeat = "F" - ctx, _, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NPCF_SMPOLICYCONTROL, models.NfType_PCF) + ctx, _, err := smf_context.GetSelf(). + GetTokenCtx(models.ServiceName_NPCF_SMPOLICYCONTROL, models.NrfNfManagementNfType_PCF) if err != nil { return "", nil, err } var smPolicyID string var smPolicyDecision *models.SmPolicyDecision - smPolicyDecisionFromPCF, httpRsp, err := client.DefaultApi. - SmPoliciesPost(ctx, smPolicyData) - defer func() { - if httpRsp != nil { - if closeErr := httpRsp.Body.Close(); closeErr != nil { - logger.PduSessLog.Errorf("rsp body close err: %v", closeErr) - } - } - }() - if err != nil { + request := &SMPolicyControl.CreateSMPolicyRequest{ + SmPolicyContextData: &smPolicyData, + } + + smPolicyDecisionFromPCF, err := client.SMPoliciesCollectionApi.CreateSMPolicy(ctx, request) + if err != nil || smPolicyDecisionFromPCF == nil { return "", nil, err } - smPolicyDecision = &smPolicyDecisionFromPCF - loc := httpRsp.Header.Get("Location") + smPolicyDecision = &smPolicyDecisionFromPCF.SmPolicyDecision + loc := smPolicyDecisionFromPCF.Location if smPolicyID = s.extractSMPolicyIDFromLocation(loc); len(smPolicyID) == 0 { return "", nil, fmt.Errorf("SMPolicy ID parse failed") } @@ -198,34 +194,32 @@ func (s *npcfService) SendSMPolicyAssociationUpdateByUERequestModification( } } - ctx, _, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NPCF_SMPOLICYCONTROL, models.NfType_PCF) + ctx, _, err := smf_context.GetSelf(). + GetTokenCtx(models.ServiceName_NPCF_SMPOLICYCONTROL, models.NrfNfManagementNfType_PCF) if err != nil { return nil, err } - var client *Npcf_SMPolicyControl.APIClient + var client *SMPolicyControl.APIClient // Create SMPolicyControl Client for this SM Context - for _, service := range *smContext.SelectedPCFProfile.NfServices { + for _, service := range smContext.SelectedPCFProfile.NfServices { if service.ServiceName == models.ServiceName_NPCF_SMPOLICYCONTROL { client = s.getSMPolicyControlClient(service.ApiPrefix) } } var smPolicyDecision *models.SmPolicyDecision - smPolicyDecisionFromPCF, rsp, err := client. - DefaultApi.SmPoliciesSmPolicyIdUpdatePost(ctx, smContext.SMPolicyID, updateSMPolicy) - defer func() { - if rsp != nil { - if closeErr := rsp.Body.Close(); closeErr != nil { - logger.PduSessLog.Errorf("rsp body close err: %v", closeErr) - } - } - }() + request := &SMPolicyControl.UpdateSMPolicyRequest{ + SmPolicyId: &smContext.SMPolicyID, + SmPolicyUpdateContextData: &updateSMPolicy, + } + + smPolicyDecisionFromPCF, err := client.IndividualSMPolicyDocumentApi.UpdateSMPolicy(ctx, request) if err != nil { return nil, fmt.Errorf("update sm policy [%s] association failed: %s", smContext.SMPolicyID, err) } - smPolicyDecision = &smPolicyDecisionFromPCF + smPolicyDecision = &smPolicyDecisionFromPCF.SmPolicyDecision return smPolicyDecision, nil } @@ -429,10 +423,10 @@ func (s *npcfService) buildPktFilterInfo(pf nasType.PacketFilter) (*models.Packe } func (s *npcfService) SendSMPolicyAssociationTermination(smContext *smf_context.SMContext) error { - var client *Npcf_SMPolicyControl.APIClient + var client *SMPolicyControl.APIClient // Create SMPolicyControl Client for this SM Context - for _, service := range *smContext.SelectedPCFProfile.NfServices { + for _, service := range smContext.SelectedPCFProfile.NfServices { if service.ServiceName == models.ServiceName_NPCF_SMPOLICYCONTROL { client = s.getSMPolicyControlClient(service.ApiPrefix) } @@ -442,20 +436,18 @@ func (s *npcfService) SendSMPolicyAssociationTermination(smContext *smf_context. return errors.Errorf("smContext not selected PCF") } - ctx, _, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NPCF_SMPOLICYCONTROL, models.NfType_PCF) + ctx, _, err := smf_context.GetSelf(). + GetTokenCtx(models.ServiceName_NPCF_SMPOLICYCONTROL, models.NrfNfManagementNfType_PCF) if err != nil { return err } - rsp, err := client.DefaultApi.SmPoliciesSmPolicyIdDeletePost( - ctx, smContext.SMPolicyID, models.SmPolicyDeleteData{}) - defer func() { - if rsp != nil { - if closeErr := rsp.Body.Close(); closeErr != nil { - logger.PduSessLog.Errorf("rsp body close err: %v", closeErr) - } - } - }() + request := &SMPolicyControl.DeleteSMPolicyRequest{ + SmPolicyId: &smContext.SMPolicyID, + SmPolicyDeleteData: &models.SmPolicyDeleteData{}, + } + + _, err = client.IndividualSMPolicyDocumentApi.DeleteSMPolicy(ctx, request) if err != nil { return fmt.Errorf("SM Policy termination failed: %v", err) } diff --git a/internal/sbi/consumer/smf_service.go b/internal/sbi/consumer/smf_service.go index e4b068be..a0dfb7cb 100644 --- a/internal/sbi/consumer/smf_service.go +++ b/internal/sbi/consumer/smf_service.go @@ -2,12 +2,11 @@ package consumer import ( "context" - "net/http" "sync" "github.com/free5gc/openapi" - "github.com/free5gc/openapi/Nsmf_PDUSession" "github.com/free5gc/openapi/models" + "github.com/free5gc/openapi/smf/PDUSession" "github.com/free5gc/smf/internal/logger" ) @@ -16,10 +15,10 @@ type nsmfService struct { PDUSessionMu sync.RWMutex - PDUSessionClients map[string]*Nsmf_PDUSession.APIClient + PDUSessionClients map[string]*PDUSession.APIClient } -func (s *nsmfService) getPDUSessionClient(uri string) *Nsmf_PDUSession.APIClient { +func (s *nsmfService) getPDUSessionClient(uri string) *PDUSession.APIClient { if uri == "" { return nil } @@ -30,9 +29,9 @@ func (s *nsmfService) getPDUSessionClient(uri string) *Nsmf_PDUSession.APIClient return client } - configuration := Nsmf_PDUSession.NewConfiguration() + configuration := PDUSession.NewConfiguration() configuration.SetBasePath(uri) - client = Nsmf_PDUSession.NewAPIClient(configuration) + client = PDUSession.NewAPIClient(configuration) s.PDUSessionMu.RUnlock() s.PDUSessionMu.Lock() @@ -43,39 +42,38 @@ func (s *nsmfService) getPDUSessionClient(uri string) *Nsmf_PDUSession.APIClient func (s *nsmfService) SendSMContextStatusNotification(uri string) (*models.ProblemDetails, error) { if uri != "" { - request := models.SmContextStatusNotification{} - request.StatusInfo = &models.StatusInfo{ - ResourceStatus: models.ResourceStatus_RELEASED, + request := &PDUSession.PostSmContextsSmContextStatusNotificationPostRequest{ + SmfPduSessionSmContextStatusNotification: &models.SmfPduSessionSmContextStatusNotification{ + StatusInfo: &models.StatusInfo{ + ResourceStatus: models.ResourceStatus_RELEASED, + }, + }, } client := s.getPDUSessionClient(uri) logger.CtxLog.Infoln("[SMF] Send SMContext Status Notification") - httpResp, localErr := client. - IndividualSMContextNotificationApi. - SMContextNotification(context.Background(), uri, request) + _, localErr := client.SMContextsCollectionApi. + PostSmContextsSmContextStatusNotificationPost(context.Background(), uri, request) - if localErr == nil { - if httpResp.StatusCode != http.StatusNoContent { - return nil, openapi.ReportError("Send SMContextStatus Notification Failed") + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case PDUSession.PostSmContextsSmContextStatusNotificationPostError: + return &errModel.ProblemDetails, nil + case error: + return openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, openapi.ReportError("openapi error") } - + case error: + return openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: logger.PduSessLog.Tracef("Send SMContextStatus Notification Success") - } else if httpResp != nil { - defer func() { - if resCloseErr := httpResp.Body.Close(); resCloseErr != nil { - logger.ConsumerLog.Errorf("SMContextNotification response body cannot close: %+v", resCloseErr) - } - }() - logger.PduSessLog.Warnf("Send SMContextStatus Notification Error[%s]", httpResp.Status) - if httpResp.Status != localErr.Error() { - return nil, localErr - } - problem := localErr.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - return &problem, nil - } else { - logger.PduSessLog.Warnln("Http Response is nil in comsumer API SMContextNotification") - return nil, openapi.ReportError("Send SMContextStatus Notification Failed[%s]", localErr.Error()) + return nil, nil + default: + logger.PduSessLog.Warnf("Send SMContextStatus Notification Unknown Error: %+v", err) + return nil, openapi.ReportError("server no response") } } return nil, nil diff --git a/internal/sbi/consumer/udm_service.go b/internal/sbi/consumer/udm_service.go index 64b3e73c..51d93dea 100644 --- a/internal/sbi/consumer/udm_service.go +++ b/internal/sbi/consumer/udm_service.go @@ -3,15 +3,14 @@ package consumer import ( "context" "fmt" - "net/http" "sync" "github.com/pkg/errors" "github.com/free5gc/openapi" - "github.com/free5gc/openapi/Nudm_SubscriberDataManagement" - "github.com/free5gc/openapi/Nudm_UEContextManagement" "github.com/free5gc/openapi/models" + "github.com/free5gc/openapi/udm/SubscriberDataManagement" + "github.com/free5gc/openapi/udm/UEContextManagement" smf_context "github.com/free5gc/smf/internal/context" "github.com/free5gc/smf/internal/logger" "github.com/free5gc/smf/internal/util" @@ -23,11 +22,11 @@ type nudmService struct { SubscriberDataManagementMu sync.RWMutex UEContextManagementMu sync.RWMutex - SubscriberDataManagementClients map[string]*Nudm_SubscriberDataManagement.APIClient - UEContextManagementClients map[string]*Nudm_UEContextManagement.APIClient + SubscriberDataManagementClients map[string]*SubscriberDataManagement.APIClient + UEContextManagementClients map[string]*UEContextManagement.APIClient } -func (s *nudmService) getSubscribeDataManagementClient(uri string) *Nudm_SubscriberDataManagement.APIClient { +func (s *nudmService) getSubscribeDataManagementClient(uri string) *SubscriberDataManagement.APIClient { if uri == "" { return nil } @@ -38,9 +37,9 @@ func (s *nudmService) getSubscribeDataManagementClient(uri string) *Nudm_Subscri return client } - configuration := Nudm_SubscriberDataManagement.NewConfiguration() + configuration := SubscriberDataManagement.NewConfiguration() configuration.SetBasePath(uri) - client = Nudm_SubscriberDataManagement.NewAPIClient(configuration) + client = SubscriberDataManagement.NewAPIClient(configuration) s.SubscriberDataManagementMu.RUnlock() s.SubscriberDataManagementMu.Lock() @@ -49,7 +48,7 @@ func (s *nudmService) getSubscribeDataManagementClient(uri string) *Nudm_Subscri return client } -func (s *nudmService) getUEContextManagementClient(uri string) *Nudm_UEContextManagement.APIClient { +func (s *nudmService) getUEContextManagementClient(uri string) *UEContextManagement.APIClient { if uri == "" { return nil } @@ -60,9 +59,9 @@ func (s *nudmService) getUEContextManagementClient(uri string) *Nudm_UEContextMa return client } - configuration := Nudm_UEContextManagement.NewConfiguration() + configuration := UEContextManagement.NewConfiguration() configuration.SetBasePath(uri) - client = Nudm_UEContextManagement.NewAPIClient(configuration) + client = UEContextManagement.NewAPIClient(configuration) s.UEContextManagementMu.RUnlock() s.UEContextManagementMu.Lock() @@ -76,7 +75,7 @@ func (s *nudmService) UeCmRegistration(smCtx *smf_context.SMContext) ( ) { smfContext := s.consumer.Context() - uecmUri := util.SearchNFServiceUri(smfContext.UDMProfile, models.ServiceName_NUDM_UECM, + uecmUri := util.SearchNFServiceUri(&smfContext.UDMProfile, models.ServiceName_NUDM_UECM, models.NfServiceStatus_REGISTERED) if uecmUri == "" { return nil, errors.Errorf("SMF can not select an UDM by NRF: SearchNFServiceUri failed") @@ -92,40 +91,47 @@ func (s *nudmService) UeCmRegistration(smCtx *smf_context.SMContext) ( Dnn: smCtx.Dnn, EmergencyServices: false, PcscfRestorationCallbackUri: "", - PlmnId: smCtx.Guami.PlmnId, - PgwFqdn: "", + PlmnId: &models.PlmnId{ + Mcc: smCtx.Guami.PlmnId.Mcc, + Mnc: smCtx.Guami.PlmnId.Mnc, + }, + PgwFqdn: "", } logger.PduSessLog.Infoln("UECM Registration SmfInstanceId:", registrationData.SmfInstanceId, " PduSessionId:", registrationData.PduSessionId, " SNssai:", registrationData.SingleNssai, " Dnn:", registrationData.Dnn, " PlmnId:", registrationData.PlmnId) - ctx, pd, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_UECM, models.NfType_UDM) + ctx, pd, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_UECM, models.NrfNfManagementNfType_UDM) if err != nil { return pd, err } - _, httpResp, localErr := client.SMFRegistrationApi.SmfRegistrationsPduSessionId(ctx, - smCtx.Supi, smCtx.PduSessionId, registrationData) - defer func() { - if httpResp != nil { - if rspCloseErr := httpResp.Body.Close(); rspCloseErr != nil { - logger.PduSessLog.Errorf("UeCmRegistration response body cannot close: %+v", - rspCloseErr) - } - } - }() + request := &UEContextManagement.RegistrationRequest{ + UeId: &smCtx.Supi, + PduSessionId: &smCtx.PduSessionId, + SmfRegistration: ®istrationData, + } - if localErr == nil { + _, localErr := client.SMFSmfRegistrationApi.Registration(ctx, request) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case UEContextManagement.RegistrationError: + return &errModel.ProblemDetails, nil + case error: + return openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, openapi.ReportError("openapi error") + } + case error: + return openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: + logger.PduSessLog.Tracef("UECM Registration Success") smCtx.UeCmRegistered = true return nil, nil - } else if httpResp != nil { - if httpResp.Status != localErr.Error() { - return nil, localErr - } - problem := localErr.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - return &problem, nil - } else { + default: return nil, openapi.ReportError("server no response") } } @@ -133,48 +139,52 @@ func (s *nudmService) UeCmRegistration(smCtx *smf_context.SMContext) ( func (s *nudmService) UeCmDeregistration(smCtx *smf_context.SMContext) (*models.ProblemDetails, error) { smfContext := s.consumer.Context() - uecmUri := util.SearchNFServiceUri(smfContext.UDMProfile, models.ServiceName_NUDM_UECM, + uecmUri := util.SearchNFServiceUri(&smfContext.UDMProfile, models.ServiceName_NUDM_UECM, models.NfServiceStatus_REGISTERED) if uecmUri == "" { return nil, errors.Errorf("SMF can not select an UDM by NRF: SearchNFServiceUri failed") } client := s.getUEContextManagementClient(uecmUri) - ctx, pd, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_UECM, models.NfType_UDM) + ctx, pd, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_UECM, models.NrfNfManagementNfType_UDM) if err != nil { return pd, err } - httpResp, localErr := client.SMFDeregistrationApi.Deregistration(ctx, - smCtx.Supi, smCtx.PduSessionId) - defer func() { - if httpResp != nil { - if rspCloseErr := httpResp.Body.Close(); rspCloseErr != nil { - logger.ConsumerLog.Errorf("UeCmDeregistration response body cannot close: %+v", - rspCloseErr) - } + request := &UEContextManagement.SmfDeregistrationRequest{ + UeId: &smCtx.Supi, + PduSessionId: &smCtx.PduSessionId, + } + + _, localErr := client.SMFDeregistrationApi.SmfDeregistration(ctx, request) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case UEContextManagement.SmfDeregistrationError: + return &errModel.ProblemDetails, nil + case error: + return openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, openapi.ReportError("openapi error") } - }() - if localErr == nil { + case error: + return openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: + logger.PduSessLog.Tracef("UECM Deregistration Success") smCtx.UeCmRegistered = false return nil, nil - } else if httpResp != nil { - if httpResp.Status != localErr.Error() { - return nil, localErr - } - problem := localErr.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - return &problem, nil - } else { + default: return nil, openapi.ReportError("server no response") } } func (s *nudmService) GetSmData(ctx context.Context, supi string, - localVarOptionals *Nudm_SubscriberDataManagement.GetSmDataParamOpts) ( - []models.SessionManagementSubscriptionData, *http.Response, error, + request *SubscriberDataManagement.GetSmDataRequest) ( + []models.SessionManagementSubscriptionData, error, ) { - var client *Nudm_SubscriberDataManagement.APIClient - for _, service := range *s.consumer.Context().UDMProfile.NfServices { + var client *SubscriberDataManagement.APIClient + for _, service := range s.consumer.Context().UDMProfile.NfServices { if service.ServiceName == models.ServiceName_NUDM_SDM { client = s.getSubscribeDataManagementClient(service.ApiPrefix) if client != nil { @@ -184,28 +194,25 @@ func (s *nudmService) GetSmData(ctx context.Context, supi string, } if client == nil { - return nil, nil, fmt.Errorf("sdm client failed") + return nil, fmt.Errorf("sdm client failed") } - sessSubData, rsp, err := client.SessionManagementSubscriptionDataRetrievalApi.GetSmData(ctx, supi, localVarOptionals) + request.Supi = &supi + + rsp, err := client.SessionManagementSubscriptionDataRetrievalApi.GetSmData(ctx, request) if err != nil { - return nil, nil, err + return nil, err } + sessSubData := rsp.SmSubsData - defer func() { - if rspCloseErr := rsp.Body.Close(); rspCloseErr != nil { - logger.ConsumerLog.Errorf("GetSmData response body cannot close: %+v", rspCloseErr) - } - }() - - return sessSubData, rsp, err + return sessSubData, err } -func (s *nudmService) Subscribe(ctx context.Context, smCtx *smf_context.SMContext, smPlmnID *models.PlmnId) ( +func (s *nudmService) Subscribe(ctx context.Context, smCtx *smf_context.SMContext, smPlmnID *models.PlmnIdNid) ( *models.ProblemDetails, error, ) { - var client *Nudm_SubscriberDataManagement.APIClient - for _, service := range *s.consumer.Context().UDMProfile.NfServices { + var client *SubscriberDataManagement.APIClient + for _, service := range s.consumer.Context().UDMProfile.NfServices { if service.ServiceName == models.ServiceName_NUDM_SDM { client = s.getSubscribeDataManagementClient(service.ApiPrefix) if client != nil { @@ -218,51 +225,53 @@ func (s *nudmService) Subscribe(ctx context.Context, smCtx *smf_context.SMContex return nil, fmt.Errorf("sdm client failed") } - sdmSubscription := models.SdmSubscription{ - NfInstanceId: s.consumer.Context().NfInstanceID, - PlmnId: smPlmnID, + request := &SubscriberDataManagement.SubscribeRequest{ + UeId: &smCtx.Supi, + SdmSubscription: &models.SdmSubscription{ + NfInstanceId: s.consumer.Context().NfInstanceID, + PlmnId: &models.PlmnId{ + Mcc: smPlmnID.Mcc, + Mnc: smPlmnID.Mnc, + }, + }, } - resSubscription, httpResp, localErr := client.SubscriptionCreationApi.Subscribe( - ctx, smCtx.Supi, sdmSubscription) - defer func() { - if httpResp != nil { - if rspCloseErr := httpResp.Body.Close(); rspCloseErr != nil { - logger.ConsumerLog.Errorf("Subscribe response body cannot close: %+v", - rspCloseErr) - } + res, localErr := client.SubscriptionCreationApi.Subscribe(ctx, request) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case SubscriberDataManagement.SubscribeError: + return &errModel.ProblemDetails, nil + case error: + return openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, openapi.ReportError("openapi error") } - }() - - if localErr == nil { - s.consumer.Context().Ues.SetSubscriptionId(smCtx.Supi, resSubscription.SubscriptionId) + case error: + return openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: + s.consumer.Context().Ues.SetSubscriptionId(smCtx.Supi, res.SdmSubscription.SubscriptionId) logger.PduSessLog.Infoln("SDM Subscription Successful UE:", smCtx.Supi, "SubscriptionId:", - resSubscription.SubscriptionId) - } else if httpResp != nil { - if httpResp.Status != localErr.Error() { - return nil, localErr - } - problem := localErr.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - return &problem, nil - } else { + res.SdmSubscription.SubscriptionId) + s.consumer.Context().Ues.IncrementPduSessionCount(smCtx.Supi) + return nil, nil + default: return nil, openapi.ReportError("server no response") } - - s.consumer.Context().Ues.IncrementPduSessionCount(smCtx.Supi) - return nil, nil } func (s *nudmService) UnSubscribe(smCtx *smf_context.SMContext) ( *models.ProblemDetails, error, ) { - ctx, _, oauthErr := s.consumer.Context().GetTokenCtx(models.ServiceName_NUDM_SDM, models.NfType_UDM) - if oauthErr != nil { - return nil, fmt.Errorf("Get Token Context Error[%v]", oauthErr) + ctx, _, err := s.consumer.Context().GetTokenCtx(models.ServiceName_NUDM_SDM, models.NrfNfManagementNfType_UDM) + if err != nil { + return nil, err } if s.consumer.Context().Ues.IsLastPduSession(smCtx.Supi) { - var client *Nudm_SubscriberDataManagement.APIClient - for _, service := range *s.consumer.Context().UDMProfile.NfServices { + var client *SubscriberDataManagement.APIClient + for _, service := range s.consumer.Context().UDMProfile.NfServices { if service.ServiceName == models.ServiceName_NUDM_SDM { client = s.getSubscribeDataManagementClient(service.ApiPrefix) if client != nil { @@ -277,28 +286,33 @@ func (s *nudmService) UnSubscribe(smCtx *smf_context.SMContext) ( subscriptionId := s.consumer.Context().Ues.GetSubscriptionId(smCtx.Supi) - httpResp, localErr := client.SubscriptionDeletionApi.Unsubscribe(ctx, smCtx.Supi, subscriptionId) - defer func() { - if httpResp != nil { - if rspCloseErr := httpResp.Body.Close(); rspCloseErr != nil { - logger.PduSessLog.Errorf("Unsubscribe response body cannot close: %+v", - rspCloseErr) - } + request := &SubscriberDataManagement.UnsubscribeRequest{ + UeId: &smCtx.Supi, + SubscriptionId: &subscriptionId, + } + + _, localErr := client.SubscriptionDeletionApi.Unsubscribe(ctx, request) + + switch err := localErr.(type) { + case openapi.GenericOpenAPIError: + switch errModel := err.Model().(type) { + case SubscriberDataManagement.UnsubscribeError: + return &errModel.ProblemDetails, nil + case error: + return openapi.ProblemDetailsSystemFailure(errModel.Error()), nil + default: + return nil, openapi.ReportError("openapi error") } - }() - if localErr == nil { + case error: + return openapi.ProblemDetailsSystemFailure(err.Error()), nil + case nil: logger.PduSessLog.Infoln("SDM UnSubscription Successful UE:", smCtx.Supi, "SubscriptionId:", subscriptionId) - } else if httpResp != nil { - if httpResp.Status != localErr.Error() { - return nil, localErr - } - problem := localErr.(openapi.GenericOpenAPIError).Model().(models.ProblemDetails) - return &problem, nil - } else { + s.consumer.Context().Ues.DeleteUe(smCtx.Supi) + return nil, nil + default: return nil, openapi.ReportError("server no response") } - s.consumer.Context().Ues.DeleteUe(smCtx.Supi) } else { s.consumer.Context().Ues.DecrementPduSessionCount(smCtx.Supi) } diff --git a/internal/sbi/processor/association.go b/internal/sbi/processor/association.go index 7a0306f1..c64a3cd7 100644 --- a/internal/sbi/processor/association.go +++ b/internal/sbi/processor/association.go @@ -3,7 +3,6 @@ package processor import ( "context" "fmt" - "net/http" "time" "github.com/free5gc/nas/nasMessage" @@ -216,7 +215,7 @@ func (p *Processor) requestAMFToReleasePDUResources( SmInfo: &models.N2SmInformation{ PduSessionId: smContext.PDUSessionID, N2InfoContent: &models.N2InfoContent{ - NgapIeType: models.NgapIeType_PDU_RES_REL_CMD, + NgapIeType: models.AmfCommunicationNgapIeType_PDU_RES_REL_CMD, NgapData: &models.RefToBinaryData{ ContentId: "N2SmInformation", }, @@ -227,20 +226,19 @@ func (p *Processor) requestAMFToReleasePDUResources( } } - ctx, _, errToken := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NfType_AMF) + ctx, _, errToken := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NrfNfManagementNfType_AMF) if errToken != nil { return false, false } - rspData, statusCode, err := p.Consumer(). + rspData, err := p.Consumer(). N1N2MessageTransfer(ctx, smContext.Supi, n1n2Request, smContext.CommunicationClientApiPrefix) - if err != nil { - logger.ConsumerLog.Warnf("N1N2MessageTransfer for RequestAMFToReleasePDUResources failed: %+v", err) - return false, true - } - switch *statusCode { - case http.StatusOK: + if err != nil || rspData == nil { + logger.ConsumerLog.Warnf("N1N2MessageTransfer for RequestAMFToReleasePDUResources failed: %+v", err) + // keep SM Context to avoid inconsistency with AMF + smContext.SetState(smf_context.InActive) + } else { if rspData.Cause == models.N1N2MessageTransferCause_N1_MSG_NOT_TRANSFERRED { // the PDU Session Release Command was not transferred to the UE since it is in CM-IDLE state. // ref. step3b of "4.3.4.2 UE or network requested PDU Session Release for Non-Roaming and @@ -256,13 +254,6 @@ func (p *Processor) requestAMFToReleasePDUResources( // keep SM Context to avoid inconsistency with AMF smContext.SetState(smf_context.InActive) } - case http.StatusNotFound: - // it is not needed to notify AMF, but needed to remove SM Context in SMF immediately - smContext.SetState(smf_context.InActive) - return false, true - default: - // keep SM Context to avoid inconsistency with AMF - smContext.SetState(smf_context.InActive) } return false, false } diff --git a/internal/sbi/processor/charging_trigger.go b/internal/sbi/processor/charging_trigger.go index e157cf5c..04ebd6d1 100644 --- a/internal/sbi/processor/charging_trigger.go +++ b/internal/sbi/processor/charging_trigger.go @@ -23,9 +23,9 @@ func (p *Processor) CreateChargingSession(smContext *smf_context.SMContext) { } func (p *Processor) UpdateChargingSession( - smContext *smf_context.SMContext, urrList []*smf_context.URR, trigger models.Trigger, + smContext *smf_context.SMContext, urrList []*smf_context.URR, trigger models.ChfConvergedChargingTrigger, ) { - var multipleUnitUsage []models.MultipleUnitUsage + var multipleUnitUsage []models.ChfConvergedChargingMultipleUnitUsage for _, urr := range urrList { if chgInfo := smContext.ChargingInfo[urr.URRID]; chgInfo != nil { @@ -34,16 +34,16 @@ func (p *Processor) UpdateChargingSession( urr.URRID, rg, chgInfo.ChargingMethod) triggerTime := time.Now() - uu := models.UsedUnitContainer{ + uu := models.ChfConvergedChargingUsedUnitContainer{ QuotaManagementIndicator: chgInfo.ChargingMethod, - Triggers: []models.Trigger{trigger}, + Triggers: []models.ChfConvergedChargingTrigger{trigger}, TriggerTimestamp: &triggerTime, } - muu := models.MultipleUnitUsage{ + muu := models.ChfConvergedChargingMultipleUnitUsage{ RatingGroup: rg, UPFID: chgInfo.UpfId, - UsedUnitContainer: []models.UsedUnitContainer{uu}, + UsedUnitContainer: []models.ChfConvergedChargingUsedUnitContainer{uu}, } multipleUnitUsage = append(multipleUnitUsage, muu) @@ -148,16 +148,18 @@ func (p *Processor) ReportUsageAndUpdateQuota(smContext *smf_context.SMContext) } } -func buildMultiUnitUsageFromUsageReport(smContext *smf_context.SMContext) []models.MultipleUnitUsage { +func buildMultiUnitUsageFromUsageReport( + smContext *smf_context.SMContext, +) []models.ChfConvergedChargingMultipleUnitUsage { logger.ChargingLog.Infof("build MultiUnitUsageFromUsageReport") - var ratingGroupUnitUsagesMap map[int32]models.MultipleUnitUsage - var multipleUnitUsage []models.MultipleUnitUsage + var ratingGroupUnitUsagesMap map[int32]models.ChfConvergedChargingMultipleUnitUsage + var multipleUnitUsage []models.ChfConvergedChargingMultipleUnitUsage - ratingGroupUnitUsagesMap = make(map[int32]models.MultipleUnitUsage) + ratingGroupUnitUsagesMap = make(map[int32]models.ChfConvergedChargingMultipleUnitUsage) for _, ur := range smContext.UrrReports { if ur.ReportTpye != "" { - var triggers []models.Trigger + var triggers []models.ChfConvergedChargingTrigger chgInfo := smContext.ChargingInfo[ur.UrrId] if chgInfo == nil { @@ -165,15 +167,16 @@ func buildMultiUnitUsageFromUsageReport(smContext *smf_context.SMContext) []mode continue } - if chgInfo.ChargingLevel == smf_context.FlowCharging && ur.ReportTpye == models.TriggerType_VOLUME_LIMIT { - triggers = []models.Trigger{ + if chgInfo.ChargingLevel == smf_context.FlowCharging && + ur.ReportTpye == models.ChfConvergedChargingTriggerType_VOLUME_LIMIT { + triggers = []models.ChfConvergedChargingTrigger{ { TriggerType: ur.ReportTpye, TriggerCategory: models.TriggerCategory_DEFERRED_REPORT, }, } } else { - triggers = []models.Trigger{ + triggers = []models.ChfConvergedChargingTrigger{ { TriggerType: ur.ReportTpye, TriggerCategory: models.TriggerCategory_IMMEDIATE_REPORT, @@ -186,7 +189,7 @@ func buildMultiUnitUsageFromUsageReport(smContext *smf_context.SMContext) []mode ur.UrrId, rg, chgInfo.ChargingMethod) triggerTime := time.Now() - uu := models.UsedUnitContainer{ + uu := models.ChfConvergedChargingUsedUnitContainer{ QuotaManagementIndicator: chgInfo.ChargingMethod, Triggers: triggers, TriggerTimestamp: &triggerTime, @@ -207,10 +210,10 @@ func buildMultiUnitUsageFromUsageReport(smContext *smf_context.SMContext) []mode } } - ratingGroupUnitUsagesMap[rg] = models.MultipleUnitUsage{ + ratingGroupUnitUsagesMap[rg] = models.ChfConvergedChargingMultipleUnitUsage{ RatingGroup: rg, UPFID: ur.UpfId, - UsedUnitContainer: []models.UsedUnitContainer{uu}, + UsedUnitContainer: []models.ChfConvergedChargingUsedUnitContainer{uu}, RequestedUnit: requestUnit, } } else { @@ -259,7 +262,7 @@ func (p *Processor) updateGrantedQuota( for _, t := range ui.Triggers { switch t.TriggerType { - case models.TriggerType_VOLUME_LIMIT: + case models.ChfConvergedChargingTriggerType_VOLUME_LIMIT: // According to 32.255, the for the trigger "Expirt of datavolume limit" have two reporting level // In the Pdu sesion level, the report should be "Immediate report", // that is this report should send to CHF immediately @@ -287,7 +290,7 @@ func (p *Processor) updateGrantedQuota( urrList := []*smf_context.URR{urr} upf := smf_context.GetUpfById(ui.UPFID) if upf != nil { - QueryReport(smContext, upf, urrList, models.TriggerType_VOLUME_LIMIT) + QueryReport(smContext, upf, urrList, models.ChfConvergedChargingTriggerType_VOLUME_LIMIT) p.ReportUsageAndUpdateQuota(smContext) } }, @@ -313,7 +316,7 @@ func (p *Processor) updateGrantedQuota( urrList := []*smf_context.URR{urr} upf := smf_context.GetUpfById(ui.UPFID) if upf != nil { - QueryReport(smContext, upf, urrList, models.TriggerType_VOLUME_LIMIT) + QueryReport(smContext, upf, urrList, models.ChfConvergedChargingTriggerType_VOLUME_LIMIT) } }, func() { @@ -323,7 +326,7 @@ func (p *Processor) updateGrantedQuota( }) } } - case models.TriggerType_MAX_NUMBER_OF_CHANGES_IN_CHARGING_CONDITIONS: + case models.ChfConvergedChargingTriggerType_MAX_NUMBER_OF_CHANGES_IN_CHARGING_CONDITIONS: switch chgInfo.ChargingLevel { case smf_context.PduSessionCharging: chgInfo.EventLimitExpiryTimer = smf_context.NewTimer(time.Duration(t.EventLimit)*time.Second, 1, @@ -333,7 +336,7 @@ func (p *Processor) updateGrantedQuota( urrList := []*smf_context.URR{urr} upf := smf_context.GetUpfById(ui.UPFID) if upf != nil { - QueryReport(smContext, upf, urrList, models.TriggerType_VOLUME_LIMIT) + QueryReport(smContext, upf, urrList, models.ChfConvergedChargingTriggerType_VOLUME_LIMIT) p.ReportUsageAndUpdateQuota(smContext) } }, @@ -345,19 +348,19 @@ func (p *Processor) updateGrantedQuota( smContext.Log.Tracef("MAX_NUMBER_OF_CHANGES_IN_CHARGING_CONDITIONS" + "should only be applied to PDU session level charging") } - case models.TriggerType_QUOTA_THRESHOLD: + case models.ChfConvergedChargingTriggerType_QUOTA_THRESHOLD: if ui.VolumeQuotaThreshold != 0 { trigger.Volth = true urr.VolumeThreshold = uint64(ui.VolumeQuotaThreshold) } // The difference between the quota validity time and the volume limit is // that the validity time is counted by the UPF, the volume limit is counted by the SMF - case models.TriggerType_VALIDITY_TIME: + case models.ChfConvergedChargingTriggerType_VALIDITY_TIME: if ui.ValidityTime != 0 { urr.ReportingTrigger.Quvti = true urr.QuotaValidityTime = time.Now().Add(time.Second * time.Duration(ui.ValidityTime)) } - case models.TriggerType_QUOTA_EXHAUSTED: + case models.ChfConvergedChargingTriggerType_QUOTA_EXHAUSTED: if chgInfo.ChargingMethod == models.QuotaManagementIndicator_ONLINE_CHARGING { if ui.GrantedUnit != nil { trigger.Volqu = true diff --git a/internal/sbi/processor/datapath.go b/internal/sbi/processor/datapath.go index eeedcc48..0e19fe0d 100644 --- a/internal/sbi/processor/datapath.go +++ b/internal/sbi/processor/datapath.go @@ -102,7 +102,7 @@ func ActivateUPFSession( } func QueryReport(smContext *smf_context.SMContext, upf *smf_context.UPF, - urrs []*smf_context.URR, reportResaon models.TriggerType, + urrs []*smf_context.URR, reportResaon models.ChfConvergedChargingTriggerType, ) { for _, urr := range urrs { urr.State = smf_context.RULE_QUERY @@ -166,7 +166,7 @@ func modifyExistingPfcpSession( smContext *smf_context.SMContext, state *PFCPState, resCh chan<- SendPfcpResult, - reportResaon models.TriggerType, + reportResaon models.ChfConvergedChargingTriggerType, ) { logger.PduSessLog.Infoln("Sending PFCP Session Modification Request") @@ -267,14 +267,14 @@ func (p *Processor) sendPDUSessionEstablishmentReject( smContext.SetState(smf_context.InActive) - ctx, _, errToken := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NfType_AMF) + ctx, _, errToken := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NrfNfManagementNfType_AMF) if errToken != nil { logger.PduSessLog.Warnf("Get NAMF_COMM context failed: %s", errToken) return } - rspData, _, err := p.Consumer(). + rspData, err := p.Consumer(). N1N2MessageTransfer(ctx, smContext.Supi, n1n2Request, smContext.CommunicationClientApiPrefix) - if err != nil { + if err != nil || rspData == nil { logger.ConsumerLog.Warnf("N1N2MessageTransfer for SendPDUSessionEstablishmentReject failed: %+v", err) return } @@ -314,7 +314,7 @@ func (p *Processor) sendPDUSessionEstablishmentAccept( SmInfo: &models.N2SmInformation{ PduSessionId: smContext.PDUSessionID, N2InfoContent: &models.N2InfoContent{ - NgapIeType: models.NgapIeType_PDU_RES_SETUP_REQ, + NgapIeType: models.AmfCommunicationNgapIeType_PDU_RES_SETUP_REQ, NgapData: &models.RefToBinaryData{ ContentId: "N2SmInformation", }, @@ -325,15 +325,15 @@ func (p *Processor) sendPDUSessionEstablishmentAccept( }, } - ctx, _, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NfType_AMF) + ctx, _, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NrfNfManagementNfType_AMF) if err != nil { logger.PduSessLog.Warnf("Get NAMF_COMM context failed: %s", err) return } - rspData, _, err := p.Consumer(). + rspData, err := p.Consumer(). N1N2MessageTransfer(ctx, smContext.Supi, n1n2Request, smContext.CommunicationClientApiPrefix) - if err != nil { + if err != nil || rspData == nil { logger.ConsumerLog.Warnf("N1N2MessageTransfer for sendPDUSessionEstablishmentAccept failed: %+v", err) return } diff --git a/internal/sbi/processor/gsm_handler_test.go b/internal/sbi/processor/gsm_handler_test.go index 0a8af803..57c8b249 100644 --- a/internal/sbi/processor/gsm_handler_test.go +++ b/internal/sbi/processor/gsm_handler_test.go @@ -29,7 +29,7 @@ func TestBuildNASPacketFilterFromPacketFilterInfo(t *testing.T) { }, }, flowInfo: models.FlowInformation{ - FlowDirection: models.FlowDirectionRm_BIDIRECTIONAL, + FlowDirection: models.FlowDirection_BIDIRECTIONAL, FlowDescription: "permit out ip from any to assigned", }, }, @@ -47,7 +47,7 @@ func TestBuildNASPacketFilterFromPacketFilterInfo(t *testing.T) { }, }, flowInfo: models.FlowInformation{ - FlowDirection: models.FlowDirectionRm_UPLINK, + FlowDirection: models.FlowDirection_UPLINK, FlowDescription: "permit out ip from any to 192.168.0.0/16", }, }, @@ -69,7 +69,7 @@ func TestBuildNASPacketFilterFromPacketFilterInfo(t *testing.T) { }, }, flowInfo: models.FlowInformation{ - FlowDirection: models.FlowDirectionRm_BIDIRECTIONAL, + FlowDirection: models.FlowDirection_BIDIRECTIONAL, FlowDescription: "permit out ip from 10.160.20.0/24 to 192.168.0.0/16", }, }, @@ -94,7 +94,7 @@ func TestBuildNASPacketFilterFromPacketFilterInfo(t *testing.T) { }, }, flowInfo: models.FlowInformation{ - FlowDirection: models.FlowDirectionRm_BIDIRECTIONAL, + FlowDirection: models.FlowDirection_BIDIRECTIONAL, FlowDescription: "permit out ip from 10.160.20.0/24 to 192.168.0.0/16 8000", }, }, @@ -120,7 +120,7 @@ func TestBuildNASPacketFilterFromPacketFilterInfo(t *testing.T) { }, }, flowInfo: models.FlowInformation{ - FlowDirection: models.FlowDirectionRm_DOWNLINK, + FlowDirection: models.FlowDirection_DOWNLINK, FlowDescription: "permit out ip from 10.160.20.0/24 to 192.168.0.0/16 3000-8000", }, }, @@ -150,7 +150,7 @@ func TestBuildNASPacketFilterFromPacketFilterInfo(t *testing.T) { }, }, flowInfo: models.FlowInformation{ - FlowDirection: models.FlowDirectionRm_DOWNLINK, + FlowDirection: models.FlowDirection_DOWNLINK, FlowDescription: "permit out ip from 10.160.20.0/24 3000-4000 to 192.168.0.0/16 6000-8000", }, }, @@ -200,7 +200,7 @@ func TestBuildNASPacketFilterFromPacketFilterInfo(t *testing.T) { }, }, flowInfo: models.FlowInformation{ - FlowDirection: models.FlowDirectionRm_DOWNLINK, + FlowDirection: models.FlowDirection_DOWNLINK, FlowDescription: "permit out ip from 10.160.20.0/24 3000-4000 to 192.168.0.0/16 6000-7000,8000", }, }, @@ -250,7 +250,7 @@ func TestBuildNASPacketFilterFromPacketFilterInfo(t *testing.T) { }, }, flowInfo: models.FlowInformation{ - FlowDirection: models.FlowDirectionRm_DOWNLINK, + FlowDirection: models.FlowDirection_DOWNLINK, FlowDescription: "permit out ip from 10.160.20.0/24 3000-4000,5000 to 192.168.0.0/16 6000-7000", }, }, diff --git a/internal/sbi/processor/notifier.go b/internal/sbi/processor/notifier.go index 733059ed..17be4069 100644 --- a/internal/sbi/processor/notifier.go +++ b/internal/sbi/processor/notifier.go @@ -7,8 +7,9 @@ import ( "github.com/gin-gonic/gin" - "github.com/free5gc/openapi/Nsmf_EventExposure" + "github.com/free5gc/openapi" "github.com/free5gc/openapi/models" + "github.com/free5gc/openapi/smf/EventExposure" smf_context "github.com/free5gc/smf/internal/context" "github.com/free5gc/smf/internal/logger" ) @@ -56,16 +57,12 @@ func (p *Processor) chargingNotificationProcedure( logger.ChargingLog.Warnf("Cound not find upf %s", upfId) continue } - QueryReport(smContext, upf, urrList, models.TriggerType_FORCED_REAUTHORISATION) + QueryReport(smContext, upf, urrList, models.ChfConvergedChargingTriggerType_FORCED_REAUTHORISATION) } p.ReportUsageAndUpdateQuota(smContext) } else { - problemDetails := &models.ProblemDetails{ - Status: http.StatusNotFound, - Cause: CONTEXT_NOT_FOUND, - Detail: fmt.Sprintf("SM Context [%s] Not Found ", smContextRef), - } - return problemDetails + detail := fmt.Sprintf("SM Context [%s] Not Found ", smContextRef) + return openapi.ProblemDetailsDataNotFound(detail) } return nil @@ -128,30 +125,23 @@ func (p *Processor) HandleSMPolicyUpdateNotify( func SendUpPathChgEventExposureNotification( uri string, notification *models.NsmfEventExposureNotification, ) { - configuration := Nsmf_EventExposure.NewConfiguration() - client := Nsmf_EventExposure.NewAPIClient(configuration) - _, httpResponse, err := client. - DefaultCallbackApi. - SmfEventExposureNotification(context.Background(), uri, *notification) - if err != nil { - if httpResponse != nil { - logger.PduSessLog.Warnf("SMF Event Exposure Notification Error[%s]", httpResponse.Status) - } else { - logger.PduSessLog.Warnf("SMF Event Exposure Notification Failed[%s]", err.Error()) - } - return - } else if httpResponse == nil { - logger.PduSessLog.Warnln("SMF Event Exposure Notification Failed[HTTP Response is nil]") - return + configuration := EventExposure.NewConfiguration() + client := EventExposure.NewAPIClient(configuration) + request := &EventExposure.CreateIndividualSubcriptionMyNotificationPostRequest{ + NsmfEventExposureNotification: notification, } - defer func() { - if rspCloseErr := httpResponse.Body.Close(); rspCloseErr != nil { - logger.PduSessLog.Errorf("SmfEventExposureNotification response body cannot close: %+v", rspCloseErr) - } - }() - if httpResponse.StatusCode != http.StatusOK && httpResponse.StatusCode != http.StatusNoContent { - logger.PduSessLog.Warnf("SMF Event Exposure Notification Failed") - } else { + _, err := client. + SubscriptionsCollectionApi. + CreateIndividualSubcriptionMyNotificationPost(context.Background(), uri, request) + + switch err := err.(type) { + case openapi.GenericOpenAPIError: + logger.PduSessLog.Warnf("SMF Event Exposure Notification Error[%s]", err.Error()) + case error: + logger.PduSessLog.Warnf("SMF Event Exposure Notification Failed[%s]", err.Error()) + case nil: logger.PduSessLog.Tracef("SMF Event Exposure Notification Success") + default: + logger.PduSessLog.Warnf("SMF Event Exposure Notification Unknown Error: %+v", err) } } diff --git a/internal/sbi/processor/pdu_session.go b/internal/sbi/processor/pdu_session.go index fd297b78..7d670aeb 100644 --- a/internal/sbi/processor/pdu_session.go +++ b/internal/sbi/processor/pdu_session.go @@ -7,18 +7,17 @@ import ( "net/http" "reflect" - "github.com/antihax/optional" "github.com/gin-gonic/gin" "github.com/free5gc/nas" "github.com/free5gc/nas/nasMessage" "github.com/free5gc/openapi" - "github.com/free5gc/openapi/Nsmf_PDUSession" - "github.com/free5gc/openapi/Nudm_SubscriberDataManagement" "github.com/free5gc/openapi/models" + "github.com/free5gc/openapi/udm/SubscriberDataManagement" "github.com/free5gc/pfcp/pfcpType" smf_context "github.com/free5gc/smf/internal/context" "github.com/free5gc/smf/internal/logger" + smf_errors "github.com/free5gc/smf/pkg/errors" "github.com/free5gc/smf/pkg/factory" ) @@ -29,8 +28,8 @@ func (p *Processor) HandlePDUSessionSMContextCreate( ) { // GSM State // PDU Session Establishment Accept/Reject - var response models.PostSmContextsResponse - response.JsonData = new(models.SmContextCreatedData) + var response models.PostSmContextsResponse201 + response.JsonData = new(models.SmfPduSessionSmContextCreatedData) logger.PduSessLog.Infoln("In HandlePDUSessionSMContextCreate") // Check has PDU Session Establishment Request @@ -38,12 +37,12 @@ func (p *Processor) HandlePDUSessionSMContextCreate( if err := m.GsmMessageDecode(&request.BinaryDataN1SmMessage); err != nil || m.GsmHeader.GetMessageType() != nas.MsgTypePDUSessionEstablishmentRequest { logger.PduSessLog.Warnln("GsmMessageDecode Error: ", err) - postSmContextsError := models.PostSmContextsErrorResponse{ + postSmContextsError := models.PostSmContextsError{ JsonData: &models.SmContextCreateError{ - Error: &Nsmf_PDUSession.N1SmError, + Error: &smf_errors.N1SmError, }, } - c.Render(http.StatusForbidden, openapi.MultipartRelatedRender{Data: postSmContextsError}) + c.JSON(http.StatusForbidden, postSmContextsError) return } @@ -55,7 +54,7 @@ func (p *Processor) HandlePDUSessionSMContextCreate( smContext := smf_context.NewSMContext(createData.Supi, createData.PduSessionId) smContext.SetState(smf_context.ActivePending) - smContext.SmContextCreateData = createData + smContext.SmfPduSessionSmContextCreateData = createData smContext.SmStatusNotifyUri = createData.SmContextStatusUri smContext.SMLock.Lock() @@ -90,27 +89,25 @@ func (p *Processor) HandlePDUSessionSMContextCreate( smPlmnID := createData.Guami.PlmnId - smDataParams := &Nudm_SubscriberDataManagement.GetSmDataParamOpts{ - Dnn: optional.NewString(createData.Dnn), - PlmnId: optional.NewInterface(openapi.MarshToJsonString(smPlmnID)), - SingleNssai: optional.NewInterface(openapi.MarshToJsonString(smContext.SNssai)), + smDataParams := &SubscriberDataManagement.GetSmDataRequest{ + Dnn: &createData.Dnn, + PlmnId: &models.PlmnId{ + Mcc: smPlmnID.Mcc, + Mnc: smPlmnID.Mnc, + }, + SingleNssai: smContext.SNssai, } - ctx, _, oauthErr := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_SDM, models.NfType_UDM) + ctx, _, oauthErr := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NUDM_SDM, models.NrfNfManagementNfType_UDM) if oauthErr != nil { smContext.Log.Errorf("Get Token Context Error[%v]", oauthErr) return } - if sessSubData, rsp, err := p.Consumer(). + if sessSubData, err := p.Consumer(). GetSmData(ctx, smContext.Supi, smDataParams); err != nil { smContext.Log.Errorln("Get SessionManagementSubscriptionData error:", err) } else { - defer func() { - if rspCloseErr := rsp.Body.Close(); rspCloseErr != nil { - smContext.Log.Errorf("GetSmData response body cannot close: %+v", rspCloseErr) - } - }() if len(sessSubData) > 0 { smContext.DnnConfiguration = sessSubData[0].DnnConfigurations[smContext.Dnn] // UP Security info present in session management subscription data @@ -145,12 +142,12 @@ func (p *Processor) HandlePDUSessionSMContextCreate( if errors.As(err, &gsmError) { p.makeEstRejectResAndReleaseSMContext(c, smContext, gsmError.GSMCause, - &Nsmf_PDUSession.N1SmError) + &smf_errors.N1SmError) return } p.makeEstRejectResAndReleaseSMContext(c, smContext, nasMessage.Cause5GSMRequestRejectedUnspecified, - &Nsmf_PDUSession.N1SmError) + &smf_errors.N1SmError) return } @@ -163,7 +160,7 @@ func (p *Processor) HandlePDUSessionSMContextCreate( smContext.Log.Traceln("Send NF Discovery Serving AMF successfully") } - for _, service := range *smContext.AMFProfile.NfServices { + for _, service := range smContext.AMFProfile.NfServices { if service.ServiceName == models.ServiceName_NAMF_COMM { smContext.CommunicationClientApiPrefix = service.ApiPrefix } @@ -174,7 +171,7 @@ func (p *Processor) HandlePDUSessionSMContextCreate( smContext.Log.Errorf("PDUSessionSMContextCreate err: %v", err) p.makeEstRejectResAndReleaseSMContext(c, smContext, nasMessage.Cause5GSMInsufficientResourcesForSpecificSliceAndDNN, - &Nsmf_PDUSession.InsufficientResourceSliceDnn) + &smf_errors.InsufficientResourceSliceDnn) return } @@ -191,13 +188,13 @@ func (p *Processor) HandlePDUSessionSMContextCreate( if problemDetails.Cause == "USER_UNKNOWN" { p.makeEstRejectResAndReleaseSMContext(c, smContext, nasMessage.Cause5GSMRequestRejectedUnspecified, - &Nsmf_PDUSession.SubscriptionDenied) + &smf_errors.SubscriptionDenied) return } } p.makeEstRejectResAndReleaseSMContext(c, smContext, nasMessage.Cause5GSMNetworkFailure, - &Nsmf_PDUSession.NetworkFailure) + &smf_errors.NetworkFailure) return } smContext.SMPolicyID = smPolicyID @@ -216,7 +213,7 @@ func (p *Processor) HandlePDUSessionSMContextCreate( smContext.Log.Errorf("PDUSessionSMContextCreate err: %v", err) p.makeEstRejectResAndReleaseSMContext(c, smContext, nasMessage.Cause5GSMRequestRejectedUnspecified, - &Nsmf_PDUSession.SubscriptionDenied) + &smf_errors.SubscriptionDenied) return } @@ -231,7 +228,7 @@ func (p *Processor) HandlePDUSessionSMContextCreate( smContext.Log.Errorf("PDUSessionSMContextCreate err: %v", err) p.makeEstRejectResAndReleaseSMContext(c, smContext, nasMessage.Cause5GSMInsufficientResourcesForSpecificSliceAndDNN, - &Nsmf_PDUSession.InsufficientResourceSliceDnn) + &smf_errors.InsufficientResourceSliceDnn) return } @@ -257,7 +254,7 @@ func (p *Processor) HandlePDUSessionSMContextCreate( doSubscribe = true response.JsonData = smContext.BuildCreatedData() c.Header("Location", smContext.Ref) - c.Render(http.StatusCreated, openapi.MultipartRelatedRender{Data: response}) + c.JSON(http.StatusCreated, response) } func (p *Processor) HandlePDUSessionSMContextUpdate( @@ -281,10 +278,10 @@ func (p *Processor) HandlePDUSessionSMContextUpdate( if smContext == nil { logger.PduSessLog.Warnf("SMContext[%s] is not found", smContextRef) - updateSmContextError := models.UpdateSmContextErrorResponse{ + updateSmContextError := models.UpdateSmContextResponse400{ JsonData: &models.SmContextUpdateError{ UpCnxState: models.UpCnxState_DEACTIVATED, - Error: &models.ProblemDetails{ + Error: &models.SmfPduSessionExtProblemDetails{ Type: "Resource Not Found", Title: "SMContext Ref is not found", Status: http.StatusNotFound, @@ -300,7 +297,7 @@ func (p *Processor) HandlePDUSessionSMContextUpdate( var sendPFCPModification bool var pfcpResponseStatus smf_context.PFCPSessionResponseStatus - var response models.UpdateSmContextResponse + var response models.UpdateSmContextResponse200 response.JsonData = new(models.SmContextUpdatedData) smContextUpdateData := body.JsonData @@ -311,9 +308,9 @@ func (p *Processor) HandlePDUSessionSMContextUpdate( smContext.Log.Tracef("N1 Message: %s", hex.EncodeToString(body.BinaryDataN1SmMessage)) if err != nil { smContext.Log.Errorf("N1 Message parse failed: %v", err) - updateSmContextError := models.UpdateSmContextErrorResponse{ + updateSmContextError := models.UpdateSmContextResponse400{ JsonData: &models.SmContextUpdateError{ - Error: &Nsmf_PDUSession.N1SmError, + Error: &smf_errors.N1SmError, }, } // Depends on the reason why N4 fail c.JSON(http.StatusForbidden, updateSmContextError) @@ -491,7 +488,7 @@ func (p *Processor) HandlePDUSessionSMContextUpdate( for curDataPathNode := dataPath.FirstDPNode; curDataPathNode != nil; curDataPathNode = curDataPathNode.Next() { if curDataPathNode.IsANUPF() { urrList = append(urrList, curDataPathNode.UpLinkTunnel.PDR.URR...) - QueryReport(smContext, curDataPathNode.UPF, urrList, models.TriggerType_USER_LOCATION_CHANGE) + QueryReport(smContext, curDataPathNode.UPF, urrList, models.ChfConvergedChargingTriggerType_USER_LOCATION_CHANGE) } } } @@ -757,7 +754,7 @@ func (p *Processor) HandlePDUSessionSMContextUpdate( response.JsonData.HoState = models.HoState_COMPLETED } - if smContextUpdateData.Cause == models.Cause_REL_DUE_TO_DUPLICATE_SESSION_ID { + if smContextUpdateData.Cause == models.SmfPduSessionCause_REL_DUE_TO_DUPLICATE_SESSION_ID { // * release PDU Session Here smContext.Log.Infoln("[SMF] Cause_REL_DUE_TO_DUPLICATE_SESSION_ID") if smContext.CheckState(smf_context.Active) { @@ -807,9 +804,9 @@ func (p *Processor) HandlePDUSessionSMContextUpdate( smContext.Log.Traceln("In case SessionUpdateFailed") smContext.SetState(smf_context.Active) // It is just a template - updateSmContextError := models.UpdateSmContextErrorResponse{ + updateSmContextError := models.UpdateSmContextResponse400{ JsonData: &models.SmContextUpdateError{ - Error: &Nsmf_PDUSession.N1SmError, + Error: &smf_errors.N1SmError, }, } // Depends on the reason why N4 fail c.JSON(http.StatusForbidden, updateSmContextError) @@ -825,17 +822,17 @@ func (p *Processor) HandlePDUSessionSMContextUpdate( // Update SmContext Request(N1 PDU Session Release Request) // Send PDU Session Release Reject smContext.Log.Traceln("In case SessionReleaseFailed") - problemDetail := models.ProblemDetails{ + problemDetail := models.SmfPduSessionExtProblemDetails{ Status: http.StatusInternalServerError, Cause: "SYSTEM_FAILURE", } smContext.SetState(smf_context.Active) - errResponse := models.UpdateSmContextErrorResponse{ + errResponse := models.UpdateSmContextResponse400{ JsonData: &models.SmContextUpdateError{ Error: &problemDetail, }, } - if smContextUpdateData.Cause != models.Cause_REL_DUE_TO_DUPLICATE_SESSION_ID { + if smContextUpdateData.Cause != models.SmfPduSessionCause_REL_DUE_TO_DUPLICATE_SESSION_ID { if buf, err = smf_context.BuildGSMPDUSessionReleaseReject(smContext); err != nil { logger.PduSessLog.Errorf("build GSM PDUSessionReleaseReject failed: %+v", err) } else { @@ -876,10 +873,10 @@ func (p *Processor) HandlePDUSessionSMContextRelease( if smContext == nil { logger.PduSessLog.Warnf("SMContext[%s] is not found", smContextRef) - updateSmContextError := &models.UpdateSmContextErrorResponse{ + updateSmContextError := &models.UpdateSmContextResponse400{ JsonData: &models.SmContextUpdateError{ UpCnxState: models.UpCnxState_DEACTIVATED, - Error: &models.ProblemDetails{ + Error: &models.SmfPduSessionExtProblemDetails{ Type: "Resource Not Found", Title: "SMContext Ref is not found", Status: http.StatusNotFound, @@ -944,12 +941,12 @@ func (p *Processor) HandlePDUSessionSMContextRelease( // Update SmContext Request(N1 PDU Session Release Request) // Send PDU Session Release Reject smContext.Log.Traceln("In case SessionReleaseFailed") - problemDetail := models.ProblemDetails{ + problemDetail := models.SmfPduSessionExtProblemDetails{ Status: http.StatusInternalServerError, Cause: "SYSTEM_FAILURE", } smContext.SetState(smf_context.Active) - errResponse := models.UpdateSmContextErrorResponse{ + errResponse := models.UpdateSmContextResponse400{ JsonData: &models.SmContextUpdateError{ Error: &problemDetail, }, @@ -967,12 +964,12 @@ func (p *Processor) HandlePDUSessionSMContextRelease( smContext.Log.Warnf("The state shouldn't be [%s]\n", pfcpResponseStatus) smContext.Log.Traceln("In case Unknown") - problemDetail := models.ProblemDetails{ + problemDetail := models.SmfPduSessionExtProblemDetails{ Status: http.StatusInternalServerError, Cause: "SYSTEM_FAILURE", } smContext.SetState(smf_context.Active) - errResponse := models.UpdateSmContextErrorResponse{ + errResponse := models.UpdateSmContextResponse400{ JsonData: &models.SmContextUpdateError{ Error: &problemDetail, }, @@ -991,7 +988,7 @@ func (p *Processor) HandlePDUSessionSMContextRelease( } func (p *Processor) HandlePDUSessionSMContextLocalRelease( - smContext *smf_context.SMContext, createData *models.SmContextCreateData, + smContext *smf_context.SMContext, createData *models.SmfPduSessionSmContextCreateData, ) { smContext.SMLock.Lock() defer smContext.SMLock.Unlock() @@ -1079,29 +1076,23 @@ func (p *Processor) makeEstRejectResAndReleaseSMContext( c *gin.Context, smContext *smf_context.SMContext, nasErrorCause uint8, - sbiError *models.ProblemDetails, + sbiError *models.SmfPduSessionExtProblemDetails, ) { + postSmContextsError := models.PostSmContextsError{ + JsonData: &models.SmContextCreateError{ + Error: sbiError, + N1SmMsg: &models.RefToBinaryData{ContentId: "n1SmMsg"}, + }, + } if buf, err := smf_context. BuildGSMPDUSessionEstablishmentReject( smContext, nasErrorCause); err != nil { - postSmContextsError := models.PostSmContextsErrorResponse{ - JsonData: &models.SmContextCreateError{ - Error: sbiError, - N1SmMsg: &models.RefToBinaryData{ContentId: "n1SmMsg"}, - }, - } - p.nasErrorResponse(c, int(sbiError.Status), postSmContextsError) + logger.PduSessLog.Errorf("Build GSM PDUSessionEstablishmentReject failed: %+v", err) } else { - postSmContextsError := models.PostSmContextsErrorResponse{ - JsonData: &models.SmContextCreateError{ - Error: sbiError, - N1SmMsg: &models.RefToBinaryData{ContentId: "n1SmMsg"}, - }, - BinaryDataN1SmMessage: buf, - } - p.nasErrorResponse(c, int(sbiError.Status), postSmContextsError) + postSmContextsError.BinaryDataN1SmMessage = buf } + p.nasErrorResponse(c, int(sbiError.Status), postSmContextsError) p.RemoveSMContextFromAllNF(smContext, false) } @@ -1123,7 +1114,7 @@ func (p *Processor) sendGSMPDUSessionReleaseCommand(smContext *smf_context.SMCon // Start T3592 t3592 := factory.SmfConfig.Configuration.T3592 if t3592.Enable { - ctx, _, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NfType_AMF) + ctx, _, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NrfNfManagementNfType_AMF) if err != nil { smContext.Log.Warnf("Get namf-comm token failed: %+v", err) return @@ -1131,7 +1122,7 @@ func (p *Processor) sendGSMPDUSessionReleaseCommand(smContext *smf_context.SMCon smContext.T3592 = smf_context.NewTimer(t3592.ExpireTime, t3592.MaxRetryTimes, func(expireTimes int32) { smContext.SMLock.Lock() - rspData, _, errMsgTransfer := p.Consumer(). + rspData, errMsgTransfer := p.Consumer(). N1N2MessageTransfer(ctx, smContext.Supi, n1n2Request, smContext.CommunicationClientApiPrefix) if errMsgTransfer != nil { logger.ConsumerLog.Warnf("N1N2MessageTransfer for GSMPDUSessionReleaseCommand failed: %+v", errMsgTransfer) @@ -1172,7 +1163,7 @@ func (p *Processor) sendGSMPDUSessionModificationCommand(smContext *smf_context. // Start T3591 t3591 := factory.SmfConfig.Configuration.T3591 if t3591.Enable { - ctx, _, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NfType_AMF) + ctx, _, err := smf_context.GetSelf().GetTokenCtx(models.ServiceName_NAMF_COMM, models.NrfNfManagementNfType_AMF) if err != nil { smContext.Log.Warnf("Get namf-comm token failed: %+v", err) return @@ -1181,7 +1172,7 @@ func (p *Processor) sendGSMPDUSessionModificationCommand(smContext *smf_context. smContext.T3591 = smf_context.NewTimer(t3591.ExpireTime, t3591.MaxRetryTimes, func(expireTimes int32) { smContext.SMLock.Lock() defer smContext.SMLock.Unlock() - rspData, _, errMsgTransfer := p.Consumer(). + rspData, errMsgTransfer := p.Consumer(). N1N2MessageTransfer(ctx, smContext.Supi, n1n2Request, smContext.CommunicationClientApiPrefix) if errMsgTransfer != nil { logger.ConsumerLog.Warnf("N1N2MessageTransfer for GSMPDUSessionModificationCommand failed: %+v", errMsgTransfer) @@ -1203,15 +1194,25 @@ func (p *Processor) sendGSMPDUSessionModificationCommand(smContext *smf_context. func (p *Processor) nasErrorResponse( c *gin.Context, status int, - errBody models.PostSmContextsErrorResponse, + errBody models.PostSmContextsError, ) { switch status { case http.StatusForbidden, - // http.StatusNotFound, + http.StatusNotFound, http.StatusInternalServerError, http.StatusGatewayTimeout: - c.Render(status, openapi.MultipartRelatedRender{Data: errBody}) - default: - c.JSON(status, errBody) + logger.SBILog.Warnf("NAS Error Response: %v", errBody) + if errBody.BinaryDataN1SmMessage != nil || + errBody.BinaryDataN2SmMessage != nil { + rspBody, contentType, err := openapi.MultipartSerialize(errBody) + if err != nil { + logger.SBILog.Infof("MultipartSerialize error: %v", err) + c.JSON(http.StatusInternalServerError, openapi.ProblemDetailsSystemFailure(err.Error())) + } else { + c.Data(status, contentType, rspBody) + } + return + } } + c.JSON(status, errBody) } diff --git a/internal/sbi/processor/pdu_session_test.go b/internal/sbi/processor/pdu_session_test.go index 4e811910..3ae69cb2 100644 --- a/internal/sbi/processor/pdu_session_test.go +++ b/internal/sbi/processor/pdu_session_test.go @@ -10,21 +10,21 @@ import ( "time" "github.com/gin-gonic/gin" + "github.com/h2non/gock" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" - "gopkg.in/h2non/gock.v1" "github.com/free5gc/nas" "github.com/free5gc/nas/nasMessage" "github.com/free5gc/nas/nasType" "github.com/free5gc/openapi" - "github.com/free5gc/openapi/Nsmf_PDUSession" "github.com/free5gc/openapi/models" smf_context "github.com/free5gc/smf/internal/context" "github.com/free5gc/smf/internal/pfcp" "github.com/free5gc/smf/internal/pfcp/udp" "github.com/free5gc/smf/internal/sbi/consumer" "github.com/free5gc/smf/internal/sbi/processor" + PDUSession_errors "github.com/free5gc/smf/pkg/errors" "github.com/free5gc/smf/pkg/factory" "github.com/free5gc/smf/pkg/service" "github.com/free5gc/util/httpwrapper" @@ -126,12 +126,12 @@ func initConfig() { func initDiscUDMStubNRF() { searchResult := &models.SearchResult{ ValidityPeriod: 100, - NfInstances: []models.NfProfile{ + NfInstances: []models.NrfNfDiscoveryNfProfile{ { NfInstanceId: "smf-unit-testing", NfType: "UDM", NfStatus: "REGISTERED", - PlmnList: &[]models.PlmnId{ + PlmnList: []models.PlmnId{ { Mcc: "208", Mnc: "93", @@ -140,11 +140,11 @@ func initDiscUDMStubNRF() { Ipv4Addresses: []string{ "127.0.0.3", }, - NfServices: &[]models.NfService{ + NfServices: []models.NrfNfDiscoveryNfService{ { ServiceInstanceId: "0", ServiceName: "nudm-sdm", - Versions: &[]models.NfServiceVersion{ + Versions: []models.NfServiceVersion{ { ApiVersionInUri: "v1", ApiFullVersion: "1.0.0", @@ -152,7 +152,7 @@ func initDiscUDMStubNRF() { }, Scheme: "http", NfServiceStatus: "REGISTERED", - IpEndPoints: &[]models.IpEndPoint{ + IpEndPoints: []models.IpEndPoint{ { Ipv4Address: "127.0.0.3", Transport: "TCP", @@ -177,12 +177,12 @@ func initDiscUDMStubNRF() { func initDiscPCFStubNRF() { searchResult := &models.SearchResult{ ValidityPeriod: 100, - NfInstances: []models.NfProfile{ + NfInstances: []models.NrfNfDiscoveryNfProfile{ { NfInstanceId: "smf-unit-testing", NfType: "PCF", NfStatus: "REGISTERED", - PlmnList: &[]models.PlmnId{ + PlmnList: []models.PlmnId{ { Mcc: "208", Mnc: "93", @@ -197,11 +197,11 @@ func initDiscPCFStubNRF() { "internet", }, }, - NfServices: &[]models.NfService{ + NfServices: []models.NrfNfDiscoveryNfService{ { ServiceInstanceId: "1", ServiceName: "npcf-smpolicycontrol", - Versions: &[]models.NfServiceVersion{ + Versions: []models.NfServiceVersion{ { ApiVersionInUri: "v1", ApiFullVersion: "1.0.0", @@ -209,7 +209,7 @@ func initDiscPCFStubNRF() { }, Scheme: "http", NfServiceStatus: "REGISTERED", - IpEndPoints: &[]models.IpEndPoint{ + IpEndPoints: []models.IpEndPoint{ { Ipv4Address: "127.0.0.7", Transport: "TCP", @@ -313,12 +313,12 @@ func initSMPoliciesPostStubPCF() { func initDiscAMFStubNRF() { searchResult := &models.SearchResult{ ValidityPeriod: 100, - NfInstances: []models.NfProfile{ + NfInstances: []models.NrfNfDiscoveryNfProfile{ { NfInstanceId: "smf-unit-testing", NfType: "AMF", NfStatus: "REGISTERED", - PlmnList: &[]models.PlmnId{ + PlmnList: []models.PlmnId{ { Mcc: "208", Mnc: "93", @@ -327,15 +327,15 @@ func initDiscAMFStubNRF() { Ipv4Addresses: []string{ "127.0.0.18", }, - AmfInfo: &models.AmfInfo{ + AmfInfo: &models.NrfNfManagementAmfInfo{ AmfSetId: "3f8", AmfRegionId: "ca", }, - NfServices: &[]models.NfService{ + NfServices: []models.NrfNfDiscoveryNfService{ { ServiceInstanceId: "0", ServiceName: "namf-comm", - Versions: &[]models.NfServiceVersion{ + Versions: []models.NfServiceVersion{ { ApiVersionInUri: "v1", ApiFullVersion: "1.0.0", @@ -343,7 +343,7 @@ func initDiscAMFStubNRF() { }, Scheme: "http", NfServiceStatus: "REGISTERED", - IpEndPoints: &[]models.IpEndPoint{ + IpEndPoints: []models.IpEndPoint{ { Ipv4Address: "127.0.0.18", Transport: "TCP", @@ -466,13 +466,13 @@ func TestHandlePDUSessionSMContextCreate(t *testing.T) { }, paramStr: "input wrong GSM Message type\n", resultStr: "PDUSessionSMContextCreate should fail due to wrong GSM type\n", - responseBody: &models.PostSmContextsErrorResponse{}, + responseBody: &models.PostSmContextsError{}, expectedHTTPRsp: &httpwrapper.Response{ Header: nil, Status: http.StatusForbidden, - Body: models.PostSmContextsErrorResponse{ + Body: models.PostSmContextsError{ JsonData: &models.SmContextCreateError{ - Error: &Nsmf_PDUSession.N1SmError, + Error: &PDUSession_errors.N1SmError, }, }, }, @@ -483,7 +483,7 @@ func TestHandlePDUSessionSMContextCreate(t *testing.T) { initGetSMDataStubUDM, initSMPoliciesPostStubPCF, initDiscAMFStubNRF, }, request: models.PostSmContextsRequest{ - JsonData: &models.SmContextCreateData{ + JsonData: &models.SmfPduSessionSmContextCreateData{ Supi: "imsi-208930000007487", Pei: "imeisv-1110000000000000", Gpsi: "msisdn-0900000000", @@ -495,14 +495,14 @@ func TestHandlePDUSessionSMContextCreate(t *testing.T) { }, ServingNfId: "c8d0ee65-f466-48aa-a42f-235ec771cb52", Guami: &models.Guami{ - PlmnId: &models.PlmnId{ + PlmnId: &models.PlmnIdNid{ Mcc: "208", Mnc: "93", }, AmfId: "cafe00", }, AnType: "3GPP_ACCESS", - ServingNetwork: &models.PlmnId{ + ServingNetwork: &models.PlmnIdNid{ Mcc: "208", Mnc: "93", }, @@ -511,13 +511,13 @@ func TestHandlePDUSessionSMContextCreate(t *testing.T) { }, paramStr: "try request the IPv6 PDU session\n", resultStr: "Reject IPv6 PDU Session and respond error\n", - responseBody: &models.PostSmContextsErrorResponse{}, + responseBody: &models.PostSmContextsError{}, expectedHTTPRsp: &httpwrapper.Response{ Header: nil, Status: http.StatusForbidden, - Body: models.PostSmContextsErrorResponse{ + Body: models.PostSmContextsError{ JsonData: &models.SmContextCreateError{ - Error: &models.ProblemDetails{ + Error: &models.SmfPduSessionExtProblemDetails{ Title: "Invalid N1 Message", Status: http.StatusForbidden, Detail: "N1 Message Error", @@ -536,7 +536,7 @@ func TestHandlePDUSessionSMContextCreate(t *testing.T) { initGetSMDataStubUDM, initSMPoliciesPostStubPCF, initDiscAMFStubNRF, }, request: models.PostSmContextsRequest{ - JsonData: &models.SmContextCreateData{ + JsonData: &models.SmfPduSessionSmContextCreateData{ Supi: "imsi-208930000007487", Pei: "imeisv-1110000000000000", Gpsi: "msisdn-0900000000", @@ -548,14 +548,14 @@ func TestHandlePDUSessionSMContextCreate(t *testing.T) { }, ServingNfId: "c8d0ee65-f466-48aa-a42f-235ec771cb52", Guami: &models.Guami{ - PlmnId: &models.PlmnId{ + PlmnId: &models.PlmnIdNid{ Mcc: "208", Mnc: "93", }, AmfId: "cafe00", }, AnType: "3GPP_ACCESS", - ServingNetwork: &models.PlmnId{ + ServingNetwork: &models.PlmnIdNid{ Mcc: "208", Mnc: "93", }, @@ -564,12 +564,12 @@ func TestHandlePDUSessionSMContextCreate(t *testing.T) { }, paramStr: "input correct PostSmContexts Request\n", resultStr: "PDUSessionSMContextCreate should pass\n", - responseBody: &models.PostSmContextsResponse{}, + responseBody: &models.PostSmContextsResponse201{}, expectedHTTPRsp: &httpwrapper.Response{ Header: nil, Status: http.StatusCreated, - Body: models.PostSmContextsResponse{ - JsonData: &models.SmContextCreatedData{ + Body: models.PostSmContextsResponse201{ + JsonData: &models.SmfPduSessionSmContextCreatedData{ SNssai: &models.Snssai{ Sst: 1, Sd: "112232", @@ -580,13 +580,6 @@ func TestHandlePDUSessionSMContextCreate(t *testing.T) { }, } - // init all stubs for all TCs first to prevent gock race condition - for _, tc := range testCases { - for _, initFunc := range tc.initFuncs { - initFunc() - } - } - mockSmf := service.NewMockSmfAppInterface(gomock.NewController(t)) consumer, err := consumer.NewConsumer(mockSmf) if err != nil { @@ -604,6 +597,9 @@ func TestHandlePDUSessionSMContextCreate(t *testing.T) { mockSmf.EXPECT().Consumer().Return(consumer).AnyTimes() for _, tc := range testCases { + for _, initFunc := range tc.initFuncs { + initFunc() + } t.Run(tc.paramStr, func(t *testing.T) { httpRecorder := httptest.NewRecorder() c, _ := gin.CreateTestContext(httpRecorder) diff --git a/internal/sbi/processor/ulcl_procedure.go b/internal/sbi/processor/ulcl_procedure.go index f19d9455..eecfc383 100644 --- a/internal/sbi/processor/ulcl_procedure.go +++ b/internal/sbi/processor/ulcl_procedure.go @@ -87,8 +87,8 @@ func (p *Processor) EstablishPSA2(smContext *context.SMContext) { } // According to 32.255 5.2.2.7, Addition of additional PDU Session Anchor is a charging event - p.UpdateChargingSession(smContext, chgUrrList, models.Trigger{ - TriggerType: models.TriggerType_ADDITION_OF_UPF, + p.UpdateChargingSession(smContext, chgUrrList, models.ChfConvergedChargingTrigger{ + TriggerType: models.ChfConvergedChargingTriggerType_ADDITION_OF_UPF, TriggerCategory: models.TriggerCategory_IMMEDIATE_REPORT, }) diff --git a/internal/sbi/routes.go b/internal/sbi/routes.go index 124bbf8d..82767aa6 100644 --- a/internal/sbi/routes.go +++ b/internal/sbi/routes.go @@ -3,6 +3,7 @@ package sbi import "github.com/gin-gonic/gin" type Route struct { + Name string Method string Pattern string APIFunc gin.HandlerFunc diff --git a/internal/sbi/server.go b/internal/sbi/server.go index 04f3371d..1bd6a58a 100644 --- a/internal/sbi/server.go +++ b/internal/sbi/server.go @@ -32,6 +32,7 @@ type ServerSmf interface { Consumer() *consumer.Consumer Processor() *processor.Processor + CancelContext() context.Context } type Server struct { @@ -107,13 +108,9 @@ func newRouter(s *Server) *gin.Engine { } func (s *Server) Run(traceCtx context.Context, wg *sync.WaitGroup) error { - err := s.Consumer().RegisterNFInstance(context.Background()) + err := s.Consumer().RegisterNFInstance(s.CancelContext()) if err != nil { - retry_err := s.Consumer().RetrySendNFRegistration(10) - if retry_err != nil { - logger.InitLog.Errorln(retry_err) - return err - } + return err } wg.Add(1) diff --git a/internal/util/search_nf_service.go b/internal/util/search_nf_service.go index 32d5e79c..4147386a 100644 --- a/internal/util/search_nf_service.go +++ b/internal/util/search_nf_service.go @@ -6,11 +6,11 @@ import ( "github.com/free5gc/openapi/models" ) -func SearchNFServiceUri(nfProfile models.NfProfile, serviceName models.ServiceName, +func SearchNFServiceUri(nfProfile *models.NrfNfDiscoveryNfProfile, serviceName models.ServiceName, nfServiceStatus models.NfServiceStatus, ) (nfUri string) { if nfProfile.NfServices != nil { - for _, service := range *nfProfile.NfServices { + for _, service := range nfProfile.NfServices { if service.ServiceName == serviceName && service.NfServiceStatus == nfServiceStatus { if nfProfile.Fqdn != "" { nfUri = nfProfile.Fqdn @@ -19,7 +19,7 @@ func SearchNFServiceUri(nfProfile models.NfProfile, serviceName models.ServiceNa } else if service.ApiPrefix != "" { nfUri = service.ApiPrefix } else if service.IpEndPoints != nil { - point := (*service.IpEndPoints)[0] + point := service.IpEndPoints[0] if point.Ipv4Address != "" { nfUri = getSbiUri(service.Scheme, point.Ipv4Address, point.Port) } else if len(nfProfile.Ipv4Addresses) != 0 { diff --git a/pkg/errors/errors.go b/pkg/errors/errors.go new file mode 100644 index 00000000..3ef1fbe5 --- /dev/null +++ b/pkg/errors/errors.go @@ -0,0 +1,68 @@ +package errors + +import ( + "net/http" + + "github.com/free5gc/openapi/models" +) + +var ( + N1SmError = models.SmfPduSessionExtProblemDetails{ + Title: "Invalid N1 Message", + Status: http.StatusForbidden, + Detail: "N1 Message Error", + Cause: "N1_SM_ERROR", + } + N2SmError = models.SmfPduSessionExtProblemDetails{ + Title: "Invalid N2 Message", + Status: http.StatusForbidden, + Detail: "N2 Message Error", + Cause: "N2_SM_ERROR", + } + DnnDeniedError = models.SmfPduSessionExtProblemDetails{ + Title: "DNN Denied", + Status: http.StatusForbidden, + Detail: "The subscriber does not have the necessary subscription to access the DNN", + Cause: "DNN_DENIED", + InvalidParams: nil, + } + DnnNotSupported = models.SmfPduSessionExtProblemDetails{ + Title: "DNN Not Supported", + Status: http.StatusForbidden, + Detail: "The DNN is not supported by the SMF.", + Cause: "DNN_NOT_SUPPORTED", + InvalidParams: nil, + } + InsufficientResourceSliceDnn = models.SmfPduSessionExtProblemDetails{ + Title: "DNN Resource insufficient", + Status: http.StatusInternalServerError, + Detail: "The request cannot be provided due to insufficient resources for the specific slice and DNN.", + Cause: "INSUFFICIENT_RESOURCES_SLICE_DNN", + InvalidParams: nil, + } + SubscriptionDenied = models.SmfPduSessionExtProblemDetails{ + Title: "Subscription Denied", + Status: http.StatusForbidden, + Detail: "This indicates an error, other than those listed in this table, " + + "due to lack of necessary subscription to serve the UE request.", + Cause: "SUBSCRIPTION_DENIED", + InvalidParams: nil, + } + NetworkFailure = models.SmfPduSessionExtProblemDetails{ + Title: "Network failure", + Status: http.StatusGatewayTimeout, + Detail: "The request is rejected due to a network problem.", + Cause: "NETWORK_FAILURE", + InvalidParams: nil, + } + SmContextStateMismatchActive = models.SmfPduSessionExtProblemDetails{ + Title: "SMContext state mismatch", + Status: http.StatusForbidden, + Detail: "The SMContext State should be Active State.", + } + SmContextStateMismatchInActive = models.SmfPduSessionExtProblemDetails{ + Title: "SMContext state mismatch", + Status: http.StatusForbidden, + Detail: "The SMContext State should be InActive State.", + } +) diff --git a/pkg/service/init.go b/pkg/service/init.go index 00ec52cb..bcbb2ff4 100644 --- a/pkg/service/init.go +++ b/pkg/service/init.go @@ -9,6 +9,8 @@ import ( "github.com/sirupsen/logrus" + "github.com/free5gc/openapi" + "github.com/free5gc/openapi/nrf/NFManagement" smf_context "github.com/free5gc/smf/internal/context" "github.com/free5gc/smf/internal/logger" "github.com/free5gc/smf/internal/sbi" @@ -196,14 +198,23 @@ func (a *SmfApp) terminateProcedure() { logger.MainLog.Infof("Terminating SMF...") a.pfcpTerminate() // deregister with NRF - problemDetails, err := a.Consumer().SendDeregisterNFInstance() - if problemDetails != nil { - logger.MainLog.Errorf("Deregister NF instance Failed Problem[%+v]", problemDetails) - } else if err != nil { - logger.MainLog.Errorf("Deregister NF instance Error[%+v]", err) - } else { - logger.MainLog.Infof("Deregister from NRF successfully") + err := a.Consumer().SendDeregisterNFInstance() + if err != nil { + switch apiErr := err.(type) { + case openapi.GenericOpenAPIError: + switch errModel := apiErr.Model().(type) { + case NFManagement.DeregisterNFInstanceError: + pd := &errModel.ProblemDetails + logger.MainLog.Errorf("Deregister NF instance Failed Problem[%+v]", pd) + case error: + logger.MainLog.Errorf("Deregister NF instance Error[%+v]", err) + } + case error: + logger.MainLog.Errorf("Deregister NF instance Error[%+v]", err) + } } + logger.MainLog.Infof("Deregister from NRF successfully") + a.sbiServer.Stop() logger.MainLog.Infof("SMF SBI Server terminated") }