blob: b0851774ec70fe29d1f53e6f19850491f3c1002d [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
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
17//Package adaptercore provides the utility for olt devices, flows and statistics
Phaneendra Manda4c62c802019-03-06 21:37:49 +053018package adaptercore
19
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
22 "errors"
23 "fmt"
Mahir Gunyele77977b2019-06-27 05:36:22 -070024 "google.golang.org/grpc/codes"
cuilin20187b2a8c32019-03-26 19:52:28 -070025 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
cuilin20187b2a8c32019-03-26 19:52:28 -070032 "github.com/gogo/protobuf/proto"
33 "github.com/golang/protobuf/ptypes"
manikkaraj k9eb6cac2019-05-09 12:32:03 -040034 "github.com/mdlayher/ethernet"
cuilin20187b2a8c32019-03-26 19:52:28 -070035 com "github.com/opencord/voltha-go/adapters/common"
36 "github.com/opencord/voltha-go/common/log"
Girish Gowdru0c588b22019-04-23 23:24:56 -040037 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj kbf256be2019-03-25 00:13:48 +053038 "github.com/opencord/voltha-protos/go/common"
39 ic "github.com/opencord/voltha-protos/go/inter_container"
40 of "github.com/opencord/voltha-protos/go/openflow_13"
41 oop "github.com/opencord/voltha-protos/go/openolt"
manikkaraj kbf256be2019-03-25 00:13:48 +053042 "github.com/opencord/voltha-protos/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070043 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040044 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053045)
46
47//DeviceHandler will interact with the OLT device.
48type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070050 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040051 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070052 device *voltha.Device
53 coreProxy *com.CoreProxy
manikkaraj kbf256be2019-03-25 00:13:48 +053054 AdapterProxy *com.AdapterProxy
Devmalya Paulfb990a52019-07-09 10:01:49 -040055 EventProxy *com.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070056 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070057 exitChannel chan int
58 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053059 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070060 transitionMap *TransitionMap
61 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053062 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040063 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053064 resourceMgr *rsrcMgr.OpenOltResourceMgr
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040065 discOnus map[string]bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070066 onus map[string]*OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067 nniIntfID int
Mahir Gunyela3f9add2019-06-06 15:13:19 -070068}
69
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070070//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070071type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070073 deviceType string
74 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075 onuID uint32
76 intfID uint32
77 proxyDeviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070078}
79
80//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070081func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -070082 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070084 device.deviceType = deviceTp
85 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 device.onuID = onuID
87 device.intfID = intfID
88 device.proxyDeviceID = proxyDevID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070089 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +053090}
91
92//NewDeviceHandler creates a new device handler
Devmalya Paulfb990a52019-07-09 10:01:49 -040093func NewDeviceHandler(cp *com.CoreProxy, ap *com.AdapterProxy, ep *com.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -070094 var dh DeviceHandler
95 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -040096 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -040097 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -070098 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070099 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700100 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400101 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700102 dh.device = cloned
103 dh.openOLT = adapter
104 dh.exitChannel = make(chan int, 1)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400105 dh.discOnus = make(map[string]bool)
cuilin20187b2a8c32019-03-26 19:52:28 -0700106 dh.lockDevice = sync.RWMutex{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107 dh.onus = make(map[string]*OnuDevice)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 // The nniIntfID is initialized to -1 (invalid) and set to right value
Girish Gowdru1110ef22019-06-24 11:17:59 -0400109 // when the first IntfOperInd with status as "up" is received for
110 // any one of the available NNI port on the OLT device.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 dh.nniIntfID = -1
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530112
cuilin20187b2a8c32019-03-26 19:52:28 -0700113 //TODO initialize the support classes.
114 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530115}
116
117// start save the device to the data model
118func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700119 dh.lockDevice.Lock()
120 defer dh.lockDevice.Unlock()
121 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
122 // Add the initial device to the local model
123 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530124}
125
126// stop stops the device dh. Not much to do for now
127func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700128 dh.lockDevice.Lock()
129 defer dh.lockDevice.Unlock()
130 log.Debug("stopping-device-agent")
131 dh.exitChannel <- 1
132 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530133}
134
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400135func macifyIP(ip net.IP) string {
136 if len(ip) > 0 {
137 oct1 := strconv.FormatInt(int64(ip[12]), 16)
138 oct2 := strconv.FormatInt(int64(ip[13]), 16)
139 oct3 := strconv.FormatInt(int64(ip[14]), 16)
140 oct4 := strconv.FormatInt(int64(ip[15]), 16)
141 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
142 }
143 return ""
144}
145
146func generateMacFromHost(host string) (string, error) {
147 var genmac string
148 var addr net.IP
149 var ips []string
150 var err error
151
152 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
153
154 if addr = net.ParseIP(host); addr == nil {
155 log.Debugw("looking-up-hostname", log.Fields{"host": host})
156
157 if ips, err = net.LookupHost(host); err == nil {
158 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
159 if addr = net.ParseIP(ips[0]); addr == nil {
160 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
161 return "", errors.New("unable-to-parse-ip")
162 }
163 genmac = macifyIP(addr)
164 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
165 return genmac, nil
166 }
167 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
168 return "", err
169 }
170
171 genmac = macifyIP(addr)
172 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
173 return genmac, nil
174}
175
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530176func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700177 slist := strings.Split(mac, ":")
178 result := make([]uint32, len(slist))
179 var err error
180 var tmp int64
181 for index, val := range slist {
182 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
183 return []uint32{1, 2, 3, 4, 5, 6}
184 }
185 result[index] = uint32(tmp)
186 }
187 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530188}
189
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700190//GetportLabel returns the label for the NNI and the PON port based on port number and port type
manikkaraj kbf256be2019-03-25 00:13:48 +0530191func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530192
Girish Gowdru0c588b22019-04-23 23:24:56 -0400193 if portType == voltha.Port_ETHERNET_NNI {
194 return fmt.Sprintf("nni-%d", portNum)
195 } else if portType == voltha.Port_PON_OLT {
196 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700197 } else if portType == voltha.Port_ETHERNET_UNI {
198 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400199 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700200 }
201 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530202}
203
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700204func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700205 var operStatus common.OperStatus_OperStatus
206 if state == "up" {
207 operStatus = voltha.OperStatus_ACTIVE
208 } else {
209 operStatus = voltha.OperStatus_DISCOVERED
210 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700211 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400212 label := GetportLabel(portNum, portType)
213 if len(label) == 0 {
214 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
215 return
216 }
217 // Now create Port
218 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700219 PortNo: portNum,
220 Label: label,
221 Type: portType,
222 OperStatus: operStatus,
223 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400224 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700225 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700226 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
227 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400228 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700229
Girish Gowdru1110ef22019-06-24 11:17:59 -0400230 // Once we have successfully added the NNI port to the core, if the
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700231 // locally cached nniIntfID is set to invalid (-1), set it to the right value.
232 if portType == voltha.Port_ETHERNET_NNI && dh.nniIntfID == -1 {
233 dh.nniIntfID = int(intfID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700234 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530235}
236
237// readIndications to read the indications from the OLT device
238func (dh *DeviceHandler) readIndications() {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400239 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700240 if err != nil {
241 log.Errorw("Failed to read indications", log.Fields{"err": err})
242 return
243 }
244 if indications == nil {
245 log.Errorw("Indications is nil", log.Fields{})
246 return
247 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400248 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700249 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400250 if err != nil || device == nil {
251 /*TODO: needs to handle error scenarios */
252 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700253 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400254 }
255 // When the device is in DISABLED and Adapter container restarts, we need to
256 // rebuild the locally maintained admin state.
257 if device.AdminState == voltha.AdminState_DISABLED {
258 dh.lockDevice.Lock()
259 dh.adminState = "down"
260 dh.lockDevice.Unlock()
261 }
262
cuilin20187b2a8c32019-03-26 19:52:28 -0700263 for {
264 indication, err := indications.Recv()
265 if err == io.EOF {
266 break
267 }
268 if err != nil {
269 log.Infow("Failed to read from indications", log.Fields{"err": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400270 dh.transitionMap.Handle(DeviceDownInd)
271 dh.transitionMap.Handle(DeviceInit)
272 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700273 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400274 // When OLT is admin down, allow only NNI operation status change indications.
275 if dh.adminState == "down" {
276 _, isIntfOperInd := indication.Data.(*oop.Indication_IntfOperInd)
277 if isIntfOperInd {
278 intfOperInd := indication.GetIntfOperInd()
279 if intfOperInd.GetType() == "nni" {
280 log.Infow("olt is admin down, allow nni ind", log.Fields{})
281 }
282 } else {
283 log.Infow("olt is admin down, ignore indication", log.Fields{})
284 continue
285 }
286 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530287
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700288 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530289
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700290 }
291}
292
293func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
294 if oltIndication.OperState == "up" {
295 dh.transitionMap.Handle(DeviceUpInd)
296 } else if oltIndication.OperState == "down" {
297 dh.transitionMap.Handle(DeviceDownInd)
298 }
299}
300
301func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400302 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700303 switch indication.Data.(type) {
304 case *oop.Indication_OltInd:
305 dh.handleOltIndication(indication.GetOltInd())
306 case *oop.Indication_IntfInd:
307 intfInd := indication.GetIntfInd()
308 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
309 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
310 case *oop.Indication_IntfOperInd:
311 intfOperInd := indication.GetIntfOperInd()
312 if intfOperInd.GetType() == "nni" {
313 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
314 } else if intfOperInd.GetType() == "pon" {
315 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
316 // Handle pon port update
cuilin20187b2a8c32019-03-26 19:52:28 -0700317 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700318 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
319 case *oop.Indication_OnuDiscInd:
320 onuDiscInd := indication.GetOnuDiscInd()
321 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700322 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400323 dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700324 case *oop.Indication_OnuInd:
325 onuInd := indication.GetOnuInd()
326 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
327 go dh.onuIndication(onuInd)
328 case *oop.Indication_OmciInd:
329 omciInd := indication.GetOmciInd()
330 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
331 if err := dh.omciIndication(omciInd); err != nil {
332 log.Errorw("send-omci-indication-errr", log.Fields{"error": err, "omciInd": omciInd})
333 }
334 case *oop.Indication_PktInd:
335 pktInd := indication.GetPktInd()
336 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
337 go dh.handlePacketIndication(pktInd)
338 case *oop.Indication_PortStats:
339 portStats := indication.GetPortStats()
340 log.Infow("Received port stats indication", log.Fields{"PortStats": portStats})
341 case *oop.Indication_FlowStats:
342 flowStats := indication.GetFlowStats()
343 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
344 case *oop.Indication_AlarmInd:
345 alarmInd := indication.GetAlarmInd()
346 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Devmalya Paulfb990a52019-07-09 10:01:49 -0400347 dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
348
cuilin20187b2a8c32019-03-26 19:52:28 -0700349 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530350}
351
352// doStateUp handle the olt up indication and update to voltha core
353func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400354 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700355 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400356 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700357 log.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400358 return err
359 }
360 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530361}
362
363// doStateDown handle the olt down indication
364func (dh *DeviceHandler) doStateDown() error {
Girish Gowdrud4245152019-05-10 00:47:31 -0400365 log.Debug("do-state-down-start")
366
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700367 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400368 if err != nil || device == nil {
369 /*TODO: needs to handle error scenarios */
370 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700371 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400372 }
373
374 cloned := proto.Clone(device).(*voltha.Device)
375 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700376 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
377 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
378 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400379 }
380
381 //Update the device oper state and connection status
382 cloned.OperStatus = voltha.OperStatus_UNKNOWN
383 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
384 dh.device = cloned
385
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700386 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
387 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
388 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400389 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400390
391 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700392 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400393 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700394 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400395 return err
396 }
397 for _, onuDevice := range onuDevices.Items {
398
399 // Update onu state as down in onu adapter
400 onuInd := oop.OnuIndication{}
401 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700402 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
403 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
404 if er != nil {
405 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
406 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
407 return er
408 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400409 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700410 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700411 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530412}
413
414// doStateInit dial the grpc before going to init state
415func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400416 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400417 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400418 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700419 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400420 return err
421 }
422 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530423}
424
425// postInit create olt client instance to invoke RPC on the olt device
426func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400427 dh.Client = oop.NewOpenoltClient(dh.clientCon)
428 dh.transitionMap.Handle(GrpcConnected)
429 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530430}
431
432// doStateConnected get the device info and update to voltha core
433func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400434 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400435
436 // Case where OLT is disabled and then rebooted.
437 if dh.adminState == "down" {
438 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700439 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400440 if err != nil || device == nil {
441 /*TODO: needs to handle error scenarios */
442 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
443 }
444
445 cloned := proto.Clone(device).(*voltha.Device)
446 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
447 cloned.OperStatus = voltha.OperStatus_UNKNOWN
448 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700449 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
450 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400451 }
452
453 // Since the device was disabled before the OLT was rebooted, enfore the OLT to be Disabled after re-connection.
454 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
455 if err != nil {
456 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
457 }
458
459 // Start reading indications
460 go dh.readIndications()
461 return nil
462 }
463
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400464 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700465 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400466 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700467 return err
468 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400469
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700470 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400471 if err != nil || device == nil {
472 /*TODO: needs to handle error scenarios */
473 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700474 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400475 }
476 cloned := proto.Clone(device).(*voltha.Device)
477 // Update the all ports (if available) on that device to ACTIVE.
478 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700479 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
480 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400481 return err
482 }
483
Girish Gowdru0c588b22019-04-23 23:24:56 -0400484 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
485 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700486 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400487 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700488 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400489 }
490 // Instantiate flow manager
491 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
492 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700493 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400494 }
495 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400496 /* Instantiating Event Manager to handle Alarms and KPIs */
497 dh.eventMgr = NewEventMgr(dh.EventProxy)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530498
cuilin20187b2a8c32019-03-26 19:52:28 -0700499 // Start reading indications
500 go dh.readIndications()
501 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530502}
503
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400504func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
505 var err error
506 var deviceInfo *oop.DeviceInfo
507
508 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
509
510 if err != nil {
511 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
512 return nil, err
513 }
514 if deviceInfo == nil {
515 log.Errorw("Device info is nil", log.Fields{})
516 return nil, errors.New("failed to get device info from OLT")
517 }
518
519 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
520 dh.device.Root = true
521 dh.device.Vendor = deviceInfo.Vendor
522 dh.device.Model = deviceInfo.Model
523 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
524 dh.device.HardwareVersion = deviceInfo.HardwareVersion
525 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
526
527 if deviceInfo.DeviceId == "" {
528 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
529 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
530 genmac, err := generateMacFromHost(host)
531 if err != nil {
532 return nil, err
533 }
534 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
535 dh.device.MacAddress = genmac
536 } else {
537 dh.device.MacAddress = deviceInfo.DeviceId
538 }
539
540 // Synchronous call to update device - this method is run in its own go routine
541 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
542 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
543 return nil, err
544 }
545
546 return deviceInfo, nil
547}
548
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700549//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530550func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400551 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700552 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400553 dh.transitionMap.Handle(DeviceInit)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530554}
555
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700556//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530557func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700558 return &ic.SwitchCapability{
559 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530560 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700561 HwDesc: "open_pon",
562 SwDesc: "open_pon",
563 SerialNum: dh.device.SerialNumber,
564 },
565 SwitchFeatures: &of.OfpSwitchFeatures{
566 NBuffers: 256,
567 NTables: 2,
568 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
569 of.OfpCapabilities_OFPC_TABLE_STATS |
570 of.OfpCapabilities_OFPC_PORT_STATS |
571 of.OfpCapabilities_OFPC_GROUP_STATS),
572 },
573 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530574}
575
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530577func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700578 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700579 return &ic.PortCapability{
580 Port: &voltha.LogicalPort{
581 OfpPort: &of.OfpPort{
582 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
583 Config: 0,
584 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700585 Curr: capacity,
586 Advertised: capacity,
587 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700588 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
589 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
590 },
591 DeviceId: dh.device.Id,
592 DevicePortNo: uint32(portNo),
593 },
594 }, nil
595}
596
597func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700598 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700599 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700600 var deviceID string
601 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700602
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700603 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
604 if onuInCache, ok := dh.onus[onuKey]; !ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
606 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700607 kwargs := make(map[string]interface{})
608 kwargs["onu_id"] = omciInd.OnuId
609 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700610
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700611 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
612 if err != nil {
613 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700614 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700615 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616 deviceType = onuDevice.Type
617 deviceID = onuDevice.Id
618 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
619 //if not exist in cache, then add to cache.
620 dh.onus[onuKey] = NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700621 } else {
622 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700623 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700624 deviceType = onuInCache.deviceType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700625 deviceID = onuInCache.deviceID
626 proxyDeviceID = onuInCache.proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700627 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700628
629 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
630 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
631 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700632 deviceID, proxyDeviceID, ""); sendErr != nil {
633 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700634 return sendErr
635 }
636 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530637}
638
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700639//ProcessInterAdapterMessage sends the proxied messages to the target device
640// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
641// is meant, and then send the unmarshalled omci message to this onu
642func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
643 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700644 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700645 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700646 fromTopic := msg.Header.FromTopic
647 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700648 toDeviceID := msg.Header.ToDeviceId
649 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700650
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700652
653 msgBody := msg.GetBody()
654
655 omciMsg := &ic.InterAdapterOmciMessage{}
656 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
657 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
658 return err
659 }
660
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700661 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
663 if err != nil {
664 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700665 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700666 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700667 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
668 dh.sendProxiedMessage(onuDevice, omciMsg)
669
cuilin20187b2a8c32019-03-26 19:52:28 -0700670 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700671 log.Debugw("Proxy Address found in omci message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700672 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700673 }
674
675 } else {
676 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
677 }
678 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530679}
680
cuilin20187b2a8c32019-03-26 19:52:28 -0700681func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682 var intfID uint32
683 var onuID uint32
684 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700685 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700686 intfID = onuDevice.ProxyAddress.GetChannelId()
687 onuID = onuDevice.ProxyAddress.GetOnuId()
688 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700689 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690 intfID = omciMsg.GetProxyAddress().GetChannelId()
691 onuID = omciMsg.GetProxyAddress().GetOnuId()
692 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700693 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700694 if connectStatus != voltha.ConnectStatus_REACHABLE {
695 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700696 return
697 }
698
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700699 omciMessage := &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
cuilin20187b2a8c32019-03-26 19:52:28 -0700700
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
702 if err != nil {
703 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
704 return
705 }
706 log.Debugw("omci-message-sent", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": string(omciMsg.GetMessage())})
cuilin20187b2a8c32019-03-26 19:52:28 -0700707}
708
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
710 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
711 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700712 // TODO: need resource manager
713 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700714 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530715 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400716 st, _ := status.FromError(err)
717 if st.Code() == codes.AlreadyExists {
718 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
719 } else {
720 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
721 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700722 } else {
723 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
724 }
725}
726
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400727func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 channelID := onuDiscInd.GetIntfId()
729 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400730 if _, ok := dh.discOnus[sn]; ok {
731 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
732 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700733 }
734
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400735 dh.lockDevice.Lock()
736 dh.discOnus[sn] = true
737 dh.lockDevice.Unlock()
738 // evict the onu serial number from local cache
739 defer func() {
740 delete(dh.discOnus, sn)
741 }()
742
cuilin20187b2a8c32019-03-26 19:52:28 -0700743 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400744 if sn != "" {
745 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400746 } else {
747 log.Error("invalid onu serial number")
748 return errors.New("failed to fetch onu serial number")
749 }
750
751 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
752 var onuID uint32
753 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700754 //This is the first time ONU discovered. Create an OnuID for it.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400755 onuID, err = dh.resourceMgr.GetONUID(onuDiscInd.GetIntfId())
756 if err != nil {
757 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"err": err})
758 return err
759 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700760 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400761 "brcm_openomci_onu", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700762 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400763 log.Errorw("Create onu error",
764 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
765 "onuID": onuID, "sn": sn, "error": err})
766 return err
767 }
768
769 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700770 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400771 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400772 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700773 //Insert the ONU into cache to use in OnuIndication.
774 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
775 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
776 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400777
Mahir Gunyele77977b2019-06-27 05:36:22 -0700778 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
779 if err != nil {
780 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id})
781 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700782 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700783 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
784 //TODO: We put this sleep here to prevent the race between state update and onuIndication
785 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
786 //then the initialisation fails.
787 time.Sleep(1 * time.Second)
788 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
789 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700790}
791
792func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
793 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
794
795 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700796 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700797 var onuDevice *voltha.Device
798 foundInCache := false
799 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
800 if onuInCache, ok := dh.onus[onuKey]; ok {
801 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
802 foundInCache = true
803 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700804 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700805 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
806 if serialNumber != "" {
807 kwargs["serial_number"] = serialNumber
808 } else {
809 kwargs["onu_id"] = onuInd.OnuId
810 kwargs["parent_port_no"] = ponPort
811 }
812 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700813 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700814
815 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400816 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817 //log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": intfIDFromPortNo(onuDevice.ParentPortNo), "currentIntfId": onuInd.GetIntfId()})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400818 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700819 }
820
821 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
822 log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{"expected_onu_id": onuDevice.ProxyAddress.OnuId, "received_onu_id": onuInd.OnuId})
823 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700824 if !foundInCache {
825 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
826 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
827 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700828 dh.updateOnuStates(onuDevice, onuInd)
cuilin20187b2a8c32019-03-26 19:52:28 -0700829
cuilin20187b2a8c32019-03-26 19:52:28 -0700830 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700831 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700832 return
833 }
834
835}
836
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700837func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700838 dh.updateOnuAdminState(onuInd)
839 // operState
840 if onuInd.OperState == "down" {
841 if onuDevice.ConnectStatus != common.ConnectStatus_UNREACHABLE {
842 err := dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_UNREACHABLE,
843 onuDevice.OperStatus)
844 if err != nil {
845 log.Errorw("unable to update onu state", log.Fields{"DeviceID": onuDevice.Id})
846 return
847 }
848 log.Debugln("onu-oper-state-is-down")
849 }
850 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
851 err := dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_UNREACHABLE,
852 common.OperStatus_DISCOVERED)
853 if err != nil {
854 log.Errorw("unable to update onu state", log.Fields{"DeviceID": onuDevice.Id})
855 return
856 }
857 }
858 log.Debugw("inter-adapter-send-onu-ind", log.Fields{"onuIndication": onuInd})
859
860 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
861 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
862 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
863 if err != nil {
864 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
865 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
866 }
867 } else if onuInd.OperState == "up" {
868 if onuDevice.ConnectStatus != common.ConnectStatus_REACHABLE {
869 err := dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, onuDevice.OperStatus)
870 if err != nil {
871 log.Errorw("unable to update onu state", log.Fields{"DeviceID": onuDevice.Id})
872 return
873 }
874 }
875 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
876 log.Warnw("ignore onu indication", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId, "operStatus": onuDevice.OperStatus, "msgOperStatus": onuInd.OperState})
877 return
878 }
879 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
880 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
881 if err != nil {
882 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
883 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
884 return
885 }
886 } else {
887 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
888 }
889}
890
891func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
892 if onuInd.AdminState == "down" {
893 if onuInd.OperState != "down" {
894 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
895 // Forcing the oper state change code to execute
896 onuInd.OperState = "down"
897 }
898 // Port and logical port update is taken care of by oper state block
899 } else if onuInd.AdminState == "up" {
900 log.Debugln("received-onu-admin-state up")
901 } else {
902 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
903 }
904 log.Debugln("admin-state-dealt-with")
905}
906
cuilin20187b2a8c32019-03-26 19:52:28 -0700907func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
908 if serialNum != nil {
909 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -0700910 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700911 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700912}
913
914func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
915 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700916 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -0700917 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
918 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
919 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
920 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
921 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
922 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
923 return tmp
924}
925
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700926//UpdateFlowsBulk upates the bulk flow
927func (dh *DeviceHandler) UpdateFlowsBulk() error {
928 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -0700929}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700930
931//GetChildDevice returns the child device for given parent port and onu id
932func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
933 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400934 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700935 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -0400936 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700937 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400938 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400940 return nil
941 }
942 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
943 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +0530944}
945
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700946// SendPacketInToCore sends packet-in to core
947// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
948// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400949func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
950 log.Debugw("SendPacketInToCore", log.Fields{"port": logicalPort, "packetPayload": packetPayload})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700951 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400952 log.Errorw("Error sending packetin to core", log.Fields{"error": err})
953 return
954 }
955 log.Debug("Sent packet-in to core successfully")
956}
957
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700958//UpdateFlowsIncrementally updates the device flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530959func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700960 log.Debugw("In Update_flows_incrementally", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400961 if flows != nil {
962 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400963 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400964 dh.flowMgr.AddFlow(flow)
965 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400966 for _, flow := range flows.ToRemove.Items {
967 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
968 dh.flowMgr.RemoveFlow(flow)
969 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400970 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700971 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400972 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700973 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400974 // dh.flowMgr.RemoveFlow(flow)
975 }
976 }
977 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530978}
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400979
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700980//DisableDevice disables the given device
981//It marks the following for the given device:
982//Device-Handler Admin-State : down
983//Device Port-State: UNKNOWN
984//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400985func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
986 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
987 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
988 return err
989 }
990 dh.lockDevice.Lock()
991 dh.adminState = "down"
992 dh.lockDevice.Unlock()
993 log.Debug("olt-disabled")
994
995 cloned := proto.Clone(device).(*voltha.Device)
996 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700997 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
998 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400999 return err
1000 }
1001
1002 //Update the device oper state
1003 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1004 dh.device = cloned
1005
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001006 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1007 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001008 return err
1009 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001010 log.Debugw("Disable_device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001011 return nil
1012}
1013
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014//ReenableDevice re-enables the olt device after disable
1015//It marks the following for the given device:
1016//Device-Handler Admin-State : up
1017//Device Port-State: ACTIVE
1018//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001019func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
1020 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1021 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
1022 return err
1023 }
1024
1025 dh.lockDevice.Lock()
1026 dh.adminState = "up"
1027 dh.lockDevice.Unlock()
1028 log.Debug("olt-reenabled")
1029
1030 cloned := proto.Clone(device).(*voltha.Device)
1031 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001032 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1033 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001034 return err
1035 }
1036
1037 //Update the device oper status as ACTIVE
1038 cloned.OperStatus = voltha.OperStatus_ACTIVE
1039 dh.device = cloned
1040
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001041 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1042 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001043 return err
1044 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001045 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001046
1047 return nil
1048}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001049
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001050//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001051func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1052 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1053 log.Errorw("Failed to reboot olt ", log.Fields{"err": err})
1054 return err
1055 }
1056
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001057 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001058
1059 return nil
1060}
1061
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001062func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
1063 log.Debugw("Received packet-in", log.Fields{"packet-indication": *packetIn})
1064 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1065 if err != nil {
1066 log.Errorw("Error getting logical port from packet-in", log.Fields{"error": err})
1067 return
1068 }
1069 log.Debugw("sending packet-in to core", log.Fields{"logicalPortNum": logicalPortNum, "packet": *packetIn})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001070 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001071 log.Errorw("Error sending packet-in to core", log.Fields{"error": err})
1072 return
1073 }
1074 log.Debug("Success sending packet-in to core!")
1075}
1076
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001077// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1078func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
1079 log.Debugw("PacketOut", log.Fields{"deviceID": dh.deviceID, "egress_port_no": egressPortNo, "pkt-length": len(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001080 var etherFrame ethernet.Frame
1081 err := (&etherFrame).UnmarshalBinary(packet.Data)
1082 if err != nil {
1083 log.Errorw("Failed to unmarshal into ethernet frame", log.Fields{"err": err, "pkt-length": len(packet.Data)})
1084 return err
1085 }
1086 log.Debugw("Ethernet Frame", log.Fields{"Frame": etherFrame})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001087 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001088 if egressPortType == voltha.Port_ETHERNET_UNI {
1089 if etherFrame.VLAN != nil { // If double tag, remove the outer tag
1090 nextEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
1091 if nextEthType == 0x8100 {
1092 etherFrame.VLAN = nil
1093 packet.Data, err = etherFrame.MarshalBinary()
1094 if err != nil {
1095 log.Fatalf("failed to marshal frame: %v", err)
1096 return err
1097 }
1098 if err := (&etherFrame).UnmarshalBinary(packet.Data); err != nil {
1099 log.Fatalf("failed to unmarshal frame: %v", err)
1100 return err
1101 }
1102 log.Debug("Double tagged packet , removed outer vlan", log.Fields{"New frame": etherFrame})
1103 }
1104 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001105 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1106 onuID := OnuIDFromPortNum(uint32(egressPortNo))
1107 uniID := UniIDFromPortNum(uint32(egressPortNo))
1108 /*gemPortId, err := dh.flowMgr.GetPacketOutGemPortId(intfID, onuID, uint32(egress_port_no))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001109 if err != nil{
1110 log.Errorw("Error while getting gemport to packet-out",log.Fields{"error": err})
1111 return err
1112 }*/
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001113 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), Pkt: packet.Data}
1114 log.Debug("sending-packet-to-ONU", log.Fields{"egress_port_no": egressPortNo, "IntfId": intfID, "onuID": onuID,
1115 "uniID": uniID, "packet": packet.Data})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001116 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
1117 log.Errorw("Error while sending packet-out to ONU", log.Fields{"error": err})
1118 return err
1119 }
1120 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001121 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001122 log.Debug("sending-packet-to-uplink", log.Fields{"uplink_pkt": uplinkPkt})
1123 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
1124 log.Errorw("Error while sending packet-out to uplink", log.Fields{"error": err})
1125 return err
1126 }
1127 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001128 log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{"egress_port_no": egressPortNo, "egressPortType": egressPortType})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001129 }
1130 return nil
1131}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001132
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1134 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001135}