blob: fef55bf548044587503a85046c5fa850194dbc93 [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"
26 "strconv"
27 "strings"
28 "sync"
29 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053030
cuilin20187b2a8c32019-03-26 19:52:28 -070031 "github.com/gogo/protobuf/proto"
32 "github.com/golang/protobuf/ptypes"
manikkaraj k9eb6cac2019-05-09 12:32:03 -040033 "github.com/mdlayher/ethernet"
cuilin20187b2a8c32019-03-26 19:52:28 -070034 com "github.com/opencord/voltha-go/adapters/common"
35 "github.com/opencord/voltha-go/common/log"
Girish Gowdru0c588b22019-04-23 23:24:56 -040036 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj kbf256be2019-03-25 00:13:48 +053037 "github.com/opencord/voltha-protos/go/common"
38 ic "github.com/opencord/voltha-protos/go/inter_container"
39 of "github.com/opencord/voltha-protos/go/openflow_13"
40 oop "github.com/opencord/voltha-protos/go/openolt"
manikkaraj kbf256be2019-03-25 00:13:48 +053041 "github.com/opencord/voltha-protos/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070042 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040043 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053044)
45
46//DeviceHandler will interact with the OLT device.
47type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070048 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070049 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040050 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070051 device *voltha.Device
52 coreProxy *com.CoreProxy
manikkaraj kbf256be2019-03-25 00:13:48 +053053 AdapterProxy *com.AdapterProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070054 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070055 exitChannel chan int
56 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053057 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070058 transitionMap *TransitionMap
59 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053060 flowMgr *OpenOltFlowMgr
61 resourceMgr *rsrcMgr.OpenOltResourceMgr
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040062 discOnus map[string]bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070063 onus map[string]*OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064 nniIntfID int
Mahir Gunyela3f9add2019-06-06 15:13:19 -070065}
66
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070068type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070070 deviceType string
71 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072 onuID uint32
73 intfID uint32
74 proxyDeviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070075}
76
77//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -070079 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070081 device.deviceType = deviceTp
82 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 device.onuID = onuID
84 device.intfID = intfID
85 device.proxyDeviceID = proxyDevID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070086 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +053087}
88
89//NewDeviceHandler creates a new device handler
cuilin20187b2a8c32019-03-26 19:52:28 -070090func NewDeviceHandler(cp *com.CoreProxy, ap *com.AdapterProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
91 var dh DeviceHandler
92 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -040093 dh.AdapterProxy = ap
cuilin20187b2a8c32019-03-26 19:52:28 -070094 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070095 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -070096 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -040097 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -070098 dh.device = cloned
99 dh.openOLT = adapter
100 dh.exitChannel = make(chan int, 1)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400101 dh.discOnus = make(map[string]bool)
cuilin20187b2a8c32019-03-26 19:52:28 -0700102 dh.lockDevice = sync.RWMutex{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700103 dh.onus = make(map[string]*OnuDevice)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700104 // The nniIntfID is initialized to -1 (invalid) and set to right value
Girish Gowdru1110ef22019-06-24 11:17:59 -0400105 // when the first IntfOperInd with status as "up" is received for
106 // any one of the available NNI port on the OLT device.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700107 dh.nniIntfID = -1
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530108
cuilin20187b2a8c32019-03-26 19:52:28 -0700109 //TODO initialize the support classes.
110 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530111}
112
113// start save the device to the data model
114func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700115 dh.lockDevice.Lock()
116 defer dh.lockDevice.Unlock()
117 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
118 // Add the initial device to the local model
119 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530120}
121
122// stop stops the device dh. Not much to do for now
123func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700124 dh.lockDevice.Lock()
125 defer dh.lockDevice.Unlock()
126 log.Debug("stopping-device-agent")
127 dh.exitChannel <- 1
128 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530129}
130
131func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700132 slist := strings.Split(mac, ":")
133 result := make([]uint32, len(slist))
134 var err error
135 var tmp int64
136 for index, val := range slist {
137 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
138 return []uint32{1, 2, 3, 4, 5, 6}
139 }
140 result[index] = uint32(tmp)
141 }
142 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530143}
144
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700145//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 +0530146func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530147
Girish Gowdru0c588b22019-04-23 23:24:56 -0400148 if portType == voltha.Port_ETHERNET_NNI {
149 return fmt.Sprintf("nni-%d", portNum)
150 } else if portType == voltha.Port_PON_OLT {
151 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 } else if portType == voltha.Port_ETHERNET_UNI {
153 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400154 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700155 }
156 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530157}
158
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700159func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700160 var operStatus common.OperStatus_OperStatus
161 if state == "up" {
162 operStatus = voltha.OperStatus_ACTIVE
163 } else {
164 operStatus = voltha.OperStatus_DISCOVERED
165 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700166 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400167 label := GetportLabel(portNum, portType)
168 if len(label) == 0 {
169 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
170 return
171 }
172 // Now create Port
173 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700174 PortNo: portNum,
175 Label: label,
176 Type: portType,
177 OperStatus: operStatus,
178 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400179 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700180 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700181 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
182 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400183 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700184
Girish Gowdru1110ef22019-06-24 11:17:59 -0400185 // Once we have successfully added the NNI port to the core, if the
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700186 // locally cached nniIntfID is set to invalid (-1), set it to the right value.
187 if portType == voltha.Port_ETHERNET_NNI && dh.nniIntfID == -1 {
188 dh.nniIntfID = int(intfID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700189 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530190}
191
192// readIndications to read the indications from the OLT device
193func (dh *DeviceHandler) readIndications() {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400194 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700195 if err != nil {
196 log.Errorw("Failed to read indications", log.Fields{"err": err})
197 return
198 }
199 if indications == nil {
200 log.Errorw("Indications is nil", log.Fields{})
201 return
202 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400203 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700204 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400205 if err != nil || device == nil {
206 /*TODO: needs to handle error scenarios */
207 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700208 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400209 }
210 // When the device is in DISABLED and Adapter container restarts, we need to
211 // rebuild the locally maintained admin state.
212 if device.AdminState == voltha.AdminState_DISABLED {
213 dh.lockDevice.Lock()
214 dh.adminState = "down"
215 dh.lockDevice.Unlock()
216 }
217
cuilin20187b2a8c32019-03-26 19:52:28 -0700218 for {
219 indication, err := indications.Recv()
220 if err == io.EOF {
221 break
222 }
223 if err != nil {
224 log.Infow("Failed to read from indications", log.Fields{"err": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400225 dh.transitionMap.Handle(DeviceDownInd)
226 dh.transitionMap.Handle(DeviceInit)
227 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700228 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400229 // When OLT is admin down, allow only NNI operation status change indications.
230 if dh.adminState == "down" {
231 _, isIntfOperInd := indication.Data.(*oop.Indication_IntfOperInd)
232 if isIntfOperInd {
233 intfOperInd := indication.GetIntfOperInd()
234 if intfOperInd.GetType() == "nni" {
235 log.Infow("olt is admin down, allow nni ind", log.Fields{})
236 }
237 } else {
238 log.Infow("olt is admin down, ignore indication", log.Fields{})
239 continue
240 }
241 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530242
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700243 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530244
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700245 }
246}
247
248func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
249 if oltIndication.OperState == "up" {
250 dh.transitionMap.Handle(DeviceUpInd)
251 } else if oltIndication.OperState == "down" {
252 dh.transitionMap.Handle(DeviceDownInd)
253 }
254}
255
256func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
257 switch indication.Data.(type) {
258 case *oop.Indication_OltInd:
259 dh.handleOltIndication(indication.GetOltInd())
260 case *oop.Indication_IntfInd:
261 intfInd := indication.GetIntfInd()
262 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
263 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
264 case *oop.Indication_IntfOperInd:
265 intfOperInd := indication.GetIntfOperInd()
266 if intfOperInd.GetType() == "nni" {
267 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
268 } else if intfOperInd.GetType() == "pon" {
269 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
270 // Handle pon port update
cuilin20187b2a8c32019-03-26 19:52:28 -0700271 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
273 case *oop.Indication_OnuDiscInd:
274 onuDiscInd := indication.GetOnuDiscInd()
275 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700276 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400277 dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700278 case *oop.Indication_OnuInd:
279 onuInd := indication.GetOnuInd()
280 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
281 go dh.onuIndication(onuInd)
282 case *oop.Indication_OmciInd:
283 omciInd := indication.GetOmciInd()
284 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
285 if err := dh.omciIndication(omciInd); err != nil {
286 log.Errorw("send-omci-indication-errr", log.Fields{"error": err, "omciInd": omciInd})
287 }
288 case *oop.Indication_PktInd:
289 pktInd := indication.GetPktInd()
290 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
291 go dh.handlePacketIndication(pktInd)
292 case *oop.Indication_PortStats:
293 portStats := indication.GetPortStats()
294 log.Infow("Received port stats indication", log.Fields{"PortStats": portStats})
295 case *oop.Indication_FlowStats:
296 flowStats := indication.GetFlowStats()
297 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
298 case *oop.Indication_AlarmInd:
299 alarmInd := indication.GetAlarmInd()
300 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
cuilin20187b2a8c32019-03-26 19:52:28 -0700301 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530302}
303
304// doStateUp handle the olt up indication and update to voltha core
305func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400306 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700307 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400308 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700309 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 -0400310 return err
311 }
312 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530313}
314
315// doStateDown handle the olt down indication
316func (dh *DeviceHandler) doStateDown() error {
Girish Gowdrud4245152019-05-10 00:47:31 -0400317 log.Debug("do-state-down-start")
318
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700319 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400320 if err != nil || device == nil {
321 /*TODO: needs to handle error scenarios */
322 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700323 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400324 }
325
326 cloned := proto.Clone(device).(*voltha.Device)
327 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700328 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
329 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
330 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400331 }
332
333 //Update the device oper state and connection status
334 cloned.OperStatus = voltha.OperStatus_UNKNOWN
335 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
336 dh.device = cloned
337
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700338 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
339 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
340 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400341 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400342
343 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700344 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400345 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700346 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400347 return err
348 }
349 for _, onuDevice := range onuDevices.Items {
350
351 // Update onu state as down in onu adapter
352 onuInd := oop.OnuIndication{}
353 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700354 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
355 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
356 if er != nil {
357 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
358 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
359 return er
360 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400361 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700362 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700363 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530364}
365
366// doStateInit dial the grpc before going to init state
367func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400368 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400369 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400370 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700371 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400372 return err
373 }
374 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530375}
376
377// postInit create olt client instance to invoke RPC on the olt device
378func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400379 dh.Client = oop.NewOpenoltClient(dh.clientCon)
380 dh.transitionMap.Handle(GrpcConnected)
381 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530382}
383
384// doStateConnected get the device info and update to voltha core
385func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400386 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400387
388 // Case where OLT is disabled and then rebooted.
389 if dh.adminState == "down" {
390 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700391 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400392 if err != nil || device == nil {
393 /*TODO: needs to handle error scenarios */
394 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
395 }
396
397 cloned := proto.Clone(device).(*voltha.Device)
398 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
399 cloned.OperStatus = voltha.OperStatus_UNKNOWN
400 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700401 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
402 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400403 }
404
405 // Since the device was disabled before the OLT was rebooted, enfore the OLT to be Disabled after re-connection.
406 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
407 if err != nil {
408 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
409 }
410
411 // Start reading indications
412 go dh.readIndications()
413 return nil
414 }
415
Girish Gowdru0c588b22019-04-23 23:24:56 -0400416 deviceInfo, err := dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700417 if err != nil {
418 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
419 return err
420 }
421 if deviceInfo == nil {
422 log.Errorw("Device info is nil", log.Fields{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700423 return errors.New("failed to get device info from OLT")
cuilin20187b2a8c32019-03-26 19:52:28 -0700424 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400425 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
cuilin20187b2a8c32019-03-26 19:52:28 -0700426 dh.device.Root = true
427 dh.device.Vendor = deviceInfo.Vendor
428 dh.device.Model = deviceInfo.Model
cuilin20187b2a8c32019-03-26 19:52:28 -0700429 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
430 dh.device.HardwareVersion = deviceInfo.HardwareVersion
431 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400432 // FIXME: Remove Hardcodings
cuilin20187b2a8c32019-03-26 19:52:28 -0700433 dh.device.MacAddress = "0a:0b:0c:0d:0e:0f"
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530434
cuilin20187b2a8c32019-03-26 19:52:28 -0700435 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700436 if er := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); er != nil {
437 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": er})
cuilin20187b2a8c32019-03-26 19:52:28 -0700438 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400439
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700440 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400441 if err != nil || device == nil {
442 /*TODO: needs to handle error scenarios */
443 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700444 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400445 }
446 cloned := proto.Clone(device).(*voltha.Device)
447 // Update the all ports (if available) on that device to ACTIVE.
448 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700449 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
450 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400451 return err
452 }
453
Girish Gowdru0c588b22019-04-23 23:24:56 -0400454 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
455 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700456 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400457 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700458 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400459 }
460 // Instantiate flow manager
461 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
462 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700463 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400464 }
465 /* TODO: Instantiate Alarm , stats , BW managers */
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530466
cuilin20187b2a8c32019-03-26 19:52:28 -0700467 // Start reading indications
468 go dh.readIndications()
469 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530470}
471
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700472//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530473func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400474 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700475 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400476 dh.transitionMap.Handle(DeviceInit)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530477}
478
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700479//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530480func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700481 return &ic.SwitchCapability{
482 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530483 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700484 HwDesc: "open_pon",
485 SwDesc: "open_pon",
486 SerialNum: dh.device.SerialNumber,
487 },
488 SwitchFeatures: &of.OfpSwitchFeatures{
489 NBuffers: 256,
490 NTables: 2,
491 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
492 of.OfpCapabilities_OFPC_TABLE_STATS |
493 of.OfpCapabilities_OFPC_PORT_STATS |
494 of.OfpCapabilities_OFPC_GROUP_STATS),
495 },
496 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530497}
498
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700499//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530500func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700501 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700502 return &ic.PortCapability{
503 Port: &voltha.LogicalPort{
504 OfpPort: &of.OfpPort{
505 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
506 Config: 0,
507 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700508 Curr: capacity,
509 Advertised: capacity,
510 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700511 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
512 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
513 },
514 DeviceId: dh.device.Id,
515 DevicePortNo: uint32(portNo),
516 },
517 }, nil
518}
519
520func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700521 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700522 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700523 var deviceID string
524 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700525
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700526 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
527 if onuInCache, ok := dh.onus[onuKey]; !ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700528 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
529 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700530 kwargs := make(map[string]interface{})
531 kwargs["onu_id"] = omciInd.OnuId
532 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700533
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700534 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
535 if err != nil {
536 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700537 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700538 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700539 deviceType = onuDevice.Type
540 deviceID = onuDevice.Id
541 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
542 //if not exist in cache, then add to cache.
543 dh.onus[onuKey] = NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700544 } else {
545 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700546 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700547 deviceType = onuInCache.deviceType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700548 deviceID = onuInCache.deviceID
549 proxyDeviceID = onuInCache.proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700550 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700551
552 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
553 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
554 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 deviceID, proxyDeviceID, ""); sendErr != nil {
556 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700557 return sendErr
558 }
559 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530560}
561
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700562//ProcessInterAdapterMessage sends the proxied messages to the target device
563// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
564// is meant, and then send the unmarshalled omci message to this onu
565func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
566 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700567 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700568 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700569 fromTopic := msg.Header.FromTopic
570 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700571 toDeviceID := msg.Header.ToDeviceId
572 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700573
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700574 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700575
576 msgBody := msg.GetBody()
577
578 omciMsg := &ic.InterAdapterOmciMessage{}
579 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
580 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
581 return err
582 }
583
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700584 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700585 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
586 if err != nil {
587 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700588 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700589 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700590 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
591 dh.sendProxiedMessage(onuDevice, omciMsg)
592
cuilin20187b2a8c32019-03-26 19:52:28 -0700593 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700594 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 -0700595 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700596 }
597
598 } else {
599 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
600 }
601 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530602}
603
cuilin20187b2a8c32019-03-26 19:52:28 -0700604func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 var intfID uint32
606 var onuID uint32
607 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700608 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 intfID = onuDevice.ProxyAddress.GetChannelId()
610 onuID = onuDevice.ProxyAddress.GetOnuId()
611 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700612 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700613 intfID = omciMsg.GetProxyAddress().GetChannelId()
614 onuID = omciMsg.GetProxyAddress().GetOnuId()
615 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700616 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 if connectStatus != voltha.ConnectStatus_REACHABLE {
618 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700619 return
620 }
621
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 omciMessage := &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
cuilin20187b2a8c32019-03-26 19:52:28 -0700623
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700624 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
625 if err != nil {
626 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
627 return
628 }
629 log.Debugw("omci-message-sent", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": string(omciMsg.GetMessage())})
cuilin20187b2a8c32019-03-26 19:52:28 -0700630}
631
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700632func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
633 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
634 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700635 // TODO: need resource manager
636 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700637 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530638 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400639 st, _ := status.FromError(err)
640 if st.Code() == codes.AlreadyExists {
641 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
642 } else {
643 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
644 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700645 } else {
646 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
647 }
648}
649
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400650func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 channelID := onuDiscInd.GetIntfId()
652 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400653 if _, ok := dh.discOnus[sn]; ok {
654 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
655 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700656 }
657
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400658 dh.lockDevice.Lock()
659 dh.discOnus[sn] = true
660 dh.lockDevice.Unlock()
661 // evict the onu serial number from local cache
662 defer func() {
663 delete(dh.discOnus, sn)
664 }()
665
cuilin20187b2a8c32019-03-26 19:52:28 -0700666 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400667 if sn != "" {
668 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400669 } else {
670 log.Error("invalid onu serial number")
671 return errors.New("failed to fetch onu serial number")
672 }
673
674 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
675 var onuID uint32
676 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700677 //This is the first time ONU discovered. Create an OnuID for it.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400678 onuID, err = dh.resourceMgr.GetONUID(onuDiscInd.GetIntfId())
679 if err != nil {
680 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"err": err})
681 return err
682 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700683 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400684 "brcm_openomci_onu", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700685 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400686 log.Errorw("Create onu error",
687 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
688 "onuID": onuID, "sn": sn, "error": err})
689 return err
690 }
691
692 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700693 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400694 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400695 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700696 //Insert the ONU into cache to use in OnuIndication.
697 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
698 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
699 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400700
Mahir Gunyele77977b2019-06-27 05:36:22 -0700701 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
702 if err != nil {
703 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id})
704 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700705 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700706 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
707 //TODO: We put this sleep here to prevent the race between state update and onuIndication
708 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
709 //then the initialisation fails.
710 time.Sleep(1 * time.Second)
711 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
712 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700713}
714
715func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
716 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
717
718 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700719 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700720 var onuDevice *voltha.Device
721 foundInCache := false
722 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
723 if onuInCache, ok := dh.onus[onuKey]; ok {
724 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
725 foundInCache = true
726 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700727 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700728 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
729 if serialNumber != "" {
730 kwargs["serial_number"] = serialNumber
731 } else {
732 kwargs["onu_id"] = onuInd.OnuId
733 kwargs["parent_port_no"] = ponPort
734 }
735 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700736 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700737
738 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400739 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700740 //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 -0400741 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700742 }
743
744 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
745 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})
746 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700747 if !foundInCache {
748 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
749 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
750 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 dh.updateOnuStates(onuDevice, onuInd)
cuilin20187b2a8c32019-03-26 19:52:28 -0700752
cuilin20187b2a8c32019-03-26 19:52:28 -0700753 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700754 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700755 return
756 }
757
758}
759
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700760func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700761 dh.updateOnuAdminState(onuInd)
762 // operState
763 if onuInd.OperState == "down" {
764 if onuDevice.ConnectStatus != common.ConnectStatus_UNREACHABLE {
765 err := dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_UNREACHABLE,
766 onuDevice.OperStatus)
767 if err != nil {
768 log.Errorw("unable to update onu state", log.Fields{"DeviceID": onuDevice.Id})
769 return
770 }
771 log.Debugln("onu-oper-state-is-down")
772 }
773 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
774 err := dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_UNREACHABLE,
775 common.OperStatus_DISCOVERED)
776 if err != nil {
777 log.Errorw("unable to update onu state", log.Fields{"DeviceID": onuDevice.Id})
778 return
779 }
780 }
781 log.Debugw("inter-adapter-send-onu-ind", log.Fields{"onuIndication": onuInd})
782
783 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
784 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
785 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
786 if err != nil {
787 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
788 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
789 }
790 } else if onuInd.OperState == "up" {
791 if onuDevice.ConnectStatus != common.ConnectStatus_REACHABLE {
792 err := dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, onuDevice.OperStatus)
793 if err != nil {
794 log.Errorw("unable to update onu state", log.Fields{"DeviceID": onuDevice.Id})
795 return
796 }
797 }
798 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
799 log.Warnw("ignore onu indication", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId, "operStatus": onuDevice.OperStatus, "msgOperStatus": onuInd.OperState})
800 return
801 }
802 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
803 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
804 if err != nil {
805 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
806 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
807 return
808 }
809 } else {
810 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
811 }
812}
813
814func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
815 if onuInd.AdminState == "down" {
816 if onuInd.OperState != "down" {
817 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
818 // Forcing the oper state change code to execute
819 onuInd.OperState = "down"
820 }
821 // Port and logical port update is taken care of by oper state block
822 } else if onuInd.AdminState == "up" {
823 log.Debugln("received-onu-admin-state up")
824 } else {
825 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
826 }
827 log.Debugln("admin-state-dealt-with")
828}
829
cuilin20187b2a8c32019-03-26 19:52:28 -0700830func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
831 if serialNum != nil {
832 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -0700833 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700834 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700835}
836
837func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
838 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700839 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -0700840 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
841 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
842 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
843 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
844 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
845 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
846 return tmp
847}
848
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700849//UpdateFlowsBulk upates the bulk flow
850func (dh *DeviceHandler) UpdateFlowsBulk() error {
851 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -0700852}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700853
854//GetChildDevice returns the child device for given parent port and onu id
855func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
856 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400857 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700858 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -0400859 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700860 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400861 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700862 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400863 return nil
864 }
865 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
866 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +0530867}
868
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700869// SendPacketInToCore sends packet-in to core
870// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
871// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400872func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
873 log.Debugw("SendPacketInToCore", log.Fields{"port": logicalPort, "packetPayload": packetPayload})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700874 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400875 log.Errorw("Error sending packetin to core", log.Fields{"error": err})
876 return
877 }
878 log.Debug("Sent packet-in to core successfully")
879}
880
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700881//UpdateFlowsIncrementally updates the device flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530882func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700883 log.Debugw("In Update_flows_incrementally", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400884 if flows != nil {
885 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400886 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400887 dh.flowMgr.AddFlow(flow)
888 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400889 for _, flow := range flows.ToRemove.Items {
890 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
891 dh.flowMgr.RemoveFlow(flow)
892 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400893 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700894 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400895 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700896 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400897 // dh.flowMgr.RemoveFlow(flow)
898 }
899 }
900 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530901}
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400902
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700903//DisableDevice disables the given device
904//It marks the following for the given device:
905//Device-Handler Admin-State : down
906//Device Port-State: UNKNOWN
907//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400908func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
909 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
910 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
911 return err
912 }
913 dh.lockDevice.Lock()
914 dh.adminState = "down"
915 dh.lockDevice.Unlock()
916 log.Debug("olt-disabled")
917
918 cloned := proto.Clone(device).(*voltha.Device)
919 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700920 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
921 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400922 return err
923 }
924
925 //Update the device oper state
926 cloned.OperStatus = voltha.OperStatus_UNKNOWN
927 dh.device = cloned
928
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700929 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
930 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400931 return err
932 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700933 log.Debugw("Disable_device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400934 return nil
935}
936
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700937//ReenableDevice re-enables the olt device after disable
938//It marks the following for the given device:
939//Device-Handler Admin-State : up
940//Device Port-State: ACTIVE
941//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400942func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
943 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
944 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
945 return err
946 }
947
948 dh.lockDevice.Lock()
949 dh.adminState = "up"
950 dh.lockDevice.Unlock()
951 log.Debug("olt-reenabled")
952
953 cloned := proto.Clone(device).(*voltha.Device)
954 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700955 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
956 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400957 return err
958 }
959
960 //Update the device oper status as ACTIVE
961 cloned.OperStatus = voltha.OperStatus_ACTIVE
962 dh.device = cloned
963
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700964 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
965 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400966 return err
967 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700968 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400969
970 return nil
971}
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400972
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700973//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400974func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
975 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
976 log.Errorw("Failed to reboot olt ", log.Fields{"err": err})
977 return err
978 }
979
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700980 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400981
982 return nil
983}
984
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400985func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
986 log.Debugw("Received packet-in", log.Fields{"packet-indication": *packetIn})
987 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
988 if err != nil {
989 log.Errorw("Error getting logical port from packet-in", log.Fields{"error": err})
990 return
991 }
992 log.Debugw("sending packet-in to core", log.Fields{"logicalPortNum": logicalPortNum, "packet": *packetIn})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700993 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400994 log.Errorw("Error sending packet-in to core", log.Fields{"error": err})
995 return
996 }
997 log.Debug("Success sending packet-in to core!")
998}
999
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1001func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
1002 log.Debugw("PacketOut", log.Fields{"deviceID": dh.deviceID, "egress_port_no": egressPortNo, "pkt-length": len(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001003 var etherFrame ethernet.Frame
1004 err := (&etherFrame).UnmarshalBinary(packet.Data)
1005 if err != nil {
1006 log.Errorw("Failed to unmarshal into ethernet frame", log.Fields{"err": err, "pkt-length": len(packet.Data)})
1007 return err
1008 }
1009 log.Debugw("Ethernet Frame", log.Fields{"Frame": etherFrame})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001010 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001011 if egressPortType == voltha.Port_ETHERNET_UNI {
1012 if etherFrame.VLAN != nil { // If double tag, remove the outer tag
1013 nextEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
1014 if nextEthType == 0x8100 {
1015 etherFrame.VLAN = nil
1016 packet.Data, err = etherFrame.MarshalBinary()
1017 if err != nil {
1018 log.Fatalf("failed to marshal frame: %v", err)
1019 return err
1020 }
1021 if err := (&etherFrame).UnmarshalBinary(packet.Data); err != nil {
1022 log.Fatalf("failed to unmarshal frame: %v", err)
1023 return err
1024 }
1025 log.Debug("Double tagged packet , removed outer vlan", log.Fields{"New frame": etherFrame})
1026 }
1027 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001028 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1029 onuID := OnuIDFromPortNum(uint32(egressPortNo))
1030 uniID := UniIDFromPortNum(uint32(egressPortNo))
1031 /*gemPortId, err := dh.flowMgr.GetPacketOutGemPortId(intfID, onuID, uint32(egress_port_no))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001032 if err != nil{
1033 log.Errorw("Error while getting gemport to packet-out",log.Fields{"error": err})
1034 return err
1035 }*/
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001036 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), Pkt: packet.Data}
1037 log.Debug("sending-packet-to-ONU", log.Fields{"egress_port_no": egressPortNo, "IntfId": intfID, "onuID": onuID,
1038 "uniID": uniID, "packet": packet.Data})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001039 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
1040 log.Errorw("Error while sending packet-out to ONU", log.Fields{"error": err})
1041 return err
1042 }
1043 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001044 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001045 log.Debug("sending-packet-to-uplink", log.Fields{"uplink_pkt": uplinkPkt})
1046 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
1047 log.Errorw("Error while sending packet-out to uplink", log.Fields{"error": err})
1048 return err
1049 }
1050 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001051 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 -04001052 }
1053 return nil
1054}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001056func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1057 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001058}