/* Execute a group entry of type FAILFAST. */ static void execute_ff(struct group_entry *entry, struct packet *pkt) { size_t b = select_from_ff_group(entry); if (b != -1) { struct ofl_bucket *bucket = entry->desc->buckets[b]; struct packet *p = packet_clone(pkt); if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) { char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp); VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b); free(b); } action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions); entry->stats->byte_count += p->buffer->size; entry->stats->packet_count++; entry->stats->counters[b]->byte_count += p->buffer->size; entry->stats->counters[b]->packet_count++; /* Cookie field is set 0xffffffffffffffff because we cannot associate to any particular flow */ action_set_execute(p->action_set, p, 0xffffffffffffffff); packet_destroy(p); } else { VLOG_DBG_RL(LOG_MODULE, &rl, "No bucket in group."); } }
/* Executes a group entry of type ALL. */ static void execute_all(struct group_entry *entry, struct packet *pkt) { size_t i; /* TODO Zoltan: Currently packets are always cloned. However it should * be possible to see if cloning is necessary, or not, based on bucket actions. */ for (i=0; i<entry->desc->buckets_num; i++) { struct ofl_bucket *bucket = entry->desc->buckets[i]; struct packet *p = packet_clone(pkt); if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) { char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp); VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b); free(b); } action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions); entry->stats->byte_count += p->buffer->size; entry->stats->packet_count++; entry->stats->counters[i]->byte_count += p->buffer->size; entry->stats->counters[i]->packet_count++; /* Cookie field is set 0xffffffffffffffff because we cannot associate to any particular flow */ action_set_execute(p->action_set, p, 0xffffffffffffffff); packet_destroy(p); } }
/* Execute a group entry of type INDIRECT. */ static void execute_indirect(struct group_entry *entry, struct packet *pkt) { if (entry->desc->buckets_num > 0) { struct ofl_bucket *bucket = entry->desc->buckets[0]; struct packet *p = packet_clone(pkt); if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) { char *b = ofl_structs_bucket_to_string(bucket, entry->dp->exp); VLOG_DBG_RL(LOG_MODULE, &rl, "Writing bucket: %s.", b); free(b); } action_set_write_actions(p->action_set, bucket->actions_num, bucket->actions); entry->stats->byte_count += p->buffer->size; entry->stats->packet_count++; entry->stats->counters[0]->byte_count += p->buffer->size; entry->stats->counters[0]->packet_count++; action_set_execute(p->action_set, p); packet_destroy(p); } else { VLOG_DBG_RL(LOG_MODULE, &rl, "No bucket in group."); } }
void pipeline_process_packet(struct pipeline *pl, struct packet *pkt) { struct flow_table *table, *next_table; if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) { char *pkt_str = packet_to_string(pkt); VLOG_DBG_RL(LOG_MODULE, &rl, "processing packet: %s", pkt_str); free(pkt_str); } if (!packet_handle_std_is_ttl_valid(pkt->handle_std)) { if ((pl->dp->config.flags & OFPC_INVALID_TTL_TO_CONTROLLER) != 0) { VLOG_DBG_RL(LOG_MODULE, &rl, "Packet has invalid TTL, sending to controller."); send_packet_to_controller(pl, pkt, 0/*table_id*/, OFPR_INVALID_TTL); } else { VLOG_DBG_RL(LOG_MODULE, &rl, "Packet has invalid TTL, dropping."); } packet_destroy(pkt); return; } next_table = pl->tables[0]; while (next_table != NULL) { struct flow_entry *entry; VLOG_DBG_RL(LOG_MODULE, &rl, "trying table %u.", next_table->stats->table_id); pkt->table_id = next_table->stats->table_id; table = next_table; next_table = NULL; entry = flow_table_lookup(table, pkt); if (entry != NULL) { if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) { char *m = ofl_structs_flow_stats_to_string(entry->stats, pkt->dp->exp); VLOG_DBG_RL(LOG_MODULE, &rl, "found matching entry: %s.", m); free(m); } execute_entry(pl, entry, &next_table, &pkt); /* Packet could be destroyed by a meter instruction */ if (!pkt) return; if (next_table == NULL) { /* Cookie field is set 0xffffffffffffffff because we cannot associate it to any particular flow */ action_set_execute(pkt->action_set, pkt, 0xffffffffffffffff); packet_destroy(pkt); return; } } else { /* OpenFlow 1.3 default behavior on a table miss */ VLOG_DBG_RL(LOG_MODULE, &rl, "No matching entry found. Dropping packet."); packet_destroy(pkt); return; } } VLOG_WARN_RL(LOG_MODULE, &rl, "Reached outside of pipeline processing cycle."); }