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; }
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); if(NULL != get_mirroring_mapping(mirror_id)) { uint8_t *metadata; deparser_produce_metadata(phv, &metadata); 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 *processing_loop_egress(void *arg) { pipeline_t *pipeline = (pipeline_t *) arg; circular_buffer_t *cb_in = pipeline->cb_in; //Added by Ming #ifdef SWITCH_CPU_DEBUG int i; #endif #ifdef RATE_LIMITING struct timeval tv; gettimeofday(&tv, NULL); uint64_t next_deque = tv.tv_sec * 1000000 + tv.tv_usec + read_atomic_int(&USEC_INTERVAL); #endif while(1) { #ifdef RATE_LIMITING struct timeval tv; gettimeofday(&tv, NULL); uint64_t now_us = tv.tv_sec * 1000000 + tv.tv_usec; //RMT_LOG(P4_LOG_LEVEL_TRACE, "next_deque %lu, now_us %lu\n", next_deque, now_us); if(next_deque > now_us) { usleep(next_deque - now_us); } next_deque += read_atomic_int(&USEC_INTERVAL); #endif egress_pkt_t *e_pkt = (egress_pkt_t *) cb_read(cb_in); if (e_pkt == NULL) continue; buffered_pkt_t *b_pkt = &e_pkt->pkt; RMT_LOG(P4_LOG_LEVEL_TRACE, "egress_pipeline: packet dequeued\n"); phv_clean(pipeline->phv); pipeline->phv->packet_id = b_pkt->pkt_id; parser_parse_pkt(pipeline->phv, b_pkt->pkt_data, b_pkt->pkt_len, pipeline->parse_state_start); parser_parse_metadata(pipeline->phv, e_pkt->metadata, e_pkt->metadata_recirc); assert(!fields_get_clone_spec(pipeline->phv)); //:: if enable_intrinsic: /* Set dequeue metadata */ fields_set_deq_qdepth(pipeline->phv, cb_count(cb_in)); uint64_t enq_timestamp = fields_get_enq_timestamp(pipeline->phv); fields_set_deq_timedelta(pipeline->phv, get_timestamp()-enq_timestamp); //:: #endif fields_set_instance_type(pipeline->phv, e_pkt->pkt.instance_type); free(e_pkt->metadata); free(e_pkt->metadata_recirc); if(pipeline->table_entry_fn) /* empty egress pipeline ? */ pipeline->table_entry_fn(pipeline->phv); uint8_t *pkt_data; int pkt_len; /* EGRESS MIRRORING */ if(fields_get_clone_spec(pipeline->phv)) { RMT_LOG(P4_LOG_LEVEL_VERBOSE, "Egress mirroring\n"); pipeline->deparse_fn(pipeline->phv, &pkt_data, &pkt_len); egress_cloning(pipeline, pkt_data, pkt_len, e_pkt->pkt.pkt_id); fields_set_clone_spec(pipeline->phv, 0); } update_checksums(pipeline->phv); pipeline->deparse_fn(pipeline->phv, &pkt_data, &pkt_len); free(b_pkt->pkt_data); //:: if "egress_drop_ctl" in extra_metadata_name_map: // program uses the separate egress_drop_ctl register // a non-zero value means drop if(pipeline->phv->deparser_drop_signal || metadata_get_egress_drop_ctl(metadata)) { //:: else: if(pipeline->phv->deparser_drop_signal){ //:: #endif RMT_LOG(P4_LOG_LEVEL_VERBOSE, "dropping packet at egress\n"); free(e_pkt); continue; } int egress = fields_get_egress_port(pipeline->phv); if(pipeline->phv->truncated_length && (pipeline->phv->truncated_length < pkt_len)) pkt_len = pipeline->phv->truncated_length; #ifdef SWITCH_CPU_DEBUG RMT_LOG(P4_LOG_LEVEL_TRACE, "Ming Packet Data: %d\n", b_pkt->pkt_len); for (i = 0; i < 21; i++) RMT_LOG(P4_LOG_LEVEL_TRACE, "%x ", b_pkt->pkt_data[i]); RMT_LOG(P4_LOG_LEVEL_TRACE, "\n"); #endif pkt_manager_transmit(egress, pkt_data, pkt_len, b_pkt->pkt_id); free(e_pkt); } return NULL; } /* name has to be ingress or egress */ pipeline_t *pipeline_create(int id) { pipeline_t *pipeline = malloc(sizeof(pipeline_t)); pipeline->name = "egress"; #ifdef RATE_LIMITING pipeline->cb_in = cb_init(read_atomic_int(&EGRESS_CB_SIZE), CB_WRITE_DROP, CB_READ_RETURN); #else pipeline->cb_in = cb_init(read_atomic_int(&EGRESS_CB_SIZE), CB_WRITE_BLOCK, CB_READ_BLOCK); #endif pipeline->parse_state_start = parse_state_start; //:: if egress_entry_table is not None: pipeline->table_entry_fn = tables_apply_${egress_entry_table}; //:: else: pipeline->table_entry_fn = NULL; //:: #endif pipeline->deparse_fn = deparser_produce_pkt; pipeline->phv = phv_init(NB_THREADS_PER_PIPELINE + id, RMT_PIPELINE_EGRESS); /* packet processing loop */ pthread_create(&pipeline->processing_thread, NULL, processing_loop_egress, (void *) pipeline); return pipeline; }