Skip to content

Commit

Permalink
refactor: VerifyStaticIp and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
andy89923 committed Aug 23, 2024
1 parent 2c29747 commit e8fbc20
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 37 deletions.
117 changes: 80 additions & 37 deletions backend/WebUI/api_verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

type VerifyScope struct {
Supi string `json:"supi"`
Sd string `json:"sd"`
Sd string `json:"sd,omitempty"`
Sst int `json:"sst"`
Dnn string `json:"dnn"`
Ipaddr string `json:"ipaddr"`
Expand Down Expand Up @@ -75,13 +75,14 @@ func GetSmfUserPlaneInfo() (interface{}, error) {
return jsonData, nil
}

func getDnnStaticIpPool(snssai models.Snssai, dnn string) (netip.Prefix, error) {
func getDnnStaticIpPool(snssai models.Snssai, dnn string) ([]netip.Prefix, error) {
var userplaneinfo smf_factory.UserPlaneInformation

raw_info, get_err := GetSmfUserPlaneInfo()
if get_err != nil {
logger.ProcLog.Errorf("GetSmfUserPlaneInfo(): %+v", get_err)
return netip.ParsePrefix("0.0.0.0/32")
// net, parseErr := netip.ParsePrefix("0.0.0.0/32")
return []netip.Prefix{}, get_err
}

tmp, err := json.Marshal(raw_info)
Expand All @@ -103,18 +104,28 @@ func getDnnStaticIpPool(snssai models.Snssai, dnn string) (netip.Prefix, error)
// Find the DNN name
if dnnInfo.Dnn == dnn {
if len(dnnInfo.StaticPools) > 0 {
staticPoolstr := dnnInfo.StaticPools[0].Cidr
return netip.ParsePrefix(staticPoolstr)
result := []netip.Prefix{}
for _, pool := range dnnInfo.StaticPools {
staticPoolstr := pool.Cidr
net, parseErr := netip.ParsePrefix(staticPoolstr)
if parseErr != nil {
return result, parseErr
}
result = append(result, net)
}
return result, nil
}
// If there is no static pool, return smallest
return netip.ParsePrefix("0.0.0.0/32")
net, parseErr := netip.ParsePrefix("0.0.0.0/32")
return []netip.Prefix{net}, parseErr
}
}
}
}
}
}
return netip.ParsePrefix("0.0.0.0/32")
net, parseErr := netip.ParsePrefix("0.0.0.0/32")
return []netip.Prefix{net}, parseErr
}

func VerifyStaticIP(c *gin.Context) {
Expand All @@ -136,46 +147,84 @@ func VerifyStaticIP(c *gin.Context) {
return
}

staticIp, parse_err := netip.ParseAddr(checkData.Ipaddr)
if parse_err != nil {
logger.ProcLog.Errorln(parse_err.Error())
c.JSON(http.StatusOK, gin.H{
"valid": false,
"cause": parse_err.Error(),
})
return
}
logger.ProcLog.Debugln("check IP address:", staticIp)

snssai := models.Snssai{
Sd: checkData.Sd,
Sst: int32(checkData.Sst),
}
if checkData.Sd != "" {
snssai.Sd = checkData.Sd
}

staticPool, get_pool_err := getDnnStaticIpPool(snssai, checkData.Dnn)
staticPools, get_pool_err := getDnnStaticIpPool(snssai, checkData.Dnn)
if get_pool_err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": get_pool_err,
"ipaddr": staticIp,
"ipaddr": checkData.Ipaddr,
"valid": false,
"cause": get_pool_err.Error(),
})
return
}
VerifyStaticIpProcedure(c, checkData, staticPools)
}

func VerifyStaticIpProcedure(
c *gin.Context,
checkData VerifyScope,
staticPools []netip.Prefix,
) {
staticIp, parse_err := netip.ParseAddr(checkData.Ipaddr)
if parse_err != nil {
logger.ProcLog.Errorln(parse_err.Error())
c.JSON(http.StatusOK, gin.H{
"valid": false,
"cause": parse_err.Error(),
})
return
}
logger.ProcLog.Debugln("check IP address:", staticIp)

// Check in Static Pool
result := staticPool.Contains(staticIp)
result := false
for _, staticPool := range staticPools {
result = staticPool.Contains(staticIp)
if result {
break
}
}
if !result {
c.JSON(http.StatusOK, gin.H{
"ipaddr": staticIp,
"valid": result,
"cause": "Not in static pool: " + staticPool.String(),
"cause": "Not in static pools!",
})
logger.ProcLog.Debugln("StaticIP", staticIp, ": not in static pool: "+staticPool.String())
logger.ProcLog.Debugln("StaticIP", staticIp, ": not in static pool!")
return
}

// Check not used by other UE
if gin.Mode() != "test" && checkIpCollisionFromDb(c, checkData) {
return
}

// Return the result
c.JSON(http.StatusOK, gin.H{
"ipaddr": staticIp,
"valid": result,
"cause": "",
})
}

