blob: 59ec56b8489bf06c3c8f89ff781e83da2e2aa2d9 [file] [log] [blame]
Chip Boling3e3b1a92017-05-16 11:51:18 -05001#
2# Copyright 2017-present Adtran, Inc.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import random
Chip Bolingc0451382018-08-24 14:21:53 -050018import arrow
Chip Boling3e3b1a92017-05-16 11:51:18 -050019
20import structlog
Chip Boling27275992017-09-22 15:17:04 -050021import xmltodict
Chip Bolingab8863d2018-03-22 14:50:31 -050022from port import AdtnPort
Chip Bolingc0451382018-08-24 14:21:53 -050023from twisted.internet import reactor
Chip Boling5561d552017-07-07 15:11:26 -050024from twisted.internet.defer import inlineCallbacks, returnValue, succeed, fail
Chip Boling27275992017-09-22 15:17:04 -050025from twisted.python.failure import Failure
Chip Boling3e3b1a92017-05-16 11:51:18 -050026from voltha.core.logical_device_agent import mac_str_to_tuple
27from voltha.protos.common_pb2 import OperStatus, AdminState
28from voltha.protos.device_pb2 import Port
29from voltha.protos.logical_device_pb2 import LogicalPort
30from voltha.protos.openflow_13_pb2 import OFPPF_100GB_FD, OFPPF_FIBER, OFPPS_LIVE, ofp_port
31
Chip Boling3e3b1a92017-05-16 11:51:18 -050032
Chip Bolingab8863d2018-03-22 14:50:31 -050033class NniPort(AdtnPort):
Chip Boling3e3b1a92017-05-16 11:51:18 -050034 """
Chip Bolingab8863d2018-03-22 14:50:31 -050035 Northbound network port, often Ethernet-based
Chip Boling3e3b1a92017-05-16 11:51:18 -050036 """
Chip Boling3e3b1a92017-05-16 11:51:18 -050037 def __init__(self, parent, **kwargs):
Chip Bolingab8863d2018-03-22 14:50:31 -050038 super(NniPort, self).__init__(parent, **kwargs)
39
Chip Boling3e3b1a92017-05-16 11:51:18 -050040 # TODO: Weed out those properties supported by common 'Port' object
Chip Boling3e3b1a92017-05-16 11:51:18 -050041
Chip Boling7294b252017-06-15 16:16:55 -050042 self.log = structlog.get_logger(port_no=kwargs.get('port_no'))
Chip Boling27275992017-09-22 15:17:04 -050043 self.log.info('creating')
Chip Boling3e3b1a92017-05-16 11:51:18 -050044
Chip Boling3eedf462018-10-17 12:18:28 -050045 # ONOS/SEBA wants 'nni-<port>' for port names, OLT NETCONF wants their
46 # name (something like hundred-gigabit-ethernet 0/1) which is reported
47 # when we enumerated the ports
48 self._physical_port_name = kwargs.get('name', 'nni-{}'.format(self._port_no))
49 self._logical_port_name = 'nni-{}'.format(self._port_no)
Chip Bolingab8863d2018-03-22 14:50:31 -050050 self._logical_port = None
51
52 self.sync_tick = 10.0
Chip Boling27275992017-09-22 15:17:04 -050053
Chip Bolingfd1fd372017-12-20 13:34:12 -060054 self._stats_tick = 5.0
55 self._stats_deferred = None
56
Chip Boling7294b252017-06-15 16:16:55 -050057 # Local cache of NNI configuration
Chip Boling27275992017-09-22 15:17:04 -050058 self._ianatype = '<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>'
Chip Boling3e3b1a92017-05-16 11:51:18 -050059
60 # And optional parameters
Chip Boling5561d552017-07-07 15:11:26 -050061 # TODO: Currently cannot update admin/oper status, so create this enabled and active
62 # self._admin_state = kwargs.pop('admin_state', AdminState.UNKNOWN)
63 # self._oper_status = kwargs.pop('oper_status', OperStatus.UNKNOWN)
Chip Bolingab8863d2018-03-22 14:50:31 -050064 self._enabled = True
Chip Boling5561d552017-07-07 15:11:26 -050065 self._admin_state = AdminState.ENABLED
66 self._oper_status = OperStatus.ACTIVE
Chip Boling3e3b1a92017-05-16 11:51:18 -050067
Chip Boling3eedf462018-10-17 12:18:28 -050068 self._label = self._physical_port_name
Chip Boling5561d552017-07-07 15:11:26 -050069 self._mac_address = kwargs.pop('mac_address', '00:00:00:00:00:00')
70 # TODO: Get with JOT and find out how to pull out MAC Address via NETCONF
Chip Boling3e3b1a92017-05-16 11:51:18 -050071 # TODO: May need to refine capabilities into current, advertised, and peer
72
Chip Boling7294b252017-06-15 16:16:55 -050073 self._ofp_capabilities = kwargs.pop('ofp_capabilities', OFPPF_100GB_FD | OFPPF_FIBER)
74 self._ofp_state = kwargs.pop('ofp_state', OFPPS_LIVE)
75 self._current_speed = kwargs.pop('current_speed', OFPPF_100GB_FD)
76 self._max_speed = kwargs.pop('max_speed', OFPPF_100GB_FD)
77 self._device_port_no = kwargs.pop('device_port_no', self._port_no)
78
Chip Bolingfd1fd372017-12-20 13:34:12 -060079 # Statistics
Chip Bolingfd1fd372017-12-20 13:34:12 -060080 self.rx_dropped = 0
Chip Bolingc0451382018-08-24 14:21:53 -050081 self.rx_error_packets = 0
82 self.rx_ucast_packets = 0
83 self.rx_bcast_packets = 0
84 self.rx_mcast_packets = 0
Chip Bolingfd1fd372017-12-20 13:34:12 -060085 self.tx_dropped = 0
Chip Bolingc0451382018-08-24 14:21:53 -050086 self.rx_ucast_packets = 0
87 self.tx_bcast_packets = 0
88 self.tx_mcast_packets = 0
Chip Bolingfd1fd372017-12-20 13:34:12 -060089
Chip Boling3e3b1a92017-05-16 11:51:18 -050090 def __str__(self):
Chip Boling7294b252017-06-15 16:16:55 -050091 return "NniPort-{}: Admin: {}, Oper: {}, parent: {}".format(self._port_no,
92 self._admin_state,
93 self._oper_status,
94 self._parent)
95
Chip Boling3e3b1a92017-05-16 11:51:18 -050096 def get_port(self):
97 """
98 Get the VOLTHA PORT object for this port
99 :return: VOLTHA Port object
100 """
Chip Bolingc64c8dc2018-04-20 14:42:24 -0500101 self.log.debug('get-port-status-update', port=self._port_no,
Chip Bolingbb15b512018-06-01 11:39:58 -0500102 label=self._label)
Chip Boling7294b252017-06-15 16:16:55 -0500103 if self._port is None:
104 self._port = Port(port_no=self._port_no,
105 label=self._label,
106 type=Port.ETHERNET_NNI,
107 admin_state=self._admin_state,
108 oper_status=self._oper_status)
Chip Bolingc64c8dc2018-04-20 14:42:24 -0500109
110 if self._port.admin_state != self._admin_state or\
111 self._port.oper_status != self._oper_status:
112
113 self.log.debug('get-port-status-update', admin_state=self._admin_state,
Chip Bolingc0451382018-08-24 14:21:53 -0500114 oper_status=self._oper_status)
Chip Bolingc64c8dc2018-04-20 14:42:24 -0500115 self._port.admin_state = self._admin_state
116 self._port.oper_status = self._oper_status
117
Chip Boling7294b252017-06-15 16:16:55 -0500118 return self._port
Chip Boling3e3b1a92017-05-16 11:51:18 -0500119
Chip Bolingab8863d2018-03-22 14:50:31 -0500120 @property
121 def iana_type(self):
122 return self._ianatype
123
124 def cancel_deferred(self):
125 super(NniPort, self).cancel_deferred()
126
127 d, self._stats_deferred = self._stats_deferred, None
128 try:
129 if d is not None and d.called:
130 d.cancel()
131 except:
132 pass
133
134 def _update_adapter_agent(self):
Chip Bolingc64c8dc2018-04-20 14:42:24 -0500135 # adapter_agent add_port also does an update of port status
136 self.log.debug('update-adapter-agent', admin_state=self._admin_state,
Chip Bolingbb15b512018-06-01 11:39:58 -0500137 oper_status=self._oper_status)
Chip Bolingc64c8dc2018-04-20 14:42:24 -0500138 self.adapter_agent.add_port(self.olt.device_id, self.get_port())
Chip Bolingab8863d2018-03-22 14:50:31 -0500139
Chip Boling3e3b1a92017-05-16 11:51:18 -0500140 def get_logical_port(self):
141 """
142 Get the VOLTHA logical port for this port
143 :return: VOLTHA logical port or None if not supported
144 """
Chip Boling7294b252017-06-15 16:16:55 -0500145 if self._logical_port is None:
146 openflow_port = ofp_port(port_no=self._port_no,
147 hw_addr=mac_str_to_tuple(self._mac_address),
Chip Boling3eedf462018-10-17 12:18:28 -0500148 name=self._logical_port_name,
Chip Boling3e3b1a92017-05-16 11:51:18 -0500149 config=0,
Chip Boling7294b252017-06-15 16:16:55 -0500150 state=self._ofp_state,
151 curr=self._ofp_capabilities,
152 advertised=self._ofp_capabilities,
153 peer=self._ofp_capabilities,
154 curr_speed=self._current_speed,
155 max_speed=self._max_speed)
Chip Boling3e3b1a92017-05-16 11:51:18 -0500156
Chip Boling3eedf462018-10-17 12:18:28 -0500157 self._logical_port = LogicalPort(id=self._logical_port_name,
Chip Boling7294b252017-06-15 16:16:55 -0500158 ofp_port=openflow_port,
159 device_id=self._parent.device_id,
160 device_port_no=self._device_port_no,
161 root_port=True)
162 return self._logical_port
Chip Boling3e3b1a92017-05-16 11:51:18 -0500163
Chip Boling48646962017-08-20 09:41:18 -0500164 @inlineCallbacks
Chip Bolingab8863d2018-03-22 14:50:31 -0500165 def finish_startup(self):
166
167 if self.state != AdtnPort.State.INITIAL:
Chip Boling7294b252017-06-15 16:16:55 -0500168 returnValue('Done')
169
Chip Bolingc64c8dc2018-04-20 14:42:24 -0500170 self.log.debug('final-startup')
Chip Bolingef0e2fa2017-10-06 14:33:01 -0500171 # TODO: Start status polling of NNI interfaces
Chip Bolingab8863d2018-03-22 14:50:31 -0500172 self.deferred = None # = reactor.callLater(3, self.do_stuff)
Chip Bolingfd1fd372017-12-20 13:34:12 -0600173
Chip Bolingab8863d2018-03-22 14:50:31 -0500174 # Begin statistics sync
175 self._stats_deferred = reactor.callLater(self._stats_tick * 2, self._update_statistics)
Chip Bolingef0e2fa2017-10-06 14:33:01 -0500176
Chip Boling48646962017-08-20 09:41:18 -0500177 try:
Chip Bolingab8863d2018-03-22 14:50:31 -0500178 yield self.set_config('enabled', True)
179
180 super(NniPort, self).finish_startup()
Chip Boling7294b252017-06-15 16:16:55 -0500181
Chip Boling48646962017-08-20 09:41:18 -0500182 except Exception as e:
183 self.log.exception('nni-start', e=e)
Chip Bolingfd1fd372017-12-20 13:34:12 -0600184 self._oper_status = OperStatus.UNKNOWN
185 self._update_adapter_agent()
186
Chip Bolingab8863d2018-03-22 14:50:31 -0500187 returnValue('Enabled')
Chip Boling7294b252017-06-15 16:16:55 -0500188
Chip Bolingab8863d2018-03-22 14:50:31 -0500189 def finish_stop(self):
Chip Boling69fba862017-08-18 15:11:32 -0500190
Chip Boling7294b252017-06-15 16:16:55 -0500191 # NOTE: Leave all NNI ports active (may have inband management)
192 # TODO: Revisit leaving NNI Ports active on disable
193
Chip Bolingab8863d2018-03-22 14:50:31 -0500194 return self.set_config('enabled', False)
Chip Boling7294b252017-06-15 16:16:55 -0500195
196 @inlineCallbacks
197 def reset(self):
198 """
199 Set the NNI Port to a known good state on initial port startup. Actual
200 NNI 'Start' is done elsewhere
201 """
Chip Bolingc0451382018-08-24 14:21:53 -0500202 # if self.state != AdtnPort.State.INITIAL:
203 # self.log.error('reset-ignored', state=self.state)
204 # returnValue('Ignored')
Chip Boling7294b252017-06-15 16:16:55 -0500205
Chip Boling27275992017-09-22 15:17:04 -0500206 self.log.info('resetting', label=self._label)
Chip Boling7294b252017-06-15 16:16:55 -0500207
208 # Always enable our NNI ports
209
210 try:
211 results = yield self.set_config('enabled', True)
212 self._admin_state = AdminState.ENABLED
213 self._enabled = True
214 returnValue(results)
215
216 except Exception as e:
Chip Boling27275992017-09-22 15:17:04 -0500217 self.log.exception('reset', e=e)
Chip Boling7294b252017-06-15 16:16:55 -0500218 self._admin_state = AdminState.UNKNOWN
219 raise
220
221 @inlineCallbacks
222 def set_config(self, leaf, value):
Chip Boling27275992017-09-22 15:17:04 -0500223 if isinstance(value, bool):
224 value = 'true' if value else 'false'
225
Chip Boling7294b252017-06-15 16:16:55 -0500226 config = '<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">' + \
227 ' <interface>' + \
Chip Boling3eedf462018-10-17 12:18:28 -0500228 ' <name>{}</name>'.format(self._physical_port_name) + \
Chip Boling27275992017-09-22 15:17:04 -0500229 ' {}'.format(self._ianatype) + \
230 ' <{}>{}</{}>'.format(leaf, value, leaf) + \
Chip Boling7294b252017-06-15 16:16:55 -0500231 ' </interface>' + \
232 '</interfaces>'
233 try:
234 results = yield self._parent.netconf_client.edit_config(config)
235 returnValue(results)
236
237 except Exception as e:
Chip Boling27275992017-09-22 15:17:04 -0500238 self.log.exception('set', leaf=leaf, value=value, e=e)
Chip Boling7294b252017-06-15 16:16:55 -0500239 raise
240
Chip Boling27275992017-09-22 15:17:04 -0500241 def get_nni_config(self):
242 config = '<filter xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">' + \
243 ' <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">' + \
244 ' <interface>' + \
Chip Boling3eedf462018-10-17 12:18:28 -0500245 ' <name>{}</name>'.format(self._physical_port_name) + \
Chip Boling27275992017-09-22 15:17:04 -0500246 ' <enabled/>' + \
247 ' </interface>' + \
248 ' </interfaces>' + \
249 '</filter>'
250 return self._parent.netconf_client.get(config)
251
Chip Bolingfd1fd372017-12-20 13:34:12 -0600252 def get_nni_statistics(self):
253 state = '<filter xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">' + \
254 ' <interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">' + \
255 ' <interface>' + \
Chip Boling3eedf462018-10-17 12:18:28 -0500256 ' <name>{}</name>'.format(self._physical_port_name) + \
Chip Bolingfd1fd372017-12-20 13:34:12 -0600257 ' <admin-status/>' + \
258 ' <oper-status/>' + \
259 ' <statistics/>' + \
260 ' </interface>' + \
261 ' </interfaces>' + \
262 '</filter>'
263 return self._parent.netconf_client.get(state)
264
Chip Bolingab8863d2018-03-22 14:50:31 -0500265 def sync_hardware(self):
266 if self.state == AdtnPort.State.RUNNING or self.state == AdtnPort.State.STOPPED:
Chip Boling27275992017-09-22 15:17:04 -0500267 def read_config(results):
Chip Bolingbb15b512018-06-01 11:39:58 -0500268 #self.log.debug('read-config', results=results)
Chip Boling27275992017-09-22 15:17:04 -0500269 try:
270 result_dict = xmltodict.parse(results.data_xml)
Chip Bolingc64c8dc2018-04-20 14:42:24 -0500271 interfaces = result_dict['data']['interfaces']
272 if 'if:interface' in interfaces:
273 entries = interfaces['if:interface']
274 else:
275 entries = interfaces['interface']
Chip Boling27275992017-09-22 15:17:04 -0500276
277 enabled = entries.get('enabled',
278 str(not self.enabled).lower()) == 'true'
279
Chip Bolingfd1fd372017-12-20 13:34:12 -0600280 if self.enabled == enabled:
281 return succeed('in-sync')
282
283 self.set_config('enabled', self.enabled)
284 self._oper_status = OperStatus.ACTIVE
285 self._update_adapter_agent()
Chip Boling27275992017-09-22 15:17:04 -0500286
287 except Exception as e:
288 self.log.exception('read-config', e=e)
289 return fail(Failure())
290
291 def failure(reason):
292 self.log.error('hardware-sync-failed', reason=reason)
293
294 def reschedule(_):
Chip Bolingab8863d2018-03-22 14:50:31 -0500295 delay = self.sync_tick
Chip Boling27275992017-09-22 15:17:04 -0500296 delay += random.uniform(-delay / 10, delay / 10)
Chip Bolingab8863d2018-03-22 14:50:31 -0500297 self.sync_deferred = reactor.callLater(delay, self.sync_hardware)
Chip Boling27275992017-09-22 15:17:04 -0500298
Chip Bolingab8863d2018-03-22 14:50:31 -0500299 self.sync_deferred = self.get_nni_config()
300 self.sync_deferred.addCallbacks(read_config, failure)
301 self.sync_deferred.addBoth(reschedule)
Chip Boling27275992017-09-22 15:17:04 -0500302
Chip Bolingfd1fd372017-12-20 13:34:12 -0600303 def _decode_nni_statistics(self, entry):
Chip Bolingc0451382018-08-24 14:21:53 -0500304 # admin_status = entry.get('admin-status')
305 # oper_status = entry.get('oper-status')
306 # admin_status = entry.get('admin-status')
307 # phys_address = entry.get('phys-address')
Chip Bolingfd1fd372017-12-20 13:34:12 -0600308
309 stats = entry.get('statistics')
310 if stats is not None:
Chip Bolingc0451382018-08-24 14:21:53 -0500311 self.timestamp = arrow.utcnow().float_timestamp
Chip Bolingfd1fd372017-12-20 13:34:12 -0600312 self.rx_bytes = int(stats.get('in-octets', 0))
Chip Bolingc0451382018-08-24 14:21:53 -0500313 self.rx_ucast_packets = int(stats.get('in-unicast-pkts', 0))
314 self.rx_bcast_packets = int(stats.get('in-broadcast-pkts', 0))
315 self.rx_mcast_packets = int(stats.get('in-multicast-pkts', 0))
316 self.rx_error_packets = int(stats.get('in-errors', 0)) + int(stats.get('in-discards', 0))
Chip Bolingfd1fd372017-12-20 13:34:12 -0600317
318 self.tx_bytes = int(stats.get('out-octets', 0))
Chip Bolingc0451382018-08-24 14:21:53 -0500319 self.tx_ucast_packets = int(stats.get('out-unicast-pkts', 0))
320 self.tx_bcast_packets = int(stats.get('out-broadcast-pkts', 0))
321 self.tx_mcasy_packets = int(stats.get('out-multicast-pkts', 0))
322 self.tx_error_packets = int(stats.get('out-errors', 0)) + int(stats.get('out-discards', 0))
Chip Bolingfd1fd372017-12-20 13:34:12 -0600323
Chip Bolingc0451382018-08-24 14:21:53 -0500324 self.rx_packets = self.rx_ucast_packets + self.rx_mcast_packets + self.rx_bcast_packets
325 self.tx_packets = self.tx_ucast_packets + self.tx_mcast_packets + self.tx_bcast_packets
326 # No support for rx_crc_errors or bip_errors
Chip Bolingfd1fd372017-12-20 13:34:12 -0600327
328 def _update_statistics(self):
Chip Bolingab8863d2018-03-22 14:50:31 -0500329 if self.state == AdtnPort.State.RUNNING:
Chip Bolingfd1fd372017-12-20 13:34:12 -0600330 def read_state(results):
Chip Bolingbb15b512018-06-01 11:39:58 -0500331 # self.log.debug('read-state', results=results)
Chip Bolingfd1fd372017-12-20 13:34:12 -0600332 try:
333 result_dict = xmltodict.parse(results.data_xml)
334 entry = result_dict['data']['interfaces-state']['interface']
335 self._decode_nni_statistics(entry)
336 return succeed('done')
337
338 except Exception as e:
339 self.log.exception('read-state', e=e)
340 return fail(Failure())
341
342 def failure(reason):
343 self.log.error('update-stats-failed', reason=reason)
344
345 def reschedule(_):
346 delay = self._stats_tick
347 delay += random.uniform(-delay / 10, delay / 10)
348 self._stats_deferred = reactor.callLater(delay, self._update_statistics)
349
350 try:
351 self._stats_deferred = self.get_nni_statistics()
352 self._stats_deferred.addCallbacks(read_state, failure)
353 self._stats_deferred.addBoth(reschedule)
354
355 except Exception as e:
356 self.log.exception('nni-sync', port=self.name, e=e)
357 self._stats_deferred = reactor.callLater(self._stats_tick, self._update_statistics)
358
Chip Boling7294b252017-06-15 16:16:55 -0500359
360class MockNniPort(NniPort):
361 """
362 A class similar to the 'Port' class in the VOLTHA but for a non-existent (virtual OLT)
363
364 TODO: Merge this with the Port class or cleanup where possible
365 so we do not duplicate fields/properties/methods
366 """
367
368 def __init__(self, parent, **kwargs):
369 super(MockNniPort, self).__init__(parent, **kwargs)
370
371 def __str__(self):
372 return "NniPort-mock-{}: Admin: {}, Oper: {}, parent: {}".format(self._port_no,
373 self._admin_state,
374 self._oper_status,
375 self._parent)
376
377 @staticmethod
378 def get_nni_port_state_results():
379 from ncclient.operations.retrieve import GetReply
380 raw = """
381 <?xml version="1.0" encoding="UTF-8"?>
382 <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
383 xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
384 message-id="urn:uuid:59e71979-01bb-462f-b17a-b3a45e1889ac">
385 <data>
386 <interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
387 <interface><name>hundred-gigabit-ethernet 0/1</name></interface>
Chip Boling7294b252017-06-15 16:16:55 -0500388 </interfaces-state>
389 </data>
390 </rpc-reply>
391 """
392 return GetReply(raw)
393
Chip Bolingab8863d2018-03-22 14:50:31 -0500394 @staticmethod
395 def get_pon_port_state_results():
396 from ncclient.operations.retrieve import GetReply
397 raw = """
398 <?xml version="1.0" encoding="UTF-8"?>
399 <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
400 xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
401 message-id="urn:uuid:59e71979-01bb-462f-b17a-b3a45e1889ac">
402 <data>
403 <interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
404 <interface><name>XPON 0/1</name></interface>
405 <interface><name>XPON 0/2</name></interface>
406 <interface><name>XPON 0/3</name></interface>
407 <interface><name>XPON 0/4</name></interface>
408 <interface><name>XPON 0/5</name></interface>
409 <interface><name>XPON 0/6</name></interface>
410 <interface><name>XPON 0/7</name></interface>
411 <interface><name>XPON 0/8</name></interface>
412 <interface><name>XPON 0/9</name></interface>
413 <interface><name>XPON 0/10</name></interface>
414 <interface><name>XPON 0/11</name></interface>
415 <interface><name>XPON 0/12</name></interface>
416 <interface><name>XPON 0/13</name></interface>
417 <interface><name>XPON 0/14</name></interface>
418 <interface><name>XPON 0/15</name></interface>
419 <interface><name>XPON 0/16</name></interface>
420 </interfaces-state>
421 </data>
422 </rpc-reply>
423 """
424 return GetReply(raw)
425
Chip Boling7294b252017-06-15 16:16:55 -0500426 def reset(self):
427 """
428 Set the NNI Port to a known good state on initial port startup. Actual
429 NNI 'Start' is done elsewhere
430 """
Chip Bolingab8863d2018-03-22 14:50:31 -0500431 if self.state != AdtnPort.State.INITIAL:
432 self.log.error('reset-ignored', state=self.state)
Chip Boling5561d552017-07-07 15:11:26 -0500433 return fail()
Chip Boling7294b252017-06-15 16:16:55 -0500434
Chip Boling27275992017-09-22 15:17:04 -0500435 self.log.info('resetting', label=self._label)
Chip Boling7294b252017-06-15 16:16:55 -0500436
437 # Always enable our NNI ports
438
439 self._enabled = True
440 self._admin_state = AdminState.ENABLED
Chip Boling5561d552017-07-07 15:11:26 -0500441 return succeed('Enabled')
Chip Boling7294b252017-06-15 16:16:55 -0500442
Chip Boling7294b252017-06-15 16:16:55 -0500443 def set_config(self, leaf, value):
444
445 if leaf == 'enabled':
446 self._enabled = value
447 else:
448 raise NotImplemented("Leaf '{}' is not supported".format(leaf))
449
Chip Boling5561d552017-07-07 15:11:26 -0500450 return succeed('Success')