static ofl_err ofl_msg_unpack_flow_mod(struct ofp_header *src, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp) { struct ofp_flow_mod *sm; struct ofl_msg_flow_mod *dm; struct ofp_instruction *inst; ofl_err error; size_t i; if (*len < (sizeof(struct ofp_flow_mod) - sizeof(struct ofp_match))) { OFL_LOG_WARN(LOG_MODULE, "Received FLOW_MOD message has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } *len -= (sizeof(struct ofp_flow_mod) - sizeof(struct ofp_match)); sm = (struct ofp_flow_mod *)src; dm = (struct ofl_msg_flow_mod *)malloc(sizeof(struct ofl_msg_flow_mod)); dm->cookie = ntoh64(sm->cookie); dm->cookie_mask = ntoh64(sm->cookie_mask); dm->table_id = sm->table_id; dm->command = (enum ofp_flow_mod_command)sm->command; dm->idle_timeout = ntohs( sm->idle_timeout); dm->hard_timeout = ntohs( sm->hard_timeout); dm->priority = ntohs( sm->priority); dm->buffer_id = ntohl( sm->buffer_id); dm->out_port = ntohl( sm->out_port); dm->out_group = ntohl( sm->out_group); dm->flags = ntohs( sm->flags); error = ofl_structs_match_unpack(&(sm->match), len, &(dm->match), exp); if (error) { free(dm); return error; } error = ofl_utils_count_ofp_instructions(&(sm->instructions), *len, &dm->instructions_num); if (error) { ofl_structs_free_match(dm->match, exp); free(dm); return error; } dm->instructions = (struct ofl_instruction_header **)malloc(dm->instructions_num * sizeof(struct ofl_instruction_header *)); inst = sm->instructions; for (i = 0; i < dm->instructions_num; i++) { error = ofl_structs_instructions_unpack(inst, len, &(dm->instructions[i]), exp); if (error) { OFL_UTILS_FREE_ARR_FUN2(dm->instructions, i, ofl_structs_free_instruction, exp); ofl_structs_free_match(dm->match, exp); free(dm); return error; } inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len)); } *msg = (struct ofl_msg_header *)dm; return 0; }
/* Sends a packet to the controller in a packet_in message */ static void send_packet_to_controller(struct pipeline *pl, struct packet *pkt, uint8_t table_id, uint8_t reason) { struct ofl_msg_packet_in msg; struct ofl_match *m; msg.header.type = OFPT_PACKET_IN; msg.total_len = pkt->buffer->size; msg.reason = reason; msg.table_id = table_id; msg.cookie = 0xffffffffffffffff; msg.data = pkt->buffer->data; /* A max_len of OFPCML_NO_BUFFER means that the complete packet should be sent, and it should not be buffered.*/ if (pl->dp->config.miss_send_len != OFPCML_NO_BUFFER){ dp_buffers_save(pl->dp->buffers, pkt); msg.buffer_id = pkt->buffer_id; msg.data_length = MIN(pl->dp->config.miss_send_len, pkt->buffer->size); }else { msg.buffer_id = OFP_NO_BUFFER; msg.data_length = pkt->buffer->size; } m = xmalloc (sizeof(struct ofl_match)); ofl_structs_match_init(m); /* In this implementation the fields in_port and in_phy_port always will be the same, because we are not considering logical ports */ ofl_structs_match_convert_pktf2oflm(&pkt->handle_std->match.match_fields, m); msg.match = (struct ofl_match_header*)m; dp_send_message(pl->dp, (struct ofl_msg_header *)&msg, NULL); ofl_structs_free_match((struct ofl_match_header* ) m, NULL); }
static int ofl_msg_free_stats_request(struct ofl_msg_stats_request_header *msg, struct ofl_exp *exp, char *errbuf) { switch (msg->type) { case OFPST_DESC: { break; } case OFPST_FLOW: case OFPST_AGGREGATE: { ofl_structs_free_match(((struct ofl_msg_stats_request_flow *)msg)->match, exp, errbuf); //TODO error break; } case OFPST_TABLE: case OFPST_PORT: case OFPST_QUEUE: case OFPST_GROUP: case OFPST_GROUP_DESC: break; case OFPST_EXPERIMENTER: { if (exp == NULL || exp->stats == NULL || exp->stats->req_free == NULL) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Trying to free EXPERIMENTER stats request, but no callback was given."); } free(msg); return -1; } exp->stats->req_free(msg); return 0; } default: return -1; } free(msg); return 0; }
int ofl_msg_free_flow_mod(struct ofl_msg_flow_mod *msg, bool with_match, bool with_instructions, struct ofl_exp *exp) { if (with_match) { ofl_structs_free_match(msg->match, exp); } if (with_instructions) { OFL_UTILS_FREE_ARR_FUN2(msg->instructions, msg->instructions_num, ofl_structs_free_instruction, exp); } free(msg); return 0; }
int ofl_msg_free_flow_mod(struct ofl_msg_flow_mod *msg, bool with_match, bool with_instructions, struct ofl_exp *exp, char *errbuf) { if (with_match) { ofl_structs_free_match(msg->match, exp, errbuf); //TODO error } if (with_instructions) { OFL_UTILS_FREE_ARR_FUN3(msg->instructions, msg->instructions_num, ofl_structs_free_instruction, exp, errbuf); //TODO error } free(msg); return 0; }
static int ofl_msg_free_multipart_request(struct ofl_msg_multipart_request_header *msg, struct ofl_exp *exp) { switch (msg->type) { case OFPMP_DESC: { break; } case OFPMP_FLOW: case OFPMP_AGGREGATE: { ofl_structs_free_match(((struct ofl_msg_multipart_request_flow *)msg)->match, exp); break; } case OFPMP_TABLE: case OFPMP_PORT_STATS : case OFPMP_QUEUE: case OFPMP_GROUP: case OFPMP_GROUP_DESC: case OFPMP_GROUP_FEATURES: case OFPMP_METER: case OFPMP_METER_CONFIG: case OFPMP_METER_FEATURES: break; case OFPMP_TABLE_FEATURES:{ struct ofl_msg_multipart_request_table_features *m = (struct ofl_msg_multipart_request_table_features *)msg; OFL_UTILS_FREE_ARR_FUN2(m->table_features, m->tables_num, ofl_structs_free_table_features, exp); break; } case OFPMP_PORT_DESC: break; case OFPMP_EXPERIMENTER: { if (exp == NULL || exp->stats == NULL || exp->stats->req_free == NULL) { OFL_LOG_WARN(LOG_MODULE, "Trying to free EXPERIMENTER stats request, but no callback was given."); break; } exp->stats->req_free(msg); return 0; } default: return -1; } free(msg); return 0; }
ofl_err ofl_structs_flow_stats_unpack(struct ofp_flow_stats *src, size_t *len, struct ofl_flow_stats **dst, struct ofl_exp *exp, char *errbuf) { struct ofl_flow_stats *s; struct ofp_instruction *inst; ofl_err error; size_t slen; size_t i; if (*len < (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match))) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received flow stats has invalid length (%zu).", *len); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } if (*len < ntohs(src->length)) { if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "Received flow stats reply has invalid length (set to %u, but only %zu received).", ntohs(src->length), *len); } return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (src->table_id == 0xff) { if (errbuf != NULL) { char *ts = ofl_table_to_string(src->table_id); snprintf(errbuf, OFL_ERRBUF_SIZE, "Received flow stats has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_ACTION, OFPBRC_BAD_LEN); } slen = ntohs(src->length) - (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match)); s = (struct ofl_flow_stats *)malloc(sizeof(struct ofl_flow_stats)); s->table_id = src->table_id; s->duration_sec = ntohl( src->duration_sec); s->duration_nsec = ntohl( src->duration_nsec); s->priority = ntohs( src->priority); s->idle_timeout = ntohs( src->idle_timeout); s->hard_timeout = ntohs( src->hard_timeout); s->cookie = ntoh64(src->cookie); s->packet_count = ntoh64(src->packet_count); s->byte_count = ntoh64(src->byte_count); error = ofl_structs_match_unpack(&(src->match), &slen, &(s->match), exp, errbuf); if (error) { free(s); return error; } error = ofl_utils_count_ofp_instructions(src->instructions, slen, &s->instructions_num, errbuf); if (error) { ofl_structs_free_match(s->match, exp, NULL); free(s); return error; } s->instructions = (struct ofl_instruction_header **)malloc(s->instructions_num * sizeof(struct ofl_instruction_header *)); inst = src->instructions; for (i = 0; i < s->instructions_num; i++) { error = ofl_structs_instructions_unpack(inst, &slen, &(s->instructions[i]), exp, errbuf); if (error) { OFL_UTILS_FREE_ARR_FUN3(s->instructions, i, ofl_structs_free_instruction, exp, errbuf); free(s); return error; } inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len)); } if (slen != 0) { *len = *len - ntohs(src->length) + slen; if (errbuf != NULL) { snprintf(errbuf, OFL_ERRBUF_SIZE, "The received flow stats contained extra bytes (%zu).", slen); } ofl_structs_free_flow_stats(s, exp, errbuf); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->length); *dst = s; return 0; }
ofl_err ofl_structs_flow_stats_unpack(struct ofp_flow_stats *src, uint8_t *buf, size_t *len, struct ofl_flow_stats **dst, struct ofl_exp *exp) { struct ofl_flow_stats *s; struct ofp_instruction *inst; ofl_err error; size_t slen; size_t i; int match_pos; if (*len < ( (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match)) + ROUND_UP(ntohs(src->match.length),8))) { OFL_LOG_WARN(LOG_MODULE, "Received flow stats has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (*len < ntohs(src->length)) { OFL_LOG_WARN(LOG_MODULE, "Received flow stats reply has invalid length (set to %u, but only %zu received).", ntohs(src->length), *len); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } if (src->table_id >= PIPELINE_TABLES) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *ts = ofl_table_to_string(src->table_id); OFL_LOG_WARN(LOG_MODULE, "Received flow stats has invalid table_id (%s).", ts); free(ts); } return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_TABLE_ID); } slen = ntohs(src->length) - (sizeof(struct ofp_flow_stats) - sizeof(struct ofp_match)); s = (struct ofl_flow_stats *)malloc(sizeof(struct ofl_flow_stats)); s->table_id = src->table_id; s->duration_sec = ntohl( src->duration_sec); s->duration_nsec = ntohl( src->duration_nsec); s->priority = ntohs( src->priority); s->idle_timeout = ntohs( src->idle_timeout); s->hard_timeout = ntohs( src->hard_timeout); s->cookie = ntoh64(src->cookie); s->packet_count = ntoh64(src->packet_count); s->byte_count = ntoh64(src->byte_count); match_pos = sizeof(struct ofp_flow_stats) - 4; error = ofl_structs_match_unpack(&(src->match),buf + match_pos , &slen, &(s->match), exp); if (error) { free(s); return error; } error = ofl_utils_count_ofp_instructions((struct ofp_instruction *) (buf + ROUND_UP(match_pos + s->match->length,8)), slen, &s->instructions_num); if (error) { ofl_structs_free_match(s->match, exp); free(s); return error; } s->instructions = (struct ofl_instruction_header **)malloc(s->instructions_num * sizeof(struct ofl_instruction_header *)); inst = (struct ofp_instruction *) (buf + ROUND_UP(match_pos + s->match->length,8)); for (i = 0; i < s->instructions_num; i++) { error = ofl_structs_instructions_unpack(inst, &slen, &(s->instructions[i]), exp); if (error) { OFL_UTILS_FREE_ARR_FUN2(s->instructions, i, ofl_structs_free_instruction, exp); free(s); return error; } inst = (struct ofp_instruction *)((uint8_t *)inst + ntohs(inst->len)); } if (slen != 0) { *len = *len - ntohs(src->length) + slen; OFL_LOG_WARN(LOG_MODULE, "The received flow stats contained extra bytes (%zu).", slen); ofl_structs_free_flow_stats(s, exp); return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } *len -= ntohs(src->length); *dst = s; return 0; }
int ofl_msg_free(struct ofl_msg_header *msg, struct ofl_exp *exp) { switch (msg->type) { case OFPT_HELLO: { break; } case OFPT_ERROR: { return ofl_msg_free_error((struct ofl_msg_error *)msg); } case OFPT_ECHO_REQUEST: case OFPT_ECHO_REPLY: { free(((struct ofl_msg_echo *)msg)->data); break; } case OFPT_EXPERIMENTER: { if (exp == NULL || exp->msg == NULL || exp->msg->free == NULL) { OFL_LOG_WARN(LOG_MODULE, "Trying to free EXPERIMENTER message, but no callback was given"); break; } exp->msg->free((struct ofl_msg_experimenter *)msg); return 0; } case OFPT_FEATURES_REQUEST: { break; } case OFPT_FEATURES_REPLY: { break; } case OFPT_GET_CONFIG_REQUEST: { break; } case OFPT_GET_CONFIG_REPLY: { free(((struct ofl_msg_get_config_reply *)msg)->config); break; } case OFPT_SET_CONFIG: { free(((struct ofl_msg_set_config *)msg)->config); break; } case OFPT_PACKET_IN: { ofl_structs_free_match(((struct ofl_msg_packet_in *)msg)->match,NULL); free(((struct ofl_msg_packet_in *)msg)->data); break; } case OFPT_FLOW_REMOVED: { return ofl_msg_free_flow_removed((struct ofl_msg_flow_removed *)msg, true, exp); break; } case OFPT_PORT_STATUS: { free(((struct ofl_msg_port_status *)msg)->desc); break; } case OFPT_PACKET_OUT: { return ofl_msg_free_packet_out((struct ofl_msg_packet_out *)msg, true, exp); } case OFPT_FLOW_MOD: { return ofl_msg_free_flow_mod((struct ofl_msg_flow_mod *)msg, true, true, exp); } case OFPT_GROUP_MOD: { return ofl_msg_free_group_mod((struct ofl_msg_group_mod *)msg, true, exp); } case OFPT_PORT_MOD: case OFPT_TABLE_MOD: { break; } case OFPT_MULTIPART_REQUEST: { return ofl_msg_free_multipart_request((struct ofl_msg_multipart_request_header *)msg, exp); } case OFPT_MULTIPART_REPLY: { return ofl_msg_free_multipart_reply((struct ofl_msg_multipart_reply_header *)msg, exp); } case OFPT_BARRIER_REQUEST: case OFPT_BARRIER_REPLY: case OFPT_QUEUE_GET_CONFIG_REQUEST: { break; } case OFPT_ROLE_REPLY: case OFPT_ROLE_REQUEST:{ break; } case OFPT_GET_ASYNC_REPLY: case OFPT_SET_ASYNC: case OFPT_GET_ASYNC_REQUEST:{ break; } case OFPT_METER_MOD:{ return ofl_msg_free_meter_mod((struct ofl_msg_meter_mod*)msg, true); } case OFPT_QUEUE_GET_CONFIG_REPLY: { struct ofl_msg_queue_get_config_reply *mod = (struct ofl_msg_queue_get_config_reply *)msg; OFL_UTILS_FREE_ARR_FUN(mod->queues, mod->queues_num, ofl_structs_free_packet_queue); break; } } free(msg); return 0; }