blob: 137f572e0b0020217112b31f2296ad7e0d693ca3 [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
Zsolt Haraszti348d1932016-12-10 01:10:07 -080021import json
Paul Grayeee44382017-03-31 09:00:25 -070022import time
23import struct
Paul Gray934d2882017-05-25 04:44:49 -070024import re
Zsolt Haraszti348d1932016-12-10 01:10:07 -080025
26from uuid import uuid4
27
Zsolt Harasztic5f740b2017-01-18 09:53:17 -080028import arrow
Zsolt Harasztied091602016-12-08 13:36:38 -080029import structlog
Zsolt Harasztic5f740b2017-01-18 09:53:17 -080030from twisted.internet.task import LoopingCall
Zsolt Harasztied091602016-12-08 13:36:38 -080031from zope.interface import implementer
32
Zsolt Haraszti348d1932016-12-10 01:10:07 -080033from scapy.layers.inet import ICMP, IP
34from scapy.layers.l2 import Ether
35from twisted.internet.defer import DeferredQueue, inlineCallbacks
36from twisted.internet import reactor
37
Zsolt Haraszti85f12852016-12-24 08:30:58 -080038from voltha.core.flow_decomposer import *
Zsolt Haraszti348d1932016-12-10 01:10:07 -080039from voltha.core.logical_device_agent import mac_str_to_tuple
Nathan Knutha1a11932017-01-12 16:59:58 -080040from common.frameio.frameio import BpfProgramFilter, hexify
Zsolt Harasztied091602016-12-08 13:36:38 -080041from voltha.adapters.interface import IAdapterInterface
42from voltha.protos.adapter_pb2 import Adapter, AdapterConfig
ggowdru236bd952017-06-20 20:32:55 -070043from voltha.protos.device_pb2 import Port, Image
Zsolt Harasztied091602016-12-08 13:36:38 -080044from voltha.protos.device_pb2 import DeviceType, DeviceTypes
Zsolt Harasztic5f740b2017-01-18 09:53:17 -080045from voltha.protos.events_pb2 import KpiEventType
46from voltha.protos.events_pb2 import MetricValuePairs, KpiEvent
Zsolt Harasztied091602016-12-08 13:36:38 -080047from voltha.protos.health_pb2 import HealthStatus
Zsolt Haraszti348d1932016-12-10 01:10:07 -080048from voltha.protos.common_pb2 import LogLevel, ConnectStatus
Zsolt Haraszti348d1932016-12-10 01:10:07 -080049from voltha.protos.common_pb2 import OperStatus, AdminState
50
51from voltha.protos.logical_device_pb2 import LogicalDevice, LogicalPort
52from voltha.protos.openflow_13_pb2 import ofp_desc, ofp_port, OFPPF_10GB_FD, \
53 OFPPF_FIBER, OFPPS_LIVE, ofp_switch_features, OFPC_PORT_STATS, \
54 OFPC_GROUP_STATS, OFPC_TABLE_STATS, OFPC_FLOW_STATS
55
56from scapy.packet import Packet, bind_layers
57from scapy.fields import StrField
Zsolt Harasztied091602016-12-08 13:36:38 -080058
59log = structlog.get_logger()
60
Paul Graycfc2dc32017-05-31 12:58:43 -070061from voltha.extensions.eoam.EOAM_TLV import UserPortObject
Nathan Knuth31c36962016-12-27 10:04:49 -080062from voltha.extensions.eoam.EOAM_TLV import AddStaticMacAddress, DeleteStaticMacAddress
63from voltha.extensions.eoam.EOAM_TLV import ClearStaticMacTable
64from voltha.extensions.eoam.EOAM_TLV import DeviceId
Nathan Knuthd8285e62017-01-11 14:18:43 -060065from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum
66from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum
Paul Gray934d2882017-05-25 04:44:49 -070067from voltha.extensions.eoam.EOAM_TLV import DPoEOpcodeEnum, DPoEVariableResponseCodes
Paul Grayef008892017-05-17 12:28:45 -070068from voltha.extensions.eoam.EOAM_TLV import DPoEOpcode_MulticastRegister, MulticastRegisterSet
Paul Gray934d2882017-05-25 04:44:49 -070069from voltha.extensions.eoam.EOAM_TLV import VendorName, OnuMode, HardwareVersion, ManufacturerInfo
Paul Gray7a312e42017-05-25 15:08:00 -070070from voltha.extensions.eoam.EOAM_TLV import SlowProtocolsSubtypeEnum, DeviceReset
Paul Graycfc2dc32017-05-31 12:58:43 -070071from voltha.extensions.eoam.EOAM_TLV import DONUObject, \
72 UserPortObject, PonPortObject, \
73 PortIngressRuleClauseMatchLength00, PortIngressRuleClauseMatchLength01, \
74 PortIngressRuleClauseMatchLength02, PortIngressRuleResultForward, \
75 PortIngressRuleResultSet, PortIngressRuleResultInsert, \
76 PortIngressRuleResultCopy, PortIngressRuleResultReplace, \
77 PortIngressRuleResultDelete, PortIngressRuleResultOLTQueue, \
78 PortIngressRuleTerminator, AddPortIngressRule
79from voltha.extensions.eoam.EOAM_TLV import PortIngressRuleHeader
80from voltha.extensions.eoam.EOAM_TLV import ClauseSubtypeEnum
81from voltha.extensions.eoam.EOAM_TLV import RuleOperatorEnum
Paul Gray934d2882017-05-25 04:44:49 -070082from voltha.extensions.eoam.EOAM_TLV import EndOfPDU
Nathan Knuthd8285e62017-01-11 14:18:43 -060083
Paul Grayef008892017-05-17 12:28:45 -070084from voltha.extensions.eoam.EOAM import EOAMPayload, EOAMEvent, EOAM_VendSpecificMsg
85from voltha.extensions.eoam.EOAM import EOAM_OmciMsg, EOAM_TibitMsg, EOAM_DpoeMsg
86from voltha.extensions.eoam.EOAM import EOAMPayload, CableLabs_OUI, Tibit_OUI
Nathan Knuth31c36962016-12-27 10:04:49 -080087from voltha.extensions.eoam.EOAM import DPoEOpcode_GetRequest, DPoEOpcode_SetRequest
Nathan Knuth5f4163e2017-01-11 18:21:10 -060088from voltha.extensions.eoam.EOAM import mcastIp2McastMac
Paul Graycfc2dc32017-05-31 12:58:43 -070089from voltha.extensions.eoam.EOAM import RxedOamMsgTypeEnum, Dpoe_Opcodes, get_oam_msg_type, \
90 handle_get_value, get_value_from_msg, check_set_resp, check_resp
Zsolt Harasztied091602016-12-08 13:36:38 -080091
Paul Grayeee44382017-03-31 09:00:25 -070092TIBIT_MSG_WAIT_TIME = 3
93
Paul Gray934d2882017-05-25 04:44:49 -070094
Zsolt Harasztied091602016-12-08 13:36:38 -080095@implementer(IAdapterInterface)
96class TibitOnuAdapter(object):
97
98 name = 'tibit_onu'
99
100 supported_device_types = [
101 DeviceType(
102 id='tibit_onu',
103 adapter=name,
104 accepts_bulk_flow_update=True
105 )
106 ]
107
108 def __init__(self, adapter_agent, config):
109 self.adapter_agent = adapter_agent
110 self.config = config
111 self.descriptor = Adapter(
112 id=self.name,
113 vendor='Tibit Communications Inc.',
114 version='0.1',
115 config=AdapterConfig(log_level=LogLevel.INFO)
116 )
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800117 self.incoming_messages = DeferredQueue()
Paul Gray934d2882017-05-25 04:44:49 -0700118 self.mode = "GPON"
Zsolt Harasztied091602016-12-08 13:36:38 -0800119
120 def start(self):
121 log.debug('starting')
122 log.info('started')
123
124 def stop(self):
125 log.debug('stopping')
126 log.info('stopped')
127
128 def adapter_descriptor(self):
129 return self.descriptor
130
131 def device_types(self):
132 return DeviceTypes(items=self.supported_device_types)
133
134 def health(self):
135 return HealthStatus(state=HealthStatus.HealthState.HEALTHY)
136
137 def change_master_state(self, master):
138 raise NotImplementedError()
139
Sergio Slobodrianec864c62017-03-09 11:41:43 -0500140 def update_pm_config(self, device, pm_configs):
141 raise NotImplementedError()
142
Zsolt Harasztied091602016-12-08 13:36:38 -0800143 def adopt_device(self, device):
144 log.info('adopt-device', device=device)
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800145 reactor.callLater(0.1, self._onu_device_activation, device)
Zsolt Harasztied091602016-12-08 13:36:38 -0800146 return device
147
khenaidoo032d3302017-06-09 14:50:04 -0400148 def reconcile_device(self, device):
149 raise NotImplementedError()
150
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800151 @inlineCallbacks
152 def _onu_device_activation(self, device):
153 # first we verify that we got parent reference and proxy info
154 assert device.parent_id
155 assert device.proxy_address.device_id
156 assert device.proxy_address.channel_id
157
Paul Gray934d2882017-05-25 04:44:49 -0700158 # Device information will be updated later on
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800159 device.vendor = 'Tibit Communications, Inc.'
160 device.model = '10G GPON ONU'
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800161 device.connect_status = ConnectStatus.REACHABLE
162 self.adapter_agent.update_device(device)
163
164 # then shortly after we create some ports for the device
165 uni_port = Port(
166 port_no=2,
167 label='UNI facing Ethernet port',
168 type=Port.ETHERNET_UNI,
169 admin_state=AdminState.ENABLED,
170 oper_status=OperStatus.ACTIVE
171 )
172 self.adapter_agent.add_port(device.id, uni_port)
173 self.adapter_agent.add_port(device.id, Port(
174 port_no=1,
175 label='PON port',
176 type=Port.PON_ONU,
177 admin_state=AdminState.ENABLED,
178 oper_status=OperStatus.ACTIVE,
179 peers=[
180 Port.PeerPort(
181 device_id=device.parent_id,
182 port_no=device.parent_port_no
183 )
184 ]
185 ))
186
187 # TODO adding vports to the logical device shall be done by agent?
188 # then we create the logical device port that corresponds to the UNI
189 # port of the device
190
191 # obtain logical device id
192 parent_device = self.adapter_agent.get_device(device.parent_id)
193 logical_device_id = parent_device.parent_id
194 assert logical_device_id
195
196 # we are going to use the proxy_address.channel_id as unique number
197 # and name for the virtual ports, as this is guaranteed to be unique
198 # in the context of the OLT port, so it is also unique in the context
199 # of the logical device
200 port_no = device.proxy_address.channel_id
201 cap = OFPPF_10GB_FD | OFPPF_FIBER
202 self.adapter_agent.add_logical_port(logical_device_id, LogicalPort(
203 id=str(port_no),
204 ofp_port=ofp_port(
205 port_no=port_no,
206 hw_addr=mac_str_to_tuple(device.mac_address),
207 name='uni-{}'.format(port_no),
208 config=0,
209 state=OFPPS_LIVE,
210 curr=cap,
211 advertised=cap,
212 peer=cap,
213 curr_speed=OFPPF_10GB_FD,
214 max_speed=OFPPF_10GB_FD
215 ),
216 device_id=device.id,
217 device_port_no=uni_port.port_no
218 ))
219
220 # simulate a proxied message sending and receving a reply
221 reply = yield self._message_exchange(device)
222
Paul Grayef008892017-05-17 12:28:45 -0700223 # TODO - Need to add validation of reply and decide what to do upon failure
224
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800225 # and finally update to "ACTIVE"
226 device = self.adapter_agent.get_device(device.id)
227 device.oper_status = OperStatus.ACTIVE
228 self.adapter_agent.update_device(device)
229
Paul Grayef008892017-05-17 12:28:45 -0700230 # TODO - Disable Stats Reporting for the moment
231 #self.start_kpi_collection(device.id)
Zsolt Harasztic5f740b2017-01-18 09:53:17 -0800232
Zsolt Harasztied091602016-12-08 13:36:38 -0800233 def abandon_device(self, device):
234 raise NotImplementedError(0
235 )
Khen Nursimulud068d812017-03-06 11:44:18 -0500236 def disable_device(self, device):
Andrew Chagnona09233a2017-07-25 12:53:55 -0400237 log.info('disabling', device_id=device.id)
238
239 # Disable all ports on that device
240 self.adapter_agent.disable_all_ports(device.id)
241
242 # Update the device operational status to UNKNOWN
243 device.oper_status = OperStatus.UNKNOWN
244 device.connect_status = ConnectStatus.UNREACHABLE
245 self.adapter_agent.update_device(device)
246
247 # Remove the uni logical port from the OLT, if still present
248 parent_device = self.adapter_agent.get_device(device.parent_id)
249 assert parent_device
250 logical_device_id = parent_device.parent_id
251 assert logical_device_id
252 port_no = device.proxy_address.channel_id
253# port_id = 'uni-{}'.format(port_no)
254 port_id = '{}'.format(port_no)
255 try:
256 port = self.adapter_agent.get_logical_port(logical_device_id,
257 port_id)
258 self.adapter_agent.delete_logical_port(logical_device_id, port)
259 except KeyError:
260 log.info('logical-port-not-found', device_id=device.id,
261 portid=port_id)
262
263 # Remove pon port from parent
264 #self.adapter_agent.delete_port_reference_from_parent(device.id,
265 # self.pon_port)
266
267 # Just updating the port status may be an option as well
268 # port.ofp_port.config = OFPPC_NO_RECV
269 # yield self.adapter_agent.update_logical_port(logical_device_id,
270 # port)
271 # Unregister for proxied message
272 self.adapter_agent.unregister_for_proxied_messages(device.proxy_address)
273
274 # TODO:
275 # 1) Remove all flows from the device
276 # 2) Remove the device from ponsim
277
278 log.info('disabled', device_id=device.id)
279
Paul Gray7a312e42017-05-25 15:08:00 -0700280 return device
Khen Nursimulud068d812017-03-06 11:44:18 -0500281
282 def reenable_device(self, device):
Andrew Chagnona09233a2017-07-25 12:53:55 -0400283 log.info('re-enabling', device_id=device.id)
284
285 # First we verify that we got parent reference and proxy info
286 assert device.parent_id
287 assert device.proxy_address.device_id
288 assert device.proxy_address.channel_id
289
290 # Re-register for proxied messages right away
291 #self.proxy_address = device.proxy_address
292 self.adapter_agent.register_for_proxied_messages(device.proxy_address)
293
294 # Re-enable the ports on that device
295 self.adapter_agent.enable_all_ports(device.id)
296
297 # Add the pon port reference to the parent
298 #self.adapter_agent.add_port_reference_to_parent(device.id,
299 # self.pon_port)
300
301 # Update the connect status to REACHABLE
302 device.connect_status = ConnectStatus.REACHABLE
303 self.adapter_agent.update_device(device)
304
305 # re-add uni port to logical device
306 parent_device = self.adapter_agent.get_device(device.parent_id)
307 logical_device_id = parent_device.parent_id
308 assert logical_device_id
309 port_no = device.proxy_address.channel_id
310 cap = OFPPF_10GB_FD | OFPPF_FIBER
311 self.adapter_agent.add_logical_port(logical_device_id, LogicalPort(
312# id='uni-{}'.format(port_no),
313 id= str(port_no),
314 ofp_port=ofp_port(
315 port_no=port_no,
316 hw_addr=mac_str_to_tuple(device.mac_address),
317 name='uni-{}'.format(port_no),
318 config=0,
319 state=OFPPS_LIVE,
320 curr=cap,
321 advertised=cap,
322 peer=cap,
323 curr_speed=OFPPF_10GB_FD,
324 max_speed=OFPPF_10GB_FD
325 ),
326 device_id=device.id,
327 device_port_no=2
328 ))
329
330 device = self.adapter_agent.get_device(device.id)
331 device.oper_status = OperStatus.ACTIVE
332 self.adapter_agent.update_device(device)
333
334 log.info('re-enabled', device_id=device.id)
335
Khen Nursimulud068d812017-03-06 11:44:18 -0500336
Paul Gray7a312e42017-05-25 15:08:00 -0700337 @inlineCallbacks
Khen Nursimulud068d812017-03-06 11:44:18 -0500338 def reboot_device(self, device):
Paul Gray7a312e42017-05-25 15:08:00 -0700339 log.info('Rebooting ONU: {}'.format(device.mac_address))
340
341 # Update the operational status to ACTIVATING and connect status to
342 # UNREACHABLE
343 previous_oper_status = device.oper_status
344 previous_conn_status = device.connect_status
345 device.oper_status = OperStatus.ACTIVATING
346 device.connect_status = ConnectStatus.UNREACHABLE
347 self.adapter_agent.update_device(device)
348
349 msg = (
350 EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
Andrew Chagnona09233a2017-07-25 12:53:55 -0400351 EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"],
Paul Gray7a312e42017-05-25 15:08:00 -0700352 body=DeviceReset())/
353 EndOfPDU()
354 )
355
356 action = "Device Reset"
357
358 # send message
359 log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
360 self.adapter_agent.send_proxied_message(device.proxy_address, msg)
361
362 rc = []
363 yield self._handle_set_resp(device, action, rc)
364
365 # Change the operational status back to its previous state.
366 device.oper_status = previous_oper_status
367 device.connect_status = previous_conn_status
368 self.adapter_agent.update_device(device)
369
370 log.info('ONU Rebooted: {}'.format(device.mac_address))
Khen Nursimulud068d812017-03-06 11:44:18 -0500371
Lydia Fang01f2e852017-06-28 17:24:58 -0700372 def download_image(self, device, request):
373 raise NotImplementedError()
374
375 def get_image_download_status(self, device, request):
376 raise NotImplementedError()
377
378 def cancel_image_download(self, device, request):
379 raise NotImplementedError()
380
381 def activate_image_update(self, device, request):
382 raise NotImplementedError()
383
384 def revert_image_update(self, device, request):
385 raise NotImplementedError()
386
sathishg5ae86222017-06-28 15:16:29 +0530387 def self_test_device(self, device):
388 """
389 This is called to Self a device based on a NBI call.
390 :param device: A Voltha.Device object.
391 :return: Will return result of self test
392 """
393 log.info('self-test-device', device=device.id)
394 raise NotImplementedError()
395
Khen Nursimulud068d812017-03-06 11:44:18 -0500396 def delete_device(self, device):
Andrew Chagnona09233a2017-07-25 12:53:55 -0400397 log.info('deleting', device_id=device.id)
398
399 # A delete request may be received when an OLT is disabled
400
401 # TODO:
402 # 1) Remove all flows from the device
403 # 2) Remove the device from ponsim
404
405 log.info('deleted', device_id=device.id)
Khen Nursimulud068d812017-03-06 11:44:18 -0500406
407 def get_device_details(self, device):
Zsolt Harasztied091602016-12-08 13:36:38 -0800408 raise NotImplementedError()
409
Paul Grayeee44382017-03-31 09:00:25 -0700410 @inlineCallbacks
Zsolt Harasztied091602016-12-08 13:36:38 -0800411 def update_flows_bulk(self, device, flows, groups):
Nathan Knuthd8285e62017-01-11 14:18:43 -0600412 log.info('########################################')
413 log.info('bulk-flow-update', device_id=device.id,
414 flows=flows, groups=groups)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800415 assert len(groups.items) == 0, "Cannot yet deal with groups"
416
Andrew Chagnona09233a2017-07-25 12:53:55 -0400417 # Only do something if there are flows to program
418 if (len(flows.items) > 0):
419 # Clear the existing entries in the Static MAC Address Table
420 yield self._send_clear_static_mac_table(device)
Paul Gray934d2882017-05-25 04:44:49 -0700421
Andrew Chagnona09233a2017-07-25 12:53:55 -0400422 # Re-add the IGMP Multicast Address
423 yield self._send_igmp_mcast_addr(device)
Paul Gray934d2882017-05-25 04:44:49 -0700424
Nathan Knuthd8285e62017-01-11 14:18:43 -0600425 Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()}
426 Operator = {v: k for k, v in RuleOperatorEnum.iteritems()}
427
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800428 for flow in flows.items:
429 in_port = get_in_port(flow)
430 assert in_port is not None
431
Nathan Knuthd8285e62017-01-11 14:18:43 -0600432 precedence = 255 - min(flow.priority / 256, 255)
433
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800434 if in_port == 2:
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600435 log.info('#### Upstream Rule ####')
Paul Grayef008892017-05-17 12:28:45 -0700436
Paul Grayef008892017-05-17 12:28:45 -0700437
Paul Graycfc2dc32017-05-31 12:58:43 -0700438 up_req = UserPortObject()
439 up_req /= PortIngressRuleHeader(precedence=precedence)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800440
441 for field in get_ofb_fields(flow):
Nathan Knuthd8285e62017-01-11 14:18:43 -0600442
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800443 if field.type == ETH_TYPE:
444 _type = field.eth_type
Nathan Knuthd8285e62017-01-11 14:18:43 -0600445 log.info('#### field.type == ETH_TYPE ####',field_type=_type)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800446
447 elif field.type == IP_PROTO:
448 _proto = field.ip_proto
Nathan Knuthd8285e62017-01-11 14:18:43 -0600449 log.info('#### field.type == IP_PROTO ####')
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800450
451 elif field.type == IN_PORT:
452 _port = field.port
Nathan Knuthd8285e62017-01-11 14:18:43 -0600453 log.info('#### field.type == IN_PORT ####', port=_port)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800454
455 elif field.type == VLAN_VID:
Nathan Knuthd8285e62017-01-11 14:18:43 -0600456 _vlan_vid = field.vlan_vid & 0xfff
457 log.info('#### field.type == VLAN_VID ####', vlan=_vlan_vid)
Paul Graycfc2dc32017-05-31 12:58:43 -0700458 up_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
459 operator=Operator['=='], match=_vlan_vid)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800460
461 elif field.type == VLAN_PCP:
462 _vlan_pcp = field.vlan_pcp
Nathan Knuthd8285e62017-01-11 14:18:43 -0600463 log.info('#### field.type == VLAN_PCP ####', pcp=_vlan_pcp)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800464
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800465 elif field.type == UDP_DST:
466 _udp_dst = field.udp_dst
Paul Graycfc2dc32017-05-31 12:58:43 -0700467 log.info('#### field.type == UDP_DST ####', udp_dst=_udp_dst)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800468
Nathan Knuthd8285e62017-01-11 14:18:43 -0600469 elif field.type == IPV4_DST:
470 _ipv4_dst = field.ipv4_dst
Paul Graycfc2dc32017-05-31 12:58:43 -0700471 log.info('#### field.type == IPV4_DST ####', ipv4_dst=_ipv4_dst)
472
473 elif field.type == METADATA:
474 _metadata = field.table_metadata
475 log.info('#### field.type == METADATA ####', metadata=_metadata)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600476
477 else:
478 log.info('#### field.type == NOT IMPLEMENTED!! ####')
479 raise NotImplementedError('field.type={}'.format(
480 field.type))
481
482 for action in get_actions(flow):
483
484 if action.type == OUTPUT:
485 log.info('#### action.type == OUTPUT ####')
Paul Graycfc2dc32017-05-31 12:58:43 -0700486 up_req /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])
Nathan Knuthd8285e62017-01-11 14:18:43 -0600487
488 elif action.type == POP_VLAN:
489 log.info('#### action.type == POP_VLAN ####')
Nathan Knuthd8285e62017-01-11 14:18:43 -0600490
491 elif action.type == PUSH_VLAN:
492 log.info('#### action.type == PUSH_VLAN ####')
Paul Graycfc2dc32017-05-31 12:58:43 -0700493 up_req /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag'])
494# if action.push.ethertype != 0x8100:
495# log.error('unhandled-tpid',
496# ethertype=action.push.ethertype)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600497
498 elif action.type == SET_FIELD:
499 log.info('#### action.type == SET_FIELD ####')
500 assert (action.set_field.field.oxm_class ==
501 ofp.OFPXMC_OPENFLOW_BASIC)
502 field = action.set_field.field.ofb_field
503 if field.type == VLAN_VID:
Paul Graycfc2dc32017-05-31 12:58:43 -0700504 log.info("#### action.field.vlan {} ####".format(field.vlan_vid & 0xfff))
505 up_req /= PortIngressRuleResultSet(
506 fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600507 else:
508 log.error('unsupported-action-set-field-type',
509 field_type=field.type)
510 else:
511 log.error('UNSUPPORTED-ACTION-TYPE',
512 action_type=action.type)
513
Paul Graycfc2dc32017-05-31 12:58:43 -0700514 up_req /= PortIngressRuleTerminator()
515 up_req /= AddPortIngressRule()
516
517 msg = (
518 EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
519 EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=up_req)/
520 EndOfPDU()
521 )
522
523 # send message
524 action = "Set ONU US Rule"
525 log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
526 self.adapter_agent.send_proxied_message(device.proxy_address, msg)
527
528 # Get and process the Set Response
529 rc = []
530 yield self._handle_set_resp(device, action, rc)
531
532
Nathan Knuthd8285e62017-01-11 14:18:43 -0600533 elif in_port == 1:
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600534 log.info('#### Downstream Rule ####')
Paul Graycfc2dc32017-05-31 12:58:43 -0700535 Is_MCast = False
536
537 dn_req = PonPortObject()
538 dn_req /= PortIngressRuleHeader(precedence=precedence)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600539
540 #### Loop through fields again...
541
542 for field in get_ofb_fields(flow):
543
544 if field.type == ETH_TYPE:
545 _type = field.eth_type
546 log.info('#### field.type == ETH_TYPE ####', in_port=in_port,
547 match=_type)
548
549 elif field.type == IP_PROTO:
550 _proto = field.ip_proto
551 log.info('#### field.type == IP_PROTO ####', in_port=in_port,
Paul Graycfc2dc32017-05-31 12:58:43 -0700552 ip_proto=_proto)
Nathan Knuthd8285e62017-01-11 14:18:43 -0600553
554 elif field.type == IN_PORT:
555 _port = field.port
556 log.info('#### field.type == IN_PORT ####')
Nathan Knuthd8285e62017-01-11 14:18:43 -0600557
558 elif field.type == VLAN_VID:
559 _vlan_vid = field.vlan_vid & 0xfff
560 log.info('#### field.type == VLAN_VID ####')
561
562 elif field.type == VLAN_PCP:
563 _vlan_pcp = field.vlan_pcp
564 log.info('#### field.type == VLAN_PCP ####')
Nathan Knuthd8285e62017-01-11 14:18:43 -0600565
566 elif field.type == UDP_DST:
567 _udp_dst = field.udp_dst
568 log.info('#### field.type == UDP_DST ####')
569
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600570 elif field.type == IPV4_DST:
571 _ipv4_dst = field.ipv4_dst
572 log.info('#### field.type == IPV4_DST ####')
573 a = int(hex(_ipv4_dst)[2:4], 16)
574 b = int(hex(_ipv4_dst)[4:6], 16)
575 c = int(hex(_ipv4_dst)[6:8], 16)
576 d = int(hex(_ipv4_dst)[8:], 16)
Paul Graycfc2dc32017-05-31 12:58:43 -0700577 dn_req = AddStaticMacAddress(mac=mcastIp2McastMac('%d.%d.%d.%d' % (a,b,c,d)))
578 Is_MCast = True
Nathan Knuth5f4163e2017-01-11 18:21:10 -0600579
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800580 else:
581 raise NotImplementedError('field.type={}'.format(
582 field.type))
583
584 for action in get_actions(flow):
585
586 if action.type == OUTPUT:
Nathan Knuthd8285e62017-01-11 14:18:43 -0600587 log.info('#### action.type == OUTPUT ####')
588
589 elif action.type == POP_VLAN:
590 log.info('#### action.type == POP_VLAN ####')
Paul Graycfc2dc32017-05-31 12:58:43 -0700591 dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
592 operator=Operator['=='], match=_vlan_vid)
593 dn_req /= PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag'])
594 dn_req /= PortIngressRuleResultSet(
595 fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800596
597 elif action.type == PUSH_VLAN:
Nathan Knuthd8285e62017-01-11 14:18:43 -0600598 log.info('#### action.type == PUSH_VLAN ####')
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800599 if action.push.ethertype != 0x8100:
600 log.error('unhandled-ether-type',
601 ethertype=action.push.ethertype)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800602
603 elif action.type == SET_FIELD:
Nathan Knuthd8285e62017-01-11 14:18:43 -0600604 log.info('#### action.type == SET_FIELD ####')
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800605 assert (action.set_field.field.oxm_class ==
606 ofp.OFPXMC_OPENFLOW_BASIC)
607 field = action.set_field.field.ofb_field
608 if field.type == VLAN_VID:
Paul Graycfc2dc32017-05-31 12:58:43 -0700609 dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0,
610 operator=Operator['=='], match=_vlan_vid)
611 dn_req /= PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag'])
612 dn_req /= PortIngressRuleResultSet(
613 fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff)
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800614 else:
615 log.error('unsupported-action-set-field-type',
616 field_type=field.type)
617
618 else:
Nathan Knuthd8285e62017-01-11 14:18:43 -0600619 log.error('UNSUPPORTED-ACTION-TYPE',
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800620 action_type=action.type)
621
Paul Graycfc2dc32017-05-31 12:58:43 -0700622 if Is_MCast is True:
623 action = "Set Static IP MCAST address"
Andrew Chagnona09233a2017-07-25 12:53:55 -0400624 else:
Paul Graycfc2dc32017-05-31 12:58:43 -0700625 dn_req /= PortIngressRuleTerminator()
626 dn_req /= AddPortIngressRule()
627 action = "Set ONU DS Rule"
628
629 msg = (
630 EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
631 EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=dn_req)/
632 EndOfPDU()
633 )
634
635 # send message
636 log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
637 self.adapter_agent.send_proxied_message(device.proxy_address, msg)
638
639 # Get and process the Set Response
640 rc = []
641 yield self._handle_set_resp(device, action, rc)
642
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800643 else:
644 raise Exception('Port should be 1 or 2 by our convention')
645
Andrew Chagnona09233a2017-07-25 12:53:55 -0400646 log.info('bulk-flow-update finished', device_id=device.id,
647 flows=flows, groups=groups)
648 log.info('########################################')
649
Zsolt Harasztied091602016-12-08 13:36:38 -0800650 def update_flows_incrementally(self, device, flow_changes, group_changes):
651 raise NotImplementedError()
652
653 def send_proxied_message(self, proxy_address, msg):
654 raise NotImplementedError()
655
656 def receive_proxied_message(self, proxy_address, msg):
Nathan Knutha1a11932017-01-12 16:59:58 -0800657 log.info('receive-proxied-message',
658 proxy_address=proxy_address, msg=msg.show(dump=True))
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800659 self.incoming_messages.put(msg)
660
Nikolay Titov89004ec2017-06-19 18:22:42 -0400661 def create_interface(self, device, data):
662 raise NotImplementedError()
663
664 def update_interface(self, device, data):
665 raise NotImplementedError()
666
667 def remove_interface(self, device, data):
668 raise NotImplementedError()
669
670 def receive_onu_detect_state(self, device_id, state):
671 raise NotImplementedError()
672
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800673 @inlineCallbacks
674 def _message_exchange(self, device):
675
676 # register for receiving async messages
677 self.adapter_agent.register_for_proxied_messages(device.proxy_address)
678
679 # reset incoming message queue
680 while self.incoming_messages.pending:
681 _ = yield self.incoming_messages.get()
682
Paul Gray934d2882017-05-25 04:44:49 -0700683 # send out ping frame to ONU device get device information
684 ping_frame = (
Paul Grayef008892017-05-17 12:28:45 -0700685 EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
Paul Gray934d2882017-05-25 04:44:49 -0700686 EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Get Request"],
687 body=VendorName() /
688 OnuMode() /
689 HardwareVersion() /
690 ManufacturerInfo()
691 ) /
692 EndOfPDU()
Paul Grayef008892017-05-17 12:28:45 -0700693 )
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800694
Paul Gray934d2882017-05-25 04:44:49 -0700695 log.info('ONU-send-proxied-message to Get Version Info for ONU: {}'.format(device.mac_address))
696 self.adapter_agent.send_proxied_message(device.proxy_address, ping_frame)
Paul Grayeee44382017-03-31 09:00:25 -0700697
Paul Gray934d2882017-05-25 04:44:49 -0700698 # Loop until we have a Get Response
Paul Grayeee44382017-03-31 09:00:25 -0700699 ack = False
Paul Grayeee44382017-03-31 09:00:25 -0700700 while not ack:
701 frame = yield self.incoming_messages.get()
Paul Grayeee44382017-03-31 09:00:25 -0700702
Paul Graycfc2dc32017-05-31 12:58:43 -0700703 respType = get_oam_msg_type(log, frame)
Andrew Chagnona09233a2017-07-25 12:53:55 -0400704
Paul Gray934d2882017-05-25 04:44:49 -0700705 if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]):
Paul Grayeee44382017-03-31 09:00:25 -0700706 ack = True
707 else:
708 # Handle unexpected events/OMCI messages
Paul Graycfc2dc32017-05-31 12:58:43 -0700709 check_resp(log, frame)
Paul Grayeee44382017-03-31 09:00:25 -0700710
Paul Grayeee44382017-03-31 09:00:25 -0700711 if ack:
Paul Gray934d2882017-05-25 04:44:49 -0700712 log.info('ONU-response received for Get Version Info for ONU: {}'.format(device.mac_address))
Paul Grayef008892017-05-17 12:28:45 -0700713
Paul Gray934d2882017-05-25 04:44:49 -0700714 self._process_ping_frame_response(device, frame)
Paul Grayef008892017-05-17 12:28:45 -0700715
Paul Grayef008892017-05-17 12:28:45 -0700716
Paul Gray934d2882017-05-25 04:44:49 -0700717 if self.mode.upper()[0] == "G": # GPON
Paul Grayac4850d2017-06-02 14:53:40 -0700718
Andrew Chagnonb4d604f2017-06-09 15:45:39 -0400719 hw_vers = int(device.hardware_version, 16)
Paul Grayac4850d2017-06-02 14:53:40 -0700720
Andrew Chagnonfe0eb732017-07-10 19:29:29 -0400721 if hw_vers >= 0x170618:
722 mcastLidx = 0x04bc
723 elif hw_vers >= 0x170517:
Paul Grayac4850d2017-06-02 14:53:40 -0700724 mcastLidx = 0x14bc
725 else:
726 mcastLidx = 0x10bc
727
728 log.info("Using Multicast LIDX {:04X}".format(mcastLidx))
729
Paul Gray934d2882017-05-25 04:44:49 -0700730 # construct multicast LLID set
731 msg = (
732 EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
Paul Grayac4850d2017-06-02 14:53:40 -0700733 EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Multicast Register"],body=MulticastRegisterSet(MulticastLink=mcastLidx, UnicastLink=0)
Paul Gray934d2882017-05-25 04:44:49 -0700734 ))
735
736 # send message
737 log.info('ONU-send-proxied-message to Multicast Register Set for ONU: {}'.format(device.mac_address))
738 self.adapter_agent.send_proxied_message(device.proxy_address, msg)
739
740 # The MulticastRegisterSet does not currently return a response. Just hope it worked.
Zsolt Haraszti348d1932016-12-10 01:10:07 -0800741
742 # by returning we allow the device to be shown as active, which
743 # indirectly verified that message passing works
Zsolt Haraszti656ecc62016-12-28 15:08:23 -0800744
745 def receive_packet_out(self, logical_device_id, egress_port_no, msg):
746 log.info('packet-out', logical_device_id=logical_device_id,
747 egress_port_no=egress_port_no, msg_len=len(msg))
Zsolt Harasztic5f740b2017-01-18 09:53:17 -0800748
Peter Shafik9107f2e2017-05-02 15:54:39 -0400749 def receive_inter_adapter_message(self, msg):
750 raise NotImplementedError()
751
Stephane Barbarie980a0912017-05-11 11:27:06 -0400752 def suppress_alarm(self, filter):
753 raise NotImplementedError()
754
755 def unsuppress_alarm(self, filter):
756 raise NotImplementedError()
757
Zsolt Harasztic5f740b2017-01-18 09:53:17 -0800758 def start_kpi_collection(self, device_id):
759
760 """TMP Simulate periodic KPI metric collection from the device"""
761 import random
762
763 @inlineCallbacks # pretend that we need to do async calls
764 def _collect(device_id, prefix):
765
766 try:
767 # Step 1: gather metrics from device (pretend it here) - examples
768 uni_port_metrics = yield dict(
769 tx_pkts=random.randint(0, 100),
770 rx_pkts=random.randint(0, 100),
771 tx_bytes=random.randint(0, 100000),
772 rx_bytes=random.randint(0, 100000),
773 )
774 pon_port_metrics = yield dict(
775 tx_pkts=uni_port_metrics['rx_pkts'],
776 rx_pkts=uni_port_metrics['tx_pkts'],
777 tx_bytes=uni_port_metrics['rx_bytes'],
778 rx_bytes=uni_port_metrics['tx_bytes'],
779 )
780 onu_metrics = yield dict(
781 cpu_util=20 + 5 * random.random(),
782 buffer_util=10 + 10 * random.random()
783 )
784
785 # Step 2: prepare the KpiEvent for submission
786 # we can time-stamp them here (or could use time derived from OLT
787 ts = arrow.utcnow().timestamp
788 kpi_event = KpiEvent(
789 type=KpiEventType.slice,
790 ts=ts,
791 prefixes={
792 # OLT-level
793 prefix: MetricValuePairs(metrics=onu_metrics),
794 # OLT NNI port
795 prefix + '.nni': MetricValuePairs(metrics=uni_port_metrics),
796 # OLT PON port
797 prefix + '.pon': MetricValuePairs(metrics=pon_port_metrics)
798 }
799 )
800
801 # Step 3: submit
802 self.adapter_agent.submit_kpis(kpi_event)
803
804 except Exception as e:
805 log.exception('failed-to-submit-kpis', e=e)
806
807 prefix = 'voltha.{}.{}'.format(self.name, device_id)
808 lc = LoopingCall(_collect, device_id, prefix)
809 lc.start(interval=15) # TODO make this configurable
810
Paul Grayef008892017-05-17 12:28:45 -0700811
812# Methods for Get / Set Response Processing from eoam_messages
813
Paul Gray934d2882017-05-25 04:44:49 -0700814 @inlineCallbacks
815 def _send_igmp_mcast_addr(self, device):
816 # construct install of igmp query address
817 msg = (
818 EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
819 EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Set Request"],body=AddStaticMacAddress(mac='01:00:5e:00:00:01')
820 ))
821
822 action = "Set Static IGMP MAC address"
823
824 # send message
825 log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
826 self.adapter_agent.send_proxied_message(device.proxy_address, msg)
827
828 rc = []
829 yield self._handle_set_resp(device, action, rc)
830
831
832 @inlineCallbacks
833 def _send_clear_static_mac_table(self, device):
834 # construct install of igmp query address
835 msg = (
836 EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) /
837 EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Set Request"],body=ClearStaticMacTable()
838 ))
839
840 action = "Clear Static MAC Table"
841
842 # send message
843 log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address))
844 self.adapter_agent.send_proxied_message(device.proxy_address, msg)
845
846 rc = []
847 yield self._handle_set_resp(device, action, rc)
Andrew Chagnona09233a2017-07-25 12:53:55 -0400848
Paul Gray934d2882017-05-25 04:44:49 -0700849
850 @inlineCallbacks
851 def _handle_set_resp(self, device, action, retcode):
852 # Get and process the Set Response
853 ack = False
854 start_time = time.time()
855
856 # Loop until we have a set response or timeout
857 while not ack:
858 frame = yield self.incoming_messages.get()
859 #TODO - Need to add propoer timeout functionality
860 #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None):
861 # break # don't wait forever
862
Paul Graycfc2dc32017-05-31 12:58:43 -0700863 respType = get_oam_msg_type(log, frame)
Paul Gray934d2882017-05-25 04:44:49 -0700864
865 #Check that the message received is a Set Response
866 if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]):
867 ack = True
868 else:
Andrew Chagnona09233a2017-07-25 12:53:55 -0400869 log.info('Received Unexpected OAM Message 0x{:X} while waiting for Set Resp for {}'.format(respType,action))
Paul Gray934d2882017-05-25 04:44:49 -0700870 # Handle unexpected events/OMCI messages
Paul Graycfc2dc32017-05-31 12:58:43 -0700871 check_resp(log, frame)
Paul Gray934d2882017-05-25 04:44:49 -0700872
873 # Verify Set Response
874 rc = False
875 if ack:
Paul Graycfc2dc32017-05-31 12:58:43 -0700876 (rc,branch,leaf,status) = check_set_resp(log, frame)
Paul Gray934d2882017-05-25 04:44:49 -0700877 if (rc is False):
878 log.info('Set Response had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status]))
Andrew Chagnona09233a2017-07-25 12:53:55 -0400879
Paul Gray934d2882017-05-25 04:44:49 -0700880 if (rc is True):
881 log.info('ONU-response received for {} for ONU: {}'.format(action, device.mac_address))
882 else:
883 log.info('BAD ONU-response received for {} for ONU: {}'.format(action, device.mac_address))
884
885 retcode.append(rc)
886
887 def _process_ping_frame_response(self, device, frame):
888
889 vendor = [0xD7, 0x0011]
890 ponMode = [0xB7, 0x0105]
891 hw_version = [0xD7, 0x0013]
892 manufacturer = [0xD7, 0x0006]
893 branch_leaf_pairs = [vendor, ponMode, hw_version, manufacturer]
Andrew Chagnona09233a2017-07-25 12:53:55 -0400894
Paul Gray934d2882017-05-25 04:44:49 -0700895 for pair in branch_leaf_pairs:
896 temp_pair = pair
Paul Graycfc2dc32017-05-31 12:58:43 -0700897 (rc, value) = (get_value_from_msg(log, frame, pair[0], pair[1]))
Paul Gray934d2882017-05-25 04:44:49 -0700898 temp_pair.append(rc)
899 temp_pair.append(value)
900 if rc:
901 overall_rc = True
Andrew Chagnona09233a2017-07-25 12:53:55 -0400902 else:
Paul Gray934d2882017-05-25 04:44:49 -0700903 log.info('Failed to get valid response for Branch 0x{:X} Leaf 0x{:0>4X} '.format(temp_pair[0], temp_pair[1]))
904 ack = True
905
906 if vendor[rc]:
907 device.vendor = vendor.pop()
908 if device.vendor.endswith(''):
909 device.vendor = device.vendor[:-1]
910 else:
911 device.vendor = "UNKNOWN"
Andrew Chagnona09233a2017-07-25 12:53:55 -0400912
Paul Gray934d2882017-05-25 04:44:49 -0700913 # mode: 3 = EPON OLT, 7 = GPON OLT
Andrew Chagnona09233a2017-07-25 12:53:55 -0400914 # mode: 2 = EPON ONU, 6 = GPON ONU
Paul Gray934d2882017-05-25 04:44:49 -0700915 if ponMode[rc]:
916 value = ponMode.pop()
917 mode = "UNKNOWN"
918 self.mode = "UNKNOWN"
919
920 if value == 6:
921 mode = "10G GPON ONU"
922 self.mode = "GPON"
923 if value == 2:
924 mode = "10G EPON ONU"
925 self.mode = "EPON"
926 if value == 1:
927 mode = "10G Point to Point"
928 self.mode = "Unsupported"
929
930 device.model = mode
931
932 else:
933 device.model = "UNKNOWN"
934 self.mode = "UNKNOWN"
935
936 log.info("PON Mode is {}".format(self.mode))
Andrew Chagnona09233a2017-07-25 12:53:55 -0400937
Paul Gray934d2882017-05-25 04:44:49 -0700938 if hw_version[rc]:
939 device.hardware_version = hw_version.pop()
Andrew Chagnonb4d604f2017-06-09 15:45:39 -0400940 device.hardware_version = device.hardware_version.replace("FA","")
Paul Gray934d2882017-05-25 04:44:49 -0700941 if device.hardware_version.endswith(''):
942 device.hardware_version = device.hardware_version[:-1]
943 else:
944 device.hardware_version = "UNKNOWN"
945
946 if manufacturer[rc]:
947 manu_value = manufacturer.pop()
948 device.firmware_version = re.search('\Firmware: (.+?) ', manu_value).group(1)
ggowdru236bd952017-06-20 20:32:55 -0700949 image_1 = Image(version = \
950 re.search('\Build: (.+?) ', manu_value).group(1))
951 device.images.image.extend([ image_1 ])
Paul Gray934d2882017-05-25 04:44:49 -0700952 device.serial_number = re.search('\Serial #: (.+?) ', manu_value).group(1)
953 else:
954 device.firmware_version = "UNKNOWN"
ggowdru236bd952017-06-20 20:32:55 -0700955 image_1 = Image(version="UNKNOWN")
956 device.images.image.extend([ image_1 ])
Paul Gray934d2882017-05-25 04:44:49 -0700957 device.serial_number = "UNKNOWN"
958
959 device.connect_status = ConnectStatus.REACHABLE