Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(5glan): add ue policy container #26

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions uePolicyContainer/NAS_UePolicyDeliveryServiceMsgType.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package uePolicyContainer

// TS24.501 v17.7.1, D.6.1
type UePolicyDeliveryServiceMsgType struct {
Octet uint8
}

func (m *UePolicyDeliveryServiceMsgType) SetMessageIdentity(MessageIdentity uint8) {
m.Octet = MessageIdentity
}

func (m *UePolicyDeliveryServiceMsgType) GetMessageIdentity(MessageIdentity uint8) uint8 {
return m.Octet
}
101 changes: 101 additions & 0 deletions uePolicyContainer/UPSC_Generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package uePolicyContainer

// idgenerator is used for generating ID from minValue to maxValue.
// It will allocate IDs in range [minValue, maxValue]
// It is thread-safe when allocating IDs

import (
"errors"
)

type IDGenerator struct {
// lock sync.Mutex
minValue int64
maxValue int64
valueRange int64
offset int64
usedMap map[int64]bool
}

// Initialize an IDGenerator with minValue and maxValue.
func NewGenerator(minValue, maxValue int64) *IDGenerator {
idGenerator := &IDGenerator{}
idGenerator.init(minValue, maxValue)
return idGenerator
}

func (idGenerator *IDGenerator) init(minValue, maxValue int64) {
idGenerator.minValue = minValue
idGenerator.maxValue = maxValue
idGenerator.valueRange = maxValue - minValue + 1
idGenerator.offset = 0
idGenerator.usedMap = make(map[int64]bool)
}

// Allocate and return an id in range [minValue, maxValue]
func (idGenerator *IDGenerator) Allocate() (int64, error) {
// idGenerator.lock.Lock()
// defer idGenerator.lock.Unlock()

offsetBegin := idGenerator.offset
for {
if _, ok := idGenerator.usedMap[idGenerator.offset]; ok {
idGenerator.updateOffset()

if idGenerator.offset == offsetBegin {
return 0, errors.New("no available value range to allocate id")
}
} else {
break
}
}
idGenerator.usedMap[idGenerator.offset] = true
id := idGenerator.offset + idGenerator.minValue
idGenerator.updateOffset()
return id, nil
}

// Allocate and return an id in from certain range [inputMin, inputMAX]
func (idGenerator *IDGenerator) Allocate_inRange(min, max int64) (int64, error) {
// idGenerator.lock.Lock()
// defer idGenerator.lock.Unlock()

offsetBegin := idGenerator.offset
idGenerator.setOffset(min)
for {
if _, ok := idGenerator.usedMap[idGenerator.offset]; ok {
idGenerator.updateOffset()

if idGenerator.offset == offsetBegin || idGenerator.offset == max {
return 0, errors.New("no available value range to allocate id")
}
} else {
break
}
}
idGenerator.usedMap[idGenerator.offset] = true
id := idGenerator.offset + idGenerator.minValue
idGenerator.updateOffset()
return id, nil
}

// param:
// - id: id to free
func (idGenerator *IDGenerator) FreeID(id int64) {
if id < idGenerator.minValue || id > idGenerator.maxValue {
return
}
// idGenerator.lock.Lock()
// defer idGenerator.lock.Unlock()
delete(idGenerator.usedMap, id-idGenerator.minValue)
}

func (idGenerator *IDGenerator) updateOffset() {
idGenerator.offset++
idGenerator.offset = idGenerator.offset % idGenerator.valueRange
}

func (idGenerator *IDGenerator) setOffset(newoffset int64) {
idGenerator.offset = newoffset
idGenerator.offset = idGenerator.offset % idGenerator.valueRange
}
125 changes: 125 additions & 0 deletions uePolicyContainer/UePolicyContainer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package uePolicyContainer

import (
"bytes"
"encoding/binary"
"fmt"
)