// Check IP not used by other UE
func checkIpCollisionFromDb(
c *gin.Context,
checkData VerifyScope,
) bool {
snssai := models.Snssai{
Sst: int32(checkData.Sst),
}
if checkData.Sd != "" {
snssai.Sd = checkData.Sd
}

smDataColl := "subscriptionData.provisionedData.smData"
filter := bson.M{
"singleNssai": snssai,
Expand All @@ -185,17 +234,17 @@ func VerifyStaticIP(c *gin.Context) {
if mongo_err != nil {
logger.ProcLog.Warningln(smDataColl, "mongo error: ", mongo_err)
c.JSON(http.StatusInternalServerError, gin.H{
"ipaddr": staticIp,
"ipaddr": checkData.Ipaddr,
"valid": false,
"cause": mongo_err.Error(),
})
return
return true
}
var smDatas []models.SessionManagementSubscriptionData
if err := json.Unmarshal(sliceToByte(smDataDataInterface), &smDatas); err != nil {
logger.ProcLog.Errorf("Unmarshal smDatas err: %+v", err)
c.JSON(http.StatusInternalServerError, gin.H{})
return
return true
}
for _, smData := range smDatas {
if dnnConfig, ok := smData.DnnConfigurations[checkData.Dnn]; ok {
Expand All @@ -204,20 +253,14 @@ func VerifyStaticIP(c *gin.Context) {
msg := "StaticIP: " + checkData.Ipaddr + " has already exist!"
logger.ProcLog.Warningln(msg)
c.JSON(http.StatusOK, gin.H{
"ipaddr": staticIp,
"ipaddr": checkData.Ipaddr,
"valid": false,
"cause": msg,
})
return
return true
}
}
}
}

// Return the result
c.JSON(http.StatusOK, gin.H{
"ipaddr": staticIp,
"valid": result,
"cause": "",
})
return false
}
63 changes: 63 additions & 0 deletions backend/WebUI/api_verify_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package WebUI_test

import (
"encoding/json"
"net/http"
"net/http/httptest"
"net/netip"
"testing"

"github.com/free5gc/webconsole/backend/WebUI"

Check failure on line 10 in backend/WebUI/api_verify_test.go

View workflow job for this annotation

GitHub Actions / lint (1.21)

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/free5gc) --custom-order (gci)
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"

Check failure on line 12 in backend/WebUI/api_verify_test.go

View workflow job for this annotation

GitHub Actions / lint (1.21)

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/free5gc) --custom-order (gci)
)

func TestVerifyStaticIpProcedure(t *testing.T) {
gin.SetMode(gin.TestMode)

testcases := []struct {
Name string
Scope WebUI.VerifyScope
IpPools []string
Result bool
}{
{
Name: "One Static Pool - PASS",
Scope: WebUI.VerifyScope{
Supi: "imsi-",
Sst: 1,
Sd: "010203",
Dnn: "internet",
Ipaddr: "10.163.100.100",
},
IpPools: []string{"10.163.100.0/24"},
Result: true,
},
}

for _, tc := range testcases {
w := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(w)

pools := []netip.Prefix{}
for _, pool := range tc.IpPools {
net, err := netip.ParsePrefix(pool)
require.NoError(t, err)

pools = append(pools, net)
}

WebUI.VerifyStaticIpProcedure(ctx, tc.Scope, pools)
require.Equal(t, http.StatusOK, w.Code)

var result gin.H
rawByte := w.Body
errUnmarshal := json.Unmarshal(rawByte.Bytes(), &result)
require.NoError(t, errUnmarshal)

valid, exist := result["valid"]
require.True(t, exist)

require.Equal(t, tc.Result, valid)
}
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/jlaffaye/ftp v0.1.0
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.3
github.com/urfave/cli v1.22.5
go.mongodb.org/mongo-driver v1.11.3
golang.org/x/crypto v0.21.0
Expand Down Expand Up @@ -63,6 +64,7 @@ require (
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/sftp v1.13.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/tidwall/gjson v1.14.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
Expand Down

0 comments on commit e8fbc20

Please sign in to comment.