int mirroring_receive(phv_data_t *phv, int *metadata_recirc, void *pkt_data, int len, uint64_t packet_id, pkt_instance_type_t instance_type) { int mirror_id = fields_get_clone_spec(phv); coalescing_session_t *coalescing_session = get_coalescing_session(mirror_id); if(NULL != coalescing_session) { RMT_LOG(P4_LOG_LEVEL_VERBOSE, "Queuing digest for mirror %d %d\n", mirror_id, *metadata_recirc); pkt_digest_t *pkt_digest = malloc(sizeof(pkt_digest_t)); pkt_digest->mirror_id = mirror_id; pkt_digest->length = 0; deparser_extract_digest(phv, metadata_recirc, pkt_digest->buffer, &(pkt_digest->length)); cb_write(rmt_mirroring_cb, pkt_digest); } else if(NULL != get_mirroring_mapping(mirror_id)) { uint8_t *metadata; deparser_produce_metadata(phv, &metadata); //:: if enable_intrinsic: //:: bytes = 0 //:: for header_instance in ordered_header_instances_non_virtual: //:: h_info = header_info[header_instance] //:: is_metadata = h_info["is_metadata"] //:: if is_metadata: bytes += h_info["byte_width_phv"] //:: #endfor uint8_t extracted_metadata[${bytes}]; metadata_extract(extracted_metadata, metadata, NULL); /* NULL ? */ // do not set deflection_flag and dod bits for mirrored packet metadata_set_deflection_flag(extracted_metadata, 0); metadata_set_deflect_on_drop(extracted_metadata, 0); metadata_dump(metadata, extracted_metadata); //:: #endif return queuing_receive(metadata, metadata_recirc, pkt_data, len, packet_id, instance_type); } else { RMT_LOG(P4_LOG_LEVEL_WARN, "Received packet with invalid mirror id %d\n", mirror_id); } free(pkt_data); free(metadata_recirc); return 0; }
static void *pkt_processing_loop(void *arg) { while(1) { queuing_pkt_t *q_pkt = (queuing_pkt_t *) cb_read(rmt_queuing_cb); buffered_pkt_t *b_pkt = &q_pkt->pkt; RMT_LOG(P4_LOG_LEVEL_TRACE, "queuing system: packet dequeued\n"); memset(metadata, 0, ${bytes}); metadata_extract(metadata, q_pkt->metadata, q_pkt->metadata_recirc); /* after this point, no one should use q_pkt->metadata */ int mirror_id = metadata_get_clone_spec(metadata); metadata_set_clone_spec(metadata, 0); int egress_port; //:: if enable_pre: if (pre_replication(q_pkt, metadata)) { continue; } //:: #endif if(mirror_id == 0) { egress_port = metadata_get_egress_spec(metadata); /* TODO: formalize somewhere that 511 is the drop port for this target */ //:: if "ingress_drop_ctl" in extra_metadata_name_map: // program uses the separate ingress_drop_ctl register // a non-zero value means drop if(egress_port = 511 || metadata_get_ingress_drop_ctl(metadata)) { //:: else: if(egress_port == 511) { //:: #endif RMT_LOG(P4_LOG_LEVEL_VERBOSE, "dropping packet at ingress\n"); free(b_pkt->pkt_data); free(q_pkt->metadata); free(q_pkt->metadata_recirc); free(q_pkt); continue; } } else { RMT_LOG(P4_LOG_LEVEL_VERBOSE, "mirror id is %d\n", mirror_id); egress_port = ${pd_prefix}mirroring_mapping_get_egress_port(mirror_id); if (egress_port < 0) { RMT_LOG(P4_LOG_LEVEL_WARN, "no mapping for mirror id %d, dropping packet\n", mirror_id); free(b_pkt->pkt_data); free(q_pkt->metadata); free(q_pkt->metadata_recirc); free(q_pkt); continue; } RMT_LOG(P4_LOG_LEVEL_TRACE, "queuing system: cloned packet, mirror_id -> egress_port : %d -> %d\n", mirror_id, egress_port); } metadata_set_egress_port(metadata, egress_port); RMT_LOG(P4_LOG_LEVEL_TRACE, "egress port set to %d\n", egress_port); pkt_instance_type_t instance_type = b_pkt->instance_type; metadata_set_instance_type(metadata, instance_type); RMT_LOG(P4_LOG_LEVEL_TRACE, "instance type set to %d\n", instance_type); //:: if enable_intrinsic: /* Set enqueue metadata */ metadata_set_enq_qdepth(metadata, egress_pipeline_count(egress_port)); metadata_set_enq_timestamp(metadata, get_timestamp()); //:: #endif metadata_dump(q_pkt->metadata, metadata); egress_pipeline_receive(egress_port, q_pkt->metadata, q_pkt->metadata_recirc, b_pkt->pkt_data, b_pkt->pkt_len, b_pkt->pkt_id, b_pkt->instance_type); free(q_pkt); } return NULL; }
int egress_pipeline_receive(int egress, uint8_t *metadata, int *metadata_recirc, void *pkt, int len, uint64_t packet_id, pkt_instance_type_t instance_type) { pipeline_t *pipeline = egress_pipeline_instances[egress % NB_THREADS_PER_PIPELINE]; egress_pkt_t *e_pkt = malloc(sizeof(egress_pkt_t)); buffered_pkt_t *b_pkt = &e_pkt->pkt; e_pkt->egress = egress; e_pkt->metadata = metadata; e_pkt->metadata_recirc = metadata_recirc; b_pkt->instance_type = instance_type; b_pkt->pkt_data = pkt; b_pkt->pkt_len = len; b_pkt->pkt_id = packet_id; //:: if enable_intrinsic: //:: bytes = 0 //:: for header_instance in ordered_header_instances_non_virtual: //:: h_info = header_info[header_instance] //:: is_metadata = h_info["is_metadata"] //:: if is_metadata: bytes += h_info["byte_width_phv"] //:: #endfor uint8_t extracted_metadata[${bytes}]; metadata_extract(extracted_metadata, metadata, NULL); /* NULL ? */ uint32_t deflect_on_drop = metadata_get_deflect_on_drop(extracted_metadata); if (!deflect_on_drop) { int ret = cb_write(pipeline->cb_in, e_pkt); if (ret == 0) { free(e_pkt); RMT_LOG(P4_LOG_LEVEL_TRACE, "egress_pipeline: dropped a packet from tail\n"); } } else { // For negative mirroring based on Qfull, // Set the deflection_flag in metadata to indicate that this packet // is moving thru' the queuing system only to get delivered to // negative mirror session. // Egress pipeline should act on the deflection_flag and perform // explicit e2e mirroing as appropriate RMT_LOG(P4_LOG_LEVEL_TRACE, "egress_pipeline: deflect tail-dropped packet %p\n", metadata); metadata_set_deflection_flag(extracted_metadata, 1); metadata_set_deflect_on_drop(extracted_metadata, 0); metadata_set_egress_spec(extracted_metadata, 0); metadata_set_egress_port(extracted_metadata, 0); metadata_dump(metadata, extracted_metadata); int ret = cb_write(pipeline->cb_in, e_pkt); if (ret ==0) { free(e_pkt); RMT_LOG(P4_LOG_LEVEL_TRACE, "egress_pipeline: could not enqueue a deflected packet\n"); } } //:: #endif //:: if not enable_intrinsic: int ret = cb_write(pipeline->cb_in, e_pkt); if (ret == 0) { free(e_pkt); RMT_LOG(P4_LOG_LEVEL_TRACE, "egress_pipeline: dropped a packet from tail\n"); } //:: #endif return 0; }