Fix for E2 Connection status counters
[ric-plt/submgr.git] / pkg / control / e2if_state.go
1 /*
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
20 package control
21
22 import (
23         "fmt"
24         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
25         "strings"
26         "sync"
27 )
28
29 type XappRnibIf struct {
30         XappRnibInterface
31 }
32
33 func (x *XappRnibIf) XappRnibSubscribe(NotificationCb func(string, ...string), channel string) error {
34         return xapp.Rnib.Subscribe(NotificationCb, channel)
35 }
36
37 func (x *XappRnibIf) XappRnibGetListGnbIds() ([]*xapp.RNIBNbIdentity, xapp.RNIBIRNibError) {
38         return xapp.Rnib.GetListGnbIds()
39 }
40 func (x *XappRnibIf) XappRnibGetNodeb(inventoryName string) (*xapp.RNIBNodebInfo, xapp.RNIBIRNibError) {
41         nodeInfo, err := xapp.Rnib.GetNodeb(inventoryName)
42         return nodeInfo, err
43 }
44
45 func CreateXappRnibIfInstance() XappRnibInterface {
46         return new(XappRnibIf)
47 }
48
49 type E2IfState struct {
50         mutex   sync.Mutex
51         control *Control
52         NbIdMap map[string]string
53 }
54
55 func (e *E2IfState) Init(c *Control) {
56         e.control = c
57         e.NbIdMap = make(map[string]string, 0)
58         e.ReadE2ConfigurationFromRnib()
59         e.SubscribeChannels()
60 }
61
62 func (e *E2IfState) NotificationCb(ch string, events ...string) {
63
64         xapp.Logger.Debug("SDL notification received from channel=%s, event=%v", ch, events[0])
65         if len(events) == 0 {
66                 xapp.Logger.Error("Invalid SDL notification received: %d", len(events))
67                 return
68         }
69
70         if strings.Contains(events[0], "_CONNECTED") && !strings.Contains(events[0], "_CONNECTED_SETUP_FAILED") {
71                 e.control.UpdateCounter(cE2StateChangedToUp)
72                 nbId, err := ExtractNbiIdFromString(events[0])
73                 if err != nil {
74                         xapp.Logger.Error("NotificationCb CONNECTED len(nbId) == 0 ")
75                         return
76                 }
77                 xapp.Logger.Debug("E2 CONNECTED. NbId=%s", nbId)
78                 e.NbIdMap[nbId] = nbId
79         } else if strings.Contains(events[0], "_DISCONNECTED") {
80                 e.control.UpdateCounter(cE2StateChangedToDown)
81                 nbId, err := ExtractNbiIdFromString(events[0])
82                 if err != nil {
83                         xapp.Logger.Error("NotificationCb DISCONNECTED len(nbId) == 0 ")
84                         return
85                 }
86                 xapp.Logger.Debug("E2 DISCONNECTED. NbId=%s", nbId)
87                 if _, ok := e.NbIdMap[nbId]; ok {
88                         delete(e.NbIdMap, nbId)
89                         e.control.registry.DeleteAllE2Subscriptions(nbId, e.control)
90                 }
91         }
92 }
93
94 func (e *E2IfState) SubscribeChannels() error {
95
96         if err := e.control.e2IfStateDb.XappRnibSubscribe(e.NotificationCb, "RAN_CONNECTION_STATUS_CHANGE"); err != nil {
97                 xapp.Logger.Error("Sdl.SubscribeChannel failed: %v", err)
98                 return err
99         }
100         xapp.Logger.Debug("Subscription to RAN state changes done!")
101         return nil
102 }
103
104 func (e *E2IfState) ReadE2ConfigurationFromRnib() {
105
106         xapp.Logger.Debug("ReadE2ConfigurationFromRnib()")
107         nbIdentities, err := e.control.e2IfStateDb.XappRnibGetListGnbIds()
108         if err != nil || len(nbIdentities) == 0 {
109                 xapp.Logger.Debug("There are no active NodeBs available: %v", err)
110                 e.NbIdMap = make(map[string]string, 0)
111                 return
112         }
113
114         for _, nbIdentity := range nbIdentities {
115                 if e.isNodeBActive(nbIdentity.InventoryName) == false {
116                         if _, ok := e.NbIdMap[nbIdentity.InventoryName]; ok {
117                                 delete(e.NbIdMap, nbIdentity.InventoryName)
118                                 xapp.Logger.Debug("E2 connection DISCONNETED: %v", nbIdentity.InventoryName)
119
120                                 // Delete all subscriptions related to InventoryName/nbId
121                                 e.control.registry.DeleteAllE2Subscriptions(nbIdentity.InventoryName, e.control)
122                         }
123                         continue
124                 }
125
126                 if _, ok := e.NbIdMap[nbIdentity.InventoryName]; !ok {
127                         e.NbIdMap[nbIdentity.InventoryName] = nbIdentity.InventoryName
128                         xapp.Logger.Debug("E2 connection CONNECTED: %v", nbIdentity.InventoryName)
129                 }
130         }
131 }
132
133 func (e *E2IfState) isNodeBActive(inventoryName string) bool {
134         nodeInfo, err := e.control.e2IfStateDb.XappRnibGetNodeb(inventoryName)
135         if err != nil {
136                 xapp.Logger.Error("GetNodeb() failed for inventoryName=%s: %v", inventoryName, err)
137                 return false
138         }
139         xapp.Logger.Debug("NodeB['%s'] connection status = %d", inventoryName, nodeInfo.ConnectionStatus)
140         return nodeInfo.ConnectionStatus == 1
141 }
142
143 func (e *E2IfState) IsE2ConnectionUp(nbId *string) bool {
144
145         if checkE2State == "false" {
146                 return true
147         }
148
149         if _, ok := e.NbIdMap[*nbId]; ok {
150                 return true
151         } else {
152                 return false
153         }
154 }
155
156 func ExtractNbiIdFromString(s string) (string, error) {
157
158         // Expected string formats are below
159         // gnb_208_092_303030_CONNECTED
160         // gnb_208_092_303030_DISCONNECTED
161         // ...
162
163         var nbId string
164         var err error
165         if strings.Contains(s, "_CONNECTED") {
166                 splitStringTbl := strings.Split(s, "_CONNECTED")
167                 nbId = splitStringTbl[0]
168         } else if strings.Contains(s, "_DISCONNECTED") {
169                 splitStringTbl := strings.Split(s, "_DISCONNECTED")
170                 nbId = splitStringTbl[0]
171         }
172         if len(nbId) == 0 {
173                 return "", fmt.Errorf("ExtractNbiIdFromString(): len(nbId) == 0 ")
174         }
175         return nbId, err
176 }