// UePolicyContainer is a kind of NAS_DLTransport message
// UePolicyContainer maps to UE_policy_delivery_service
// TS 124 501 V17.7.1, page.760, Table 9.11.3.39.1: Payload container information element
type UePolicyContainer = UePolDeliverySer

// TS 124 501 V17.7.1, page.893, UE policy delivery service
type UePolDeliverySer struct {
UePolDeliveryHeader
*ManageUEPolicyCommand // D.2.1.2 Network-requested UE policy management procedure initiation
*ManageUEPolicyComplete // D.2.1.3 Network-requested UE policy management procedure accepted by the UE
*ManageUEPolicyReject // D.2.1.4 Network-requested UE policy management procedure not accepted by the UE
// TODO: add below encoding way
// *nasMessage.UEStateIndication // D.2.2 UE-initiated UE state indication procedure
}

func NewUePolDeliverySer() *UePolDeliverySer {
uePolDeliverySer := &UePolDeliverySer{}
return uePolDeliverySer
}

type UePolDeliveryHeader struct {
Octet [2]uint8
}

// PTI(Procedure transaction identity) is assign by PCF
func (u *UePolDeliveryHeader) SetHeaderPTI(PTI uint8) {
u.Octet[0] = PTI
}

// PTI(Procedure transaction identity)
func (u *UePolDeliveryHeader) GetHeaderPTI() (pTI uint8) {
pTI = u.Octet[0]
return pTI
}

func (u *UePolDeliveryHeader) GetHeaderMessageType() (messageType uint8) {
messageType = u.Octet[1]
return messageType
}

func (u *UePolDeliveryHeader) SetHeaderMessageType(messageType uint8) {
u.Octet[1] = messageType
}

const (
MsgTypeManageUEPolicyCommand uint8 = 1
MsgTypeManageUEPolicyComplete uint8 = 2
MsgTypeManageUEPolicyReject uint8 = 3
MsgTypeUEStateIndication uint8 = 4
MsgTypeUEPolicyProvisioningRequest uint8 = 5
MsgTypeUEPolicyProvisioningReject uint8 = 6
)

// TODO: add other Decoding processes
func (u *UePolDeliverySer) UePolDeliverySerDecode(byteArray []byte) error {
buffer := bytes.NewBuffer(byteArray)
if err := binary.Read(buffer, binary.BigEndian, &u.UePolDeliveryHeader); err != nil {
return fmt.Errorf("uePolicyContainer-UePolDeliveryHeader decode Fail:%+v", err)
}

switch u.GetHeaderMessageType() {
case MsgTypeManageUEPolicyCommand:
u.ManageUEPolicyCommand = NewManageUEPolicyCommand(MsgTypeManageUEPolicyCommand)
if err := u.DecodeManageUEPolicyCommand(byteArray); err != nil {
return err
}
case MsgTypeManageUEPolicyComplete:
u.ManageUEPolicyComplete = NewManageUEPolicyComplete(MsgTypeManageUEPolicyComplete)
if err := u.DecodeManageUEPolicyComplete(byteArray); err != nil {
return err
}
case MsgTypeManageUEPolicyReject:
u.ManageUEPolicyReject = NewManageUEPolicyReject(MsgTypeManageUEPolicyReject)
if err := u.DecodeManageUEPolicyReject(byteArray); err != nil {
return err
}
case MsgTypeUEStateIndication:
// TODO
case MsgTypeUEPolicyProvisioningRequest:
// TODO
case MsgTypeUEPolicyProvisioningReject:
// TODO
default:
return fmt.Errorf("ue Policy Delivery Service decode Fail: MsgType[%d] doesn't exist",
u.GetHeaderMessageType())
}
return nil
}

