blob: 25709605a29c1a56c8d5d333abc19af599eba112 [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 Hyttinenb31b13f2020-03-18 10:25:30 +020025 "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/xapptweaks"
Juha Hyttinenc9eb08a2020-02-28 08:53:33 +020026 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models"
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020027 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
28 "sync"
Juha Hyttinen12d31af2020-01-22 12:59:01 +020029 "time"
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020030)
31
Juha Hyttinen0d064ec2020-01-09 09:08:53 +020032//-----------------------------------------------------------------------------
33//
34//-----------------------------------------------------------------------------
Juha Hyttinen83ada002020-01-30 10:36:33 +020035
kalnagy45114752019-06-18 14:40:39 +020036type Registry struct {
Juha Hyttinen0388dd92020-01-09 14:14:16 +020037 mutex sync.Mutex
Juha Hyttinen83ada002020-01-30 10:36:33 +020038 register map[uint32]*Subscription
39 subIds []uint32
Juha Hyttinen0388dd92020-01-09 14:14:16 +020040 rtmgrClient *RtmgrClient
kalnagy45114752019-06-18 14:40:39 +020041}
42
Anssi Mannila5c161a92020-01-15 15:40:57 +020043func (r *Registry) Initialize() {
Juha Hyttinen83ada002020-01-30 10:36:33 +020044 r.register = make(map[uint32]*Subscription)
45 var i uint32
Anssi Mannila5c161a92020-01-15 15:40:57 +020046 for i = 0; i < 65535; i++ {
47 r.subIds = append(r.subIds, i+1)
48 }
kalnagy45114752019-06-18 14:40:39 +020049}
50
Juha Hyttinenc9eb08a2020-02-28 08:53:33 +020051func (r *Registry) QueryHandler() (models.SubscriptionList, error) {
52 r.mutex.Lock()
53 defer r.mutex.Unlock()
54
55 resp := models.SubscriptionList{}
56 for _, subs := range r.register {
57 subs.mutex.Lock()
58 resp = append(resp, &models.SubscriptionData{SubscriptionID: int64(subs.ReqId.Seq), Meid: subs.Meid.RanName, Endpoint: subs.EpList.StringList()})
59 subs.mutex.Unlock()
60 }
61 return resp, nil
62}
63
Juha Hyttinen83ada002020-01-30 10:36:33 +020064func (r *Registry) allocateSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
Juha Hyttinen12d31af2020-01-22 12:59:01 +020065 if len(r.subIds) > 0 {
Juha Hyttinen3944a222020-01-24 11:51:46 +020066 sequenceNumber := r.subIds[0]
Juha Hyttinen12d31af2020-01-22 12:59:01 +020067 r.subIds = r.subIds[1:]
68 if _, ok := r.register[sequenceNumber]; ok == true {
69 r.subIds = append(r.subIds, sequenceNumber)
Juha Hyttinen3944a222020-01-24 11:51:46 +020070 return nil, fmt.Errorf("Registry: Failed to reserve subscription exists")
Juha Hyttinen12d31af2020-01-22 12:59:01 +020071 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020072 subs := &Subscription{
73 registry: r,
Juha Hyttinen3944a222020-01-24 11:51:46 +020074 Meid: trans.Meid,
75 SubReqMsg: subReqMsg,
76 valid: true,
77 }
Juha Hyttinen83ada002020-01-30 10:36:33 +020078 subs.ReqId.Id = 123
79 subs.ReqId.Seq = sequenceNumber
Juha Hyttinen3944a222020-01-24 11:51:46 +020080
81 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
Juha Hyttinen83ada002020-01-30 10:36:33 +020082 r.subIds = append(r.subIds, subs.ReqId.Seq)
Juha Hyttinen3944a222020-01-24 11:51:46 +020083 return nil, fmt.Errorf("Registry: Endpoint existing already in subscription")
84 }
85
86 return subs, nil
Juha Hyttinen12d31af2020-01-22 12:59:01 +020087 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020088 return nil, fmt.Errorf("Registry: Failed to reserve subscription no free ids")
89}
90
Juha Hyttinen83ada002020-01-30 10:36:33 +020091func (r *Registry) findExistingSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) *Subscription {
92
Juha Hyttinen3944a222020-01-24 11:51:46 +020093 for _, subs := range r.register {
Juha Hyttinen83ada002020-01-30 10:36:33 +020094 if subs.IsMergeable(trans, subReqMsg) {
Juha Hyttinen3944a222020-01-24 11:51:46 +020095
96 //
97 // check if there has been race conditions
98 //
99 subs.mutex.Lock()
100 //subs has been set to invalid
101 if subs.valid == false {
102 subs.mutex.Unlock()
103 continue
104 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200105 // If size is zero, entry is to be deleted
106 if subs.EpList.Size() == 0 {
107 subs.mutex.Unlock()
108 continue
109 }
Juha Hyttinen3944a222020-01-24 11:51:46 +0200110 // try to add to endpointlist.
111 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
112 subs.mutex.Unlock()
113 continue
114 }
115 subs.mutex.Unlock()
116
Juha Hyttinen83ada002020-01-30 10:36:33 +0200117 xapp.Logger.Debug("Registry: Mergeable subs found %s for %s", subs.String(), trans.String())
Juha Hyttinen3944a222020-01-24 11:51:46 +0200118 return subs
119 }
120 }
121 return nil
122}
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 Mannila9bcb0a42020-02-11 11:30:44 +0200144 xapp.Logger.Debug("CREATE %s. Existing subscription for Policy found", subs.String())
145 subs.SetCachedResponse(nil, true)
146 return subs, nil
147 }
148 }
149
150 subs := r.findExistingSubs(trans, subReqMsg)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200151 if subs == nil {
152 subs, err = r.allocateSubs(trans, subReqMsg)
153 if err != nil {
154 return nil, err
155 }
156 newAlloc = true
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200157 }
158
159 //
160 // Add to subscription
161 //
162 subs.mutex.Lock()
163 defer subs.mutex.Unlock()
164
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200165 epamount := subs.EpList.Size()
166
167 r.mutex.Unlock()
168 //
169 // Subscription route updates
170 //
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200171 if epamount == 1 {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200172 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.Seq)}
173 err = r.rtmgrClient.SubscriptionRequestCreate(subRouteAction)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200174 } else {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200175 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.Seq)}
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200176 err = r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
177 }
178 r.mutex.Lock()
179
180 if err != nil {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200181 if newAlloc {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200182 r.subIds = append(r.subIds, subs.ReqId.Seq)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200183 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200184 return nil, err
185 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200186
Juha Hyttinen3944a222020-01-24 11:51:46 +0200187 if newAlloc {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200188 r.register[subs.ReqId.Seq] = subs
Juha Hyttinen3944a222020-01-24 11:51:46 +0200189 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200190 xapp.Logger.Debug("CREATE %s", subs.String())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200191 xapp.Logger.Debug("Registry: substable=%v", r.register)
192 return subs, nil
193}
194
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200195func (r *Registry) CheckActionTypes(subReqMsg *e2ap.E2APSubscriptionRequest) (uint64, error) {
196 var reportFound bool = false
197 var policyFound bool = false
198
199 for _, acts := range subReqMsg.ActionSetups {
200 if acts.ActionType == e2ap.E2AP_ActionTypeReport {
201 reportFound = true
202 }
203 if acts.ActionType == e2ap.E2AP_ActionTypePolicy {
204 policyFound = true
205 }
206 }
207 if reportFound == true && policyFound == true {
208 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Report and Policy in same RICactions-ToBeSetup-List")
209 }
210 if reportFound == true {
211 return e2ap.E2AP_ActionTypeReport, nil
212 }
213 if policyFound == true {
214 return e2ap.E2AP_ActionTypePolicy, nil
215 }
216 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Invalid action type in RICactions-ToBeSetup-List")
217}
218
Juha Hyttinen83ada002020-01-30 10:36:33 +0200219// TODO: Works with concurrent calls, but check if can be improved
220func (r *Registry) RemoveFromSubscription(subs *Subscription, trans *TransactionXapp, waitRouteClean time.Duration) error {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200221
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200222 r.mutex.Lock()
223 defer r.mutex.Unlock()
224 subs.mutex.Lock()
225 defer subs.mutex.Unlock()
226
227 delStatus := subs.EpList.DelEndpoint(trans.GetEndpoint())
228 epamount := subs.EpList.Size()
Juha Hyttinen83ada002020-01-30 10:36:33 +0200229 seqId := subs.ReqId.Seq
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200230
Juha Hyttinen83ada002020-01-30 10:36:33 +0200231 if delStatus == false {
232 return nil
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200233 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200234
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200235 go func() {
236 if waitRouteClean > 0 {
237 time.Sleep(waitRouteClean)
Juha Hyttinen83ada002020-01-30 10:36:33 +0200238 }
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200239
240 subs.mutex.Lock()
241 defer subs.mutex.Unlock()
242 xapp.Logger.Info("CLEAN %s", subs.String())
243
244 if epamount == 0 {
245 //
246 // Subscription route delete
247 //
Juha Hyttinenb31b13f2020-03-18 10:25:30 +0200248 tmpList := xapptweaks.RmrEndpointList{}
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200249 tmpList.AddEndpoint(trans.GetEndpoint())
250 subRouteAction := SubRouteInfo{tmpList, uint16(seqId)}
251 r.rtmgrClient.SubscriptionRequestDelete(subRouteAction)
252
253 //
254 // Subscription release
255 //
256 r.mutex.Lock()
257 defer r.mutex.Unlock()
258
259 if _, ok := r.register[seqId]; ok {
260 xapp.Logger.Debug("RELEASE %s", subs.String())
261 delete(r.register, seqId)
262 xapp.Logger.Debug("Registry: substable=%v", r.register)
263 }
264 r.subIds = append(r.subIds, seqId)
265
266 } else if subs.EpList.Size() > 0 {
267 //
268 // Subscription route updates
269 //
270 subRouteAction := SubRouteInfo{subs.EpList, uint16(seqId)}
271 r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
272 }
273
274 }()
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200275
276 return nil
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200277}
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200278
Juha Hyttinen83ada002020-01-30 10:36:33 +0200279func (r *Registry) GetSubscription(sn uint32) *Subscription {
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200280 r.mutex.Lock()
281 defer r.mutex.Unlock()
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200282 if _, ok := r.register[sn]; ok {
283 return r.register[sn]
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200284 }
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200285 return nil
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000286}
287
Juha Hyttinen83ada002020-01-30 10:36:33 +0200288func (r *Registry) GetSubscriptionFirstMatch(ids []uint32) (*Subscription, error) {
Juha Hyttinen422d0182020-01-17 13:37:05 +0200289 r.mutex.Lock()
290 defer r.mutex.Unlock()
291 for _, id := range ids {
292 if _, ok := r.register[id]; ok {
293 return r.register[id], nil
294 }
295 }
296 return nil, fmt.Errorf("No valid subscription found with ids %v", ids)
297}