blob: 7d0fad5b38ae483321839e80eecf4db97a3b0a90 [file] [log] [blame]
Chip Boling67b674a2019-02-08 11:42:18 -06001#
2# Copyright 2018 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"""
18Adapter abstract base class
19"""
20
Zack Williams84a71e92019-11-15 09:00:19 -070021from __future__ import absolute_import
Chip Boling67b674a2019-02-08 11:42:18 -060022import structlog
23from twisted.internet import reactor
24from zope.interface import implementer
25
Zack Williams84a71e92019-11-15 09:00:19 -070026from .interface import IAdapterInterface
William Kurkianede82e92019-03-05 13:02:57 -050027from voltha_protos.adapter_pb2 import Adapter
28from voltha_protos.adapter_pb2 import AdapterConfig
29from voltha_protos.common_pb2 import AdminState
30from voltha_protos.common_pb2 import LogLevel
31from voltha_protos.device_pb2 import DeviceType, DeviceTypes
32from voltha_protos.health_pb2 import HealthStatus
Chip Boling67b674a2019-02-08 11:42:18 -060033
34
35log = structlog.get_logger()
36
37
38@implementer(IAdapterInterface)
39class IAdapter(object):
40 def __init__(self,
41 core_proxy,
42 adapter_proxy,
43 config,
44 device_handler_class,
45 name,
46 vendor,
47 version,
48 device_type, vendor_id,
49 accepts_bulk_flow_update=True,
50 accepts_add_remove_flow_updates=False):
51 log.debug(
52 'Initializing adapter: {} {} {}'.format(vendor, name, version))
53 self.core_proxy = core_proxy
54 self.adapter_proxy = adapter_proxy
55 self.config = config
56 self.name = name
57 self.supported_device_types = [
58 DeviceType(
59 id=device_type,
60 vendor_id=vendor_id,
61 adapter=name,
62 accepts_bulk_flow_update=accepts_bulk_flow_update,
63 accepts_add_remove_flow_updates=accepts_add_remove_flow_updates
64 )
65 ]
66 self.descriptor = Adapter(
67 id=self.name,
68 vendor=vendor,
69 version=version,
70 config=AdapterConfig(log_level=LogLevel.INFO)
71 )
72 self.devices_handlers = dict() # device_id -> Olt/OnuHandler()
73 self.device_handler_class = device_handler_class
74
75 def start(self):
76 log.info('Starting adapter: {}'.format(self.name))
77
78 def stop(self):
79 log.info('Stopping adapter: {}'.format(self.name))
80
81 def adapter_descriptor(self):
82 return self.descriptor
83
84 def device_types(self):
85 return DeviceTypes(items=self.supported_device_types)
86
87 def health(self):
88 # return HealthStatus(state=HealthStatus.HealthState.HEALTHY)
89 return HealthStatus(state=HealthStatus.HEALTHY)
90
91 def change_master_state(self, master):
92 raise NotImplementedError()
93
94 def get_ofp_device_info(self, device):
95 log.debug('get_ofp_device_info_start', device_id=device.id)
96 ofp_device_info = self.devices_handlers[device.id].get_ofp_device_info(
97 device)
98 log.debug('get_ofp_device_info_ends', device_id=device.id)
99 return ofp_device_info
100
Chip Boling67b674a2019-02-08 11:42:18 -0600101 def adopt_device(self, device):
102 log.debug('adopt_device', device_id=device.id)
103 self.devices_handlers[device.id] = self.device_handler_class(self,
104 device.id)
105 reactor.callLater(0, self.devices_handlers[device.id].activate, device)
106 log.debug('adopt_device_done', device_id=device.id)
107 return device
108
109 def reconcile_device(self, device):
110 raise NotImplementedError()
111
112 def abandon_device(self, device):
113 raise NotImplementedError()
114
115 def disable_device(self, device):
116 log.info('disable-device', device_id=device.id)
117 reactor.callLater(0, self.devices_handlers[device.id].disable)
118 log.debug('disable-device-done', device_id=device.id)
119 return device
120
121 def reenable_device(self, device):
122 log.info('reenable-device', device_id=device.id)
123 reactor.callLater(0, self.devices_handlers[device.id].reenable)
124 log.info('reenable-device-done', device_id=device.id)
125 return device
126
127 def reboot_device(self, device):
128 log.info('reboot-device', device_id=device.id)
129 reactor.callLater(0, self.devices_handlers[device.id].reboot)
130 log.info('reboot-device-done', device_id=device.id)
131 return device
132
133 def download_image(self, device, request):
134 raise NotImplementedError()
135
136 def get_image_download_status(self, device, request):
137 raise NotImplementedError()
138
139 def cancel_image_download(self, device, request):
140 raise NotImplementedError()
141
142 def activate_image_update(self, device, request):
143 raise NotImplementedError()
144
145 def revert_image_update(self, device, request):
146 raise NotImplementedError()
147
148 def self_test_device(self, device):
149 log.info('self-test', device_id=device.id)
150 result = reactor.callLater(0, self.devices_handlers[
151 device.id].self_test_device)
152 log.info('self-test-done', device_id=device.id)
153 return result
154
155 def delete_device(self, device):
156 log.info('delete-device', device_id=device.id)
157 reactor.callLater(0, self.devices_handlers[device.id].delete)
158 log.info('delete-device-done', device_id=device.id)
159 return device
160
161 def get_device_details(self, device):
162 raise NotImplementedError()
163
164 def update_flows_bulk(self, device, flows, groups):
Matteo Scandolo63efb062019-11-26 12:14:48 -0700165 log.debug('bulk-flow-update', device_id=device.id,
Chip Boling67b674a2019-02-08 11:42:18 -0600166 flows=flows, groups=groups)
167 assert len(groups.items) == 0
168 reactor.callLater(0, self.devices_handlers[device.id].update_flow_table,
169 flows.items)
170 return device
171
172 def update_flows_incrementally(self, device, flow_changes, group_changes):
173 log.info('incremental-flow-update', device_id=device.id,
174 flows=flow_changes, groups=group_changes)
175 # For now, there is no support for group changes
176 assert len(group_changes.to_add.items) == 0
177 assert len(group_changes.to_remove.items) == 0
178
179 handler = self.devices_handlers[device.id]
180 # Remove flows
181 if len(flow_changes.to_remove.items) != 0:
182 reactor.callLater(0, handler.remove_from_flow_table,
183 flow_changes.to_remove.items)
184
185 # Add flows
186 if len(flow_changes.to_add.items) != 0:
187 reactor.callLater(0, handler.add_to_flow_table,
188 flow_changes.to_add.items)
189 return device
190
191 def update_pm_config(self, device, pm_config):
192 log.info("adapter-update-pm-config", device=device,
193 pm_config=pm_config)
194 handler = self.devices_handlers[device.id]
195 if handler:
196 reactor.callLater(0, handler.update_pm_config, device, pm_config)
197
198 def process_inter_adapter_message(self, msg):
199 raise NotImplementedError()
200
201 def receive_packet_out(self, device_id, egress_port_no, msg):
202 raise NotImplementedError()
203
204 def suppress_alarm(self, filter):
205 raise NotImplementedError()
206
207 def unsuppress_alarm(self, filter):
208 raise NotImplementedError()
209
amit.ghosh1b7b4542020-11-19 09:19:21 +0100210 def single_get_value_request(self, request):
211 raise NotImplementedError()
212
213 def single_set_value_request(self, request):
214 raise NotImplementedError()
215
Chip Boling67b674a2019-02-08 11:42:18 -0600216 def _get_handler(self, device):
217 if device.id in self.devices_handlers:
218 handler = self.devices_handlers[device.id]
219 if handler is not None:
220 return handler
221 return None
222
223
224"""
225OLT Adapter base class
226"""
227
228
229class OltAdapter(IAdapter):
230 def __init__(self,
231 core_proxy,
232 adapter_proxy,
233 config,
234 device_handler_class,
235 name,
236 vendor,
237 version, device_type,
238 accepts_bulk_flow_update=True,
239 accepts_add_remove_flow_updates=False):
240 super(OltAdapter, self).__init__(core_proxy=core_proxy,
241 adapter_proxy=adapter_proxy,
242 config=config,
243 device_handler_class=device_handler_class,
244 name=name,
245 vendor=vendor,
246 version=version,
247 device_type=device_type,
248 vendor_id=None,
249 accepts_bulk_flow_update=accepts_bulk_flow_update,
250 accepts_add_remove_flow_updates=accepts_add_remove_flow_updates)
251 self.logical_device_id_to_root_device_id = dict()
252
253 def reconcile_device(self, device):
254 try:
255 self.devices_handlers[device.id] = self.device_handler_class(self,
256 device.id)
257 # Work only required for devices that are in ENABLED state
258 if device.admin_state == AdminState.ENABLED:
259 reactor.callLater(0,
260 self.devices_handlers[device.id].reconcile,
261 device)
262 else:
263 # Invoke the children reconciliation which would setup the
264 # basic children data structures
265 self.core_proxy.reconcile_child_devices(device.id)
266 return device
Zack Williams84a71e92019-11-15 09:00:19 -0700267 except Exception as e:
Chip Boling67b674a2019-02-08 11:42:18 -0600268 log.exception('Exception', e=e)
269
270 def send_proxied_message(self, proxy_address, msg):
271 log.info('send-proxied-message', proxy_address=proxy_address, msg=msg)
272 handler = self.devices_handlers[proxy_address.device_id]
273 handler.send_proxied_message(proxy_address, msg)
274
275 def process_inter_adapter_message(self, msg):
276 log.debug('process-inter-adapter-message', msg=msg)
277 # Unpack the header to know which device needs to handle this message
278 handler = None
279 if msg.header.proxy_device_id:
280 # typical request
281 handler = self.devices_handlers[msg.header.proxy_device_id]
282 elif msg.header.to_device_id and \
283 msg.header.to_device_id in self.devices_handlers:
284 # typical response
285 handler = self.devices_handlers[msg.header.to_device_id]
286 if handler:
287 reactor.callLater(0, handler.process_inter_adapter_message, msg)
288
289 def receive_packet_out(self, device_id, egress_port_no, msg):
290 try:
291 log.info('receive_packet_out', device_id=device_id,
292 egress_port=egress_port_no, msg=msg)
293 handler = self.devices_handlers[device_id]
294 if handler:
295 reactor.callLater(0, handler.packet_out, egress_port_no, msg.data)
Zack Williams84a71e92019-11-15 09:00:19 -0700296 except Exception as e:
Chip Boling67b674a2019-02-08 11:42:18 -0600297 log.exception('packet-out-failure', e=e)
298
299
300"""
301ONU Adapter base class
302"""
303
304
305class OnuAdapter(IAdapter):
306 def __init__(self,
307 core_proxy,
308 adapter_proxy,
309 config,
310 device_handler_class,
311 name,
312 vendor,
313 version,
314 device_type,
315 vendor_id,
316 accepts_bulk_flow_update=True,
317 accepts_add_remove_flow_updates=False):
318 super(OnuAdapter, self).__init__(core_proxy=core_proxy,
319 adapter_proxy=adapter_proxy,
320 config=config,
321 device_handler_class=device_handler_class,
322 name=name,
323 vendor=vendor,
324 version=version,
325 device_type=device_type,
326 vendor_id=vendor_id,
327 accepts_bulk_flow_update=accepts_bulk_flow_update,
328 accepts_add_remove_flow_updates=accepts_add_remove_flow_updates)
329
330 def reconcile_device(self, device):
331 self.devices_handlers[device.id] = self.device_handler_class(self,
332 device.id)
333 # Reconcile only if state was ENABLED
334 if device.admin_state == AdminState.ENABLED:
335 reactor.callLater(0,
336 self.devices_handlers[device.id].reconcile,
337 device)
338 return device
339
340 def receive_proxied_message(self, proxy_address, msg):
341 log.info('receive-proxied-message', proxy_address=proxy_address,
342 device_id=proxy_address.device_id, msg=msg)
343 # Device_id from the proxy_address is the olt device id. We need to
344 # get the onu device id using the port number in the proxy_address
345 device = self.core_proxy. \
346 get_child_device_with_proxy_address(proxy_address)
347 if device:
348 handler = self.devices_handlers[device.id]
349 handler.receive_message(msg)
350
351 def process_inter_adapter_message(self, msg):
352 log.info('process-inter-adapter-message', msg=msg)
353 # Unpack the header to know which device needs to handle this message
354 if msg.header:
355 handler = self.devices_handlers[msg.header.to_device_id]
356 handler.process_inter_adapter_message(msg)