blob: 678fd54f0a5a282e1de84ca28b7da0d382afa2c7 [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, \
20 VeipUniFrame, ExtendedVlanTaggingOperationConfigurationDataFrame
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
198 except TimeoutError as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400199 self.log.warn('rx-timeout-initial-gal-profile', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500200 raise
201
202 except Exception as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400203 self.log.exception('omci-setup-initial-gal-profile', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500204 raise
205
206 returnValue(None)
207
208 @inlineCallbacks
209 def perform_uni_initial_bridge_setup(self, uni_port):
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500210 omci_cc = self._onu_device.omci_cc
211 frame = None
212 try:
213 ################################################################################
214 # Common - PON and/or UNI #
215 ################################################################################
216 # MAC Bridge Service Profile
217 #
218 # EntityID will be referenced by:
219 # - MAC Bridge Port Configuration Data (PON & UNI)
220 # References:
221 # - Nothing
222
223 # TODO: magic. event if static, assign to a meaningful variable name
224 attributes = {
225 'spanning_tree_ind': False,
226 'learning_ind': True,
227 'priority': 0x8000,
228 'max_age': 20 * 256,
229 'hello_time': 2 * 256,
230 'forward_delay': 15 * 256,
231 'unknown_mac_address_discard': True
232 }
233 msg = MacBridgeServiceProfileFrame(
234 self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num,
235 attributes
236 )
237 frame = msg.create()
238 self.log.debug('openomci-msg', omci_msg=msg)
239 results = yield omci_cc.send(frame)
240 self.check_status_and_state(results, 'create-mac-bridge-service-profile')
241
242 ################################################################################
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500243 # UNI Specific #
244 ################################################################################
245 # MAC Bridge Port config
246 # This configuration is for Ethernet UNI
247 #
248 # EntityID will be referenced by:
249 # - Nothing
250 # References:
251 # - MAC Bridge Service Profile (the bridge)
252 # - PPTP Ethernet or VEIP UNI
253
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500254 # default to PPTP
Matt Jeanneret31509ec2019-12-20 14:57:53 -0500255 tp_type = 1
Matt Jeanneretaf7cd6b2019-04-05 15:37:34 -0400256 if uni_port.type.value == UniType.VEIP.value:
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500257 tp_type = 11
Matt Jeanneretaf7cd6b2019-04-05 15:37:34 -0400258 elif uni_port.type.value == UniType.PPTP.value:
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500259 tp_type = 1
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500260
261 msg = MacBridgePortConfigurationDataFrame(
Matt Jeanneret2e5c6f12019-12-13 07:06:06 -0500262 self._mac_bridge_port_ani_entity_id + uni_port.entity_id, # Entity ID
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500263 bridge_id_pointer=self._mac_bridge_service_profile_entity_id + uni_port.mac_bridge_port_num, # Bridge Entity ID
264 port_num=uni_port.mac_bridge_port_num, # Port ID
265 tp_type=tp_type, # PPTP Ethernet or VEIP UNI
266 tp_pointer=uni_port.entity_id # Ethernet UNI ID
267 )
268 frame = msg.create()
269 self.log.debug('openomci-msg', omci_msg=msg)
270 results = yield omci_cc.send(frame)
Matt Jeanneret810148b2019-09-29 12:44:01 -0400271 self.check_status_and_state(results, 'create-mac-bridge-port-configuration-data-uni-port')
272
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500273 except TimeoutError as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400274 self.log.warn('rx-timeout-inital-per-uni-setup', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500275 raise
276
277 except Exception as e:
Matt Jeanneret810148b2019-09-29 12:44:01 -0400278 self.log.exception('omci-setup-initial-per-uni-setup', e=e)
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500279 raise
280
281 returnValue(None)