blob: 96e618981a07252cfb367a89b1dbb8b5c6797341 [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"
24 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040025 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "strconv"
27 "strings"
28 "sync"
29 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053030
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040031 "google.golang.org/grpc/codes"
32
cuilin20187b2a8c32019-03-26 19:52:28 -070033 "github.com/gogo/protobuf/proto"
34 "github.com/golang/protobuf/ptypes"
manikkaraj k9eb6cac2019-05-09 12:32:03 -040035 "github.com/mdlayher/ethernet"
cuilin20187b2a8c32019-03-26 19:52:28 -070036 com "github.com/opencord/voltha-go/adapters/common"
37 "github.com/opencord/voltha-go/common/log"
Girish Gowdru0c588b22019-04-23 23:24:56 -040038 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj kbf256be2019-03-25 00:13:48 +053039 "github.com/opencord/voltha-protos/go/common"
40 ic "github.com/opencord/voltha-protos/go/inter_container"
41 of "github.com/opencord/voltha-protos/go/openflow_13"
42 oop "github.com/opencord/voltha-protos/go/openolt"
manikkaraj kbf256be2019-03-25 00:13:48 +053043 "github.com/opencord/voltha-protos/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070044 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040045 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053046)
47
48//DeviceHandler will interact with the OLT device.
49type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070051 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040052 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070053 device *voltha.Device
54 coreProxy *com.CoreProxy
manikkaraj kbf256be2019-03-25 00:13:48 +053055 AdapterProxy *com.AdapterProxy
Devmalya Paulfb990a52019-07-09 10:01:49 -040056 EventProxy *com.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070057 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070058 exitChannel chan int
59 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053060 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070061 transitionMap *TransitionMap
62 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053063 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040064 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053065 resourceMgr *rsrcMgr.OpenOltResourceMgr
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040066 discOnus map[string]bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -070067 onus map[string]*OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 nniIntfID int
Mahir Gunyela3f9add2019-06-06 15:13:19 -070069}
70
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070072type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070073 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070074 deviceType string
75 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076 onuID uint32
77 intfID uint32
78 proxyDeviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070079}
80
81//NewOnuDevice creates a new Onu Device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -070083 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070085 device.deviceType = deviceTp
86 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 device.onuID = onuID
88 device.intfID = intfID
89 device.proxyDeviceID = proxyDevID
Mahir Gunyela3f9add2019-06-06 15:13:19 -070090 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +053091}
92
93//NewDeviceHandler creates a new device handler
Devmalya Paulfb990a52019-07-09 10:01:49 -040094func NewDeviceHandler(cp *com.CoreProxy, ap *com.AdapterProxy, ep *com.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -070095 var dh DeviceHandler
96 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -040097 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -040098 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -070099 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700100 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700101 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400102 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700103 dh.device = cloned
104 dh.openOLT = adapter
105 dh.exitChannel = make(chan int, 1)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400106 dh.discOnus = make(map[string]bool)
cuilin20187b2a8c32019-03-26 19:52:28 -0700107 dh.lockDevice = sync.RWMutex{}
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700108 dh.onus = make(map[string]*OnuDevice)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109 // The nniIntfID is initialized to -1 (invalid) and set to right value
Girish Gowdru1110ef22019-06-24 11:17:59 -0400110 // when the first IntfOperInd with status as "up" is received for
111 // any one of the available NNI port on the OLT device.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 dh.nniIntfID = -1
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530113
cuilin20187b2a8c32019-03-26 19:52:28 -0700114 //TODO initialize the support classes.
115 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530116}
117
118// start save the device to the data model
119func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700120 dh.lockDevice.Lock()
121 defer dh.lockDevice.Unlock()
122 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
123 // Add the initial device to the local model
124 log.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530125}
126
127// stop stops the device dh. Not much to do for now
128func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700129 dh.lockDevice.Lock()
130 defer dh.lockDevice.Unlock()
131 log.Debug("stopping-device-agent")
132 dh.exitChannel <- 1
133 log.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530134}
135
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400136func macifyIP(ip net.IP) string {
137 if len(ip) > 0 {
138 oct1 := strconv.FormatInt(int64(ip[12]), 16)
139 oct2 := strconv.FormatInt(int64(ip[13]), 16)
140 oct3 := strconv.FormatInt(int64(ip[14]), 16)
141 oct4 := strconv.FormatInt(int64(ip[15]), 16)
142 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
143 }
144 return ""
145}
146
147func generateMacFromHost(host string) (string, error) {
148 var genmac string
149 var addr net.IP
150 var ips []string
151 var err error
152
153 log.Debugw("generating-mac-from-host", log.Fields{"host": host})
154
155 if addr = net.ParseIP(host); addr == nil {
156 log.Debugw("looking-up-hostname", log.Fields{"host": host})
157
158 if ips, err = net.LookupHost(host); err == nil {
159 log.Debugw("dns-result-ips", log.Fields{"ips": ips})
160 if addr = net.ParseIP(ips[0]); addr == nil {
161 log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
162 return "", errors.New("unable-to-parse-ip")
163 }
164 genmac = macifyIP(addr)
165 log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
166 return genmac, nil
167 }
168 log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
169 return "", err
170 }
171
172 genmac = macifyIP(addr)
173 log.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
174 return genmac, nil
175}
176
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530177func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700178 slist := strings.Split(mac, ":")
179 result := make([]uint32, len(slist))
180 var err error
181 var tmp int64
182 for index, val := range slist {
183 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
184 return []uint32{1, 2, 3, 4, 5, 6}
185 }
186 result[index] = uint32(tmp)
187 }
188 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530189}
190
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700191//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 +0530192func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530193
Girish Gowdru0c588b22019-04-23 23:24:56 -0400194 if portType == voltha.Port_ETHERNET_NNI {
195 return fmt.Sprintf("nni-%d", portNum)
196 } else if portType == voltha.Port_PON_OLT {
197 return fmt.Sprintf("pon-%d", portNum)
cuilin20187b2a8c32019-03-26 19:52:28 -0700198 } else if portType == voltha.Port_ETHERNET_UNI {
199 log.Errorw("local UNI management not supported", log.Fields{})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400200 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700201 }
202 return ""
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530203}
204
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700205func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700206 var operStatus common.OperStatus_OperStatus
207 if state == "up" {
208 operStatus = voltha.OperStatus_ACTIVE
209 } else {
210 operStatus = voltha.OperStatus_DISCOVERED
211 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212 portNum := IntfIDToPortNo(intfID, portType)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400213 label := GetportLabel(portNum, portType)
214 if len(label) == 0 {
215 log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
216 return
217 }
218 // Now create Port
219 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700220 PortNo: portNum,
221 Label: label,
222 Type: portType,
223 OperStatus: operStatus,
224 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400225 log.Debugw("Sending port update to core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700226 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700227 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
228 log.Errorw("error-creating-nni-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
Girish Gowdru1110ef22019-06-24 11:17:59 -0400229 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700230
Girish Gowdru1110ef22019-06-24 11:17:59 -0400231 // Once we have successfully added the NNI port to the core, if the
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700232 // locally cached nniIntfID is set to invalid (-1), set it to the right value.
233 if portType == voltha.Port_ETHERNET_NNI && dh.nniIntfID == -1 {
234 dh.nniIntfID = int(intfID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700235 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530236}
237
238// readIndications to read the indications from the OLT device
239func (dh *DeviceHandler) readIndications() {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400240 indications, err := dh.Client.EnableIndication(context.Background(), new(oop.Empty))
cuilin20187b2a8c32019-03-26 19:52:28 -0700241 if err != nil {
242 log.Errorw("Failed to read indications", log.Fields{"err": err})
243 return
244 }
245 if indications == nil {
246 log.Errorw("Indications is nil", log.Fields{})
247 return
248 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400249 /* get device state */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700250 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400251 if err != nil || device == nil {
252 /*TODO: needs to handle error scenarios */
253 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700254 return
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400255 }
256 // When the device is in DISABLED and Adapter container restarts, we need to
257 // rebuild the locally maintained admin state.
258 if device.AdminState == voltha.AdminState_DISABLED {
259 dh.lockDevice.Lock()
260 dh.adminState = "down"
261 dh.lockDevice.Unlock()
262 }
263
cuilin20187b2a8c32019-03-26 19:52:28 -0700264 for {
265 indication, err := indications.Recv()
266 if err == io.EOF {
267 break
268 }
269 if err != nil {
270 log.Infow("Failed to read from indications", log.Fields{"err": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400271 dh.transitionMap.Handle(DeviceDownInd)
272 dh.transitionMap.Handle(DeviceInit)
273 break
cuilin20187b2a8c32019-03-26 19:52:28 -0700274 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400275 // When OLT is admin down, allow only NNI operation status change indications.
276 if dh.adminState == "down" {
277 _, isIntfOperInd := indication.Data.(*oop.Indication_IntfOperInd)
278 if isIntfOperInd {
279 intfOperInd := indication.GetIntfOperInd()
280 if intfOperInd.GetType() == "nni" {
281 log.Infow("olt is admin down, allow nni ind", log.Fields{})
282 }
283 } else {
284 log.Infow("olt is admin down, ignore indication", log.Fields{})
285 continue
286 }
287 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530288
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700289 dh.handleIndication(indication)
manikkaraj kbf256be2019-03-25 00:13:48 +0530290
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700291 }
292}
293
294func (dh *DeviceHandler) handleOltIndication(oltIndication *oop.OltIndication) {
295 if oltIndication.OperState == "up" {
296 dh.transitionMap.Handle(DeviceUpInd)
297 } else if oltIndication.OperState == "down" {
298 dh.transitionMap.Handle(DeviceDownInd)
299 }
300}
301
302func (dh *DeviceHandler) handleIndication(indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400303 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700304 switch indication.Data.(type) {
305 case *oop.Indication_OltInd:
306 dh.handleOltIndication(indication.GetOltInd())
307 case *oop.Indication_IntfInd:
308 intfInd := indication.GetIntfInd()
309 go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
310 log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
311 case *oop.Indication_IntfOperInd:
312 intfOperInd := indication.GetIntfOperInd()
313 if intfOperInd.GetType() == "nni" {
314 go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
315 } else if intfOperInd.GetType() == "pon" {
316 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
317 // Handle pon port update
cuilin20187b2a8c32019-03-26 19:52:28 -0700318 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700319 log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
320 case *oop.Indication_OnuDiscInd:
321 onuDiscInd := indication.GetOnuDiscInd()
322 log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700323 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400324 dh.onuDiscIndication(onuDiscInd, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700325 case *oop.Indication_OnuInd:
326 onuInd := indication.GetOnuInd()
327 log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
328 go dh.onuIndication(onuInd)
329 case *oop.Indication_OmciInd:
330 omciInd := indication.GetOmciInd()
331 log.Infow("Received Omci indication ", log.Fields{"OmciInd": omciInd})
332 if err := dh.omciIndication(omciInd); err != nil {
333 log.Errorw("send-omci-indication-errr", log.Fields{"error": err, "omciInd": omciInd})
334 }
335 case *oop.Indication_PktInd:
336 pktInd := indication.GetPktInd()
337 log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
338 go dh.handlePacketIndication(pktInd)
339 case *oop.Indication_PortStats:
340 portStats := indication.GetPortStats()
341 log.Infow("Received port stats indication", log.Fields{"PortStats": portStats})
342 case *oop.Indication_FlowStats:
343 flowStats := indication.GetFlowStats()
344 log.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
345 case *oop.Indication_AlarmInd:
346 alarmInd := indication.GetAlarmInd()
347 log.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Devmalya Paulfb990a52019-07-09 10:01:49 -0400348 dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
349
cuilin20187b2a8c32019-03-26 19:52:28 -0700350 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530351}
352
353// doStateUp handle the olt up indication and update to voltha core
354func (dh *DeviceHandler) doStateUp() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400355 // Synchronous call to update device state - this method is run in its own go routine
cuilin20187b2a8c32019-03-26 19:52:28 -0700356 if err := dh.coreProxy.DeviceStateUpdate(context.Background(), dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400357 voltha.OperStatus_ACTIVE); err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700358 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 -0400359 return err
360 }
361 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530362}
363
364// doStateDown handle the olt down indication
365func (dh *DeviceHandler) doStateDown() error {
Girish Gowdrud4245152019-05-10 00:47:31 -0400366 log.Debug("do-state-down-start")
367
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700368 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400369 if err != nil || device == nil {
370 /*TODO: needs to handle error scenarios */
371 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700372 return errors.New("failed to fetch device device")
Girish Gowdrud4245152019-05-10 00:47:31 -0400373 }
374
375 cloned := proto.Clone(device).(*voltha.Device)
376 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700377 if er := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
378 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
379 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400380 }
381
382 //Update the device oper state and connection status
383 cloned.OperStatus = voltha.OperStatus_UNKNOWN
384 cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
385 dh.device = cloned
386
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700387 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
388 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
389 return er
Girish Gowdrud4245152019-05-10 00:47:31 -0400390 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400391
392 //get the child device for the parent device
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700393 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400394 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700395 log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400396 return err
397 }
398 for _, onuDevice := range onuDevices.Items {
399
400 // Update onu state as down in onu adapter
401 onuInd := oop.OnuIndication{}
402 onuInd.OperState = "down"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700403 er := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
404 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
405 if er != nil {
406 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
407 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
408 return er
409 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400410 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700411 log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700412 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530413}
414
415// doStateInit dial the grpc before going to init state
416func (dh *DeviceHandler) doStateInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400417 var err error
Girish Gowdrud4245152019-05-10 00:47:31 -0400418 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
Girish Gowdru0c588b22019-04-23 23:24:56 -0400419 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700420 log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400421 return err
422 }
423 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530424}
425
426// postInit create olt client instance to invoke RPC on the olt device
427func (dh *DeviceHandler) postInit() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400428 dh.Client = oop.NewOpenoltClient(dh.clientCon)
429 dh.transitionMap.Handle(GrpcConnected)
430 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530431}
432
433// doStateConnected get the device info and update to voltha core
434func (dh *DeviceHandler) doStateConnected() error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400435 log.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400436
437 // Case where OLT is disabled and then rebooted.
438 if dh.adminState == "down" {
439 log.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700440 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -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})
444 }
445
446 cloned := proto.Clone(device).(*voltha.Device)
447 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
448 cloned.OperStatus = voltha.OperStatus_UNKNOWN
449 dh.device = cloned
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700450 if er := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
451 log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400452 }
453
454 // Since the device was disabled before the OLT was rebooted, enfore the OLT to be Disabled after re-connection.
455 _, err = dh.Client.DisableOlt(context.Background(), new(oop.Empty))
456 if err != nil {
457 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
458 }
459
460 // Start reading indications
461 go dh.readIndications()
462 return nil
463 }
464
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400465 deviceInfo, err := dh.populateDeviceInfo()
cuilin20187b2a8c32019-03-26 19:52:28 -0700466 if err != nil {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400467 log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
cuilin20187b2a8c32019-03-26 19:52:28 -0700468 return err
469 }
Girish Gowdrud4245152019-05-10 00:47:31 -0400470
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700471 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400472 if err != nil || device == nil {
473 /*TODO: needs to handle error scenarios */
474 log.Errorw("Failed to fetch device device", log.Fields{"err": err})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700475 return err
Girish Gowdrud4245152019-05-10 00:47:31 -0400476 }
477 cloned := proto.Clone(device).(*voltha.Device)
478 // Update the all ports (if available) on that device to ACTIVE.
479 // The ports do not normally exist, unless the device is coming back from a reboot
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700480 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
481 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdrud4245152019-05-10 00:47:31 -0400482 return err
483 }
484
Girish Gowdru0c588b22019-04-23 23:24:56 -0400485 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
486 // Instantiate resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700487 if dh.resourceMgr = rsrcMgr.NewResourceMgr(dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400488 log.Error("Error while instantiating resource manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700489 return errors.New("instantiating resource manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400490 }
491 // Instantiate flow manager
492 if dh.flowMgr = NewFlowManager(dh, dh.resourceMgr); dh.flowMgr == nil {
493 log.Error("Error while instantiating flow manager")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700494 return errors.New("instantiating flow manager failed")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400495 }
496 /* TODO: Instantiate Alarm , stats , BW managers */
Devmalya Paulfb990a52019-07-09 10:01:49 -0400497 /* Instantiating Event Manager to handle Alarms and KPIs */
498 dh.eventMgr = NewEventMgr(dh.EventProxy)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530499
cuilin20187b2a8c32019-03-26 19:52:28 -0700500 // Start reading indications
501 go dh.readIndications()
502 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530503}
504
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400505func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
506 var err error
507 var deviceInfo *oop.DeviceInfo
508
509 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
510
511 if err != nil {
512 log.Errorw("Failed to fetch device info", log.Fields{"err": err})
513 return nil, err
514 }
515 if deviceInfo == nil {
516 log.Errorw("Device info is nil", log.Fields{})
517 return nil, errors.New("failed to get device info from OLT")
518 }
519
520 log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
521 dh.device.Root = true
522 dh.device.Vendor = deviceInfo.Vendor
523 dh.device.Model = deviceInfo.Model
524 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
525 dh.device.HardwareVersion = deviceInfo.HardwareVersion
526 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
527
528 if deviceInfo.DeviceId == "" {
529 log.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
530 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
531 genmac, err := generateMacFromHost(host)
532 if err != nil {
533 return nil, err
534 }
535 log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
536 dh.device.MacAddress = genmac
537 } else {
538 dh.device.MacAddress = deviceInfo.DeviceId
539 }
540
541 // Synchronous call to update device - this method is run in its own go routine
542 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
543 log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
544 return nil, err
545 }
546
547 return deviceInfo, nil
548}
549
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700550//AdoptDevice adopts the OLT device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530551func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400552 dh.transitionMap = NewTransitionMap(dh)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700553 log.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400554 dh.transitionMap.Handle(DeviceInit)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530555}
556
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700557//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530558func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700559 return &ic.SwitchCapability{
560 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530561 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700562 HwDesc: "open_pon",
563 SwDesc: "open_pon",
564 SerialNum: dh.device.SerialNumber,
565 },
566 SwitchFeatures: &of.OfpSwitchFeatures{
567 NBuffers: 256,
568 NTables: 2,
569 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
570 of.OfpCapabilities_OFPC_TABLE_STATS |
571 of.OfpCapabilities_OFPC_PORT_STATS |
572 of.OfpCapabilities_OFPC_GROUP_STATS),
573 },
574 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530575}
576
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530578func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700579 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700580 return &ic.PortCapability{
581 Port: &voltha.LogicalPort{
582 OfpPort: &of.OfpPort{
583 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
584 Config: 0,
585 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700586 Curr: capacity,
587 Advertised: capacity,
588 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700589 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
590 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
591 },
592 DeviceId: dh.device.Id,
593 DevicePortNo: uint32(portNo),
594 },
595 }, nil
596}
597
598func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700599 log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700600 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700601 var deviceID string
602 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700603
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700604 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
605 if onuInCache, ok := dh.onus[onuKey]; !ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700606 log.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
607 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700608 kwargs := make(map[string]interface{})
609 kwargs["onu_id"] = omciInd.OnuId
610 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700611
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700612 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
613 if err != nil {
614 log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700615 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700616 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 deviceType = onuDevice.Type
618 deviceID = onuDevice.Id
619 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
620 //if not exist in cache, then add to cache.
621 dh.onus[onuKey] = NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700622 } else {
623 //found in cache
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700624 log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700625 deviceType = onuInCache.deviceType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700626 deviceID = onuInCache.deviceID
627 proxyDeviceID = onuInCache.proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700628 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700629
630 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
631 if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
632 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633 deviceID, proxyDeviceID, ""); sendErr != nil {
634 log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700635 return sendErr
636 }
637 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530638}
639
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640//ProcessInterAdapterMessage sends the proxied messages to the target device
641// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
642// is meant, and then send the unmarshalled omci message to this onu
643func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
644 log.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700645 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700646 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700647 fromTopic := msg.Header.FromTopic
648 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649 toDeviceID := msg.Header.ToDeviceId
650 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700651
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700652 log.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700653
654 msgBody := msg.GetBody()
655
656 omciMsg := &ic.InterAdapterOmciMessage{}
657 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
658 log.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
659 return err
660 }
661
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700662 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700663 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
664 if err != nil {
665 log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700666 return err
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700667 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
669 dh.sendProxiedMessage(onuDevice, omciMsg)
670
cuilin20187b2a8c32019-03-26 19:52:28 -0700671 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700672 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 -0700673 dh.sendProxiedMessage(nil, omciMsg)
cuilin20187b2a8c32019-03-26 19:52:28 -0700674 }
675
676 } else {
677 log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
678 }
679 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530680}
681
cuilin20187b2a8c32019-03-26 19:52:28 -0700682func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700683 var intfID uint32
684 var onuID uint32
685 var connectStatus common.ConnectStatus_ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700686 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700687 intfID = onuDevice.ProxyAddress.GetChannelId()
688 onuID = onuDevice.ProxyAddress.GetOnuId()
689 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700690 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 intfID = omciMsg.GetProxyAddress().GetChannelId()
692 onuID = omciMsg.GetProxyAddress().GetOnuId()
693 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700694 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 if connectStatus != voltha.ConnectStatus_REACHABLE {
696 log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700697 return
698 }
699
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700700 omciMessage := &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
cuilin20187b2a8c32019-03-26 19:52:28 -0700701
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
703 if err != nil {
704 log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
705 return
706 }
707 log.Debugw("omci-message-sent", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": string(omciMsg.GetMessage())})
cuilin20187b2a8c32019-03-26 19:52:28 -0700708}
709
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710func (dh *DeviceHandler) activateONU(intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
711 log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
712 dh.flowMgr.UpdateOnuInfo(intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700713 // TODO: need resource manager
714 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700715 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
manikkaraj kbf256be2019-03-25 00:13:48 +0530716 if _, err := dh.Client.ActivateOnu(context.Background(), &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400717 st, _ := status.FromError(err)
718 if st.Code() == codes.AlreadyExists {
719 log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
720 } else {
721 log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
722 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700723 } else {
724 log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
725 }
726}
727
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400728func (dh *DeviceHandler) onuDiscIndication(onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700729 channelID := onuDiscInd.GetIntfId()
730 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400731 if _, ok := dh.discOnus[sn]; ok {
732 log.Debugw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
733 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700734 }
735
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400736 dh.lockDevice.Lock()
737 dh.discOnus[sn] = true
738 dh.lockDevice.Unlock()
739 // evict the onu serial number from local cache
740 defer func() {
741 delete(dh.discOnus, sn)
742 }()
743
cuilin20187b2a8c32019-03-26 19:52:28 -0700744 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400745 if sn != "" {
746 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400747 } else {
748 log.Error("invalid onu serial number")
749 return errors.New("failed to fetch onu serial number")
750 }
751
752 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
753 var onuID uint32
754 if onuDevice == nil || err != nil {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700755 //This is the first time ONU discovered. Create an OnuID for it.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400756 onuID, err = dh.resourceMgr.GetONUID(onuDiscInd.GetIntfId())
757 if err != nil {
758 log.Errorw("failed to fetch onuID from resource manager", log.Fields{"err": err})
759 return err
760 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700761 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400762 "brcm_openomci_onu", int(channelID),
Mahir Gunyele77977b2019-06-27 05:36:22 -0700763 string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); onuDevice == nil {
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400764 log.Errorw("Create onu error",
765 log.Fields{"parent_id": dh.device.Id, "ponPort": onuDiscInd.GetIntfId(),
766 "onuID": onuID, "sn": sn, "error": err})
767 return err
768 }
769
770 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700771 //ONU already discovered before. Use the same OnuID.
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400772 onuID = onuDevice.ProxyAddress.OnuId
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400773 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700774 //Insert the ONU into cache to use in OnuIndication.
775 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
776 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
777 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
Chaitrashree G S35b5d802019-07-08 23:12:03 -0400778
Mahir Gunyele77977b2019-06-27 05:36:22 -0700779 err = dh.coreProxy.DeviceStateUpdate(context.TODO(), onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
780 if err != nil {
781 log.Errorw("failed to update device state", log.Fields{"DeviceID": onuDevice.Id})
782 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700783 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700784 log.Debugw("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id})
785 //TODO: We put this sleep here to prevent the race between state update and onuIndication
786 //In onuIndication the operStatus of device is checked. If it is still not updated in KV store
787 //then the initialisation fails.
788 time.Sleep(1 * time.Second)
789 dh.activateONU(onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
790 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700791}
792
793func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
794 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
795
796 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700797 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -0700798 var onuDevice *voltha.Device
799 foundInCache := false
800 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
801 if onuInCache, ok := dh.onus[onuKey]; ok {
802 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
803 foundInCache = true
804 onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -0700805 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -0700806 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
807 if serialNumber != "" {
808 kwargs["serial_number"] = serialNumber
809 } else {
810 kwargs["onu_id"] = onuInd.OnuId
811 kwargs["parent_port_no"] = ponPort
812 }
813 onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700814 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700815
816 if onuDevice != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400817 if onuDevice.ParentPortNo != ponPort {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818 //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 -0400819 log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
cuilin20187b2a8c32019-03-26 19:52:28 -0700820 }
821
822 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
823 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})
824 }
Mahir Gunyele77977b2019-06-27 05:36:22 -0700825 if !foundInCache {
826 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
827 dh.onus[onuKey] = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
828 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700829 dh.updateOnuStates(onuDevice, onuInd)
cuilin20187b2a8c32019-03-26 19:52:28 -0700830
cuilin20187b2a8c32019-03-26 19:52:28 -0700831 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700832 log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
cuilin20187b2a8c32019-03-26 19:52:28 -0700833 return
834 }
835
836}
837
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700838func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700839 dh.updateOnuAdminState(onuInd)
840 // operState
841 if onuInd.OperState == "down" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700842 log.Debugw("inter-adapter-send-onu-ind", log.Fields{"onuIndication": onuInd})
843
844 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
845 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
846 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
847 if err != nil {
848 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
849 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
850 }
851 } else if onuInd.OperState == "up" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700852 if onuDevice.OperStatus != common.OperStatus_DISCOVERED {
853 log.Warnw("ignore onu indication", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId, "operStatus": onuDevice.OperStatus, "msgOperStatus": onuInd.OperState})
854 return
855 }
856 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
857 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
858 if err != nil {
859 log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
860 "From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
861 return
862 }
863 } else {
864 log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
865 }
866}
867
868func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
869 if onuInd.AdminState == "down" {
870 if onuInd.OperState != "down" {
871 log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
872 // Forcing the oper state change code to execute
873 onuInd.OperState = "down"
874 }
875 // Port and logical port update is taken care of by oper state block
876 } else if onuInd.AdminState == "up" {
877 log.Debugln("received-onu-admin-state up")
878 } else {
879 log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
880 }
881 log.Debugln("admin-state-dealt-with")
882}
883
cuilin20187b2a8c32019-03-26 19:52:28 -0700884func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
885 if serialNum != nil {
886 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -0700887 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700888 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -0700889}
890
891func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
892 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700893 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -0700894 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
895 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
896 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
897 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
898 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
899 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
900 return tmp
901}
902
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700903//UpdateFlowsBulk upates the bulk flow
904func (dh *DeviceHandler) UpdateFlowsBulk() error {
905 return errors.New("unimplemented")
cuilin20187b2a8c32019-03-26 19:52:28 -0700906}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700907
908//GetChildDevice returns the child device for given parent port and onu id
909func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
910 log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400911 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700912 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -0400913 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700914 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400915 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700916 log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400917 return nil
918 }
919 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
920 return onuDevice
manikkaraj kbf256be2019-03-25 00:13:48 +0530921}
922
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700923// SendPacketInToCore sends packet-in to core
924// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
925// The adapter handling the device creates a device specific topic
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400926func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
927 log.Debugw("SendPacketInToCore", log.Fields{"port": logicalPort, "packetPayload": packetPayload})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700928 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400929 log.Errorw("Error sending packetin to core", log.Fields{"error": err})
930 return
931 }
932 log.Debug("Sent packet-in to core successfully")
933}
934
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700935//UpdateFlowsIncrementally updates the device flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530936func (dh *DeviceHandler) UpdateFlowsIncrementally(device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700937 log.Debugw("In Update_flows_incrementally", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400938 if flows != nil {
939 for _, flow := range flows.ToAdd.Items {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400940 log.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400941 dh.flowMgr.AddFlow(flow)
942 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400943 for _, flow := range flows.ToRemove.Items {
944 log.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
945 dh.flowMgr.RemoveFlow(flow)
946 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400947 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700948 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400949 for _, flow := range flows.ToRemove.Items {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950 log.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400951 // dh.flowMgr.RemoveFlow(flow)
952 }
953 }
954 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530955}
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400956
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700957//DisableDevice disables the given device
958//It marks the following for the given device:
959//Device-Handler Admin-State : down
960//Device Port-State: UNKNOWN
961//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400962func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
963 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
964 log.Errorw("Failed to disable olt ", log.Fields{"err": err})
965 return err
966 }
967 dh.lockDevice.Lock()
968 dh.adminState = "down"
969 dh.lockDevice.Unlock()
970 log.Debug("olt-disabled")
971
972 cloned := proto.Clone(device).(*voltha.Device)
973 // Update the all ports state on that device to disable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700974 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
975 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400976 return err
977 }
978
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700979 log.Debugw("Disable_device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400980 return nil
981}
982
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700983//ReenableDevice re-enables the olt device after disable
984//It marks the following for the given device:
985//Device-Handler Admin-State : up
986//Device Port-State: ACTIVE
987//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400988func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
989 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
990 log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
991 return err
992 }
993
994 dh.lockDevice.Lock()
995 dh.adminState = "up"
996 dh.lockDevice.Unlock()
997 log.Debug("olt-reenabled")
998
999 cloned := proto.Clone(device).(*voltha.Device)
1000 // Update the all ports state on that device to enable
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001001 if err := dh.coreProxy.PortsStateUpdate(context.TODO(), cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
1002 log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001003 return err
1004 }
1005
1006 //Update the device oper status as ACTIVE
1007 cloned.OperStatus = voltha.OperStatus_ACTIVE
1008 dh.device = cloned
1009
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001010 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1011 log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001012 return err
1013 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014 log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001015
1016 return nil
1017}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001018
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001019//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001020func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1021 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
1022 log.Errorw("Failed to reboot olt ", log.Fields{"err": err})
1023 return err
1024 }
1025
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001026 log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001027
1028 return nil
1029}
1030
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001031func (dh *DeviceHandler) handlePacketIndication(packetIn *oop.PacketIndication) {
1032 log.Debugw("Received packet-in", log.Fields{"packet-indication": *packetIn})
1033 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(packetIn)
1034 if err != nil {
1035 log.Errorw("Error getting logical port from packet-in", log.Fields{"error": err})
1036 return
1037 }
1038 log.Debugw("sending packet-in to core", log.Fields{"logicalPortNum": logicalPortNum, "packet": *packetIn})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001039 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001040 log.Errorw("Error sending packet-in to core", log.Fields{"error": err})
1041 return
1042 }
1043 log.Debug("Success sending packet-in to core!")
1044}
1045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001046// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
1047func (dh *DeviceHandler) PacketOut(egressPortNo int, packet *of.OfpPacketOut) error {
1048 log.Debugw("PacketOut", log.Fields{"deviceID": dh.deviceID, "egress_port_no": egressPortNo, "pkt-length": len(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001049 var etherFrame ethernet.Frame
1050 err := (&etherFrame).UnmarshalBinary(packet.Data)
1051 if err != nil {
1052 log.Errorw("Failed to unmarshal into ethernet frame", log.Fields{"err": err, "pkt-length": len(packet.Data)})
1053 return err
1054 }
1055 log.Debugw("Ethernet Frame", log.Fields{"Frame": etherFrame})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001056 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001057 if egressPortType == voltha.Port_ETHERNET_UNI {
1058 if etherFrame.VLAN != nil { // If double tag, remove the outer tag
1059 nextEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
1060 if nextEthType == 0x8100 {
1061 etherFrame.VLAN = nil
1062 packet.Data, err = etherFrame.MarshalBinary()
1063 if err != nil {
1064 log.Fatalf("failed to marshal frame: %v", err)
1065 return err
1066 }
1067 if err := (&etherFrame).UnmarshalBinary(packet.Data); err != nil {
1068 log.Fatalf("failed to unmarshal frame: %v", err)
1069 return err
1070 }
1071 log.Debug("Double tagged packet , removed outer vlan", log.Fields{"New frame": etherFrame})
1072 }
1073 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001074 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1075 onuID := OnuIDFromPortNum(uint32(egressPortNo))
1076 uniID := UniIDFromPortNum(uint32(egressPortNo))
1077 /*gemPortId, err := dh.flowMgr.GetPacketOutGemPortId(intfID, onuID, uint32(egress_port_no))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001078 if err != nil{
1079 log.Errorw("Error while getting gemport to packet-out",log.Fields{"error": err})
1080 return err
1081 }*/
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001082 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), Pkt: packet.Data}
1083 log.Debug("sending-packet-to-ONU", log.Fields{"egress_port_no": egressPortNo, "IntfId": intfID, "onuID": onuID,
1084 "uniID": uniID, "packet": packet.Data})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001085 if _, err := dh.Client.OnuPacketOut(context.Background(), &onuPkt); err != nil {
1086 log.Errorw("Error while sending packet-out to ONU", log.Fields{"error": err})
1087 return err
1088 }
1089 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001090 uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001091 log.Debug("sending-packet-to-uplink", log.Fields{"uplink_pkt": uplinkPkt})
1092 if _, err := dh.Client.UplinkPacketOut(context.Background(), &uplinkPkt); err != nil {
1093 log.Errorw("Error while sending packet-out to uplink", log.Fields{"error": err})
1094 return err
1095 }
1096 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001097 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 -04001098 }
1099 return nil
1100}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001101
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001102func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1103 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001104}