blob: fba1f68c7890661b967bf7a806721bf9406f58de [file] [log] [blame]
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -05001#
2# Copyright 2017 the original author or authors.
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#
16
17"""
18Broadcom OpenOMCI OLT/ONU adapter.
19
20This adapter does NOT support XPON
21"""
22
Matt Jeanneret2e3cb8d2019-11-16 09:22:41 -050023from __future__ import absolute_import
24import structlog
25from twisted.internet import reactor
William Kurkian3a206332019-04-29 11:05:47 -040026from twisted.internet.defer import inlineCallbacks
27
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050028from zope.interface import implementer
29
Matt Jeanneret72f96fc2019-02-11 10:53:05 -050030from pyvoltha.adapters.interface import IAdapterInterface
William Kurkian8235c1e2019-03-05 12:58:28 -050031from voltha_protos.adapter_pb2 import Adapter
32from voltha_protos.adapter_pb2 import AdapterConfig
Matt Jeanneret2e3cb8d2019-11-16 09:22:41 -050033from voltha_protos.device_pb2 import DeviceType, DeviceTypes
William Kurkian8235c1e2019-03-05 12:58:28 -050034from voltha_protos.health_pb2 import HealthStatus
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050035
Matt Jeanneret72f96fc2019-02-11 10:53:05 -050036from pyvoltha.adapters.common.frameio.frameio import hexify
37from pyvoltha.adapters.extensions.omci.openomci_agent import OpenOMCIAgent, OpenOmciAgentDefaults
Matt Jeanneret98f99dc2019-09-25 11:05:25 -040038from pyvoltha.adapters.extensions.omci.database.mib_db_dict import MibDbVolatileDict
Matt Jeanneret5e331892019-12-07 21:31:45 -050039from pyvoltha.adapters.extensions.omci.database.mib_db_dict_lazy import MibDbLazyWriteDict
Matt Jeanneret72f96fc2019-02-11 10:53:05 -050040
41from brcm_openomci_onu_handler import BrcmOpenomciOnuHandler
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050042from omci.brcm_capabilities_task import BrcmCapabilitiesTask
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050043from copy import deepcopy
44
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050045
46@implementer(IAdapterInterface)
47class BrcmOpenomciOnuAdapter(object):
48
49 name = 'brcm_openomci_onu'
50
51 supported_device_types = [
52 DeviceType(
53 id=name,
Mahir Gunyeld680cb62020-02-18 10:28:12 -080054 vendor_ids=['OPEN', 'ALCL', 'BRCM', 'TWSH', 'ALPH', 'ISKT', 'SFAA', 'BBSM', 'SCOM', 'ARPX', 'DACM', 'ERSN', 'HWTC', 'CIGG'],
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050055 adapter=name,
Mahir Gunyel9dfab822020-02-20 15:52:15 -080056 accepts_bulk_flow_update=False,
57 accepts_add_remove_flow_updates=True
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050058 )
59 ]
60
Matt Jeanneret08a8e862019-12-20 14:02:32 -050061 def __init__(self, core_proxy, adapter_proxy, config, build_info):
62 self.log = structlog.get_logger()
63 self.log.debug('starting-adapter', config=config)
64
Matt Jeannereta32441c2019-03-07 05:16:37 -050065 self.core_proxy = core_proxy
Matt Jeanneret0bd63c82019-02-15 05:40:44 -050066 self.adapter_proxy = adapter_proxy
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050067 self.config = config
68 self.descriptor = Adapter(
69 id=self.name,
Matt Jeanneret08a8e862019-12-20 14:02:32 -050070 vendor='VOLTHA OpenONU',
71 version=build_info.version,
Rohan Agrawalb744d102020-03-06 07:52:46 +000072 config=AdapterConfig()
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050073 )
74 self.devices_handlers = dict()
Matt Jeanneret21363202019-02-13 16:21:48 -050075 self.device_handler_class = BrcmOpenomciOnuHandler
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050076
77 # Customize OpenOMCI for Broadcom ONUs
78 self.broadcom_omci = deepcopy(OpenOmciAgentDefaults)
79
Matt Jeanneretde16ed52019-09-18 19:05:15 -040080 self.broadcom_omci['mib-synchronizer']['audit-delay'] = 0 # disable audits as brcm onu wont upload once provisioned
Matt Jeanneret5e331892019-12-07 21:31:45 -050081 self.broadcom_omci['mib-synchronizer']['database'] = MibDbLazyWriteDict
Matt Jeanneret98f99dc2019-09-25 11:05:25 -040082 self.broadcom_omci['alarm-synchronizer']['database'] = MibDbVolatileDict
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050083 self.broadcom_omci['omci-capabilities']['tasks']['get-capabilities'] = BrcmCapabilitiesTask
84
85 # Defer creation of omci agent to a lazy init that allows subclasses to override support classes
86
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050087 def custom_me_entities(self):
88 return None
89
90 @property
91 def omci_agent(self):
92 if not hasattr(self, '_omci_agent') or self._omci_agent is None:
Matt Jeanneret08a8e862019-12-20 14:02:32 -050093 self.log.debug('creating-omci-agent')
Matt Jeannereta32441c2019-03-07 05:16:37 -050094 self._omci_agent = OpenOMCIAgent(self.core_proxy,
95 self.adapter_proxy,
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050096 support_classes=self.broadcom_omci)
97 return self._omci_agent
98
99 def start(self):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500100 self.log.debug('starting')
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500101 self.omci_agent.start()
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500102 self.log.info('started')
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500103
104 def stop(self):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500105 self.log.debug('stopping')
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500106
107 omci, self._omci_agent = self._omci_agent, None
108 if omci is not None:
109 self._omci_agent.stop()
110
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500111 self.log.info('stopped')
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500112
113 def adapter_descriptor(self):
114 return self.descriptor
115
116 def device_types(self):
117 return DeviceTypes(items=self.supported_device_types)
118
119 def health(self):
120 return HealthStatus(state=HealthStatus.HealthState.HEALTHY)
121
122 def change_master_state(self, master):
123 raise NotImplementedError()
124
125 def adopt_device(self, device):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500126 self.log.info('adopt-device', device_id=device.id)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500127 self.devices_handlers[device.id] = BrcmOpenomciOnuHandler(self, device.id)
128 reactor.callLater(0, self.devices_handlers[device.id].activate, device)
129 return device
130
131 def reconcile_device(self, device):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500132 self.log.info('reconcile-device', device_id=device.id)
Matt Jeanneret5e331892019-12-07 21:31:45 -0500133 if not device.id in self.devices_handlers:
134 self.devices_handlers[device.id] = BrcmOpenomciOnuHandler(self, device.id)
135 reactor.callLater(0, self.devices_handlers[device.id].reconcile, device)
136 else:
137 self.log.debug('already-called-reconcile-device', device_id=device.id)
138 return device
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500139
140 def abandon_device(self, device):
141 raise NotImplementedError()
142
143 def disable_device(self, device):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500144 self.log.info('disable-onu-device', device_id=device.id)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500145 if device.id in self.devices_handlers:
146 handler = self.devices_handlers[device.id]
147 if handler is not None:
148 handler.disable(device)
149
150 def reenable_device(self, device):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500151 self.log.info('reenable-onu-device', device_id=device.id)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500152 if device.id in self.devices_handlers:
153 handler = self.devices_handlers[device.id]
154 if handler is not None:
155 handler.reenable(device)
156
157 def reboot_device(self, device):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500158 self.log.info('reboot-device', device_id=device.id)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500159 if device.id in self.devices_handlers:
160 handler = self.devices_handlers[device.id]
161 if handler is not None:
162 handler.reboot()
163
164 def download_image(self, device, request):
165 raise NotImplementedError()
166
167 def get_image_download_status(self, device, request):
168 raise NotImplementedError()
169
170 def cancel_image_download(self, device, request):
171 raise NotImplementedError()
172
173 def activate_image_update(self, device, request):
174 raise NotImplementedError()
175
176 def revert_image_update(self, device, request):
177 raise NotImplementedError()
178
kesavand54959a32020-01-20 18:52:42 +0530179 def enable_port(self, device_id, port):
180 raise NotImplementedError()
181
182 def disable_port(self, device_id, port):
183 raise NotImplementedError()
184
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500185 def self_test_device(self, device):
186 """
187 This is called to Self a device based on a NBI call.
188 :param device: A Voltha.Device object.
189 :return: Will return result of self test
190 """
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500191 self.log.info('self-test-device - Not implemented yet', device_id=device.id, serial_number=device.serial_number)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500192 raise NotImplementedError()
193
194 def delete_device(self, device):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500195 self.log.info('delete-device', device_id=device.id)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500196 if device.id in self.devices_handlers:
197 handler = self.devices_handlers[device.id]
198 if handler is not None:
199 handler.delete(device)
200 del self.devices_handlers[device.id]
201 return
202
203 def get_device_details(self, device):
204 raise NotImplementedError()
205
206 # TODO(smbaker): When BrcmOpenomciOnuAdapter is updated to inherit from OnuAdapter, this function can be deleted
207 def update_pm_config(self, device, pm_config):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500208 self.log.info("adapter-update-pm-config", device_id=device.id, serial_number=device.serial_number,
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500209 pm_config=pm_config)
210 handler = self.devices_handlers[device.id]
211 handler.update_pm_config(device, pm_config)
212
213 def update_flows_bulk(self, device, flows, groups):
214 '''
215 log.info('bulk-flow-update', device_id=device.id,
216 flows=flows, groups=groups)
217 '''
218 assert len(groups.items) == 0
219 handler = self.devices_handlers[device.id]
220 return handler.update_flow_table(device, flows.items)
221
222 def update_flows_incrementally(self, device, flow_changes, group_changes):
Mahir Gunyeld680cb62020-02-18 10:28:12 -0800223 self.log.info('incremental-flow-update', device_id=device.id,
224 flows=flow_changes, groups=group_changes)
225 # For now, there is no support for group changes
226 assert len(group_changes.to_add.items) == 0
227 assert len(group_changes.to_remove.items) == 0
228
229 handler = self.devices_handlers[device.id]
230 # Remove flows
231 if len(flow_changes.to_remove.items) != 0:
232 handler.remove_onu_flows(device, flow_changes.to_remove.items)
233
234 # Add flows
235 if len(flow_changes.to_add.items) != 0:
236 handler.add_onu_flows(device, flow_changes.to_add.items)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500237
238 def send_proxied_message(self, proxy_address, msg):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500239 self.log.debug('send-proxied-message', proxy_address=proxy_address, msg=msg)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500240
William Kurkian3a206332019-04-29 11:05:47 -0400241 @inlineCallbacks
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500242 def receive_proxied_message(self, proxy_address, msg):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500243 self.log.debug('receive-proxied-message', proxy_address=proxy_address,
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500244 device_id=proxy_address.device_id, msg=hexify(msg))
245 # Device_id from the proxy_address is the olt device id. We need to
246 # get the onu device id using the port number in the proxy_address
William Kurkian3a206332019-04-29 11:05:47 -0400247 device = self.core_proxy. \
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500248 get_child_device_with_proxy_address(proxy_address)
249 if device:
250 handler = self.devices_handlers[device.id]
251 handler.receive_message(msg)
252
253 def receive_packet_out(self, logical_device_id, egress_port_no, msg):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500254 self.log.debug('packet-out', logical_device_id=logical_device_id,
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500255 egress_port_no=egress_port_no, msg_len=len(msg))
256
William Kurkian3a206332019-04-29 11:05:47 -0400257 @inlineCallbacks
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500258 def receive_inter_adapter_message(self, msg):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500259 self.log.debug('receive-inter-adapter-message', msg=msg)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500260 proxy_address = msg['proxy_address']
261 assert proxy_address is not None
262 # Device_id from the proxy_address is the olt device id. We need to
263 # get the onu device id using the port number in the proxy_address
William Kurkian3a206332019-04-29 11:05:47 -0400264 device = self.core_proxy. \
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500265 get_child_device_with_proxy_address(proxy_address)
266 if device:
267 handler = self.devices_handlers[device.id]
268 handler.event_messages.put(msg)
269 else:
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500270 self.log.error("device-not-found")
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500271
Matt Jeanneretc083f462019-03-11 15:02:01 -0400272 def get_ofp_port_info(self, device, port_no):
273 ofp_port_info = self.devices_handlers[device.id].get_ofp_port_info(device, port_no)
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500274 self.log.debug('get-ofp-port-info', device_id=device.id,
Matteo Scandolod8d73172019-11-26 12:15:15 -0700275 port_name=ofp_port_info.port.ofp_port.name, port_no=ofp_port_info.port.device_port_no)
Matt Jeanneretc083f462019-03-11 15:02:01 -0400276 return ofp_port_info
277
Matt Jeannereta32441c2019-03-07 05:16:37 -0500278 def process_inter_adapter_message(self, msg):
Matt Jeannereta32441c2019-03-07 05:16:37 -0500279 # Unpack the header to know which device needs to handle this message
280 if msg.header:
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500281 self.log.debug('process-inter-adapter-message', type=msg.header.type, from_topic=msg.header.from_topic,
Matteo Scandolod8d73172019-11-26 12:15:15 -0700282 to_topic=msg.header.to_topic, to_device_id=msg.header.to_device_id)
Matt Jeannereta32441c2019-03-07 05:16:37 -0500283 handler = self.devices_handlers[msg.header.to_device_id]
284 handler.process_inter_adapter_message(msg)
onkarkundargia1e2af22020-01-27 11:51:43 +0530285
286 def start_omci_test(self, device, uuid):
287 """
288
289 :param device:
290 :return:
291 """
292 self.log.info('Omci-test-action-request-On', request=device)
293 handler = self.devices_handlers[device.id]
294 result = handler.start_omci_test_action(device, uuid)
295 return result