blob: b816b61c5d66e2e4632afe8464a33762f6df9128 [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()
57 resp = append(resp, &models.SubscriptionData{SubscriptionID: int64(subs.ReqId.Seq), Meid: subs.Meid.RanName, Endpoint: subs.EpList.StringList()})
58 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 Hyttinen3944a222020-01-24 11:51:46 +020065 sequenceNumber := r.subIds[0]
Juha Hyttinen12d31af2020-01-22 12:59:01 +020066 r.subIds = r.subIds[1:]
67 if _, ok := r.register[sequenceNumber]; ok == true {
68 r.subIds = append(r.subIds, sequenceNumber)
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
78 subs.ReqId.Seq = sequenceNumber
Juha Hyttinen3944a222020-01-24 11:51:46 +020079
80 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
Juha Hyttinen83ada002020-01-30 10:36:33 +020081 r.subIds = append(r.subIds, subs.ReqId.Seq)
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
Juha Hyttinen83ada002020-01-30 10:36:33 +020090func (r *Registry) findExistingSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) *Subscription {
91
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 }
Juha Hyttinen3944a222020-01-24 11:51:46 +0200109 // try to add to endpointlist.
110 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
111 subs.mutex.Unlock()
112 continue
113 }
114 subs.mutex.Unlock()
115
Juha Hyttinen83ada002020-01-30 10:36:33 +0200116 xapp.Logger.Debug("Registry: Mergeable subs found %s for %s", subs.String(), trans.String())
Juha Hyttinen3944a222020-01-24 11:51:46 +0200117 return subs
118 }
119 }
120 return nil
121}
122
Juha Hyttinen83ada002020-01-30 10:36:33 +0200123func (r *Registry) AssignToSubscription(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200124 var err error
125 var newAlloc bool
126 r.mutex.Lock()
127 defer r.mutex.Unlock()
128
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200129 //
130 // Check validity of subscription action types
131 //
132 actionType, err := r.CheckActionTypes(subReqMsg)
133 if err != nil {
134 xapp.Logger.Debug("CREATE %s", err)
135 return nil, err
136 }
Juha Hyttinen3944a222020-01-24 11:51:46 +0200137
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200138 //
139 // Find possible existing Policy subscription
140 //
141 if actionType == e2ap.E2AP_ActionTypePolicy {
Juha Hyttinen47942b42020-02-27 10:41:43 +0200142 if subs, ok := r.register[trans.GetSubId()]; ok {
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200143 xapp.Logger.Debug("CREATE %s. Existing subscription for Policy found", subs.String())
144 subs.SetCachedResponse(nil, true)
145 return subs, nil
146 }
147 }
148
149 subs := r.findExistingSubs(trans, subReqMsg)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200150 if subs == nil {
151 subs, err = r.allocateSubs(trans, subReqMsg)
152 if err != nil {
153 return nil, err
154 }
155 newAlloc = true
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200156 }
157
158 //
159 // Add to subscription
160 //
161 subs.mutex.Lock()
162 defer subs.mutex.Unlock()
163
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200164 epamount := subs.EpList.Size()
165
166 r.mutex.Unlock()
167 //
168 // Subscription route updates
169 //
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200170 if epamount == 1 {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200171 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.Seq)}
172 err = r.rtmgrClient.SubscriptionRequestCreate(subRouteAction)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200173 } else {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200174 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.Seq)}
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200175 err = r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
176 }
177 r.mutex.Lock()
178
179 if err != nil {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200180 if newAlloc {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200181 r.subIds = append(r.subIds, subs.ReqId.Seq)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200182 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200183 return nil, err
184 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200185
Juha Hyttinen3944a222020-01-24 11:51:46 +0200186 if newAlloc {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200187 r.register[subs.ReqId.Seq] = subs
Juha Hyttinen3944a222020-01-24 11:51:46 +0200188 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200189 xapp.Logger.Debug("CREATE %s", subs.String())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200190 xapp.Logger.Debug("Registry: substable=%v", r.register)
191 return subs, nil
192}
193
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200194func (r *Registry) CheckActionTypes(subReqMsg *e2ap.E2APSubscriptionRequest) (uint64, error) {
195 var reportFound bool = false
196 var policyFound bool = false
197
198 for _, acts := range subReqMsg.ActionSetups {
199 if acts.ActionType == e2ap.E2AP_ActionTypeReport {
200 reportFound = true
201 }
202 if acts.ActionType == e2ap.E2AP_ActionTypePolicy {
203 policyFound = true
204 }
205 }
206 if reportFound == true && policyFound == true {
207 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Report and Policy in same RICactions-ToBeSetup-List")
208 }
209 if reportFound == true {
210 return e2ap.E2AP_ActionTypeReport, nil
211 }
212 if policyFound == true {
213 return e2ap.E2AP_ActionTypePolicy, nil
214 }
215 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Invalid action type in RICactions-ToBeSetup-List")
216}
217
Juha Hyttinen83ada002020-01-30 10:36:33 +0200218// TODO: Works with concurrent calls, but check if can be improved
219func (r *Registry) RemoveFromSubscription(subs *Subscription, trans *TransactionXapp, waitRouteClean time.Duration) error {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200220
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200221 r.mutex.Lock()
222 defer r.mutex.Unlock()
223 subs.mutex.Lock()
224 defer subs.mutex.Unlock()
225
226 delStatus := subs.EpList.DelEndpoint(trans.GetEndpoint())
227 epamount := subs.EpList.Size()
Juha Hyttinen83ada002020-01-30 10:36:33 +0200228 seqId := subs.ReqId.Seq
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200229
Juha Hyttinen83ada002020-01-30 10:36:33 +0200230 if delStatus == false {
231 return nil
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200232 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200233
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200234 go func() {
235 if waitRouteClean > 0 {
236 time.Sleep(waitRouteClean)
Juha Hyttinen83ada002020-01-30 10:36:33 +0200237 }
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200238
239 subs.mutex.Lock()
240 defer subs.mutex.Unlock()
241 xapp.Logger.Info("CLEAN %s", subs.String())
242
243 if epamount == 0 {
244 //
245 // Subscription route delete
246 //
247 tmpList := RmrEndpointList{}
248 tmpList.AddEndpoint(trans.GetEndpoint())
249 subRouteAction := SubRouteInfo{tmpList, uint16(seqId)}
250 r.rtmgrClient.SubscriptionRequestDelete(subRouteAction)
251
252 //
253 // Subscription release
254 //
255 r.mutex.Lock()
256 defer r.mutex.Unlock()
257
258 if _, ok := r.register[seqId]; ok {
259 xapp.Logger.Debug("RELEASE %s", subs.String())
260 delete(r.register, seqId)
261 xapp.Logger.Debug("Registry: substable=%v", r.register)
262 }
263 r.subIds = append(r.subIds, seqId)
264
265 } else if subs.EpList.Size() > 0 {
266 //
267 // Subscription route updates
268 //
269 subRouteAction := SubRouteInfo{subs.EpList, uint16(seqId)}
270 r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
271 }
272
273 }()
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200274
275 return nil
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200276}
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200277
Juha Hyttinen83ada002020-01-30 10:36:33 +0200278func (r *Registry) GetSubscription(sn uint32) *Subscription {
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200279 r.mutex.Lock()
280 defer r.mutex.Unlock()
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200281 if _, ok := r.register[sn]; ok {
282 return r.register[sn]
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200283 }
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200284 return nil
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000285}
286
Juha Hyttinen83ada002020-01-30 10:36:33 +0200287func (r *Registry) GetSubscriptionFirstMatch(ids []uint32) (*Subscription, error) {
Juha Hyttinen422d0182020-01-17 13:37:05 +0200288 r.mutex.Lock()
289 defer r.mutex.Unlock()
290 for _, id := range ids {
291 if _, ok := r.register[id]; ok {
292 return r.register[id], nil
293 }
294 }
295 return nil, fmt.Errorf("No valid subscription found with ids %v", ids)
296}