blob: eaa8ff5fc919ed59c5e0afcd53d96bdc474fe850 [file] [log] [blame]
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -05001#
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
16import structlog
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050017from twisted.internet import reactor
18from twisted.internet.defer import inlineCallbacks, returnValue, TimeoutError, failure
Matt Jeanneret2e3cb8d2019-11-16 09:22:41 -050019from pyvoltha.adapters.extensions.omci.omci_me import PptpEthernetUniFrame, GalEthernetProfileFrame, \
20 MacBridgePortConfigurationDataFrame, MacBridgeServiceProfileFrame, Ieee8021pMapperServiceProfileFrame, \
21 VeipUniFrame, ExtendedVlanTaggingOperationConfigurationDataFrame
Matt Jeanneret72f96fc2019-02-11 10:53:05 -050022from pyvoltha.adapters.extensions.omci.tasks.task import Task
Matt Jeanneret2e3cb8d2019-11-16 09:22:41 -050023from pyvoltha.adapters.extensions.omci.omci_defs import EntityOperations, ReasonCodes
24from uni_port import UniType
25from pon_port \
Matt Jeanneret810148b2019-09-29 12:44:01 -040026 import TASK_PRIORITY, DEFAULT_TPID, DEFAULT_GEM_PAYLOAD
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050027
28OP = EntityOperations
29RC = ReasonCodes
30
31
32class MibDownloadFailure(Exception):
33 """
34 This error is raised by default when the download fails
35 """
36
37
38class MibResourcesFailure(Exception):
39 """
40 This error is raised by when one or more resources required is not available
41 """
42
43
44class BrcmMibDownloadTask(Task):
45 """
Matt Jeanneret810148b2019-09-29 12:44:01 -040046 OpenOMCI MIB Download Bridge Setup Task
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050047
48 This task takes the legacy OMCI 'script' for provisioning the Broadcom ONU
49 and converts it to run as a Task on the OpenOMCI Task runner. This is
50 in order to begin to decompose service instantiation in preparation for
51 Technology Profile work.
52
53 Once technology profiles are ready, some of this task may hang around or
54 be moved into OpenOMCI if there are any very common settings/configs to do
55 for any profile that may be provided in the v2.0 release
56
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050057 """
58
Matt Jeanneret810148b2019-09-29 12:44:01 -040059 name = "Broadcom MIB Download Bridge Setup Task"
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050060
61 def __init__(self, omci_agent, handler):
62 """
63 Class initialization
64
65 :param omci_agent: (OmciAdapterAgent) OMCI Adapter agent
66 :param device_id: (str) ONU Device ID
67 """
68
69 self.log = structlog.get_logger(device_id=handler.device_id)
70 self.log.debug('function-entry')
71
72 super(BrcmMibDownloadTask, self).__init__(BrcmMibDownloadTask.name,
73 omci_agent,
74 handler.device_id,
75 priority=TASK_PRIORITY)
76 self._handler = handler
77 self._onu_device = omci_agent.get_device(handler.device_id)
78 self._local_deferred = None
79
80 # Frame size
81 self._max_gem_payload = DEFAULT_GEM_PAYLOAD
82
83 self._pon = handler.pon_port
84
85 # Defaults
86 self._input_tpid = DEFAULT_TPID
87 self._output_tpid = DEFAULT_TPID
88
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050089 # Entity IDs. IDs with values can probably be most anything for most ONUs,
90 # IDs set to None are discovered/set
91
92 self._mac_bridge_service_profile_entity_id = \
93 self._handler.mac_bridge_service_profile_entity_id
94 self._ieee_mapper_service_profile_entity_id = \
95 self._pon.ieee_mapper_service_profile_entity_id
96 self._mac_bridge_port_ani_entity_id = \
97 self._pon.mac_bridge_port_ani_entity_id
98 self._gal_enet_profile_entity_id = \
99 self._handler.gal_enet_profile_entity_id
100
101 self._free_ul_prior_q_entity_ids = set()
102 self._free_dl_prior_q_entity_ids = set()
103
104 def cancel_deferred(self):
105 self.log.debug('function-entry')
106 super(BrcmMibDownloadTask, self).cancel_deferred()
107
108 d, self._local_deferred = self._local_deferred, None
109 try:
110 if d is not None and not d.called:
111 d.cancel()
112 except:
113 pass
114
115 def start(self):
116 """
117 Start the MIB Download
118 """
119 self.log.debug('function-entry')
120 super(BrcmMibDownloadTask, self).start()
121 self._local_deferred = reactor.callLater(0, self.perform_mib_download)
122
123 def stop(self):
124 """
125 Shutdown MIB Synchronization tasks
126 """
127 self.log.debug('function-entry')
128 self.log.debug('stopping')
129
130 self.cancel_deferred()
131 super(BrcmMibDownloadTask, self).stop()
132
133 def check_status_and_state(self, results, operation=''):
134 """
135 Check the results of an OMCI response. An exception is thrown
136 if the task was cancelled or an error was detected.
137
138 :param results: (OmciFrame) OMCI Response frame
139 :param operation: (str) what operation was being performed
140 :return: True if successful, False if the entity existed (already created)
141 """
142 self.log.debug('function-entry')
143
144 omci_msg = results.fields['omci_message'].fields
145 status = omci_msg['success_code']
146 error_mask = omci_msg.get('parameter_error_attributes_mask', 'n/a')
147 failed_mask = omci_msg.get('failed_attributes_mask', 'n/a')
148 unsupported_mask = omci_msg.get('unsupported_attributes_mask', 'n/a')
149
Matt Jeannerete8fc53e2019-04-13 15:58:33 -0400150 self.log.debug("OMCI Result", operation=operation,
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500151 omci_msg=omci_msg, status=status,
152 error_mask=error_mask, failed_mask=failed_mask,
153 unsupported_mask=unsupported_mask)
154
155 if status == RC.Success:
156 self.strobe_watchdog()
157 return True
158
159 elif status == RC.InstanceExists:
160 return False
161
162 raise MibDownloadFailure('{} failed with a status of {}, error_mask: {}, failed_mask: {}, unsupported_mask: {}'
163 .format(operation, status, error_mask, failed_mask, unsupported_mask))
164
165 @inlineCallbacks
166 def perform_mib_download(self):
167 """
168 Send the commands to minimally configure the PON, Bridge, and
169 UNI ports for this device. The application of any service flows
170 and other characteristics are done as needed.
171 """
172 try:
173 self.log.debug('function-entry')
174 self.log.info('perform-download')
175
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500176 if self._handler.enabled and len(self._handler.uni_ports) > 0:
Mahir Gunyel0e6882a2019-10-16 17:02:39 -0700177 yield self._handler.core_proxy.device_reason_update(self.device_id, 'performing-initial-mib-download')
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500178
179 try:
180 # Lock the UNI ports to prevent any alarms during initial configuration
181 # of the ONU
182 self.strobe_watchdog()
183
184 # Provision the initial bridge configuration
185 yield self.perform_initial_bridge_setup()
186
187 for uni_port in self._handler.uni_ports:
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500188 # Provision the initial bridge configuration
189 yield self.perform_uni_initial_bridge_setup(uni_port)
190
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500191 self.deferred.callback('initial-download-success')
192
193 except TimeoutError as e:
194 self.log.error('initial-download-failure', e=e)
195 self.deferred.errback(failure.Failure(e))
196
197 except Exception as e:
198 self.log.exception('initial-download-failure', e=e)
199 self.deferred.errback(failure.Failure(e))
200
201 else:
202 e = MibResourcesFailure('Required resources are not available',
203 len(self._handler.uni_ports))
204 self.deferred.errback(failure.Failure(e))
205 except BaseException as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400206 self.log.debug('cannot-start-mib-download', exception=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500207
208 @inlineCallbacks
209 def perform_initial_bridge_setup(self):
210 self.log.debug('function-entry')
211
212 omci_cc = self._onu_device.omci_cc
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500213 try:
214 ########################################################################################
215 # Create GalEthernetProfile - Once per ONU/PON interface
216 #
217 # EntityID will be referenced by:
218 # - GemInterworkingTp
219 # References:
220 # - Nothing
221
222 msg = GalEthernetProfileFrame(
223 self._gal_enet_profile_entity_id,
224 max_gem_payload_size=self._max_gem_payload
225 )
226 frame = msg.create()
227 self.log.debug('openomci-msg', omci_msg=msg)
228 results = yield omci_cc.send(frame)
229 self.check_status_and_state(results, 'create-gal-ethernet-profile')
230
231 except TimeoutError as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400232 self.log.warn('rx-timeout-initial-gal-profile', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500233 raise
234
235 except Exception as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400236 self.log.exception('omci-setup-initial-gal-profile', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500237 raise
238
239 returnValue(None)
240
241 @inlineCallbacks
242 def perform_uni_initial_bridge_setup(self, uni_port):
243 self.log.debug('function-entry')
244 omci_cc = self._onu_device.omci_cc
245 frame = None
246 try:
247 ################################################################################
248 # Common - PON and/or UNI #
249 ################################################################################
250 # MAC Bridge Service Profile
251 #
252 # EntityID will be referenced by:
253 # - MAC Bridge Port Configuration Data (PON & UNI)
254 # References:
255 # - Nothing
256
257 # TODO: magic. event if static, assign to a meaningful variable name
258 attributes = {
259 'spanning_tree_ind': False,
260 'learning_ind': True,
261 'priority': 0x8000,
262 'max_age': 20 * 256,
263 'hello_time': 2 * 256,
264 'forward_delay': 15 * 256,
265 'unknown_mac_address_discard': True
266 }
267 msg = MacBridgeServiceProfileFrame(
268 self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num,
269 attributes
270 )
271 frame = msg.create()
272 self.log.debug('openomci-msg', omci_msg=msg)
273 results = yield omci_cc.send(frame)
274 self.check_status_and_state(results, 'create-mac-bridge-service-profile')
275
276 ################################################################################
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500277 # UNI Specific #
278 ################################################################################
279 # MAC Bridge Port config
280 # This configuration is for Ethernet UNI
281 #
282 # EntityID will be referenced by:
283 # - Nothing
284 # References:
285 # - MAC Bridge Service Profile (the bridge)
286 # - PPTP Ethernet or VEIP UNI
287
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500288 # default to PPTP
Matt Jeanneret31509ec2019-12-20 14:57:53 -0500289 tp_type = 1
Matt Jeanneretaf7cd6b2019-04-05 15:37:34 -0400290 if uni_port.type.value == UniType.VEIP.value:
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500291 tp_type = 11
Matt Jeanneretaf7cd6b2019-04-05 15:37:34 -0400292 elif uni_port.type.value == UniType.PPTP.value:
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500293 tp_type = 1
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500294
295 msg = MacBridgePortConfigurationDataFrame(
Matt Jeanneret2e5c6f12019-12-13 07:06:06 -0500296 self._mac_bridge_port_ani_entity_id + uni_port.entity_id, # Entity ID
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500297 bridge_id_pointer=self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num, # Bridge Entity ID
298 port_num=uni_port.mac_bridge_port_num, # Port ID
299 tp_type=tp_type, # PPTP Ethernet or VEIP UNI
300 tp_pointer=uni_port.entity_id # Ethernet UNI ID
301 )
302 frame = msg.create()
303 self.log.debug('openomci-msg', omci_msg=msg)
304 results = yield omci_cc.send(frame)
Matt Jeanneret810148b2019-09-29 12:44:01 -0400305 self.check_status_and_state(results, 'create-mac-bridge-port-configuration-data-uni-port')
306
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500307 except TimeoutError as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400308 self.log.warn('rx-timeout-inital-per-uni-setup', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500309 raise
310
311 except Exception as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400312 self.log.exception('omci-setup-initial-per-uni-setup', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500313 raise
314
315 returnValue(None)