blob: ca02767c4dbe280c825eafe6cc4dcf0bef0db8cb [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
23from twisted.internet import reactor, task
William Kurkian3a206332019-04-29 11:05:47 -040024from twisted.internet.defer import inlineCallbacks
25
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050026from zope.interface import implementer
27
Matt Jeanneret72f96fc2019-02-11 10:53:05 -050028from pyvoltha.adapters.interface import IAdapterInterface
Matt Jeanneret21363202019-02-13 16:21:48 -050029from pyvoltha.adapters.iadapter import OnuAdapter
William Kurkian8235c1e2019-03-05 12:58:28 -050030from voltha_protos.adapter_pb2 import Adapter
31from voltha_protos.adapter_pb2 import AdapterConfig
32from voltha_protos.common_pb2 import LogLevel
33from voltha_protos.device_pb2 import DeviceType, DeviceTypes, Port, Image
34from 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
38from pyvoltha.adapters.extensions.omci.omci_me import *
William Kurkian602f84c2019-07-31 16:25:28 -040039from pyvoltha.adapters.extensions.omci.database.mib_db_ext import MibDbExternal
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 omci.brcm_mib_sync import BrcmMibSynchronizer
44from copy import deepcopy
45
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050046log = structlog.get_logger()
47
48
49@implementer(IAdapterInterface)
50class BrcmOpenomciOnuAdapter(object):
51
52 name = 'brcm_openomci_onu'
53
54 supported_device_types = [
55 DeviceType(
56 id=name,
57 vendor_ids=['OPEN', 'ALCL', 'BRCM', 'TWSH', 'ALPH', 'ISKT', 'SFAA', 'BBSM'],
58 adapter=name,
59 accepts_bulk_flow_update=True
60 )
61 ]
62
Matt Jeanneret21363202019-02-13 16:21:48 -050063 def __init__(self, core_proxy, adapter_proxy, config):
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050064 log.debug('function-entry', config=config)
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,
70 vendor='Voltha project',
Matt Jeanneret21363202019-02-13 16:21:48 -050071 version='2.0',
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050072 config=AdapterConfig(log_level=LogLevel.INFO)
73 )
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
80 self.broadcom_omci['mib-synchronizer']['state-machine'] = BrcmMibSynchronizer
William Kurkian602f84c2019-07-31 16:25:28 -040081 self.broadcom_omci['mib-synchronizer']['database'] = MibDbExternal
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050082 self.broadcom_omci['omci-capabilities']['tasks']['get-capabilities'] = BrcmCapabilitiesTask
83
84 # Defer creation of omci agent to a lazy init that allows subclasses to override support classes
85
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050086 def custom_me_entities(self):
87 return None
88
89 @property
90 def omci_agent(self):
91 if not hasattr(self, '_omci_agent') or self._omci_agent is None:
92 log.debug('creating-omci-agent')
Matt Jeannereta32441c2019-03-07 05:16:37 -050093 self._omci_agent = OpenOMCIAgent(self.core_proxy,
94 self.adapter_proxy,
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050095 support_classes=self.broadcom_omci)
96 return self._omci_agent
97
98 def start(self):
99 log.debug('starting')
100 self.omci_agent.start()
101 log.info('started')
102
103 def stop(self):
104 log.debug('stopping')
105
106 omci, self._omci_agent = self._omci_agent, None
107 if omci is not None:
108 self._omci_agent.stop()
109
110 log.info('stopped')
111
112 def adapter_descriptor(self):
113 return self.descriptor
114
115 def device_types(self):
116 return DeviceTypes(items=self.supported_device_types)
117
118 def health(self):
119 return HealthStatus(state=HealthStatus.HealthState.HEALTHY)
120
121 def change_master_state(self, master):
122 raise NotImplementedError()
123
124 def adopt_device(self, device):
125 log.info('adopt_device', device_id=device.id)
126 self.devices_handlers[device.id] = BrcmOpenomciOnuHandler(self, device.id)
127 reactor.callLater(0, self.devices_handlers[device.id].activate, device)
128 return device
129
130 def reconcile_device(self, device):
131 log.info('reconcile-device', device_id=device.id)
132 self.devices_handlers[device.id] = BrcmOpenomciOnuHandler(self, device.id)
133 reactor.callLater(0, self.devices_handlers[device.id].reconcile, device)
134
135 def abandon_device(self, device):
136 raise NotImplementedError()
137
138 def disable_device(self, device):
139 log.info('disable-onu-device', device_id=device.id)
140 if device.id in self.devices_handlers:
141 handler = self.devices_handlers[device.id]
142 if handler is not None:
143 handler.disable(device)
144
145 def reenable_device(self, device):
146 log.info('reenable-onu-device', device_id=device.id)
147 if device.id in self.devices_handlers:
148 handler = self.devices_handlers[device.id]
149 if handler is not None:
150 handler.reenable(device)
151
152 def reboot_device(self, device):
153 log.info('reboot-device', device_id=device.id)
154 if device.id in self.devices_handlers:
155 handler = self.devices_handlers[device.id]
156 if handler is not None:
157 handler.reboot()
158
159 def download_image(self, device, request):
160 raise NotImplementedError()
161
162 def get_image_download_status(self, device, request):
163 raise NotImplementedError()
164
165 def cancel_image_download(self, device, request):
166 raise NotImplementedError()
167
168 def activate_image_update(self, device, request):
169 raise NotImplementedError()
170
171 def revert_image_update(self, device, request):
172 raise NotImplementedError()
173
174 def self_test_device(self, device):
175 """
176 This is called to Self a device based on a NBI call.
177 :param device: A Voltha.Device object.
178 :return: Will return result of self test
179 """
180 log.info('self-test-device - Not implemented yet', device=device.id)
181 raise NotImplementedError()
182
183 def delete_device(self, device):
184 log.info('delete-device', device_id=device.id)
185 if device.id in self.devices_handlers:
186 handler = self.devices_handlers[device.id]
187 if handler is not None:
188 handler.delete(device)
189 del self.devices_handlers[device.id]
190 return
191
192 def get_device_details(self, device):
193 raise NotImplementedError()
194
195 # TODO(smbaker): When BrcmOpenomciOnuAdapter is updated to inherit from OnuAdapter, this function can be deleted
196 def update_pm_config(self, device, pm_config):
197 log.info("adapter-update-pm-config", device=device,
198 pm_config=pm_config)
199 handler = self.devices_handlers[device.id]
200 handler.update_pm_config(device, pm_config)
201
202 def update_flows_bulk(self, device, flows, groups):
203 '''
204 log.info('bulk-flow-update', device_id=device.id,
205 flows=flows, groups=groups)
206 '''
207 assert len(groups.items) == 0
208 handler = self.devices_handlers[device.id]
209 return handler.update_flow_table(device, flows.items)
210
211 def update_flows_incrementally(self, device, flow_changes, group_changes):
212 raise NotImplementedError()
213
214 def send_proxied_message(self, proxy_address, msg):
215 log.debug('send-proxied-message', proxy_address=proxy_address, msg=msg)
216
William Kurkian3a206332019-04-29 11:05:47 -0400217 @inlineCallbacks
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500218 def receive_proxied_message(self, proxy_address, msg):
219 log.debug('receive-proxied-message', proxy_address=proxy_address,
220 device_id=proxy_address.device_id, msg=hexify(msg))
221 # Device_id from the proxy_address is the olt device id. We need to
222 # get the onu device id using the port number in the proxy_address
William Kurkian3a206332019-04-29 11:05:47 -0400223 device = self.core_proxy. \
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500224 get_child_device_with_proxy_address(proxy_address)
225 if device:
226 handler = self.devices_handlers[device.id]
227 handler.receive_message(msg)
228
229 def receive_packet_out(self, logical_device_id, egress_port_no, msg):
230 log.info('packet-out', logical_device_id=logical_device_id,
231 egress_port_no=egress_port_no, msg_len=len(msg))
232
William Kurkian3a206332019-04-29 11:05:47 -0400233 @inlineCallbacks
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500234 def receive_inter_adapter_message(self, msg):
235 log.debug('receive_inter_adapter_message', msg=msg)
236 proxy_address = msg['proxy_address']
237 assert proxy_address is not None
238 # Device_id from the proxy_address is the olt device id. We need to
239 # get the onu device id using the port number in the proxy_address
William Kurkian3a206332019-04-29 11:05:47 -0400240 device = self.core_proxy. \
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500241 get_child_device_with_proxy_address(proxy_address)
242 if device:
243 handler = self.devices_handlers[device.id]
244 handler.event_messages.put(msg)
245 else:
246 log.error("device-not-found")
247
Matt Jeanneretc083f462019-03-11 15:02:01 -0400248 def get_ofp_port_info(self, device, port_no):
249 ofp_port_info = self.devices_handlers[device.id].get_ofp_port_info(device, port_no)
250 log.debug('get_ofp_port_info', device_id=device.id, ofp_port_info=ofp_port_info)
251 return ofp_port_info
252
Matt Jeannereta32441c2019-03-07 05:16:37 -0500253 def process_inter_adapter_message(self, msg):
254 log.debug('process-inter-adapter-message', msg=msg)
255 # Unpack the header to know which device needs to handle this message
256 if msg.header:
257 handler = self.devices_handlers[msg.header.to_device_id]
258 handler.process_inter_adapter_message(msg)
259
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500260 def create_interface(self, device, data):
261 log.debug('create-interface', device_id=device.id)
262 if device.id in self.devices_handlers:
263 handler = self.devices_handlers[device.id]
264 if handler is not None:
265 handler.create_interface(data)
266
267 def update_interface(self, device, data):
268 log.debug('update-interface', device_id=device.id)
269 if device.id in self.devices_handlers:
270 handler = self.devices_handlers[device.id]
271 if handler is not None:
272 handler.update_interface(data)
273
274 def remove_interface(self, device, data):
275 log.debug('remove-interface', device_id=device.id)
276 if device.id in self.devices_handlers:
277 handler = self.devices_handlers[device.id]
278 if handler is not None:
279 handler.remove_interface(data)
280
281 def receive_onu_detect_state(self, device_id, state):
282 raise NotImplementedError()
283
284 def create_tcont(self, device, tcont_data, traffic_descriptor_data):
285 log.debug('create-tcont', device_id=device.id)
286 if device.id in self.devices_handlers:
287 handler = self.devices_handlers[device.id]
288 if handler is not None:
289 handler.create_tcont(tcont_data, traffic_descriptor_data)
290
291 def update_tcont(self, device, tcont_data, traffic_descriptor_data):
292 raise NotImplementedError()
293
294 def remove_tcont(self, device, tcont_data, traffic_descriptor_data):
295 log.debug('remove-tcont', device_id=device.id)
296 if device.id in self.devices_handlers:
297 handler = self.devices_handlers[device.id]
298 if handler is not None:
299 handler.remove_tcont(tcont_data, traffic_descriptor_data)
300
301 def create_gemport(self, device, data):
302 log.debug('create-gemport', device_id=device.id)
303 if device.id in self.devices_handlers:
304 handler = self.devices_handlers[device.id]
305 if handler is not None:
306 handler.create_gemport(data)
307
308 def update_gemport(self, device, data):
309 raise NotImplementedError()
310
311 def remove_gemport(self, device, data):
312 log.debug('remove-gemport', device_id=device.id)
313 if device.id in self.devices_handlers:
314 handler = self.devices_handlers[device.id]
315 if handler is not None:
316 handler.remove_gemport(data)
317
318 def create_multicast_gemport(self, device, data):
319 log.debug('create-multicast-gemport', device_id=device.id)
320 if device.id in self.devices_handlers:
321 handler = self.devices_handlers[device.id]
322 if handler is not None:
323 handler.create_multicast_gemport(data)
324
325 def update_multicast_gemport(self, device, data):
326 raise NotImplementedError()
327
328 def remove_multicast_gemport(self, device, data):
329 raise NotImplementedError()
330
331 def create_multicast_distribution_set(self, device, data):
332 raise NotImplementedError()
333
334 def update_multicast_distribution_set(self, device, data):
335 raise NotImplementedError()
336
337 def remove_multicast_distribution_set(self, device, data):
338 raise NotImplementedError()
339
340 def suppress_alarm(self, filter):
341 raise NotImplementedError()
342
343 def unsuppress_alarm(self, filter):
344 raise NotImplementedError()
345
346