blob: 20701abda5e0928423dfab58c97f2f27c8555fd7 [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
Devmalya Paulfb990a52019-07-09 10:01:49 -040054 EventProxy *com.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070055 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070056 exitChannel chan int
57 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053058 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070059 transitionMap *TransitionMap
60 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053061 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040062 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053063 resourceMgr *rsrcMgr.OpenOltResourceMgr
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040064 discOnus map[string]bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070065 onus map[string]*OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070066 nniIntfID int
Mahir Gunyela3f9add2019-06-06 15:13:19 -070067}
68
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070070type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070072 deviceType string
73 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070074 onuID uint32
75 intfID uint32
76 proxyDeviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070077}
78
79//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -070081 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070083 device.deviceType = deviceTp
84 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070085 device.onuID = onuID
86 device.intfID = intfID
87 device.proxyDeviceID = proxyDevID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070088 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +053089}
90
91//NewDeviceHandler creates a new device handler
Devmalya Paulfb990a52019-07-09 10:01:49 -040092func NewDeviceHandler(cp *com.CoreProxy, ap *com.AdapterProxy, ep *com.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -070093 var dh DeviceHandler
94 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -040095 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -040096 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -070097 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -070099 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400100 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700101 dh.device = cloned
102 dh.openOLT = adapter
103 dh.exitChannel = make(chan int, 1)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400104 dh.discOnus = make(map[string]bool)
cuilin20187b2a8c32019-03-26 19:52:28 -0700105 dh.lockDevice = sync.RWMutex{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700106 dh.onus = make(map[string]*OnuDevice)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700107 // The nniIntfID is initialized to -1 (invalid) and set to right value
Girish Gowdru1110ef22019-06-24 11:17:59 -0400108 // when the first IntfOperInd with status as "up" is received for
109 // any one of the available NNI port on the OLT device.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110 dh.nniIntfID = -1
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530111
cuilin20187b2a8c32019-03-26 19:52:28 -0700112 //TODO initialize the support classes.
113 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530114}
115
116// start save the device to the data model
117func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700118 dh.lockDevice.Lock()
119 defer dh.lockDevice.Unlock()
120 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
121 // Add the initial device to the local model
122 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530123}
124
125// stop stops the device dh. Not much to do for now
126func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700127 dh.lockDevice.Lock()
128 defer dh.lockDevice.Unlock()
129 log.Debug("stopping-device-agent")
130 dh.exitChannel <- 1
131 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530132}
133
134func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700135 slist := strings.Split(mac, ":")
136 result := make([]uint32, len(slist))
137 var err error
138 var tmp int64
139 for index, val := range slist {
140 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
141 return []uint32{1, 2, 3, 4, 5, 6}
142 }
143 result[index] = uint32(tmp)
144 }
145 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530146}
147
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700148//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 +0530149func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530150
Girish Gowdru0c588b22019-04-23 23:24:56 -0400151 if portType == voltha.Port_ETHERNET_NNI {
152 return fmt.Sprintf("nni-%d", portNum)
153 } else if portType == voltha.Port_PON_OLT {
154 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700155 } else if portType == voltha.Port_ETHERNET_UNI {
156 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400157 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700158 }
159 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530160}
161
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700162func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700163 var operStatus common.OperStatus_OperStatus
164 if state == "up" {
165 operStatus = voltha.OperStatus_ACTIVE
166 } else {
167 operStatus = voltha.OperStatus_DISCOVERED
168 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700169 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400170 label := GetportLabel(portNum, portType)
171 if len(label) == 0 {
172 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
173 return
174 }
175 // Now create Port
176 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700177 PortNo: portNum,
178 Label: label,
179 Type: portType,
180 OperStatus: operStatus,
181 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400182 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700183 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700184 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
185 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400186 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700187
Girish Gowdru1110ef22019-06-24 11:17:59 -0400188 // Once we have successfully added the NNI port to the core, if the
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700189 // locally cached nniIntfID is set to invalid (-1), set it to the right value.
190 if portType == voltha.Port_ETHERNET_NNI && dh.nniIntfID == -1 {
191 dh.nniIntfID = int(intfID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700192 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530193}
194
195// readIndications to read the indications from the OLT device
196func (dh *DeviceHandler) readIndications() {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400197 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700198 if err != nil {
199 log.Errorw("Failed to read indications", log.Fields{"err": err})
200 return
201 }
202 if indications == nil {
203 log.Errorw("Indications is nil", log.Fields{})
204 return
205 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400206 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700207 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400208 if err != nil || device == nil {
209 /*TODO: needs to handle error scenarios */
210 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700211 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400212 }
213 // When the device is in DISABLED and Adapter container restarts, we need to
214 // rebuild the locally maintained admin state.
215 if device.AdminState == voltha.AdminState_DISABLED {
216 dh.lockDevice.Lock()
217 dh.adminState = "down"
218 dh.lockDevice.Unlock()
219 }
220
cuilin20187b2a8c32019-03-26 19:52:28 -0700221 for {
222 indication, err := indications.Recv()
223 if err == io.EOF {
224 break
225 }
226 if err != nil {
227 log.Infow("Failed to read from indications", log.Fields{"err": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400228 dh.transitionMap.Handle(DeviceDownInd)
229 dh.transitionMap.Handle(DeviceInit)
230 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700231 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400232 // When OLT is admin down, allow only NNI operation status change indications.
233 if dh.adminState == "down" {
234 _, isIntfOperInd := indication.Data.(*oop.Indication_IntfOperInd)
235 if isIntfOperInd {
236 intfOperInd := indication.GetIntfOperInd()
237 if intfOperInd.GetType() == "nni" {
238 log.Infow("olt is admin down, allow nni ind", log.Fields{})
239 }
240 } else {
241 log.Infow("olt is admin down, ignore indication", log.Fields{})
242 continue
243 }
244 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530245
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700246 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530247
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700248 }
249}
250
251func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
252 if oltIndication.OperState == "up" {
253 dh.transitionMap.Handle(DeviceUpInd)
254 } else if oltIndication.OperState == "down" {
255 dh.transitionMap.Handle(DeviceDownInd)
256 }
257}
258
259func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400260 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700261 switch indication.Data.(type) {
262 case *oop.Indication_OltInd:
263 dh.handleOltIndication(indication.GetOltInd())
264 case *oop.Indication_IntfInd:
265 intfInd := indication.GetIntfInd()
266 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
267 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
268 case *oop.Indication_IntfOperInd:
269 intfOperInd := indication.GetIntfOperInd()
270 if intfOperInd.GetType() == "nni" {
271 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
272 } else if intfOperInd.GetType() == "pon" {
273 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
274 // Handle pon port update
cuilin20187b2a8c32019-03-26 19:52:28 -0700275 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700276 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
277 case *oop.Indication_OnuDiscInd:
278 onuDiscInd := indication.GetOnuDiscInd()
279 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700280 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400281 dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700282 case *oop.Indication_OnuInd:
283 onuInd := indication.GetOnuInd()
284 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
285 go dh.onuIndication(onuInd)
286 case *oop.Indication_OmciInd:
287 omciInd := indication.GetOmciInd()
288 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
289 if err := dh.omciIndication(omciInd); err != nil {
290 log.Errorw("send-omci-indication-errr", log.Fields{"error": err, "omciInd": omciInd})
291 }
292 case *oop.Indication_PktInd:
293 pktInd := indication.GetPktInd()
294 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
295 go dh.handlePacketIndication(pktInd)
296 case *oop.Indication_PortStats:
297 portStats := indication.GetPortStats()
298 log.Infow("Received port stats indication", log.Fields{"PortStats": portStats})
299 case *oop.Indication_FlowStats:
300 flowStats := indication.GetFlowStats()
301 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
302 case *oop.Indication_AlarmInd:
303 alarmInd := indication.GetAlarmInd()
304 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Devmalya Paulfb990a52019-07-09 10:01:49 -0400305 dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
306
cuilin20187b2a8c32019-03-26 19:52:28 -0700307 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530308}
309
310// doStateUp handle the olt up indication and update to voltha core
311func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400312 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700313 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400314 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700315 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 -0400316 return err
317 }
318 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530319}
320
321// doStateDown handle the olt down indication
322func (dh *DeviceHandler) doStateDown() error {
Girish Gowdrud4245152019-05-10 00:47:31 -0400323 log.Debug("do-state-down-start")
324
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700325 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400326 if err != nil || device == nil {
327 /*TODO: needs to handle error scenarios */
328 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700329 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400330 }
331
332 cloned := proto.Clone(device).(*voltha.Device)
333 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700334 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
335 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
336 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400337 }
338
339 //Update the device oper state and connection status
340 cloned.OperStatus = voltha.OperStatus_UNKNOWN
341 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
342 dh.device = cloned
343
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700344 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
345 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
346 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400347 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400348
349 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700350 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400351 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700352 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400353 return err
354 }
355 for _, onuDevice := range onuDevices.Items {
356
357 // Update onu state as down in onu adapter
358 onuInd := oop.OnuIndication{}
359 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700360 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
361 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
362 if er != nil {
363 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
364 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
365 return er
366 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400367 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700368 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700369 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530370}
371
372// doStateInit dial the grpc before going to init state
373func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400374 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400375 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400376 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700377 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400378 return err
379 }
380 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530381}
382
383// postInit create olt client instance to invoke RPC on the olt device
384func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400385 dh.Client = oop.NewOpenoltClient(dh.clientCon)
386 dh.transitionMap.Handle(GrpcConnected)
387 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530388}
389
390// doStateConnected get the device info and update to voltha core
391func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400392 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400393
394 // Case where OLT is disabled and then rebooted.
395 if dh.adminState == "down" {
396 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700397 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400398 if err != nil || device == nil {
399 /*TODO: needs to handle error scenarios */
400 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
401 }
402
403 cloned := proto.Clone(device).(*voltha.Device)
404 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
405 cloned.OperStatus = voltha.OperStatus_UNKNOWN
406 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700407 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
408 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400409 }
410
411 // Since the device was disabled before the OLT was rebooted, enfore the OLT to be Disabled after re-connection.
412 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
413 if err != nil {
414 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
415 }
416
417 // Start reading indications
418 go dh.readIndications()
419 return nil
420 }
421
Girish Gowdru0c588b22019-04-23 23:24:56 -0400422 deviceInfo, err := dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700423 if err != nil {
424 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
425 return err
426 }
427 if deviceInfo == nil {
428 log.Errorw("Device info is nil", log.Fields{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700429 return errors.New("failed to get device info from OLT")
cuilin20187b2a8c32019-03-26 19:52:28 -0700430 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400431 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
cuilin20187b2a8c32019-03-26 19:52:28 -0700432 dh.device.Root = true
433 dh.device.Vendor = deviceInfo.Vendor
434 dh.device.Model = deviceInfo.Model
cuilin20187b2a8c32019-03-26 19:52:28 -0700435 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
436 dh.device.HardwareVersion = deviceInfo.HardwareVersion
437 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400438 // FIXME: Remove Hardcodings
cuilin20187b2a8c32019-03-26 19:52:28 -0700439 dh.device.MacAddress = "0a:0b:0c:0d:0e:0f"
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530440
cuilin20187b2a8c32019-03-26 19:52:28 -0700441 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700442 if er := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); er != nil {
443 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": er})
cuilin20187b2a8c32019-03-26 19:52:28 -0700444 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400445
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700446 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400447 if err != nil || device == nil {
448 /*TODO: needs to handle error scenarios */
449 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700450 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400451 }
452 cloned := proto.Clone(device).(*voltha.Device)
453 // Update the all ports (if available) on that device to ACTIVE.
454 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700455 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
456 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400457 return err
458 }
459
Girish Gowdru0c588b22019-04-23 23:24:56 -0400460 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
461 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700462 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400463 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700464 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400465 }
466 // Instantiate flow manager
467 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
468 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700469 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400470 }
471 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400472 /* Instantiating Event Manager to handle Alarms and KPIs */
473 dh.eventMgr = NewEventMgr(dh.EventProxy)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530474
cuilin20187b2a8c32019-03-26 19:52:28 -0700475 // Start reading indications
476 go dh.readIndications()
477 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530478}
479
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700480//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530481func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400482 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700483 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400484 dh.transitionMap.Handle(DeviceInit)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530485}
486
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700487//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530488func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700489 return &ic.SwitchCapability{
490 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530491 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700492 HwDesc: "open_pon",
493 SwDesc: "open_pon",
494 SerialNum: dh.device.SerialNumber,
495 },
496 SwitchFeatures: &of.OfpSwitchFeatures{
497 NBuffers: 256,
498 NTables: 2,
499 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
500 of.OfpCapabilities_OFPC_TABLE_STATS |
501 of.OfpCapabilities_OFPC_PORT_STATS |
502 of.OfpCapabilities_OFPC_GROUP_STATS),
503 },
504 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530505}
506
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700507//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530508func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700509 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700510 return &ic.PortCapability{
511 Port: &voltha.LogicalPort{
512 OfpPort: &of.OfpPort{
513 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
514 Config: 0,
515 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700516 Curr: capacity,
517 Advertised: capacity,
518 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700519 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
520 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
521 },
522 DeviceId: dh.device.Id,
523 DevicePortNo: uint32(portNo),
524 },
525 }, nil
526}
527
528func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700529 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700530 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700531 var deviceID string
532 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700533
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700534 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
535 if onuInCache, ok := dh.onus[onuKey]; !ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700536 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
537 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700538 kwargs := make(map[string]interface{})
539 kwargs["onu_id"] = omciInd.OnuId
540 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700541
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
543 if err != nil {
544 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700545 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700546 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700547 deviceType = onuDevice.Type
548 deviceID = onuDevice.Id
549 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
550 //if not exist in cache, then add to cache.
551 dh.onus[onuKey] = NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700552 } else {
553 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700554 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700555 deviceType = onuInCache.deviceType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700556 deviceID = onuInCache.deviceID
557 proxyDeviceID = onuInCache.proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700558 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700559
560 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
561 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
562 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700563 deviceID, proxyDeviceID, ""); sendErr != nil {
564 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700565 return sendErr
566 }
567 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530568}
569
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700570//ProcessInterAdapterMessage sends the proxied messages to the target device
571// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
572// is meant, and then send the unmarshalled omci message to this onu
573func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
574 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700575 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700577 fromTopic := msg.Header.FromTopic
578 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700579 toDeviceID := msg.Header.ToDeviceId
580 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700581
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700582 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700583
584 msgBody := msg.GetBody()
585
586 omciMsg := &ic.InterAdapterOmciMessage{}
587 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
588 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
589 return err
590 }
591
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700592 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700593 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
594 if err != nil {
595 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700596 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700597 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700598 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
599 dh.sendProxiedMessage(onuDevice, omciMsg)
600
cuilin20187b2a8c32019-03-26 19:52:28 -0700601 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700602 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 -0700603 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700604 }
605
606 } else {
607 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
608 }
609 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530610}
611
cuilin20187b2a8c32019-03-26 19:52:28 -0700612func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700613 var intfID uint32
614 var onuID uint32
615 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700616 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 intfID = onuDevice.ProxyAddress.GetChannelId()
618 onuID = onuDevice.ProxyAddress.GetOnuId()
619 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700620 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700621 intfID = omciMsg.GetProxyAddress().GetChannelId()
622 onuID = omciMsg.GetProxyAddress().GetOnuId()
623 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700624 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700625 if connectStatus != voltha.ConnectStatus_REACHABLE {
626 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700627 return
628 }
629
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700630 omciMessage := &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
cuilin20187b2a8c32019-03-26 19:52:28 -0700631
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700632 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
633 if err != nil {
634 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
635 return
636 }
637 log.Debugw("omci-message-sent", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": string(omciMsg.GetMessage())})
cuilin20187b2a8c32019-03-26 19:52:28 -0700638}
639
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
641 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
642 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700643 // TODO: need resource manager
644 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700645 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530646 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400647 st, _ := status.FromError(err)
648 if st.Code() == codes.AlreadyExists {
649 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
650 } else {
651 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
652 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700653 } else {
654 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
655 }
656}
657
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400658func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700659 channelID := onuDiscInd.GetIntfId()
660 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400661 if _, ok := dh.discOnus[sn]; ok {
662 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
663 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700664 }
665
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400666 dh.lockDevice.Lock()
667 dh.discOnus[sn] = true
668 dh.lockDevice.Unlock()
669 // evict the onu serial number from local cache
670 defer func() {
671 delete(dh.discOnus, sn)
672 }()
673
cuilin20187b2a8c32019-03-26 19:52:28 -0700674 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400675 if sn != "" {
676 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400677 } else {
678 log.Error("invalid onu serial number")
679 return errors.New("failed to fetch onu serial number")
680 }
681
682 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
683 var onuID uint32
684 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700685 //This is the first time ONU discovered. Create an OnuID for it.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400686 onuID, err = dh.resourceMgr.GetONUID(onuDiscInd.GetIntfId())
687 if err != nil {
688 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"err": err})
689 return err
690 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700691 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400692 "brcm_openomci_onu", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700693 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400694 log.Errorw("Create onu error",
695 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
696 "onuID": onuID, "sn": sn, "error": err})
697 return err
698 }
699
700 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700701 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400702 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400703 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700704 //Insert the ONU into cache to use in OnuIndication.
705 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
706 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
707 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400708
Mahir Gunyele77977b2019-06-27 05:36:22 -0700709 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
710 if err != nil {
711 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id})
712 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700713 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700714 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
715 //TODO: We put this sleep here to prevent the race between state update and onuIndication
716 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
717 //then the initialisation fails.
718 time.Sleep(1 * time.Second)
719 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
720 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700721}
722
723func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
724 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
725
726 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700727 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700728 var onuDevice *voltha.Device
729 foundInCache := false
730 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
731 if onuInCache, ok := dh.onus[onuKey]; ok {
732 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
733 foundInCache = true
734 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700735 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700736 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
737 if serialNumber != "" {
738 kwargs["serial_number"] = serialNumber
739 } else {
740 kwargs["onu_id"] = onuInd.OnuId
741 kwargs["parent_port_no"] = ponPort
742 }
743 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700744 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700745
746 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400747 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700748 //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 -0400749 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700750 }
751
752 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
753 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})
754 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700755 if !foundInCache {
756 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
757 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
758 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 dh.updateOnuStates(onuDevice, onuInd)
cuilin20187b2a8c32019-03-26 19:52:28 -0700760
cuilin20187b2a8c32019-03-26 19:52:28 -0700761 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700762 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700763 return
764 }
765
766}
767
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769 dh.updateOnuAdminState(onuInd)
770 // operState
771 if onuInd.OperState == "down" {
772 if onuDevice.ConnectStatus != common.ConnectStatus_UNREACHABLE {
773 err := dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_UNREACHABLE,
774 onuDevice.OperStatus)
775 if err != nil {
776 log.Errorw("unable to update onu state", log.Fields{"DeviceID": onuDevice.Id})
777 return
778 }
779 log.Debugln("onu-oper-state-is-down")
780 }
781 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
782 err := dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_UNREACHABLE,
783 common.OperStatus_DISCOVERED)
784 if err != nil {
785 log.Errorw("unable to update onu state", log.Fields{"DeviceID": onuDevice.Id})
786 return
787 }
788 }
789 log.Debugw("inter-adapter-send-onu-ind", log.Fields{"onuIndication": onuInd})
790
791 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
792 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
793 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
794 if err != nil {
795 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
796 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
797 }
798 } else if onuInd.OperState == "up" {
799 if onuDevice.ConnectStatus != common.ConnectStatus_REACHABLE {
800 err := dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, onuDevice.OperStatus)
801 if err != nil {
802 log.Errorw("unable to update onu state", log.Fields{"DeviceID": onuDevice.Id})
803 return
804 }
805 }
806 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
807 log.Warnw("ignore onu indication", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId, "operStatus": onuDevice.OperStatus, "msgOperStatus": onuInd.OperState})
808 return
809 }
810 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
811 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
812 if err != nil {
813 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
814 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
815 return
816 }
817 } else {
818 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
819 }
820}
821
822func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
823 if onuInd.AdminState == "down" {
824 if onuInd.OperState != "down" {
825 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
826 // Forcing the oper state change code to execute
827 onuInd.OperState = "down"
828 }
829 // Port and logical port update is taken care of by oper state block
830 } else if onuInd.AdminState == "up" {
831 log.Debugln("received-onu-admin-state up")
832 } else {
833 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
834 }
835 log.Debugln("admin-state-dealt-with")
836}
837
cuilin20187b2a8c32019-03-26 19:52:28 -0700838func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
839 if serialNum != nil {
840 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -0700841 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700842 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700843}
844
845func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
846 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -0700848 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
849 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
850 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
851 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
852 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
853 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
854 return tmp
855}
856
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700857//UpdateFlowsBulk upates the bulk flow
858func (dh *DeviceHandler) UpdateFlowsBulk() error {
859 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -0700860}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700861
862//GetChildDevice returns the child device for given parent port and onu id
863func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
864 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400865 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700866 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -0400867 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700868 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400869 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700870 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400871 return nil
872 }
873 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
874 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +0530875}
876
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700877// SendPacketInToCore sends packet-in to core
878// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
879// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400880func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
881 log.Debugw("SendPacketInToCore", log.Fields{"port": logicalPort, "packetPayload": packetPayload})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700882 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400883 log.Errorw("Error sending packetin to core", log.Fields{"error": err})
884 return
885 }
886 log.Debug("Sent packet-in to core successfully")
887}
888
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700889//UpdateFlowsIncrementally updates the device flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530890func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700891 log.Debugw("In Update_flows_incrementally", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400892 if flows != nil {
893 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400894 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400895 dh.flowMgr.AddFlow(flow)
896 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400897 for _, flow := range flows.ToRemove.Items {
898 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
899 dh.flowMgr.RemoveFlow(flow)
900 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400901 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700902 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400903 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700904 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400905 // dh.flowMgr.RemoveFlow(flow)
906 }
907 }
908 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530909}
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400910
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700911//DisableDevice disables the given device
912//It marks the following for the given device:
913//Device-Handler Admin-State : down
914//Device Port-State: UNKNOWN
915//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400916func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
917 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
918 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
919 return err
920 }
921 dh.lockDevice.Lock()
922 dh.adminState = "down"
923 dh.lockDevice.Unlock()
924 log.Debug("olt-disabled")
925
926 cloned := proto.Clone(device).(*voltha.Device)
927 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700928 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
929 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400930 return err
931 }
932
933 //Update the device oper state
934 cloned.OperStatus = voltha.OperStatus_UNKNOWN
935 dh.device = cloned
936
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700937 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
938 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400939 return err
940 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700941 log.Debugw("Disable_device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400942 return nil
943}
944
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700945//ReenableDevice re-enables the olt device after disable
946//It marks the following for the given device:
947//Device-Handler Admin-State : up
948//Device Port-State: ACTIVE
949//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400950func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
951 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
952 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
953 return err
954 }
955
956 dh.lockDevice.Lock()
957 dh.adminState = "up"
958 dh.lockDevice.Unlock()
959 log.Debug("olt-reenabled")
960
961 cloned := proto.Clone(device).(*voltha.Device)
962 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700963 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
964 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400965 return err
966 }
967
968 //Update the device oper status as ACTIVE
969 cloned.OperStatus = voltha.OperStatus_ACTIVE
970 dh.device = cloned
971
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700972 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
973 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400974 return err
975 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400977
978 return nil
979}
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400980
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700981//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400982func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
983 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
984 log.Errorw("Failed to reboot olt ", log.Fields{"err": err})
985 return err
986 }
987
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400989
990 return nil
991}
992
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400993func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
994 log.Debugw("Received packet-in", log.Fields{"packet-indication": *packetIn})
995 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
996 if err != nil {
997 log.Errorw("Error getting logical port from packet-in", log.Fields{"error": err})
998 return
999 }
1000 log.Debugw("sending packet-in to core", log.Fields{"logicalPortNum": logicalPortNum, "packet": *packetIn})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001001 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001002 log.Errorw("Error sending packet-in to core", log.Fields{"error": err})
1003 return
1004 }
1005 log.Debug("Success sending packet-in to core!")
1006}
1007
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001008// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1009func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
1010 log.Debugw("PacketOut", log.Fields{"deviceID": dh.deviceID, "egress_port_no": egressPortNo, "pkt-length": len(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001011 var etherFrame ethernet.Frame
1012 err := (&etherFrame).UnmarshalBinary(packet.Data)
1013 if err != nil {
1014 log.Errorw("Failed to unmarshal into ethernet frame", log.Fields{"err": err, "pkt-length": len(packet.Data)})
1015 return err
1016 }
1017 log.Debugw("Ethernet Frame", log.Fields{"Frame": etherFrame})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001018 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001019 if egressPortType == voltha.Port_ETHERNET_UNI {
1020 if etherFrame.VLAN != nil { // If double tag, remove the outer tag
1021 nextEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
1022 if nextEthType == 0x8100 {
1023 etherFrame.VLAN = nil
1024 packet.Data, err = etherFrame.MarshalBinary()
1025 if err != nil {
1026 log.Fatalf("failed to marshal frame: %v", err)
1027 return err
1028 }
1029 if err := (&etherFrame).UnmarshalBinary(packet.Data); err != nil {
1030 log.Fatalf("failed to unmarshal frame: %v", err)
1031 return err
1032 }
1033 log.Debug("Double tagged packet , removed outer vlan", log.Fields{"New frame": etherFrame})
1034 }
1035 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001036 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1037 onuID := OnuIDFromPortNum(uint32(egressPortNo))
1038 uniID := UniIDFromPortNum(uint32(egressPortNo))
1039 /*gemPortId, err := dh.flowMgr.GetPacketOutGemPortId(intfID, onuID, uint32(egress_port_no))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001040 if err != nil{
1041 log.Errorw("Error while getting gemport to packet-out",log.Fields{"error": err})
1042 return err
1043 }*/
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001044 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), Pkt: packet.Data}
1045 log.Debug("sending-packet-to-ONU", log.Fields{"egress_port_no": egressPortNo, "IntfId": intfID, "onuID": onuID,
1046 "uniID": uniID, "packet": packet.Data})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001047 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
1048 log.Errorw("Error while sending packet-out to ONU", log.Fields{"error": err})
1049 return err
1050 }
1051 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001052 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001053 log.Debug("sending-packet-to-uplink", log.Fields{"uplink_pkt": uplinkPkt})
1054 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
1055 log.Errorw("Error while sending packet-out to uplink", log.Fields{"error": err})
1056 return err
1057 }
1058 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001059 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 -04001060 }
1061 return nil
1062}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001063
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001064func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1065 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001066}