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