blob: 13659429d959ca64f4d99a47c254e22b30cb3f5a [file] [log] [blame]
Shad Ansarib32e31c2017-06-28 01:55:50 -07001#
2# Copyright 2017 the original author or authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17"""
18Asfvolt16 OLT adapter
19"""
20
Rajeswara Raob2b369a2017-09-08 11:44:15 +053021import arrow
22from twisted.internet.defer import inlineCallbacks
23from voltha.protos.events_pb2 import KpiEvent, MetricValuePairs
24from voltha.protos.events_pb2 import KpiEventType
25from voltha.protos.device_pb2 import PmConfigs, PmConfig,PmGroupConfig
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +053026from voltha.adapters.asfvolt16_olt.protos import bal_errno_pb2, bal_pb2
Rajeswara Raob2b369a2017-09-08 11:44:15 +053027from voltha.protos.events_pb2 import AlarmEvent, AlarmEventType, \
28 AlarmEventSeverity, AlarmEventState, AlarmEventCategory
Shad Ansari1831fcc2017-08-11 16:41:44 -070029from scapy.layers.l2 import Ether, Dot1Q
Shad Ansarib32e31c2017-06-28 01:55:50 -070030from uuid import uuid4
Shad Ansarida0f3a42017-07-19 09:51:06 -070031from common.frameio.frameio import BpfProgramFilter
rshettyc26a3c32017-07-27 11:06:38 +053032from twisted.internet import reactor
Shad Ansari1831fcc2017-08-11 16:41:44 -070033from common.frameio.frameio import hexify
rshettyc26a3c32017-07-27 11:06:38 +053034from scapy.packet import Packet
rshetty1cc73982017-09-02 03:31:12 +053035import voltha.core.flow_decomposer as fd
Shad Ansari0d83c942017-07-05 21:30:38 -070036from voltha.protos.common_pb2 import OperStatus, ConnectStatus
Shad Ansari1831fcc2017-08-11 16:41:44 -070037from voltha.protos.device_pb2 import Port
Shad Ansari0d83c942017-07-05 21:30:38 -070038from voltha.protos.common_pb2 import AdminState
Shad Ansarib32e31c2017-06-28 01:55:50 -070039from voltha.protos.logical_device_pb2 import LogicalPort, LogicalDevice
rshettyf4bf19e2017-09-19 01:28:27 +053040from voltha.protos.openflow_13_pb2 import OFPPS_LIVE, OFPPF_FIBER, OFPPS_LINK_DOWN, \
Shad Ansarib32e31c2017-06-28 01:55:50 -070041 OFPPF_1GB_FD, OFPC_GROUP_STATS, OFPC_PORT_STATS, OFPC_TABLE_STATS, \
rshetty1cc73982017-09-02 03:31:12 +053042 OFPC_FLOW_STATS, ofp_switch_features, ofp_desc, ofp_port, \
43 OFPXMC_OPENFLOW_BASIC
Shad Ansarib32e31c2017-06-28 01:55:50 -070044from voltha.core.logical_device_agent import mac_str_to_tuple
Shad Ansari0d83c942017-07-05 21:30:38 -070045from voltha.adapters.asfvolt16_olt.bal import Bal
46from voltha.adapters.device_handler import OltDeviceHandler
rshetty1cc73982017-09-02 03:31:12 +053047from voltha.protos.bbf_fiber_base_pb2 import \
48 ChannelgroupConfig, ChannelpartitionConfig, ChannelpairConfig, \
49 ChannelterminationConfig, OntaniConfig, VOntaniConfig, VEnetConfig
50from voltha.protos.bbf_fiber_traffic_descriptor_profile_body_pb2 import \
51 TrafficDescriptorProfileData
52from voltha.protos.bbf_fiber_tcont_body_pb2 import TcontsConfigData
53from voltha.protos.bbf_fiber_gemport_body_pb2 import GemportsConfigData
54from voltha.protos.bbf_fiber_multicast_gemport_body_pb2 import \
55 MulticastGemportsConfigData
56from voltha.protos.bbf_fiber_multicast_distribution_set_body_pb2 import \
57 MulticastDistributionSetData
58import time
rshettyf4bf19e2017-09-19 01:28:27 +053059import binascii
Shad Ansarib32e31c2017-06-28 01:55:50 -070060
rshettyf4bf19e2017-09-19 01:28:27 +053061ASFVOLT_NNI_PORT = 129
Suhas Raoeba61c22017-08-10 11:42:32 -070062# ASFVOLT_NNI_PORT needs to be other than pon port value.
63# Edgecore OLT assigns PONport between 0 to 15, hence
rshettyf4bf19e2017-09-19 01:28:27 +053064# having a value 129 for NNI port to avoid collision.
Shad Ansarida0f3a42017-07-19 09:51:06 -070065# TODO: VLAN ID needs to come from some sort of configuration.
rshettyf4bf19e2017-09-19 01:28:27 +053066ASFVOLT16_DEFAULT_VLAN = 4091
Shad Ansarida0f3a42017-07-19 09:51:06 -070067PACKET_IN_VLAN = 4091
68is_inband_frame = BpfProgramFilter('(ether[14:2] & 0xfff) = 0x{:03x}'.format(
69 PACKET_IN_VLAN))
70
rshetty1cc73982017-09-02 03:31:12 +053071ASFVOLT_EAPOL_ID = 1
rshettyf4bf19e2017-09-19 01:28:27 +053072ASFVOLT_DOWNLINK_EAPOL_ID = 2
rshetty1cc73982017-09-02 03:31:12 +053073
rshettyf4bf19e2017-09-19 01:28:27 +053074ASFVOLT_EAPOL_ID_DATA_VLAN = 3
75ASFVOLT_DOWNLINK_EAPOL_ID_DATA_VLAN = 4
rshetty1cc73982017-09-02 03:31:12 +053076
rshettyf4bf19e2017-09-19 01:28:27 +053077ASFVOLT_DHCP_TAGGED_ID = 5
78ASFVOLT_DOWNLINK_DHCP_TAGGED_ID = 6
79
80ASFVOLT_IGMP_TAGGED_ID = 7
81ASFVOLT_DOWNLINK_IGMP_TAGGED_ID = 8
82
83ASFVOLT_FIRMWARE_ID = 9
84ASFVOLT_DOWNLINK_FIRMWARE_ID = 10
85
86ASFVOLT_ARP_ID = 11
87ASFVOLT_DOWNLINK_ARP_ID = 12
88
89ASFVOLT_HSIA_ID = 13
90ASFVOLT_DOWNLINK_HSIA_ID = 14
91
92ASFVOLT_DNS_ID = 15
93ASFVOLT_DOWNLINK_DNS_ID = 16
94
95
96class FlowInfo(object):
97
98 def __init__(self):
99 self.classifier = dict()
100 self.action = dict()
101 self.traffic_class = None
rshetty1cc73982017-09-02 03:31:12 +0530102
103class VEnetHandler(object):
104
105 def __init__(self):
106 self.v_enet = VEnetConfig()
107 self.gem_ports = dict()
rshettyf4bf19e2017-09-19 01:28:27 +0530108 self.pending_flows = []
rshetty1cc73982017-09-02 03:31:12 +0530109
110class VOntAniHandler(object):
111
112 def __init__(self):
113 self.v_ont_ani = VOntaniConfig()
114 self.tconts = dict()
115
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530116class Asfvolt16OltPmMetrics:
117 class Metrics:
118 def __init__(self, config, value=0):
119 self.config = config
120 self.value = value
121 # group PM config is not supported currently
122
123 def __init__(self,device):
124 self.pm_names = {
125 "rx_bytes", "rx_packets", "rx_ucast_packets", "rx_mcast_packets",
126 "rx_bcast_packets", "rx_error_packets", "rx_unknown_protos",
127 "tx_bytes", "tx_packets", "tx_ucast_packets", "tx_mcast_packets",
128 "tx_bcast_packets", "tx_error_packets", "rx_crc_errors", "bip_errors"
129 }
130 self.device = device
131 self.id = device.id
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530132 # To collect pm metrices for each 'pm_default_freq/10' secs
133 self.pm_default_freq = 20
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530134 self.pon_metrics = dict()
135 self.nni_metrics = dict()
136 for m in self.pm_names:
137 self.pon_metrics[m] = \
138 self.Metrics(config = PmConfig(name=m,
139 type=PmConfig.COUNTER,
140 enabled=True), value = 0)
141 self.nni_metrics[m] = \
142 self.Metrics(config = PmConfig(name=m,
143 type=PmConfig.COUNTER,
144 enabled=True), value = 0)
145
146 def update(self, device, pm_config):
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530147 if self.pm_default_freq != pm_config.default_freq:
148 self.pm_default_freq = pm_config.default_freq
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530149
150 if pm_config.grouped is True:
151 log.error('pm-groups-are-not-supported')
152 else:
153 for m in pm_config.metrics:
154 self.pon_metrics[m.name].config.enabled = m.enabled
155 self.nni_metrics[m.name].config.enabled = m.enabled
156
157 def make_proto(self):
158 pm_config = PmConfigs(
159 id=self.id,
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530160 default_freq=self.pm_default_freq,
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530161 grouped = False,
162 freq_override = False)
163 return pm_config
Shad Ansarida0f3a42017-07-19 09:51:06 -0700164
Shad Ansari0d83c942017-07-05 21:30:38 -0700165class Asfvolt16Handler(OltDeviceHandler):
rshetty1cc73982017-09-02 03:31:12 +0530166
Shad Ansarib32e31c2017-06-28 01:55:50 -0700167 def __init__(self, adapter, device_id):
Shad Ansari0d83c942017-07-05 21:30:38 -0700168 super(Asfvolt16Handler, self).__init__(adapter, device_id)
Shad Ansarida0f3a42017-07-19 09:51:06 -0700169 self.filter = is_inband_frame
rshettye4bd2ed2017-07-19 16:38:11 +0530170 self.bal = Bal(self, self.log)
Shad Ansarida0f3a42017-07-19 09:51:06 -0700171 self.host_and_port = None
rshettye4bd2ed2017-07-19 16:38:11 +0530172 self.olt_id = 0
rshetty1cc73982017-09-02 03:31:12 +0530173 self.channel_groups = dict()
174 self.channel_partitions = dict()
175 self.channel_pairs = dict()
176 self.channel_terminations = dict()
177 self.v_ont_anis = dict()
178 self.ont_anis = dict()
179 self.v_enets = dict()
180 self.traffic_descriptors = dict()
Rajeswara Rao37ddfc92017-09-13 16:56:18 +0530181 self.adapter_name = adapter.name
rshetty1cc73982017-09-02 03:31:12 +0530182 self.uni_port_num = 20
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530183 self.pm_metrics = None
184 self.heartbeat_count = 0
185 self.heartbeat_miss = 0
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530186 # For each 'heartbeat_interval' seconds,
187 # Adapter will send heartbeat request to device
188 self.heartbeat_interval = 5
189 self.heartbeat_failed_limit = 1
190 self.is_heartbeat_started = 0
Shad Ansarida0f3a42017-07-19 09:51:06 -0700191
192 def __del__(self):
193 super(Asfvolt16Handler, self).__del__()
194
195 def __str__(self):
196 return "Asfvolt16Handler: {}".format(self.host_and_port)
Shad Ansarib32e31c2017-06-28 01:55:50 -0700197
rshetty1cc73982017-09-02 03:31:12 +0530198 def _get_next_uni_port(self):
199 self.uni_port_num += 1
200 return self.uni_port_num
201
rshettyf4bf19e2017-09-19 01:28:27 +0530202 def get_venet(self, **kwargs):
203 name = kwargs.pop('name', None)
204 gem_port_id = kwargs.pop('gem_port_id', None)
rshetty1cc73982017-09-02 03:31:12 +0530205 for key, v_enet in self.v_enets.items():
rshettyf4bf19e2017-09-19 01:28:27 +0530206 if name is not None:
207 if key == name:
208 return v_enet
209 if gem_port_id is not None:
210 for gem_key, gem_port in v_enet.gem_ports.items():
211 if gem_port_id == gem_port.gemport_id:
212 return v_enet
rshetty1cc73982017-09-02 03:31:12 +0530213 return None
214
215 def get_v_ont_ani(self, name):
216 for key, v_ont_ani in self.v_ont_anis.items():
217 if key == name:
218 return v_ont_ani
219 return None
220
221 def get_gem_port_info(self, v_enet, **kwargs):
222 traffic_class = kwargs.pop('traffic_class', None)
223 name = kwargs.pop('name', None)
224 for key, gem_port in v_enet.gem_ports.items():
225 if traffic_class is not None:
226 if traffic_class == gem_port.traffic_class:
227 return gem_port
228 if name is not None:
229 if name == gem_port.name:
230 return gem_port
231 return None
232
233 def get_tcont_info(self, v_ont_ani, **kwargs):
234 alloc_id = kwargs.pop('alloc_id', None)
235 name = kwargs.pop('name', None)
236 for key, tcont in v_ont_ani.tconts.items():
237 if alloc_id is not None:
238 if alloc_id == tcont.alloc_id:
239 return tcont
240 if name is not None:
241 if name == tcont.name:
242 return tcont
243 return None
244
245 def get_traffic_profile(self, name):
246 for key, traffic_profile in self.traffic_descriptors():
247 if name is not None:
248 if name == traffic_profile.name:
249 return traffic_profile
250 return None
251
252 def get_flow_id(self, onu_id, intf_id, id):
253 # Tp-Do Need to generate unique flow ID using
254 # OnuID, IntfId, id
255 # BAL accepts flow_id till 16384. So we are
256 # using only onu_id and id to generate flow ID.
rshettyf4bf19e2017-09-19 01:28:27 +0530257 return ((onu_id << 5) | id)
258
259 def get_uni_port(self, device_id):
260 ports = self.adapter_agent.get_ports(device_id, Port.ETHERNET_UNI)
261 if ports:
262 # For now, we use on one uni port
263 return ports[0]
264 return None
265
266 def store_flows(self, uplink_classifier, uplink_action,
267 v_enet, traffic_class):
268 flow = FlowInfo()
269 flow.classifier = dict(uplink_classifier)
270 flow.action = dict(uplink_action)
271 flow.traffic_class = traffic_class
272 v_enet.pending_flows.append(flow)
273 return None
274
275 def add_pending_flows(self, v_enet, traffic_class):
276 for flow in v_enet.pending_flows[:]:
277 if flow.traffic_class == traffic_class:
278 self.divide_and_add_flow(v_enet,
279 flow.classifier,
280 flow.action)
281 v_enet.pending_flows.remove(flow)
282 return
283
284 def get_logical_port_using_gem_port(self, gem_port_id):
285 logical_port = None
286 v_enet = self.get_venet(gem_port_id=gem_port_id)
287 if v_enet is None:
288 self.log.error('Failed-to-get-v-enet', gem_port_id=gem_port_id)
289 return
290
291 v_ont_ani = self.get_v_ont_ani(v_enet.v_enet.data.v_ontani_ref)
292 if v_ont_ani is None:
293 self.log.info('Failed-to-get-v_ont_ani',
294 v_ont_ani=v_enet.v_enet.data.v_ontani_ref)
295 return
296
297 onu_device = self.adapter_agent.get_child_device(
298 self.device_id, onu_id=v_ont_ani.v_ont_ani.data.onu_id)
299 if onu_device is None:
300 self.log.info('Failed-to-get-onu-device',
301 onu_id=v_ont_ani.v_ont_ani.data.onu_id)
302 return
303
304 uni = self.get_uni_port(onu_device.id)
305 if uni is not None:
306 logical_port = (onu_device.proxy_address.channel_id + uni.port_no)
307 return logical_port
rshetty1cc73982017-09-02 03:31:12 +0530308
Shad Ansari0d83c942017-07-05 21:30:38 -0700309 def activate(self, device):
Shad Ansarida0f3a42017-07-19 09:51:06 -0700310
311 self.log.info('activating-asfvolt16-olt', device=device)
Shad Ansarib32e31c2017-06-28 01:55:50 -0700312
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530313 if not device.host_and_port:
314 device.oper_status = OperStatus.FAILED
315 device.reason = 'No host_and_port field provided'
316 self.adapter_agent.update_device(device)
317 return
Shad Ansarib32e31c2017-06-28 01:55:50 -0700318
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530319 self.bal.connect_olt(device.host_and_port, self.device_id)
320
321 if self.logical_device_id is None:
rshettye4bd2ed2017-07-19 16:38:11 +0530322
323 self.host_and_port = device.host_and_port
324 device.root = True
325 device.vendor = 'Edgecore'
326 device.model = 'ASFvOLT16'
327 device.serial_number = device.host_and_port
Shad Ansari0d83c942017-07-05 21:30:38 -0700328 self.adapter_agent.update_device(device)
rshettyc26a3c32017-07-27 11:06:38 +0530329
Shad Ansari1831fcc2017-08-11 16:41:44 -0700330 self.add_port(port_no=ASFVOLT_NNI_PORT,
331 port_type=Port.ETHERNET_NNI,
rshettyc26a3c32017-07-27 11:06:38 +0530332 label='NNI facing Ethernet port')
333 self.logical_device_id = \
334 self.add_logical_device(device_id=device.id)
rshetty1cc73982017-09-02 03:31:12 +0530335 self.add_logical_port(port_no=ASFVOLT_NNI_PORT,
rshettye4bd2ed2017-07-19 16:38:11 +0530336 port_type=Port.ETHERNET_NNI,
337 device_id=device.id,
338 logical_device_id=self.logical_device_id)
Shad Ansarib32e31c2017-06-28 01:55:50 -0700339
rshettye4bd2ed2017-07-19 16:38:11 +0530340 self.bal.activate_olt()
Shad Ansarib32e31c2017-06-28 01:55:50 -0700341
Shad Ansari0d83c942017-07-05 21:30:38 -0700342 device = self.adapter_agent.get_device(device.id)
343 device.parent_id = self.logical_device_id
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530344 device.connect_status = ConnectStatus.REACHABLE
Shad Ansari0d83c942017-07-05 21:30:38 -0700345 device.oper_status = OperStatus.ACTIVATING
346 self.adapter_agent.update_device(device)
Shad Ansarib32e31c2017-06-28 01:55:50 -0700347
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530348 @inlineCallbacks
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530349 def heartbeat(self, device, state = 'run'):
350 self.log.debug('olt-heartbeat', device=device, state=state,
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530351 count=self.heartbeat_count)
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530352 self.is_heartbeat_started = 1
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530353
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530354 def heartbeat_alarm(device, status, heartbeat_misses=0):
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530355 try:
356 ts = arrow.utcnow().timestamp
357
358 alarm_data = {'heartbeats_missed':str(heartbeat_misses)}
359
360 alarm_event = self.adapter_agent.create_alarm(
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530361 id='voltha.{}.{}.olt'.format(self.adapter.name, device),
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530362 resource_id='olt',
363 type=AlarmEventType.EQUIPMENT,
364 category=AlarmEventCategory.OLT,
365 severity=AlarmEventSeverity.CRITICAL,
366 state=AlarmEventState.RAISED if status else
367 AlarmEventState.CLEARED,
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530368 description='OLT Alarm - Connection to OLT - {}'.format('Lost'
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530369 if status
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530370 else 'Regained'),
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530371 context=alarm_data,
372 raised_ts = ts)
373
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530374 self.adapter_agent.submit_alarm(device, alarm_event)
375 self.log.debug('olt-heartbeat alarm sent')
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530376
377 except Exception as e:
378 self.log.exception('failed-to-submit-alarm', e=e)
379
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530380 try:
381 d = yield self.bal.get_bal_heartbeat(self.device_id.__str__())
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530382 except Exception as e:
383 d = None
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530384
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530385 _device = device
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530386
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530387 if d == None:
388 # something is not right - OLT is not Reachable
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530389 self.heartbeat_miss += 1
390 self.log.info('olt-heartbeat-miss',d=d,
391 count=self.heartbeat_count, miss=self.heartbeat_miss)
392 else:
393 if self.heartbeat_miss > 0:
394 self.heartbeat_miss = 0
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530395 if d.is_reboot == bal_pb2.BAL_OLT_UP_AFTER_REBOOT:
396 self.log.info('Activating OLT again after reboot')
397
398 # Since OLT is reachable after reboot, OLT should configurable with
399 # all the old existing flows. NNI port should be mark it as down for
400 # ONOS to push the old flows
401 self.update_logical_port(ASFVOLT_NNI_PORT, Port.ETHERNET_NNI,
402 OFPPS_LINK_DOWN)
403 for key, v_ont_ani in self.v_ont_anis.items():
404 child_device = self.adapter_agent.get_child_device(
405 self.device_id, onu_id=v_ont_ani.v_ont_ani.data.onu_id)
406 if child_device:
407 msg = {'proxy_address': child_device.proxy_address,
408 'event': 'deactivate-onu', 'event_data': "olt-reboot"}
409 # Send the event message to the ONU adapter
410 self.adapter_agent.publish_inter_adapter_message(child_device.id,
411 msg)
412 #Activate Device
413 self.activate(device);
414 else:
415 _device.connect_status = ConnectStatus.REACHABLE
416 _device.oper_status = OperStatus.ACTIVE
417 _device.reason = ''
418 self.adapter_agent.update_device(_device)
419 self.log.info('Clearing the Hearbeat Alarm')
420 heartbeat_alarm(_device, 0)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530421
422 if (self.heartbeat_miss >= self.heartbeat_failed_limit) and \
423 (_device.connect_status == ConnectStatus.REACHABLE):
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530424 self.log.info('olt-heartbeat-failed', count=self.heartbeat_miss)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530425 _device.connect_status = ConnectStatus.UNREACHABLE
426 _device.oper_status = OperStatus.FAILED
427 _device.reason = 'Lost connectivity to OLT'
428 self.adapter_agent.update_device(_device)
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530429 heartbeat_alarm(device, 1, self.heartbeat_miss)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530430
431 self.heartbeat_count += 1
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530432 reactor.callLater(self.heartbeat_interval, self.heartbeat, device)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530433
434 @inlineCallbacks
435 def reboot(self):
436 err_status = yield self.bal.set_bal_reboot(self.device_id.__str__())
437 self.log.info('Reboot Status', err_status = err_status)
438
439 @inlineCallbacks
440 def _handle_pm_counter_req_towards_device(self, device):
441 yield self._req_pm_counter_from_device_in_loop(device)
442
443 @inlineCallbacks
444 def _req_pm_counter_from_device_in_loop(self, device):
445 # NNI port is hardcoded to 0
Rajeswara Rao37ddfc92017-09-13 16:56:18 +0530446 kpi_status = -1
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530447 if device.connect_status == ConnectStatus.UNREACHABLE:
448 self.log.info('Device is not Reachable')
449 else:
450 try:
451 pm_counters = yield self.bal.get_bal_nni_stats(0)
452 kpi_status = 0
453 self.log.info('pm_counters',pm_counters=pm_counters)
454 except Exception as e:
455 kpi_status = -1
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530456
457 if kpi_status == 0 and pm_counters!=None:
458 pm_data = { }
459 pm_data["rx_bytes"]= pm_counters.rx_bytes
460 pm_data["rx_packets"]= pm_counters.rx_packets
461 pm_data["rx_ucast_packets"]= pm_counters.rx_ucast_packets
462 pm_data["rx_mcast_packets"]= pm_counters.rx_mcast_packets
463 pm_data["rx_bcast_packets"]= pm_counters.rx_bcast_packets
464 pm_data["rx_error_packets"]= pm_counters.rx_error_packets
465 pm_data["rx_unknown_protos"]= pm_counters.rx_unknown_protos
466 pm_data["tx_bytes"]= pm_counters.tx_bytes
467 pm_data["tx_packets"]= pm_counters.tx_packets
468 pm_data["tx_ucast_packets"]= pm_counters.tx_ucast_packets
469 pm_data["tx_mcast_packets"]= pm_counters.tx_mcast_packets
470 pm_data["tx_bcast_packets"]= pm_counters.tx_bcast_packets
471 pm_data["tx_error_packets"]= pm_counters.tx_error_packets
472 pm_data["rx_crc_errors"]= pm_counters.rx_crc_errors
473 pm_data["bip_errors"]= pm_counters.bip_errors
474
475 self.log.info('KPI stats', pm_data = pm_data)
476 name = 'asfvolt16_olt'
477 prefix = 'voltha.{}.{}'.format(name, self.device_id)
478 ts = arrow.utcnow().timestamp
479 prefixes = {
480 prefix + '.nni': MetricValuePairs(metrics = pm_data)
481 }
482
483 kpi_event = KpiEvent(
484 type=KpiEventType.slice,
485 ts=ts,
486 prefixes=prefixes)
487 self.adapter_agent.submit_kpis(kpi_event)
488 else:
489 self.log.info('Lost Connectivity to OLT')
490
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530491 reactor.callLater(self.pm_metrics.pm_default_freq/10,
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530492 self._req_pm_counter_from_device_in_loop,
493 device)
494
495 def update_pm_config(self, device, pm_config):
496 self.log.info("update-pm-config", device=device, pm_config=pm_config)
497 self.pm_metrics.update(device, pm_config)
498
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530499 def handle_alarms(self, _device_id, _object, key, alarm,
500 status, priority,
501 alarm_data=None):
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530502 self.log.info('received-alarm-msg',
503 object=_object,
504 key=key,
505 alarm=alarm,
506 status=status,
507 priority=priority,
508 alarm_data=alarm_data)
509
rshettyf4bf19e2017-09-19 01:28:27 +0530510 id = 'voltha.{}.{}.{}'.format(self.adapter.name,
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530511 _device_id, _object)
512 description = '{} Alarm - {} - {}'.format(_object.upper(),
513 alarm.upper(),
514 'Raised' if status else 'Cleared')
515
516 if priority == 'low':
517 severity = AlarmEventSeverity.MINOR
518 elif priority == 'medium':
519 severity = AlarmEventSeverity.MAJOR
520 elif priority == 'high':
521 severity = AlarmEventSeverity.CRITICAL
522 else:
523 severity = AlarmEventSeverity.INDETERMINATE
524
525 try:
526 ts = arrow.utcnow().timestamp
527
528 alarm_event = self.adapter_agent.create_alarm(
529 id=id,
530 resource_id=str(key),
531 type=AlarmEventType.EQUIPMENT,
532 category=AlarmEventCategory.PON,
533 severity=severity,
534 state=AlarmEventState.RAISED if status else AlarmEventState.CLEARED,
535 description=description,
536 context=alarm_data,
537 raised_ts=ts)
538
539 self.adapter_agent.submit_alarm(_device_id, alarm_event)
540
541 except Exception as e:
542 self.log.exception('failed-to-submit-alarm', e=e)
543
544 # take action based on alarm type, only pon_ni and onu objects report alarms
545 if object == 'pon_ni':
546 # key: {'device_id': <int>, 'pon_ni': <int>}
547 # alarm: 'los'
548 # status: <False|True>
549 pass
550 elif object == 'onu':
551 # key: {'device_id': <int>, 'pon_ni': <int>, 'onu_id': <int>}
552 # alarm: <'los'|'lob'|'lopc_miss'|'los_mic_err'|'dow'|'sf'|'sd'|'suf'|'df'|'tiw'|'looc'|'dg'>
553 # status: <False|True>
554 pass
555
556 def BalIfaceLosAlarm(self, device_id, Iface_ID,\
557 los_status, IfaceLos_data):
558 self.log.info('Interface Loss Of Signal Alarm')
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530559 self.handle_alarms(device_id,"pon_ni",\
560 Iface_ID,\
561 "loss_of_signal",los_status,"high",\
562 IfaceLos_data)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530563
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530564 def BalSubsTermDgiAlarm(self, device_id, intf_id,\
565 onu_id, dgi_status, balSubTermDgi_data,\
566 ind_info):
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530567 self.log.info('Subscriber terminal dying gasp')
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530568 self.handle_alarms(device_id,"onu",\
569 intf_id,\
570 "dgi_indication",dgi_status,"medium",\
571 balSubTermDgi_data)
572 if dgi_status == 1:
573 child_device = self.adapter_agent.get_child_device(
574 device_id, onu_id=onu_id)
575 if child_device is None:
576 self.log.info('Onu-is-not-configured', onu_id=onu_id)
577 return
578 msg = {'proxy_address': child_device.proxy_address,
579 'event': 'deactivate-onu', 'event_data': ind_info}
580
581 # Send the event message to the ONU adapter
582 self.adapter_agent.publish_inter_adapter_message(child_device.id,
583 msg)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530584
585 def BalSubsTermLosAlarm(self, device_id, Iface_ID,
586 los_status, SubTermAlarm_Data):
587 self.log.info('ONU Alarms for Subscriber Terminal LOS')
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530588 self.handle_alarms(device_id,"onu",\
589 Iface_ID,\
590 "ONU : Loss Of Signal",\
591 los_status, "medium",\
592 SubTermAlarm_Data)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530593
594 def BalSubsTermLobAlarm(self, device_id, Iface_ID,
595 lob_status, SubTermAlarm_Data):
596 self.log.info('ONU Alarms for Subscriber Terminal LOB')
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530597 self.handle_alarms(device_id,"onu",\
598 Iface_ID,\
599 "ONU : Loss Of Burst",\
600 lob_status, "medium",\
601 SubTermAlarm_Data)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530602
603 def BalSubsTermLopcMissAlarm(self, device_id, Iface_ID,
604 lopc_miss_status, SubTermAlarm_Data):
605 self.log.info('ONU Alarms for Subscriber Terminal LOPC Miss')
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530606 self.handle_alarms(device_id,"onu",\
607 Iface_ID,\
608 "ONU : Loss Of PLOAM miss channel",\
609 lopc_miss_status, "medium",\
610 SubTermAlarm_Data)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530611
612 def BalSubsTermLopcMicErrorAlarm(self, device_id, Iface_ID,
613 lopc_mic_error_status, SubTermAlarm_Data):
614 self.log.info('ONU Alarms for Subscriber Terminal LOPC Mic Error')
Rajeswara Rao2eb42bf2017-10-10 14:30:10 +0530615 self.handle_alarms(device_id,"onu",\
616 Iface_ID,\
617 "ONU : Loss Of PLOAM MIC Error",\
618 lopc_mic_error_status, "medium",\
619 SubTermAlarm_Data)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530620
rshettyc26a3c32017-07-27 11:06:38 +0530621 def add_port(self, port_no, port_type, label):
Shad Ansari0d83c942017-07-05 21:30:38 -0700622 self.log.info('adding-port', port_no=port_no, port_type=port_type)
623 if port_type is Port.ETHERNET_NNI:
rshettyc26a3c32017-07-27 11:06:38 +0530624 oper_status = OperStatus.ACTIVE
rshettye4bd2ed2017-07-19 16:38:11 +0530625 elif port_type is Port.PON_OLT:
rshettyc26a3c32017-07-27 11:06:38 +0530626 # To-Do The pon port status should be ACTIVATING.
627 # For now make the status as Active.
628 oper_status = OperStatus.ACTIVE
629 else:
rshetty1cc73982017-09-02 03:31:12 +0530630 self.log.error('invalid-port-type', port_type=port_type)
Shad Ansari0d83c942017-07-05 21:30:38 -0700631 return
Shad Ansarib32e31c2017-06-28 01:55:50 -0700632
Shad Ansari0d83c942017-07-05 21:30:38 -0700633 port = Port(
634 port_no=port_no,
635 label=label,
636 type=port_type,
637 admin_state=AdminState.ENABLED,
rshettye4bd2ed2017-07-19 16:38:11 +0530638 oper_status=oper_status
Shad Ansarib32e31c2017-06-28 01:55:50 -0700639 )
Shad Ansari0d83c942017-07-05 21:30:38 -0700640 self.adapter_agent.add_port(self.device_id, port)
Shad Ansarib32e31c2017-06-28 01:55:50 -0700641
Shad Ansari0d83c942017-07-05 21:30:38 -0700642 def add_logical_device(self, device_id):
643 self.log.info('adding-logical-device', device_id=device_id)
644 ld = LogicalDevice(
645 # not setting id and datapth_id will let the adapter
646 # agent pick id
647 desc=ofp_desc(
648 mfr_desc='cord project',
649 hw_desc='n/a',
650 sw_desc='logical device for Edgecore ASFvOLT16 OLT',
rshettyf4bf19e2017-09-19 01:28:27 +0530651 #serial_num=uuid4().hex,
652 serial_num=self.host_and_port,
Shad Ansari0d83c942017-07-05 21:30:38 -0700653 dp_desc='n/a'
654 ),
655 switch_features=ofp_switch_features(
656 n_buffers=256, # TODO fake for now
657 n_tables=2, # TODO ditto
658 capabilities=( # TODO and ditto
Shad Ansari1831fcc2017-08-11 16:41:44 -0700659 OFPC_FLOW_STATS |
660 OFPC_TABLE_STATS |
661 OFPC_PORT_STATS |
662 OFPC_GROUP_STATS
Shad Ansari0d83c942017-07-05 21:30:38 -0700663 )
664 ),
665 root_device_id=device_id
666 )
667 ld_initialized = self.adapter_agent.create_logical_device(ld)
668 return ld_initialized.id
669
rshettyc26a3c32017-07-27 11:06:38 +0530670 def add_logical_port(self, port_no, port_type,
671 device_id, logical_device_id):
672 self.log.info('adding-logical-port', port_no=port_no,
673 port_type=port_type, device_id=device_id)
Shad Ansari0d83c942017-07-05 21:30:38 -0700674 if port_type is Port.ETHERNET_NNI:
rshettyc26a3c32017-07-27 11:06:38 +0530675 label = 'nni'
Shad Ansari0d83c942017-07-05 21:30:38 -0700676 cap = OFPPF_1GB_FD | OFPPF_FIBER
rshettyc26a3c32017-07-27 11:06:38 +0530677 curr_speed = OFPPF_1GB_FD
678 max_speed = OFPPF_1GB_FD
Shad Ansari0d83c942017-07-05 21:30:38 -0700679 else:
rshetty1cc73982017-09-02 03:31:12 +0530680 self.log.error('invalid-port-type', port_type=port_type)
Shad Ansari0d83c942017-07-05 21:30:38 -0700681 return
682
rshettyc26a3c32017-07-27 11:06:38 +0530683 ofp = ofp_port(
rshettyf4bf19e2017-09-19 01:28:27 +0530684 port_no=port_no, # is 0 OK?
Shad Ansari0d83c942017-07-05 21:30:38 -0700685 hw_addr=mac_str_to_tuple('00:00:00:00:00:%02x' % 129),
686 name=label,
687 config=0,
rshettyf4bf19e2017-09-19 01:28:27 +0530688 #state=OFPPS_LIVE,
689 state=OFPPS_LINK_DOWN,
Shad Ansari0d83c942017-07-05 21:30:38 -0700690 curr=cap,
691 advertised=cap,
692 peer=cap,
693 curr_speed=curr_speed,
694 max_speed=max_speed)
695
696 logical_port = LogicalPort(
697 id=label,
698 ofp_port=ofp,
699 device_id=device_id,
700 device_port_no=port_no,
701 root_port=True
702 )
703
704 self.adapter_agent.add_logical_port(logical_device_id, logical_port)
705
rshettyf4bf19e2017-09-19 01:28:27 +0530706 def update_logical_port(self, port_no, port_type, state):
707 self.log.info('updating-logical-port', port_no=port_no,
708 port_type=port_type, device_id=self.device_id,
709 logical_device_id=self.logical_device_id)
710 if port_type is Port.ETHERNET_NNI:
711 label = 'nni'
712 else:
713 self.log.error('invalid-port-type', port_type=port_type)
714 return
715 logical_port = self.adapter_agent.get_logical_port(self.logical_device_id,
716 label)
717 logical_port.ofp_port.state = state
718 self.adapter_agent.update_logical_port(self.logical_device_id,
719 logical_port)
720
rshettye4bd2ed2017-07-19 16:38:11 +0530721 def handle_access_term_ind(self, ind_info):
rshettye4bd2ed2017-07-19 16:38:11 +0530722 device = self.adapter_agent.get_device(self.device_id)
rshettyc26a3c32017-07-27 11:06:38 +0530723 if ind_info['activation_successful'] is True:
rshetty1cc73982017-09-02 03:31:12 +0530724 self.log.info('successful-access-terminal-Indication',
rshettyc26a3c32017-07-27 11:06:38 +0530725 olt_id=self.olt_id)
rshettye4bd2ed2017-07-19 16:38:11 +0530726 device.connect_status = ConnectStatus.REACHABLE
727 device.oper_status = OperStatus.ACTIVE
728 device.reason = 'OLT activated successfully'
Shad Ansari1831fcc2017-08-11 16:41:44 -0700729 self.adapter_agent.update_device(device)
rshettyf4bf19e2017-09-19 01:28:27 +0530730 self.update_logical_port(ASFVOLT_NNI_PORT, Port.ETHERNET_NNI,
731 OFPPS_LIVE)
rshettye4bd2ed2017-07-19 16:38:11 +0530732 self.log.info('OLT activation complete')
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530733
734 #heart beat - To health checkup of OLT
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530735 if self.is_heartbeat_started == 0:
736 self.log.info('Heart beat is not yet started..starting now')
737 self.heartbeat(device)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530738
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530739 self.pm_metrics=Asfvolt16OltPmMetrics(device)
740 pm_config = self.pm_metrics.make_proto()
741 self.log.info("initial-pm-config", pm_config=pm_config)
742 self.adapter_agent.update_device_pm_config(pm_config,init=True)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530743
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530744 # Apply the PM configuration
745 self.update_pm_config(device, pm_config)
Rajeswara Raob2b369a2017-09-08 11:44:15 +0530746
Rajeswara Raoa78ddcd2017-10-10 18:13:27 +0530747 # Request PM counters from OLT device.
748 self._handle_pm_counter_req_towards_device(device)
rshettye4bd2ed2017-07-19 16:38:11 +0530749 else:
750 device.oper_status = OperStatus.FAILED
751 device.reason = 'Failed to Intialize OLT'
752 self.adapter_agent.update_device(device)
rshettyc26a3c32017-07-27 11:06:38 +0530753 reactor.callLater(15, self.activate, device)
rshettye4bd2ed2017-07-19 16:38:11 +0530754 return
755
rshettyc26a3c32017-07-27 11:06:38 +0530756 def handle_not_started_onu(self, child_device, ind_info):
757 if ind_info['_sub_group_type'] == 'onu_discovery':
rshetty1cc73982017-09-02 03:31:12 +0530758 self.log.info('Onu-discovered', olt_id=self.olt_id,
rshettyc26a3c32017-07-27 11:06:38 +0530759 pon_ni=ind_info['_pon_id'], onu_data=ind_info)
Shad Ansari1831fcc2017-08-11 16:41:44 -0700760 # To-Do: Need to handle the ONUs, where the admin state is
761 # ENABLED and operation state is in Failed or Unkown
rshetty1cc73982017-09-02 03:31:12 +0530762 self.log.info('Not-Yet-handled', olt_id=self.olt_id,
rshettyc26a3c32017-07-27 11:06:38 +0530763 pon_ni=ind_info['_pon_id'], onu_data=ind_info)
764 else:
rshetty1cc73982017-09-02 03:31:12 +0530765 self.log.info('Invalid-ONU-event', olt_id=self.olt_id,
rshettyc26a3c32017-07-27 11:06:38 +0530766 pon_ni=ind_info['_pon_id'], onu_data=ind_info)
767
768 def handle_activating_onu(self, child_device, ind_info):
769 pon_id = ind_info['_pon_id']
rshetty1cc73982017-09-02 03:31:12 +0530770 self.log.info('Not-handled-Yet', olt_id=self.olt_id,
rshettyc26a3c32017-07-27 11:06:38 +0530771 pon_ni=pon_id, onu_data=ind_info)
772
773 def handle_activated_onu(self, child_device, ind_info):
774 pon_id = ind_info['_pon_id']
rshetty1cc73982017-09-02 03:31:12 +0530775 self.log.info('Not-handled-Yet', olt_id=self.olt_id,
rshettyc26a3c32017-07-27 11:06:38 +0530776 pon_ni=pon_id, onu_data=ind_info)
777
778 def handle_discovered_onu(self, child_device, ind_info):
779 pon_id = ind_info['_pon_id']
780 if ind_info['_sub_group_type'] == 'onu_discovery':
rshetty1cc73982017-09-02 03:31:12 +0530781 self.log.info('Activation-is-in-progress', olt_id=self.olt_id,
rshettyc26a3c32017-07-27 11:06:38 +0530782 pon_ni=pon_id, onu_data=ind_info,
783 onu_id=child_device.proxy_address.onu_id)
784
785 elif ind_info['_sub_group_type'] == 'sub_term_indication':
rshetty1cc73982017-09-02 03:31:12 +0530786 self.log.info('ONU-activation-is-completed', olt_id=self.olt_id,
rshettyc26a3c32017-07-27 11:06:38 +0530787 pon_ni=pon_id, onu_data=ind_info)
788
789 msg = {'proxy_address': child_device.proxy_address,
790 'event': 'activation-completed', 'event_data': ind_info}
791
792 # Send the event message to the ONU adapter
793 self.adapter_agent.publish_inter_adapter_message(child_device.id,
794 msg)
rshetty1cc73982017-09-02 03:31:12 +0530795 if ind_info['activation_successful'] is True:
796 for key, v_ont_ani in self.v_ont_anis.items():
797 if v_ont_ani.v_ont_ani.data.onu_id == \
798 child_device.proxy_address.onu_id:
799 for tcont_key, tcont in v_ont_ani.tconts.items():
800 owner_info = dict()
801 # To-Do: Right Now use alloc_id as schduler ID. Need to
802 # find way to generate uninqe number.
803 id = tcont.alloc_id
804 owner_info['type'] = 'agg_port'
805 owner_info['intf_id'] = \
806 child_device.proxy_address.channel_id
807 owner_info['onu_id'] = \
808 child_device.proxy_address.onu_id
809 owner_info['alloc_id'] = tcont.alloc_id
810 self.bal.create_scheduler(id, 'upstream',
811 owner_info, 8)
rshettyc26a3c32017-07-27 11:06:38 +0530812 else:
rshetty1cc73982017-09-02 03:31:12 +0530813 self.log.info('Invalid-ONU-event', olt_id=self.olt_id,
rshettyc26a3c32017-07-27 11:06:38 +0530814 pon_ni=ind_info['_pon_id'], onu_data=ind_info)
815
816 onu_handlers = {
817 OperStatus.UNKNOWN: handle_not_started_onu,
818 OperStatus.FAILED: handle_not_started_onu,
819 OperStatus.ACTIVATING: handle_activating_onu,
820 OperStatus.ACTIVE: handle_activated_onu,
821 OperStatus.DISCOVERED: handle_discovered_onu,
822 }
823
824 def handle_sub_term_ind(self, ind_info):
825 child_device = self.adapter_agent.get_child_device(
826 self.device_id,
827 serial_number=(ind_info['_vendor_id'] +
828 ind_info['_vendor_specific']))
829 if child_device is None:
rshetty1cc73982017-09-02 03:31:12 +0530830 self.log.info('Onu-is-not-configured', olt_id=self.olt_id,
rshettyc26a3c32017-07-27 11:06:38 +0530831 pon_ni=ind_info['_pon_id'], onu_data=ind_info)
832 return
833
834 handler = self.onu_handlers.get(child_device.oper_status)
835 if handler:
836 handler(self, child_device, ind_info)
Suhas Raoc926fc12017-07-28 11:17:49 +0530837
838 def send_proxied_message(self, proxy_address, msg):
rshettyc26a3c32017-07-27 11:06:38 +0530839 if isinstance(msg, Packet):
840 msg = str(msg)
Suhas Raoc926fc12017-07-28 11:17:49 +0530841 try:
842 self.bal.send_omci_request_message(proxy_address, msg)
843 except Exception as e:
rshettyc26a3c32017-07-27 11:06:38 +0530844 self.log.exception('', exc=str(e))
845 return
rshettye4bd2ed2017-07-19 16:38:11 +0530846
Suhas Raoeba61c22017-08-10 11:42:32 -0700847 def handle_omci_ind(self, ind_info):
Shad Ansari1831fcc2017-08-11 16:41:44 -0700848 child_device = self.adapter_agent.get_child_device(
849 self.device_id,
850 onu_id=ind_info['onu_id'])
Suhas Raoeba61c22017-08-10 11:42:32 -0700851 if child_device is None:
Shad Ansari1831fcc2017-08-11 16:41:44 -0700852 self.log.info('Onu is not configured', onu_id=ind_info['onu_id'])
Suhas Raoeba61c22017-08-10 11:42:32 -0700853 return
854 try:
Shad Ansari1831fcc2017-08-11 16:41:44 -0700855 self.adapter_agent.receive_proxied_message(
856 child_device.proxy_address,
857 ind_info['packet'])
Suhas Raoeba61c22017-08-10 11:42:32 -0700858 except Exception as e:
rshetty1cc73982017-09-02 03:31:12 +0530859 self.log.exception('', exc=str(e))
Suhas Raoeba61c22017-08-10 11:42:32 -0700860 return
861
rshetty1cc73982017-09-02 03:31:12 +0530862 def handle_v_ont_ani_config(self, data):
863 serial_number = data.data.expected_serial_number
864 child_device = self.adapter_agent.get_child_device(
865 self.device_id,
866 serial_number=serial_number)
867 if child_device is None:
868 self.log.info('Failed-to-find-ONU-Info',
869 serial_number=serial_number)
870 elif child_device.admin_state == AdminState.ENABLED:
871 self.log.info('Activating ONU',
872 serial_number=serial_number,
873 onu_id=child_device.proxy_address.onu_id,
874 pon_id=child_device.parent_port_no)
875 onu_info = dict()
876 onu_info['pon_id'] = child_device.parent_port_no
877 onu_info['onu_id'] = child_device.proxy_address.onu_id
878 onu_info['vendor'] = child_device.vendor_id
879 onu_info['vendor_specific'] = serial_number[4:]
880 self.bal.activate_onu(onu_info)
881 else:
882 self.log.info('Invalid-ONU-state-to-activate',
883 onu_id=child_device.proxy_address.onu_id,
884 serial_number=serial_number)
885
rshettyc26a3c32017-07-27 11:06:38 +0530886 def create_interface(self, data):
887 try:
rshetty1cc73982017-09-02 03:31:12 +0530888 if isinstance(data, ChannelgroupConfig):
889 if data.name in self.channel_groups:
890 self.log('Channel-Group-already-present',
891 channel_group=data)
892 else:
893 channel_group_config = ChannelgroupConfig()
894 channel_group_config.CopyFrom(data)
895 self.channel_groups[data.name] = channel_group_config
896 if isinstance(data, ChannelpartitionConfig):
897 if data.name in self.channel_partitions:
898 self.log('Channel-partition-already-present',
899 channel_partition=data)
900 else:
901 channel_partition_config = ChannelpartitionConfig()
902 channel_partition_config.CopyFrom(data)
903 self.channel_partitions[data.name] = \
904 channel_partition_config
905 if isinstance(data, ChannelpairConfig):
906 if data.name in self.channel_pairs:
907 self.log('Channel-pair-already-present',
908 channel_pair=data)
909 else:
910 channel_pair_config = ChannelpairConfig()
911 channel_pair_config.CopyFrom(data)
912 self.channel_pairs[data.name] = channel_pair_config
rshettyc26a3c32017-07-27 11:06:38 +0530913 if isinstance(data, ChannelterminationConfig):
rshetty1cc73982017-09-02 03:31:12 +0530914 self.log.info('Activating-PON-port-at-OLT',
rshettyc26a3c32017-07-27 11:06:38 +0530915 pon_id=data.data.xgs_ponid)
916 self.add_port(port_no=data.data.xgs_ponid,
917 port_type=Port.PON_OLT,
918 label=data.name)
919 self.bal.activate_pon_port(self.olt_id, data.data.xgs_ponid)
rshetty1cc73982017-09-02 03:31:12 +0530920 if data.name in self.channel_terminations:
921 self.log.info('Channel-termination-already-present',
922 channel_termination=data)
rshettyc26a3c32017-07-27 11:06:38 +0530923 else:
rshetty1cc73982017-09-02 03:31:12 +0530924 channel_termination_config = ChannelterminationConfig()
925 channel_termination_config.CopyFrom(data)
926 self.channel_terminations[data.name] = \
927 channel_termination_config
928 if isinstance(data, VOntaniConfig):
929 if data.name in self.v_ont_anis:
930 self.log.info('v_ont_ani-already-present',
931 v_ont_ani=data)
932 else:
933 self.handle_v_ont_ani_config(data)
934 v_ont_ani_config = VOntAniHandler()
935 v_ont_ani_config.v_ont_ani.CopyFrom(data)
936 self.v_ont_anis[data.name] = v_ont_ani_config
937 if isinstance(data, VEnetConfig):
938 if data.name in self.v_enets:
939 self.log.info('v_enet-already-present',
940 v_enet=data)
941 else:
942 v_enet_config = VEnetHandler()
943 v_enet_config.v_enet.CopyFrom(data)
944 self.log.info("creating-port-at-olt")
945 self.adapter_agent.add_port(self.device_id, Port(
946 port_no=self._get_next_uni_port(),
947 label=data.interface.name,
948 type=Port.ETHERNET_UNI,
949 admin_state=AdminState.ENABLED,
950 oper_status=OperStatus.ACTIVE
951 ))
952 self.v_enets[data.name] = v_enet_config
953 if isinstance(data, OntaniConfig):
954 if data.name in self.ont_anis:
955 self.log.info('ont_ani-already-present',
956 v_enet=data)
957 else:
958 ont_ani_config = OntaniConfig()
959 ont_ani_config.CopyFrom(data)
960 self.ont_anis[data.name] = ont_ani_config
rshettyc26a3c32017-07-27 11:06:38 +0530961 except Exception as e:
962 self.log.exception('', exc=str(e))
963 return
964
965 def update_interface(self, data):
rshetty1cc73982017-09-02 03:31:12 +0530966 self.log.info('Not-Implemented-yet')
rshettyc26a3c32017-07-27 11:06:38 +0530967 return
968
969 def remove_interface(self, data):
rshetty1cc73982017-09-02 03:31:12 +0530970 self.log.info('Not-Implemented-yet')
rshettyc26a3c32017-07-27 11:06:38 +0530971 return
972
rshetty1cc73982017-09-02 03:31:12 +0530973 def create_tcont(self, tcont_data, traffic_descriptor_data):
974 if traffic_descriptor_data.name in self.traffic_descriptors:
975 traffic_descriptor = TrafficDescriptorProfileData()
976 traffic_descriptor.CopyFrom(traffic_descriptor_data)
977 self.traffic_descriptors[traffic_descriptor_data.name] = \
978 traffic_descriptor
979 if tcont_data.interface_reference in self.v_ont_anis:
980 v_ont_ani = self.v_ont_anis[tcont_data.interface_reference]
981 onu_device = self.adapter_agent.get_child_device(
982 self.device_id,
983 onu_id=v_ont_ani.v_ont_ani.data.onu_id)
984 if (onu_device is not None and
985 onu_device.oper_status == OperStatus.ACTIVE):
986 owner_info = dict()
987 # To-Do: Right Now use alloc_id as schduler ID. Need to
988 # find way to generate uninqe number.
989 id = tcont_data.alloc_id
990 owner_info['type'] = 'agg_port'
991 owner_info['intf_id'] = onu_device.proxy_address.channel_id
992 owner_info['onu_id'] = onu_device.proxy_address.onu_id
993 owner_info['alloc_id'] = tcont_data.alloc_id
994 self.bal.create_scheduler(id, 'upstream', owner_info, 8)
995 else:
996 self.log.info('Onu-is-not-configured', olt_id=self.olt_id,
997 intf_id=onu_device.proxy_address.channel_id,
998 onu_data=onu_device.proxy_address.onu_id)
999 if tcont_data.name in v_ont_ani.tconts:
1000 self.log.info('tcont-info-already-present',
1001 tcont_info=tcont_data)
1002 else:
1003 tcont = TcontsConfigData()
1004 tcont.CopyFrom(tcont_data)
1005 v_ont_ani.tconts[tcont_data.name] = tcont
1006
1007 def update_tcont(self, tcont_data, traffic_descriptor_data):
1008 raise NotImplementedError()
1009
1010 def remove_tcont(self, tcont_data, traffic_descriptor_data):
1011 raise NotImplementedError()
1012
1013 def create_gemport(self, data):
1014 if data.itf_ref in self.v_enets:
1015 v_enet = self.v_enets[data.itf_ref]
1016 if data.name in v_enet.gem_ports:
1017 self.log.info('Gem-port-info-is-already-present',
1018 VEnet=v_enet, gem_info=data)
rshettyf4bf19e2017-09-19 01:28:27 +05301019 if data.gemport_id > 9215:
rshetty1cc73982017-09-02 03:31:12 +05301020 raise Exception('supported range for '
rshettyf4bf19e2017-09-19 01:28:27 +05301021 'gem-port is from 1024 to 9215')
rshetty1cc73982017-09-02 03:31:12 +05301022 gem_port = GemportsConfigData()
1023 gem_port.CopyFrom(data)
1024 v_enet.gem_ports[data.name] = gem_port
rshettyf4bf19e2017-09-19 01:28:27 +05301025 self.add_pending_flows(v_enet, gem_port.traffic_class)
rshetty1cc73982017-09-02 03:31:12 +05301026 else:
1027 self.log.info('VEnet-is-not-configured-yet.',
1028 gem_port_info=data)
1029
1030 def update_gemport(self, data):
1031 raise NotImplementedError()
1032
1033 def remove_gemport(self, data):
1034 raise NotImplementedError()
1035
rshettyc26a3c32017-07-27 11:06:38 +05301036 def disable(self):
Shad Ansari0d83c942017-07-05 21:30:38 -07001037 super(Asfvolt16Handler, self).disable()
1038
rshettyc26a3c32017-07-27 11:06:38 +05301039 def delete(self):
Shad Ansari0d83c942017-07-05 21:30:38 -07001040 super(Asfvolt16Handler, self).delete()
Shad Ansari1831fcc2017-08-11 16:41:44 -07001041
1042 def handle_packet_in(self, ind_info):
1043 self.log.info('Received Packet-In', ind_info=ind_info)
rshettyf4bf19e2017-09-19 01:28:27 +05301044 logical_port = self.get_logical_port_using_gem_port(ind_info['svc_port'])
Shad Ansari1831fcc2017-08-11 16:41:44 -07001045 pkt = Ether(ind_info['packet'])
rshettyf4bf19e2017-09-19 01:28:27 +05301046 kw = dict(
1047 logical_device_id=self.logical_device_id,
1048 logical_port_no=logical_port,
1049 )
1050 self.log.info('sending-packet-in', **kw)
1051 self.adapter_agent.send_packet_in(packet=str(pkt), **kw)
1052
1053 def packet_out(self, egress_port, msg):
1054 pkt_info = dict()
1055 pkt = Ether(msg)
1056 self.log.info('received-packet-out-from-of-agent',
1057 egress_port=egress_port,
1058 packet=str(pkt).encode("HEX"))
1059
Shad Ansari1831fcc2017-08-11 16:41:44 -07001060 if pkt.haslayer(Dot1Q):
1061 outer_shim = pkt.getlayer(Dot1Q)
1062 if isinstance(outer_shim.payload, Dot1Q):
1063 inner_shim = outer_shim.payload
rshettyf4bf19e2017-09-19 01:28:27 +05301064 payload = (
1065 Ether(src=pkt.src, dst=pkt.dst, type=outer_shim.type) /
1066 outer_shim.payload
Shad Ansari1831fcc2017-08-11 16:41:44 -07001067 )
rshettyf4bf19e2017-09-19 01:28:27 +05301068 else:
1069 payload = pkt
1070 else:
1071 payload = pkt
Shad Ansari1831fcc2017-08-11 16:41:44 -07001072
rshettyf4bf19e2017-09-19 01:28:27 +05301073 self.log.info('sending-packet-to-device',
1074 egress_port=egress_port,
1075 packet=str(payload).encode("HEX"))
1076 send_pkt = binascii.unhexlify(str(payload).encode("HEX"))
Shad Ansari1831fcc2017-08-11 16:41:44 -07001077
rshettyf4bf19e2017-09-19 01:28:27 +05301078 if egress_port == ASFVOLT_NNI_PORT:
1079 port_id = 'nni'
1080 pkt_info['dest_type'] = 'nni'
1081 pkt_info['intf_id'] = 0
1082 else:
1083 port_id = 'uni-{}'.format(egress_port)
1084 logical_port = None
1085 logical_port = \
1086 self.adapter_agent.get_logical_port(self.logical_device_id,
1087 port_id)
1088 if logical_port is None:
1089 self.log.info('Unable-to-find-logical-port-info',
1090 logical_port_number=egress_port)
1091 return
1092 onu_device = None
1093 onu_device = self.adapter_agent.get_device(logical_port.device_id)
1094 if onu_device is None:
1095 self.log.info('Unable-to-find-onu_device-info',
1096 onu_device_id=logical_port.device_id)
1097 return
1098 pkt_info['intf_id'] = onu_device.proxy_address.channel_id
1099 pkt_info['onu_id'] = onu_device.proxy_address.onu_id
1100
1101 pkt_info['dest_type'] = 'onu'
1102 #pkt_info['dest_type'] = 'gem_port'
1103 if pkt_info['dest_type'] == 'gem_port':
1104 pkt_info['gem_port'] = 1024
1105 self.bal.packet_out(send_pkt, pkt_info)
rshetty1cc73982017-09-02 03:31:12 +05301106
1107 def update_flow_table(self, flows):
1108 device = self.adapter_agent.get_device(self.device_id)
1109 self.log.info('bulk-flow-update', device_id=self.device_id)
1110
1111 for flow in flows:
1112 self.log.info('flow-details', device_id=self.device_id, flow=flow)
1113 classifier_info = dict()
1114 action_info = dict()
1115 is_down_stream = None
1116 _in_port = None
1117 try:
1118 _in_port = fd.get_in_port(flow)
1119 assert _in_port is not None
1120 # Right now there is only one NNI port. Get the NNI PORT and compare
1121 # with IN_PUT port number. Need to find better way.
1122 ports = self.adapter_agent.get_ports(device.id, Port.ETHERNET_NNI)
1123
1124 for port in ports:
1125 if (port.port_no == _in_port):
1126 self.log.info('downstream-flow')
1127 is_down_stream = True
1128 break
1129 if is_down_stream is None:
1130 is_down_stream = False
1131 self.log.info('upstream-flow')
1132
1133 _out_port = fd.get_out_port(flow) # may be None
1134 self.log.info('out-port', out_port=_out_port)
1135
1136 for field in fd.get_ofb_fields(flow):
1137
1138 if field.type == fd.ETH_TYPE:
1139 classifier_info['eth_type'] = field.eth_type
1140 self.log.info('field-type-eth-type',
1141 eth_type=classifier_info['eth_type'])
1142
1143 elif field.type == fd.IP_PROTO:
1144 classifier_info['ip_proto'] = field.ip_proto
1145 self.log.info('field-type-ip-proto',
1146 ip_proto=classifier_info['ip_proto'])
1147
1148 elif field.type == fd.IN_PORT:
1149 classifier_info['in_port'] = field.port
1150 self.log.info('field-type-in-port',
1151 in_port=classifier_info['in_port'])
1152
1153 elif field.type == fd.VLAN_VID:
1154 classifier_info['vlan_vid'] = field.vlan_vid & 0xfff
1155 self.log.info('field-type-vlan-vid',
1156 vlan=classifier_info['vlan_vid'])
1157
1158 elif field.type == fd.VLAN_PCP:
1159 classifier_info['vlan_pcp'] = field.vlan_pcp
1160 self.log.info('field-type-vlan-pcp',
1161 pcp=classifier_info['vlan_pcp'])
1162
1163 elif field.type == fd.UDP_DST:
1164 classifier_info['udp_dst'] = field.udp_dst
1165 self.log.info('field-type-udp-dst',
1166 udp_dst=classifier_info['udp_dst'])
1167
1168 elif field.type == fd.UDP_SRC:
1169 classifier_info['udp_src'] = field.udp_src
1170 self.log.info('field-type-udp-src',
1171 udp_src=classifier_info['udp_src'])
1172
1173 elif field.type == fd.IPV4_DST:
1174 classifier_info['ipv4_dst'] = field.ipv4_dst
1175 self.log.info('field-type-ipv4-dst',
1176 ipv4_dst=classifier_info['ipv4_dst'])
1177
1178 elif field.type == fd.IPV4_SRC:
1179 classifier_info['ipv4_src'] = field.ipv4_src
1180 self.log.info('field-type-ipv4-src',
1181 ipv4_dst=classifier_info['ipv4_src'])
1182
1183 elif field.type == fd.METADATA:
1184 classifier_info['metadata'] = field.table_metadata
1185 self.log.info('field-type-metadata',
1186 metadata=classifier_info['metadata'])
1187
1188 else:
1189 raise NotImplementedError('field.type={}'.format(
1190 field.type))
1191
1192 for action in fd.get_actions(flow):
1193
1194 if action.type == fd.OUTPUT:
1195 action_info['output'] = action.output.port
1196 self.log.info('action-type-output',
1197 output=action_info['output'],
1198 in_port=classifier_info['in_port'])
1199
1200 elif action.type == fd.POP_VLAN:
1201 action_info['pop_vlan'] = True
1202 self.log.info('action-type-pop-vlan',
1203 in_port=_in_port)
1204
1205 elif action.type == fd.PUSH_VLAN:
1206 action_info['push_vlan'] = True
1207 action_info['tpid'] = action.push.ethertype
1208 self.log.info('action-type-push-vlan',
1209 push_tpid=action_info['tpid'],
1210 in_port=_in_port)
1211 if action.push.ethertype != 0x8100:
1212 self.log.error('unhandled-tpid',
1213 ethertype=action.push.ethertype)
1214
1215 elif action.type == fd.SET_FIELD:
1216 # action_info['action_type'] = 'set_field'
1217 _field = action.set_field.field.ofb_field
1218 assert (action.set_field.field.oxm_class ==
1219 OFPXMC_OPENFLOW_BASIC)
1220 self.log.info('action-type-set-field',
1221 field=_field, in_port=_in_port)
1222 if _field.type == fd.VLAN_VID:
1223 self.log.info('set-field-type-vlan-vid',
1224 vlan_vid=_field.vlan_vid & 0xfff)
1225 action_info['vlan_vid'] = (_field.vlan_vid & 0xfff)
1226 else:
1227 self.log.error('unsupported-action-set-field-type',
1228 field_type=_field.type)
1229 else:
1230 self.log.error('unsupported-action-type',
1231 action_type=action.type, in_port=_in_port)
1232
1233 if is_down_stream is False:
rshettyf4bf19e2017-09-19 01:28:27 +05301234 found = False
1235 ports = self.adapter_agent.get_ports(self.device_id,
1236 Port.ETHERNET_UNI)
1237 for port in ports:
1238 if port.port_no == classifier_info['in_port']:
1239 found = True
1240 break
1241 if found is True:
1242 v_enet = self.get_venet(name=port.label)
1243 else:
1244 self.log.error('Failed to get v_enet info',
1245 in_port=classifier_info['in_port'])
1246 return
1247 self.divide_and_add_flow(v_enet, classifier_info, action_info)
rshetty1cc73982017-09-02 03:31:12 +05301248 except Exception as e:
1249 self.log.exception('failed-to-install-flow', e=e, flow=flow)
1250
1251 # This function will divide the upstream flow into both
1252 # upstreand and downstream flow, as broadcom devices
1253 # expects down stream flows to be added to handle
1254 # packet_out messge from controller.
rshettyf4bf19e2017-09-19 01:28:27 +05301255 def divide_and_add_flow(self, v_enet, classifier, action):
rshetty1cc73982017-09-02 03:31:12 +05301256 if 'ip_proto' in classifier:
1257 if classifier['ip_proto'] == 17:
1258 self.log.error('Addtion of DHCP flows are defferd')
1259 '''
1260 # DHCP flow from the ONOS doesn't have Ctag and Stags
1261 # information. For now DHCP flow will be added as a
1262 # part of data flows.
1263 # self.add_dhcp_flow(classifier, action, v_enet,
1264 # ASFVOLT_DHCP_UNTAGGED_ID)
1265 '''
1266 elif classifier['ip_proto'] == 2:
1267 self.log.info('Addtion of IGMP flow are not handled yet')
1268 '''
1269 #self.add_igmp_flow(classifier, action, v_enet,
1270 # ASFVOLT_IGMP_UNTAGGED_ID)
1271 '''
1272 else:
1273 self.log.info("Invalid-Classifier-to-handle",
1274 classifier=classifier,
1275 action=action)
1276 elif 'eth_type' in classifier:
1277 if classifier['eth_type'] == 0x888e:
1278 # self.log.error('Addtion of EAPOL flows are defferd')
1279 self.add_eapol_flow(classifier, action,
1280 v_enet, ASFVOLT_EAPOL_ID,
rshettyf4bf19e2017-09-19 01:28:27 +05301281 ASFVOLT_DOWNLINK_EAPOL_ID,
1282 ASFVOLT16_DEFAULT_VLAN)
rshetty1cc73982017-09-02 03:31:12 +05301283 elif 'push_vlan' in action:
rshettyf4bf19e2017-09-19 01:28:27 +05301284
rshetty1cc73982017-09-02 03:31:12 +05301285 self.prepare_and_add_dhcp_flow(classifier, action, v_enet,
1286 ASFVOLT_DHCP_TAGGED_ID,
1287 ASFVOLT_DOWNLINK_DHCP_TAGGED_ID)
rshettyf4bf19e2017-09-19 01:28:27 +05301288
1289 #self.del_flow(v_enet, ASFVOLT_EAPOL_ID, ASFVOLT_DOWNLINK_EAPOL_ID)
1290 self.prepare_and_add_eapol_flow(classifier, action, v_enet,
1291 ASFVOLT_EAPOL_ID_DATA_VLAN,
1292 ASFVOLT_DOWNLINK_EAPOL_ID_DATA_VLAN)
rshetty1cc73982017-09-02 03:31:12 +05301293 self.add_data_flow(classifier, action, v_enet)
1294 else:
1295 self.log.info('Invalid-flow-type-to-handle',
1296 classifier=classifier,
1297 action=action)
1298
rshettyf4bf19e2017-09-19 01:28:27 +05301299
1300 def prepare_and_add_eapol_flow(self, data_classifier, data_action,
1301 v_enet, eapol_id, downlink_eapol_id):
1302 eapol_classifier = dict()
1303 eapol_action = dict()
1304 eapol_classifier['eth_type'] = 0x888e
1305 eapol_classifier['pkt_tag_type'] = 'single_tag'
1306 #eapol_classifier['vlan_vid'] = data_classifier['vlan_vid']
1307
1308 eapol_action['vlan_push'] = True
1309 eapol_action['vlan_vid'] = data_action['vlan_vid']
1310 self.add_eapol_flow(eapol_classifier, eapol_action, v_enet,
1311 eapol_id, downlink_eapol_id, data_classifier['vlan_vid'])
1312
1313
rshetty1cc73982017-09-02 03:31:12 +05301314 def add_eapol_flow(self, uplink_classifier, uplink_action,
rshettyf4bf19e2017-09-19 01:28:27 +05301315 v_enet, uplink_eapol_id, downlink_eapol_id, vlan_id):
rshetty1cc73982017-09-02 03:31:12 +05301316 downlink_classifier = dict(uplink_classifier)
1317 downlink_action = dict(uplink_action)
1318 # To-Do For a time being hard code the traffic class value.
1319 # Need to know how to get the traffic class info from flows.
1320 gem_port = self.get_gem_port_info(v_enet, traffic_class=2)
1321 if gem_port is None:
1322 self.log.info('Failed-to-get-gemport',)
rshettyf4bf19e2017-09-19 01:28:27 +05301323 # To-Do: If Gemport not found, then flow failure indication
1324 # should be sent to controller. For now, not sure how to
1325 # send that to controller. so store the flows in v_enet
1326 # and add it when gem port is created
1327 self.store_flows(uplink_classifier, uplink_action,
1328 v_enet, traffic_class=2)
rshetty1cc73982017-09-02 03:31:12 +05301329 return
1330 v_ont_ani = self.get_v_ont_ani(v_enet.v_enet.data.v_ontani_ref)
1331 if v_ont_ani is None:
1332 self.log.info('Failed-to-get-v_ont_ani',
1333 v_ont_ani=v_enet.v_enet.data.v_ontani_ref)
1334 return
1335 tcont = self.get_tcont_info(v_ont_ani, name=gem_port.tcont_ref)
1336 if tcont is None:
1337 self.log.info('Failed-to-get-tcont-info',
1338 tcont=gem_port.tcont_ref)
1339 return
1340 onu_device = self.adapter_agent.get_child_device(
1341 self.device_id, onu_id=v_ont_ani.v_ont_ani.data.onu_id)
1342 if onu_device is None:
1343 self.log.info('Failed-to-get-onu-device',
1344 onu_id=v_ont_ani.v_ont_ani.data.onu_id)
1345 return
1346
1347 flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
1348 onu_device.proxy_address.channel_id,
1349 uplink_eapol_id)
1350 # Add Upstream EAPOL Flow.
rshettyf4bf19e2017-09-19 01:28:27 +05301351 #uplink_classifier['pkt_tag_type'] = 'untagged'
1352 uplink_classifier['pkt_tag_type'] = 'single_tag'
1353 uplink_classifier['vlan_vid'] = vlan_id
rshetty1cc73982017-09-02 03:31:12 +05301354 uplink_action.clear()
1355 uplink_action['trap_to_host'] = True
1356 try:
1357 is_down_stream = False
1358 self.log.info('Adding-Upstream-EAPOL-flow',
1359 classifier=uplink_classifier,
1360 action=uplink_action, gem_port=gem_port,
1361 flow_id=flow_id,
1362 sched_info=tcont.alloc_id)
1363 self.bal.add_flow(onu_device.proxy_address.onu_id,
1364 onu_device.proxy_address.channel_id,
1365 flow_id, gem_port.gemport_id,
1366 uplink_classifier, is_down_stream,
1367 action_info=uplink_action,
1368 sched_id=tcont.alloc_id)
1369 # To-Do. While addition of one flow is in progress,
1370 # we cannot add an another flow. Right now use sleep
1371 # of 5 sec, assuming that addtion of flow is successful.
rshettyf4bf19e2017-09-19 01:28:27 +05301372 time.sleep(0.1)
rshetty1cc73982017-09-02 03:31:12 +05301373 except Exception as e:
1374 self.log.exception('failed-to-install-Upstream-EAPOL-flow', e=e,
1375 classifier=uplink_classifier,
1376 action=uplink_action,
1377 onu_id=onu_device.proxy_address.onu_id,
1378 intf_id=onu_device.proxy_address.channel_id)
1379
1380 # Add Downstream EAPOL Flow.
1381 downlink_flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
1382 onu_device.proxy_address.channel_id,
1383 downlink_eapol_id)
1384 is_down_stream = True
rshettyf4bf19e2017-09-19 01:28:27 +05301385 #downlink_classifier['pkt_tag_type'] = 'untagged'
1386 downlink_classifier['pkt_tag_type'] = 'single_tag'
1387 downlink_classifier['vlan_vid'] = vlan_id
rshetty1cc73982017-09-02 03:31:12 +05301388 try:
1389 self.log.info('Adding-Downstream-EAPOL-flow',
1390 classifier=downlink_classifier,
1391 action=downlink_action,
1392 gem_port=gem_port,
1393 flow_id=downlink_flow_id,
1394 sched_info=tcont.alloc_id)
1395 self.bal.add_flow(onu_device.proxy_address.onu_id,
1396 onu_device.proxy_address.channel_id,
1397 downlink_flow_id, gem_port.gemport_id,
1398 downlink_classifier, is_down_stream)
1399 # To-Do. While addition of one flow is in progress,
1400 # we cannot add an another flow. Right now use sleep
1401 # of 5 sec, assuming that addtion of flow is successful.
rshettyf4bf19e2017-09-19 01:28:27 +05301402 time.sleep(0.1)
rshetty1cc73982017-09-02 03:31:12 +05301403 except Exception as e:
1404 self.log.exception('failed-to-install-downstream-EAPOL-flow', e=e,
1405 classifier=downlink_classifier,
1406 action=downlink_action,
1407 onu_id=onu_device.proxy_address.onu_id,
1408 intf_id=onu_device.proxy_address.channel_id)
1409
1410 def prepare_and_add_dhcp_flow(self, data_classifier, data_action,
1411 v_enet, dhcp_id, downlink_dhcp_id):
1412 dhcp_classifier = dict()
1413 dhcp_action = dict()
1414 dhcp_classifier['ip_proto'] = 17
1415 dhcp_classifier['udp_src'] = 68
rshettyf4bf19e2017-09-19 01:28:27 +05301416 dhcp_classifier['udp_dst'] = 67
rshetty1cc73982017-09-02 03:31:12 +05301417 dhcp_classifier['pkt_tag_type'] = 'single_tag'
1418 dhcp_classifier['vlan_vid'] = data_classifier['vlan_vid']
1419 dhcp_action['vlan_push'] = True
1420 dhcp_action['vlan_vid'] = data_action['vlan_vid']
1421 self.add_dhcp_flow(dhcp_classifier, dhcp_action, v_enet,
1422 dhcp_id, downlink_dhcp_id)
1423
1424 def add_dhcp_flow(self, uplink_classifier, uplink_action,
1425 v_enet, dhcp_id, downlink_dhcp_id):
1426 downlink_classifier = dict(uplink_classifier)
1427 downlink_action = dict(uplink_action)
1428 # Add Upstream DHCP Flow.
1429 # To-Do For a time being hard code the traffic class value.
1430 # Need to know how to get the traffic class info from flows.
1431 gem_port = self.get_gem_port_info(v_enet, traffic_class=2)
1432 if gem_port is None:
rshettyf4bf19e2017-09-19 01:28:27 +05301433 self.log.info('Failed-to-get-gemport')
1434 self.store_flows(uplink_classifier, uplink_action,
1435 v_enet, traffic_class=2)
rshetty1cc73982017-09-02 03:31:12 +05301436 return
1437 v_ont_ani = self.get_v_ont_ani(v_enet.v_enet.data.v_ontani_ref)
1438 if v_ont_ani is None:
1439 self.log.error('Failed-to-get-v_ont_ani',
1440 v_ont_ani=v_enet.v_enet.data.v_ontani_ref)
1441 return
1442 tcont = self.get_tcont_info(v_ont_ani, name=gem_port.tcont_ref)
1443 if tcont is None:
1444 self.log.error('Failed-to-get-tcont-info',
1445 tcont=gem_port.tcont_ref)
1446 return
1447 onu_device = self.adapter_agent.get_child_device(
1448 self.device_id, onu_id=v_ont_ani.v_ont_ani.data.onu_id)
1449 if onu_device is None:
1450 self.log.error('Failed-to-get-onu-device',
1451 onu_id=v_ont_ani.v_ont_ani.data.onu_id)
1452 return
1453
1454 flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
1455 onu_device.proxy_address.channel_id,
1456 dhcp_id)
1457 uplink_action.clear()
1458 uplink_action['trap_to_host'] = True
1459 try:
1460 is_down_stream = False
1461 self.log.info('Adding-Upstream-DHCP-flow',
1462 classifier=uplink_classifier,
1463 action=uplink_action,
1464 gem_port=gem_port,
1465 flow_id=flow_id,
1466 sched_info=tcont.alloc_id)
1467 self.bal.add_flow(onu_device.proxy_address.onu_id,
1468 onu_device.proxy_address.channel_id,
1469 flow_id, gem_port.gemport_id,
1470 uplink_classifier, is_down_stream,
1471 action_info=uplink_action,
1472 sched_id=tcont.alloc_id)
1473 # To-Do. While addition of one flow is in progress,
1474 # we cannot add an another flow. Right now use sleep
1475 # of 5 sec, assuming that addtion of flow is successful.
rshettyf4bf19e2017-09-19 01:28:27 +05301476 time.sleep(0.1)
rshetty1cc73982017-09-02 03:31:12 +05301477
1478 except Exception as e:
1479 self.log.exception('failed-to-install-dhcp-upstream-flow', e=e,
1480 classifier=uplink_classifier,
1481 action=uplink_action,
1482 onu_id=onu_device.proxy_address.onu_id,
1483 intf_id=onu_device.proxy_address.channel_id)
1484
1485 is_down_stream = True
1486 downlink_classifier['udp_src'] = 67
1487 downlink_classifier['udp_dst'] = 68
1488
1489 if dhcp_id == ASFVOLT_DHCP_TAGGED_ID:
1490 downlink_classifier['pkt_tag_type'] = 'double_tag'
rshettyf4bf19e2017-09-19 01:28:27 +05301491 # Copy O_OVID
rshetty1cc73982017-09-02 03:31:12 +05301492 downlink_classifier['vlan_vid'] = downlink_action['vlan_vid']
rshettyf4bf19e2017-09-19 01:28:27 +05301493 # Copy I_OVID
1494 #downlink_classifier['metadata'] = uplink_classifier['vlan_vid']
rshetty1cc73982017-09-02 03:31:12 +05301495 if 'push_vlan' in downlink_classifier:
1496 downlink_action.pop('push_vlan')
1497 downlink_action['pop_vlan'] = True
rshettyf4bf19e2017-09-19 01:28:27 +05301498 else:
1499 downlink_classifier['pkt_tag_type'] = 'untagged'
1500 downlink_classifier.pop('vlan_vid')
1501
rshetty1cc73982017-09-02 03:31:12 +05301502
1503 downlink_flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
1504 onu_device.proxy_address.channel_id,
1505 downlink_dhcp_id)
1506
1507 try:
1508 self.log.info('Adding-Downstream-DHCP-flow',
1509 classifier=downlink_classifier,
1510 action=downlink_action, gem_port=gem_port,
1511 flow_id=downlink_flow_id,
1512 sched_info=tcont.alloc_id)
1513 self.bal.add_flow(onu_device.proxy_address.onu_id,
1514 onu_device.proxy_address.channel_id,
1515 downlink_flow_id, gem_port.gemport_id,
1516 downlink_classifier, is_down_stream,
1517 action_info=downlink_action)
1518 # To-Do. While addition of one flow is in progress,
1519 # we cannot add an another flow. Right now use sleep
1520 # of 5 sec, assuming that addtion of flow is successful.
rshettyf4bf19e2017-09-19 01:28:27 +05301521 time.sleep(0.1)
rshetty1cc73982017-09-02 03:31:12 +05301522 except Exception as e:
1523 self.log.exception('failed-to-install-dhcp-downstream-flow', e=e,
1524 classifier=downlink_classifier,
1525 action=downlink_action,
1526 onu_id=onu_device.proxy_address.onu_id,
1527 intf_id=onu_device.proxy_address.channel_id)
1528
1529 def add_igmp_flow(self, classifier, action, v_enet, igmp_id):
1530 self.log.info('Not-Implemented-Yet')
1531 return
1532
1533 def add_data_flow(self, uplink_classifier, uplink_action, v_enet):
1534
1535 downlink_classifier = dict(uplink_classifier)
1536 downlink_action = dict(uplink_action)
1537
1538 uplink_classifier['pkt_tag_type'] = 'single_tag'
1539
1540 downlink_classifier['pkt_tag_type'] = 'double_tag'
1541 downlink_classifier['vlan_vid'] = uplink_action['vlan_vid']
rshettyf4bf19e2017-09-19 01:28:27 +05301542 downlink_classifier['metadata'] = uplink_classifier['vlan_vid']
rshetty1cc73982017-09-02 03:31:12 +05301543 del downlink_action['push_vlan']
1544 downlink_action['pop_vlan'] = True
1545
rshettyf4bf19e2017-09-19 01:28:27 +05301546 # To-Do right now only one GEM port is supported, so below method
1547 # will take care of handling all the p bits.
1548 # We need to revisit when mulitple gem port per bits is needed.
rshetty1cc73982017-09-02 03:31:12 +05301549 self.add_hsia_flow(uplink_classifier, uplink_action,
rshetty1cc73982017-09-02 03:31:12 +05301550 downlink_classifier, downlink_action,
rshettyf4bf19e2017-09-19 01:28:27 +05301551 v_enet, ASFVOLT_HSIA_ID, ASFVOLT_DOWNLINK_HSIA_ID)
rshetty1cc73982017-09-02 03:31:12 +05301552
1553 def add_hsia_flow(self, uplink_classifier, uplink_action,
rshettyf4bf19e2017-09-19 01:28:27 +05301554 downlink_classifier, downlink_action,
1555 v_enet, hsia_id, downlink_hsia_id):
rshetty1cc73982017-09-02 03:31:12 +05301556 # Add Upstream Firmware Flow.
1557 # To-Do For a time being hard code the traffic class value.
1558 # Need to know how to get the traffic class info from flows.
1559 gem_port = self.get_gem_port_info(v_enet, traffic_class=2)
1560 if gem_port is None:
1561 self.log.info('Failed-to-get-gemport')
rshettyf4bf19e2017-09-19 01:28:27 +05301562 self.store_flows(uplink_classifier, uplink_action,
1563 v_enet, traffic_class=2)
rshetty1cc73982017-09-02 03:31:12 +05301564 return
1565 v_ont_ani = self.get_v_ont_ani(v_enet.v_enet.data.v_ontani_ref)
1566 if v_ont_ani is None:
1567 self.log.info('Failed-to-get-v_ont_ani',
1568 v_ont_ani=v_enet.v_enet.data.v_ontani_ref)
1569 return
1570 tcont = self.get_tcont_info(v_ont_ani, name=gem_port.tcont_ref)
1571 if tcont is None:
1572 self.log.info('Failed-to-get-tcont-info',
1573 tcont=gem_port.tcont_ref)
1574 return
1575 onu_device = self.adapter_agent.get_child_device(
1576 self.device_id, onu_id=v_ont_ani.v_ont_ani.data.onu_id)
1577 if onu_device is None:
1578 self.log.info('Failed-to-get-onu-device',
1579 onu_id=v_ont_ani.v_ont_ani.data.onu_id)
1580 return
1581
1582 flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
1583 onu_device.proxy_address.channel_id,
1584 hsia_id)
1585 try:
1586 is_down_stream = False
rshettyf4bf19e2017-09-19 01:28:27 +05301587 self.log.info('Adding-ARP-upstream-flow',
rshetty1cc73982017-09-02 03:31:12 +05301588 classifier=uplink_classifier,
1589 action=uplink_action,
1590 gem_port=gem_port,
1591 flow_id=flow_id,
1592 sched_info=tcont.alloc_id)
1593 self.bal.add_flow(onu_device.proxy_address.onu_id,
1594 onu_device.proxy_address.channel_id,
1595 flow_id, gem_port.gemport_id,
1596 uplink_classifier, is_down_stream,
1597 action_info=uplink_action,
1598 sched_id=tcont.alloc_id)
1599 # To-Do. While addition of one flow is in progress,
1600 # we cannot add an another flow. Right now use sleep
1601 # of 5 sec, assuming that addtion of flow is successful.
rshettyf4bf19e2017-09-19 01:28:27 +05301602 time.sleep(0.1)
rshetty1cc73982017-09-02 03:31:12 +05301603 except Exception as e:
rshettyf4bf19e2017-09-19 01:28:27 +05301604 self.log.exception('failed-to-install-ARP-upstream-flow', e=e,
rshetty1cc73982017-09-02 03:31:12 +05301605 classifier=uplink_classifier,
1606 action=uplink_action,
1607 onu_id=onu_device.proxy_address.onu_id,
1608 intf_id=onu_device.proxy_address.channel_id)
1609 is_down_stream = True
1610 # To-Do: For Now hard code the p-bit values.
rshettyf4bf19e2017-09-19 01:28:27 +05301611 #downlink_classifier['vlan_pcp'] = 7
rshetty1cc73982017-09-02 03:31:12 +05301612 downlink_flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
1613 onu_device.proxy_address.channel_id,
rshettyf4bf19e2017-09-19 01:28:27 +05301614 hsia_id)
1615 #downlink_hsia_id)
rshetty1cc73982017-09-02 03:31:12 +05301616 try:
rshettyf4bf19e2017-09-19 01:28:27 +05301617 self.log.info('Adding-ARP-downstream-flow',
rshetty1cc73982017-09-02 03:31:12 +05301618 classifier=downlink_classifier,
1619 action=downlink_action,
1620 gem_port=gem_port,
1621 flow_id=downlink_flow_id)
1622 self.bal.add_flow(onu_device.proxy_address.onu_id,
1623 onu_device.proxy_address.channel_id,
1624 downlink_flow_id, gem_port.gemport_id,
1625 downlink_classifier, is_down_stream,
1626 action_info=downlink_action)
1627 # To-Do. While addition of one flow is in progress,
1628 # we cannot add an another flow. Right now use sleep
1629 # of 5 sec, assuming that addtion of flow is successful.
rshettyf4bf19e2017-09-19 01:28:27 +05301630 time.sleep(0.1)
rshetty1cc73982017-09-02 03:31:12 +05301631 except Exception as e:
rshettyf4bf19e2017-09-19 01:28:27 +05301632 self.log.exception('failed-to-install-ARP-downstream-flow', e=e,
rshetty1cc73982017-09-02 03:31:12 +05301633 classifier=downlink_classifier,
1634 action=downlink_action,
1635 onu_id=onu_device.proxy_address.onu_id,
1636 intf_id=onu_device.proxy_address.channel_id)
rshettyf4bf19e2017-09-19 01:28:27 +05301637
1638
1639 def del_flow(self, v_enet, uplink_id, downlink_id):
1640 # To-Do For a time being hard code the traffic class value.
1641 # Need to know how to get the traffic class info from flows.
1642 v_ont_ani = self.get_v_ont_ani(v_enet.v_enet.data.v_ontani_ref)
1643 if v_ont_ani is None:
1644 self.log.info('Failed-to-get-v_ont_ani',
1645 v_ont_ani=v_enet.v_enet.data.v_ontani_ref)
1646 return
1647 onu_device = self.adapter_agent.get_child_device(
1648 self.device_id, onu_id=v_ont_ani.v_ont_ani.data.onu_id)
1649 if onu_device is None:
1650 self.log.info('Failed-to-get-onu-device',
1651 onu_id=v_ont_ani.v_ont_ani.data.onu_id)
1652 return
1653
1654 flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
1655 onu_device.proxy_address.channel_id,
1656 uplink_id)
1657 try:
1658 is_down_stream = False
1659 self.log.info('deleting-Upstream-EAPOL-flow',
1660 flow_id=flow_id)
1661 self.bal.delete_flow(onu_device.proxy_address.onu_id,
1662 onu_device.proxy_address.channel_id,
1663 flow_id, is_down_stream)
1664 # To-Do. While deletion of one flow is in progress,
1665 # we cannot delete an another flow. Right now use sleep
1666 # of 5 sec, assuming that deletion of flow is successful.
1667 time.sleep(0.1)
1668 except Exception as e:
1669 self.log.exception('failed-to-delete-Upstream-EAPOL-flow', e=e,
1670 flow_id=flow_id,
1671 onu_id=onu_device.proxy_address.onu_id,
1672 intf_id=onu_device.proxy_address.channel_id)
1673
1674 downlink_flow_id = self.get_flow_id(onu_device.proxy_address.onu_id,
1675 onu_device.proxy_address.channel_id,
1676 downlink_id)
1677 is_down_stream = True
1678 try:
1679 self.log.info('Deleting-Downstream-EAPOL-flow',
1680 flow_id=downlink_flow_id)
1681
1682 self.bal.delete_flow(onu_device.proxy_address.onu_id,
1683 onu_device.proxy_address.channel_id,
1684 downlink_flow_id, is_down_stream)
1685 # To-Do. While deletion of one flow is in progress,
1686 # we cannot delete an another flow. Right now use sleep
1687 # of 5 sec, assuming that deletion of flow is successful.
1688 time.sleep(0.1)
1689 except Exception as e:
1690 self.log.exception('failed-to-install-downstream-EAPOL-flow', e=e,
1691 flow_id=flow_id,
1692 onu_id=onu_device.proxy_address.onu_id,
1693 intf_id=onu_device.proxy_address.channel_id)