blob: f24dccdded23b9970abe238b272e89a61ee602e9 [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"
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020025 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
26 "sync"
Juha Hyttinen12d31af2020-01-22 12:59:01 +020027 "time"
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020028)
29
Juha Hyttinen0d064ec2020-01-09 09:08:53 +020030//-----------------------------------------------------------------------------
31//
32//-----------------------------------------------------------------------------
Juha Hyttinen83ada002020-01-30 10:36:33 +020033
kalnagy45114752019-06-18 14:40:39 +020034type Registry struct {
Juha Hyttinen0388dd92020-01-09 14:14:16 +020035 mutex sync.Mutex
Juha Hyttinen83ada002020-01-30 10:36:33 +020036 register map[uint32]*Subscription
37 subIds []uint32
Juha Hyttinen0388dd92020-01-09 14:14:16 +020038 rtmgrClient *RtmgrClient
kalnagy45114752019-06-18 14:40:39 +020039}
40
Anssi Mannila5c161a92020-01-15 15:40:57 +020041func (r *Registry) Initialize() {
Juha Hyttinen83ada002020-01-30 10:36:33 +020042 r.register = make(map[uint32]*Subscription)
43 var i uint32
Anssi Mannila5c161a92020-01-15 15:40:57 +020044 for i = 0; i < 65535; i++ {
45 r.subIds = append(r.subIds, i+1)
46 }
kalnagy45114752019-06-18 14:40:39 +020047}
48
Juha Hyttinen83ada002020-01-30 10:36:33 +020049func (r *Registry) allocateSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
Juha Hyttinen12d31af2020-01-22 12:59:01 +020050 if len(r.subIds) > 0 {
Juha Hyttinen3944a222020-01-24 11:51:46 +020051 sequenceNumber := r.subIds[0]
Juha Hyttinen12d31af2020-01-22 12:59:01 +020052 r.subIds = r.subIds[1:]
53 if _, ok := r.register[sequenceNumber]; ok == true {
54 r.subIds = append(r.subIds, sequenceNumber)
Juha Hyttinen3944a222020-01-24 11:51:46 +020055 return nil, fmt.Errorf("Registry: Failed to reserve subscription exists")
Juha Hyttinen12d31af2020-01-22 12:59:01 +020056 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020057 subs := &Subscription{
58 registry: r,
Juha Hyttinen3944a222020-01-24 11:51:46 +020059 Meid: trans.Meid,
60 SubReqMsg: subReqMsg,
61 valid: true,
62 }
Juha Hyttinen83ada002020-01-30 10:36:33 +020063 subs.ReqId.Id = 123
64 subs.ReqId.Seq = sequenceNumber
Juha Hyttinen3944a222020-01-24 11:51:46 +020065
66 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
Juha Hyttinen83ada002020-01-30 10:36:33 +020067 r.subIds = append(r.subIds, subs.ReqId.Seq)
Juha Hyttinen3944a222020-01-24 11:51:46 +020068 return nil, fmt.Errorf("Registry: Endpoint existing already in subscription")
69 }
70
71 return subs, nil
Juha Hyttinen12d31af2020-01-22 12:59:01 +020072 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020073 return nil, fmt.Errorf("Registry: Failed to reserve subscription no free ids")
74}
75
Juha Hyttinen83ada002020-01-30 10:36:33 +020076func (r *Registry) findExistingSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) *Subscription {
77
Juha Hyttinen3944a222020-01-24 11:51:46 +020078 for _, subs := range r.register {
Juha Hyttinen83ada002020-01-30 10:36:33 +020079 if subs.IsMergeable(trans, subReqMsg) {
Juha Hyttinen3944a222020-01-24 11:51:46 +020080
81 //
82 // check if there has been race conditions
83 //
84 subs.mutex.Lock()
85 //subs has been set to invalid
86 if subs.valid == false {
87 subs.mutex.Unlock()
88 continue
89 }
Juha Hyttinen83ada002020-01-30 10:36:33 +020090 // If size is zero, entry is to be deleted
91 if subs.EpList.Size() == 0 {
92 subs.mutex.Unlock()
93 continue
94 }
Juha Hyttinen3944a222020-01-24 11:51:46 +020095 // try to add to endpointlist.
96 if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
97 subs.mutex.Unlock()
98 continue
99 }
100 subs.mutex.Unlock()
101
Juha Hyttinen83ada002020-01-30 10:36:33 +0200102 xapp.Logger.Debug("Registry: Mergeable subs found %s for %s", subs.String(), trans.String())
Juha Hyttinen3944a222020-01-24 11:51:46 +0200103 return subs
104 }
105 }
106 return nil
107}
108
Juha Hyttinen83ada002020-01-30 10:36:33 +0200109func (r *Registry) AssignToSubscription(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200110 var err error
111 var newAlloc bool
112 r.mutex.Lock()
113 defer r.mutex.Unlock()
114
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200115 //
116 // Check validity of subscription action types
117 //
118 actionType, err := r.CheckActionTypes(subReqMsg)
119 if err != nil {
120 xapp.Logger.Debug("CREATE %s", err)
121 return nil, err
122 }
Juha Hyttinen3944a222020-01-24 11:51:46 +0200123
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200124 //
125 // Find possible existing Policy subscription
126 //
127 if actionType == e2ap.E2AP_ActionTypePolicy {
Juha Hyttinen47942b42020-02-27 10:41:43 +0200128 if subs, ok := r.register[trans.GetSubId()]; ok {
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200129 xapp.Logger.Debug("CREATE %s. Existing subscription for Policy found", subs.String())
130 subs.SetCachedResponse(nil, true)
131 return subs, nil
132 }
133 }
134
135 subs := r.findExistingSubs(trans, subReqMsg)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200136 if subs == nil {
137 subs, err = r.allocateSubs(trans, subReqMsg)
138 if err != nil {
139 return nil, err
140 }
141 newAlloc = true
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200142 }
143
144 //
145 // Add to subscription
146 //
147 subs.mutex.Lock()
148 defer subs.mutex.Unlock()
149
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200150 epamount := subs.EpList.Size()
151
152 r.mutex.Unlock()
153 //
154 // Subscription route updates
155 //
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200156 if epamount == 1 {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200157 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.Seq)}
158 err = r.rtmgrClient.SubscriptionRequestCreate(subRouteAction)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200159 } else {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200160 subRouteAction := SubRouteInfo{subs.EpList, uint16(subs.ReqId.Seq)}
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200161 err = r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
162 }
163 r.mutex.Lock()
164
165 if err != nil {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200166 if newAlloc {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200167 r.subIds = append(r.subIds, subs.ReqId.Seq)
Juha Hyttinen3944a222020-01-24 11:51:46 +0200168 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200169 return nil, err
170 }
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200171
Juha Hyttinen3944a222020-01-24 11:51:46 +0200172 if newAlloc {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200173 r.register[subs.ReqId.Seq] = subs
Juha Hyttinen3944a222020-01-24 11:51:46 +0200174 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200175 xapp.Logger.Debug("CREATE %s", subs.String())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200176 xapp.Logger.Debug("Registry: substable=%v", r.register)
177 return subs, nil
178}
179
Anssi Mannila9bcb0a42020-02-11 11:30:44 +0200180func (r *Registry) CheckActionTypes(subReqMsg *e2ap.E2APSubscriptionRequest) (uint64, error) {
181 var reportFound bool = false
182 var policyFound bool = false
183
184 for _, acts := range subReqMsg.ActionSetups {
185 if acts.ActionType == e2ap.E2AP_ActionTypeReport {
186 reportFound = true
187 }
188 if acts.ActionType == e2ap.E2AP_ActionTypePolicy {
189 policyFound = true
190 }
191 }
192 if reportFound == true && policyFound == true {
193 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Report and Policy in same RICactions-ToBeSetup-List")
194 }
195 if reportFound == true {
196 return e2ap.E2AP_ActionTypeReport, nil
197 }
198 if policyFound == true {
199 return e2ap.E2AP_ActionTypePolicy, nil
200 }
201 return e2ap.E2AP_ActionTypeInvalid, fmt.Errorf("Invalid action type in RICactions-ToBeSetup-List")
202}
203
Juha Hyttinen83ada002020-01-30 10:36:33 +0200204// TODO: Works with concurrent calls, but check if can be improved
205func (r *Registry) RemoveFromSubscription(subs *Subscription, trans *TransactionXapp, waitRouteClean time.Duration) error {
Juha Hyttinen3944a222020-01-24 11:51:46 +0200206
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200207 r.mutex.Lock()
208 defer r.mutex.Unlock()
209 subs.mutex.Lock()
210 defer subs.mutex.Unlock()
211
212 delStatus := subs.EpList.DelEndpoint(trans.GetEndpoint())
213 epamount := subs.EpList.Size()
Juha Hyttinen83ada002020-01-30 10:36:33 +0200214 seqId := subs.ReqId.Seq
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200215
Juha Hyttinen83ada002020-01-30 10:36:33 +0200216 if delStatus == false {
217 return nil
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200218 }
Juha Hyttinen83ada002020-01-30 10:36:33 +0200219
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200220 go func() {
221 if waitRouteClean > 0 {
222 time.Sleep(waitRouteClean)
Juha Hyttinen83ada002020-01-30 10:36:33 +0200223 }
Juha Hyttinenf44377d2020-02-12 10:18:40 +0200224
225 subs.mutex.Lock()
226 defer subs.mutex.Unlock()
227 xapp.Logger.Info("CLEAN %s", subs.String())
228
229 if epamount == 0 {
230 //
231 // Subscription route delete
232 //
233 tmpList := RmrEndpointList{}
234 tmpList.AddEndpoint(trans.GetEndpoint())
235 subRouteAction := SubRouteInfo{tmpList, uint16(seqId)}
236 r.rtmgrClient.SubscriptionRequestDelete(subRouteAction)
237
238 //
239 // Subscription release
240 //
241 r.mutex.Lock()
242 defer r.mutex.Unlock()
243
244 if _, ok := r.register[seqId]; ok {
245 xapp.Logger.Debug("RELEASE %s", subs.String())
246 delete(r.register, seqId)
247 xapp.Logger.Debug("Registry: substable=%v", r.register)
248 }
249 r.subIds = append(r.subIds, seqId)
250
251 } else if subs.EpList.Size() > 0 {
252 //
253 // Subscription route updates
254 //
255 subRouteAction := SubRouteInfo{subs.EpList, uint16(seqId)}
256 r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
257 }
258
259 }()
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200260
261 return nil
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200262}
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200263
Juha Hyttinen83ada002020-01-30 10:36:33 +0200264func (r *Registry) GetSubscription(sn uint32) *Subscription {
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200265 r.mutex.Lock()
266 defer r.mutex.Unlock()
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200267 if _, ok := r.register[sn]; ok {
268 return r.register[sn]
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200269 }
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200270 return nil
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000271}
272
Juha Hyttinen83ada002020-01-30 10:36:33 +0200273func (r *Registry) GetSubscriptionFirstMatch(ids []uint32) (*Subscription, error) {
Juha Hyttinen422d0182020-01-17 13:37:05 +0200274 r.mutex.Lock()
275 defer r.mutex.Unlock()
276 for _, id := range ids {
277 if _, ok := r.register[id]; ok {
278 return r.register[id], nil
279 }
280 }
281 return nil, fmt.Errorf("No valid subscription found with ids %v", ids)
282}