blob: 3fa3ddc2518c03f6d6cd4e9a1e6d665bb3637391 [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 """
Girish Gowdrae933cd32019-11-21 21:04:41 +053063 super(BrcmTpDeleteTask, self).__init__(BrcmTpDeleteTask.name,
64 omci_agent,
65 handler.device_id,
66 priority=DELETE_TP_TASK_PRIORITY,
67 exclusive=True)
68
Matt Jeanneret08a8e862019-12-20 14:02:32 -050069 self.log = structlog.get_logger(device_id=handler.device_id,
70 name=BrcmTpDeleteTask.name,
71 task_id=self._task_id,
72 uni_id=uni_id,
73 tp_table_id=tp_table_id)
Girish Gowdrae933cd32019-11-21 21:04:41 +053074
75 self._onu_device = omci_agent.get_device(handler.device_id)
76 self._local_deferred = None
77
78 self._uni_port = handler.uni_ports[uni_id]
79 assert self._uni_port.uni_id == uni_id
80
81 # Tech Profile Table ID
82 self._tp_table_id = tp_table_id
83
84 self._tcont = tcont
85 self._gem_port = gem_port
86
87 self._alloc_id = self._tcont.alloc_id if self._tcont else None
88 self._gem_port_id = self._gem_port.gem_id if gem_port else None
89
90 # Entity IDs. IDs with values can probably be most anything for most ONUs,
91 # IDs set to None are discovered/set
92 self._mac_bridge_service_profile_entity_id = \
93 handler.mac_bridge_service_profile_entity_id
94 self._ieee_mapper_service_profile_entity_id = \
95 handler.pon_port.ieee_mapper_service_profile_entity_id
96 self._mac_bridge_port_ani_entity_id = \
97 handler.pon_port.mac_bridge_port_ani_entity_id
98
99 def cancel_deferred(self):
Girish Gowdrae933cd32019-11-21 21:04:41 +0530100 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 """
Girish Gowdrae933cd32019-11-21 21:04:41 +0530113 super(BrcmTpDeleteTask, self).start()
114 if self._tcont is not None:
115 self._local_deferred = reactor.callLater(0, self.delete_tcont_and_associated_me)
116 elif self._gem_port is not None:
117 self._local_deferred = reactor.callLater(0, self.delete_gem_port_nw_ctp_and_associated_me)
118 else:
119 raise Exception("both-alloc-id-and-gem-port-id-are-none")
120
121 def stop(self):
122 """
123 Shutdown Tech-Profile delete tasks
124 """
Girish Gowdrae933cd32019-11-21 21:04:41 +0530125 self.cancel_deferred()
126 super(BrcmTpDeleteTask, self).stop()
127
128 def check_status_and_state(self, results, operation=''):
129 """
130 Check the results of an OMCI response. An exception is thrown
131 if the task was cancelled or an error was detected.
132
133 :param results: (OmciFrame) OMCI Response frame
134 :param operation: (str) what operation was being performed
135 :return: True if successful, False if the entity existed (already created)
136 """
Girish Gowdrae933cd32019-11-21 21:04:41 +0530137
138 omci_msg = results.fields['omci_message'].fields
139 status = omci_msg['success_code']
140 error_mask = omci_msg.get('parameter_error_attributes_mask', 'n/a')
141 failed_mask = omci_msg.get('failed_attributes_mask', 'n/a')
142 unsupported_mask = omci_msg.get('unsupported_attributes_mask', 'n/a')
143
144 self.log.debug("OMCI Result", operation=operation, omci_msg=omci_msg, status=status, error_mask=error_mask,
145 failed_mask=failed_mask, unsupported_mask=unsupported_mask)
146
147 if status == RC.Success:
148 self.strobe_watchdog()
149 return True
150
151 elif status == RC.InstanceExists:
152 return False
153
154 raise TechProfileDeleteFailure(
155 '{} failed with a status of {}, error_mask: {}, failed_mask: {}, '
156 'unsupported_mask: {}'.format(operation, status, error_mask, failed_mask, unsupported_mask))
157
158 @inlineCallbacks
159 def delete_tcont_and_associated_me(self):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500160 self.log.info('deleting-tcont')
Girish Gowdrae933cd32019-11-21 21:04:41 +0530161
162 omci_cc = self._onu_device.omci_cc
163
164 try:
165 ################################################################################
166 # Reset TCONT ME
167 ################################################################################
168
169 tcont_idents = self._onu_device.query_mib(Tcont.class_id)
170 self.log.debug('tcont-idents', tcont_idents=tcont_idents)
171 tcont_entity_id = None
172 for k, v in tcont_idents.items():
173 if not isinstance(v, dict):
174 continue
175 alloc_check = v.get('attributes', {}).get('alloc_id', 0)
176 # Some onu report both to indicate an available tcont
177 if alloc_check == self._alloc_id:
178 tcont_entity_id = k
179 break
180
181 if tcont_entity_id is None:
182 self.log.error("tcont-not-found-for-delete", alloc_id=self._alloc_id)
183 return
184
185 self.log.debug('found-tcont', tcont_entity_id=tcont_entity_id, alloc_id=self._alloc_id)
186
187 # Remove the TCONT (rather reset the TCONT to point alloc_id to 0xffff)
188 # The _tcont.remove_from_hardware is already doing check_status_and_state
189 yield self._tcont.remove_from_hardware(omci_cc)
190
191 # At this point, the gem-ports should have been removed already.
192 # Remove the 8021p Mapper and ANI MacBridgePortConfigData
193 yield self._delete__8021p_mapper__ani_mac_bridge_port()
194
195 # There are no other associated MEs now.
196 # There might be TrafficScheduler MEs that point to a TCONT.
197 # TrafficScheduler ME not used currently.
198
199 self.deferred.callback("tech-profile-remove-success--tcont")
200
201 except TimeoutError as e:
202 self.log.warn('rx-timeout-tech-profile', e=e)
203 self.deferred.errback(failure.Failure(e))
204
205 except Exception as e:
206 self.log.exception('omci-delete-tech-profile', e=e)
207 self.deferred.errback(failure.Failure(e))
208
209 @inlineCallbacks
210 def delete_gem_port_nw_ctp_and_associated_me(self):
Matt Jeanneret08a8e862019-12-20 14:02:32 -0500211 self.log.info('deleting-gem-port-iw')
212
Girish Gowdrae933cd32019-11-21 21:04:41 +0530213 omci_cc = self._onu_device.omci_cc
214 try:
215 ################################################################################
216 # Delete GemPortNetworkCTP and GemPortInterworkingPoint
217 ################################################################################
218 # The _gem_port.remove_from_hardware is already doing check_status_and_state
219 yield self._gem_port.remove_from_hardware(omci_cc)
220
221 self.deferred.callback("tech-profile-remove-success--gem-port")
222
223 except TimeoutError as e:
224 self.log.warn('rx-timeout-tech-profile', e=e)
225 self.deferred.errback(failure.Failure(e))
226
227 except Exception as e:
228 self.log.exception('omci-delete-tech-profile', e=e)
229 self.deferred.errback(failure.Failure(e))
230
231 @inlineCallbacks
232 def _delete__8021p_mapper__ani_mac_bridge_port(self):
233
234 omci_cc = self._onu_device.omci_cc
235
236 try:
237 ################################################################################
238 # Delete 8021p mapper
239 ################################################################################
240 msg = Ieee8021pMapperServiceProfileFrame(
241 self._ieee_mapper_service_profile_entity_id +
242 self._uni_port.mac_bridge_port_num +
243 self._tp_table_id
244 )
245 frame = msg.delete()
246 self.log.debug('openomci-msg', omci_msg=msg)
247 results = yield omci_cc.send(frame)
248 self.check_status_and_state(results, 'delete-8021p-mapper-service-profile')
249
250 ################################################################################
251 # Delete MacBridgePortConfigData
252 ################################################################################
253 # TODO: magic. make a static variable for tp_type
254 msg = MacBridgePortConfigurationDataFrame(
Matt Jeanneret2e5c6f12019-12-13 07:06:06 -0500255 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 +0530256 )
257 frame = msg.delete()
258 self.log.debug('openomci-msg', omci_msg=msg)
259 results = yield omci_cc.send(frame)
260 self.check_status_and_state(results, 'delete-mac-bridge-port-configuration-data-8021p-mapper')
261
262 except TimeoutError as e:
263 self.log.warn('rx-timeout-8021p-ani-port-delete', e=e)
264 raise
265
266 except Exception as e:
267 self.log.exception('omci-delete-8021p-ani-port-delete', e=e)
268 raise