blob: a3fcc470292fda893ee2efff03d067f45481755a [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
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050016from twisted.internet import reactor
17from twisted.internet.defer import inlineCallbacks, returnValue, TimeoutError, failure
Matt Jeanneret2e3cb8d2019-11-16 09:22:41 -050018from pyvoltha.adapters.extensions.omci.omci_me import PptpEthernetUniFrame, GalEthernetProfileFrame, \
19 MacBridgePortConfigurationDataFrame, MacBridgeServiceProfileFrame, Ieee8021pMapperServiceProfileFrame, \
Mahir Gunyel45610b42020-03-16 17:29:01 -070020 VeipUniFrame, ExtendedVlanTaggingOperationConfigurationDataFrame,Ont2GFrame
Matt Jeanneret72f96fc2019-02-11 10:53:05 -050021from pyvoltha.adapters.extensions.omci.tasks.task import Task
Matt Jeanneret2e3cb8d2019-11-16 09:22:41 -050022from pyvoltha.adapters.extensions.omci.omci_defs import EntityOperations, ReasonCodes
23from uni_port import UniType
24from pon_port \
Matt Jeanneret810148b2019-09-29 12:44:01 -040025 import TASK_PRIORITY, DEFAULT_TPID, DEFAULT_GEM_PAYLOAD
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050026
27OP = EntityOperations
28RC = ReasonCodes
29
30
31class MibDownloadFailure(Exception):
32 """
33 This error is raised by default when the download fails
34 """
35
36
37class MibResourcesFailure(Exception):
38 """
39 This error is raised by when one or more resources required is not available
40 """
41
42
43class BrcmMibDownloadTask(Task):
44 """
Matt Jeanneret810148b2019-09-29 12:44:01 -040045 OpenOMCI MIB Download Bridge Setup Task
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050046
47 This task takes the legacy OMCI 'script' for provisioning the Broadcom ONU
48 and converts it to run as a Task on the OpenOMCI Task runner. This is
49 in order to begin to decompose service instantiation in preparation for
50 Technology Profile work.
51
52 Once technology profiles are ready, some of this task may hang around or
53 be moved into OpenOMCI if there are any very common settings/configs to do
54 for any profile that may be provided in the v2.0 release
55
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050056 """
57
Matt Jeanneret810148b2019-09-29 12:44:01 -040058 name = "Broadcom MIB Download Bridge Setup Task"
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050059
60 def __init__(self, omci_agent, handler):
61 """
62 Class initialization
63
64 :param omci_agent: (OmciAdapterAgent) OMCI Adapter agent
65 :param device_id: (str) ONU Device ID
66 """
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050067 super(BrcmMibDownloadTask, self).__init__(BrcmMibDownloadTask.name,
68 omci_agent,
69 handler.device_id,
70 priority=TASK_PRIORITY)
71 self._handler = handler
72 self._onu_device = omci_agent.get_device(handler.device_id)
73 self._local_deferred = None
74
75 # Frame size
76 self._max_gem_payload = DEFAULT_GEM_PAYLOAD
77
78 self._pon = handler.pon_port
79
80 # Defaults
81 self._input_tpid = DEFAULT_TPID
82 self._output_tpid = DEFAULT_TPID
83
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050084 # Entity IDs. IDs with values can probably be most anything for most ONUs,
85 # IDs set to None are discovered/set
86
87 self._mac_bridge_service_profile_entity_id = \
88 self._handler.mac_bridge_service_profile_entity_id
89 self._ieee_mapper_service_profile_entity_id = \
90 self._pon.ieee_mapper_service_profile_entity_id
91 self._mac_bridge_port_ani_entity_id = \
92 self._pon.mac_bridge_port_ani_entity_id
93 self._gal_enet_profile_entity_id = \
94 self._handler.gal_enet_profile_entity_id
95
96 self._free_ul_prior_q_entity_ids = set()
97 self._free_dl_prior_q_entity_ids = set()
98
99 def cancel_deferred(self):
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500100 super(BrcmMibDownloadTask, self).cancel_deferred()
101
102 d, self._local_deferred = self._local_deferred, None
103 try:
104 if d is not None and not d.called:
105 d.cancel()
106 except:
107 pass
108
109 def start(self):
110 """
111 Start the MIB Download
112 """
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500113 super(BrcmMibDownloadTask, self).start()
114 self._local_deferred = reactor.callLater(0, self.perform_mib_download)
115
116 def stop(self):
117 """
118 Shutdown MIB Synchronization tasks
119 """
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500120 self.cancel_deferred()
121 super(BrcmMibDownloadTask, self).stop()
122
123 def check_status_and_state(self, results, operation=''):
124 """
125 Check the results of an OMCI response. An exception is thrown
126 if the task was cancelled or an error was detected.
127
128 :param results: (OmciFrame) OMCI Response frame
129 :param operation: (str) what operation was being performed
130 :return: True if successful, False if the entity existed (already created)
131 """
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500132
133 omci_msg = results.fields['omci_message'].fields
134 status = omci_msg['success_code']
135 error_mask = omci_msg.get('parameter_error_attributes_mask', 'n/a')
136 failed_mask = omci_msg.get('failed_attributes_mask', 'n/a')
137 unsupported_mask = omci_msg.get('unsupported_attributes_mask', 'n/a')
138
Matt Jeannerete8fc53e2019-04-13 15:58:33 -0400139 self.log.debug("OMCI Result", operation=operation,
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500140 omci_msg=omci_msg, status=status,
141 error_mask=error_mask, failed_mask=failed_mask,
142 unsupported_mask=unsupported_mask)
143
Matt Jeanneret04ebe8f2020-01-26 01:05:23 -0500144 self.strobe_watchdog()
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500145 if status == RC.Success:
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500146 return True
147
148 elif status == RC.InstanceExists:
149 return False
150
151 raise MibDownloadFailure('{} failed with a status of {}, error_mask: {}, failed_mask: {}, unsupported_mask: {}'
152 .format(operation, status, error_mask, failed_mask, unsupported_mask))
153
154 @inlineCallbacks
155 def perform_mib_download(self):
156 """
157 Send the commands to minimally configure the PON, Bridge, and
158 UNI ports for this device. The application of any service flows
159 and other characteristics are done as needed.
160 """
161 try:
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500162 self.log.info('perform-download')
163
Matt Jeanneret04ebe8f2020-01-26 01:05:23 -0500164 # Provision the initial bridge configuration
165 yield self.perform_initial_bridge_setup()
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500166
Matt Jeanneret04ebe8f2020-01-26 01:05:23 -0500167 for uni_port in self._handler.uni_ports:
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500168 # Provision the initial bridge configuration
Matt Jeanneret04ebe8f2020-01-26 01:05:23 -0500169 yield self.perform_uni_initial_bridge_setup(uni_port)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500170
Matt Jeanneret04ebe8f2020-01-26 01:05:23 -0500171 self.deferred.callback('initial-download-success')
172 except Exception as e:
173 self.log.error('initial-download-failure', e=e)
174 self.deferred.errback(failure.Failure(e))
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500175
176 @inlineCallbacks
177 def perform_initial_bridge_setup(self):
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500178
179 omci_cc = self._onu_device.omci_cc
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500180 try:
181 ########################################################################################
182 # Create GalEthernetProfile - Once per ONU/PON interface
183 #
184 # EntityID will be referenced by:
185 # - GemInterworkingTp
186 # References:
187 # - Nothing
188
189 msg = GalEthernetProfileFrame(
190 self._gal_enet_profile_entity_id,
191 max_gem_payload_size=self._max_gem_payload
192 )
193 frame = msg.create()
194 self.log.debug('openomci-msg', omci_msg=msg)
195 results = yield omci_cc.send(frame)
196 self.check_status_and_state(results, 'create-gal-ethernet-profile')
197
Mahir Gunyel45610b42020-03-16 17:29:01 -0700198 ont2_attributes = dict(current_connectivity_mode=5)
199 msg = Ont2GFrame(attributes=ont2_attributes)
200 frame = msg.set()
201 self.log.debug('openomci-msg', omci_msg=msg)
202 results = yield omci_cc.send(frame)
203 self.check_status_and_state(results, 'set-ont2g')
204
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500205 except TimeoutError as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400206 self.log.warn('rx-timeout-initial-gal-profile', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500207 raise
208
209 except Exception as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400210 self.log.exception('omci-setup-initial-gal-profile', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500211 raise
212
213 returnValue(None)
214
215 @inlineCallbacks
216 def perform_uni_initial_bridge_setup(self, uni_port):
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500217 omci_cc = self._onu_device.omci_cc
218 frame = None
219 try:
220 ################################################################################
221 # Common - PON and/or UNI #
222 ################################################################################
223 # MAC Bridge Service Profile
224 #
225 # EntityID will be referenced by:
226 # - MAC Bridge Port Configuration Data (PON & UNI)
227 # References:
228 # - Nothing
229
230 # TODO: magic. event if static, assign to a meaningful variable name
231 attributes = {
232 'spanning_tree_ind': False,
Mahir Gunyel45610b42020-03-16 17:29:01 -0700233 'learning_ind': False,
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500234 'priority': 0x8000,
235 'max_age': 20 * 256,
236 'hello_time': 2 * 256,
237 'forward_delay': 15 * 256,
Mahir Gunyel45610b42020-03-16 17:29:01 -0700238 'unknown_mac_address_discard': False
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500239 }
240 msg = MacBridgeServiceProfileFrame(
241 self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num,
242 attributes
243 )
244 frame = msg.create()
245 self.log.debug('openomci-msg', omci_msg=msg)
246 results = yield omci_cc.send(frame)
247 self.check_status_and_state(results, 'create-mac-bridge-service-profile')
248
249 ################################################################################
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500250 # UNI Specific #
251 ################################################################################
252 # MAC Bridge Port config
253 # This configuration is for Ethernet UNI
254 #
255 # EntityID will be referenced by:
256 # - Nothing
257 # References:
258 # - MAC Bridge Service Profile (the bridge)
259 # - PPTP Ethernet or VEIP UNI
260
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500261 # default to PPTP
Matt Jeanneret31509ec2019-12-20 14:57:53 -0500262 tp_type = 1
Mahir Gunyel45610b42020-03-16 17:29:01 -0700263 association_type = 2
Matt Jeanneretaf7cd6b2019-04-05 15:37:34 -0400264 if uni_port.type.value == UniType.VEIP.value:
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500265 tp_type = 11
Mahir Gunyel45610b42020-03-16 17:29:01 -0700266 association_type = 10
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500267
268 msg = MacBridgePortConfigurationDataFrame(
Matt Jeanneret2e5c6f12019-12-13 07:06:06 -0500269 self._mac_bridge_port_ani_entity_id + uni_port.entity_id, # Entity ID
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500270 bridge_id_pointer=self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num, # Bridge Entity ID
271 port_num=uni_port.mac_bridge_port_num, # Port ID
272 tp_type=tp_type, # PPTP Ethernet or VEIP UNI
273 tp_pointer=uni_port.entity_id # Ethernet UNI ID
274 )
275 frame = msg.create()
276 self.log.debug('openomci-msg', omci_msg=msg)
277 results = yield omci_cc.send(frame)
Matt Jeanneret810148b2019-09-29 12:44:01 -0400278 self.check_status_and_state(results, 'create-mac-bridge-port-configuration-data-uni-port')
279
Mahir Gunyel45610b42020-03-16 17:29:01 -0700280
281 ################################################################################
282 # Create Extended VLAN Tagging Operation config (UNI-side)
283 #
284 # EntityID relates to the VLAN TCIS later used int vlan filter task. This only
285 # sets up the inital MIB entry as it relates to port config, it does not set vlan
286 # that is saved for the vlan filter task
287 #
288 # References:
289 # - PPTP Ethernet or VEIP UNI
290 #
291
292 attributes = dict(
293 association_type=association_type, # Assoc Type, PPTP/VEIP Ethernet UNI
294 associated_me_pointer=uni_port.entity_id, # Assoc ME, PPTP/VEIP Entity Id
295
296 # See VOL-1311 - Need to set table during create to avoid exception
297 # trying to read back table during post-create-read-missing-attributes
298 # But, because this is a R/W attribute. Some ONU may not accept the
299 # value during create. It is repeated again in a set below.
300 input_tpid=self._input_tpid, # input TPID
301 output_tpid=self._output_tpid, # output TPID
302 )
303
304 msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
305 self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num, # Bridge Entity ID
306 attributes=attributes
307 )
308
309 frame = msg.create()
310 self.log.debug('openomci-msg', omci_msg=msg)
311 results = yield omci_cc.send(frame)
312 self.check_status_and_state(results, 'create-extended-vlan-tagging-operation-configuration-data')
313
ozgecanetsiab1cef1d2020-06-09 23:09:00 +0300314 attributes = dict(
315 # Specifies the TPIDs in use and that operations in the downstream direction are
316 # inverse to the operations in the upstream direction
317 input_tpid=self._input_tpid, # input TPID
318 output_tpid=self._output_tpid, # output TPID
319 downstream_mode=0, # inverse of upstream
320 )
321
322 msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
323 self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num, # Bridge Entity ID
324 attributes=attributes
325 )
326
327 frame = msg.set()
328 self.log.debug('openomci-msg', omci_msg=msg)
329 self.strobe_watchdog()
330 results = yield self._device.omci_cc.send(frame)
331 self.check_status_and_state(results, 'set-extended-vlan-tagging-operation-configuration-data')
332
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500333 except TimeoutError as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400334 self.log.warn('rx-timeout-inital-per-uni-setup', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500335 raise
336
337 except Exception as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400338 self.log.exception('omci-setup-initial-per-uni-setup', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500339 raise
340
341 returnValue(None)