blob: 1c6ab3d745d35e73a4c6885c1b7afdcb3f7c9d18 [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"
Juha Hyttinenc9eb08a2020-02-28 08:53:33 +020025 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models"
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020026 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
27 "sync"
Juha Hyttinen12d31af2020-01-22 12:59:01 +020028 "time"
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020029)
30
Juha Hyttinen0d064ec2020-01-09 09:08:53 +020031//-----------------------------------------------------------------------------
32//
33//-----------------------------------------------------------------------------
Juha Hyttinen83ada002020-01-30 10:36:33 +020034
kalnagy45114752019-06-18 14:40:39 +020035type Registry struct {
Juha Hyttinen0388dd92020-01-09 14:14:16 +020036 mutex sync.Mutex
Juha Hyttinen83ada002020-01-30 10:36:33 +020037 register map[uint32]*Subscription
38 subIds []uint32
Juha Hyttinen0388dd92020-01-09 14:14:16 +020039 rtmgrClient *RtmgrClient
kalnagy45114752019-06-18 14:40:39 +020040}
41
Anssi Mannila5c161a92020-01-15 15:40:57 +020042func (r *Registry) Initialize() {
Juha Hyttinen83ada002020-01-30 10:36:33 +020043 r.register = make(map[uint32]*Subscription)
44 var i uint32
Anssi Mannilac92b4212020-12-07 14:59:34 +020045 for i = 1; i < 65535; i++ {
46 r.subIds = append(r.subIds, i)
Anssi Mannila5c161a92020-01-15 15:40:57 +020047 }
kalnagy45114752019-06-18 14:40:39 +020048}
49
Juha Hyttinenc9eb08a2020-02-28 08:53:33 +020050func (r *Registry) QueryHandler() (models.SubscriptionList, error) {
51 r.mutex.Lock()
52 defer r.mutex.Unlock()
53
54 resp := models.SubscriptionList{}
55 for _, subs := range r.register {
56 subs.mutex.Lock()
archaggea5c58bc2021-04-14 08:54:05 +030057 resp = append(resp, &models.SubscriptionData{SubscriptionID: int64(subs.ReqId.InstanceId), Meid: subs.Meid.RanName, ClientEndpoint: subs.EpList.StringList()})
Juha Hyttinenc9eb08a2020-02-28 08:53:33 +020058 subs.mutex.Unlock()
59 }
60 return resp, nil
61}
62
Anssi Mannilac92b4212020-12-07 14:59:34 +020063func (r *Registry) allocateSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest, resetTestFlag bool) (*Subscription, error) {
Juha Hyttinen12d31af2020-01-22 12:59:01 +020064 if len(r.subIds) > 0 {
Juha Hyttinenaada6452020-04-07 08:47:58 +030065 subId := r.subIds[0]
Juha Hyttinen12d31af2020-01-22 12:59:01 +020066 r.subIds = r.subIds[1:]
Juha Hyttinenaada6452020-04-07 08:47:58 +030067 if _, ok := r.register[subId]; ok == true {
68 r.subIds = append(r.subIds, subId)
Juha Hyttinen3944a222020-01-24 11:51:46 +020069 return nil, fmt.Errorf("Registry: Failed to reserve subscription exists")
Juha Hyttinen12d31af2020-01-22 12:59:01 +020070 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020071 subs := &Subscription{
Anssi Mannilac92b4212020-12-07 14:59:34 +020072 registry: r,
73 Meid: trans.Meid,
74 SubReqMsg: subReqMsg,
75 valid: true,
76 RetryFromXapp: false,
77 SubRespRcvd: false,
78 DeleteFromDb: false,
79 NoRespToXapp: false,
80 DoNotWaitSubResp: false,
Juha Hyttinen3944a222020-01-24 11:51:46 +020081 }
Juha Hyttinen83ada002020-01-30 10:36:33 +020082 subs.ReqId.Id = 123
Juha Hyttinenaada6452020-04-07 08:47:58 +030083 subs.ReqId.InstanceId = subId
Anssi Mannilac92b4212020-12-07 14:59:34 +020084 if resetTestFlag == true {
85 subs.DoNotWaitSubResp = true
86 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020087
88 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
Juha Hyttinenaada6452020-04-07 08:47:58 +030089 r.subIds = append(r.subIds, subs.ReqId.InstanceId)
Juha Hyttinen3944a222020-01-24 11:51:46 +020090 return nil, fmt.Errorf("Registry: Endpoint existing already in subscription")
91 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020092 return subs, nil
Juha Hyttinen12d31af2020-01-22 12:59:01 +020093 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020094 return nil, fmt.Errorf("Registry: Failed to reserve subscription no free ids")
95}
96
Anssi Mannila2f26fb22020-12-07 08:32:13 +020097func (r *Registry) findExistingSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, bool) {
Juha Hyttinen83ada002020-01-30 10:36:33 +020098
Juha Hyttinen3944a222020-01-24 11:51:46 +020099 for _, subs := range r.register {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200100 if subs.IsMergeable(trans, subReqMsg) {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200101
102 //
103 // check if there has been race conditions
104 //
105 subs.mutex.Lock()
106 //subs has been set to invalid
107 if subs.valid == false {
108 subs.mutex.Unlock()
109 continue
110 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200111 // If size is zero, entry is to be deleted
112 if subs.EpList.Size() == 0 {
113 subs.mutex.Unlock()
114 continue
115 }
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200116 // Try to add to endpointlist. Adding fails if endpoint is already in the list
Juha Hyttinen3944a222020-01-24 11:51:46 +0200117 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
118 subs.mutex.Unlock()
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200119 xapp.Logger.Debug("Registry: Subs with requesting endpoint found. %s for %s", subs.String(), trans.String())
120 return subs, true
Juha Hyttinen3944a222020-01-24 11:51:46 +0200121 }
122 subs.mutex.Unlock()
123
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200124 xapp.Logger.Debug("Registry: Mergeable subs found. %s for %s", subs.String(), trans.String())
125 return subs, false
Juha Hyttinen3944a222020-01-24 11:51:46 +0200126 }
127 }
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200128 return nil, false
Juha Hyttinen3944a222020-01-24 11:51:46 +0200129}
130
Anssi Mannila4abf1802021-01-28 13:06:46 +0200131func (r *Registry) AssignToSubscription(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest, resetTestFlag bool, c *Control) (*Subscription, error) {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200132 var err error
133 var newAlloc bool
134 r.mutex.Lock()
135 defer r.mutex.Unlock()
136
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200137 //
138 // Check validity of subscription action types
139 //
140 actionType, err := r.CheckActionTypes(subReqMsg)
141 if err != nil {
142 xapp.Logger.Debug("CREATE %s", err)
143 return nil, err
144 }
Juha Hyttinen3944a222020-01-24 11:51:46 +0200145
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200146 //
147 // Find possible existing Policy subscription
148 //
149 if actionType == e2ap.E2AP_ActionTypePolicy {
Juha Hyttinen47942b42020-02-27 10:41:43 +0200150 if subs, ok := r.register[trans.GetSubId()]; ok {
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200151 xapp.Logger.Debug("CREATE %s. Existing subscription for Policy found.", subs.String())
Anssi Mannilacc7d9e02020-04-08 12:58:53 +0300152 // Update message data to subscription
153 subs.SubReqMsg = subReqMsg
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200154 subs.SetCachedResponse(nil, true)
155 return subs, nil
156 }
157 }
158
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200159 subs, endPointFound := r.findExistingSubs(trans, subReqMsg)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200160 if subs == nil {
Anssi Mannila4abf1802021-01-28 13:06:46 +0200161 if subs, err = r.allocateSubs(trans, subReqMsg, resetTestFlag); err != nil {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200162 return nil, err
163 }
164 newAlloc = true
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200165 } else if endPointFound == true {
166 // Requesting endpoint is already present in existing subscription. This can happen if xApp is restarted.
Anssi Mannilac92b4212020-12-07 14:59:34 +0200167 subs.RetryFromXapp = true
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200168 xapp.Logger.Debug("CREATE: subscription already exists. %s", subs.String())
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200169 return subs, nil
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200170 }
171
172 //
173 // Add to subscription
174 //
175 subs.mutex.Lock()
176 defer subs.mutex.Unlock()
177
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200178 epamount := subs.EpList.Size()
Anssi Mannila4abf1802021-01-28 13:06:46 +0200179 xapp.Logger.Info("AssignToSubscription subs.EpList.Size() = %v", subs.EpList.Size())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200180
181 r.mutex.Unlock()
182 //
183 // Subscription route updates
184 //
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200185 if epamount == 1 {
Anssi Mannila4abf1802021-01-28 13:06:46 +0200186 err = r.RouteCreate(subs, c)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200187 } else {
Anssi Mannila4abf1802021-01-28 13:06:46 +0200188 err = r.RouteCreateUpdate(subs, c)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200189 }
190 r.mutex.Lock()
191
192 if err != nil {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200193 if newAlloc {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300194 r.subIds = append(r.subIds, subs.ReqId.InstanceId)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200195 }
Anssi Mannila4abf1802021-01-28 13:06:46 +0200196 // Delete already added endpoint for the request
197 subs.EpList.DelEndpoint(trans.GetEndpoint())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200198 return nil, err
199 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200200
Juha Hyttinen3944a222020-01-24 11:51:46 +0200201 if newAlloc {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300202 r.register[subs.ReqId.InstanceId] = subs
Juha Hyttinen3944a222020-01-24 11:51:46 +0200203 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200204 xapp.Logger.Debug("CREATE %s", subs.String())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200205 xapp.Logger.Debug("Registry: substable=%v", r.register)
206 return subs, nil
207}
208
Anssi Mannila4abf1802021-01-28 13:06:46 +0200209func (r *Registry) RouteCreate(subs *Subscription, c *Control) error {
210 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.InstanceId)}
211 err := r.rtmgrClient.SubscriptionRequestCreate(subRouteAction)
212 if err != nil {
213 c.UpdateCounter(cRouteCreateFail)
214 }
215 return err
216}
217
218func (r *Registry) RouteCreateUpdate(subs *Subscription, c *Control) error {
219 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.InstanceId)}
220 err := r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
221 if err != nil {
222 c.UpdateCounter(cRouteCreateUpdateFail)
223 return err
224 }
225 c.UpdateCounter(cMergedSubscriptions)
226 return err
227}
228
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200229func (r *Registry) CheckActionTypes(subReqMsg *e2ap.E2APSubscriptionRequest) (uint64, error) {
230 var reportFound bool = false
231 var policyFound bool = false
Anssi Mannilaf0d95262020-08-17 13:00:20 +0300232 var insertFound bool = false
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200233
234 for _, acts := range subReqMsg.ActionSetups {
235 if acts.ActionType == e2ap.E2AP_ActionTypeReport {
236 reportFound = true
237 }
238 if acts.ActionType == e2ap.E2AP_ActionTypePolicy {
239 policyFound = true
240 }
Anssi Mannilaf0d95262020-08-17 13:00:20 +0300241 if acts.ActionType == e2ap.E2AP_ActionTypeInsert {
242 insertFound = true
243 }
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200244 }
Anssi Mannilaf0d95262020-08-17 13:00:20 +0300245 if reportFound == true && policyFound == true || reportFound == true && insertFound == true || policyFound == true && insertFound == true {
246 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Different action types (Report, Policy or Insert) in same RICactions-ToBeSetup-List")
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200247 }
248 if reportFound == true {
249 return e2ap.E2AP_ActionTypeReport, nil
250 }
251 if policyFound == true {
252 return e2ap.E2AP_ActionTypePolicy, nil
253 }
Anssi Mannilaf0d95262020-08-17 13:00:20 +0300254 if insertFound == true {
255 return e2ap.E2AP_ActionTypeInsert, nil
256 }
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200257 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Invalid action type in RICactions-ToBeSetup-List")
258}
259
Juha Hyttinen83ada002020-01-30 10:36:33 +0200260// TODO: Works with concurrent calls, but check if can be improved
Anssi Mannilac92b4212020-12-07 14:59:34 +0200261func (r *Registry) RemoveFromSubscription(subs *Subscription, trans *TransactionXapp, waitRouteClean time.Duration, c *Control) error {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200262
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200263 r.mutex.Lock()
264 defer r.mutex.Unlock()
265 subs.mutex.Lock()
266 defer subs.mutex.Unlock()
267
268 delStatus := subs.EpList.DelEndpoint(trans.GetEndpoint())
269 epamount := subs.EpList.Size()
Juha Hyttinenaada6452020-04-07 08:47:58 +0300270 subId := subs.ReqId.InstanceId
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200271
Juha Hyttinen83ada002020-01-30 10:36:33 +0200272 if delStatus == false {
273 return nil
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200274 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200275
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200276 go func() {
277 if waitRouteClean > 0 {
278 time.Sleep(waitRouteClean)
Juha Hyttinen83ada002020-01-30 10:36:33 +0200279 }
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200280
281 subs.mutex.Lock()
282 defer subs.mutex.Unlock()
283 xapp.Logger.Info("CLEAN %s", subs.String())
284
285 if epamount == 0 {
286 //
287 // Subscription route delete
288 //
Anssi Mannila4abf1802021-01-28 13:06:46 +0200289 r.RouteDelete(subs, trans, c)
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200290
291 //
292 // Subscription release
293 //
294 r.mutex.Lock()
295 defer r.mutex.Unlock()
296
Juha Hyttinenaada6452020-04-07 08:47:58 +0300297 if _, ok := r.register[subId]; ok {
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200298 xapp.Logger.Debug("RELEASE %s", subs.String())
Juha Hyttinenaada6452020-04-07 08:47:58 +0300299 delete(r.register, subId)
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200300 xapp.Logger.Debug("Registry: substable=%v", r.register)
301 }
Juha Hyttinenaada6452020-04-07 08:47:58 +0300302 r.subIds = append(r.subIds, subId)
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200303 } else if subs.EpList.Size() > 0 {
304 //
Anssi Mannila4abf1802021-01-28 13:06:46 +0200305 // Subscription route update
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200306 //
Anssi Mannila4abf1802021-01-28 13:06:46 +0200307 r.RouteDeleteUpdate(subs, c)
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200308 }
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200309 }()
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200310
311 return nil
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200312}
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200313
Anssi Mannila4abf1802021-01-28 13:06:46 +0200314func (r *Registry) RouteDelete(subs *Subscription, trans *TransactionXapp, c *Control) {
315 tmpList := xapp.RmrEndpointList{}
316 tmpList.AddEndpoint(trans.GetEndpoint())
317 subRouteAction := SubRouteInfo{tmpList, uint16(subs.ReqId.InstanceId)}
318 if err := r.rtmgrClient.SubscriptionRequestDelete(subRouteAction); err != nil {
319 c.UpdateCounter(cRouteDeleteFail)
320 }
321}
322
323func (r *Registry) RouteDeleteUpdate(subs *Subscription, c *Control) {
324 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.InstanceId)}
325 if err := r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction); err != nil {
326 c.UpdateCounter(cRouteDeleteUpdateFail)
327 }
328}
329
Anssi Mannilac92b4212020-12-07 14:59:34 +0200330func (r *Registry) UpdateSubscriptionToDb(subs *Subscription, c *Control) {
331 r.mutex.Lock()
332 defer r.mutex.Unlock()
333 subs.mutex.Lock()
334 defer subs.mutex.Unlock()
335
336 epamount := subs.EpList.Size()
337 if epamount == 0 {
338 if _, ok := r.register[subs.ReqId.InstanceId]; ok {
339 // Not merged subscription is being deleted
340 c.RemoveSubscriptionFromDb(subs)
341
342 }
343 } else if subs.EpList.Size() > 0 {
344 // Endpoint of merged subscription is being deleted
345 c.WriteSubscriptionToDb(subs)
Anssi Mannila4abf1802021-01-28 13:06:46 +0200346 c.UpdateCounter(cUnmergedSubscriptions)
Anssi Mannilac92b4212020-12-07 14:59:34 +0200347 }
348}
349
Juha Hyttinenaada6452020-04-07 08:47:58 +0300350func (r *Registry) GetSubscription(subId uint32) *Subscription {
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200351 r.mutex.Lock()
352 defer r.mutex.Unlock()
Juha Hyttinenaada6452020-04-07 08:47:58 +0300353 if _, ok := r.register[subId]; ok {
354 return r.register[subId]
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200355 }
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200356 return nil
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000357}
358
Juha Hyttinenaada6452020-04-07 08:47:58 +0300359func (r *Registry) GetSubscriptionFirstMatch(subIds []uint32) (*Subscription, error) {
Juha Hyttinen422d0182020-01-17 13:37:05 +0200360 r.mutex.Lock()
361 defer r.mutex.Unlock()
Juha Hyttinenaada6452020-04-07 08:47:58 +0300362 for _, subId := range subIds {
363 if _, ok := r.register[subId]; ok {
364 return r.register[subId], nil
Juha Hyttinen422d0182020-01-17 13:37:05 +0200365 }
366 }
Juha Hyttinenaada6452020-04-07 08:47:58 +0300367 return nil, fmt.Errorf("No valid subscription found with subIds %v", subIds)
Juha Hyttinen422d0182020-01-17 13:37:05 +0200368}