blob: e00062b7b4ea9140b7516ee90aa023ce4bc17fda [file] [log] [blame]
kalnagy45114752019-06-18 14:40:39 +02001/*
2==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17==================================================================================
18*/
19
20package control
21
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020022import (
Juha Hyttinen0388dd92020-01-09 14:14:16 +020023 "fmt"
Juha Hyttinen422d0182020-01-17 13:37:05 +020024 "gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap"
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020025 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
26 "sync"
Juha Hyttinen12d31af2020-01-22 12:59:01 +020027 "time"
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020028)
29
Juha Hyttinen0d064ec2020-01-09 09:08:53 +020030//-----------------------------------------------------------------------------
31//
32//-----------------------------------------------------------------------------
Juha Hyttinen83ada002020-01-30 10:36:33 +020033
kalnagy45114752019-06-18 14:40:39 +020034type Registry struct {
Juha Hyttinen0388dd92020-01-09 14:14:16 +020035 mutex sync.Mutex
Juha Hyttinen83ada002020-01-30 10:36:33 +020036 register map[uint32]*Subscription
37 subIds []uint32
Juha Hyttinen0388dd92020-01-09 14:14:16 +020038 rtmgrClient *RtmgrClient
kalnagy45114752019-06-18 14:40:39 +020039}
40
Anssi Mannila5c161a92020-01-15 15:40:57 +020041func (r *Registry) Initialize() {
Juha Hyttinen83ada002020-01-30 10:36:33 +020042 r.register = make(map[uint32]*Subscription)
43 var i uint32
Anssi Mannila5c161a92020-01-15 15:40:57 +020044 for i = 0; i < 65535; i++ {
45 r.subIds = append(r.subIds, i+1)
46 }
kalnagy45114752019-06-18 14:40:39 +020047}
48
Juha Hyttinen83ada002020-01-30 10:36:33 +020049func (r *Registry) allocateSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
Juha Hyttinen12d31af2020-01-22 12:59:01 +020050 if len(r.subIds) > 0 {
Juha Hyttinen3944a222020-01-24 11:51:46 +020051 sequenceNumber := r.subIds[0]
Juha Hyttinen12d31af2020-01-22 12:59:01 +020052 r.subIds = r.subIds[1:]
53 if _, ok := r.register[sequenceNumber]; ok == true {
54 r.subIds = append(r.subIds, sequenceNumber)
Juha Hyttinen3944a222020-01-24 11:51:46 +020055 return nil, fmt.Errorf("Registry: Failed to reserve subscription exists")
Juha Hyttinen12d31af2020-01-22 12:59:01 +020056 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020057 subs := &Subscription{
58 registry: r,
Juha Hyttinen3944a222020-01-24 11:51:46 +020059 Meid: trans.Meid,
60 SubReqMsg: subReqMsg,
61 valid: true,
62 }
Juha Hyttinen83ada002020-01-30 10:36:33 +020063 subs.ReqId.Id = 123
64 subs.ReqId.Seq = sequenceNumber
Juha Hyttinen3944a222020-01-24 11:51:46 +020065
66 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
Juha Hyttinen83ada002020-01-30 10:36:33 +020067 r.subIds = append(r.subIds, subs.ReqId.Seq)
Juha Hyttinen3944a222020-01-24 11:51:46 +020068 return nil, fmt.Errorf("Registry: Endpoint existing already in subscription")
69 }
70
71 return subs, nil
Juha Hyttinen12d31af2020-01-22 12:59:01 +020072 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020073 return nil, fmt.Errorf("Registry: Failed to reserve subscription no free ids")
74}
75
Juha Hyttinen83ada002020-01-30 10:36:33 +020076func (r *Registry) findExistingSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) *Subscription {
77
Juha Hyttinen3944a222020-01-24 11:51:46 +020078 for _, subs := range r.register {
Juha Hyttinen83ada002020-01-30 10:36:33 +020079 if subs.IsMergeable(trans, subReqMsg) {
Juha Hyttinen3944a222020-01-24 11:51:46 +020080
81 //
82 // check if there has been race conditions
83 //
84 subs.mutex.Lock()
85 //subs has been set to invalid
86 if subs.valid == false {
87 subs.mutex.Unlock()
88 continue
89 }
Juha Hyttinen83ada002020-01-30 10:36:33 +020090 // If size is zero, entry is to be deleted
91 if subs.EpList.Size() == 0 {
92 subs.mutex.Unlock()
93 continue
94 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020095 // try to add to endpointlist.
96 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
97 subs.mutex.Unlock()
98 continue
99 }
100 subs.mutex.Unlock()
101
Juha Hyttinen83ada002020-01-30 10:36:33 +0200102 xapp.Logger.Debug("Registry: Mergeable subs found %s for %s", subs.String(), trans.String())
Juha Hyttinen3944a222020-01-24 11:51:46 +0200103 return subs
104 }
105 }
106 return nil
107}
108
Juha Hyttinen83ada002020-01-30 10:36:33 +0200109func (r *Registry) AssignToSubscription(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200110 var err error
111 var newAlloc bool
112 r.mutex.Lock()
113 defer r.mutex.Unlock()
114
115 subs := r.findExistingSubs(trans, subReqMsg)
116
117 if subs == nil {
118 subs, err = r.allocateSubs(trans, subReqMsg)
119 if err != nil {
120 return nil, err
121 }
122 newAlloc = true
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200123 }
124
125 //
126 // Add to subscription
127 //
128 subs.mutex.Lock()
129 defer subs.mutex.Unlock()
130
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200131 epamount := subs.EpList.Size()
132
133 r.mutex.Unlock()
134 //
135 // Subscription route updates
136 //
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200137 if epamount == 1 {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200138 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.Seq)}
139 err = r.rtmgrClient.SubscriptionRequestCreate(subRouteAction)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200140 } else {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200141 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.Seq)}
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200142 err = r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
143 }
144 r.mutex.Lock()
145
146 if err != nil {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200147 if newAlloc {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200148 r.subIds = append(r.subIds, subs.ReqId.Seq)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200149 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200150 return nil, err
151 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200152
Juha Hyttinen3944a222020-01-24 11:51:46 +0200153 if newAlloc {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200154 r.register[subs.ReqId.Seq] = subs
Juha Hyttinen3944a222020-01-24 11:51:46 +0200155 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200156 xapp.Logger.Debug("CREATE %s", subs.String())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200157 xapp.Logger.Debug("Registry: substable=%v", r.register)
158 return subs, nil
159}
160
Juha Hyttinen83ada002020-01-30 10:36:33 +0200161// TODO: Works with concurrent calls, but check if can be improved
162func (r *Registry) RemoveFromSubscription(subs *Subscription, trans *TransactionXapp, waitRouteClean time.Duration) error {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200163
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200164 r.mutex.Lock()
165 defer r.mutex.Unlock()
166 subs.mutex.Lock()
167 defer subs.mutex.Unlock()
168
169 delStatus := subs.EpList.DelEndpoint(trans.GetEndpoint())
170 epamount := subs.EpList.Size()
Juha Hyttinen83ada002020-01-30 10:36:33 +0200171 seqId := subs.ReqId.Seq
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200172
Juha Hyttinen83ada002020-01-30 10:36:33 +0200173 if delStatus == false {
174 return nil
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200175 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200176
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200177 r.mutex.Unlock()
178
179 //
180 // Wait some time before really do route updates
181 //
182 if waitRouteClean > 0 {
183 subs.mutex.Unlock()
184 time.Sleep(waitRouteClean)
185 subs.mutex.Lock()
186 }
187
Juha Hyttinen83ada002020-01-30 10:36:33 +0200188 xapp.Logger.Info("CLEAN %s", subs.String())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200189
190 //
191 // Subscription route updates
192 //
Juha Hyttinen83ada002020-01-30 10:36:33 +0200193 if epamount == 0 {
194 tmpList := RmrEndpointList{}
195 tmpList.AddEndpoint(trans.GetEndpoint())
196 subRouteAction := SubRouteInfo{tmpList, uint16(seqId)}
197 r.rtmgrClient.SubscriptionRequestDelete(subRouteAction)
198 } else if subs.EpList.Size() > 0 {
199 subRouteAction := SubRouteInfo{subs.EpList, uint16(seqId)}
200 r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200201 }
202
203 r.mutex.Lock()
204 //
Juha Hyttinen83ada002020-01-30 10:36:33 +0200205 // If last endpoint, release and free seqid
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200206 //
207 if epamount == 0 {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200208 if _, ok := r.register[seqId]; ok {
209 xapp.Logger.Debug("RELEASE %s", subs.String())
210 delete(r.register, seqId)
211 xapp.Logger.Debug("Registry: substable=%v", r.register)
212 }
213 r.subIds = append(r.subIds, seqId)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200214 }
215
216 return nil
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200217}
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200218
Juha Hyttinen83ada002020-01-30 10:36:33 +0200219func (r *Registry) GetSubscription(sn uint32) *Subscription {
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200220 r.mutex.Lock()
221 defer r.mutex.Unlock()
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200222 if _, ok := r.register[sn]; ok {
223 return r.register[sn]
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200224 }
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200225 return nil
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000226}
227
Juha Hyttinen83ada002020-01-30 10:36:33 +0200228func (r *Registry) GetSubscriptionFirstMatch(ids []uint32) (*Subscription, error) {
Juha Hyttinen422d0182020-01-17 13:37:05 +0200229 r.mutex.Lock()
230 defer r.mutex.Unlock()
231 for _, id := range ids {
232 if _, ok := r.register[id]; ok {
233 return r.register[id], nil
234 }
235 }
236 return nil, fmt.Errorf("No valid subscription found with ids %v", ids)
237}