blob: b75d791d2b80ed57ce3b393cb0542b94987a641f [file] [log] [blame]
Girish Gowdrae933cd32019-11-21 21:04:41 +05301#
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
16from __future__ import absolute_import
17import structlog
18from twisted.internet import reactor
19from twisted.internet.defer import inlineCallbacks, TimeoutError, failure
20from pyvoltha.adapters.extensions.omci.omci_me import Ont2G, OmciNullPointer, PriorityQueueFrame, \
21 Ieee8021pMapperServiceProfileFrame, MacBridgePortConfigurationDataFrame
22from pyvoltha.adapters.extensions.omci.tasks.task import Task
23from pyvoltha.adapters.extensions.omci.omci_defs import EntityOperations, ReasonCodes
24from pyvoltha.adapters.extensions.omci.omci_entities import OntG, Tcont, PriorityQueueG
25
26OP = EntityOperations
27RC = ReasonCodes
28
29# The DELETE_TP_TASK_PRIORITY should be higher than SETUP_TP_TASK_PRIORITY
30DELETE_TP_TASK_PRIORITY = 250
31
32
33class TechProfileDeleteFailure(Exception):
34 """
35 This error is raised by default when the delete fails
36 """
37
38
39class TechProfileResourcesFailure(Exception):
40 """
41 This error is raised by when one or more resources required is not available
42 """
43
44
45class BrcmTpDeleteTask(Task):
46 """
47 OpenOMCI Tech-Profile Delete Task
48
49 """
50
51 name = "Broadcom Tech-Profile Delete Task"
52
53 def __init__(self, omci_agent, handler, uni_id, tp_table_id,
54 tcont=None, gem_port=None):
55 """
56 Class initialization
57
58 :param omci_agent: (OmciAdapterAgent) OMCI Adapter agent
59 :param handler: (BrcmOpenomciOnuHandler) ONU Device Handler Instance
60 :param uni_id: (int) numeric id of the uni port on the onu device, starts at 0
61 :param tp_table_id: (int) Technology Profile Table-ID
62 """
63 log = structlog.get_logger(device_id=handler.device_id, uni_id=uni_id)
64 log.debug('function-entry')
65
66 super(BrcmTpDeleteTask, self).__init__(BrcmTpDeleteTask.name,
67 omci_agent,
68 handler.device_id,
69 priority=DELETE_TP_TASK_PRIORITY,
70 exclusive=True)
71
72 self.log = log
73
74 self._onu_device = omci_agent.get_device(handler.device_id)
75 self._local_deferred = None
76
77 self._uni_port = handler.uni_ports[uni_id]
78 assert self._uni_port.uni_id == uni_id
79
80 # Tech Profile Table ID
81 self._tp_table_id = tp_table_id
82
83 self._tcont = tcont
84 self._gem_port = gem_port
85
86 self._alloc_id = self._tcont.alloc_id if self._tcont else None
87 self._gem_port_id = self._gem_port.gem_id if gem_port else None
88
89 # Entity IDs. IDs with values can probably be most anything for most ONUs,
90 # IDs set to None are discovered/set
91 self._mac_bridge_service_profile_entity_id = \
92 handler.mac_bridge_service_profile_entity_id
93 self._ieee_mapper_service_profile_entity_id = \
94 handler.pon_port.ieee_mapper_service_profile_entity_id
95 self._mac_bridge_port_ani_entity_id = \
96 handler.pon_port.mac_bridge_port_ani_entity_id
97
98 def cancel_deferred(self):
99 self.log.debug('function-entry')
100 super(BrcmTpDeleteTask, 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 Tech-Profile Delete
112 """
113 self.log.debug('function-entry')
114 super(BrcmTpDeleteTask, self).start()
115 if self._tcont is not None:
116 self._local_deferred = reactor.callLater(0, self.delete_tcont_and_associated_me)
117 elif self._gem_port is not None:
118 self._local_deferred = reactor.callLater(0, self.delete_gem_port_nw_ctp_and_associated_me)
119 else:
120 raise Exception("both-alloc-id-and-gem-port-id-are-none")
121
122 def stop(self):
123 """
124 Shutdown Tech-Profile delete tasks
125 """
126 self.log.debug('function-entry')
127 self.log.debug('stopping')
128
129 self.cancel_deferred()
130 super(BrcmTpDeleteTask, self).stop()
131
132 def check_status_and_state(self, results, operation=''):
133 """
134 Check the results of an OMCI response. An exception is thrown
135 if the task was cancelled or an error was detected.
136
137 :param results: (OmciFrame) OMCI Response frame
138 :param operation: (str) what operation was being performed
139 :return: True if successful, False if the entity existed (already created)
140 """
141 self.log.debug('function-entry')
142
143 omci_msg = results.fields['omci_message'].fields
144 status = omci_msg['success_code']
145 error_mask = omci_msg.get('parameter_error_attributes_mask', 'n/a')
146 failed_mask = omci_msg.get('failed_attributes_mask', 'n/a')
147 unsupported_mask = omci_msg.get('unsupported_attributes_mask', 'n/a')
148
149 self.log.debug("OMCI Result", operation=operation, omci_msg=omci_msg, status=status, error_mask=error_mask,
150 failed_mask=failed_mask, unsupported_mask=unsupported_mask)
151
152 if status == RC.Success:
153 self.strobe_watchdog()
154 return True
155
156 elif status == RC.InstanceExists:
157 return False
158
159 raise TechProfileDeleteFailure(
160 '{} failed with a status of {}, error_mask: {}, failed_mask: {}, '
161 'unsupported_mask: {}'.format(operation, status, error_mask, failed_mask, unsupported_mask))
162
163 @inlineCallbacks
164 def delete_tcont_and_associated_me(self):
165 self.log.debug('function-entry')
166
167 omci_cc = self._onu_device.omci_cc
168
169 try:
170 ################################################################################
171 # Reset TCONT ME
172 ################################################################################
173
174 tcont_idents = self._onu_device.query_mib(Tcont.class_id)
175 self.log.debug('tcont-idents', tcont_idents=tcont_idents)
176 tcont_entity_id = None
177 for k, v in tcont_idents.items():
178 if not isinstance(v, dict):
179 continue
180 alloc_check = v.get('attributes', {}).get('alloc_id', 0)
181 # Some onu report both to indicate an available tcont
182 if alloc_check == self._alloc_id:
183 tcont_entity_id = k
184 break
185
186 if tcont_entity_id is None:
187 self.log.error("tcont-not-found-for-delete", alloc_id=self._alloc_id)
188 return
189
190 self.log.debug('found-tcont', tcont_entity_id=tcont_entity_id, alloc_id=self._alloc_id)
191
192 # Remove the TCONT (rather reset the TCONT to point alloc_id to 0xffff)
193 # The _tcont.remove_from_hardware is already doing check_status_and_state
194 yield self._tcont.remove_from_hardware(omci_cc)
195
196 # At this point, the gem-ports should have been removed already.
197 # Remove the 8021p Mapper and ANI MacBridgePortConfigData
198 yield self._delete__8021p_mapper__ani_mac_bridge_port()
199
200 # There are no other associated MEs now.
201 # There might be TrafficScheduler MEs that point to a TCONT.
202 # TrafficScheduler ME not used currently.
203
204 self.deferred.callback("tech-profile-remove-success--tcont")
205
206 except TimeoutError as e:
207 self.log.warn('rx-timeout-tech-profile', e=e)
208 self.deferred.errback(failure.Failure(e))
209
210 except Exception as e:
211 self.log.exception('omci-delete-tech-profile', e=e)
212 self.deferred.errback(failure.Failure(e))
213
214 @inlineCallbacks
215 def delete_gem_port_nw_ctp_and_associated_me(self):
216 omci_cc = self._onu_device.omci_cc
217 try:
218 ################################################################################
219 # Delete GemPortNetworkCTP and GemPortInterworkingPoint
220 ################################################################################
221 # The _gem_port.remove_from_hardware is already doing check_status_and_state
222 yield self._gem_port.remove_from_hardware(omci_cc)
223
224 self.deferred.callback("tech-profile-remove-success--gem-port")
225
226 except TimeoutError as e:
227 self.log.warn('rx-timeout-tech-profile', e=e)
228 self.deferred.errback(failure.Failure(e))
229
230 except Exception as e:
231 self.log.exception('omci-delete-tech-profile', e=e)
232 self.deferred.errback(failure.Failure(e))
233
234 @inlineCallbacks
235 def _delete__8021p_mapper__ani_mac_bridge_port(self):
236
237 omci_cc = self._onu_device.omci_cc
238
239 try:
240 ################################################################################
241 # Delete 8021p mapper
242 ################################################################################
243 msg = Ieee8021pMapperServiceProfileFrame(
244 self._ieee_mapper_service_profile_entity_id +
245 self._uni_port.mac_bridge_port_num +
246 self._tp_table_id
247 )
248 frame = msg.delete()
249 self.log.debug('openomci-msg', omci_msg=msg)
250 results = yield omci_cc.send(frame)
251 self.check_status_and_state(results, 'delete-8021p-mapper-service-profile')
252
253 ################################################################################
254 # Delete MacBridgePortConfigData
255 ################################################################################
256 # TODO: magic. make a static variable for tp_type
257 msg = MacBridgePortConfigurationDataFrame(
Matt Jeanneret2e5c6f12019-12-13 07:06:06 -0500258 self._mac_bridge_port_ani_entity_id + self._uni_port.entity_id + self._tp_table_id, # Entity ID
Girish Gowdrae933cd32019-11-21 21:04:41 +0530259 )
260 frame = msg.delete()
261 self.log.debug('openomci-msg', omci_msg=msg)
262 results = yield omci_cc.send(frame)
263 self.check_status_and_state(results, 'delete-mac-bridge-port-configuration-data-8021p-mapper')
264
265 except TimeoutError as e:
266 self.log.warn('rx-timeout-8021p-ani-port-delete', e=e)
267 raise
268
269 except Exception as e:
270 self.log.exception('omci-delete-8021p-ani-port-delete', e=e)
271 raise