def _message_exchange(self, device): # register for receiving async messages self.adapter_agent.register_for_proxied_messages(device.proxy_address) # reset incoming message queue while self.incoming_messages.pending: _ = yield self.incoming_messages.get() # send out ping frame to ONU device get device information ping_frame = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Get Request"], body=VendorName() / OnuMode() / HardwareVersion() / ManufacturerInfo() ) / EndOfPDU() ) log.info('ONU-send-proxied-message to Get Version Info for ONU: {}'.format(device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, ping_frame) # Loop until we have a Get Response ack = False while not ack: frame = yield self.incoming_messages.get() respType = get_oam_msg_type(log, frame) if (respType == RxedOamMsgTypeEnum["DPoE Get Response"]): ack = True else: # Handle unexpected events/OMCI messages check_resp(log, frame) if ack: log.info('ONU-response received for Get Version Info for ONU: {}'.format(device.mac_address)) self._process_ping_frame_response(device, frame) if self.mode.upper()[0] == "G": # GPON # construct multicast LLID set msg = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Multicast Register"],body=MulticastRegisterSet(MulticastLink=0x10bc, UnicastLink=0) )) # send message log.info('ONU-send-proxied-message to Multicast Register Set for ONU: {}'.format(device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, msg)
def reboot_device(self, device): log.info('Rebooting ONU: {}'.format(device.mac_address)) # Update the operational status to ACTIVATING and connect status to # UNREACHABLE previous_oper_status = device.oper_status previous_conn_status = device.connect_status device.oper_status = OperStatus.ACTIVATING device.connect_status = ConnectStatus.UNREACHABLE self.adapter_agent.update_device(device) msg = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=DeviceReset())/ EndOfPDU() ) action = "Device Reset" # send message log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, msg) rc = [] yield self._handle_set_resp(device, action, rc) # Change the operational status back to its previous state. device.oper_status = previous_oper_status device.connect_status = previous_conn_status self.adapter_agent.update_device(device) log.info('ONU Rebooted: {}'.format(device.mac_address))
def _send_clear_static_mac_table(self, device): # construct install of igmp query address msg = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Set Request"],body=ClearStaticMacTable() )) action = "Clear Static MAC Table" # send message log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, msg) rc = [] yield self._handle_set_resp(device, action, rc)
def _send_igmp_mcast_addr(self, device): # construct install of igmp query address msg = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode=Dpoe_Opcodes["Set Request"],body=AddStaticMacAddress(mac='01:00:5e:00:00:01') )) action = "Set Static IGMP MAC address" # send message log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, msg) rc = [] yield self._handle_set_resp(device, action, rc)
def update_flows_bulk(self, device, flows, groups): log.info('########################################') log.info('bulk-flow-update', device_id=device.id, flows=flows, groups=groups) assert len(groups.items) == 0, "Cannot yet deal with groups" # Only do something if there are flows to program if (len(flows.items) > 0): # Clear the existing entries in the Static MAC Address Table yield self._send_clear_static_mac_table(device) # Re-add the IGMP Multicast Address yield self._send_igmp_mcast_addr(device) Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()} Operator = {v: k for k, v in RuleOperatorEnum.iteritems()} for flow in flows.items: in_port = get_in_port(flow) assert in_port is not None precedence = 255 - min(flow.priority / 256, 255) if in_port == 2: log.info('#### Upstream Rule ####') up_req = UserPortObject() up_req /= PortIngressRuleHeader(precedence=precedence) for field in get_ofb_fields(flow): if field.type == ETH_TYPE: _type = field.eth_type log.info('#### field.type == ETH_TYPE ####',field_type=_type) elif field.type == IP_PROTO: _proto = field.ip_proto log.info('#### field.type == IP_PROTO ####') elif field.type == IN_PORT: _port = field.port log.info('#### field.type == IN_PORT ####', port=_port) elif field.type == VLAN_VID: _vlan_vid = field.vlan_vid & 0xfff log.info('#### field.type == VLAN_VID ####', vlan=_vlan_vid) up_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0, operator=Operator['=='], match=_vlan_vid) elif field.type == VLAN_PCP: _vlan_pcp = field.vlan_pcp log.info('#### field.type == VLAN_PCP ####', pcp=_vlan_pcp) elif field.type == UDP_DST: _udp_dst = field.udp_dst log.info('#### field.type == UDP_DST ####', udp_dst=_udp_dst) elif field.type == IPV4_DST: _ipv4_dst = field.ipv4_dst log.info('#### field.type == IPV4_DST ####', ipv4_dst=_ipv4_dst) elif field.type == METADATA: _metadata = field.table_metadata log.info('#### field.type == METADATA ####', metadata=_metadata) else: log.info('#### field.type == NOT IMPLEMENTED!! ####') raise NotImplementedError('field.type={}'.format( field.type)) for action in get_actions(flow): if action.type == OUTPUT: log.info('#### action.type == OUTPUT ####') up_req /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag']) elif action.type == POP_VLAN: log.info('#### action.type == POP_VLAN ####') elif action.type == PUSH_VLAN: log.info('#### action.type == PUSH_VLAN ####') up_req /= PortIngressRuleResultInsert(fieldcode=Clause['C-VLAN Tag']) # if action.push.ethertype != 0x8100: # log.error('unhandled-tpid', # ethertype=action.push.ethertype) elif action.type == SET_FIELD: log.info('#### action.type == SET_FIELD ####') assert (action.set_field.field.oxm_class == ofp.OFPXMC_OPENFLOW_BASIC) field = action.set_field.field.ofb_field if field.type == VLAN_VID: log.info("#### action.field.vlan {} ####".format(field.vlan_vid & 0xfff)) up_req /= PortIngressRuleResultSet( fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff) else: log.error('unsupported-action-set-field-type', field_type=field.type) else: log.error('UNSUPPORTED-ACTION-TYPE', action_type=action.type) up_req /= PortIngressRuleTerminator() up_req /= AddPortIngressRule() msg = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=up_req)/ EndOfPDU() ) # send message action = "Set ONU US Rule" log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, msg) # Get and process the Set Response rc = [] yield self._handle_set_resp(device, action, rc) elif in_port == 1: log.info('#### Downstream Rule ####') Is_MCast = False dn_req = PonPortObject() dn_req /= PortIngressRuleHeader(precedence=precedence) #### Loop through fields again... for field in get_ofb_fields(flow): if field.type == ETH_TYPE: _type = field.eth_type log.info('#### field.type == ETH_TYPE ####', in_port=in_port, match=_type) elif field.type == IP_PROTO: _proto = field.ip_proto log.info('#### field.type == IP_PROTO ####', in_port=in_port, ip_proto=_proto) elif field.type == IN_PORT: _port = field.port log.info('#### field.type == IN_PORT ####') elif field.type == VLAN_VID: _vlan_vid = field.vlan_vid & 0xfff log.info('#### field.type == VLAN_VID ####') elif field.type == VLAN_PCP: _vlan_pcp = field.vlan_pcp log.info('#### field.type == VLAN_PCP ####') elif field.type == UDP_DST: _udp_dst = field.udp_dst log.info('#### field.type == UDP_DST ####') elif field.type == IPV4_DST: _ipv4_dst = field.ipv4_dst log.info('#### field.type == IPV4_DST ####') a = int(hex(_ipv4_dst)[2:4], 16) b = int(hex(_ipv4_dst)[4:6], 16) c = int(hex(_ipv4_dst)[6:8], 16) d = int(hex(_ipv4_dst)[8:], 16) dn_req = AddStaticMacAddress(mac=mcastIp2McastMac('%d.%d.%d.%d' % (a,b,c,d))) Is_MCast = True else: raise NotImplementedError('field.type={}'.format( field.type)) for action in get_actions(flow): if action.type == OUTPUT: log.info('#### action.type == OUTPUT ####') elif action.type == POP_VLAN: log.info('#### action.type == POP_VLAN ####') dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0, operator=Operator['=='], match=_vlan_vid) dn_req /= PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag']) dn_req /= PortIngressRuleResultSet( fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff) elif action.type == PUSH_VLAN: log.info('#### action.type == PUSH_VLAN ####') if action.push.ethertype != 0x8100: log.error('unhandled-ether-type', ethertype=action.push.ethertype) elif action.type == SET_FIELD: log.info('#### action.type == SET_FIELD ####') assert (action.set_field.field.oxm_class == ofp.OFPXMC_OPENFLOW_BASIC) field = action.set_field.field.ofb_field if field.type == VLAN_VID: dn_req /= PortIngressRuleClauseMatchLength02(fieldcode=Clause['C-VLAN Tag'], fieldinstance=0, operator=Operator['=='], match=_vlan_vid) dn_req /= PortIngressRuleResultReplace(fieldcode=Clause['C-VLAN Tag']) dn_req /= PortIngressRuleResultSet( fieldcode=Clause['C-VLAN Tag'], value=field.vlan_vid & 0xfff) else: log.error('unsupported-action-set-field-type', field_type=field.type) else: log.error('UNSUPPORTED-ACTION-TYPE', action_type=action.type) if Is_MCast is True: action = "Set Static IP MCAST address" else: dn_req /= PortIngressRuleTerminator() dn_req /= AddPortIngressRule() action = "Set ONU DS Rule" msg = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode = Dpoe_Opcodes["Set Request"], body=dn_req)/ EndOfPDU() ) # send message log.info('ONU-send-proxied-message to {} for ONU: {}'.format(action, device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, msg) # Get and process the Set Response rc = [] yield self._handle_set_resp(device, action, rc) else: raise Exception('Port should be 1 or 2 by our convention') log.info('bulk-flow-update finished', device_id=device.id, flows=flows, groups=groups) log.info('########################################')
def _message_exchange(self, device): # register for receiving async messages self.adapter_agent.register_for_proxied_messages(device.proxy_address) # reset incoming message queue while self.incoming_messages.pending: _ = yield self.incoming_messages.get() # construct message msg = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode=0x01,body=DeviceId()) ) # send message log.info('ONU-send-proxied-message to Get Device Id for ONU: {}'.format(device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, msg) # wait till we detect incoming message yield self.incoming_messages.get() log.info('ONU-response received for Get Device Id for ONU: {}'.format(device.mac_address)) #TODO Add a timeout to the above, if we do not recieve a message #The above get request/ get response is done to verify the message exchange is #functioning correctly, there is nothing to store from the response # construct install of igmp query address msg = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode=0x03,body=AddStaticMacAddress(mac='01:00:5e:00:00:01') )) # send message log.info('ONU-send-proxied-message to Set Static IGMP MAC address for ONU: {}'.format(device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, msg) # Get and process the Set Response ack = False start_time = time.time() # Loop until we have a set response or timeout while not ack: frame = yield self.incoming_messages.get() #TODO - Need to add propoer timeout functionality #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None): # break # don't wait forever respType = self._get_oam_msg_type(frame) log.info('Received OAM Message 0x %s' % str(respType)) #Check that the message received is a Set Response if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]): ack = True else: # Handle unexpected events/OMCI messages self._check_resp(frame) # Verify Set Response if ack: log.info('ONU-response received for Set Static IGMP MAC address for ONU: {}'.format(device.mac_address)) (rc,branch,leaf,status) = self._check_set_resp(frame) if (rc == True): log.info('Set Response had no errors') else: log.info('Set Response had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status])) # construct multicast LLID set # TODO - This is needed to support multicast traffic for GPON. This should only be done for a # a GPON ONU and the UnicastLink value needs to come from the OLT. This will work only for # a single GPON ONU. msg = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode=0x06,body=MulticastRegisterSet(MulticastLink=0x10bc, UnicastLink=0x1008) )) # send message log.info('ONU-send-proxied-message to Set Static IGMP MAC address for ONU: {}'.format(device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, msg)
def update_flows_bulk(self, device, flows, groups): log.info('########################################') log.info('bulk-flow-update', device_id=device.id, flows=flows, groups=groups) assert len(groups.items) == 0, "Cannot yet deal with groups" Clause = {v: k for k, v in ClauseSubtypeEnum.iteritems()} Operator = {v: k for k, v in RuleOperatorEnum.iteritems()} for flow in flows.items: in_port = get_in_port(flow) assert in_port is not None precedence = 255 - min(flow.priority / 256, 255) if in_port == 2: log.info('#### Upstream Rule ####') up_req = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode=0x03) ) #TODO - There is no body to the message above, is there ever an Upstream Rule for field in get_ofb_fields(flow): if field.type == ETH_TYPE: _type = field.eth_type log.info('#### field.type == ETH_TYPE ####',field_type=_type) elif field.type == IP_PROTO: _proto = field.ip_proto log.info('#### field.type == IP_PROTO ####') elif field.type == IN_PORT: _port = field.port log.info('#### field.type == IN_PORT ####', port=_port) elif field.type == VLAN_VID: _vlan_vid = field.vlan_vid & 0xfff log.info('#### field.type == VLAN_VID ####', vlan=_vlan_vid) elif field.type == VLAN_PCP: _vlan_pcp = field.vlan_pcp log.info('#### field.type == VLAN_PCP ####', pcp=_vlan_pcp) elif field.type == UDP_DST: _udp_dst = field.udp_dst log.info('#### field.type == UDP_DST ####') elif field.type == IPV4_DST: _ipv4_dst = field.ipv4_dst log.info('#### field.type == IPV4_DST ####') else: log.info('#### field.type == NOT IMPLEMENTED!! ####') raise NotImplementedError('field.type={}'.format( field.type)) for action in get_actions(flow): if action.type == OUTPUT: log.info('#### action.type == OUTPUT ####') elif action.type == POP_VLAN: log.info('#### action.type == POP_VLAN ####') elif action.type == PUSH_VLAN: log.info('#### action.type == PUSH_VLAN ####') if action.push.ethertype != 0x8100: log.error('unhandled-tpid', ethertype=action.push.ethertype) elif action.type == SET_FIELD: log.info('#### action.type == SET_FIELD ####') assert (action.set_field.field.oxm_class == ofp.OFPXMC_OPENFLOW_BASIC) field = action.set_field.field.ofb_field if field.type == VLAN_VID: pass else: log.error('unsupported-action-set-field-type', field_type=field.type) else: log.error('UNSUPPORTED-ACTION-TYPE', action_type=action.type) elif in_port == 1: log.info('#### Downstream Rule ####') #### Loop through fields again... for field in get_ofb_fields(flow): if field.type == ETH_TYPE: _type = field.eth_type log.info('#### field.type == ETH_TYPE ####', in_port=in_port, match=_type) elif field.type == IP_PROTO: _proto = field.ip_proto log.info('#### field.type == IP_PROTO ####', in_port=in_port, ip_proto=ip_proto) elif field.type == IN_PORT: _port = field.port log.info('#### field.type == IN_PORT ####') elif field.type == VLAN_VID: _vlan_vid = field.vlan_vid & 0xfff log.info('#### field.type == VLAN_VID ####') elif field.type == VLAN_PCP: _vlan_pcp = field.vlan_pcp log.info('#### field.type == VLAN_PCP ####') elif field.type == UDP_DST: _udp_dst = field.udp_dst log.info('#### field.type == UDP_DST ####') elif field.type == IPV4_DST: _ipv4_dst = field.ipv4_dst log.info('#### field.type == IPV4_DST ####') a = int(hex(_ipv4_dst)[2:4], 16) b = int(hex(_ipv4_dst)[4:6], 16) c = int(hex(_ipv4_dst)[6:8], 16) d = int(hex(_ipv4_dst)[8:], 16) dn_req = ( EOAMPayload() / EOAM_VendSpecificMsg(oui=CableLabs_OUI) / EOAM_DpoeMsg(dpoe_opcode=0x03, body=AddStaticMacAddress(mac=mcastIp2McastMac('%d.%d.%d.%d' % (a,b,c,d))) )) # send message log.info('ONU-send-proxied-message to Set Static IP MCAST address for ONU: {}'.format(device.mac_address)) self.adapter_agent.send_proxied_message(device.proxy_address, dn_req) # Get and process the Set Response ack = False start_time = time.time() # Loop until we have a set response or timeout while not ack: frame = yield self.incoming_messages.get() #TODO - Need to add propoer timeout functionality #if (time.time() - start_time) > TIBIT_MSG_WAIT_TIME or (frame is None): # break # don't wait forever respType = self._get_oam_msg_type(frame) log.info('Received OAM Message 0x %s' % str(respType)) #Check that the message received is a Set Response if (respType == RxedOamMsgTypeEnum["DPoE Set Response"]): ack = True else: # Handle unexpected events/OMCI messages self._check_resp(frame) # Verify Set Response if ack: log.info('ONU-response received for Set Static IP MCAST address for ONU: {}'.format(device.mac_address)) (rc,branch,leaf,status) = self._check_set_resp(frame) if (rc == True): log.info('Set Response had no errors') else: log.info('Set Response had errors - Branch 0x{:X} Leaf 0x{:0>4X} {}'.format(branch, leaf, DPoEVariableResponseCodes[status])) else: raise NotImplementedError('field.type={}'.format( field.type)) for action in get_actions(flow): if action.type == OUTPUT: log.info('#### action.type == OUTPUT ####') elif action.type == POP_VLAN: log.info('#### action.type == POP_VLAN ####') elif action.type == PUSH_VLAN: log.info('#### action.type == PUSH_VLAN ####') if action.push.ethertype != 0x8100: log.error('unhandled-ether-type', ethertype=action.push.ethertype) elif action.type == SET_FIELD: log.info('#### action.type == SET_FIELD ####') assert (action.set_field.field.oxm_class == ofp.OFPXMC_OPENFLOW_BASIC) field = action.set_field.field.ofb_field if field.type == VLAN_VID: pass else: log.error('unsupported-action-set-field-type', field_type=field.type) else: log.error('UNSUPPORTED-ACTION-TYPE', action_type=action.type) else: raise Exception('Port should be 1 or 2 by our convention')