// TODO: add other Encoding processes
func (u *UePolDeliverySer) UePolDeliverySerEncode() ([]byte, error) {
buf := bytes.NewBuffer(nil)
switch u.GetHeaderMessageType() {
case MsgTypeManageUEPolicyCommand:
if err := u.EncodeManageUEPolicyCommand(buf); err != nil {
return nil, err
}
case MsgTypeManageUEPolicyComplete:
if err := u.EncodeManageUEPolicyComplete(buf); err != nil {
return nil, err
}
case MsgTypeManageUEPolicyReject:
if err := u.EncodeManageUEPolicyReject(buf); err != nil {
return nil, err
}
case MsgTypeUEStateIndication:
// TODO
case MsgTypeUEPolicyProvisioningRequest:
// TODO
case MsgTypeUEPolicyProvisioningReject:
// TODO
default:
return nil, fmt.Errorf("ue Policy Delivery Service Encode Fail: MsgType[%d] doesn't exist",
u.GetHeaderMessageType())
}
return buf.Bytes(), nil
}
112 changes: 112 additions & 0 deletions uePolicyContainer/UePolicyContainer_Instruction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package uePolicyContainer

import (
"bytes"
"encoding/binary"
"io"
)

type UEPolicySectionManagementSubListContents []Instruction

type Instruction struct {
Len uint16
Upsc uint16 // a UE policy section code (UPSC) containing a value assigned by the PCF.
UEPolicySectionContents UEPolicySectionContents
}

func (u *UEPolicySectionManagementSubListContents) AppendInstruction(ins Instruction) {
*u = append(*u, ins)
}

// Marshal Strcuture into byte slice
func (u *UEPolicySectionManagementSubListContents) MarshalBinary() ([]byte, error) {
buf := bytes.NewBuffer(nil)
for i, instruct := range *u {
if instrucBuf, err := instruct.MarshalBinary(); err != nil {
return nil, err
} else {
_, err = buf.Write(instrucBuf)
if err != nil {
return nil, err
}
(*u)[i] = instruct
}
}
return buf.Bytes(), nil
}

// UnMarshal byte slice into Strctute
func (u *UEPolicySectionManagementSubListContents) UnmarshalBinary(b []byte) error {
// initial an empty slice that length and capacity = 0
// *u = make(UEPolicySectionManagementSubListContents, 0)
buf := bytes.NewBuffer(b)
for {
if instrcut, err := parseInstruction(buf); err != nil {
if err == io.EOF {
return nil
} else {
return err
}
} else {
*u = append(*u, *instrcut)
}
}
}

func (i *Instruction) SetLen(length uint16) {
i.Len = length
}

func (i *Instruction) GetLen() uint16 {
return i.Len
}

func (i *Instruction) SetUpsc(upsc uint16) {
i.Upsc = upsc
}

func (i *Instruction) GetUpsc() uint16 {
return i.Upsc
}

func (i *Instruction) MarshalBinary() ([]byte, error) {
buf := bytes.NewBuffer(nil)
// Preprocess the content into byte slice, but append to buffer at the end
policySectionContentBuf, err := i.UEPolicySectionContents.MarshalBinary()
if err != nil {
return nil, err
}
i.SetLen(uint16(len(policySectionContentBuf) + 2))

// len
if err := binary.Write(buf, binary.BigEndian, i.Len); err != nil {
return nil, err
}
// UPSC
if err := binary.Write(buf, binary.BigEndian, i.Upsc); err != nil {
return nil, err
}
// Policy Section Content
if _, err := buf.Write(policySectionContentBuf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

func parseInstruction(buf *bytes.Buffer) (*Instruction, error) {
var instruction Instruction
// Len
if err := binary.Read(buf, binary.BigEndian, &instruction.Len); err != nil {
return nil, err
}
// UPSC
if err := binary.Read(buf, binary.BigEndian, &instruction.Upsc); err != nil {
return nil, err
}
// Ue policy section contents
if err := instruction.UEPolicySectionContents.UnmarshalBinary(buf.Next(int(instruction.Len) - 2)); err != nil {
return nil, err
}

return &instruction, nil
}
Loading
Loading