blob: 5fab1d5290d34bfb49df9f0b3032419fd78bb568 [file] [log] [blame]
Girish Gowdru0c588b22019-04-23 23:24:56 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Girish Gowdru0c588b22019-04-23 23:24:56 -040019
20import (
npujarec5762e2020-01-01 14:08:48 +053021 "context"
Girish Gowdru0c588b22019-04-23 23:24:56 -040022 "reflect"
23 "runtime"
24
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070025 "github.com/opencord/voltha-lib-go/v5/pkg/log"
Girish Gowdru0c588b22019-04-23 23:24:56 -040026)
27
28// DeviceState OLT Device state
29type DeviceState int
30
31const (
32 // deviceStateNull OLT is not instantiated
33 deviceStateNull DeviceState = iota
34 // deviceStateInit OLT is instantiated
35 deviceStateInit
36 // deviceStateConnected Grpc session established with OLT
37 deviceStateConnected
38 // deviceStateUp Admin state of OLT is UP
39 deviceStateUp
40 // deviceStateDown Admin state of OLT is down
41 deviceStateDown
42)
43
44// Trigger for changing the state
45type Trigger int
46
47const (
48 // DeviceInit Go to Device init state
49 DeviceInit Trigger = iota
50 // GrpcConnected Go to connected state
51 GrpcConnected
52 // DeviceUpInd Go to Device up state
53 DeviceUpInd
54 // DeviceDownInd Go to Device down state
55 DeviceDownInd
56 // GrpcDisconnected Go to Device init state
57 GrpcDisconnected
58)
59
60// TransitionHandler function type for handling transition
npujarec5762e2020-01-01 14:08:48 +053061type TransitionHandler func(ctx context.Context) error
Girish Gowdru0c588b22019-04-23 23:24:56 -040062
63// Transition to store state machine
64type Transition struct {
65 previousState []DeviceState
66 currentState DeviceState
67 before []TransitionHandler
68 after []TransitionHandler
69}
70
71// TransitionMap to store all the states and current device state
72type TransitionMap struct {
73 transitions map[Trigger]Transition
74 currentDeviceState DeviceState
75}
76
77// OpenoltDevice state machine:
78//
79// null ----> init ------> connected -----> up -----> down
80// ^ ^ | ^ | |
81// | | | | | |
82// | +-------------+ +---------+ |
83// | |
84// +-----------------------------------------+
85
86// NewTransitionMap create a new state machine with all the transitions
87func NewTransitionMap(dh *DeviceHandler) *TransitionMap {
88 var transitionMap TransitionMap
89 transitionMap.currentDeviceState = deviceStateNull
90 transitionMap.transitions = make(map[Trigger]Transition)
91 // In doInit establish the grpc session
92 transitionMap.transitions[DeviceInit] =
93 Transition{
Chaitrashree G Sa4649252020-03-11 21:24:11 -040094 previousState: []DeviceState{deviceStateNull, deviceStateUp, deviceStateDown},
Girish Gowdru0c588b22019-04-23 23:24:56 -040095 currentState: deviceStateInit,
96 before: []TransitionHandler{dh.doStateInit},
97 after: []TransitionHandler{dh.postInit}}
98 // If gRpc session fails, re-establish the grpc session
99 transitionMap.transitions[GrpcDisconnected] =
100 Transition{
101 previousState: []DeviceState{deviceStateConnected, deviceStateDown},
102 currentState: deviceStateInit,
103 before: []TransitionHandler{dh.doStateInit},
104 after: []TransitionHandler{dh.postInit}}
105 // in doConnected, create logical device and read the indications
106 transitionMap.transitions[GrpcConnected] =
107 Transition{
108 previousState: []DeviceState{deviceStateInit},
109 currentState: deviceStateConnected,
110 before: []TransitionHandler{dh.doStateConnected}}
111
112 // Once the olt UP is indication received, then do state up
113 transitionMap.transitions[DeviceUpInd] =
114 Transition{
115 previousState: []DeviceState{deviceStateConnected, deviceStateDown},
116 currentState: deviceStateUp,
117 before: []TransitionHandler{dh.doStateUp}}
118 // If olt DOWN indication comes then do sate down
119 transitionMap.transitions[DeviceDownInd] =
120 Transition{
Girish Gowdra852ad912021-05-04 00:05:50 -0700121 previousState: []DeviceState{deviceStateUp, deviceStateConnected},
Girish Gowdru0c588b22019-04-23 23:24:56 -0400122 currentState: deviceStateDown,
123 before: []TransitionHandler{dh.doStateDown}}
124
125 return &transitionMap
126}
127
128// funcName gets the handler function name
129func funcName(f interface{}) string {
130 p := reflect.ValueOf(f).Pointer()
131 rf := runtime.FuncForPC(p)
132 return rf.Name()
133}
134
135// isValidTransition checks for the new state transition is valid from current state
136func (tMap *TransitionMap) isValidTransition(trigger Trigger) bool {
137 // Validate the state transition
138 for _, state := range tMap.transitions[trigger].previousState {
139 if tMap.currentDeviceState == state {
140 return true
141 }
142 }
143 return false
144}
145
146// Handle moves the state machine to next state based on the trigger and invokes the before and
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700147// after handlers if the transition is a valid transition
npujarec5762e2020-01-01 14:08:48 +0530148func (tMap *TransitionMap) Handle(ctx context.Context, trigger Trigger) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400149
150 // Check whether the transtion is valid from current state
151 if !tMap.isValidTransition(trigger) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000152 logger.Errorw(ctx, "invalid-transition-triggered",
Shrey Baid26912972020-04-16 21:02:31 +0530153 log.Fields{
154 "current-state": tMap.currentDeviceState,
155 "trigger": trigger})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400156 return
157 }
158
159 // Invoke the before handlers
160 beforeHandlers := tMap.transitions[trigger].before
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700161 if beforeHandlers == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000162 logger.Debugw(ctx, "no-handlers-for-before", log.Fields{"trigger": trigger})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400163 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700164 for _, handler := range beforeHandlers {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000165 logger.Debugw(ctx, "running-before-handler", log.Fields{"handler": funcName(handler)})
npujarec5762e2020-01-01 14:08:48 +0530166 if err := handler(ctx); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700167 // TODO handle error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000168 logger.Error(ctx, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700169 return
170 }
171 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400172
173 // Update the state
174 tMap.currentDeviceState = tMap.transitions[trigger].currentState
Neha Sharma96b7bf22020-06-15 10:37:32 +0000175 logger.Debugw(ctx, "updated-device-state ", log.Fields{"current-device-state": tMap.currentDeviceState})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400176
177 // Invoke the after handlers
178 afterHandlers := tMap.transitions[trigger].after
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179 if afterHandlers == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000180 logger.Debugw(ctx, "no-handlers-for-after", log.Fields{"trigger": trigger})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400181 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700182 for _, handler := range afterHandlers {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000183 logger.Debugw(ctx, "running-after-handler", log.Fields{"handler": funcName(handler)})
npujarec5762e2020-01-01 14:08:48 +0530184 if err := handler(ctx); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185 // TODO handle error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000186 logger.Error(ctx, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700187 return
188 }
189 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400190}