From 31cfed866f21684af76621b32b35cb85f584e446 Mon Sep 17 00:00:00 2001 From: adjivas Date: Tue, 20 May 2025 16:06:50 +0200 Subject: [PATCH 1/2] fix: add IPv6 support --- internal/context/context.go | 83 +++++-- internal/context/context_test.go | 345 ++++++++++++++++++++++++++ internal/gmm/handler.go | 23 +- internal/ngap/handler_test.go | 13 +- internal/ngap/message/build.go | 6 +- internal/sbi/consumer/nrf_service.go | 10 +- internal/sbi/consumer/pcf_service.go | 2 +- internal/sbi/consumer/smf_service.go | 2 +- internal/sbi/consumer/udm_service.go | 2 +- internal/sbi/processor/n1n2message.go | 4 +- internal/sbi/server.go | 9 +- internal/util/search_nf_service.go | 22 +- pkg/factory/config.go | 86 +++---- pkg/service/init.go | 2 +- 14 files changed, 516 insertions(+), 93 deletions(-) create mode 100644 internal/context/context_test.go diff --git a/internal/context/context.go b/internal/context/context.go index cdd342bf..4deb46ae 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -5,6 +5,8 @@ import ( "fmt" "math" "net" + "net/netip" + "os" "reflect" "strconv" "strings" @@ -66,9 +68,9 @@ type AMFContext struct { Name string NfService map[models.ServiceName]models.NrfNfManagementNfService // nfservice that amf support UriScheme models.UriScheme - BindingIPv4 string + BindingIP netip.Addr SBIPort int - RegisterIPv4 string + RegisterIP netip.Addr HttpIPv6Address string TNLWeightFactor int64 SupportDnnLists []string @@ -114,6 +116,7 @@ func InitAmfContext(context *AMFContext) { logger.UtilLog.Infof("amfconfig Info: Version[%s]", config.GetVersion()) configuration := config.Configuration context.NfId = uuid.New().String() + sbi := configuration.Sbi if configuration.AmfName != "" { context.Name = configuration.AmfName } @@ -123,10 +126,22 @@ func InitAmfContext(context *AMFContext) { context.NgapIpList = []string{"127.0.0.1"} // default localhost } context.NgapPort = config.GetNgapPort() - context.UriScheme = models.UriScheme(config.GetSbiScheme()) - context.RegisterIPv4 = config.GetSbiRegisterIP() - context.SBIPort = config.GetSbiPort() - context.BindingIPv4 = config.GetSbiBindingIP() + + context.SBIPort = sbi.Port + + context.UriScheme = models.UriScheme(sbi.Scheme) + + if bindingIP := os.Getenv(sbi.BindingIP); bindingIP != "" { + logger.UtilLog.Info("Parsing BindingIP address from ENV Variable.") + sbi.BindingIP = bindingIP + } + if registerIP := os.Getenv(sbi.RegisterIP); registerIP != "" { + logger.UtilLog.Info("Parsing RegisterIP address from ENV Variable.") + sbi.RegisterIP = registerIP + } + context.BindingIP = resolveIP(sbi.BindingIP) + context.RegisterIP = resolveIP(sbi.RegisterIP) + context.InitNFService(config.GetServiceNameList(), config.GetVersion()) context.ServedGuamiList = configuration.ServedGumaiList @@ -484,8 +499,44 @@ func (context *AMFContext) RanUeFindByAmfUeNgapID(amfUeNgapID int64) *RanUe { return nil } -func (context *AMFContext) GetIPv4Uri() string { - return fmt.Sprintf("%s://%s:%d", context.UriScheme, context.RegisterIPv4, context.SBIPort) +func (context *AMFContext) GetIPUri() string { + addr := context.RegisterIP + port := context.SBIPort + + return fmt.Sprintf("%s://%s", context.UriScheme, netip.AddrPortFrom(addr, uint16(port)).String()) +} + +func resolveIP(ip string) netip.Addr { + resolvedIPs, err := net.DefaultResolver.LookupNetIP(context.Background(), "ip", ip) + if err != nil { + logger.InitLog.Errorf("Lookup failed with %s: %+v", ip, err) + } + resolvedIP := resolvedIPs[0].Unmap() + if resolvedIP := resolvedIP.String(); resolvedIP != ip { + logger.UtilLog.Infof("Lookup revolved %s into %s", ip, resolvedIP) + } + return resolvedIP +} + +func GetIpEndPoint(context *AMFContext) []models.IpEndPoint { + if context.RegisterIP.Is6() { + return []models.IpEndPoint{ + { + Ipv6Address: context.RegisterIP.String(), + Transport: models.NrfNfManagementTransportProtocol_TCP, + Port: int32(context.SBIPort), + }, + } + } else if context.RegisterIP.Is4() { + return []models.IpEndPoint{ + { + Ipv4Address: context.RegisterIP.String(), + Transport: models.NrfNfManagementTransportProtocol_TCP, + Port: int32(context.SBIPort), + }, + } + } + return nil } func (context *AMFContext) InitNFService(serivceName []string, version string) { @@ -504,14 +555,8 @@ func (context *AMFContext) InitNFService(serivceName []string, version string) { }, Scheme: context.UriScheme, NfServiceStatus: models.NfServiceStatus_REGISTERED, - ApiPrefix: context.GetIPv4Uri(), - IpEndPoints: []models.IpEndPoint{ - { - Ipv4Address: context.RegisterIPv4, - Transport: models.NrfNfManagementTransportProtocol_TCP, - Port: int32(context.SBIPort), - }, - }, + ApiPrefix: context.GetIPUri(), + IpEndPoints: GetIpEndPoint(context), } } } @@ -547,13 +592,15 @@ func (context *AMFContext) Reset() { context.NfId = "" context.UriScheme = models.UriScheme_HTTPS context.SBIPort = 0 - context.BindingIPv4 = "" - context.RegisterIPv4 = "" context.HttpIPv6Address = "" context.Name = "amf" context.NrfUri = "" context.NrfCertPem = "" context.OAuth2Required = false + + var zeroAddr netip.Addr + context.BindingIP = zeroAddr + context.RegisterIP = zeroAddr } // Create new AMF context diff --git a/internal/context/context_test.go b/internal/context/context_test.go new file mode 100644 index 00000000..145ab927 --- /dev/null +++ b/internal/context/context_test.go @@ -0,0 +1,345 @@ +package context + +import ( + "errors" + "net/netip" + "os" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/free5gc/amf/pkg/factory" + "github.com/free5gc/openapi/models" +) + +func createConfigFile(t *testing.T, postContent []byte) *os.File { + content := []byte(`info: + version: "1.0.9" + +logger: + level: debug + +configuration: + security: + integrityOrder: + - NIA2 + + networkName: + full: free5GC + short: free + + amfName: AMF + ngapIpList: + - 127.0.0.19 + ngapPort: 38412 + + supportDnnList: + - internet + nrfUri: http://127.0.0.10:8000 + + serviceNameList: + - namf-comm + + servedGuamiList: + - plmnId: + mcc: 208 + mnc: 93 + amfId: cafe00 + + supportTaiList: + - plmnId: + mcc: 208 + mnc: 93 + tac: 000001 + + plmnSupportList: + - plmnId: + mcc: 208 + mnc: 93 + snssaiList: + - sst: 1 + sd: 010203 + - sst: 1 + sd: 112233 + + t3502Value: 720 + t3512Value: 3600 + t3513: + enable: true + t3522: + enable: true + t3550: + enable: true + t3555: + enable: true + t3560: + enable: true + t3565: + enable: true + t3570: + enable: true`) + + configFile, err := os.CreateTemp("", "") + if err != nil { + t.Errorf("can't create temp file: %+v", err) + } + + if _, err = configFile.Write(content); err != nil { + t.Errorf("can't write content of temp file: %+v", err) + } + if _, err = configFile.Write(postContent); err != nil { + t.Errorf("can't write content of temp file: %+v", err) + } + if err = configFile.Close(); err != nil { + t.Fatal(err) + } + return configFile +} + +func TestInitAmfContextWithConfigIPv6(t *testing.T) { + postContent := []byte(` + + sbi: + scheme: http + registerIP: 2001:db8::1:0:0:19 + bindingIP: 2001:db8::1:0:0:19 + port: 8000`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg + + InitAmfContext(GetSelf()) + + assert.Equal(t, amfContext.SBIPort, 8000) + assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:19") + assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:19") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) + + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitAmfContextWithConfigIPv4(t *testing.T) { + postContent := []byte(` + sbi: + scheme: http + registerIP: "127.0.0.13" + bindingIP: "127.0.0.13" + port: 8131`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg + + InitAmfContext(GetSelf()) + + assert.Equal(t, amfContext.SBIPort, 8131) + assert.Equal(t, amfContext.RegisterIP.String(), "127.0.0.13") + assert.Equal(t, amfContext.BindingIP.String(), "127.0.0.13") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) + + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitAmfContextWithConfigDeprecated(t *testing.T) { + postContent := []byte(` + sbi: + scheme: http + registerIPv4: "127.0.0.30" + bindingIPv4: "127.0.0.30" + port: 8003`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg + + InitAmfContext(GetSelf()) + + assert.Equal(t, amfContext.SBIPort, 8003) + assert.Equal(t, amfContext.RegisterIP.String(), "127.0.0.30") + assert.Equal(t, amfContext.BindingIP.String(), "127.0.0.30") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) + + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitAmfContextWithConfigEmptySBI(t *testing.T) { + postContent := []byte("") + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + _, err := factory.ReadConfig(configFile.Name()) + assert.Equal(t, err, errors.New("Config validate Error")) + + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitAmfContextWithConfigMissingRegisterIP(t *testing.T) { + postContent := []byte(` + sbi: + bindingIP: "2001:db8::1:0:0:130"`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg + + InitAmfContext(GetSelf()) + + assert.Equal(t, amfContext.SBIPort, 8000) + assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("https")) + + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitAmfContextWithConfigMissingBindingIP(t *testing.T) { + postContent := []byte(` + sbi: + registerIP: "2001:db8::1:0:0:131"`) + + configFile := createConfigFile(t, postContent) + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg + + InitAmfContext(GetSelf()) + + assert.Equal(t, amfContext.SBIPort, 8000) + assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:131") + assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:131") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("https")) + + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestInitAmfContextWithConfigIPv6FromEnv(t *testing.T) { + postContent := []byte(` + sbi: + scheme: http + registerIP: "MY_REGISTER_IP" + bindingIP: "MY_BINDING_IP" + port: 8313`) + + configFile := createConfigFile(t, postContent) + + if err := os.Setenv("MY_REGISTER_IP", "2001:db8::1:0:0:130"); err != nil { + t.Errorf("Can't set MY_REGISTER_IP env") + } + if err := os.Setenv("MY_BINDING_IP", "2001:db8::1:0:0:130"); err != nil { + t.Errorf("Can't set MY_BINDING_IP env") + } + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg + + InitAmfContext(GetSelf()) + + assert.Equal(t, amfContext.SBIPort, 8313) + assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) + + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) +} + +func TestResolveIPLocalhost(t *testing.T) { + expectedAddr, err := netip.ParseAddr("::1") + if err != nil { + t.Errorf("invalid expected IP: %+v", expectedAddr) + } + + addr := resolveIP("localhost") + if addr != expectedAddr { + t.Errorf("invalid IP: %+v", addr) + } + assert.Equal(t, addr, expectedAddr) +} + +func TestResolveIPv4(t *testing.T) { + expectedAddr, err := netip.ParseAddr("127.0.0.1") + if err != nil { + t.Errorf("invalid expected IP: %+v", expectedAddr) + } + + addr := resolveIP("127.0.0.1") + if addr != expectedAddr { + t.Errorf("invalid IP: %+v", addr) + } +} + +func TestResolveIPv6(t *testing.T) { + expectedAddr, err := netip.ParseAddr("2001:db8::1:0:0:1") + if err != nil { + t.Errorf("invalid expected IP: %+v", expectedAddr) + } + + addr := resolveIP("2001:db8::1:0:0:1") + if addr != expectedAddr { + t.Errorf("invalid IP: %+v", addr) + } +} diff --git a/internal/gmm/handler.go b/internal/gmm/handler.go index 71059086..b257db97 100644 --- a/internal/gmm/handler.go +++ b/internal/gmm/handler.go @@ -5,7 +5,9 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + "net" "net/http" + "net/netip" "reflect" "strconv" "strings" @@ -128,7 +130,7 @@ func transport5GSMMessage(ue *context.AmfUe, anType models.AccessType, Release: true, Cause: models.SmfPduSessionCause_REL_DUE_TO_DUPLICATE_SESSION_ID, SmContextStatusUri: fmt.Sprintf("%s"+factory.AmfCallbackResUriPrefix+"/smContextStatus/%s/%d", - ue.ServingAMF().GetIPv4Uri(), ue.Guti, pduSessionID), + ue.ServingAMF().GetIPUri(), ue.Guti, pduSessionID), } ue.GmmLog.Warningf("Duplicated PDU session ID[%d]", pduSessionID) smContext.SetDuplicatedPduSessionID(true) @@ -1211,7 +1213,18 @@ func handleRequestedNssai(ue *context.AmfUe, anType models.AccessType) error { // Condition (A) Step 7: initial AMF find Target AMF via NRF -> // Send Namf_Communication_N1MessageNotify to Target AMF ueContext := consumer.GetConsumer().BuildUeContextModel(ue) - registerContext := models.RegistrationContextContainer{ + AnN2IPAddr := ue.RanUe[anType].Ran.Conn.RemoteAddr().String() + ran_host, _, ran_err := net.SplitHostPort(AnN2IPAddr) + if ran_err != nil { + logger.GmmLog.Errorf("Can't split AnN2IPAddr %+v", ran_err) + return fmt.Errorf("Send Namf_Communication_N1MessageNotify to Target AMF failed") + } + ran_addr, ran_addr_err := netip.ParseAddr(ran_host) + if ran_addr_err != nil { + logger.GmmLog.Errorf("Can't parse AnN2IPAddr Host %+v", ran_addr_err) + return fmt.Errorf("Send Namf_Communication_N1MessageNotify to Target AMF failed") + } + var registerContext models.RegistrationContextContainer = models.RegistrationContextContainer{ UeContext: &ueContext, AnType: anType, AnN2ApId: int32(ue.RanUe[anType].RanUeNgapId), @@ -1220,12 +1233,16 @@ func handleRequestedNssai(ue *context.AmfUe, anType models.AccessType) error { UserLocation: &ue.Location, RrcEstCause: ue.RanUe[anType].RRCEstablishmentCause, UeContextRequest: ue.RanUe[anType].UeContextRequest, - AnN2IPv4Addr: ue.RanUe[anType].Ran.Conn.RemoteAddr().String(), AllowedNssai: &models.AllowedNssai{ AllowedSnssaiList: ue.AllowedNssai[anType], AccessType: anType, }, } + if ran_addr.Is6() { + registerContext.AnN2IPv6Addr = AnN2IPAddr + } else if ran_addr.Is4() { + registerContext.AnN2IPv4Addr = AnN2IPAddr + } if len(ue.NetworkSliceInfo.RejectedNssaiInPlmn) > 0 { registerContext.RejectedNssaiInPlmn = ue.NetworkSliceInfo.RejectedNssaiInPlmn } diff --git a/internal/ngap/handler_test.go b/internal/ngap/handler_test.go index 52bfbb35..a6222d3b 100644 --- a/internal/ngap/handler_test.go +++ b/internal/ngap/handler_test.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" "net" + "net/netip" "testing" "github.com/google/uuid" @@ -71,12 +72,12 @@ func NewAmfContext(amfCtx *amf_context.AMFContext) { *amfCtx = amf_context.AMFContext{ NfId: uuid.New().String(), - NgapIpList: []string{"127.0.0.1"}, - NgapPort: 38412, - UriScheme: "http", - RegisterIPv4: "127.0.0.18", - BindingIPv4: "127.0.0.18", - SBIPort: 8000, + NgapIpList: []string{"127.0.0.1"}, + NgapPort: 38412, + UriScheme: "http", + RegisterIP: netip.MustParseAddr("127.0.0.18"), + BindingIP: netip.MustParseAddr("127.0.0.18"), + SBIPort: 8000, ServedGuamiList: []models.Guami{ { PlmnId: &models.PlmnIdNid{ diff --git a/internal/ngap/message/build.go b/internal/ngap/message/build.go index 1ec906d3..c7b6ad71 100644 --- a/internal/ngap/message/build.go +++ b/internal/ngap/message/build.go @@ -3054,7 +3054,7 @@ func BuildAMFConfigurationUpdate(tNLassociationUsage ngapType.TNLAssociationUsag CPTransportLayerInformationPresentEndpointIPAddress aMFTNLAssociationToAddItem.AMFTNLAssociationAddress.EndpointIPAddress = new(ngapType.TransportLayerAddress) *aMFTNLAssociationToAddItem.AMFTNLAssociationAddress.EndpointIPAddress = ngapConvert. - IPAddressToNgap(amfSelf.RegisterIPv4, amfSelf.HttpIPv6Address) + IPAddressToNgap(amfSelf.RegisterIP.String(), amfSelf.HttpIPv6Address) // AMF TNL Association Usage[optional] if aMFTNLAssociationToAddItem.TNLAssociationUsage != nil { @@ -3083,7 +3083,7 @@ func BuildAMFConfigurationUpdate(tNLassociationUsage ngapType.TNLAssociationUsag CPTransportLayerInformationPresentEndpointIPAddress aMFTNLAssociationToRemoveItem.AMFTNLAssociationAddress.EndpointIPAddress = new(ngapType.TransportLayerAddress) *aMFTNLAssociationToRemoveItem.AMFTNLAssociationAddress.EndpointIPAddress = ngapConvert. - IPAddressToNgap(amfSelf.RegisterIPv4, amfSelf.HttpIPv6Address) + IPAddressToNgap(amfSelf.RegisterIP.String(), amfSelf.HttpIPv6Address) aMFTNLAssociationToRemoveList.List = append(aMFTNLAssociationToRemoveList.List, aMFTNLAssociationToRemoveItem) aMFConfigurationUpdateIEs.List = append(aMFConfigurationUpdateIEs.List, ie) @@ -3103,7 +3103,7 @@ func BuildAMFConfigurationUpdate(tNLassociationUsage ngapType.TNLAssociationUsag CPTransportLayerInformationPresentEndpointIPAddress aMFTNLAssociationToUpdateItem.AMFTNLAssociationAddress.EndpointIPAddress = new(ngapType.TransportLayerAddress) *aMFTNLAssociationToUpdateItem.AMFTNLAssociationAddress.EndpointIPAddress = ngapConvert. - IPAddressToNgap(amfSelf.RegisterIPv4, amfSelf.HttpIPv6Address) + IPAddressToNgap(amfSelf.RegisterIP.String(), amfSelf.HttpIPv6Address) // TNLAssociationUsage in AMFTNLAssociationtoUpdateItem [optional] if aMFTNLAssociationToUpdateItem.TNLAssociationUsage != nil { diff --git a/internal/sbi/consumer/nrf_service.go b/internal/sbi/consumer/nrf_service.go index 7cc1b433..4fbfd2c1 100644 --- a/internal/sbi/consumer/nrf_service.go +++ b/internal/sbi/consumer/nrf_service.go @@ -221,11 +221,15 @@ func (s *nnrfService) BuildNFInstance(context *amf_context.AMFContext) ( } amfInfo.TaiList = context.SupportTaiLists profile.AmfInfo = &amfInfo - if context.RegisterIPv4 == "" { + if !context.RegisterIP.IsValid() { err = fmt.Errorf("AMF Address is empty") return profile, err } - profile.Ipv4Addresses = append(profile.Ipv4Addresses, context.RegisterIPv4) + if context.RegisterIP.Is6() { + profile.Ipv6Addresses = append(profile.Ipv6Addresses, context.RegisterIP.String()) + } else if context.RegisterIP.Is4() { + profile.Ipv4Addresses = append(profile.Ipv4Addresses, context.RegisterIP.String()) + } service := []models.NrfNfManagementNfService{} for _, nfService := range context.NfService { service = append(service, nfService) @@ -235,7 +239,7 @@ func (s *nnrfService) BuildNFInstance(context *amf_context.AMFContext) ( } defaultNotificationSubscription := models.DefaultNotificationSubscription{ - CallbackUri: fmt.Sprintf("%s"+factory.AmfCallbackResUriPrefix+"/n1-message-notify", context.GetIPv4Uri()), + CallbackUri: fmt.Sprintf("%s"+factory.AmfCallbackResUriPrefix+"/n1-message-notify", context.GetIPUri()), NotificationType: models.NrfNfManagementNotificationType_N1_MESSAGES, N1MessageClass: models.N1MessageClass__5_GMM, } diff --git a/internal/sbi/consumer/pcf_service.go b/internal/sbi/consumer/pcf_service.go index 7ddf101a..42a3fc5b 100644 --- a/internal/sbi/consumer/pcf_service.go +++ b/internal/sbi/consumer/pcf_service.go @@ -59,7 +59,7 @@ func (s *npcfService) AMPolicyControlCreate( } policyAssociationRequest := models.PcfAmPolicyControlPolicyAssociationRequest{ - NotificationUri: amfSelf.GetIPv4Uri() + factory.AmfCallbackResUriPrefix + "/am-policy/", + NotificationUri: amfSelf.GetIPUri() + factory.AmfCallbackResUriPrefix + "/am-policy/", Supi: ue.Supi, Pei: ue.Pei, Gpsi: ue.Gpsi, diff --git a/internal/sbi/consumer/smf_service.go b/internal/sbi/consumer/smf_service.go index 79c3764f..61af7af8 100644 --- a/internal/sbi/consumer/smf_service.go +++ b/internal/sbi/consumer/smf_service.go @@ -234,7 +234,7 @@ func (s *nsmfService) buildCreateSmContextRequest(ue *amf_context.AmfUe, smConte } smContextCreateData.UeLocation = &ue.Location smContextCreateData.UeTimeZone = ue.TimeZone - smContextCreateData.SmContextStatusUri = context.GetIPv4Uri() + factory.AmfCallbackResUriPrefix + "/smContextStatus/" + + smContextCreateData.SmContextStatusUri = context.GetIPUri() + factory.AmfCallbackResUriPrefix + "/smContextStatus/" + ue.Supi + "/" + strconv.Itoa(int(smContext.PduSessionID())) return smContextCreateData diff --git a/internal/sbi/consumer/udm_service.go b/internal/sbi/consumer/udm_service.go index 19f99e58..dced865b 100644 --- a/internal/sbi/consumer/udm_service.go +++ b/internal/sbi/consumer/udm_service.go @@ -396,7 +396,7 @@ func (s *nudmService) UeCmRegistration( switch accessType { case models.AccessType__3_GPP_ACCESS: deregCallbackUri := fmt.Sprintf("%s%s/deregistration/%s", - amfSelf.GetIPv4Uri(), + amfSelf.GetIPUri(), factory.AmfCallbackResUriPrefix, ue.Supi, ) diff --git a/internal/sbi/processor/n1n2message.go b/internal/sbi/processor/n1n2message.go index 6432ecd5..f3f0a6f9 100644 --- a/internal/sbi/processor/n1n2message.go +++ b/internal/sbi/processor/n1n2message.go @@ -296,7 +296,7 @@ func (p *Processor) N1N2MessageTransferProcedure(ueContextID string, reqUri stri } else { n1n2MessageID = n1n2MessageIDTmp } - locationHeader = context.GetSelf().GetIPv4Uri() + reqUri + "/" + strconv.Itoa(int(n1n2MessageID)) + locationHeader = context.GetSelf().GetIPUri() + reqUri + "/" + strconv.Itoa(int(n1n2MessageID)) // Case A (UE is CM-IDLE in 3GPP access and the associated access type is 3GPP access) // in subclause 5.2.2.3.1.2 of TS29518 @@ -416,7 +416,7 @@ func (p *Processor) N1N2MessageTransferStatusProcedure(ueContextID string, ue.Lock.Lock() defer ue.Lock.Unlock() - resourceUri := amfSelf.GetIPv4Uri() + reqUri + resourceUri := amfSelf.GetIPUri() + reqUri n1n2Message := ue.N1N2Message if n1n2Message == nil || n1n2Message.ResourceUri != resourceUri { problemDetails := &models.ProblemDetails{ diff --git a/internal/sbi/server.go b/internal/sbi/server.go index c9e2dec3..e14f91eb 100644 --- a/internal/sbi/server.go +++ b/internal/sbi/server.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "net/http" + "net/netip" "runtime/debug" "sync" "time" @@ -52,8 +53,12 @@ func NewServer(amf ServerAmf, tlsKeyLogPath string) (*Server, error) { s.router = newRouter(s) - cfg := s.Config() - bindAddr := cfg.GetSbiBindingAddr() + amf_context.InitAmfContext(amf.Context()) + + port := amf.Context().SBIPort + addr := amf.Context().BindingIP + bindAddr := netip.AddrPortFrom(addr, uint16(port)).String() + logger.SBILog.Infof("Binding addr: [%s]", bindAddr) var err error if s.httpServer, err = httpwrapper.NewHttp2Server(bindAddr, tlsKeyLogPath, s.router); err != nil { diff --git a/internal/util/search_nf_service.go b/internal/util/search_nf_service.go index ef762a3c..51d1e3b6 100644 --- a/internal/util/search_nf_service.go +++ b/internal/util/search_nf_service.go @@ -2,7 +2,9 @@ package util import ( "fmt" + "net/netip" + "github.com/free5gc/amf/internal/logger" "github.com/free5gc/openapi/models" ) @@ -20,7 +22,11 @@ func SearchNFServiceUri(nfProfile *models.NrfNfDiscoveryNfProfile, serviceName m nfUri = service.ApiPrefix } else if service.IpEndPoints != nil { point := (service.IpEndPoints)[0] - if point.Ipv4Address != "" { + if point.Ipv6Address != "" { + nfUri = getSbiUri(service.Scheme, point.Ipv6Address, point.Port) + } else if len(nfProfile.Ipv6Addresses) != 0 { + nfUri = getSbiUri(service.Scheme, nfProfile.Ipv6Addresses[0], point.Port) + } else if point.Ipv4Address != "" { nfUri = getSbiUri(service.Scheme, point.Ipv4Address, point.Port) } else if len(nfProfile.Ipv4Addresses) != 0 { nfUri = getSbiUri(service.Scheme, nfProfile.Ipv4Addresses[0], point.Port) @@ -32,18 +38,22 @@ func SearchNFServiceUri(nfProfile *models.NrfNfDiscoveryNfProfile, serviceName m } } } - return + return nfUri } -func getSbiUri(scheme models.UriScheme, ipv4Address string, port int32) (uri string) { +func getSbiUri(scheme models.UriScheme, ipAddress string, port int32) (uri string) { + addr, err := netip.ParseAddr(ipAddress) + if err != nil { + logger.InitLog.Errorf("Parse RegisterIP hostname %s failed: %+v", ipAddress, err) + } if port != 0 { - uri = fmt.Sprintf("%s://%s:%d", scheme, ipv4Address, port) + uri = fmt.Sprintf("%s://%s", scheme, netip.AddrPortFrom(addr, uint16(port)).String()) } else { switch scheme { case models.UriScheme_HTTP: - uri = fmt.Sprintf("%s://%s:80", scheme, ipv4Address) + uri = fmt.Sprintf("%s://%s", scheme, netip.AddrPortFrom(addr, 80).String()) case models.UriScheme_HTTPS: - uri = fmt.Sprintf("%s://%s:443", scheme, ipv4Address) + uri = fmt.Sprintf("%s://%s", scheme, netip.AddrPortFrom(addr, 443).String()) } } return diff --git a/pkg/factory/config.go b/pkg/factory/config.go index ddebc254..4d9f1c22 100644 --- a/pkg/factory/config.go +++ b/pkg/factory/config.go @@ -6,8 +6,6 @@ package factory import ( "fmt" - "os" - "strconv" "sync" "time" @@ -23,7 +21,7 @@ const ( AmfDefaultCertPemPath = "./cert/amf.pem" AmfDefaultPrivateKeyPath = "./cert/amf.key" AmfDefaultConfigPath = "./config/amfcfg.yaml" - AmfSbiDefaultIPv4 = "127.0.0.18" + AmfSbiDefaultIP = "127.0.0.18" AmfSbiDefaultPort = 8000 AmfSbiDefaultScheme = "https" AmfMetricsDefaultEnabled = false @@ -340,25 +338,55 @@ func (m *Metrics) validate() (bool, error) { } type Sbi struct { - Scheme string `yaml:"scheme" valid:"required,scheme"` - RegisterIPv4 string `yaml:"registerIPv4,omitempty" valid:"required,host"` // IP that is registered at NRF. - BindingIPv4 string `yaml:"bindingIPv4,omitempty" valid:"required,host"` // IP used to run the server in the node. - Port int `yaml:"port,omitempty" valid:"required,port"` + Scheme string `yaml:"scheme" valid:"in(http|https),optional"` + RegisterIPv4 string `yaml:"registerIPv4,omitempty" valid:"host,optional"` // IP that is registered at NRF. + RegisterIP string `yaml:"registerIP,omitempty" valid:"host,optional"` // IP that is registered at NRF. + BindingIPv4 string `yaml:"bindingIPv4,omitempty" valid:"host,optional"` // IP used to run the server in the node. + BindingIP string `yaml:"bindingIP,omitempty" valid:"host,optional"` // IP used to run the server in the node. + Port int `yaml:"port,omitempty" valid:"port,optional"` Tls *Tls `yaml:"tls,omitempty" valid:"optional"` } func (s *Sbi) validate() (bool, error) { + // Set a default Schme if the Configuration does not provides one + if s.Scheme == "" { + s.Scheme = AmfSbiDefaultScheme + } + + // Set BindingIP/RegisterIP from deprecated BindingIPv4/RegisterIPv4 + if s.BindingIP == "" && s.BindingIPv4 != "" { + s.BindingIP = s.BindingIPv4 + } + if s.RegisterIP == "" && s.RegisterIPv4 != "" { + s.RegisterIP = s.RegisterIPv4 + } + + // Set a default BindingIP/RegisterIP if the Configuration does not provides them + if s.BindingIP == "" && s.RegisterIP == "" { + s.BindingIP = AmfSbiDefaultIP + s.RegisterIP = AmfSbiDefaultIP + } else { + // Complete any missing BindingIP/RegisterIP from RegisterIP/BindingIP + if s.BindingIP == "" { + s.BindingIP = s.RegisterIP + } else if s.RegisterIP == "" { + s.RegisterIP = s.BindingIP + } + } + + // Set a default Port if the Configuration does not provides one + if s.Port == 0 { + s.Port = AmfSbiDefaultPort + } + if tls := s.Tls; tls != nil { if result, err := tls.validate(); err != nil { return result, err } } - if _, err := govalidator.ValidateStruct(s); err != nil { - return false, appendInvalid(err) - } - - return true, nil + result, err := govalidator.ValidateStruct(s) + return result, err } type Tls struct { @@ -893,40 +921,6 @@ func (c *Config) GetSbiPort() int { return AmfSbiDefaultPort } -func (c *Config) GetSbiBindingIP() string { - bindIP := "0.0.0.0" - if c.Configuration == nil || c.Configuration.Sbi == nil { - return bindIP - } - if c.Configuration.Sbi.BindingIPv4 != "" { - if bindIP = os.Getenv(c.Configuration.Sbi.BindingIPv4); bindIP != "" { - logger.CfgLog.Infof("Parsing ServerIPv4 [%s] from ENV Variable", bindIP) - } else { - bindIP = c.Configuration.Sbi.BindingIPv4 - } - } - return bindIP -} - -func (c *Config) GetSbiBindingAddr() string { - return c.GetSbiBindingIP() + ":" + strconv.Itoa(c.GetSbiPort()) -} - -func (c *Config) GetSbiRegisterIP() string { - if c.Configuration != nil && c.Configuration.Sbi != nil && c.Configuration.Sbi.RegisterIPv4 != "" { - return c.Configuration.Sbi.RegisterIPv4 - } - return AmfSbiDefaultIPv4 -} - -func (c *Config) GetSbiRegisterAddr() string { - return c.GetSbiRegisterIP() + ":" + strconv.Itoa(c.GetSbiPort()) -} - -func (c *Config) GetSbiUri() string { - return c.GetSbiScheme() + "://" + c.GetSbiRegisterAddr() -} - func (c *Config) GetNrfUri() string { if c.Configuration != nil && c.Configuration.NrfUri != "" { return c.Configuration.NrfUri diff --git a/pkg/service/init.go b/pkg/service/init.go index dfd4b313..b9dc39d5 100644 --- a/pkg/service/init.go +++ b/pkg/service/init.go @@ -209,7 +209,7 @@ func (a *AmfApp) Start() { } var profile models.NrfNfManagementNfProfile - if profileTmp, err1 := a.Consumer().BuildNFInstance(a.Context()); err1 != nil { + if profileTmp, err1 := a.Consumer().BuildNFInstance(self); err1 != nil { logger.InitLog.Error("Build AMF Profile Error") } else { profile = profileTmp From 818cfd9eb66afbe542dc194ca1f4fba18fbc3e4d Mon Sep 17 00:00:00 2001 From: adjivas Date: Tue, 20 May 2025 16:07:18 +0200 Subject: [PATCH 2/2] fix: format --- internal/context/context.go | 29 ++- internal/context/context_test.go | 374 +++++++++++++++---------------- internal/gmm/handler.go | 10 +- internal/ngap/handler_test.go | 12 +- internal/sbi/server.go | 6 +- pkg/factory/config.go | 4 +- 6 files changed, 217 insertions(+), 218 deletions(-) diff --git a/internal/context/context.go b/internal/context/context.go index 4deb46ae..87045c47 100644 --- a/internal/context/context.go +++ b/internal/context/context.go @@ -127,21 +127,20 @@ func InitAmfContext(context *AMFContext) { } context.NgapPort = config.GetNgapPort() - context.SBIPort = sbi.Port - - context.UriScheme = models.UriScheme(sbi.Scheme) - - if bindingIP := os.Getenv(sbi.BindingIP); bindingIP != "" { - logger.UtilLog.Info("Parsing BindingIP address from ENV Variable.") - sbi.BindingIP = bindingIP - } - if registerIP := os.Getenv(sbi.RegisterIP); registerIP != "" { - logger.UtilLog.Info("Parsing RegisterIP address from ENV Variable.") - sbi.RegisterIP = registerIP - } - context.BindingIP = resolveIP(sbi.BindingIP) - context.RegisterIP = resolveIP(sbi.RegisterIP) - + context.SBIPort = sbi.Port + + context.UriScheme = models.UriScheme(sbi.Scheme) + + if bindingIP := os.Getenv(sbi.BindingIP); bindingIP != "" { + logger.UtilLog.Info("Parsing BindingIP address from ENV Variable.") + sbi.BindingIP = bindingIP + } + if registerIP := os.Getenv(sbi.RegisterIP); registerIP != "" { + logger.UtilLog.Info("Parsing RegisterIP address from ENV Variable.") + sbi.RegisterIP = registerIP + } + context.BindingIP = resolveIP(sbi.BindingIP) + context.RegisterIP = resolveIP(sbi.RegisterIP) context.InitNFService(config.GetServiceNameList(), config.GetVersion()) context.ServedGuamiList = configuration.ServedGumaiList diff --git a/internal/context/context_test.go b/internal/context/context_test.go index 145ab927..cb8d73e1 100644 --- a/internal/context/context_test.go +++ b/internal/context/context_test.go @@ -1,19 +1,19 @@ package context import ( - "errors" - "net/netip" - "os" - "testing" + "errors" + "net/netip" + "os" + "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/assert" - "github.com/free5gc/amf/pkg/factory" - "github.com/free5gc/openapi/models" + "github.com/free5gc/amf/pkg/factory" + "github.com/free5gc/openapi/models" ) func createConfigFile(t *testing.T, postContent []byte) *os.File { - content := []byte(`info: + content := []byte(`info: version: "1.0.9" logger: @@ -79,25 +79,25 @@ configuration: t3570: enable: true`) - configFile, err := os.CreateTemp("", "") - if err != nil { - t.Errorf("can't create temp file: %+v", err) - } - - if _, err = configFile.Write(content); err != nil { - t.Errorf("can't write content of temp file: %+v", err) - } - if _, err = configFile.Write(postContent); err != nil { - t.Errorf("can't write content of temp file: %+v", err) - } - if err = configFile.Close(); err != nil { - t.Fatal(err) - } - return configFile + configFile, err := os.CreateTemp("", "") + if err != nil { + t.Errorf("can't create temp file: %+v", err) + } + + if _, err = configFile.Write(content); err != nil { + t.Errorf("can't write content of temp file: %+v", err) + } + if _, err = configFile.Write(postContent); err != nil { + t.Errorf("can't write content of temp file: %+v", err) + } + if err = configFile.Close(); err != nil { + t.Fatal(err) + } + return configFile } func TestInitAmfContextWithConfigIPv6(t *testing.T) { - postContent := []byte(` + postContent := []byte(` sbi: scheme: http @@ -105,241 +105,241 @@ func TestInitAmfContextWithConfigIPv6(t *testing.T) { bindingIP: 2001:db8::1:0:0:19 port: 8000`) - configFile := createConfigFile(t, postContent) + configFile := createConfigFile(t, postContent) - // Test the initialization with the config file - cfg, err := factory.ReadConfig(configFile.Name()) - if err != nil { - t.Errorf("invalid read config: %+v %+v", err, cfg) - } - factory.AmfConfig = cfg + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg - InitAmfContext(GetSelf()) + InitAmfContext(GetSelf()) - assert.Equal(t, amfContext.SBIPort, 8000) - assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:19") - assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:19") - assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) + assert.Equal(t, amfContext.SBIPort, 8000) + assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:19") + assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:19") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) - // Close the config file - t.Cleanup(func() { - if err = os.RemoveAll(configFile.Name()); err != nil { - t.Fatal(err) - } - }) + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) } func TestInitAmfContextWithConfigIPv4(t *testing.T) { - postContent := []byte(` + postContent := []byte(` sbi: scheme: http registerIP: "127.0.0.13" bindingIP: "127.0.0.13" port: 8131`) - configFile := createConfigFile(t, postContent) + configFile := createConfigFile(t, postContent) - // Test the initialization with the config file - cfg, err := factory.ReadConfig(configFile.Name()) - if err != nil { - t.Errorf("invalid read config: %+v %+v", err, cfg) - } - factory.AmfConfig = cfg + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg - InitAmfContext(GetSelf()) + InitAmfContext(GetSelf()) - assert.Equal(t, amfContext.SBIPort, 8131) - assert.Equal(t, amfContext.RegisterIP.String(), "127.0.0.13") - assert.Equal(t, amfContext.BindingIP.String(), "127.0.0.13") - assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) + assert.Equal(t, amfContext.SBIPort, 8131) + assert.Equal(t, amfContext.RegisterIP.String(), "127.0.0.13") + assert.Equal(t, amfContext.BindingIP.String(), "127.0.0.13") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) - // Close the config file - t.Cleanup(func() { - if err = os.RemoveAll(configFile.Name()); err != nil { - t.Fatal(err) - } - }) + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) } func TestInitAmfContextWithConfigDeprecated(t *testing.T) { - postContent := []byte(` + postContent := []byte(` sbi: scheme: http registerIPv4: "127.0.0.30" bindingIPv4: "127.0.0.30" port: 8003`) - configFile := createConfigFile(t, postContent) + configFile := createConfigFile(t, postContent) - // Test the initialization with the config file - cfg, err := factory.ReadConfig(configFile.Name()) - if err != nil { - t.Errorf("invalid read config: %+v %+v", err, cfg) - } - factory.AmfConfig = cfg + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg - InitAmfContext(GetSelf()) + InitAmfContext(GetSelf()) - assert.Equal(t, amfContext.SBIPort, 8003) - assert.Equal(t, amfContext.RegisterIP.String(), "127.0.0.30") - assert.Equal(t, amfContext.BindingIP.String(), "127.0.0.30") - assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) + assert.Equal(t, amfContext.SBIPort, 8003) + assert.Equal(t, amfContext.RegisterIP.String(), "127.0.0.30") + assert.Equal(t, amfContext.BindingIP.String(), "127.0.0.30") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) - // Close the config file - t.Cleanup(func() { - if err = os.RemoveAll(configFile.Name()); err != nil { - t.Fatal(err) - } - }) + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) } func TestInitAmfContextWithConfigEmptySBI(t *testing.T) { - postContent := []byte("") + postContent := []byte("") - configFile := createConfigFile(t, postContent) + configFile := createConfigFile(t, postContent) - // Test the initialization with the config file - _, err := factory.ReadConfig(configFile.Name()) - assert.Equal(t, err, errors.New("Config validate Error")) + // Test the initialization with the config file + _, err := factory.ReadConfig(configFile.Name()) + assert.Equal(t, err, errors.New("Config validate Error")) - // Close the config file - t.Cleanup(func() { - if err = os.RemoveAll(configFile.Name()); err != nil { - t.Fatal(err) - } - }) + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) } func TestInitAmfContextWithConfigMissingRegisterIP(t *testing.T) { - postContent := []byte(` + postContent := []byte(` sbi: bindingIP: "2001:db8::1:0:0:130"`) - configFile := createConfigFile(t, postContent) + configFile := createConfigFile(t, postContent) - // Test the initialization with the config file - cfg, err := factory.ReadConfig(configFile.Name()) - if err != nil { - t.Errorf("invalid read config: %+v %+v", err, cfg) - } - factory.AmfConfig = cfg + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg - InitAmfContext(GetSelf()) + InitAmfContext(GetSelf()) - assert.Equal(t, amfContext.SBIPort, 8000) - assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:130") - assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:130") - assert.Equal(t, amfContext.UriScheme, models.UriScheme("https")) + assert.Equal(t, amfContext.SBIPort, 8000) + assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("https")) - // Close the config file - t.Cleanup(func() { - if err = os.RemoveAll(configFile.Name()); err != nil { - t.Fatal(err) - } - }) + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) } func TestInitAmfContextWithConfigMissingBindingIP(t *testing.T) { - postContent := []byte(` + postContent := []byte(` sbi: registerIP: "2001:db8::1:0:0:131"`) - configFile := createConfigFile(t, postContent) + configFile := createConfigFile(t, postContent) - // Test the initialization with the config file - cfg, err := factory.ReadConfig(configFile.Name()) - if err != nil { - t.Errorf("invalid read config: %+v %+v", err, cfg) - } - factory.AmfConfig = cfg + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg - InitAmfContext(GetSelf()) + InitAmfContext(GetSelf()) - assert.Equal(t, amfContext.SBIPort, 8000) - assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:131") - assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:131") - assert.Equal(t, amfContext.UriScheme, models.UriScheme("https")) + assert.Equal(t, amfContext.SBIPort, 8000) + assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:131") + assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:131") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("https")) - // Close the config file - t.Cleanup(func() { - if err = os.RemoveAll(configFile.Name()); err != nil { - t.Fatal(err) - } - }) + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) } func TestInitAmfContextWithConfigIPv6FromEnv(t *testing.T) { - postContent := []byte(` + postContent := []byte(` sbi: scheme: http registerIP: "MY_REGISTER_IP" bindingIP: "MY_BINDING_IP" port: 8313`) - configFile := createConfigFile(t, postContent) - - if err := os.Setenv("MY_REGISTER_IP", "2001:db8::1:0:0:130"); err != nil { - t.Errorf("Can't set MY_REGISTER_IP env") - } - if err := os.Setenv("MY_BINDING_IP", "2001:db8::1:0:0:130"); err != nil { - t.Errorf("Can't set MY_BINDING_IP env") - } - - // Test the initialization with the config file - cfg, err := factory.ReadConfig(configFile.Name()) - if err != nil { - t.Errorf("invalid read config: %+v %+v", err, cfg) - } - factory.AmfConfig = cfg - - InitAmfContext(GetSelf()) - - assert.Equal(t, amfContext.SBIPort, 8313) - assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:130") - assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:130") - assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) - - // Close the config file - t.Cleanup(func() { - if err = os.RemoveAll(configFile.Name()); err != nil { - t.Fatal(err) - } - }) + configFile := createConfigFile(t, postContent) + + if err := os.Setenv("MY_REGISTER_IP", "2001:db8::1:0:0:130"); err != nil { + t.Errorf("Can't set MY_REGISTER_IP env") + } + if err := os.Setenv("MY_BINDING_IP", "2001:db8::1:0:0:130"); err != nil { + t.Errorf("Can't set MY_BINDING_IP env") + } + + // Test the initialization with the config file + cfg, err := factory.ReadConfig(configFile.Name()) + if err != nil { + t.Errorf("invalid read config: %+v %+v", err, cfg) + } + factory.AmfConfig = cfg + + InitAmfContext(GetSelf()) + + assert.Equal(t, amfContext.SBIPort, 8313) + assert.Equal(t, amfContext.RegisterIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, amfContext.BindingIP.String(), "2001:db8::1:0:0:130") + assert.Equal(t, amfContext.UriScheme, models.UriScheme("http")) + + // Close the config file + t.Cleanup(func() { + if err = os.RemoveAll(configFile.Name()); err != nil { + t.Fatal(err) + } + }) } func TestResolveIPLocalhost(t *testing.T) { - expectedAddr, err := netip.ParseAddr("::1") - if err != nil { - t.Errorf("invalid expected IP: %+v", expectedAddr) - } - - addr := resolveIP("localhost") - if addr != expectedAddr { - t.Errorf("invalid IP: %+v", addr) - } - assert.Equal(t, addr, expectedAddr) + expectedAddr, err := netip.ParseAddr("::1") + if err != nil { + t.Errorf("invalid expected IP: %+v", expectedAddr) + } + + addr := resolveIP("localhost") + if addr != expectedAddr { + t.Errorf("invalid IP: %+v", addr) + } + assert.Equal(t, addr, expectedAddr) } func TestResolveIPv4(t *testing.T) { - expectedAddr, err := netip.ParseAddr("127.0.0.1") - if err != nil { - t.Errorf("invalid expected IP: %+v", expectedAddr) - } - - addr := resolveIP("127.0.0.1") - if addr != expectedAddr { - t.Errorf("invalid IP: %+v", addr) - } + expectedAddr, err := netip.ParseAddr("127.0.0.1") + if err != nil { + t.Errorf("invalid expected IP: %+v", expectedAddr) + } + + addr := resolveIP("127.0.0.1") + if addr != expectedAddr { + t.Errorf("invalid IP: %+v", addr) + } } func TestResolveIPv6(t *testing.T) { - expectedAddr, err := netip.ParseAddr("2001:db8::1:0:0:1") - if err != nil { - t.Errorf("invalid expected IP: %+v", expectedAddr) - } - - addr := resolveIP("2001:db8::1:0:0:1") - if addr != expectedAddr { - t.Errorf("invalid IP: %+v", addr) - } + expectedAddr, err := netip.ParseAddr("2001:db8::1:0:0:1") + if err != nil { + t.Errorf("invalid expected IP: %+v", expectedAddr) + } + + addr := resolveIP("2001:db8::1:0:0:1") + if addr != expectedAddr { + t.Errorf("invalid IP: %+v", addr) + } } diff --git a/internal/gmm/handler.go b/internal/gmm/handler.go index b257db97..0e98ee61 100644 --- a/internal/gmm/handler.go +++ b/internal/gmm/handler.go @@ -1224,7 +1224,7 @@ func handleRequestedNssai(ue *context.AmfUe, anType models.AccessType) error { logger.GmmLog.Errorf("Can't parse AnN2IPAddr Host %+v", ran_addr_err) return fmt.Errorf("Send Namf_Communication_N1MessageNotify to Target AMF failed") } - var registerContext models.RegistrationContextContainer = models.RegistrationContextContainer{ + var registerContext models.RegistrationContextContainer = models.RegistrationContextContainer{ UeContext: &ueContext, AnType: anType, AnN2ApId: int32(ue.RanUe[anType].RanUeNgapId), @@ -1239,10 +1239,10 @@ func handleRequestedNssai(ue *context.AmfUe, anType models.AccessType) error { }, } if ran_addr.Is6() { - registerContext.AnN2IPv6Addr = AnN2IPAddr - } else if ran_addr.Is4() { - registerContext.AnN2IPv4Addr = AnN2IPAddr - } + registerContext.AnN2IPv6Addr = AnN2IPAddr + } else if ran_addr.Is4() { + registerContext.AnN2IPv4Addr = AnN2IPAddr + } if len(ue.NetworkSliceInfo.RejectedNssaiInPlmn) > 0 { registerContext.RejectedNssaiInPlmn = ue.NetworkSliceInfo.RejectedNssaiInPlmn } diff --git a/internal/ngap/handler_test.go b/internal/ngap/handler_test.go index a6222d3b..c90c29e2 100644 --- a/internal/ngap/handler_test.go +++ b/internal/ngap/handler_test.go @@ -72,12 +72,12 @@ func NewAmfContext(amfCtx *amf_context.AMFContext) { *amfCtx = amf_context.AMFContext{ NfId: uuid.New().String(), - NgapIpList: []string{"127.0.0.1"}, - NgapPort: 38412, - UriScheme: "http", - RegisterIP: netip.MustParseAddr("127.0.0.18"), - BindingIP: netip.MustParseAddr("127.0.0.18"), - SBIPort: 8000, + NgapIpList: []string{"127.0.0.1"}, + NgapPort: 38412, + UriScheme: "http", + RegisterIP: netip.MustParseAddr("127.0.0.18"), + BindingIP: netip.MustParseAddr("127.0.0.18"), + SBIPort: 8000, ServedGuamiList: []models.Guami{ { PlmnId: &models.PlmnIdNid{ diff --git a/internal/sbi/server.go b/internal/sbi/server.go index e14f91eb..dc63e6a7 100644 --- a/internal/sbi/server.go +++ b/internal/sbi/server.go @@ -55,9 +55,9 @@ func NewServer(amf ServerAmf, tlsKeyLogPath string) (*Server, error) { amf_context.InitAmfContext(amf.Context()) - port := amf.Context().SBIPort - addr := amf.Context().BindingIP - bindAddr := netip.AddrPortFrom(addr, uint16(port)).String() + port := amf.Context().SBIPort + addr := amf.Context().BindingIP + bindAddr := netip.AddrPortFrom(addr, uint16(port)).String() logger.SBILog.Infof("Binding addr: [%s]", bindAddr) var err error diff --git a/pkg/factory/config.go b/pkg/factory/config.go index 4d9f1c22..072d0ecb 100644 --- a/pkg/factory/config.go +++ b/pkg/factory/config.go @@ -385,8 +385,8 @@ func (s *Sbi) validate() (bool, error) { } } - result, err := govalidator.ValidateStruct(s) - return result, err + result, err := govalidator.ValidateStruct(s) + return result, err } type Tls struct {