blob: ed3d21b9b866a5b54ddfcd0348ab7aef0bdc29f1 [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 Jeanneret72f96fc2019-02-11 10:53:05 -050016from pyvoltha.adapters.extensions.omci.tasks.task import Task
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050017from twisted.internet import reactor
18from twisted.internet.defer import inlineCallbacks, failure, returnValue
Matt Jeanneret72f96fc2019-02-11 10:53:05 -050019from pyvoltha.adapters.extensions.omci.omci_defs import ReasonCodes, EntityOperations
20from pyvoltha.adapters.extensions.omci.omci_me import *
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -050021
22RC = ReasonCodes
23OP = EntityOperations
24
25
26class BrcmVlanFilterException(Exception):
27 pass
28
29
30class BrcmVlanFilterTask(Task):
31 """
32 Apply Vlan Tagging Filter Data and Extended VLAN Tagging Operation Configuration on an ANI and UNI
33 """
34 task_priority = 200
35 name = "Broadcom VLAN Filter Task"
36
37 def __init__(self, omci_agent, device_id, uni_port, set_vlan_id, priority=task_priority):
38 """
39 Class initialization
40
41 :param omci_agent: (OmciAdapterAgent) OMCI Adapter agent
42 :param device_id: (str) ONU Device ID
43 :param set_vlan_id: (int) VLAN to filter for and set
44 :param priority: (int) OpenOMCI Task priority (0..255) 255 is the highest
45 """
46
47 self.log = structlog.get_logger(device_id=device_id, uni_port=uni_port.port_number)
48
49 super(BrcmVlanFilterTask, self).__init__(BrcmVlanFilterTask.name,
50 omci_agent,
51 device_id,
52 priority=priority,
53 exclusive=True)
54 self._device = omci_agent.get_device(device_id)
55 self._uni_port = uni_port
56 self._set_vlan_id = set_vlan_id
57 self._results = None
58 self._local_deferred = None
59 self._config = self._device.configuration
60
61 def cancel_deferred(self):
62 super(BrcmVlanFilterTask, self).cancel_deferred()
63
64 d, self._local_deferred = self._local_deferred, None
65 try:
66 if d is not None and not d.called:
67 d.cancel()
68 except:
69 pass
70
71 def start(self):
72 """
73 Start Vlan Tagging Task
74 """
75 super(BrcmVlanFilterTask, self).start()
76 self._local_deferred = reactor.callLater(0, self.perform_vlan_tagging)
77
78 @inlineCallbacks
79 def perform_vlan_tagging(self):
80 """
81 Perform the vlan tagging
82 """
83 self.log.info('setting-vlan-tagging')
84
85 try:
86 # TODO: parameterize these from the handler, or objects in the handler
87 # TODO: make this a member of the onu gem port or the uni port
88 _mac_bridge_service_profile_entity_id = 0x201
89 _mac_bridge_port_ani_entity_id = 0x2102 # TODO: can we just use the entity id from the anis list?
90 # Delete bridge ani side vlan filter
91 msg = VlanTaggingFilterDataFrame(_mac_bridge_port_ani_entity_id + self._uni_port.mac_bridge_port_num)
92 frame = msg.delete()
93 self.log.debug('openomci-msg', omci_msg=msg)
94 self.strobe_watchdog()
95 results = yield self._device.omci_cc.send(frame)
96 self.check_status_and_state(results, 'flow-delete-vlan-tagging-filter-data')
97
98 # Re-Create bridge ani side vlan filter
99 msg = VlanTaggingFilterDataFrame(
100 _mac_bridge_port_ani_entity_id + self._uni_port.mac_bridge_port_num, # Entity ID
101 vlan_tcis=[self._set_vlan_id], # VLAN IDs
102 forward_operation=0x10
103 )
104 frame = msg.create()
105 self.log.debug('openomci-msg', omci_msg=msg)
106 self.strobe_watchdog()
107 results = yield self._device.omci_cc.send(frame)
108 self.check_status_and_state(results, 'flow-create-vlan-tagging-filter-data')
109
110 # Re-Create bridge ani side vlan filter
111
112 # Update uni side extended vlan filter
113 # filter for untagged
114 # probably for eapol
115 # TODO: Create constants for the operation values. See omci spec
116 attributes = dict(
117 received_frame_vlan_tagging_operation_table=
118 VlanTaggingOperation(
119 filter_outer_priority=15,
120 filter_outer_vid=4096,
121 filter_outer_tpid_de=0,
122
123 filter_inner_priority=15,
124 filter_inner_vid=4096,
125 filter_inner_tpid_de=0,
126 filter_ether_type=0,
127
128 treatment_tags_to_remove=0,
129 treatment_outer_priority=15,
130 treatment_outer_vid=0,
131 treatment_outer_tpid_de=0,
132
133 treatment_inner_priority=0,
134 treatment_inner_vid=self._set_vlan_id,
135 treatment_inner_tpid_de=4
136 )
137 )
138 msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
139 _mac_bridge_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # Bridge Entity ID
140 attributes=attributes # See above
141 )
142 frame = msg.set()
143 self.log.debug('openomci-msg', omci_msg=msg)
144 self.strobe_watchdog()
145 results = yield self._device.omci_cc.send(frame)
146 self.check_status_and_state(results,
147 'flow-set-ext-vlan-tagging-op-config-data-untagged')
148
149 # Update uni side extended vlan filter
150 # filter for vlan 0
151 # TODO: Create constants for the operation values. See omci spec
152 attributes = dict(
153 received_frame_vlan_tagging_operation_table=
154 VlanTaggingOperation(
155 filter_outer_priority=15, # This entry is not a double-tag rule
156 filter_outer_vid=4096, # Do not filter on the outer VID value
157 filter_outer_tpid_de=0, # Do not filter on the outer TPID field
158
159 filter_inner_priority=8, # Filter on inner vlan
160 filter_inner_vid=0x0, # Look for vlan 0
161 filter_inner_tpid_de=0, # Do not filter on inner TPID field
162 filter_ether_type=0, # Do not filter on EtherType
163
164 treatment_tags_to_remove=1,
165 treatment_outer_priority=15,
166 treatment_outer_vid=0,
167 treatment_outer_tpid_de=0,
168
169 treatment_inner_priority=8, # Add an inner tag and insert this value as the priority
170 treatment_inner_vid=self._set_vlan_id, # use this value as the VID in the inner VLAN tag
171 treatment_inner_tpid_de=4, # set TPID
172 )
173 )
174 msg = ExtendedVlanTaggingOperationConfigurationDataFrame(
175 _mac_bridge_service_profile_entity_id + self._uni_port.mac_bridge_port_num, # Bridge Entity ID
176 attributes=attributes # See above
177 )
178 frame = msg.set()
179 self.log.debug('openomci-msg', omci_msg=msg)
180 self.strobe_watchdog()
181 results = yield self._device.omci_cc.send(frame)
182 self.check_status_and_state(results,
183 'flow-set-ext-vlan-tagging-op-config-data-zero-tagged')
184
185 self.deferred.callback(self)
186
187 except Exception as e:
188 self.log.exception('setting-vlan-tagging', e=e)
189 self.deferred.errback(failure.Failure(e))
190
191 def check_status_and_state(self, results, operation=''):
192 """
193 Check the results of an OMCI response. An exception is thrown
194 if the task was cancelled or an error was detected.
195
196 :param results: (OmciFrame) OMCI Response frame
197 :param operation: (str) what operation was being performed
198 :return: True if successful, False if the entity existed (already created)
199 """
200
201 omci_msg = results.fields['omci_message'].fields
202 status = omci_msg['success_code']
203 error_mask = omci_msg.get('parameter_error_attributes_mask', 'n/a')
204 failed_mask = omci_msg.get('failed_attributes_mask', 'n/a')
205 unsupported_mask = omci_msg.get('unsupported_attributes_mask', 'n/a')
206
Matt Jeannerete8fc53e2019-04-13 15:58:33 -0400207 self.log.debug("OMCI Result", operation=operation, omci_msg=omci_msg,
Matt Jeanneretf1e9c5d2019-02-08 07:41:29 -0500208 status=status, error_mask=error_mask,
209 failed_mask=failed_mask, unsupported_mask=unsupported_mask)
210
211 if status == RC.Success:
212 self.strobe_watchdog()
213 return True
214
215 elif status == RC.InstanceExists:
216 return False