indigo_error_t icmpa_create_send_packet_in (of_octets_t *of_octets, uint64_t reason, of_port_no_t in_port) { of_packet_in_t *of_packet_in; of_match_t match; memset(&match, 0, sizeof(of_match_t)); if (!of_octets) return INDIGO_ERROR_UNKNOWN; if ((of_packet_in = of_packet_in_new(OF_VERSION_1_3)) == NULL) { return INDIGO_ERROR_RESOURCE; } of_packet_in_total_len_set(of_packet_in, of_octets->bytes); match.version = OF_VERSION_1_3; match.fields.in_port = in_port; OF_MATCH_MASK_IN_PORT_EXACT_SET(&match); match.fields.metadata |= reason; OF_MATCH_MASK_METADATA_EXACT_SET(&match); if ((of_packet_in_match_set(of_packet_in, &match)) != OF_ERROR_NONE) { printf("Failed to write match to packet-in message\n"); of_packet_in_delete(of_packet_in); return INDIGO_ERROR_UNKNOWN; } if ((of_packet_in_data_set(of_packet_in, of_octets)) != OF_ERROR_NONE) { printf("Failed to write packet data to packet-in message\n"); of_packet_in_delete(of_packet_in); return INDIGO_ERROR_UNKNOWN; } if (icmpa_packet_in_handler(of_packet_in) == INDIGO_CORE_LISTENER_RESULT_DROP) { printf("Listener dropped packet-in\n"); } else { printf("Listener passed packet-in\n"); } of_packet_in_delete(of_packet_in); return INDIGO_ERROR_NONE; }
void SimpleForwardingModule::handlePacketIn(const zmf::data::ZmfMessage& packetInMsg) { Device* destinationDevice = nullptr; // Unpack ZmfMessage which contains OpenFlow packet of_packet_in_t* ofPacketIn = zsdn::of_object_new_from_data_string_copy(packetInMsg.getData()); of_octets_t ofPayload; of_packet_in_data_get(ofPacketIn, &ofPayload); // extracted message data uint8_t* payloadData = ofPayload.data; uint16_t payloadLength = ofPayload.bytes; // get the ethernet message frame Tins::EthernetII ethPacket(payloadData, payloadLength); of_version_t ofVersion = ofPacketIn->version; // some ethertype may be excluded from beeing handled by this module. we check if the received packet is one of them. bool ignoreEtherType = false; for (uint16_t ignoredType : ignoreEthertypes_) { if (ethPacket.payload_type() == ignoredType) { ignoreEtherType = true; break; } } if (ignoreEtherType) { getLogger().trace("Ignoring packet due to ethertype"); } else { Tins::EthernetII::address_type dstAdress = ethPacket.dst_addr(); // extract the destination address uint64_t destinationMac = zsdn::NetUtils::mac_address_tins_to_uint64(dstAdress); // check for broadcast if == TRUE -> skip the message if (dstAdress.is_broadcast()) { this->getLogger().trace("Received Broadcast -> Message ignored"); } else { this->getLogger().trace("Received Packet in"); // check if the device is known if == FALSE -> request the device by a DeviceManager module if ((this->devices_.count(destinationMac) > 0)) { destinationDevice = &this->devices_.find(destinationMac)->second; // get the device out of the map } else { destinationDevice = this->requestDevice(destinationMac); // request the device by DeviceManager module } if (destinationDevice != nullptr) { // send the initial message payload to the destination switch port if (ofVersion == OF_VERSION_UNKNOWN) { getLogger().warning("Received Packet with OF_VERSION_UNKNOWN. Ignoring Packet."); return; } of_port_no_t port_no = destinationDevice->switchPort; of_object_t* resultObject = nullptr; switch (ofVersion) { case OF_VERSION_UNKNOWN: break; case OF_VERSION_1_0: of_packet_out_data_set(tempPacketOut_OF_1_0, &ofPayload); of_action_output_port_set(tempOutPut_OF_1_0, port_no); of_packet_out_actions_set(tempPacketOut_OF_1_0, tempActionList_OF_1_0); resultObject = tempPacketOut_OF_1_0; break; case OF_VERSION_1_1: break; case OF_VERSION_1_2: break; case OF_VERSION_1_3: of_packet_out_data_set(tempPacketOut_OF_1_3, &ofPayload); of_action_output_port_set(tempOutPut_OF_1_3, port_no); of_packet_out_actions_set(tempPacketOut_OF_1_3, tempActionList_OF_1_3); resultObject = tempPacketOut_OF_1_3; break; case OF_VERSION_1_4: break; } if (resultObject != nullptr) { std::string messageBytes = zsdn::of_object_serialize_to_data_string(resultObject); std::map<uint64_t, zmf::data::MessageType>::iterator msgType = this->linkDevicePacketOutMessageTypeMap_.find( destinationDevice->macAddress); this->getZmf()->publish(zmf::data::ZmfMessage( msgType->second, messageBytes)); if (this->getLogger().trace()) { this->getLogger().trace( "Forwarded packet to " + std::to_string(unsigned(destinationDevice->switchDpid)) + ":" + std::to_string(unsigned(destinationDevice->switchPort))); } } } else { this->getLogger().trace( "Not able to forwared packet, host " + dstAdress.to_string() + " unknown"); } } } of_packet_in_delete(ofPacketIn); };
int test_discovery_pkt_in(int port_no, int indigo_ret_expected) { #define OUT_PKT_BUF_SIZE 1500 uint8_t buf[OUT_PKT_BUF_SIZE]; int rv = 0; of_packet_in_t *obj = 0; ppe_packet_t ppep; of_octets_t data = { .bytes = sizeof(Dhcp_discovery) //346 bytes (342 + 4byteVLAN }; /* Timeout due to re-register the timer */ printf("\n\n*******************************\n"); printf("TEST 1 DHCP Discovery: PKT_IN on port:%d\nExpect Option Added\n", port_no); printf("pkt_in bytes = %d\n", data.bytes); printf("*******************************\n"); /* Set up GOLDEN Expected pkt*/ AIM_TRUE_OR_DIE(sizeof(Dhcp_discovery_expected) <= OUT_PKT_BUF_SIZE); convert_chars_to_bytes(Dhcp_discovery_expected, Dhcp_discovery_expected_hex_stream, sizeof(Dhcp_discovery_expected)); /* Setup discovery pkt */ AIM_TRUE_OR_DIE(sizeof(Dhcp_discovery) <= OUT_PKT_BUF_SIZE); convert_chars_to_bytes(Dhcp_discovery, Dhcp_discovery_hex_stream, sizeof(Dhcp_discovery)); memcpy(buf, Dhcp_discovery, sizeof(Dhcp_discovery)); data.data = buf; obj = of_packet_in_new(OF_VERSION_1_0); AIM_TRUE_OR_DIE(obj); of_packet_in_reason_set(obj, OF_PACKET_IN_REASON_BSN_DHCP); of_packet_in_in_port_set(obj,port_no); if(of_packet_in_data_set(obj, &data) < 0) { AIM_TRUE_OR_DIE(obj); } /* Dump pkt in obj */ // of_object_dump((loci_writer_f)aim_printf, &aim_pvs_stdout, obj); ppe_packet_init(&ppep, data.data, data.bytes); if (ppe_parse(&ppep) < 0) { printf("\nERROR: Packet parsing failed. packet=%p, len=%u", data.data, data.bytes); } /* Dump up to DHCP hdr */ // ppe_packet_dump(&ppep,&aim_pvs_stdout); // parse_dhcp_options(&ppep, data.bytes, 0, 0); /* Handle packet */ rv = dhcpra_handle_pkt (obj); AIM_TRUE_OR_DIE(rv == indigo_ret_expected); of_packet_in_delete(obj); return rv; } int test_offer_pkt_in(int port_no) { #define OUT_PKT_BUF_SIZE 1500 uint8_t buf[OUT_PKT_BUF_SIZE]; int rv = 0; of_packet_in_t *obj; ppe_packet_t ppep; of_octets_t data = { .bytes = sizeof(Dhcp_offer) //354 (342 + 4byte VLAN + 8bytes CirID) }; printf("\n\n*******************************\n" "TEST 2 DHCP OFFER: PKT_IN on port:%d\nExpect Option Removed\n", port_no); printf("pkt_in bytes = %d\n", data.bytes); printf("*******************************\n\n"); /* Set up GOLDEN Expected pkt*/ //printf("Expected Offer pkt:\n"); AIM_TRUE_OR_DIE(sizeof(Dhcp_offer_expected) <= OUT_PKT_BUF_SIZE); convert_chars_to_bytes(Dhcp_offer_expected, Dhcp_offer_expected_hex_stream, sizeof(Dhcp_offer_expected)); /* Setup offer pkt */ //printf("Offer pkt:\n"); AIM_TRUE_OR_DIE(sizeof(Dhcp_offer) <= OUT_PKT_BUF_SIZE); convert_chars_to_bytes(Dhcp_offer, Dhcp_offer_hex_stream, sizeof(Dhcp_offer)); memcpy(buf, Dhcp_offer, sizeof(Dhcp_offer)); data.data = buf; obj = of_packet_in_new(OF_VERSION_1_0); AIM_TRUE_OR_DIE(obj); of_packet_in_in_port_set(obj,port_no); of_packet_in_reason_set(obj, OF_PACKET_IN_REASON_BSN_DHCP); if(of_packet_in_data_set(obj, &data) < 0) { AIM_TRUE_OR_DIE(obj); } /* Dump pkt in obj */ //of_object_dump((loci_writer_f)aim_printf, &aim_pvs_stdout, obj); ppe_packet_init(&ppep, data.data, data.bytes); if (ppe_parse(&ppep) < 0) { printf("\nERROR: Packet parsing failed. packet=%p, len=%u", data.data, data.bytes); } /* Dump up to DHCP hdr */ //ppe_packet_dump(&ppep,&aim_pvs_stdout); //parse_dhcp_options(&ppep, data.bytes, 0, 0); /* Handle packet */ rv = dhcpra_handle_pkt (obj); if (rv == INDIGO_CORE_LISTENER_RESULT_PASS) { printf("\nError: NOT DHCP packet-in\n"); } else if (rv == INDIGO_CORE_LISTENER_RESULT_DROP) printf("\nIS DHCP packet-in\n"); else printf("\nError: Unsupport packet-in\n"); of_packet_in_delete(obj); return rv; } int aim_main(int argc, char* argv[]) { printf("dhcpra Utest Is Empty\n"); dhcpra_config_show(&aim_pvs_stdout); dhcpra_system_init(); printf("\n*********\n0. PRE-TEST TABLE\n********\n"); test_pass[0] = fill_all_vlan_dhcpr_table_test(); printf("\n*********\nI. TEST PASS AFTER ADD and MOD\n********\n"); add_entry_to_dhcpr_table(); mod_entry_to_dhcpr_table(); //Port 1: Correct setup, packet process //Driver will take care of sending L2_SRC_MISSED to controller test_discovery_pkt_in(1, INDIGO_CORE_LISTENER_RESULT_DROP); test_offer_pkt_in(1); printf("\n\nSUMMARY:\nDISCOV:\t%s\n", dhcp_pkt_matched[0] ? "PASSED" : "FAILED"); printf("OFFER:\t%s\n", dhcp_pkt_matched[1] ? "PASSED" : "FAILED"); test_pass[1] = dhcp_pkt_matched[0]; test_pass[2] = dhcp_pkt_matched[1]; printf("\n*********\nII. TEST FAILED AFTER DELETE\n********\n"); dhcp_pkt_matched[0] = 0; dhcp_pkt_matched[1] = 0; del_entry_to_dhcpr_table(); //Incorrect VLAN pass packet test_discovery_pkt_in(1, INDIGO_CORE_LISTENER_RESULT_PASS); test_offer_pkt_in(1); printf("\n\nSUMMARY:\nDISCOV:\t%s\n", dhcp_pkt_matched[0] ? "PASSED" : "FAILED"); printf("OFFER:\t%s\n", dhcp_pkt_matched[1] ? "PASSED" : "FAILED"); test_pass[3] = !dhcp_pkt_matched[0]; test_pass[4] = !dhcp_pkt_matched[1]; printf("\n\n*****SUMMARY ALL 3 TESTS*****\n"); printf("TEST DHCP TABLE: %s\n", test_pass[0] ? "PASSED" : "FAILED"); printf("TEST DISCOVER with valid table: %s\n", test_pass[1] ? "PASSED" : "FAILED"); printf("TEST OFFER with valid table: %s\n", test_pass[2] ? "PASSED" : "FAILED"); printf("TEST DISCOVER with in valid table: %s\n", test_pass[3] ? "PASSED" : "FAILED"); printf("TEST OFFER with in valid table: %s\n", test_pass[4] ? "PASSED" : "FAILED"); return 0; }