blob: 7ad54c16143572149e6ada308e7abf2a208fc962 [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 Mannila5c161a92020-01-15 15:40:57 +020045 for i = 0; i < 65535; i++ {
46 r.subIds = append(r.subIds, i+1)
47 }
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()
Juha Hyttinenaada6452020-04-07 08:47:58 +030057 resp = append(resp, &models.SubscriptionData{SubscriptionID: int64(subs.ReqId.InstanceId), Meid: subs.Meid.RanName, Endpoint: subs.EpList.StringList()})
Juha Hyttinenc9eb08a2020-02-28 08:53:33 +020058 subs.mutex.Unlock()
59 }
60 return resp, nil
61}
62
Juha Hyttinen83ada002020-01-30 10:36:33 +020063func (r *Registry) allocateSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*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{
72 registry: r,
Juha Hyttinen3944a222020-01-24 11:51:46 +020073 Meid: trans.Meid,
74 SubReqMsg: subReqMsg,
75 valid: true,
76 }
Juha Hyttinen83ada002020-01-30 10:36:33 +020077 subs.ReqId.Id = 123
Juha Hyttinenaada6452020-04-07 08:47:58 +030078 subs.ReqId.InstanceId = subId
Juha Hyttinen3944a222020-01-24 11:51:46 +020079
80 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
Juha Hyttinenaada6452020-04-07 08:47:58 +030081 r.subIds = append(r.subIds, subs.ReqId.InstanceId)
Juha Hyttinen3944a222020-01-24 11:51:46 +020082 return nil, fmt.Errorf("Registry: Endpoint existing already in subscription")
83 }
84
85 return subs, nil
Juha Hyttinen12d31af2020-01-22 12:59:01 +020086 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020087 return nil, fmt.Errorf("Registry: Failed to reserve subscription no free ids")
88}
89
Anssi Mannila2f26fb22020-12-07 08:32:13 +020090func (r *Registry) findExistingSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, bool) {
Juha Hyttinen83ada002020-01-30 10:36:33 +020091
Juha Hyttinen3944a222020-01-24 11:51:46 +020092 for _, subs := range r.register {
Juha Hyttinen83ada002020-01-30 10:36:33 +020093 if subs.IsMergeable(trans, subReqMsg) {
Juha Hyttinen3944a222020-01-24 11:51:46 +020094
95 //
96 // check if there has been race conditions
97 //
98 subs.mutex.Lock()
99 //subs has been set to invalid
100 if subs.valid == false {
101 subs.mutex.Unlock()
102 continue
103 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200104 // If size is zero, entry is to be deleted
105 if subs.EpList.Size() == 0 {
106 subs.mutex.Unlock()
107 continue
108 }
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200109 // Try to add to endpointlist. Adding fails if endpoint is already in the list
Juha Hyttinen3944a222020-01-24 11:51:46 +0200110 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
111 subs.mutex.Unlock()
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200112 xapp.Logger.Debug("Registry: Subs with requesting endpoint found. %s for %s", subs.String(), trans.String())
113 return subs, true
Juha Hyttinen3944a222020-01-24 11:51:46 +0200114 }
115 subs.mutex.Unlock()
116
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200117 xapp.Logger.Debug("Registry: Mergeable subs found. %s for %s", subs.String(), trans.String())
118 return subs, false
Juha Hyttinen3944a222020-01-24 11:51:46 +0200119 }
120 }
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200121 return nil, false
Juha Hyttinen3944a222020-01-24 11:51:46 +0200122}
123
Juha Hyttinen83ada002020-01-30 10:36:33 +0200124func (r *Registry) AssignToSubscription(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200125 var err error
126 var newAlloc bool
127 r.mutex.Lock()
128 defer r.mutex.Unlock()
129
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200130 //
131 // Check validity of subscription action types
132 //
133 actionType, err := r.CheckActionTypes(subReqMsg)
134 if err != nil {
135 xapp.Logger.Debug("CREATE %s", err)
136 return nil, err
137 }
Juha Hyttinen3944a222020-01-24 11:51:46 +0200138
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200139 //
140 // Find possible existing Policy subscription
141 //
142 if actionType == e2ap.E2AP_ActionTypePolicy {
Juha Hyttinen47942b42020-02-27 10:41:43 +0200143 if subs, ok := r.register[trans.GetSubId()]; ok {
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200144 xapp.Logger.Debug("CREATE %s. Existing subscription for Policy found.", subs.String())
Anssi Mannilacc7d9e02020-04-08 12:58:53 +0300145 // Update message data to subscription
146 subs.SubReqMsg = subReqMsg
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200147 subs.SetCachedResponse(nil, true)
148 return subs, nil
149 }
150 }
151
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200152 subs, endPointFound := r.findExistingSubs(trans, subReqMsg)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200153 if subs == nil {
154 subs, err = r.allocateSubs(trans, subReqMsg)
155 if err != nil {
156 return nil, err
157 }
158 newAlloc = true
Anssi Mannila2f26fb22020-12-07 08:32:13 +0200159 } else if endPointFound == true {
160 // Requesting endpoint is already present in existing subscription. This can happen if xApp is restarted.
161 xapp.Logger.Debug("CREATE: subscription already exists. %s", subs.String())
162 xapp.Logger.Debug("Registry: substable=%v", r.register)
163 return subs, nil
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200164 }
165
166 //
167 // Add to subscription
168 //
169 subs.mutex.Lock()
170 defer subs.mutex.Unlock()
171
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200172 epamount := subs.EpList.Size()
173
174 r.mutex.Unlock()
175 //
176 // Subscription route updates
177 //
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200178 if epamount == 1 {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300179 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.InstanceId)}
Juha Hyttinen83ada002020-01-30 10:36:33 +0200180 err = r.rtmgrClient.SubscriptionRequestCreate(subRouteAction)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200181 } else {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300182 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.InstanceId)}
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200183 err = r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
184 }
185 r.mutex.Lock()
186
187 if err != nil {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200188 if newAlloc {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300189 r.subIds = append(r.subIds, subs.ReqId.InstanceId)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200190 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200191 return nil, err
192 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200193
Juha Hyttinen3944a222020-01-24 11:51:46 +0200194 if newAlloc {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300195 r.register[subs.ReqId.InstanceId] = subs
Juha Hyttinen3944a222020-01-24 11:51:46 +0200196 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200197 xapp.Logger.Debug("CREATE %s", subs.String())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200198 xapp.Logger.Debug("Registry: substable=%v", r.register)
199 return subs, nil
200}
201
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200202func (r *Registry) CheckActionTypes(subReqMsg *e2ap.E2APSubscriptionRequest) (uint64, error) {
203 var reportFound bool = false
204 var policyFound bool = false
Anssi Mannilaf0d95262020-08-17 13:00:20 +0300205 var insertFound bool = false
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200206
207 for _, acts := range subReqMsg.ActionSetups {
208 if acts.ActionType == e2ap.E2AP_ActionTypeReport {
209 reportFound = true
210 }
211 if acts.ActionType == e2ap.E2AP_ActionTypePolicy {
212 policyFound = true
213 }
Anssi Mannilaf0d95262020-08-17 13:00:20 +0300214 if acts.ActionType == e2ap.E2AP_ActionTypeInsert {
215 insertFound = true
216 }
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200217 }
Anssi Mannilaf0d95262020-08-17 13:00:20 +0300218 if reportFound == true && policyFound == true || reportFound == true && insertFound == true || policyFound == true && insertFound == true {
219 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 +0200220 }
221 if reportFound == true {
222 return e2ap.E2AP_ActionTypeReport, nil
223 }
224 if policyFound == true {
225 return e2ap.E2AP_ActionTypePolicy, nil
226 }
Anssi Mannilaf0d95262020-08-17 13:00:20 +0300227 if insertFound == true {
228 return e2ap.E2AP_ActionTypeInsert, nil
229 }
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200230 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Invalid action type in RICactions-ToBeSetup-List")
231}
232
Juha Hyttinen83ada002020-01-30 10:36:33 +0200233// TODO: Works with concurrent calls, but check if can be improved
234func (r *Registry) RemoveFromSubscription(subs *Subscription, trans *TransactionXapp, waitRouteClean time.Duration) error {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200235
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200236 r.mutex.Lock()
237 defer r.mutex.Unlock()
238 subs.mutex.Lock()
239 defer subs.mutex.Unlock()
240
241 delStatus := subs.EpList.DelEndpoint(trans.GetEndpoint())
242 epamount := subs.EpList.Size()
Juha Hyttinenaada6452020-04-07 08:47:58 +0300243 subId := subs.ReqId.InstanceId
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200244
Juha Hyttinen83ada002020-01-30 10:36:33 +0200245 if delStatus == false {
246 return nil
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200247 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200248
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200249 go func() {
250 if waitRouteClean > 0 {
251 time.Sleep(waitRouteClean)
Juha Hyttinen83ada002020-01-30 10:36:33 +0200252 }
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200253
254 subs.mutex.Lock()
255 defer subs.mutex.Unlock()
256 xapp.Logger.Info("CLEAN %s", subs.String())
257
258 if epamount == 0 {
259 //
260 // Subscription route delete
261 //
Juha Hyttinen9dc5adc2020-08-13 10:02:40 +0300262 tmpList := xapp.RmrEndpointList{}
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200263 tmpList.AddEndpoint(trans.GetEndpoint())
Juha Hyttinenaada6452020-04-07 08:47:58 +0300264 subRouteAction := SubRouteInfo{tmpList, uint16(subId)}
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200265 r.rtmgrClient.SubscriptionRequestDelete(subRouteAction)
266
267 //
268 // Subscription release
269 //
270 r.mutex.Lock()
271 defer r.mutex.Unlock()
272
Juha Hyttinenaada6452020-04-07 08:47:58 +0300273 if _, ok := r.register[subId]; ok {
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200274 xapp.Logger.Debug("RELEASE %s", subs.String())
Juha Hyttinenaada6452020-04-07 08:47:58 +0300275 delete(r.register, subId)
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200276 xapp.Logger.Debug("Registry: substable=%v", r.register)
277 }
Juha Hyttinenaada6452020-04-07 08:47:58 +0300278 r.subIds = append(r.subIds, subId)
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200279
280 } else if subs.EpList.Size() > 0 {
281 //
282 // Subscription route updates
283 //
Juha Hyttinenaada6452020-04-07 08:47:58 +0300284 subRouteAction := SubRouteInfo{subs.EpList, uint16(subId)}
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200285 r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
286 }
287
288 }()
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200289
290 return nil
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200291}
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200292
Juha Hyttinenaada6452020-04-07 08:47:58 +0300293func (r *Registry) GetSubscription(subId uint32) *Subscription {
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200294 r.mutex.Lock()
295 defer r.mutex.Unlock()
Juha Hyttinenaada6452020-04-07 08:47:58 +0300296 if _, ok := r.register[subId]; ok {
297 return r.register[subId]
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200298 }
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200299 return nil
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000300}
301
Juha Hyttinenaada6452020-04-07 08:47:58 +0300302func (r *Registry) GetSubscriptionFirstMatch(subIds []uint32) (*Subscription, error) {
Juha Hyttinen422d0182020-01-17 13:37:05 +0200303 r.mutex.Lock()
304 defer r.mutex.Unlock()
Juha Hyttinenaada6452020-04-07 08:47:58 +0300305 for _, subId := range subIds {
306 if _, ok := r.register[subId]; ok {
307 return r.register[subId], nil
Juha Hyttinen422d0182020-01-17 13:37:05 +0200308 }
309 }
Juha Hyttinenaada6452020-04-07 08:47:58 +0300310 return nil, fmt.Errorf("No valid subscription found with subIds %v", subIds)
Juha Hyttinen422d0182020-01-17 13:37:05 +0200311}