static ucli_status_t ppe_ucli_utm__data__(ucli_context_t* uc) { uint8_t* data; int size; UCLI_COMMAND_INFO(uc, "data", 1, "Assign packet data."); UCLI_ARGPARSE_OR_RETURN(uc, "{data}", &data, &size); if(ppec->ppep.data) { aim_free(ppec->ppep.data); } if(ppe_packet_init(&ppec->ppep, data, size) < 0) { return ucli_e_internal(uc, "ppe_packet_init()"); } if(ppe_parse(&ppec->ppep) < 0) { return ucli_e_internal(uc, "ppe_parse()"); } return UCLI_STATUS_OK; }
ucli_status_t vt_ucli_module__ppedump__(ucli_context_t* uc) { int count = 0; UCLI_COMMAND_INFO(uc, "ppedump", 1, "$summary#PPE dump all packets on the given VPI." "$args#<vpi_spec>"); UCLI_ARGPARSE_OR_RETURN(uc, "{vpi}", &vtc->vpi); while(1) { if(vpi_recv__(uc, vtc) > 0) { ppe_packet_t ppep; ppe_packet_init(&ppep, vtc->data, vtc->size); if(ppe_parse(&ppep) < 0) { ucli_printf(uc, "[%.3d] recv(%{vpi}):\n%{data}\n", count, vtc->vpi, vtc->data, vtc->size); } else { ucli_printf(uc, "[%.3d] recv(%{vpi}):\n", count, vtc->vpi); ppe_packet_dump(&ppep, &uc->pvs); } count++; } else { break; } } return UCLI_STATUS_OK; }
int ppe_packet_dup(ppe_packet_t* dst, ppe_packet_t* src) { ppe_packet_init(dst, aim_memdup(src->data, src->size), src->size); PPE_MEMCPY(dst->mh, src->mh, sizeof(dst->mh)); ppe_parse(dst); dst->realloc = 1; return 0; }
void icmpa_verify_packet (of_octets_t *octets, uint32_t reason) { ppe_packet_t ppep; uint32_t icmp_type; if (!octets) return; ppe_packet_init(&ppep, octets->data, octets->bytes); if (ppe_parse(&ppep) < 0) { AIM_LOG_ERROR("Packet_in parsing failed."); return; } assert(ppe_header_get(&ppep, PPE_HEADER_ICMP)); ppe_field_get(&ppep, PPE_FIELD_ICMP_TYPE, &icmp_type); assert(icmp_type == reason); }
/* * lacpa_receive * * Process incoming LACPDU and take appropriate action */ extern bool lacpa_receive (lacpa_port_t *port, uint8_t *data, uint32_t bytes) { lacpa_pdu_t pdu; ppe_packet_t ppep; if (!port || !data) return FALSE; if (!port->lacp_enabled) { AIM_LOG_ERROR("LACPDU-Rx-FAILED - Agent is Disabled on port: %d", port->actor.port_no); return FALSE; } LACPA_MEMSET(&pdu, DEFAULT_ZERO, sizeof(lacpa_pdu_t)); AIM_LOG_TRACE("LACPDU Received on port: %d", port->actor.port_no); /* * Use ppe api's to fill info from data in our pdu */ ppe_packet_init(&ppep, data, bytes); if (ppe_parse(&ppep) < 0) { AIM_LOG_ERROR("Packet parsing failed. packet=%{data}", data, bytes); return FALSE; } if (!ppe_header_get(&ppep, PPE_HEADER_LACP)) { AIM_LOG_ERROR("Not a Valid LCAP Packet"); return FALSE; } /* * Retrieve the information from the LCAP packet */ if (!lacpa_parse_pdu(&ppep, &pdu)) { AIM_LOG_ERROR("Packet parsing failed."); return FALSE; } port->lacp_event = LACPA_EVENT_PDU_RECEIVED; lacpa_machine(port, &pdu); return TRUE; }
indigo_error_t dhcpra_create_send_packet_in (of_port_no_t in_port, of_octets_t *of_octets) { of_packet_in_t *of_packet_in; of_match_t match; ppe_packet_t ppep; ppe_header_t format; uint8_t buf[1500]; int option; int debug_dump = 0; if (!of_octets) return INDIGO_ERROR_UNKNOWN; /* * Check if the packet_in is untagged, then add the Vlan tag */ ppe_packet_init(&ppep, of_octets->data, of_octets->bytes); if (ppe_parse(&ppep) < 0) { printf("RAW untag linux packet parsing failed.\n"); return INDIGO_ERROR_UNKNOWN; } if (!(ppe_header_get(&ppep, PPE_HEADER_DHCP))) { /* Since we listen to all pkt_in * Rate is high, no need add debug msg here * Not LLDP packet, simply return */ printf("in_port=%u: NOT DHCP packet IGNORED", in_port); return INDIGO_ERROR_NONE; } /* Dump up to DHCP hdr */ printf("RAW untag Linux dump\n"); get_dhcp_options(&ppep, of_octets->bytes, debug_dump, &option); ppe_packet_format_get(&ppep, &format); if (format != PPE_HEADER_8021Q) { of_octets->bytes += 4; memcpy(buf, of_octets->data, of_octets->bytes); memcpy(of_octets->data+16, buf+12, of_octets->bytes-16); of_octets->data[12] = ETHERTYPE_DOT1Q >> 8; of_octets->data[13] = ETHERTYPE_DOT1Q & 0xFF; of_octets->data[14] = 0; of_octets->data[15] = VLAN_TEST; //7; } else {
indigo_error_t indigo_fwd_packet_out (of_packet_out_t *pkt) { of_octets_t data; ppe_packet_t ppep; printf("\n********\n***DUMPING Fwd pkt out Received and Checked\n*************\n"); //of_packet_out_OF_VERSION_1_3_dump((loci_writer_f)aim_printf, &aim_pvs_stdout, pkt); of_packet_out_data_get(pkt, &data); 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); } //ppe_packet_dump(&ppep,&aim_pvs_stdout); parse_dhcp_options(&ppep, data.bytes, 1, 1); return INDIGO_ERROR_NONE; }
/* * lacpa_transmit * * Construct an LACPDU for the given port and transmit it out */ extern bool lacpa_transmit (lacpa_port_t *port) { ppe_packet_t ppep; uint8_t data[LACP_PKT_BUF_SIZE]; if (!port) return FALSE; if (!port->lacp_enabled) { AIM_LOG_ERROR("LACPDU-Tx-FAILED - Agent is Disabled on port: %d", port->actor.port_no); return FALSE; } LACPA_MEMSET(data, DEFAULT_ZERO, LACP_PKT_BUF_SIZE); AIM_LOG_TRACE("Transmit Packet for port: %d, reason: %{lacpa_transmit}", port->actor.port_no, port->ntt_reason); lacpa_dump_port(port); ppe_packet_init(&ppep, data, LACP_PKT_BUF_SIZE); /* * Set ethertype as slow-protocols and Set LACP subtype * Parse to recognize LACP packet. */ data[12] = PPE_ETHERTYPE_SLOW_PROTOCOLS >> 8; data[13] = PPE_ETHERTYPE_SLOW_PROTOCOLS & 0xFF; data[14] = PPE_SLOW_PROTOCOL_LACP; if (ppe_parse(&ppep) < 0) { AIM_LOG_ERROR("Packet parsing failed after ethertype. packet=%{data}", data, LACP_PKT_BUF_SIZE); return FALSE; } /* * Set the Src and Dest Mac. * Src Mac is provided to us and Dest Mac is the slow-protocols-mac-address */ ppe_wide_field_set(&ppep, PPE_FIELD_ETHERNET_SRC_MAC, port->src_mac); ppe_wide_field_set(&ppep, PPE_FIELD_ETHERNET_DST_MAC, slow_protocols_address); /* * Build the rest of the LCAP packet */ if (!lacpa_build_pdu(&ppep, port)) { AIM_LOG_ERROR("Packet sending failed."); return FALSE; } /* * Dump out the packet to verify all the fields are set properly */ ppe_packet_dump(&ppep, &aim_pvs_stdout); lacpa_send(port, data, LACP_PKT_BUF_SIZE); return TRUE; }
/* * icmp_packet_in_handler * * API for handling incoming packets */ indigo_core_listener_result_t icmpa_packet_in_handler (of_packet_in_t *packet_in) { of_octets_t octets; of_port_no_t port_no; of_match_t match; ppe_packet_t ppep; indigo_core_listener_result_t result = INDIGO_CORE_LISTENER_RESULT_PASS; uint32_t type, code; debug_counter_inc(&pkt_counters.icmp_total_in_packets); if (!packet_in) return INDIGO_CORE_LISTENER_RESULT_PASS; of_packet_in_data_get(packet_in, &octets); /* * Identify the recv port */ if (packet_in->version <= OF_VERSION_1_1) { return INDIGO_CORE_LISTENER_RESULT_PASS; } else { if (of_packet_in_match_get(packet_in, &match) < 0) { AIM_LOG_ERROR("ICMPA: match get failed"); debug_counter_inc(&pkt_counters.icmp_internal_errors); return INDIGO_CORE_LISTENER_RESULT_PASS; } port_no = match.fields.in_port; } if (port_no == OF_PORT_DEST_CONTROLLER) { debug_counter_inc(&pkt_counters.icmp_total_passed_packets); return INDIGO_CORE_LISTENER_RESULT_PASS; } if (port_no > MAX_PORTS) { AIM_LOG_ERROR("ICMPA: Port No: %d Out of Range %d", port_no, MAX_PORTS); debug_counter_inc(&pkt_counters.icmp_internal_errors); return INDIGO_CORE_LISTENER_RESULT_PASS; } /* * Check the packet-in reasons in metadata * * Icmp agent should not consume packets coming in due to L2 Src miss * and Station Move. */ if ((match.fields.metadata & OFP_BSN_PKTIN_FLAG_STATION_MOVE) || (match.fields.metadata & OFP_BSN_PKTIN_FLAG_NEW_HOST)) { debug_counter_inc(&pkt_counters.icmp_total_passed_packets); return INDIGO_CORE_LISTENER_RESULT_PASS; } ppe_packet_init(&ppep, octets.data, octets.bytes); if (ppe_parse(&ppep) < 0) { AIM_LOG_RL_ERROR(&icmp_pktin_log_limiter, os_time_monotonic(), "ICMPA: Packet_in parsing failed."); debug_counter_inc(&pkt_counters.icmp_internal_errors); return INDIGO_CORE_LISTENER_RESULT_PASS; } /* * Identify if this is an Echo Request, destined to one of VRouter */ if (ppe_header_get(&ppep, PPE_HEADER_ICMP)) { if (icmpa_reply(&ppep, port_no, &result)) { ++port_pkt_counters[port_no].icmp_echo_packets; return result; } } /* * To handle traceroute, we need to check for * a) UDP Packet * b) dest IP is Vrouter IP * c) UDP src and dest ports are ephemeral */ if (ppe_header_get(&ppep, PPE_HEADER_UDP) && ppe_header_get(&ppep, PPE_HEADER_IP4)) { uint32_t dest_ip, src_port, dest_port; ppe_field_get(&ppep, PPE_FIELD_IP4_DST_ADDR, &dest_ip); ppe_field_get(&ppep, PPE_FIELD_UDP_SRC_PORT, &src_port); ppe_field_get(&ppep, PPE_FIELD_UDP_DST_PORT, &dest_port); if (router_ip_check(dest_ip) && is_ephemeral(src_port) && is_ephemeral(dest_port)) { AIM_LOG_TRACE("ICMP Port Unreachable received on port: %d", port_no); type = ICMP_DEST_UNREACHABLE; code = 3; result = INDIGO_CORE_LISTENER_RESULT_DROP; if (icmpa_send(&ppep, port_no, type, code)) { ++port_pkt_counters[port_no].icmp_port_unreachable_packets; return result; } } } /* * Identify if the reason is valid for ICMP Agent to consume the packet */ if (match.fields.metadata & OFP_BSN_PKTIN_FLAG_L3_MISS) { AIM_LOG_TRACE("ICMP Dest Network Unreachable received on port: %d", port_no); type = ICMP_DEST_UNREACHABLE; code = 0; result = INDIGO_CORE_LISTENER_RESULT_DROP; if (icmpa_send(&ppep, port_no, type, code)) { ++port_pkt_counters[port_no].icmp_net_unreachable_packets; } } else if (match.fields.metadata & OFP_BSN_PKTIN_FLAG_TTL_EXPIRED) { AIM_LOG_TRACE("ICMP TTL Expired received on port: %d", port_no); type = ICMP_TIME_EXCEEDED; code = 0; result = INDIGO_CORE_LISTENER_RESULT_DROP; if (icmpa_send(&ppep, port_no, type, code)) { ++port_pkt_counters[port_no].icmp_time_exceeded_packets; } } return result; }
/* * This is clearly an unscaleable approach. * If the combinations increase this should be * rewritten properly. */ int ppe_packet_format_set(ppe_packet_t* ppep, ppe_header_t type) { int rv = 0; ppe_header_t current; ppe_packet_format_get(ppep, ¤t); PPE_LOG_FORMAT("convert (data=%p,size=%d) from format %s to format %s", ppep->data, ppep->size, ppe_header_name(current), ppe_header_name(type)); if(current == type) { /* Already in the requested format. */ return 0; } else { switch(current) { case PPE_HEADER_8021Q: { switch(type) { case PPE_HEADER_ETHERII: { PPE_MEMMOVE(ppep->data + 12, ppep->data + 16, ppep->size - 16); ppep->size -= 4; break; } default: { AIM_LOG_ERROR("invalid format set (%s)", ppe_header_name(type)); return -1; } } break; } case PPE_HEADER_ETHERII: { switch(type) { case PPE_HEADER_8021Q: { /* @fixme architecture */ ppep->size += 4; ppep->_data = ppep->data; ppep->data = aim_zmalloc(ppep->size); PPE_MEMCPY(ppep->data, ppep->_data, 12); PPE_MEMCPY(ppep->data+16, ppep->_data+12, ppep->size-16); ppep->data[12] = 0x81; ppep->data[13] = 0; ppep->data[14] = 0; ppep->data[15] = 0; ppep->realloc = 1; rv = 1; break; } default: { AIM_LOG_ERROR("invalid format set(%s)", ppe_header_name(type)); return -1; } } break; } default: { AIM_LOG_ERROR("cannot convert from current format (%s)", ppe_header_name(type)); return -1; } } /** * Need to reparse */ ppe_parse(ppep); return rv; } }
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; }