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; }
/* * NAME: cmdbuf->substitute() * DESCRIPTION: do substitutions on a range of lines */ int cb_subst(cmdbuf *cb) { char buf[MAX_LINE_SIZE], delim; Int m[26]; Int edit; const char *p; Int *k, *l; delim = cb->cmd[0]; if (delim == '\0' || strchr("0123456789gpl#-+", delim) != (char*) NULL) { /* no search pattern & replace string specified */ if (cb->search[0] == '\0') { error("No previous substitute to repeat"); } } else if (!isalpha(delim)) { char *q; /* get search pattern */ p = pattern(cb->cmd + 1, delim, cb->search); /* get replace string */ q = cb->replace; while (*p != '\0') { if (*p == delim) { p++; break; } if (q == cb->replace + STRINGSZ - 1) { cb->search[0] = '\0'; error("Replace string too large"); } if ((*q++ = *p++) == '\\' && *p != '\0') { *q++ = *p++; } } *q = '\0'; cb->cmd = p; } else { /* cause error */ cb->search[0] = '\0'; } if (cb->search[0] == '\0') { error("Missing regular expression for substitute"); } /* compile regexp */ p = rx_comp(cb->regexp, cb->search); if (p != (char *) NULL) { error(p); } cb_count(cb); /* get count */ /* handle global flag */ if (cb->cmd[0] == 'g') { cb->flags |= CB_GLOBSUBST; cb->cmd++; } else { cb->flags &= ~CB_GLOBSUBST; } /* make a blank mark table */ cb->moffset = m; for (l = m; l < &m[26]; ) { *l++ = 0; } cb->offset = 0; /* do substitutions */ cb_do(cb, cb->first); cb->lineno = cb->first; edit = cb->edit; cb->buffer = buf; cb->buflen = 0; cb->flags &= ~(CB_CURRENTBLK | CB_SKIPPED); eb_range(cb->edbuf, cb->first, cb->last, subst, FALSE); if (cb->flags & CB_CURRENTBLK) { /* finish current block, if needed */ endblock(cb); } cb->othis = cb->uthis; if (edit != cb->edit) { /* some marks may have been messed up. fix them */ for (l = m, k = cb->mark; l < &m[26]; l++, k++) { if (*l != 0) { *k = *l; } } } else if (!(cb->flags & CB_GLOBAL)) { error("Substitute pattern match failed"); } return RET_FLAGS; }
int egress_pipeline_count(int egress) { pipeline_t *pipeline = egress_pipeline_instances[egress % NB_THREADS_PER_PIPELINE]; return cb_count(pipeline->cb_in); }