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;
}
Exemple #3
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;
}