blob: 22ecc1a72f581eaff4d2400eeab5c5ea9d8908dc [file] [log] [blame]
Scott Baker2d897982019-09-24 11:50:08 -07001/*
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 */
16package adaptercore
17
18import (
19 "context"
20 "fmt"
21 "github.com/gogo/protobuf/proto"
Scott Bakerb61e3332019-10-24 13:36:06 -070022 com "github.com/opencord/voltha-lib-go/v2/pkg/adapters/common"
23 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Scott Bakerc3337a52019-11-04 09:24:30 -080024 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
25 of "github.com/opencord/voltha-protos/v2/go/openflow_13"
26 "github.com/opencord/voltha-protos/v2/go/voltha"
Scott Baker2d897982019-09-24 11:50:08 -070027 "strconv"
28 "strings"
29 "sync"
30)
31
32// A set of pm names to create the initial pm config. This is used only for testing in this simulated adapter
33var pmNames = []string{
34 "tx_64_pkts",
35 "tx_65_127_pkts",
36 "tx_128_255_pkts",
37 "tx_256_511_pkts",
38 "tx_512_1023_pkts",
39 "tx_1024_1518_pkts",
40 "tx_1519_9k_pkts",
41 "rx_64_pkts",
42 "rx_65_127_pkts",
43 "rx_128_255_pkts",
44 "rx_256_511_pkts",
45 "rx_512_1023_pkts",
46 "rx_1024_1518_pkts",
47 "rx_1519_9k_pkts",
48}
49
50//DeviceHandler follows the same patterns as ponsim_olt. The only difference is that it does not
51// interact with an OLT device.
52type DeviceHandler struct {
53 deviceId string
54 deviceType string
55 device *voltha.Device
56 coreProxy *com.CoreProxy
57 simulatedOLT *SimulatedOLT
58 nniPort *voltha.Port
59 ponPort *voltha.Port
60 exitChannel chan int
61 lockDevice sync.RWMutex
62 metrics *com.PmMetrics
63}
64
65//NewDeviceHandler creates a new device handler
66func NewDeviceHandler(cp *com.CoreProxy, device *voltha.Device, adapter *SimulatedOLT) *DeviceHandler {
67 var dh DeviceHandler
68 dh.coreProxy = cp
69 cloned := (proto.Clone(device)).(*voltha.Device)
70 dh.deviceId = cloned.Id
71 dh.deviceType = cloned.Type
72 dh.device = cloned
73 dh.simulatedOLT = adapter
74 dh.exitChannel = make(chan int, 1)
75 dh.lockDevice = sync.RWMutex{}
76 // Set up PON metrics
77 dh.metrics = com.NewPmMetrics(
78 cloned.Id,
79 com.Frequency(150),
80 com.Grouped(false),
81 com.FrequencyOverride(false),
82 com.Metrics(pmNames),
83 )
84 return &dh
85}
86
87// start save the device to the data model
88func (dh *DeviceHandler) start(ctx context.Context) {
89 dh.lockDevice.Lock()
90 defer dh.lockDevice.Unlock()
91 log.Debugw("starting-device-agent", log.Fields{"device": dh.device})
92 // Add the initial device to the local model
93 log.Debug("device-agent-started")
94}
95
96// stop stops the device dh. Not much to do for now
97func (dh *DeviceHandler) stop(ctx context.Context) {
98 dh.lockDevice.Lock()
99 defer dh.lockDevice.Unlock()
100 log.Debug("stopping-device-agent")
101 dh.exitChannel <- 1
102 log.Debug("device-agent-stopped")
103}
104
105func macAddressToUint32Array(mac string) []uint32 {
106 slist := strings.Split(mac, ":")
107 result := make([]uint32, len(slist))
108 var err error
109 var tmp int64
110 for index, val := range slist {
111 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
112 return []uint32{1, 2, 3, 4, 5, 6}
113 }
114 result[index] = uint32(tmp)
115 }
116 return result
117}
118
119func (dh *DeviceHandler) AdoptDevice(device *voltha.Device) {
120 log.Debugw("AdoptDevice", log.Fields{"deviceId": device.Id})
121
122 // Update the device info
123 cloned := proto.Clone(device).(*voltha.Device)
124 cloned.Root = true
125 cloned.Vendor = "simulators"
126 cloned.Model = "go-simulators"
127 cloned.SerialNumber = com.GetRandomSerialNumber()
128 cloned.MacAddress = strings.ToUpper(com.GetRandomMacAddress())
129
130 // Synchronous call to update device - this method is run in its own go routine
131 if err := dh.coreProxy.DeviceUpdate(nil, cloned); err != nil {
132 log.Errorw("error-updating-device", log.Fields{"deviceId": device.Id, "error": err})
133 }
134
135 // Now, set the initial PM configuration for that device
136 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
137 log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
138 }
139
140 // Now create the NNI Port
141 dh.nniPort = &voltha.Port{
142 PortNo: 2,
143 Label: fmt.Sprintf("nni-%d", 2),
144 Type: voltha.Port_ETHERNET_NNI,
145 OperStatus: voltha.OperStatus_ACTIVE,
146 }
147
148 // Synchronous call to update device - this method is run in its own go routine
149 if err := dh.coreProxy.PortCreated(nil, cloned.Id, dh.nniPort); err != nil {
150 log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
151 }
152
153 // Now create the PON Port
154 dh.ponPort = &voltha.Port{
155 PortNo: 1,
156 Label: fmt.Sprintf("pon-%d", 1),
157 Type: voltha.Port_PON_OLT,
158 OperStatus: voltha.OperStatus_ACTIVE,
159 }
160
161 // Synchronous call to update device - this method is run in its own go routine
162 if err := dh.coreProxy.PortCreated(nil, cloned.Id, dh.ponPort); err != nil {
163 log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
164 }
165
166 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
167 cloned.OperStatus = voltha.OperStatus_ACTIVE
168
169 dh.device = cloned
170 //dh.device.SerialNumber = cloned.SerialNumber
171
172 // Update the device state
173 if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
174 log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
175 }
176
177 // Register Child device
178 initialUniPortNo := 100
179 log.Debugw("registering-onus", log.Fields{"total": dh.simulatedOLT.numOnus})
180 for i := 0; i < dh.simulatedOLT.numOnus; i++ {
181 go dh.coreProxy.ChildDeviceDetected(
182 nil,
183 cloned.Id,
184 1,
185 "simulated_onu",
186 initialUniPortNo+i,
187 "simulated_onu",
188 com.GetRandomSerialNumber(),
189 int64(i))
190 }
191}
192
193func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
194 return &ic.SwitchCapability{
195 Desc: &of.OfpDesc{
196 HwDesc: "simulated_pon",
197 SwDesc: "simulated_pon",
198 SerialNum: dh.device.SerialNumber,
199 },
200 SwitchFeatures: &of.OfpSwitchFeatures{
201 NBuffers: 256,
202 NTables: 2,
203 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
204 of.OfpCapabilities_OFPC_TABLE_STATS |
205 of.OfpCapabilities_OFPC_PORT_STATS |
206 of.OfpCapabilities_OFPC_GROUP_STATS),
207 },
208 }, nil
209}
210
211func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
212 cap := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
213 return &ic.PortCapability{
214 Port: &voltha.LogicalPort{
215 OfpPort: &of.OfpPort{
216 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
217 Config: 0,
218 State: uint32(of.OfpPortState_OFPPS_LIVE),
219 Curr: cap,
220 Advertised: cap,
221 Peer: cap,
222 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
223 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
224 },
225 DeviceId: dh.device.Id,
226 DevicePortNo: uint32(portNo),
227 },
228 }, nil
229}
230
231func (dh *DeviceHandler) Process_inter_adapter_message(msg *ic.InterAdapterMessage) error {
232 log.Debugw("Process_inter_adapter_message", log.Fields{"msgId": msg.Header.Id})
233 return nil
234}
235
236func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
237 cloned := proto.Clone(device).(*voltha.Device)
238 // Update the all ports state on that device to disable
239 if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
240 log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
241 return
242 }
243
244 //Update the device state
245 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
246 cloned.OperStatus = voltha.OperStatus_UNKNOWN
247 dh.device = cloned
248
249 if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
250 log.Errorw("device-state-update-failed", log.Fields{"deviceId": device.Id, "error": err})
251 return
252 }
253
254 // Tell the Core that all child devices have been disabled (by default it's an action already taken by the Core
255 if err := dh.coreProxy.ChildDevicesLost(nil, cloned.Id); err != nil {
256 log.Errorw("lost-notif-of-child-devices-failed", log.Fields{"deviceId": device.Id, "error": err})
257 return
258 }
259
260 log.Debugw("DisableDevice-end", log.Fields{"deviceId": device.Id})
261}
262
263func (dh *DeviceHandler) ReEnableDevice(device *voltha.Device) {
264
265 cloned := proto.Clone(device).(*voltha.Device)
266 // Update the all ports state on that device to enable
267 if err := dh.coreProxy.PortsStateUpdate(nil, cloned.Id, voltha.OperStatus_ACTIVE); err != nil {
268 log.Errorw("updating-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
269 return
270 }
271
272 //Update the device state
273 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
274 cloned.OperStatus = voltha.OperStatus_ACTIVE
275 dh.device = cloned
276
277 if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
278 log.Errorw("device-state-update-failed", log.Fields{"deviceId": device.Id, "error": err})
279 return
280 }
281
282 // Tell the Core that all child devices have been enabled
283 if err := dh.coreProxy.ChildDevicesDetected(nil, cloned.Id); err != nil {
284 log.Errorw("detection-notif-of-child-devices-failed", log.Fields{"deviceId": device.Id, "error": err})
285 return
286 }
287
288 log.Debugw("ReEnableDevice-end", log.Fields{"deviceId": device.Id})
289}
290
291func (dh *DeviceHandler) DeleteDevice(device *voltha.Device) {
292 cloned := proto.Clone(device).(*voltha.Device)
293 // Update the all ports state on that device to disable
294 if err := dh.coreProxy.DeleteAllPorts(nil, cloned.Id); err != nil {
295 log.Errorw("delete-ports-failed", log.Fields{"deviceId": device.Id, "error": err})
296 return
297 }
298
299 log.Debugw("DeleteDevice-end", log.Fields{"deviceId": device.Id})
300}
301
302func (dh *DeviceHandler) UpdateFlowsBulk(device *voltha.Device, flows *voltha.Flows, groups *voltha.FlowGroups, metadata *voltha.FlowMetadata) {
303 log.Debugw("UpdateFlowsBulk", log.Fields{"deviceId": device.Id, "flows": flows, "groups": groups})
304 // For now we do nothing with it
305 return
306}
307
308func (dh *DeviceHandler) UpdateFlowsIncremental(device *voltha.Device, flowChanges *of.FlowChanges, groupChanges *of.FlowGroupChanges, metadata *voltha.FlowMetadata) {
309 log.Debugw("UpdateFlowsIncremental", log.Fields{"deviceId": device.Id, "flowChanges": flowChanges, "groupChanges": groupChanges})
310 // For now we do nothing with it
311 return
312}
313
314func (dh *DeviceHandler) UpdatePmConfigs(device *voltha.Device, pmConfigs *voltha.PmConfigs) {
315 log.Debugw("UpdatePmConfigs", log.Fields{"deviceId": device.Id, "pmConfigs": pmConfigs})
316 // For now we do nothing with it
317 return
318}
319
320func (dh *DeviceHandler) ReconcileDevice(device *voltha.Device) {
321 // Update the device info
322 cloned := proto.Clone(device).(*voltha.Device)
323 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
324 cloned.OperStatus = voltha.OperStatus_ACTIVE
325
326 dh.device = cloned
327
328 // Update the device state
329 if err := dh.coreProxy.DeviceStateUpdate(nil, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
330 log.Errorw("error-creating-nni-port", log.Fields{"deviceId": device.Id, "error": err})
331 }
332
333 // Since we don't know how long we were down, let's reconcile the child devices
334 go dh.coreProxy.ReconcileChildDevices(nil, cloned.Id)
335}