Skip to content

Commit

Permalink
adress pr review comments
Browse files Browse the repository at this point in the history
Signed-off-by: Raguideau <[email protected]>
  • Loading branch information
Raguideau committed Dec 6, 2023
1 parent 684d491 commit 0bc1bbc
Show file tree
Hide file tree
Showing 25 changed files with 360 additions and 287 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ jobs:
run: go mod download

- name: Launch tests
run: go test -v ./test/amf
run: go test -v ./test
2 changes: 1 addition & 1 deletion config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ ue:
ciphering:
nea0: true
nea1: false
nea2: false
nea2: true
nea3: false
amfif:
ip: "192.168.11.30"
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/mitchellh/mapstructure v1.4.2
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/sirupsen/logrus v1.9.2
github.com/stretchr/testify v1.7.0
github.com/tetratelabs/wazero v1.3.0
github.com/urfave/cli/v2 v2.25.5
github.com/vishvananda/netlink v1.1.0
Expand All @@ -30,8 +31,10 @@ require (
github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
github.com/khirono/go-genl v1.0.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/sys v0.13.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
107 changes: 103 additions & 4 deletions internal/common/tools/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,25 @@
package tools

import (
"log"
"fmt"
"my5G-RANTester/config"
"my5G-RANTester/internal/control_test_engine/gnb"
"my5G-RANTester/internal/control_test_engine/gnb/context"
gnbCxt "my5G-RANTester/internal/control_test_engine/gnb/context"
"my5G-RANTester/internal/control_test_engine/procedures"
"my5G-RANTester/internal/control_test_engine/ue"
ueCtx "my5G-RANTester/internal/control_test_engine/ue/context"
"net"
"strconv"
"sync"
"time"

"errors"

log "github.com/sirupsen/logrus"
)

func CreateGnbs(count int, cfg config.Config, wg *sync.WaitGroup) map[string]*context.GNBContext {
gnbs := make(map[string]*context.GNBContext)
func CreateGnbs(count int, cfg config.Config, wg *sync.WaitGroup) map[string]*gnbCxt.GNBContext {
gnbs := make(map[string]*gnbCxt.GNBContext)
var err error
// Each gNB have their own IP address on both N2 and N3
// TODO: Limitation for now, these IPs must be sequential, eg:
Expand Down Expand Up @@ -92,3 +98,96 @@ func Contains(s []string, str string) bool {

return false
}

type UESimulationConfig struct {
UeId int
Gnbs map[string]*gnbCxt.GNBContext
Cfg config.Config
ScenarioChan chan procedures.UeTesterMessage
TimeBeforeDeregistration int
TimeBeforeHandover int
NumPduSessions int
}

func SimulateSingleUE(simConfig UESimulationConfig, wg *sync.WaitGroup) {
numGnb := len(simConfig.Gnbs)
ueCfg := simConfig.Cfg
ueCfg.Ue.Msin = IncrementMsin(simConfig.UeId, simConfig.Cfg.Ue.Msin)
log.Info("[TESTER] TESTING REGISTRATION USING IMSI ", ueCfg.Ue.Msin, " UE")

ueCfg.GNodeB.PlmnList.GnbId = gnbIdGenerator(simConfig.UeId%numGnb + 1)

// If there is currently a coroutine handling current UE
// kill it, before creating a new coroutine with same UE
// Use case: Registration of N UEs in loop, when loop = true
if simConfig.ScenarioChan != nil {
simConfig.ScenarioChan <- procedures.UeTesterMessage{Type: procedures.Kill}
close(simConfig.ScenarioChan)
}

// Launch a coroutine to handle UE's individual scenario
go func(scenarioChan chan procedures.UeTesterMessage, ueId int) {
wg.Add(1)

ueRx := make(chan procedures.UeTesterMessage)

// Create a new UE coroutine
// ue.NewUE returns context of the new UE
ueTx := ue.NewUE(ueCfg, uint8(ueId), ueRx, simConfig.Gnbs[ueCfg.GNodeB.PlmnList.GnbId], wg)

// We tell the UE to perform a registration
ueRx <- procedures.UeTesterMessage{Type: procedures.Registration}

var deregistrationChannel <-chan time.Time = nil
if simConfig.TimeBeforeDeregistration != 0 {
deregistrationChannel = time.After(time.Duration(simConfig.TimeBeforeDeregistration) * time.Millisecond)
}
var handoverChannel <-chan time.Time = nil
if simConfig.TimeBeforeHandover != 0 {
handoverChannel = time.After(time.Duration(simConfig.TimeBeforeHandover) * time.Millisecond)
}

loop := true
state := ueCtx.MM5G_NULL
for loop {
select {
case <-deregistrationChannel:
ueRx <- procedures.UeTesterMessage{Type: procedures.Terminate}
ueRx = nil
case <-handoverChannel:
if ueRx != nil {
ueRx <- procedures.UeTesterMessage{Type: procedures.Handover, GnbChan: simConfig.Gnbs[gnbIdGenerator((ueId+1)%numGnb+1)].GetInboundChannel()}
}
case msg := <-scenarioChan:
if ueRx != nil {
ueRx <- msg
}
case msg := <-ueTx:
log.Info("[UE] Switched from state ", state, " to state ", msg.StateChange)
switch msg.StateChange {
case ueCtx.MM5G_REGISTERED:
if state != msg.StateChange {
for i := 0; i < simConfig.NumPduSessions; i++ {
ueRx <- procedures.UeTesterMessage{Type: procedures.NewPDUSession}
}
}
case ueCtx.MM5G_NULL:
loop = false
}
state = msg.StateChange
}
}
}(simConfig.ScenarioChan, simConfig.UeId)
}

func IncrementMsin(i int, msin string) string {

msin_int, err := strconv.Atoi(msin)
if err != nil {
log.Fatal("[UE][CONFIG] Given MSIN is invalid")
}
base := msin_int + (i - 1)

imsi := fmt.Sprintf("%010d", base)
return imsi
}
96 changes: 11 additions & 85 deletions internal/templates/test-multi-ues-in-queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@
package templates

import (
"fmt"
"my5G-RANTester/config"
"my5G-RANTester/internal/common/tools"
"my5G-RANTester/internal/control_test_engine/procedures"
"my5G-RANTester/internal/control_test_engine/ue"
"my5G-RANTester/internal/control_test_engine/ue/context"
"os"
"os/signal"
"strconv"
"sync"
"time"

Expand All @@ -24,7 +20,6 @@ func TestMultiUesInQueue(numUes int, tunnelEnabled bool, dedicatedGnb bool, loop
if tunnelEnabled && !dedicatedGnb {
log.Fatal("You cannot use the --tunnel option, without using the --dedicatedGnb option")
}

if tunnelEnabled && timeBetweenRegistration < 500 {
log.Fatal("When using the --tunnel option, --timeBetweenRegistration must be equal to at least 500 ms, or else gtp5g kernel module may crash if you create tunnels too rapidly.")
}
Expand Down Expand Up @@ -56,86 +51,29 @@ func TestMultiUesInQueue(numUes int, tunnelEnabled bool, dedicatedGnb bool, loop
// TODO: We should wait for NGSetupResponse instead
time.Sleep(1 * time.Second)

msin := cfg.Ue.Msin
cfg.Ue.TunnelEnabled = tunnelEnabled

scenarioChans := make([]chan procedures.UeTesterMessage, numUes+1)

sigStop := make(chan os.Signal, 1)
signal.Notify(sigStop, os.Interrupt)

ueSimCfg := tools.UESimulationConfig{
Gnbs: gnbs,
Cfg: cfg,
TimeBeforeDeregistration: timeBeforeDeregistration,
TimeBeforeHandover: timeBeforeHandover,
NumPduSessions: numPduSessions,
}

stopSignal := true
for stopSignal {
// If CTRL-C signal has been received,
// stop creating new UEs, else we create numUes UEs
for ueId := 1; stopSignal && ueId <= numUes; ueId++ {
ueCfg := cfg
ueCfg.Ue.Msin = imsiGenerator(ueId, msin)
log.Info("[TESTER] TESTING REGISTRATION USING IMSI ", ueCfg.Ue.Msin, " UE")

ueCfg.GNodeB.PlmnList.GnbId = gnbIdGenerator(ueId%numGnb + 1)

// If there is currently a coroutine handling current UE
// kill it, before creating a new coroutine with same UE
// Use case: Registration of N UEs in loop, when loop = true
if scenarioChans[ueId] != nil {
scenarioChans[ueId] <- procedures.UeTesterMessage{Type: procedures.Kill}
close(scenarioChans[ueId])
}
for ueSimCfg.UeId = 1; stopSignal && ueSimCfg.UeId <= numUes; ueSimCfg.UeId++ {
ueSimCfg.ScenarioChan = scenarioChans[ueSimCfg.UeId]

// Launch a coroutine to handle UE's individual scenario
go func(scenarioChan chan procedures.UeTesterMessage, ueId int) {
wg.Add(1)

ueRx := make(chan procedures.UeTesterMessage)

// Create a new UE coroutine
// ue.NewUE returns context of the new UE
ueTx := ue.NewUE(ueCfg, uint8(ueId), ueRx, gnbs[ueCfg.GNodeB.PlmnList.GnbId], &wg)

// We tell the UE to perform a registration
ueRx <- procedures.UeTesterMessage{Type: procedures.Registration}

var deregistrationChannel <-chan time.Time = nil
if timeBeforeDeregistration != 0 {
deregistrationChannel = time.After(time.Duration(timeBeforeDeregistration) * time.Millisecond)
}
var handoverChannel <-chan time.Time = nil
if timeBeforeHandover != 0 {
handoverChannel = time.After(time.Duration(timeBeforeHandover) * time.Millisecond)
}

loop := true
state := context.MM5G_NULL
for loop {
select {
case <-deregistrationChannel:
ueRx <- procedures.UeTesterMessage{Type: procedures.Terminate}
ueRx = nil
case <-handoverChannel:
if ueRx != nil {
ueRx <- procedures.UeTesterMessage{Type: procedures.Handover, GnbChan: gnbs[gnbIdGenerator((ueId+1)%numGnb+1)].GetInboundChannel()}
}
case msg := <-scenarioChan:
if ueRx != nil {
ueRx <- msg
}
case msg := <-ueTx:
log.Info("[UE] Switched from state ", state, " to state ", msg.StateChange)
switch msg.StateChange {
case context.MM5G_REGISTERED:
if state != msg.StateChange {
for i := 0; i < numPduSessions; i++ {
ueRx <- procedures.UeTesterMessage{Type: procedures.NewPDUSession}
}
}
case context.MM5G_NULL:
loop = false
}
state = msg.StateChange
}
}
}(scenarioChans[ueId], ueId)
tools.SimulateSingleUE(ueSimCfg, &wg)

// Before creating a new UE, we wait for timeBetweenRegistration ms
time.Sleep(time.Duration(timeBetweenRegistration) * time.Millisecond)
Expand All @@ -155,15 +93,3 @@ func TestMultiUesInQueue(numUes int, tunnelEnabled bool, dedicatedGnb bool, loop

wg.Wait()
}

func imsiGenerator(i int, msin string) string {

msin_int, err := strconv.Atoi(msin)
if err != nil {
log.Fatal("[UE][CONFIG] Given MSIN is invalid")
}
base := msin_int + (i - 1)

imsi := fmt.Sprintf("%010d", base)
return imsi
}
14 changes: 7 additions & 7 deletions test/aio5gc/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ import (

type FiveGCBuilder struct {
config config.Config
nasHook func(*nas.Message, *context.UEContext, *context.Aio5gc) (bool, error)
ngapHook func(*ngapType.NGAPPDU, *context.GNBContext, *context.Aio5gc) (bool, error)
nasHook []func(*nas.Message, *context.UEContext, *context.GNBContext, *context.Aio5gc) (bool, error)
ngapHook []func(*ngapType.NGAPPDU, *context.GNBContext, *context.Aio5gc) (bool, error)
}

func (f *FiveGCBuilder) WithConfig(conf config.Config) *FiveGCBuilder {
f.config = conf
return f
}

func (f *FiveGCBuilder) WithNASDispatcherHook(hook func(*nas.Message, *context.UEContext, *context.Aio5gc) (bool, error)) *FiveGCBuilder {
f.nasHook = hook
func (f *FiveGCBuilder) WithNASDispatcherHook(hook func(*nas.Message, *context.UEContext, *context.GNBContext, *context.Aio5gc) (bool, error)) *FiveGCBuilder {
f.nasHook = append(f.nasHook, hook)
return f
}

func (f *FiveGCBuilder) WithNGAPDispatcherHook(hook func(*ngapType.NGAPPDU, *context.GNBContext, *context.Aio5gc) (bool, error)) *FiveGCBuilder {
f.ngapHook = hook
f.ngapHook = append(f.ngapHook, hook)
return f
}

Expand All @@ -48,11 +48,11 @@ func (f *FiveGCBuilder) Build() (*context.Aio5gc, error) {
return &context.Aio5gc{}, err
}
if f.nasHook != nil {
fgc.SetNasHook(f.nasHook)
fgc.SetNasHooks(f.nasHook)
}

if f.ngapHook != nil {
fgc.SetNgapHook(f.ngapHook)
fgc.SetNgapHooks(f.ngapHook)
}
go service.RunServer(f.config.AMF.Ip, f.config.AMF.Port, &fgc)
return &fgc, nil
Expand Down
8 changes: 4 additions & 4 deletions test/aio5gc/context/amf.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func (c *AMFContext) NewAmfContext(amfName string, id string, supportedPlmnSnssa
c.securityContext = []SecurityContext{}
c.idUeGenerator = 0
c.networkName = NetworkName{
Full: "TestNtwFull",
Short: "TestNtwShort",
Full: "NtwFull",
Short: "Ntwshrt",
}
}

Expand Down Expand Up @@ -97,7 +97,7 @@ func (c *AMFContext) FindUEById(id int64) (*UEContext, error) {
return &c.ues[ue], nil
}
}
return &UEContext{}, errors.New("[5GC] UE with amfNgapId " + strconv.Itoa(int(id)) + "not found")
return nil, errors.New("[5GC] UE with amfNgapId " + strconv.Itoa(int(id)) + "not found")
}

func (c *AMFContext) FindUEByRanId(id int64) (*UEContext, error) {
Expand All @@ -109,7 +109,7 @@ func (c *AMFContext) FindUEByRanId(id int64) (*UEContext, error) {
}
}

return &UEContext{}, errors.New("[5GC] UE with RanNgapId " + strconv.Itoa(int(id)) + "not found")
return nil, errors.New("[5GC] UE with RanNgapId " + strconv.Itoa(int(id)) + "not found")
}

func (c *AMFContext) NewSecurityContext(sub SecurityContext) error {
Expand Down
Loading

0 comments on commit 0bc1bbc

Please sign in to comment.