blob: 396daded93335e834879b7442a2f6a0f0786e5d5 [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()
Juha Hyttinenaada6452020-04-07 08:47:58 +030058 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 +020059 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 Hyttinenaada6452020-04-07 08:47:58 +030066 subId := r.subIds[0]
Juha Hyttinen12d31af2020-01-22 12:59:01 +020067 r.subIds = r.subIds[1:]
Juha Hyttinenaada6452020-04-07 08:47:58 +030068 if _, ok := r.register[subId]; ok == true {
69 r.subIds = append(r.subIds, subId)
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
Juha Hyttinenaada6452020-04-07 08:47:58 +030079 subs.ReqId.InstanceId = subId
Juha Hyttinen3944a222020-01-24 11:51:46 +020080
81 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
Juha Hyttinenaada6452020-04-07 08:47:58 +030082 r.subIds = append(r.subIds, subs.ReqId.InstanceId)
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())
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
152 subs := 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
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200159 }
160
161 //
162 // Add to subscription
163 //
164 subs.mutex.Lock()
165 defer subs.mutex.Unlock()
166
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200167 epamount := subs.EpList.Size()
168
169 r.mutex.Unlock()
170 //
171 // Subscription route updates
172 //
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200173 if epamount == 1 {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300174 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.InstanceId)}
Juha Hyttinen83ada002020-01-30 10:36:33 +0200175 err = r.rtmgrClient.SubscriptionRequestCreate(subRouteAction)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200176 } else {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300177 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.InstanceId)}
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200178 err = r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
179 }
180 r.mutex.Lock()
181
182 if err != nil {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200183 if newAlloc {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300184 r.subIds = append(r.subIds, subs.ReqId.InstanceId)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200185 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200186 return nil, err
187 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200188
Juha Hyttinen3944a222020-01-24 11:51:46 +0200189 if newAlloc {
Juha Hyttinenaada6452020-04-07 08:47:58 +0300190 r.register[subs.ReqId.InstanceId] = subs
Juha Hyttinen3944a222020-01-24 11:51:46 +0200191 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200192 xapp.Logger.Debug("CREATE %s", subs.String())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200193 xapp.Logger.Debug("Registry: substable=%v", r.register)
194 return subs, nil
195}
196
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200197func (r *Registry) CheckActionTypes(subReqMsg *e2ap.E2APSubscriptionRequest) (uint64, error) {
198 var reportFound bool = false
199 var policyFound bool = false
200
201 for _, acts := range subReqMsg.ActionSetups {
202 if acts.ActionType == e2ap.E2AP_ActionTypeReport {
203 reportFound = true
204 }
205 if acts.ActionType == e2ap.E2AP_ActionTypePolicy {
206 policyFound = true
207 }
208 }
209 if reportFound == true && policyFound == true {
210 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Report and Policy in same RICactions-ToBeSetup-List")
211 }
212 if reportFound == true {
213 return e2ap.E2AP_ActionTypeReport, nil
214 }
215 if policyFound == true {
216 return e2ap.E2AP_ActionTypePolicy, nil
217 }
218 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Invalid action type in RICactions-ToBeSetup-List")
219}
220
Juha Hyttinen83ada002020-01-30 10:36:33 +0200221// TODO: Works with concurrent calls, but check if can be improved
222func (r *Registry) RemoveFromSubscription(subs *Subscription, trans *TransactionXapp, waitRouteClean time.Duration) error {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200223
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200224 r.mutex.Lock()
225 defer r.mutex.Unlock()
226 subs.mutex.Lock()
227 defer subs.mutex.Unlock()
228
229 delStatus := subs.EpList.DelEndpoint(trans.GetEndpoint())
230 epamount := subs.EpList.Size()
Juha Hyttinenaada6452020-04-07 08:47:58 +0300231 subId := subs.ReqId.InstanceId
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200232
Juha Hyttinen83ada002020-01-30 10:36:33 +0200233 if delStatus == false {
234 return nil
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200235 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200236
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200237 go func() {
238 if waitRouteClean > 0 {
239 time.Sleep(waitRouteClean)
Juha Hyttinen83ada002020-01-30 10:36:33 +0200240 }
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200241
242 subs.mutex.Lock()
243 defer subs.mutex.Unlock()
244 xapp.Logger.Info("CLEAN %s", subs.String())
245
246 if epamount == 0 {
247 //
248 // Subscription route delete
249 //
Juha Hyttinenb31b13f2020-03-18 10:25:30 +0200250 tmpList := xapptweaks.RmrEndpointList{}
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200251 tmpList.AddEndpoint(trans.GetEndpoint())
Juha Hyttinenaada6452020-04-07 08:47:58 +0300252 subRouteAction := SubRouteInfo{tmpList, uint16(subId)}
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200253 r.rtmgrClient.SubscriptionRequestDelete(subRouteAction)
254
255 //
256 // Subscription release
257 //
258 r.mutex.Lock()
259 defer r.mutex.Unlock()
260
Juha Hyttinenaada6452020-04-07 08:47:58 +0300261 if _, ok := r.register[subId]; ok {
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200262 xapp.Logger.Debug("RELEASE %s", subs.String())
Juha Hyttinenaada6452020-04-07 08:47:58 +0300263 delete(r.register, subId)
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200264 xapp.Logger.Debug("Registry: substable=%v", r.register)
265 }
Juha Hyttinenaada6452020-04-07 08:47:58 +0300266 r.subIds = append(r.subIds, subId)
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200267
268 } else if subs.EpList.Size() > 0 {
269 //
270 // Subscription route updates
271 //
Juha Hyttinenaada6452020-04-07 08:47:58 +0300272 subRouteAction := SubRouteInfo{subs.EpList, uint16(subId)}
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200273 r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
274 }
275
276 }()
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200277
278 return nil
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200279}
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200280
Juha Hyttinenaada6452020-04-07 08:47:58 +0300281func (r *Registry) GetSubscription(subId uint32) *Subscription {
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200282 r.mutex.Lock()
283 defer r.mutex.Unlock()
Juha Hyttinenaada6452020-04-07 08:47:58 +0300284 if _, ok := r.register[subId]; ok {
285 return r.register[subId]
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200286 }
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200287 return nil
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000288}
289
Juha Hyttinenaada6452020-04-07 08:47:58 +0300290func (r *Registry) GetSubscriptionFirstMatch(subIds []uint32) (*Subscription, error) {
Juha Hyttinen422d0182020-01-17 13:37:05 +0200291 r.mutex.Lock()
292 defer r.mutex.Unlock()
Juha Hyttinenaada6452020-04-07 08:47:58 +0300293 for _, subId := range subIds {
294 if _, ok := r.register[subId]; ok {
295 return r.register[subId], nil
Juha Hyttinen422d0182020-01-17 13:37:05 +0200296 }
297 }
Juha Hyttinenaada6452020-04-07 08:47:58 +0300298 return nil, fmt.Errorf("No valid subscription found with subIds %v", subIds)
Juha Hyttinen422d0182020-01-17 13:37:05 +0200299}