diff --git a/config/config.yaml b/config/config.yaml index 71fbae6..b5cb051 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -8,7 +8,11 @@ slices: nextmn-lite: pool: "10.0.0.0/24" upfs: - - "203.0.113.2" # only the first upf is used for now + - node-id: "203.0.113.2" # only the first upf is used for now + interfaces: + - type: "N3" + addr: "198.51.100.11" + logger: level: "trace" diff --git a/internal/app/pdu_session.go b/internal/app/pdu_session.go index 8611a56..bfe9195 100644 --- a/internal/app/pdu_session.go +++ b/internal/app/pdu_session.go @@ -13,6 +13,7 @@ import ( "math/rand" "net/http" "net/netip" + "strings" "sync" "time" @@ -86,6 +87,7 @@ type PduSessions struct { type PduSession struct { Upf netip.Addr + UpfN3 netip.Addr UplinkTeid uint32 Gnb netip.Addr DownlinkTeid uint32 @@ -143,9 +145,9 @@ func (p *PduSessions) EstablishmentRequest(c *gin.Context) { upf := p.Slices[ps.Dnn].Upfs[0] upfTeids := &UpfTeids{} - l, ok := p.UpfMap.Load(upf) + l, ok := p.UpfMap.Load(upf.NodeID) if !ok { - p.UpfMap.Store(upf, upfTeids) + p.UpfMap.Store(upf.NodeID, upfTeids) } else { upfTeids = l.(*UpfTeids) } @@ -170,9 +172,24 @@ func (p *PduSessions) EstablishmentRequest(c *gin.Context) { } } } + var iface netip.Addr + ifacedone := false + for _, i := range upf.Interfaces { + if strings.ToLower(i.Type) == "n3" { + iface = i.Addr + ifacedone = true + break + } + } + if !ifacedone { + logrus.Error("could not find n3 interface on first upf") + c.JSON(http.StatusInternalServerError, jsonapi.MessageWithError{Message: "could not find n3 interface on first upf", Error: nil}) + return + } // allocate uplink teid pduSession := PduSession{ - Upf: upf, + Upf: upf.NodeID, + UpfN3: iface, UplinkTeid: teid, } @@ -231,14 +248,15 @@ func (p *PduSessions) N2EstablishmentResponse(c *gin.Context) { "ue": ps.UeInfo.Header.Ue.String(), "gnb": ps.UeInfo.Header.Gnb.String(), "ip-addr": ps.UeInfo.Addr, - "gtp-upf": psStruct.Upf, + "upf-pfcp": psStruct.Upf, + "gtp-upf": psStruct.UpfN3, "gtp-uplink-teid": psStruct.UplinkTeid, "gtp-downlink-teid": psStruct.DownlinkTeid, "gtp-gnb": psStruct.Gnb, "dnn": ps.UeInfo.Header.Dnn, }).Info("New PDU Session Established") - err := p.pfcp.CreateSession(ps.UeInfo.Addr, psStruct.UplinkTeid, psStruct.DownlinkTeid, psStruct.Upf, psStruct.Gnb, ps.UeInfo.Header.Dnn) + err := p.pfcp.CreateSession(ps.UeInfo.Addr, psStruct.UplinkTeid, psStruct.DownlinkTeid, psStruct.Upf, psStruct.UpfN3, psStruct.Gnb, ps.UeInfo.Header.Dnn) if err != nil { logrus.WithError(err).Error("Could not configure PDR/FAR in UPF") c.JSON(http.StatusInternalServerError, jsonapi.MessageWithError{Message: "could not configure PDR/FAR in UPF", Error: err}) diff --git a/internal/app/pfcp.go b/internal/app/pfcp.go index 36afd2f..425f89c 100644 --- a/internal/app/pfcp.go +++ b/internal/app/pfcp.go @@ -59,21 +59,21 @@ func (p *PFCPServer) Start(ctx context.Context) error { } for _, slice := range p.slices { for _, upf := range slice.Upfs { - association, err := p.srv.NewEstablishedPFCPAssociation(ie.NewNodeIDHeuristic(upf.String())) + association, err := p.srv.NewEstablishedPFCPAssociation(ie.NewNodeIDHeuristic(upf.NodeID.String())) if err != nil { logrus.WithError(err).WithFields(logrus.Fields{ - "upf": upf, + "upf": upf.NodeID, }).Error("Could not perform PFCP association") return err } - p.associations[upf] = association + p.associations[upf.NodeID] = association } } logrus.Info("PFCP Associations complete") return nil } -func (p *PFCPServer) CreateSession(ue netip.Addr, uplinkTeid uint32, downlinkTeid uint32, upfI netip.Addr, gNB netip.Addr, slice string) error { +func (p *PFCPServer) CreateSession(ue netip.Addr, uplinkTeid uint32, downlinkTeid uint32, upfI netip.Addr, upfIn3 netip.Addr, gNB netip.Addr, slice string) error { a, ok := p.associations[upfI] if !ok { return fmt.Errorf("Could not create PFCP Session: not associated with UPF") @@ -84,7 +84,7 @@ func (p *PFCPServer) CreateSession(ue netip.Addr, uplinkTeid uint32, downlinkTei ie.NewCreatePDR(ie.NewPDRID(1), ie.NewPrecedence(255), ie.NewPDI( ie.NewSourceInterface(ie.SrcInterfaceAccess), - ie.NewFTEID(0x01, uplinkTeid, upfI.AsSlice(), nil, 0), // ipv4: 0x01 + ie.NewFTEID(0x01, uplinkTeid, upfIn3.AsSlice(), nil, 0), // ipv4: 0x01 ie.NewNetworkInstance(slice), ie.NewUEIPAddress(0x02, ue.String(), "", 0, 0), // ipv4: 0x02 ), diff --git a/internal/config/config.go b/internal/config/config.go index 9467d15..60d3f86 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -45,5 +45,15 @@ type Control struct { type Slice struct { Pool netip.Prefix `yaml:"pool"` - Upfs []netip.Addr `yaml:"upfs"` + Upfs []Upf `yaml:"upfs"` +} + +type Upf struct { + NodeID netip.Addr `yaml:"node-id"` + Interfaces []Interface `yaml:"interfaces"` +} + +type Interface struct { + Type string `yaml:"type"` + Addr netip.Addr `yaml:"addr"` }