blob: c9abdb8aa0fd535ce4ae5f25f9efa11fad56936c [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 {
128 if subs, ok := r.register[subReqMsg.RequestId.Seq]; ok {
129 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 Hyttinen12d31af2020-01-22 12:59:01 +0200220 r.mutex.Unlock()
221
222 //
223 // Wait some time before really do route updates
224 //
225 if waitRouteClean > 0 {
226 subs.mutex.Unlock()
227 time.Sleep(waitRouteClean)
228 subs.mutex.Lock()
229 }
230
Juha Hyttinen83ada002020-01-30 10:36:33 +0200231 xapp.Logger.Info("CLEAN %s", subs.String())
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200232
233 //
234 // Subscription route updates
235 //
Juha Hyttinen83ada002020-01-30 10:36:33 +0200236 if epamount == 0 {
237 tmpList := RmrEndpointList{}
238 tmpList.AddEndpoint(trans.GetEndpoint())
239 subRouteAction := SubRouteInfo{tmpList, uint16(seqId)}
240 r.rtmgrClient.SubscriptionRequestDelete(subRouteAction)
241 } else if subs.EpList.Size() > 0 {
242 subRouteAction := SubRouteInfo{subs.EpList, uint16(seqId)}
243 r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200244 }
245
246 r.mutex.Lock()
247 //
Juha Hyttinen83ada002020-01-30 10:36:33 +0200248 // If last endpoint, release and free seqid
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200249 //
250 if epamount == 0 {
Juha Hyttinen83ada002020-01-30 10:36:33 +0200251 if _, ok := r.register[seqId]; ok {
252 xapp.Logger.Debug("RELEASE %s", subs.String())
253 delete(r.register, seqId)
254 xapp.Logger.Debug("Registry: substable=%v", r.register)
255 }
256 r.subIds = append(r.subIds, seqId)
Juha Hyttinen12d31af2020-01-22 12:59:01 +0200257 }
258
259 return nil
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200260}
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200261
Juha Hyttinen83ada002020-01-30 10:36:33 +0200262func (r *Registry) GetSubscription(sn uint32) *Subscription {
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200263 r.mutex.Lock()
264 defer r.mutex.Unlock()
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200265 if _, ok := r.register[sn]; ok {
266 return r.register[sn]
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200267 }
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200268 return nil
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000269}
270
Juha Hyttinen83ada002020-01-30 10:36:33 +0200271func (r *Registry) GetSubscriptionFirstMatch(ids []uint32) (*Subscription, error) {
Juha Hyttinen422d0182020-01-17 13:37:05 +0200272 r.mutex.Lock()
273 defer r.mutex.Unlock()
274 for _, id := range ids {
275 if _, ok := r.register[id]; ok {
276 return r.register[id], nil
277 }
278 }
279 return nil, fmt.Errorf("No valid subscription found with ids %v", ids)
280}