blob: 646da82afd3482f2c92224c560e8565dbe9427e2 [file] [log] [blame]
#
# Copyright 2017 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from uuid import uuid4
import structlog
from voltha.adapters.microsemi_olt.PAS5211 import CHANNELS, PORTS
from voltha.protos.common_pb2 import ConnectStatus, OperStatus, AdminState
from voltha.protos.device_pb2 import Device, Port, Image
from voltha.protos.logical_device_pb2 import LogicalDevice, LogicalPort
from voltha.protos.openflow_13_pb2 import ofp_desc, ofp_switch_features, OFPC_FLOW_STATS, OFPC_TABLE_STATS, \
OFPC_PORT_STATS, OFPC_GROUP_STATS, ofp_port, OFPPS_LIVE, OFPPF_10GB_FD, OFPPF_FIBER
from twisted.internet import reactor
log = structlog.get_logger()
def mac_str_to_tuple(mac):
"""
Convert 'xx:xx:xx:xx:xx:xx' MAC address string to a tuple of integers.
Example: mac_str_to_tuple('00:01:02:03:04:05') == (0, 1, 2, 3, 4, 5)
"""
return tuple(int(d, 16) for d in mac.split(':'))
class DeviceManager(object):
def __init__(self, device, adapter_agent):
self.device = device
self.adapter_agent = adapter_agent
self.logical_device = None
def update_device_info_from_pkt(self, pkt):
self.device.root = True
self.device.vendor = 'Celestica Inc.'
self.device.model = 'Ruby'
self.device.hardware_version = \
'{}.{}'.format(hex(pkt.major_hardware_version),
pkt.minor_hardware_version)
self.device.firmware_version = '{}.{}.{}'.format(pkt.major_firmware_version,
pkt.minor_firmware_version,
pkt.build_firmware_version)
# There could be multiple software version on the device,
# active, standby etc. Choose the active or running software
# below. See simulated_olt for example implementation
self.device.images.image.extend([
Image(version="0.0.1")
])
self.device.serial_number = self.device.mac_address
self.device.oper_status = ConnectStatus.REACHABLE
# self.adapter_agent.update_device(self.device)
for i in PORTS:
self.adapter_agent.add_port(self.device.id, Port(
port_no=i,
label='PON port',
type=Port.PON_OLT,
admin_state=AdminState.ENABLED,
oper_status=OperStatus.ACTIVE
))
self.create_logical_device()
self.add_upstream_port(129)
self.add_logical_upstream_port(129)
self.device.parent_id = self.logical_device.id
self.adapter_agent.update_device(self.device)
def create_logical_device(self):
log.debug('create-logical-device')
# then shortly after we create the logical device with one port
# that will correspond to the NNI port
ld = LogicalDevice(
desc=ofp_desc(
mfr_desc=self.device.vendor,
hw_desc=self.device.hardware_version,
sw_desc=self.device.firmware_version,
serial_num=uuid4().hex,
dp_desc='n/a'
),
switch_features=ofp_switch_features(
n_buffers=256, # TODO fake for now
n_tables=2, # TODO ditto
capabilities=( # TODO and ditto
OFPC_FLOW_STATS
| OFPC_TABLE_STATS
| OFPC_PORT_STATS
| OFPC_GROUP_STATS
)
),
root_device_id=self.device.id
)
self.logical_device = self.adapter_agent.create_logical_device(ld, dpid=self.device.mac_address)
def delete_logical_device(self):
try:
log.debug('delete-logical-device')
self.adapter_agent.delete_logical_device(self.logical_device)
except Exception as e:
log.exception('delete-logical-device-failed', e=e)
def remove_all_logical_ports(self):
try:
log.debug('remove-logical-ports')
self.adapter_agent.remove_all_logical_ports(self.logical_device)
except Exception as e:
log.exception('delete-logical-device-failed', e=e)
def add_upstream_port(self, port):
nni_port = Port(
port_no=port,
label='NNI',
type=Port.ETHERNET_NNI,
admin_state=AdminState.ENABLED,
oper_status=OperStatus.ACTIVE
)
self.adapter_agent.add_port(self.device.id, nni_port)
def add_logical_upstream_port(self, port):
cap = OFPPF_10GB_FD | OFPPF_FIBER
self.adapter_agent.add_logical_port(self.logical_device.id, LogicalPort(
id='nni',
ofp_port=ofp_port(
port_no=port,
# hw_addr=mac_str_to_tuple(self.device.serial_number)[2:8],
hw_addr=mac_str_to_tuple('00:00:00:00:00:%02x' % port),
name='nni',
config=0,
state=OFPPS_LIVE,
curr=cap,
advertised=cap,
peer=cap,
curr_speed=OFPPF_10GB_FD,
max_speed=OFPPF_10GB_FD
),
device_id=self.device.id,
device_port_no=port,
root_port=True
))
def add_port(self, port):
self.adapter_agent.add_port(self.device.id, port)
cap = OFPPF_10GB_FD | OFPPF_FIBER
logical_port = LogicalPort(
id='uni',
ofp_port=ofp_port(
port_no=port.port_no,
hw_addr=mac_str_to_tuple(self.device.mac_address),
name='{}-{}'.format(port.label, port.port_no),
config=0,
state=OFPPS_LIVE,
curr=cap,
advertised=cap,
peer=cap,
curr_speed=OFPPF_10GB_FD,
max_speed=OFPPF_10GB_FD
)
)
self.adapter_agent.add_logical_port(self.logical_device.id,
logical_port)
def onu_detected(self, parent_port_no=None,
child_device_type=None,
onu_id=None,
serial_number=None,
onu_session_id=None,
channel_id=None):
log.debug('onu-detected')
try:
# self.adapter_agent.child_device_detected(
# parent_device_id=self.device.id,
# parent_port_no=parent_port_no,
# child_device_type=child_device_type,
# serial_number=serial_number,
# proxy_address=Device.ProxyAddress(
# device_id=self.device.id,
# channel_id=channel_id, # happens to be the channel id as well
# onu_id=onu_id,
# onu_session_id=onu_session_id
# ),
# admin_state=AdminState.ENABLED,
# vlan=0)
reactor.callLater(0, self.adapter_agent.child_device_detected,
parent_device_id=self.device.id,
parent_port_no=parent_port_no,
child_device_type=child_device_type,
serial_number=serial_number,
proxy_address=Device.ProxyAddress(
device_id=self.device.id,
channel_id=channel_id, # happens to be the channel id as well
onu_id=onu_id,
onu_session_id=onu_session_id
),
admin_state=AdminState.ENABLED,
vlan=0)
except Exception as e:
log.exception('onu-detected-failed', e=e)
raise e
def update_child_devices_state(self, oper_status=None,
connect_status=None,
admin_state=None):
try:
# self.adapter_agent.update_child_devices_state(self.device.id,
# oper_status=oper_status,
# connect_status=connect_status,
# admin_state=admin_state)
reactor.callLater(0, self.adapter_agent.update_child_devices_state,
self.device.id,
oper_status=oper_status,
connect_status=connect_status,
admin_state=admin_state)
except Exception:
log.debug("Child ONUs from {} could not be updated".format(self.device.id))
def delete_all_child_devices(self):
try:
# self.adapter_agent.delete_all_child_devices(self.device.id)
reactor.callLater(0, self.adapter_agent.delete_all_child_devices, self.device.id)
except Exception:
log.debug("Child ONUs from {} cannot be removed".format(self.device.id))
def deactivate_onu(self, onu_id=None, channel_id=None, onu_session_id=None):
try:
child_device = self.adapter_agent.get_child_device_with_proxy_address(Device.ProxyAddress(
device_id=self.device.id,
channel_id=channel_id,
onu_id=onu_id,
onu_session_id=onu_session_id
))
# self.adapter_agent.delete_child_device(self.device.id, child_device)
if child_device:
child_device.admin_state = AdminState.DISABLED
# self.adapter_agent._make_up_to_date('/devices', child_device.id, child_device)
reactor.callLater(0, self.adapter_agent._make_up_to_date,
'/devices', child_device.id, child_device)
#child_device.admin_state=AdminState.DISABLED
#self.adapter_agent.update_device(child_device)
except Exception:
log.debug("ONU {} cannot be deactivated".format(onu_id))
def activate(self):
# self.device = self.adapter_agent.get_device(self.device.id)
# self.device.parent_id = self.logical_device.id
self.device.oper_status = OperStatus.ACTIVE
self.adapter_agent.update_device(self.device)
def publish_alarm(self, alarm):
log.debug("publish-alarm-start")
new_alarm = self.adapter_agent.create_alarm(
id = alarm.get("id"),
resource_id = alarm.get("resource_id"),
description = alarm.get("description"),
type = alarm.get("type"),
category = alarm.get("category"),
severity = alarm.get("severity"),
state = alarm.get("state"),
context = alarm.get("context")
)
self.adapter_agent.submit_alarm(self.device.id, new_alarm)
log.debug("publish-alarm-stop")