blob: b8acafc4dd1886e496f7f02017ff88e31f24cc25 [file] [log] [blame]
khenaidoob9203542018-09-17 22:56:37 -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 */
npujar1d86a522019-11-14 17:11:16 +053016
khenaidoob9203542018-09-17 22:56:37 -040017package core
18
19import (
npujar467fe752020-01-16 20:17:45 +053020 "context"
npujar1d86a522019-11-14 17:11:16 +053021 "github.com/opencord/voltha-go/rw_core/coreif"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080022 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoob9203542018-09-17 22:56:37 -040023)
24
npujar1d86a522019-11-14 17:11:16 +053025// DeviceType mentions type of device like parent, child
khenaidoob9203542018-09-17 22:56:37 -040026type DeviceType int32
27
28const (
29 parent DeviceType = 0
30 child DeviceType = 1
31 any DeviceType = 2
32)
33
khenaidoo442e7c72020-03-10 16:13:48 -040034type MatchResult uint8
35
36const (
37 noMatch MatchResult = iota // current state has not match in the transition table
38 currWildcardMatch // current state matches the wildcard *_UNKNOWN state in the transition table
39 currStateOnlyMatch // current state matches the current state and previous state matches the wildcard in the transition table
40 currPrevStateMatch // both current and previous states match in the transition table
41)
42
43// match is used to keep the current match states
44type match struct {
45 admin, oper, conn MatchResult
46}
47
48// toInt returns an integer representing the matching level of the match (the larger the number the better)
49func (m *match) toInt() int {
50 return int(m.admin<<4 | m.oper<<2 | m.conn)
51}
52
53// isExactMatch returns true if match is an exact match
54func (m *match) isExactMatch() bool {
55 return m.admin == currPrevStateMatch && m.oper == currPrevStateMatch && m.conn == currPrevStateMatch
56}
57
58// isBetterMatch returns true if newMatch is a worse match
59func (m *match) isBetterMatch(newMatch *match) bool {
60 return m.toInt() > newMatch.toInt()
61}
62
npujar1d86a522019-11-14 17:11:16 +053063// DeviceState has admin, operational and connection status of device
khenaidoob9203542018-09-17 22:56:37 -040064type DeviceState struct {
serkant.uluderya2ae470f2020-01-21 11:13:09 -080065 Admin voltha.AdminState_Types
66 Connection voltha.ConnectStatus_Types
67 Operational voltha.OperStatus_Types
khenaidoob9203542018-09-17 22:56:37 -040068}
69
khenaidoo442e7c72020-03-10 16:13:48 -040070// TransitionHandler function type which takes the current and previous device info as input parameter
71type TransitionHandler func(ctx context.Context, curr *voltha.Device, prev *voltha.Device) error
khenaidoob9203542018-09-17 22:56:37 -040072
npujar1d86a522019-11-14 17:11:16 +053073// Transition represent transition related attributes
khenaidoob9203542018-09-17 22:56:37 -040074type Transition struct {
75 deviceType DeviceType
76 previousState DeviceState
77 currentState DeviceState
khenaidoo92e62c52018-10-03 14:02:54 -040078 handlers []TransitionHandler
khenaidoob9203542018-09-17 22:56:37 -040079}
80
npujar1d86a522019-11-14 17:11:16 +053081// TransitionMap represent map of transitions and device manager
khenaidoob9203542018-09-17 22:56:37 -040082type TransitionMap struct {
83 transitions []Transition
npujar1d86a522019-11-14 17:11:16 +053084 dMgr coreif.DeviceManager
khenaidoob9203542018-09-17 22:56:37 -040085}
86
npujar1d86a522019-11-14 17:11:16 +053087// NewTransitionMap creates transition map
88func NewTransitionMap(dMgr coreif.DeviceManager) *TransitionMap {
khenaidoob9203542018-09-17 22:56:37 -040089 var transitionMap TransitionMap
khenaidoo0a822f92019-05-08 15:15:57 -040090 transitionMap.dMgr = dMgr
khenaidoob9203542018-09-17 22:56:37 -040091 transitionMap.transitions = make([]Transition, 0)
khenaidoo442e7c72020-03-10 16:13:48 -040092 transitionMap.transitions = append(
93 transitionMap.transitions,
khenaidoob9203542018-09-17 22:56:37 -040094 Transition{
khenaidoob9203542018-09-17 22:56:37 -040095 deviceType: parent,
khenaidoo59ef7be2019-06-21 12:40:28 -040096 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
97 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoo0a822f92019-05-08 15:15:57 -040098 handlers: []TransitionHandler{dMgr.CreateLogicalDevice}})
99 transitionMap.transitions = append(transitionMap.transitions,
100 Transition{
khenaidoo59ef7be2019-06-21 12:40:28 -0400101 deviceType: child,
102 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED},
khenaidoo442e7c72020-03-10 16:13:48 -0400103 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
104 handlers: []TransitionHandler{}})
105 transitionMap.transitions = append(transitionMap.transitions,
106 Transition{
107 deviceType: child,
108 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED},
khenaidoo59ef7be2019-06-21 12:40:28 -0400109 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
110 handlers: []TransitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -0400111 transitionMap.transitions = append(transitionMap.transitions,
112 Transition{
113 deviceType: child,
khenaidoo59ef7be2019-06-21 12:40:28 -0400114 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
khenaidoo442e7c72020-03-10 16:13:48 -0400115 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_DISCOVERED},
116 handlers: []TransitionHandler{}})
117 transitionMap.transitions = append(transitionMap.transitions,
118 Transition{
119 deviceType: child,
120 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
khenaidoo59ef7be2019-06-21 12:40:28 -0400121 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
khenaidoo0a822f92019-05-08 15:15:57 -0400122 handlers: []TransitionHandler{dMgr.SetupUNILogicalPorts}})
khenaidoob9203542018-09-17 22:56:37 -0400123 transitionMap.transitions = append(transitionMap.transitions,
124 Transition{
khenaidoo4554f7c2019-05-29 22:13:15 -0400125 deviceType: any,
126 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
127 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
128 handlers: []TransitionHandler{dMgr.RunPostDeviceDelete}})
129 transitionMap.transitions = append(transitionMap.transitions,
130 Transition{
khenaidoo4d4802d2018-10-04 21:59:49 -0400131 deviceType: parent,
khenaidoo442e7c72020-03-10 16:13:48 -0400132 previousState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo4d4802d2018-10-04 21:59:49 -0400133 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Andrea Campanella09400bd2020-04-02 11:58:04 +0200134 handlers: []TransitionHandler{dMgr.DisableAllChildDevices, dMgr.DeleteAllUNILogicalPorts, dMgr.DeleteAllChildDevices, dMgr.DeleteAllLogicalPorts, dMgr.DeleteLogicalDevice, dMgr.RunPostDeviceDelete}})
khenaidoo0a822f92019-05-08 15:15:57 -0400135 transitionMap.transitions = append(transitionMap.transitions,
136 Transition{
Girish Gowdra408cd962020-03-11 14:31:31 -0700137 deviceType: parent,
138 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
139 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN},
140 handlers: []TransitionHandler{dMgr.DeleteAllLogicalPorts, dMgr.DeleteLogicalDevice, dMgr.DeleteAllChildDevices, dMgr.DeleteAllDeviceFlows}})
141 transitionMap.transitions = append(transitionMap.transitions,
142 Transition{
143 deviceType: parent,
144 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNREACHABLE, Operational: voltha.OperStatus_UNKNOWN},
145 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_REACHABLE, Operational: voltha.OperStatus_ACTIVE},
146 handlers: []TransitionHandler{dMgr.CreateLogicalDevice}})
147 transitionMap.transitions = append(transitionMap.transitions,
148 Transition{
khenaidoo0a822f92019-05-08 15:15:57 -0400149 deviceType: child,
khenaidoo442e7c72020-03-10 16:13:48 -0400150 previousState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400151 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
Chaitrashree G S543df3e2020-02-24 22:36:54 -0500152 handlers: []TransitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
153 transitionMap.transitions = append(transitionMap.transitions,
154 Transition{
155 deviceType: child,
156 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
157 currentState: DeviceState{Admin: voltha.AdminState_DELETED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
158 handlers: []TransitionHandler{dMgr.ChildDeviceLost, dMgr.DeleteLogicalPorts, dMgr.RunPostDeviceDelete}})
khenaidoob9203542018-09-17 22:56:37 -0400159 transitionMap.transitions = append(transitionMap.transitions,
160 Transition{
161 deviceType: any,
khenaidoo59ef7be2019-06-21 12:40:28 -0400162 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
163 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
164 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
165 transitionMap.transitions = append(transitionMap.transitions,
166 Transition{
167 deviceType: any,
168 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
169 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
170 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
171 transitionMap.transitions = append(transitionMap.transitions,
172 Transition{
173 deviceType: any,
174 previousState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
175 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
176 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
177 transitionMap.transitions = append(transitionMap.transitions,
178 Transition{
179 deviceType: any,
180 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
181 currentState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
182 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
183 transitionMap.transitions = append(transitionMap.transitions,
184 Transition{
185 deviceType: any,
186 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
187 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
188 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
189 transitionMap.transitions = append(transitionMap.transitions,
190 Transition{
191 deviceType: parent,
192 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVE},
193 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
194 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
195 transitionMap.transitions = append(transitionMap.transitions,
196 Transition{
197 deviceType: any,
198 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_ACTIVATING},
199 currentState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
200 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
201 transitionMap.transitions = append(transitionMap.transitions,
202 Transition{
203 deviceType: any,
204 previousState: DeviceState{Admin: voltha.AdminState_ENABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
205 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
206 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
207 transitionMap.transitions = append(transitionMap.transitions,
208 Transition{
209 deviceType: child,
210 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
211 currentState: DeviceState{Admin: voltha.AdminState_UNKNOWN, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
212 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
213 transitionMap.transitions = append(transitionMap.transitions,
214 Transition{
215 deviceType: any,
216 previousState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
217 currentState: DeviceState{Admin: voltha.AdminState_PREPROVISIONED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
218 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
219 transitionMap.transitions = append(transitionMap.transitions,
220 Transition{
221 deviceType: any,
khenaidoob9203542018-09-17 22:56:37 -0400222 previousState: DeviceState{Admin: voltha.AdminState_DOWNLOADING_IMAGE, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
223 currentState: DeviceState{Admin: voltha.AdminState_DISABLED, Connection: voltha.ConnectStatus_UNKNOWN, Operational: voltha.OperStatus_UNKNOWN},
khenaidoo0a822f92019-05-08 15:15:57 -0400224 handlers: []TransitionHandler{dMgr.NotifyInvalidTransition}})
khenaidoob9203542018-09-17 22:56:37 -0400225
226 return &transitionMap
227}
228
229func getDeviceStates(device *voltha.Device) *DeviceState {
230 return &DeviceState{Admin: device.AdminState, Connection: device.ConnectStatus, Operational: device.OperStatus}
231}
232
233// isMatched matches a state transition. It returns whether there is a match and if there is whether it is an exact match
khenaidoo442e7c72020-03-10 16:13:48 -0400234func getHandler(previous *DeviceState, current *DeviceState, transition *Transition) ([]TransitionHandler, *match) {
235 m := &match{}
khenaidoob9203542018-09-17 22:56:37 -0400236 // Do we have an exact match?
237 if *previous == transition.previousState && *current == transition.currentState {
khenaidoo442e7c72020-03-10 16:13:48 -0400238 return transition.handlers, &match{admin: currPrevStateMatch, oper: currPrevStateMatch, conn: currPrevStateMatch}
khenaidoob9203542018-09-17 22:56:37 -0400239 }
khenaidoo0a822f92019-05-08 15:15:57 -0400240
khenaidoo442e7c72020-03-10 16:13:48 -0400241 // Do we have Admin state match?
242 if current.Admin == transition.currentState.Admin && transition.currentState.Admin != voltha.AdminState_UNKNOWN {
243 if previous.Admin == transition.previousState.Admin {
244 m.admin = currPrevStateMatch
245 } else if transition.previousState.Admin == voltha.AdminState_UNKNOWN {
246 m.admin = currStateOnlyMatch
247 }
248 } else if current.Admin == transition.currentState.Admin && transition.currentState.Admin == voltha.AdminState_UNKNOWN {
249 if previous.Admin == transition.previousState.Admin || transition.previousState.Admin == voltha.AdminState_UNKNOWN {
250 m.admin = currWildcardMatch
251 }
252 }
253 if m.admin == noMatch {
254 // invalid transition - need to match on current admin state
255 return nil, m
khenaidoo0a822f92019-05-08 15:15:57 -0400256 }
257
khenaidoo442e7c72020-03-10 16:13:48 -0400258 // Do we have an operational state match?
259 if current.Operational == transition.currentState.Operational && transition.previousState.Operational != voltha.OperStatus_UNKNOWN {
260 if previous.Operational == transition.previousState.Operational || transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
261 m.oper = currPrevStateMatch
262 } else {
263 m.oper = currStateOnlyMatch
264 }
265 } else if current.Operational == transition.currentState.Operational && transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
266 if previous.Operational == transition.previousState.Operational || transition.previousState.Operational == voltha.OperStatus_UNKNOWN {
267 m.oper = currWildcardMatch
khenaidoob9203542018-09-17 22:56:37 -0400268 }
269 }
khenaidoo442e7c72020-03-10 16:13:48 -0400270
271 // Do we have an connection state match?
272 if current.Connection == transition.currentState.Connection && transition.previousState.Connection != voltha.ConnectStatus_UNKNOWN {
273 if previous.Connection == transition.previousState.Connection || transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
274 m.conn = currPrevStateMatch
275 } else {
276 m.conn = currStateOnlyMatch
277 }
278 } else if current.Connection == transition.currentState.Connection && transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
279 if previous.Connection == transition.previousState.Connection || transition.previousState.Connection == voltha.ConnectStatus_UNKNOWN {
280 m.conn = currWildcardMatch
khenaidoob9203542018-09-17 22:56:37 -0400281 }
282 }
khenaidoo442e7c72020-03-10 16:13:48 -0400283
284 return transition.handlers, m
khenaidoob9203542018-09-17 22:56:37 -0400285}
286
npujar1d86a522019-11-14 17:11:16 +0530287// GetTransitionHandler returns transition handler
khenaidoo92e62c52018-10-03 14:02:54 -0400288func (tMap *TransitionMap) GetTransitionHandler(pDevice *voltha.Device, cDevice *voltha.Device) []TransitionHandler {
khenaidoob9203542018-09-17 22:56:37 -0400289 //1. Get the previous and current set of states
290 pState := getDeviceStates(pDevice)
291 cState := getDeviceStates(cDevice)
khenaidoo442e7c72020-03-10 16:13:48 -0400292
293 // Do nothing is there are no states change
294 if *pState == *cState {
295 return nil
296 }
297
Girish Kumarf56a4682020-03-20 20:07:46 +0000298 //logger.Infow("DeviceType", log.Fields{"device": pDevice})
khenaidoob9203542018-09-17 22:56:37 -0400299 deviceType := parent
300 if !pDevice.Root {
Girish Kumarf56a4682020-03-20 20:07:46 +0000301 logger.Info("device is child")
khenaidoob9203542018-09-17 22:56:37 -0400302 deviceType = child
303 }
Girish Kumarf56a4682020-03-20 20:07:46 +0000304 logger.Infof("deviceType:%d-deviceId:%s-previous:%v-current:%v", deviceType, pDevice.Id, pState, cState)
khenaidoob9203542018-09-17 22:56:37 -0400305
306 //2. Go over transition array to get the right transition
khenaidoo92e62c52018-10-03 14:02:54 -0400307 var currentMatch []TransitionHandler
308 var tempHandler []TransitionHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400309 var m *match
310 bestMatch := &match{}
khenaidoob9203542018-09-17 22:56:37 -0400311 for _, aTransition := range tMap.transitions {
312 // consider transition only if it matches deviceType or is a wild card - any
313 if aTransition.deviceType != deviceType && aTransition.deviceType != any {
314 continue
315 }
khenaidoo442e7c72020-03-10 16:13:48 -0400316 tempHandler, m = getHandler(pState, cState, &aTransition)
khenaidoob9203542018-09-17 22:56:37 -0400317 if tempHandler != nil {
khenaidoo442e7c72020-03-10 16:13:48 -0400318 if m.isExactMatch() && aTransition.deviceType == deviceType {
khenaidoob9203542018-09-17 22:56:37 -0400319 return tempHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400320 } else if m.isExactMatch() || m.isBetterMatch(bestMatch) {
khenaidoo0a822f92019-05-08 15:15:57 -0400321 currentMatch = tempHandler
khenaidoo442e7c72020-03-10 16:13:48 -0400322 bestMatch = m
khenaidoob9203542018-09-17 22:56:37 -0400323 }
324 }
325 }
326 return currentMatch
327}