blob: e3706af9f9c57a1c152a244c6d26adbcbc34ca31 [file] [log] [blame]
Zsolt Harasztied091602016-12-08 13:36:38 -08001#
Zsolt Haraszti3eb27a52017-01-03 21:56:48 -08002# Copyright 2017 the original author or authors.
Zsolt Harasztied091602016-12-08 13:36:38 -08003#
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#
16
17"""
18Tibit ONU device adapter
19"""
20
Paul Grayeee44382017-03-31 09:00:25 -070021import time
22import struct
Paul Gray934d2882017-05-25 04:44:49 -070023import re
Zsolt Haraszti348d1932016-12-10 01:10:07 -080024
25from uuid import uuid4
26
Zsolt Harasztic5f740b2017-01-18 09:53:17 -080027import arrow
Zsolt Harasztied091602016-12-08 13:36:38 -080028import structlog
Zsolt Harasztic5f740b2017-01-18 09:53:17 -080029from twisted.internet.task import LoopingCall
Zsolt Harasztied091602016-12-08 13:36:38 -080030from zope.interface import implementer
31
Zsolt Haraszti348d1932016-12-10 01:10:07 -080032from scapy.layers.inet import ICMP, IP
33from scapy.layers.l2 import Ether
34from twisted.internet.defer import DeferredQueue, inlineCallbacks
35from twisted.internet import reactor
36
Zsolt Haraszti85f12852016-12-24 08:30:58 -080037from voltha.core.flow_decomposer import *
Zsolt Haraszti348d1932016-12-10 01:10:07 -080038from voltha.core.logical_device_agent import mac_str_to_tuple
Nathan Knutha1a11932017-01-12 16:59:58 -080039from common.frameio.frameio import BpfProgramFilter, hexify
Zsolt Harasztied091602016-12-08 13:36:38 -080040from voltha.adapters.interface import IAdapterInterface
41from voltha.protos.adapter_pb2 import Adapter, AdapterConfig
ggowdru236bd952017-06-20 20:32:55 -070042from voltha.protos.device_pb2 import Port, Image
Zsolt Harasztied091602016-12-08 13:36:38 -080043from voltha.protos.device_pb2 import DeviceType, DeviceTypes
Zsolt Harasztic5f740b2017-01-18 09:53:17 -080044from voltha.protos.events_pb2 import KpiEventType
45from voltha.protos.events_pb2 import MetricValuePairs, KpiEvent
Zsolt Harasztied091602016-12-08 13:36:38 -080046from voltha.protos.health_pb2 import HealthStatus
Zsolt Haraszti348d1932016-12-10 01:10:07 -080047from voltha.protos.common_pb2 import LogLevel, ConnectStatus
Zsolt Haraszti348d1932016-12-10 01:10:07 -080048from voltha.protos.common_pb2 import OperStatus, AdminState
49
50from voltha.protos.logical_device_pb2 import LogicalDevice, LogicalPort
51from voltha.protos.openflow_13_pb2 import ofp_desc, ofp_port, OFPPF_10GB_FD, \
52 OFPPF_FIBER, OFPPS_LIVE, ofp_switch_features, OFPC_PORT_STATS, \
53 OFPC_GROUP_STATS, OFPC_TABLE_STATS, OFPC_FLOW_STATS
54
55from scapy.packet import Packet, bind_layers
56from scapy.fields import StrField
Zsolt Harasztied091602016-12-08 13:36:38 -080057
58log = structlog.get_logger()
59
Paul Graycfc2dc32017-05-31 12:58:43 -070060from voltha.extensions.eoam.EOAM_TLV import UserPortObject
Nathan Knuth31c36962016-12-27 10:04:49 -080061from voltha.extensions.eoam.EOAM_TLV import AddStaticMacAddress, DeleteStaticMacAddress
62from voltha.extensions.eoam.EOAM_TLV import ClearStaticMacTable
63from voltha.extensions.eoam.EOAM_TLV import DeviceId
Andrew Chagnon48ecb442017-08-22 11:01:25 -040064from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum, RuleClauses
65from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum, RuleOperators
66from voltha.extensions.eoam.EOAM_TLV import DPoEOpcodeEnum, DPoEVariableResponseEnum
Paul Grayef008892017-05-17 12:28:45 -070067from voltha.extensions.eoam.EOAM_TLV import DPoEOpcode_MulticastRegister, MulticastRegisterSet
Paul Gray934d2882017-05-25 04:44:49 -070068from voltha.extensions.eoam.EOAM_TLV import VendorName, OnuMode, HardwareVersion, ManufacturerInfo
Paul Gray7a312e42017-05-25 15:08:00 -070069from voltha.extensions.eoam.EOAM_TLV import SlowProtocolsSubtypeEnum, DeviceReset
Paul Graycfc2dc32017-05-31 12:58:43 -070070from voltha.extensions.eoam.EOAM_TLV import DONUObject, \
71 UserPortObject, PonPortObject, \
72 PortIngressRuleClauseMatchLength00, PortIngressRuleClauseMatchLength01, \
73 PortIngressRuleClauseMatchLength02, PortIngressRuleResultForward, \
74 PortIngressRuleResultSet, PortIngressRuleResultInsert, \
75 PortIngressRuleResultCopy, PortIngressRuleResultReplace, \
76 PortIngressRuleResultDelete, PortIngressRuleResultOLTQueue, \
Andrew Chagnon48ecb442017-08-22 11:01:25 -040077 PortIngressRuleTerminator, AddPortIngressRule, DPoEOpcodes
Paul Graycfc2dc32017-05-31 12:58:43 -070078from voltha.extensions.eoam.EOAM_TLV import PortIngressRuleHeader
Paul Gray934d2882017-05-25 04:44:49 -070079from voltha.extensions.eoam.EOAM_TLV import EndOfPDU
Nathan Knuthd8285e62017-01-11 14:18:43 -060080
Andrew Chagnon48ecb442017-08-22 11:01:25 -040081from voltha.extensions.eoam.EOAM_Layers import EOAMPayload, EOAM_EventMsg, EOAM_VendSpecificMsg
82from voltha.extensions.eoam.EOAM_Layers import EOAM_TibitMsg, EOAM_DpoeMsg
83from voltha.extensions.eoam.EOAM_Layers import OAM_ETHERTYPE
84from voltha.extensions.eoam.EOAM_Layers import CABLELABS_OUI, TIBIT_OUI
85from voltha.extensions.eoam.EOAM_Layers import RxedOamMsgTypeEnum, RxedOamMsgTypes
Nathan Knuth31c36962016-12-27 10:04:49 -080086from voltha.extensions.eoam.EOAM import DPoEOpcode_GetRequest, DPoEOpcode_SetRequest
Andrew Chagnon48ecb442017-08-22 11:01:25 -040087from voltha.extensions.eoam.EOAM import mcastIp2McastMac, get_oam_msg_type, get_value_from_msg, check_set_resp, check_resp
88
Zsolt Harasztied091602016-12-08 13:36:38 -080089
Paul Grayeee44382017-03-31 09:00:25 -070090TIBIT_MSG_WAIT_TIME = 3
91
Paul Gray934d2882017-05-25 04:44:49 -070092
Zsolt Harasztied091602016-12-08 13:36:38 -080093@implementer(IAdapterInterface)
94class TibitOnuAdapter(object):
95
96 name = 'tibit_onu'
97
98 supported_device_types = [
99 DeviceType(
100 id='tibit_onu',
101 adapter=name,
102 accepts_bulk_flow_update=True
103 )
104 ]
105
106 def __init__(self, adapter_agent, config):
107 self.adapter_agent = adapter_agent
108 self.config = config
109 self.descriptor = Adapter(
110 id=self.name,
111 vendor='Tibit Communications Inc.',
112 version='0.1',
113 config=AdapterConfig(log_level=LogLevel.INFO)
114 )
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800115 self.incoming_messages = DeferredQueue()
Paul Gray934d2882017-05-25 04:44:49 -0700116 self.mode = "GPON"
Zsolt Harasztied091602016-12-08 13:36:38 -0800117
118 def start(self):
119 log.debug('starting')
120 log.info('started')
121
122 def stop(self):
123 log.debug('stopping')
124 log.info('stopped')
125
126 def adapter_descriptor(self):
127 return self.descriptor
128
129 def device_types(self):
130 return DeviceTypes(items=self.supported_device_types)
131
132 def health(self):
133 return HealthStatus(state=HealthStatus.HealthState.HEALTHY)
134
135 def change_master_state(self, master):
136 raise NotImplementedError()
137
Sergio Slobodrianec864c62017-03-09 11:41:43 -0500138 def update_pm_config(self, device, pm_configs):
139 raise NotImplementedError()
140
Zsolt Harasztied091602016-12-08 13:36:38 -0800141 def adopt_device(self, device):
142 log.info('adopt-device', device=device)
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800143 reactor.callLater(0.1, self._onu_device_activation, device)
Zsolt Harasztied091602016-12-08 13:36:38 -0800144 return device
145
khenaidoo032d3302017-06-09 14:50:04 -0400146 def reconcile_device(self, device):
147 raise NotImplementedError()
148
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800149 @inlineCallbacks
150 def _onu_device_activation(self, device):
151 # first we verify that we got parent reference and proxy info
152 assert device.parent_id
153 assert device.proxy_address.device_id
154 assert device.proxy_address.channel_id
155
Paul Gray934d2882017-05-25 04:44:49 -0700156 # Device information will be updated later on
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800157 device.vendor = 'Tibit Communications, Inc.'
158 device.model = '10G GPON ONU'
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800159 device.connect_status = ConnectStatus.REACHABLE
160 self.adapter_agent.update_device(device)
161
162 # then shortly after we create some ports for the device
163 uni_port = Port(
164 port_no=2,
165 label='UNI facing Ethernet port',
166 type=Port.ETHERNET_UNI,
167 admin_state=AdminState.ENABLED,
168 oper_status=OperStatus.ACTIVE
169 )
170 self.adapter_agent.add_port(device.id, uni_port)
171 self.adapter_agent.add_port(device.id, Port(
172 port_no=1,
173 label='PON port',
174 type=Port.PON_ONU,
175 admin_state=AdminState.ENABLED,
176 oper_status=OperStatus.ACTIVE,
177 peers=[
178 Port.PeerPort(
179 device_id=device.parent_id,
180 port_no=device.parent_port_no
181 )
182 ]
183 ))
184
185 # TODO adding vports to the logical device shall be done by agent?
186 # then we create the logical device port that corresponds to the UNI
187 # port of the device
188
189 # obtain logical device id
190 parent_device = self.adapter_agent.get_device(device.parent_id)
191 logical_device_id = parent_device.parent_id
192 assert logical_device_id
193
194 # we are going to use the proxy_address.channel_id as unique number
195 # and name for the virtual ports, as this is guaranteed to be unique
196 # in the context of the OLT port, so it is also unique in the context
197 # of the logical device
198 port_no = device.proxy_address.channel_id
199 cap = OFPPF_10GB_FD | OFPPF_FIBER
200 self.adapter_agent.add_logical_port(logical_device_id, LogicalPort(
201 id=str(port_no),
202 ofp_port=ofp_port(
203 port_no=port_no,
204 hw_addr=mac_str_to_tuple(device.mac_address),
205 name='uni-{}'.format(port_no),
206 config=0,
207 state=OFPPS_LIVE,
208 curr=cap,
209 advertised=cap,
210 peer=cap,
211 curr_speed=OFPPF_10GB_FD,
212 max_speed=OFPPF_10GB_FD
213 ),
214 device_id=device.id,
215 device_port_no=uni_port.port_no
216 ))
217
218 # simulate a proxied message sending and receving a reply
219 reply = yield self._message_exchange(device)
220
Paul Grayef008892017-05-17 12:28:45 -0700221 # TODO - Need to add validation of reply and decide what to do upon failure
222
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800223 # and finally update to "ACTIVE"
224 device = self.adapter_agent.get_device(device.id)
225 device.oper_status = OperStatus.ACTIVE
226 self.adapter_agent.update_device(device)
227
Paul Grayef008892017-05-17 12:28:45 -0700228 # TODO - Disable Stats Reporting for the moment
229 #self.start_kpi_collection(device.id)
Zsolt Harasztic5f740b2017-01-18 09:53:17 -0800230
Zsolt Harasztied091602016-12-08 13:36:38 -0800231 def abandon_device(self, device):
232 raise NotImplementedError(0
233 )
Khen Nursimulud068d812017-03-06 11:44:18 -0500234 def disable_device(self, device):
Andrew Chagnona09233a2017-07-25 12:53:55 -0400235 log.info('disabling', device_id=device.id)
236
237 # Disable all ports on that device
238 self.adapter_agent.disable_all_ports(device.id)
239
240 # Update the device operational status to UNKNOWN
241 device.oper_status = OperStatus.UNKNOWN
242 device.connect_status = ConnectStatus.UNREACHABLE
243 self.adapter_agent.update_device(device)
244
245 # Remove the uni logical port from the OLT, if still present
246 parent_device = self.adapter_agent.get_device(device.parent_id)
247 assert parent_device
248 logical_device_id = parent_device.parent_id
249 assert logical_device_id
250 port_no = device.proxy_address.channel_id
251# port_id = 'uni-{}'.format(port_no)
252 port_id = '{}'.format(port_no)
253 try:
254 port = self.adapter_agent.get_logical_port(logical_device_id,
255 port_id)
256 self.adapter_agent.delete_logical_port(logical_device_id, port)
257 except KeyError:
258 log.info('logical-port-not-found', device_id=device.id,
259 portid=port_id)
260
261 # Remove pon port from parent
262 #self.adapter_agent.delete_port_reference_from_parent(device.id,
263 # self.pon_port)
264
265 # Just updating the port status may be an option as well
266 # port.ofp_port.config = OFPPC_NO_RECV
267 # yield self.adapter_agent.update_logical_port(logical_device_id,
268 # port)
269 # Unregister for proxied message
270 self.adapter_agent.unregister_for_proxied_messages(device.proxy_address)
271
272 # TODO:
273 # 1) Remove all flows from the device
274 # 2) Remove the device from ponsim
275
276 log.info('disabled', device_id=device.id)
277
Paul Gray7a312e42017-05-25 15:08:00 -0700278 return device
Khen Nursimulud068d812017-03-06 11:44:18 -0500279
280 def reenable_device(self, device):
Andrew Chagnona09233a2017-07-25 12:53:55 -0400281 log.info('re-enabling', device_id=device.id)
282
283 # First we verify that we got parent reference and proxy info
284 assert device.parent_id
285 assert device.proxy_address.device_id
286 assert device.proxy_address.channel_id
287
288 # Re-register for proxied messages right away
289 #self.proxy_address = device.proxy_address
290 self.adapter_agent.register_for_proxied_messages(device.proxy_address)
291
292 # Re-enable the ports on that device
293 self.adapter_agent.enable_all_ports(device.id)
294
295 # Add the pon port reference to the parent
296 #self.adapter_agent.add_port_reference_to_parent(device.id,
297 # self.pon_port)
298
299 # Update the connect status to REACHABLE
300 device.connect_status = ConnectStatus.REACHABLE
301 self.adapter_agent.update_device(device)
302
303 # re-add uni port to logical device
304 parent_device = self.adapter_agent.get_device(device.parent_id)
305 logical_device_id = parent_device.parent_id
306 assert logical_device_id
307 port_no = device.proxy_address.channel_id
308 cap = OFPPF_10GB_FD | OFPPF_FIBER
309 self.adapter_agent.add_logical_port(logical_device_id, LogicalPort(
310# id='uni-{}'.format(port_no),
311 id= str(port_no),
312 ofp_port=ofp_port(
313 port_no=port_no,
314 hw_addr=mac_str_to_tuple(device.mac_address),
315 name='uni-{}'.format(port_no),
316 config=0,
317 state=OFPPS_LIVE,
318 curr=cap,
319 advertised=cap,
320 peer=cap,
321 curr_speed=OFPPF_10GB_FD,
322 max_speed=OFPPF_10GB_FD
323 ),
324 device_id=device.id,
325 device_port_no=2
326 ))
327
328 device = self.adapter_agent.get_device(device.id)
329 device.oper_status = OperStatus.ACTIVE
330 self.adapter_agent.update_device(device)
331
332 log.info('re-enabled', device_id=device.id)
333
Khen Nursimulud068d812017-03-06 11:44:18 -0500334
Paul Gray7a312e42017-05-25 15:08:00 -0700335 @inlineCallbacks
Khen Nursimulud068d812017-03-06 11:44:18 -0500336 def reboot_device(self, device):
Paul Gray7a312e42017-05-25 15:08:00 -0700337 log.info('Rebooting ONU: {}'.format(device.mac_address))
338
339 # Update the operational status to ACTIVATING and connect status to
340 # UNREACHABLE
341 previous_oper_status = device.oper_status
342 previous_conn_status = device.connect_status
343 device.oper_status = OperStatus.ACTIVATING
344 device.connect_status = ConnectStatus.UNREACHABLE
345 self.adapter_agent.update_device(device)
346
Paul Gray7a312e42017-05-25 15:08:00 -0700347 # send message
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400348 action = "Device Reset"
Paul Gray7a312e42017-05-25 15:08:00 -0700349 rc = []
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400350 tlvs = DeviceReset()
351 yield self._set_req_rsp(device, action, tlvs, rc)
Paul Gray7a312e42017-05-25 15:08:00 -0700352
353 # Change the operational status back to its previous state.
354 device.oper_status = previous_oper_status
355 device.connect_status = previous_conn_status
356 self.adapter_agent.update_device(device)
357
358 log.info('ONU Rebooted: {}'.format(device.mac_address))
Khen Nursimulud068d812017-03-06 11:44:18 -0500359
Lydia Fang01f2e852017-06-28 17:24:58 -0700360 def download_image(self, device, request):
361 raise NotImplementedError()
362
363 def get_image_download_status(self, device, request):
364 raise NotImplementedError()
365
366 def cancel_image_download(self, device, request):
367 raise NotImplementedError()
368
369 def activate_image_update(self, device, request):
370 raise NotImplementedError()
371
372 def revert_image_update(self, device, request):
373 raise NotImplementedError()
374
sathishg5ae86222017-06-28 15:16:29 +0530375 def self_test_device(self, device):
376 """
377 This is called to Self a device based on a NBI call.
378 :param device: A Voltha.Device object.
379 :return: Will return result of self test
380 """
381 log.info('self-test-device', device=device.id)
382 raise NotImplementedError()
383
Khen Nursimulud068d812017-03-06 11:44:18 -0500384 def delete_device(self, device):
Andrew Chagnona09233a2017-07-25 12:53:55 -0400385 log.info('deleting', device_id=device.id)
386
387 # A delete request may be received when an OLT is disabled
388
389 # TODO:
390 # 1) Remove all flows from the device
391 # 2) Remove the device from ponsim
392
393 log.info('deleted', device_id=device.id)
Khen Nursimulud068d812017-03-06 11:44:18 -0500394
395 def get_device_details(self, device):
Zsolt Harasztied091602016-12-08 13:36:38 -0800396 raise NotImplementedError()
397
Paul Grayeee44382017-03-31 09:00:25 -0700398 @inlineCallbacks
Zsolt Harasztied091602016-12-08 13:36:38 -0800399 def update_flows_bulk(self, device, flows, groups):
Nathan Knuthd8285e62017-01-11 14:18:43 -0600400 log.info('########################################')
401 log.info('bulk-flow-update', device_id=device.id,
402 flows=flows, groups=groups)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800403 assert len(groups.items) == 0, "Cannot yet deal with groups"
404
Andrew Chagnona09233a2017-07-25 12:53:55 -0400405 # Only do something if there are flows to program
406 if (len(flows.items) > 0):
407 # Clear the existing entries in the Static MAC Address Table
408 yield self._send_clear_static_mac_table(device)
Paul Gray934d2882017-05-25 04:44:49 -0700409
Andrew Chagnona09233a2017-07-25 12:53:55 -0400410 # Re-add the IGMP Multicast Address
411 yield self._send_igmp_mcast_addr(device)
Paul Gray934d2882017-05-25 04:44:49 -0700412
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800413 for flow in flows.items:
414 in_port = get_in_port(flow)
415 assert in_port is not None
416
Nathan Knuthd8285e62017-01-11 14:18:43 -0600417 precedence = 255 - min(flow.priority / 256, 255)
418
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800419 if in_port == 2:
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600420 log.info('#### Upstream Rule ####')
Paul Grayef008892017-05-17 12:28:45 -0700421
Paul Graycfc2dc32017-05-31 12:58:43 -0700422 up_req = UserPortObject()
423 up_req /= PortIngressRuleHeader(precedence=precedence)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800424
425 for field in get_ofb_fields(flow):
Nathan Knuthd8285e62017-01-11 14:18:43 -0600426
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800427 if field.type == ETH_TYPE:
428 _type = field.eth_type
Nathan Knuthd8285e62017-01-11 14:18:43 -0600429 log.info('#### field.type == ETH_TYPE ####',field_type=_type)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800430
431 elif field.type == IP_PROTO:
432 _proto = field.ip_proto
Nathan Knuthd8285e62017-01-11 14:18:43 -0600433 log.info('#### field.type == IP_PROTO ####')
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800434
435 elif field.type == IN_PORT:
436 _port = field.port
Nathan Knuthd8285e62017-01-11 14:18:43 -0600437 log.info('#### field.type == IN_PORT ####', port=_port)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800438
439 elif field.type == VLAN_VID:
Nathan Knuthd8285e62017-01-11 14:18:43 -0600440 _vlan_vid = field.vlan_vid & 0xfff
441 log.info('#### field.type == VLAN_VID ####', vlan=_vlan_vid)
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400442 up_req /= PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=0,
443 operator=RuleOperators['=='], match=_vlan_vid)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800444
445 elif field.type == VLAN_PCP:
446 _vlan_pcp = field.vlan_pcp
Nathan Knuthd8285e62017-01-11 14:18:43 -0600447 log.info('#### field.type == VLAN_PCP ####', pcp=_vlan_pcp)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800448
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800449 elif field.type == UDP_DST:
450 _udp_dst = field.udp_dst
Paul Graycfc2dc32017-05-31 12:58:43 -0700451 log.info('#### field.type == UDP_DST ####', udp_dst=_udp_dst)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800452
Nathan Knuthd8285e62017-01-11 14:18:43 -0600453 elif field.type == IPV4_DST:
454 _ipv4_dst = field.ipv4_dst
Paul Graycfc2dc32017-05-31 12:58:43 -0700455 log.info('#### field.type == IPV4_DST ####', ipv4_dst=_ipv4_dst)
456
457 elif field.type == METADATA:
458 _metadata = field.table_metadata
459 log.info('#### field.type == METADATA ####', metadata=_metadata)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600460
461 else:
462 log.info('#### field.type == NOT IMPLEMENTED!! ####')
463 raise NotImplementedError('field.type={}'.format(
464 field.type))
465
466 for action in get_actions(flow):
467
468 if action.type == OUTPUT:
469 log.info('#### action.type == OUTPUT ####')
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400470 up_req /= PortIngressRuleResultInsert(fieldcode=RuleClauses['C-VLAN Tag'])
Nathan Knuthd8285e62017-01-11 14:18:43 -0600471
472 elif action.type == POP_VLAN:
473 log.info('#### action.type == POP_VLAN ####')
Nathan Knuthd8285e62017-01-11 14:18:43 -0600474
475 elif action.type == PUSH_VLAN:
476 log.info('#### action.type == PUSH_VLAN ####')
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400477 up_req /= PortIngressRuleResultInsert(fieldcode=RuleClauses['C-VLAN Tag'])
Paul Graycfc2dc32017-05-31 12:58:43 -0700478# if action.push.ethertype != 0x8100:
479# log.error('unhandled-tpid',
480# ethertype=action.push.ethertype)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600481
482 elif action.type == SET_FIELD:
483 log.info('#### action.type == SET_FIELD ####')
484 assert (action.set_field.field.oxm_class ==
485 ofp.OFPXMC_OPENFLOW_BASIC)
486 field = action.set_field.field.ofb_field
487 if field.type == VLAN_VID:
Paul Graycfc2dc32017-05-31 12:58:43 -0700488 log.info("#### action.field.vlan {} ####".format(field.vlan_vid & 0xfff))
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400489 # need to convert value in Set to a variable length value
490 ctagStr = struct.pack('>H', (field.vlan_vid & 0xfff))
491
Paul Graycfc2dc32017-05-31 12:58:43 -0700492 up_req /= PortIngressRuleResultSet(
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400493 fieldcode=RuleClauses['C-VLAN Tag'], value=ctagStr)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600494 else:
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400495 raise NotImplementedError('unsupported-action-set-field-type={}'.format(field.type))
Nathan Knuthd8285e62017-01-11 14:18:43 -0600496 else:
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400497 raise NotImplementedError('unsupported-action-type={}'.format(action.type))
Nathan Knuthd8285e62017-01-11 14:18:43 -0600498
Paul Graycfc2dc32017-05-31 12:58:43 -0700499 up_req /= PortIngressRuleTerminator()
500 up_req /= AddPortIngressRule()
501
Paul Graycfc2dc32017-05-31 12:58:43 -0700502 # send message
503 action = "Set ONU US Rule"
Paul Graycfc2dc32017-05-31 12:58:43 -0700504 rc = []
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400505 yield self._set_req_rsp(device, action, up_req, rc)
Paul Graycfc2dc32017-05-31 12:58:43 -0700506
507
Nathan Knuthd8285e62017-01-11 14:18:43 -0600508 elif in_port == 1:
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600509 log.info('#### Downstream Rule ####')
Paul Graycfc2dc32017-05-31 12:58:43 -0700510 Is_MCast = False
511
512 dn_req = PonPortObject()
513 dn_req /= PortIngressRuleHeader(precedence=precedence)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600514
515 #### Loop through fields again...
516
517 for field in get_ofb_fields(flow):
518
519 if field.type == ETH_TYPE:
520 _type = field.eth_type
521 log.info('#### field.type == ETH_TYPE ####', in_port=in_port,
522 match=_type)
523
524 elif field.type == IP_PROTO:
525 _proto = field.ip_proto
526 log.info('#### field.type == IP_PROTO ####', in_port=in_port,
Paul Graycfc2dc32017-05-31 12:58:43 -0700527 ip_proto=_proto)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600528
529 elif field.type == IN_PORT:
530 _port = field.port
531 log.info('#### field.type == IN_PORT ####')
Nathan Knuthd8285e62017-01-11 14:18:43 -0600532
533 elif field.type == VLAN_VID:
534 _vlan_vid = field.vlan_vid & 0xfff
535 log.info('#### field.type == VLAN_VID ####')
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400536 dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=RuleClauses['C-VLAN Tag'], fieldinstance=0,
537 operator=RuleOperators['=='], match=_vlan_vid)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600538
539 elif field.type == VLAN_PCP:
540 _vlan_pcp = field.vlan_pcp
541 log.info('#### field.type == VLAN_PCP ####')
Nathan Knuthd8285e62017-01-11 14:18:43 -0600542
543 elif field.type == UDP_DST:
544 _udp_dst = field.udp_dst
545 log.info('#### field.type == UDP_DST ####')
546
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600547 elif field.type == IPV4_DST:
548 _ipv4_dst = field.ipv4_dst
549 log.info('#### field.type == IPV4_DST ####')
550 a = int(hex(_ipv4_dst)[2:4], 16)
551 b = int(hex(_ipv4_dst)[4:6], 16)
552 c = int(hex(_ipv4_dst)[6:8], 16)
553 d = int(hex(_ipv4_dst)[8:], 16)
Paul Graycfc2dc32017-05-31 12:58:43 -0700554 dn_req = AddStaticMacAddress(mac=mcastIp2McastMac('%d.%d.%d.%d' % (a,b,c,d)))
555 Is_MCast = True
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600556
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800557 else:
558 raise NotImplementedError('field.type={}'.format(
559 field.type))
560
561 for action in get_actions(flow):
562
563 if action.type == OUTPUT:
Nathan Knuthd8285e62017-01-11 14:18:43 -0600564 log.info('#### action.type == OUTPUT ####')
565
566 elif action.type == POP_VLAN:
567 log.info('#### action.type == POP_VLAN ####')
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400568
569 # TODO - This is not the correct operation for a POP operation.
570 # This should be a Delete result
571 dn_req /= PortIngressRuleResultReplace(fieldcode=RuleClauses['C-VLAN Tag'])
572 # need to convert value in Set to a variable length value
573 ctagStr = struct.pack('>H', (field.vlan_vid & 0xfff))
Paul Graycfc2dc32017-05-31 12:58:43 -0700574 dn_req /= PortIngressRuleResultSet(
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400575 fieldcode=RuleClauses['C-VLAN Tag'], value=ctagStr)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800576
577 elif action.type == PUSH_VLAN:
Nathan Knuthd8285e62017-01-11 14:18:43 -0600578 log.info('#### action.type == PUSH_VLAN ####')
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800579 if action.push.ethertype != 0x8100:
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400580 raise NotImplementedError('unhandled-ether-type={}'.format(action.push.ethertype))
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800581
582 elif action.type == SET_FIELD:
Nathan Knuthd8285e62017-01-11 14:18:43 -0600583 log.info('#### action.type == SET_FIELD ####')
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800584 assert (action.set_field.field.oxm_class ==
585 ofp.OFPXMC_OPENFLOW_BASIC)
586 field = action.set_field.field.ofb_field
587 if field.type == VLAN_VID:
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400588 log.info("#### action.field.vlan {} ####".format(field.vlan_vid & 0xfff))
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800589
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400590 # TODO - Currently only support setting the VID in the DS to zero (clearing the VID)
591 if ((field.vlan_vid & 0xfff) == 0):
592 dn_req /= PortIngressRuleResultReplace(fieldcode=RuleClauses['C-VLAN Tag'])
593 # need to convert value in Set to a variable length value
594 ctagStr = struct.pack('>H', (field.vlan_vid & 0xfff))
595 dn_req /= PortIngressRuleResultSet(
596 fieldcode=RuleClauses['C-VLAN Tag'], value=ctagStr)
597 else:
598 raise NotImplementedError('unsupported-set-vlan-id={}'.format(field.vlan_vid & 0xfff))
599 else:
600 raise NotImplementedError('unsupported-action-set-field-type={}'.format(field.type))
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800601 else:
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400602 raise NotImplementedError('unsupported-action-type={}'.format(action.type))
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800603
Paul Graycfc2dc32017-05-31 12:58:43 -0700604 if Is_MCast is True:
605 action = "Set Static IP MCAST address"
Andrew Chagnona09233a2017-07-25 12:53:55 -0400606 else:
Paul Graycfc2dc32017-05-31 12:58:43 -0700607 dn_req /= PortIngressRuleTerminator()
608 dn_req /= AddPortIngressRule()
609 action = "Set ONU DS Rule"
610
Paul Graycfc2dc32017-05-31 12:58:43 -0700611 # send message
Paul Graycfc2dc32017-05-31 12:58:43 -0700612 rc = []
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400613 yield self._set_req_rsp(device, action, dn_req, rc)
Paul Graycfc2dc32017-05-31 12:58:43 -0700614
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800615 else:
616 raise Exception('Port should be 1 or 2 by our convention')
617
Andrew Chagnona09233a2017-07-25 12:53:55 -0400618 log.info('bulk-flow-update finished', device_id=device.id,
619 flows=flows, groups=groups)
620 log.info('########################################')
621
Zsolt Harasztied091602016-12-08 13:36:38 -0800622 def update_flows_incrementally(self, device, flow_changes, group_changes):
623 raise NotImplementedError()
624
625 def send_proxied_message(self, proxy_address, msg):
626 raise NotImplementedError()
627
628 def receive_proxied_message(self, proxy_address, msg):
Nathan Knutha1a11932017-01-12 16:59:58 -0800629 log.info('receive-proxied-message',
630 proxy_address=proxy_address, msg=msg.show(dump=True))
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800631 self.incoming_messages.put(msg)
632
Nikolay Titov89004ec2017-06-19 18:22:42 -0400633 def create_interface(self, device, data):
634 raise NotImplementedError()
635
636 def update_interface(self, device, data):
637 raise NotImplementedError()
638
639 def remove_interface(self, device, data):
640 raise NotImplementedError()
641
642 def receive_onu_detect_state(self, device_id, state):
643 raise NotImplementedError()
644
Nikolay Titov176f1db2017-08-10 12:38:43 -0400645 def create_tcont(self, device, tcont_data, traffic_descriptor_data):
646 raise NotImplementedError()
647
648 def update_tcont(self, device, tcont_data, traffic_descriptor_data):
649 raise NotImplementedError()
650
651 def remove_tcont(self, device, tcont_data, traffic_descriptor_data):
652 raise NotImplementedError()
653
654 def create_gemport(self, device, data):
655 raise NotImplementedError()
656
657 def update_gemport(self, device, data):
658 raise NotImplementedError()
659
660 def remove_gemport(self, device, data):
661 raise NotImplementedError()
662
663 def create_multicast_gemport(self, device, data):
664 raise NotImplementedError()
665
666 def update_multicast_gemport(self, device, data):
667 raise NotImplementedError()
668
669 def remove_multicast_gemport(self, device, data):
670 raise NotImplementedError()
671
672 def create_multicast_distribution_set(self, device, data):
673 raise NotImplementedError()
674
675 def update_multicast_distribution_set(self, device, data):
676 raise NotImplementedError()
677
678 def remove_multicast_distribution_set(self, device, data):
679 raise NotImplementedError()
680
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800681 @inlineCallbacks
682 def _message_exchange(self, device):
683
684 # register for receiving async messages
685 self.adapter_agent.register_for_proxied_messages(device.proxy_address)
686
687 # reset incoming message queue
688 while self.incoming_messages.pending:
689 _ = yield self.incoming_messages.get()
690
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400691 resp = []
692 action = "Get Device Info"
693 body = VendorName()/OnuMode()/HardwareVersion()/ManufacturerInfo()
694 yield self._get_req_rsp(device, action, body, resp)
695 if resp is not []: frame = resp[0]
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800696
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400697 if frame:
Paul Gray934d2882017-05-25 04:44:49 -0700698 log.info('ONU-response received for Get Version Info for ONU: {}'.format(device.mac_address))
Paul Gray934d2882017-05-25 04:44:49 -0700699 self._process_ping_frame_response(device, frame)
Paul Grayef008892017-05-17 12:28:45 -0700700
Paul Grayef008892017-05-17 12:28:45 -0700701
Paul Gray934d2882017-05-25 04:44:49 -0700702 if self.mode.upper()[0] == "G": # GPON
Paul Grayac4850d2017-06-02 14:53:40 -0700703
Andrew Chagnonb4d604f2017-06-09 15:45:39 -0400704 hw_vers = int(device.hardware_version, 16)
Paul Grayac4850d2017-06-02 14:53:40 -0700705
Andrew Chagnonfe0eb732017-07-10 19:29:29 -0400706 if hw_vers >= 0x170618:
707 mcastLidx = 0x04bc
708 elif hw_vers >= 0x170517:
Paul Grayac4850d2017-06-02 14:53:40 -0700709 mcastLidx = 0x14bc
710 else:
711 mcastLidx = 0x10bc
712
713 log.info("Using Multicast LIDX {:04X}".format(mcastLidx))
714
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400715 tlvs = MulticastRegisterSet(MulticastLink=mcastLidx, UnicastLink=0)
716 msg = self._build_dpoe_oam_msg(DPoEOpcodes["Multicast Register"], tlvs)
Paul Gray934d2882017-05-25 04:44:49 -0700717 # send message
718 log.info('ONU-send-proxied-message to Multicast Register Set for ONU: {}'.format(device.mac_address))
719 self.adapter_agent.send_proxied_message(device.proxy_address, msg)
720
721 # The MulticastRegisterSet does not currently return a response. Just hope it worked.
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800722
723 # by returning we allow the device to be shown as active, which
724 # indirectly verified that message passing works
Zsolt Haraszti656ecc62016-12-28 15:08:23 -0800725
726 def receive_packet_out(self, logical_device_id, egress_port_no, msg):
727 log.info('packet-out', logical_device_id=logical_device_id,
728 egress_port_no=egress_port_no, msg_len=len(msg))
Zsolt Harasztic5f740b2017-01-18 09:53:17 -0800729
Peter Shafik9107f2e2017-05-02 15:54:39 -0400730 def receive_inter_adapter_message(self, msg):
731 raise NotImplementedError()
732
Stephane Barbarie980a0912017-05-11 11:27:06 -0400733 def suppress_alarm(self, filter):
734 raise NotImplementedError()
735
736 def unsuppress_alarm(self, filter):
737 raise NotImplementedError()
738
Zsolt Harasztic5f740b2017-01-18 09:53:17 -0800739 def start_kpi_collection(self, device_id):
740
741 """TMP Simulate periodic KPI metric collection from the device"""
742 import random
743
744 @inlineCallbacks # pretend that we need to do async calls
745 def _collect(device_id, prefix):
746
747 try:
748 # Step 1: gather metrics from device (pretend it here) - examples
749 uni_port_metrics = yield dict(
750 tx_pkts=random.randint(0, 100),
751 rx_pkts=random.randint(0, 100),
752 tx_bytes=random.randint(0, 100000),
753 rx_bytes=random.randint(0, 100000),
754 )
755 pon_port_metrics = yield dict(
756 tx_pkts=uni_port_metrics['rx_pkts'],
757 rx_pkts=uni_port_metrics['tx_pkts'],
758 tx_bytes=uni_port_metrics['rx_bytes'],
759 rx_bytes=uni_port_metrics['tx_bytes'],
760 )
761 onu_metrics = yield dict(
762 cpu_util=20 + 5 * random.random(),
763 buffer_util=10 + 10 * random.random()
764 )
765
766 # Step 2: prepare the KpiEvent for submission
767 # we can time-stamp them here (or could use time derived from OLT
768 ts = arrow.utcnow().timestamp
769 kpi_event = KpiEvent(
770 type=KpiEventType.slice,
771 ts=ts,
772 prefixes={
773 # OLT-level
774 prefix: MetricValuePairs(metrics=onu_metrics),
775 # OLT NNI port
776 prefix + '.nni': MetricValuePairs(metrics=uni_port_metrics),
777 # OLT PON port
778 prefix + '.pon': MetricValuePairs(metrics=pon_port_metrics)
779 }
780 )
781
782 # Step 3: submit
783 self.adapter_agent.submit_kpis(kpi_event)
784
785 except Exception as e:
786 log.exception('failed-to-submit-kpis', e=e)
787
788 prefix = 'voltha.{}.{}'.format(self.name, device_id)
789 lc = LoopingCall(_collect, device_id, prefix)
790 lc.start(interval=15) # TODO make this configurable
791
Paul Grayef008892017-05-17 12:28:45 -0700792
793# Methods for Get / Set Response Processing from eoam_messages
794
Paul Gray934d2882017-05-25 04:44:49 -0700795 @inlineCallbacks
796 def _send_igmp_mcast_addr(self, device):
797 # construct install of igmp query address
Paul Gray934d2882017-05-25 04:44:49 -0700798 action = "Set Static IGMP MAC address"
Paul Gray934d2882017-05-25 04:44:49 -0700799 rc = []
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400800 tlvs = AddStaticMacAddress(mac='01:00:5e:00:00:01')
801 yield self._set_req_rsp(device, action, tlvs, rc)
Paul Gray934d2882017-05-25 04:44:49 -0700802
803
804 @inlineCallbacks
805 def _send_clear_static_mac_table(self, device):
Paul Gray934d2882017-05-25 04:44:49 -0700806 action = "Clear Static MAC Table"
Paul Gray934d2882017-05-25 04:44:49 -0700807 rc = []
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400808 tlvs = ClearStaticMacTable()
809 yield self._set_req_rsp(device, action, tlvs, rc)
Andrew Chagnona09233a2017-07-25 12:53:55 -0400810
Paul Gray934d2882017-05-25 04:44:49 -0700811
Paul Gray934d2882017-05-25 04:44:49 -0700812 def _process_ping_frame_response(self, device, frame):
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400813 vendor = [VendorName().branch, VendorName().leaf]
814 ponMode = [OnuMode().branch, OnuMode().leaf]
815 hw_version = [HardwareVersion().branch, HardwareVersion().leaf]
816 manufacturer = [ManufacturerInfo().branch, ManufacturerInfo().leaf]
Paul Gray934d2882017-05-25 04:44:49 -0700817
Paul Gray934d2882017-05-25 04:44:49 -0700818 branch_leaf_pairs = [vendor, ponMode, hw_version, manufacturer]
Andrew Chagnona09233a2017-07-25 12:53:55 -0400819
Paul Gray934d2882017-05-25 04:44:49 -0700820 for pair in branch_leaf_pairs:
821 temp_pair = pair
Paul Graycfc2dc32017-05-31 12:58:43 -0700822 (rc, value) = (get_value_from_msg(log, frame, pair[0], pair[1]))
Paul Gray934d2882017-05-25 04:44:49 -0700823 temp_pair.append(rc)
824 temp_pair.append(value)
825 if rc:
826 overall_rc = True
Andrew Chagnona09233a2017-07-25 12:53:55 -0400827 else:
Paul Gray934d2882017-05-25 04:44:49 -0700828 log.info('Failed to get valid response for Branch 0x{:X} Leaf 0x{:0>4X} '.format(temp_pair[0], temp_pair[1]))
829 ack = True
830
831 if vendor[rc]:
832 device.vendor = vendor.pop()
833 if device.vendor.endswith(''):
834 device.vendor = device.vendor[:-1]
835 else:
836 device.vendor = "UNKNOWN"
Andrew Chagnona09233a2017-07-25 12:53:55 -0400837
Paul Gray934d2882017-05-25 04:44:49 -0700838 # mode: 3 = EPON OLT, 7 = GPON OLT
Andrew Chagnona09233a2017-07-25 12:53:55 -0400839 # mode: 2 = EPON ONU, 6 = GPON ONU
Paul Gray934d2882017-05-25 04:44:49 -0700840 if ponMode[rc]:
841 value = ponMode.pop()
842 mode = "UNKNOWN"
843 self.mode = "UNKNOWN"
844
845 if value == 6:
846 mode = "10G GPON ONU"
847 self.mode = "GPON"
848 if value == 2:
849 mode = "10G EPON ONU"
850 self.mode = "EPON"
851 if value == 1:
852 mode = "10G Point to Point"
853 self.mode = "Unsupported"
854
855 device.model = mode
856
857 else:
858 device.model = "UNKNOWN"
859 self.mode = "UNKNOWN"
860
861 log.info("PON Mode is {}".format(self.mode))
Andrew Chagnona09233a2017-07-25 12:53:55 -0400862
Paul Gray934d2882017-05-25 04:44:49 -0700863 if hw_version[rc]:
864 device.hardware_version = hw_version.pop()
Andrew Chagnonb4d604f2017-06-09 15:45:39 -0400865 device.hardware_version = device.hardware_version.replace("FA","")
Paul Gray934d2882017-05-25 04:44:49 -0700866 if device.hardware_version.endswith(''):
867 device.hardware_version = device.hardware_version[:-1]
868 else:
869 device.hardware_version = "UNKNOWN"
870
871 if manufacturer[rc]:
872 manu_value = manufacturer.pop()
873 device.firmware_version = re.search('\Firmware: (.+?) ', manu_value).group(1)
ggowdru236bd952017-06-20 20:32:55 -0700874 image_1 = Image(version = \
875 re.search('\Build: (.+?) ', manu_value).group(1))
876 device.images.image.extend([ image_1 ])
Paul Gray934d2882017-05-25 04:44:49 -0700877 device.serial_number = re.search('\Serial #: (.+?) ', manu_value).group(1)
878 else:
879 device.firmware_version = "UNKNOWN"
ggowdru236bd952017-06-20 20:32:55 -0700880 image_1 = Image(version="UNKNOWN")
881 device.images.image.extend([ image_1 ])
Paul Gray934d2882017-05-25 04:44:49 -0700882 device.serial_number = "UNKNOWN"
883
884 device.connect_status = ConnectStatus.REACHABLE
Andrew Chagnon48ecb442017-08-22 11:01:25 -0400885
886
887 # Generic Request handlers
888
889 def _build_dpoe_oam_msg(self, opcode, body):
890 msg = (
891 EOAMPayload() / EOAM_VendSpecificMsg(oui=CABLELABS_OUI) /
892 EOAM_DpoeMsg(dpoe_opcode = opcode, body=body)/
893 EndOfPDU()
894 )
895 return msg
896
897 @inlineCallbacks
898 def _get_req_rsp(self, device, action, body, resp):
899 msg = self._build_dpoe_oam_msg(DPoEOpcodes["Get Request"], body)
900 log.info('Send to {} for {}: {}'.format(action, device.model, device.mac_address))
901
902 self.adapter_agent.send_proxied_message(device.proxy_address, msg)
903
904 # Loop until we have a Get Response or timeout
905 ack = False
906 start_time = time.time()
907 while not ack:
908 frame = yield self.incoming_messages.get()
909 #TODO - Need to add proper timeout functionality
910 #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
911 # break # don't wait forever
912
913 respType = get_oam_msg_type(log, frame)
914
915 if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
916 ack = True
917 resp.append(frame)
918 else:
919 # Handle unexpected events/OMCI messages
920 check_resp(log, frame)
921
922 @inlineCallbacks
923 def _handle_set_resp(self, device, action, retcode):
924 # Get and process the Set Response
925 ack = False
926 #start_time = time.time()
927
928 # Loop until we have a set response or timeout
929 while not ack:
930 frame = yield self.incoming_messages.get()
931 #TODO - Need to add proper timeout functionality
932 #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
933 # break # don't wait forever
934
935 respType = get_oam_msg_type(log, frame)
936
937 #Check that the message received is a Set Response
938 if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]):
939 ack = True
940 else:
941 log.info('Received Unexpected OAM Message 0x{:X} while waiting for Set Resp for {}'.format(respType,action))
942 # Handle unexpected events/OMCI messages
943 check_resp(log, frame)
944
945 # Verify Set Response
946 rc = False
947 if ack:
948 (rc,branch,leaf,status) = check_set_resp(log, frame)
949 if (rc is False):
950 log.info('Set Response for {} for {}: {} had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(action, device.model, device.mac_address,branch, leaf, DPoEVariableResponseEnum[status]))
951 else:
952 log.info('Set Response received for {} for {}: {} had no errors'.format(action, device.model, device.mac_address))
953 else:
954 log.info('No Set Response received for {} for {}: {}'.format(action, device.model, device.mac_address))
955
956 retcode.append(rc)
957
958 @inlineCallbacks
959 def _set_req_rsp(self, device, action, body, rc):
960 msg = self._build_dpoe_oam_msg(DPoEOpcodes["Set Request"], body)
961 log.info('Send to {} for {}: {}'.format(action, device.model, device.mac_address))
962 self.adapter_agent.send_proxied_message(device.proxy_address, msg)
963
964 # Get and process the Set Response
965 yield self._handle_set_resp(device, action, rc)