Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 1 | # |
| 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 | """ |
| 18 | Asfvolt16 OLT adapter |
| 19 | """ |
| 20 | |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 21 | import arrow |
| 22 | from twisted.internet.defer import inlineCallbacks |
| 23 | from voltha.protos.events_pb2 import KpiEvent, MetricValuePairs |
| 24 | from voltha.protos.events_pb2 import KpiEventType |
| 25 | from voltha.protos.device_pb2 import PmConfigs, PmConfig,PmGroupConfig |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 26 | from voltha.adapters.asfvolt16_olt.protos import bal_errno_pb2, bal_pb2 |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 27 | from voltha.protos.events_pb2 import AlarmEvent, AlarmEventType, \ |
| 28 | AlarmEventSeverity, AlarmEventState, AlarmEventCategory |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 29 | from scapy.layers.l2 import Ether, Dot1Q |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 30 | from uuid import uuid4 |
Shad Ansari | da0f3a4 | 2017-07-19 09:51:06 -0700 | [diff] [blame] | 31 | from common.frameio.frameio import BpfProgramFilter |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 32 | from twisted.internet import reactor |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 33 | from common.frameio.frameio import hexify |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 34 | from scapy.packet import Packet |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 35 | import voltha.core.flow_decomposer as fd |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 36 | from voltha.protos.common_pb2 import OperStatus, ConnectStatus |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 37 | from voltha.protos.device_pb2 import Port |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 38 | from voltha.protos.common_pb2 import AdminState |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 39 | from voltha.protos.logical_device_pb2 import LogicalPort, LogicalDevice |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 40 | from voltha.protos.openflow_13_pb2 import OFPPS_LIVE, OFPPF_FIBER, OFPPS_LINK_DOWN, \ |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 41 | OFPPF_1GB_FD, OFPC_GROUP_STATS, OFPC_PORT_STATS, OFPC_TABLE_STATS, \ |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 42 | OFPC_FLOW_STATS, ofp_switch_features, ofp_desc, ofp_port, \ |
| 43 | OFPXMC_OPENFLOW_BASIC |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 44 | from voltha.core.logical_device_agent import mac_str_to_tuple |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 45 | from voltha.adapters.asfvolt16_olt.bal import Bal |
| 46 | from voltha.adapters.device_handler import OltDeviceHandler |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 47 | from voltha.protos.bbf_fiber_base_pb2 import \ |
| 48 | ChannelgroupConfig, ChannelpartitionConfig, ChannelpairConfig, \ |
| 49 | ChannelterminationConfig, OntaniConfig, VOntaniConfig, VEnetConfig |
| 50 | from voltha.protos.bbf_fiber_traffic_descriptor_profile_body_pb2 import \ |
| 51 | TrafficDescriptorProfileData |
| 52 | from voltha.protos.bbf_fiber_tcont_body_pb2 import TcontsConfigData |
| 53 | from voltha.protos.bbf_fiber_gemport_body_pb2 import GemportsConfigData |
| 54 | from voltha.protos.bbf_fiber_multicast_gemport_body_pb2 import \ |
| 55 | MulticastGemportsConfigData |
| 56 | from voltha.protos.bbf_fiber_multicast_distribution_set_body_pb2 import \ |
| 57 | MulticastDistributionSetData |
| 58 | import time |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 59 | import binascii |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 60 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 61 | ASFVOLT_NNI_PORT = 129 |
Suhas Rao | eba61c2 | 2017-08-10 11:42:32 -0700 | [diff] [blame] | 62 | # ASFVOLT_NNI_PORT needs to be other than pon port value. |
| 63 | # Edgecore OLT assigns PONport between 0 to 15, hence |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 64 | # having a value 129 for NNI port to avoid collision. |
Shad Ansari | da0f3a4 | 2017-07-19 09:51:06 -0700 | [diff] [blame] | 65 | # TODO: VLAN ID needs to come from some sort of configuration. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 66 | ASFVOLT16_DEFAULT_VLAN = 4091 |
Shad Ansari | da0f3a4 | 2017-07-19 09:51:06 -0700 | [diff] [blame] | 67 | PACKET_IN_VLAN = 4091 |
| 68 | is_inband_frame = BpfProgramFilter('(ether[14:2] & 0xfff) = 0x{:03x}'.format( |
| 69 | PACKET_IN_VLAN)) |
| 70 | |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 71 | ASFVOLT_EAPOL_ID = 1 |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 72 | ASFVOLT_DOWNLINK_EAPOL_ID = 2 |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 73 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 74 | ASFVOLT_EAPOL_ID_DATA_VLAN = 3 |
| 75 | ASFVOLT_DOWNLINK_EAPOL_ID_DATA_VLAN = 4 |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 76 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 77 | ASFVOLT_DHCP_TAGGED_ID = 5 |
| 78 | ASFVOLT_DOWNLINK_DHCP_TAGGED_ID = 6 |
| 79 | |
| 80 | ASFVOLT_IGMP_TAGGED_ID = 7 |
| 81 | ASFVOLT_DOWNLINK_IGMP_TAGGED_ID = 8 |
| 82 | |
| 83 | ASFVOLT_FIRMWARE_ID = 9 |
| 84 | ASFVOLT_DOWNLINK_FIRMWARE_ID = 10 |
| 85 | |
| 86 | ASFVOLT_ARP_ID = 11 |
| 87 | ASFVOLT_DOWNLINK_ARP_ID = 12 |
| 88 | |
| 89 | ASFVOLT_HSIA_ID = 13 |
| 90 | ASFVOLT_DOWNLINK_HSIA_ID = 14 |
| 91 | |
| 92 | ASFVOLT_DNS_ID = 15 |
| 93 | ASFVOLT_DOWNLINK_DNS_ID = 16 |
| 94 | |
| 95 | |
| 96 | class FlowInfo(object): |
| 97 | |
| 98 | def __init__(self): |
| 99 | self.classifier = dict() |
| 100 | self.action = dict() |
| 101 | self.traffic_class = None |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 102 | |
| 103 | class VEnetHandler(object): |
| 104 | |
| 105 | def __init__(self): |
| 106 | self.v_enet = VEnetConfig() |
| 107 | self.gem_ports = dict() |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 108 | self.pending_flows = [] |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 109 | |
| 110 | class VOntAniHandler(object): |
| 111 | |
| 112 | def __init__(self): |
| 113 | self.v_ont_ani = VOntaniConfig() |
| 114 | self.tconts = dict() |
| 115 | |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 116 | class 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 Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 132 | # To collect pm metrices for each 'pm_default_freq/10' secs |
| 133 | self.pm_default_freq = 20 |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 134 | 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 Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 147 | if self.pm_default_freq != pm_config.default_freq: |
| 148 | self.pm_default_freq = pm_config.default_freq |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 149 | |
| 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 Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 160 | default_freq=self.pm_default_freq, |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 161 | grouped = False, |
| 162 | freq_override = False) |
| 163 | return pm_config |
Shad Ansari | da0f3a4 | 2017-07-19 09:51:06 -0700 | [diff] [blame] | 164 | |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 165 | class Asfvolt16Handler(OltDeviceHandler): |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 166 | |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 167 | def __init__(self, adapter, device_id): |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 168 | super(Asfvolt16Handler, self).__init__(adapter, device_id) |
Shad Ansari | da0f3a4 | 2017-07-19 09:51:06 -0700 | [diff] [blame] | 169 | self.filter = is_inband_frame |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 170 | self.bal = Bal(self, self.log) |
Shad Ansari | da0f3a4 | 2017-07-19 09:51:06 -0700 | [diff] [blame] | 171 | self.host_and_port = None |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 172 | self.olt_id = 0 |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 173 | 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 Rao | 37ddfc9 | 2017-09-13 16:56:18 +0530 | [diff] [blame] | 181 | self.adapter_name = adapter.name |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 182 | self.uni_port_num = 20 |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 183 | self.pm_metrics = None |
| 184 | self.heartbeat_count = 0 |
| 185 | self.heartbeat_miss = 0 |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 186 | # 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 Ansari | da0f3a4 | 2017-07-19 09:51:06 -0700 | [diff] [blame] | 191 | |
| 192 | def __del__(self): |
| 193 | super(Asfvolt16Handler, self).__del__() |
| 194 | |
| 195 | def __str__(self): |
| 196 | return "Asfvolt16Handler: {}".format(self.host_and_port) |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 197 | |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 198 | def _get_next_uni_port(self): |
| 199 | self.uni_port_num += 1 |
| 200 | return self.uni_port_num |
| 201 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 202 | def get_venet(self, **kwargs): |
| 203 | name = kwargs.pop('name', None) |
| 204 | gem_port_id = kwargs.pop('gem_port_id', None) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 205 | for key, v_enet in self.v_enets.items(): |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 206 | 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 |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 213 | 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 257 | 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 |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 308 | |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 309 | def activate(self, device): |
Shad Ansari | da0f3a4 | 2017-07-19 09:51:06 -0700 | [diff] [blame] | 310 | |
| 311 | self.log.info('activating-asfvolt16-olt', device=device) |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 312 | |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 313 | 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 Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 318 | |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 319 | self.bal.connect_olt(device.host_and_port, self.device_id) |
| 320 | |
| 321 | if self.logical_device_id is None: |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 322 | |
| 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 Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 328 | self.adapter_agent.update_device(device) |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 329 | |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 330 | self.add_port(port_no=ASFVOLT_NNI_PORT, |
| 331 | port_type=Port.ETHERNET_NNI, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 332 | label='NNI facing Ethernet port') |
| 333 | self.logical_device_id = \ |
| 334 | self.add_logical_device(device_id=device.id) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 335 | self.add_logical_port(port_no=ASFVOLT_NNI_PORT, |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 336 | port_type=Port.ETHERNET_NNI, |
| 337 | device_id=device.id, |
| 338 | logical_device_id=self.logical_device_id) |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 339 | |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 340 | self.bal.activate_olt() |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 341 | |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 342 | device = self.adapter_agent.get_device(device.id) |
| 343 | device.parent_id = self.logical_device_id |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 344 | device.connect_status = ConnectStatus.REACHABLE |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 345 | device.oper_status = OperStatus.ACTIVATING |
| 346 | self.adapter_agent.update_device(device) |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 347 | |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 348 | @inlineCallbacks |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 349 | def heartbeat(self, device, state = 'run'): |
| 350 | self.log.debug('olt-heartbeat', device=device, state=state, |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 351 | count=self.heartbeat_count) |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 352 | self.is_heartbeat_started = 1 |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 353 | |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 354 | def heartbeat_alarm(device, status, heartbeat_misses=0): |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 355 | 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 Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 361 | id='voltha.{}.{}.olt'.format(self.adapter.name, device), |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 362 | 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 Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 368 | description='OLT Alarm - Connection to OLT - {}'.format('Lost' |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 369 | if status |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 370 | else 'Regained'), |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 371 | context=alarm_data, |
| 372 | raised_ts = ts) |
| 373 | |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 374 | self.adapter_agent.submit_alarm(device, alarm_event) |
| 375 | self.log.debug('olt-heartbeat alarm sent') |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 376 | |
| 377 | except Exception as e: |
| 378 | self.log.exception('failed-to-submit-alarm', e=e) |
| 379 | |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 380 | try: |
| 381 | d = yield self.bal.get_bal_heartbeat(self.device_id.__str__()) |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 382 | except Exception as e: |
| 383 | d = None |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 384 | |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 385 | _device = device |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 386 | |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 387 | if d == None: |
| 388 | # something is not right - OLT is not Reachable |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 389 | 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 Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 395 | 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 Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 421 | |
| 422 | if (self.heartbeat_miss >= self.heartbeat_failed_limit) and \ |
| 423 | (_device.connect_status == ConnectStatus.REACHABLE): |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 424 | self.log.info('olt-heartbeat-failed', count=self.heartbeat_miss) |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 425 | _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 Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 429 | heartbeat_alarm(device, 1, self.heartbeat_miss) |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 430 | |
| 431 | self.heartbeat_count += 1 |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 432 | reactor.callLater(self.heartbeat_interval, self.heartbeat, device) |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 433 | |
| 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 Rao | 37ddfc9 | 2017-09-13 16:56:18 +0530 | [diff] [blame] | 446 | kpi_status = -1 |
Rajeswara Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 447 | 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 Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 456 | |
| 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 Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 491 | reactor.callLater(self.pm_metrics.pm_default_freq/10, |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 492 | 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 Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 499 | def handle_alarms(self, _device_id, _object, key, alarm, |
| 500 | status, priority, |
| 501 | alarm_data=None): |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 502 | 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 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 510 | id = 'voltha.{}.{}.{}'.format(self.adapter.name, |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 511 | _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 Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 559 | self.handle_alarms(device_id,"pon_ni",\ |
| 560 | Iface_ID,\ |
| 561 | "loss_of_signal",los_status,"high",\ |
| 562 | IfaceLos_data) |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 563 | |
Rajeswara Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 564 | def BalSubsTermDgiAlarm(self, device_id, intf_id,\ |
| 565 | onu_id, dgi_status, balSubTermDgi_data,\ |
| 566 | ind_info): |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 567 | self.log.info('Subscriber terminal dying gasp') |
Rajeswara Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 568 | 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 Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 584 | |
| 585 | def BalSubsTermLosAlarm(self, device_id, Iface_ID, |
| 586 | los_status, SubTermAlarm_Data): |
| 587 | self.log.info('ONU Alarms for Subscriber Terminal LOS') |
Rajeswara Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 588 | self.handle_alarms(device_id,"onu",\ |
| 589 | Iface_ID,\ |
| 590 | "ONU : Loss Of Signal",\ |
| 591 | los_status, "medium",\ |
| 592 | SubTermAlarm_Data) |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 593 | |
| 594 | def BalSubsTermLobAlarm(self, device_id, Iface_ID, |
| 595 | lob_status, SubTermAlarm_Data): |
| 596 | self.log.info('ONU Alarms for Subscriber Terminal LOB') |
Rajeswara Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 597 | self.handle_alarms(device_id,"onu",\ |
| 598 | Iface_ID,\ |
| 599 | "ONU : Loss Of Burst",\ |
| 600 | lob_status, "medium",\ |
| 601 | SubTermAlarm_Data) |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 602 | |
| 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 Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 606 | 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 Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 611 | |
| 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 Rao | 2eb42bf | 2017-10-10 14:30:10 +0530 | [diff] [blame] | 615 | 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 Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 620 | |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 621 | def add_port(self, port_no, port_type, label): |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 622 | self.log.info('adding-port', port_no=port_no, port_type=port_type) |
| 623 | if port_type is Port.ETHERNET_NNI: |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 624 | oper_status = OperStatus.ACTIVE |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 625 | elif port_type is Port.PON_OLT: |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 626 | # To-Do The pon port status should be ACTIVATING. |
| 627 | # For now make the status as Active. |
| 628 | oper_status = OperStatus.ACTIVE |
| 629 | else: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 630 | self.log.error('invalid-port-type', port_type=port_type) |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 631 | return |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 632 | |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 633 | port = Port( |
| 634 | port_no=port_no, |
| 635 | label=label, |
| 636 | type=port_type, |
| 637 | admin_state=AdminState.ENABLED, |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 638 | oper_status=oper_status |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 639 | ) |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 640 | self.adapter_agent.add_port(self.device_id, port) |
Shad Ansari | b32e31c | 2017-06-28 01:55:50 -0700 | [diff] [blame] | 641 | |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 642 | 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', |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 651 | #serial_num=uuid4().hex, |
| 652 | serial_num=self.host_and_port, |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 653 | 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 Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 659 | OFPC_FLOW_STATS | |
| 660 | OFPC_TABLE_STATS | |
| 661 | OFPC_PORT_STATS | |
| 662 | OFPC_GROUP_STATS |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 663 | ) |
| 664 | ), |
| 665 | root_device_id=device_id |
| 666 | ) |
| 667 | ld_initialized = self.adapter_agent.create_logical_device(ld) |
| 668 | return ld_initialized.id |
| 669 | |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 670 | 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 Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 674 | if port_type is Port.ETHERNET_NNI: |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 675 | label = 'nni' |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 676 | cap = OFPPF_1GB_FD | OFPPF_FIBER |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 677 | curr_speed = OFPPF_1GB_FD |
| 678 | max_speed = OFPPF_1GB_FD |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 679 | else: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 680 | self.log.error('invalid-port-type', port_type=port_type) |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 681 | return |
| 682 | |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 683 | ofp = ofp_port( |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 684 | port_no=port_no, # is 0 OK? |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 685 | hw_addr=mac_str_to_tuple('00:00:00:00:00:%02x' % 129), |
| 686 | name=label, |
| 687 | config=0, |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 688 | #state=OFPPS_LIVE, |
| 689 | state=OFPPS_LINK_DOWN, |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 690 | 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 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 706 | 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 | |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 721 | def handle_access_term_ind(self, ind_info): |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 722 | device = self.adapter_agent.get_device(self.device_id) |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 723 | if ind_info['activation_successful'] is True: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 724 | self.log.info('successful-access-terminal-Indication', |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 725 | olt_id=self.olt_id) |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 726 | device.connect_status = ConnectStatus.REACHABLE |
| 727 | device.oper_status = OperStatus.ACTIVE |
| 728 | device.reason = 'OLT activated successfully' |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 729 | self.adapter_agent.update_device(device) |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 730 | self.update_logical_port(ASFVOLT_NNI_PORT, Port.ETHERNET_NNI, |
| 731 | OFPPS_LIVE) |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 732 | self.log.info('OLT activation complete') |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 733 | |
| 734 | #heart beat - To health checkup of OLT |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 735 | if self.is_heartbeat_started == 0: |
| 736 | self.log.info('Heart beat is not yet started..starting now') |
| 737 | self.heartbeat(device) |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 738 | |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 739 | 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 Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 743 | |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 744 | # Apply the PM configuration |
| 745 | self.update_pm_config(device, pm_config) |
Rajeswara Rao | b2b369a | 2017-09-08 11:44:15 +0530 | [diff] [blame] | 746 | |
Rajeswara Rao | a78ddcd | 2017-10-10 18:13:27 +0530 | [diff] [blame] | 747 | # Request PM counters from OLT device. |
| 748 | self._handle_pm_counter_req_towards_device(device) |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 749 | else: |
| 750 | device.oper_status = OperStatus.FAILED |
| 751 | device.reason = 'Failed to Intialize OLT' |
| 752 | self.adapter_agent.update_device(device) |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 753 | reactor.callLater(15, self.activate, device) |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 754 | return |
| 755 | |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 756 | def handle_not_started_onu(self, child_device, ind_info): |
| 757 | if ind_info['_sub_group_type'] == 'onu_discovery': |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 758 | self.log.info('Onu-discovered', olt_id=self.olt_id, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 759 | pon_ni=ind_info['_pon_id'], onu_data=ind_info) |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 760 | # To-Do: Need to handle the ONUs, where the admin state is |
| 761 | # ENABLED and operation state is in Failed or Unkown |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 762 | self.log.info('Not-Yet-handled', olt_id=self.olt_id, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 763 | pon_ni=ind_info['_pon_id'], onu_data=ind_info) |
| 764 | else: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 765 | self.log.info('Invalid-ONU-event', olt_id=self.olt_id, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 766 | 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'] |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 770 | self.log.info('Not-handled-Yet', olt_id=self.olt_id, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 771 | 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'] |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 775 | self.log.info('Not-handled-Yet', olt_id=self.olt_id, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 776 | 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': |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 781 | self.log.info('Activation-is-in-progress', olt_id=self.olt_id, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 782 | 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': |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 786 | self.log.info('ONU-activation-is-completed', olt_id=self.olt_id, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 787 | 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) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 795 | 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) |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 812 | else: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 813 | self.log.info('Invalid-ONU-event', olt_id=self.olt_id, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 814 | 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: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 830 | self.log.info('Onu-is-not-configured', olt_id=self.olt_id, |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 831 | 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 Rao | c926fc1 | 2017-07-28 11:17:49 +0530 | [diff] [blame] | 837 | |
| 838 | def send_proxied_message(self, proxy_address, msg): |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 839 | if isinstance(msg, Packet): |
| 840 | msg = str(msg) |
Suhas Rao | c926fc1 | 2017-07-28 11:17:49 +0530 | [diff] [blame] | 841 | try: |
| 842 | self.bal.send_omci_request_message(proxy_address, msg) |
| 843 | except Exception as e: |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 844 | self.log.exception('', exc=str(e)) |
| 845 | return |
rshetty | e4bd2ed | 2017-07-19 16:38:11 +0530 | [diff] [blame] | 846 | |
Suhas Rao | eba61c2 | 2017-08-10 11:42:32 -0700 | [diff] [blame] | 847 | def handle_omci_ind(self, ind_info): |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 848 | child_device = self.adapter_agent.get_child_device( |
| 849 | self.device_id, |
| 850 | onu_id=ind_info['onu_id']) |
Suhas Rao | eba61c2 | 2017-08-10 11:42:32 -0700 | [diff] [blame] | 851 | if child_device is None: |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 852 | self.log.info('Onu is not configured', onu_id=ind_info['onu_id']) |
Suhas Rao | eba61c2 | 2017-08-10 11:42:32 -0700 | [diff] [blame] | 853 | return |
| 854 | try: |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 855 | self.adapter_agent.receive_proxied_message( |
| 856 | child_device.proxy_address, |
| 857 | ind_info['packet']) |
Suhas Rao | eba61c2 | 2017-08-10 11:42:32 -0700 | [diff] [blame] | 858 | except Exception as e: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 859 | self.log.exception('', exc=str(e)) |
Suhas Rao | eba61c2 | 2017-08-10 11:42:32 -0700 | [diff] [blame] | 860 | return |
| 861 | |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 862 | 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 | |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 886 | def create_interface(self, data): |
| 887 | try: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 888 | 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 |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 913 | if isinstance(data, ChannelterminationConfig): |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 914 | self.log.info('Activating-PON-port-at-OLT', |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 915 | 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) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 920 | if data.name in self.channel_terminations: |
| 921 | self.log.info('Channel-termination-already-present', |
| 922 | channel_termination=data) |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 923 | else: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 924 | 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 |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 961 | except Exception as e: |
| 962 | self.log.exception('', exc=str(e)) |
| 963 | return |
| 964 | |
| 965 | def update_interface(self, data): |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 966 | self.log.info('Not-Implemented-yet') |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 967 | return |
| 968 | |
| 969 | def remove_interface(self, data): |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 970 | self.log.info('Not-Implemented-yet') |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 971 | return |
| 972 | |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 973 | 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) |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1019 | if data.gemport_id > 9215: |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1020 | raise Exception('supported range for ' |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1021 | 'gem-port is from 1024 to 9215') |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1022 | gem_port = GemportsConfigData() |
| 1023 | gem_port.CopyFrom(data) |
| 1024 | v_enet.gem_ports[data.name] = gem_port |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1025 | self.add_pending_flows(v_enet, gem_port.traffic_class) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1026 | 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 | |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 1036 | def disable(self): |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 1037 | super(Asfvolt16Handler, self).disable() |
| 1038 | |
rshetty | c26a3c3 | 2017-07-27 11:06:38 +0530 | [diff] [blame] | 1039 | def delete(self): |
Shad Ansari | 0d83c94 | 2017-07-05 21:30:38 -0700 | [diff] [blame] | 1040 | super(Asfvolt16Handler, self).delete() |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 1041 | |
| 1042 | def handle_packet_in(self, ind_info): |
| 1043 | self.log.info('Received Packet-In', ind_info=ind_info) |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1044 | logical_port = self.get_logical_port_using_gem_port(ind_info['svc_port']) |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 1045 | pkt = Ether(ind_info['packet']) |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1046 | 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 Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 1060 | if pkt.haslayer(Dot1Q): |
| 1061 | outer_shim = pkt.getlayer(Dot1Q) |
| 1062 | if isinstance(outer_shim.payload, Dot1Q): |
| 1063 | inner_shim = outer_shim.payload |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1064 | payload = ( |
| 1065 | Ether(src=pkt.src, dst=pkt.dst, type=outer_shim.type) / |
| 1066 | outer_shim.payload |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 1067 | ) |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1068 | else: |
| 1069 | payload = pkt |
| 1070 | else: |
| 1071 | payload = pkt |
Shad Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 1072 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1073 | 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 Ansari | 1831fcc | 2017-08-11 16:41:44 -0700 | [diff] [blame] | 1077 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1078 | 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) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1106 | |
| 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: |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1234 | 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) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1248 | 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1255 | def divide_and_add_flow(self, v_enet, classifier, action): |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1256 | 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, |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1281 | ASFVOLT_DOWNLINK_EAPOL_ID, |
| 1282 | ASFVOLT16_DEFAULT_VLAN) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1283 | elif 'push_vlan' in action: |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1284 | |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1285 | self.prepare_and_add_dhcp_flow(classifier, action, v_enet, |
| 1286 | ASFVOLT_DHCP_TAGGED_ID, |
| 1287 | ASFVOLT_DOWNLINK_DHCP_TAGGED_ID) |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1288 | |
| 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) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1293 | 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 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1299 | |
| 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 | |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1314 | def add_eapol_flow(self, uplink_classifier, uplink_action, |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1315 | v_enet, uplink_eapol_id, downlink_eapol_id, vlan_id): |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1316 | 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',) |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1323 | # 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) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1329 | 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1351 | #uplink_classifier['pkt_tag_type'] = 'untagged' |
| 1352 | uplink_classifier['pkt_tag_type'] = 'single_tag' |
| 1353 | uplink_classifier['vlan_vid'] = vlan_id |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1354 | 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1372 | time.sleep(0.1) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1373 | 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 |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1385 | #downlink_classifier['pkt_tag_type'] = 'untagged' |
| 1386 | downlink_classifier['pkt_tag_type'] = 'single_tag' |
| 1387 | downlink_classifier['vlan_vid'] = vlan_id |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1388 | 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1402 | time.sleep(0.1) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1403 | 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 |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1416 | dhcp_classifier['udp_dst'] = 67 |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1417 | 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: |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1433 | self.log.info('Failed-to-get-gemport') |
| 1434 | self.store_flows(uplink_classifier, uplink_action, |
| 1435 | v_enet, traffic_class=2) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1436 | 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1476 | time.sleep(0.1) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1477 | |
| 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' |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1491 | # Copy O_OVID |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1492 | downlink_classifier['vlan_vid'] = downlink_action['vlan_vid'] |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1493 | # Copy I_OVID |
| 1494 | #downlink_classifier['metadata'] = uplink_classifier['vlan_vid'] |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1495 | if 'push_vlan' in downlink_classifier: |
| 1496 | downlink_action.pop('push_vlan') |
| 1497 | downlink_action['pop_vlan'] = True |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1498 | else: |
| 1499 | downlink_classifier['pkt_tag_type'] = 'untagged' |
| 1500 | downlink_classifier.pop('vlan_vid') |
| 1501 | |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1502 | |
| 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1521 | time.sleep(0.1) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1522 | 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'] |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1542 | downlink_classifier['metadata'] = uplink_classifier['vlan_vid'] |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1543 | del downlink_action['push_vlan'] |
| 1544 | downlink_action['pop_vlan'] = True |
| 1545 | |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1546 | # 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. |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1549 | self.add_hsia_flow(uplink_classifier, uplink_action, |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1550 | downlink_classifier, downlink_action, |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1551 | v_enet, ASFVOLT_HSIA_ID, ASFVOLT_DOWNLINK_HSIA_ID) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1552 | |
| 1553 | def add_hsia_flow(self, uplink_classifier, uplink_action, |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1554 | downlink_classifier, downlink_action, |
| 1555 | v_enet, hsia_id, downlink_hsia_id): |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1556 | # 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') |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1562 | self.store_flows(uplink_classifier, uplink_action, |
| 1563 | v_enet, traffic_class=2) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1564 | 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 |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1587 | self.log.info('Adding-ARP-upstream-flow', |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1588 | 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1602 | time.sleep(0.1) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1603 | except Exception as e: |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1604 | self.log.exception('failed-to-install-ARP-upstream-flow', e=e, |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1605 | 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1611 | #downlink_classifier['vlan_pcp'] = 7 |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1612 | downlink_flow_id = self.get_flow_id(onu_device.proxy_address.onu_id, |
| 1613 | onu_device.proxy_address.channel_id, |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1614 | hsia_id) |
| 1615 | #downlink_hsia_id) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1616 | try: |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1617 | self.log.info('Adding-ARP-downstream-flow', |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1618 | 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. |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1630 | time.sleep(0.1) |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1631 | except Exception as e: |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1632 | self.log.exception('failed-to-install-ARP-downstream-flow', e=e, |
rshetty | 1cc7398 | 2017-09-02 03:31:12 +0530 | [diff] [blame] | 1633 | 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) |
rshetty | f4bf19e | 2017-09-19 01:28:27 +0530 | [diff] [blame] | 1637 | |
| 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) |