static lagopus_result_t s_parse_bucket_list(struct pbuf *pbuf, struct bucket_list *bucket_list, struct ofp_error *error) { lagopus_result_t res = LAGOPUS_RESULT_OK; if (TAILQ_EMPTY(bucket_list) == true && pbuf_plen_get(pbuf) == 0) { res = LAGOPUS_RESULT_OK; /* bucket_list is empty */ } else { /* decode buckets. */ while (pbuf_plen_get(pbuf) > 0) { res = ofp_bucket_parse(pbuf, bucket_list, error); if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED : ofp_bucket_parse (%s).\n", lagopus_error_get_string(res)); break; } } /* check plen. */ if (res == LAGOPUS_RESULT_OK && pbuf_plen_get(pbuf) > 0) { lagopus_msg_warning("packet decode failed. (size over).\n"); ofp_error_set(error, OFPET_GROUP_MOD_FAILED, OFPGMFC_BAD_BUCKET); res = LAGOPUS_RESULT_OFP_ERROR; } } return res; }
/* header only packet. */ lagopus_result_t ofp_header_create(struct channel *channel, uint8_t type, struct ofp_header *xid_header, struct ofp_header *header, struct pbuf *pbuf) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; uint32_t xid; if (channel != NULL && header != NULL && pbuf != NULL) { if (xid_header != NULL) { xid = xid_header->xid; } else { xid = channel_xid_get(channel); } ofp_header_set(header, channel_version_get(channel), type, (uint16_t) pbuf_plen_get(pbuf), xid); ret = ofp_header_encode(pbuf, header); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
void test_pbuf_info_store_load_normal(void) { struct pbuf *pbuf = pbuf_alloc(PBUF_LENGTH); pbuf_info_t pbuf_info; /* create test data */ pbuf->getp = pbuf->data + 1; pbuf->putp = pbuf->data + 3; pbuf->plen = 2; /* call store func. */ pbuf_info_store(pbuf, &pbuf_info); TEST_ASSERT_EQUAL_MESSAGE(pbuf->data + 1, pbuf_getp_get(&pbuf_info), "getp error."); TEST_ASSERT_EQUAL_MESSAGE(pbuf->data + 3, pbuf_putp_get(&pbuf_info), "putp error."); TEST_ASSERT_EQUAL_MESSAGE(2, pbuf_plen_get(&pbuf_info), "plen error."); /* create test data */ pbuf_reset(pbuf); /* check reset. */ TEST_ASSERT_EQUAL_MESSAGE(pbuf->data, pbuf_getp_get(pbuf), "getp error."); TEST_ASSERT_EQUAL_MESSAGE(pbuf->data, pbuf_putp_get(pbuf), "putp error."); TEST_ASSERT_EQUAL_MESSAGE(0, pbuf_plen_get(pbuf), "plen error."); /* call load func. */ pbuf_info_load(pbuf, &pbuf_info); TEST_ASSERT_EQUAL_MESSAGE(pbuf->data + 1, pbuf_getp_get(pbuf), "getp error."); TEST_ASSERT_EQUAL_MESSAGE(pbuf->data + 3, pbuf_putp_get(pbuf), "putp error."); TEST_ASSERT_EQUAL_MESSAGE(2, pbuf_plen_get(pbuf), "plen error."); /* after. */ pbuf_free(pbuf); }
/* Header only packet receive. */ lagopus_result_t ofp_header_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_error *error) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; struct ofp_header msg; if (channel != NULL && pbuf != NULL && error != NULL) { /* Parse ofp_header. */ ret = ofp_header_decode(pbuf, &msg); if (ret == LAGOPUS_RESULT_OK) { /* Skip payload if it exists. */ if (pbuf_plen_get(pbuf) > 0) { ret = pbuf_forward(pbuf, pbuf_plen_get(pbuf)); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); if (ret == LAGOPUS_RESULT_OUT_OF_RANGE) { ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); ret = LAGOPUS_RESULT_OFP_ERROR; } } } if (ret == LAGOPUS_RESULT_OK && channel_version_get(channel) != msg.version) { lagopus_msg_warning("Unsupported vetsion.\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION); ret = LAGOPUS_RESULT_OFP_ERROR; } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); return LAGOPUS_RESULT_OFP_ERROR; } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
/* Port mod received. */ lagopus_result_t ofp_port_mod_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header, struct ofp_error *error) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; uint64_t dpid; struct ofp_port_mod port_mod; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { /* Parse port_mod header. */ res = ofp_port_mod_decode(pbuf, &(port_mod)); if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("port_mod decode error.\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); res = LAGOPUS_RESULT_OFP_ERROR; } else if (pbuf_plen_get(pbuf) > 0) { lagopus_msg_warning("packet decode failed. (size over).\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); res = LAGOPUS_RESULT_OFP_ERROR; } else { /* decode success */ /* dump trace. */ port_mod_trace(&port_mod); /* check config. */ res = ofp_port_config_check(port_mod.config, error); if (res == LAGOPUS_RESULT_OK) { /* check mask. */ res = ofp_port_config_check(port_mod.mask, error); if (res == LAGOPUS_RESULT_OK) { /* check advertise. */ res = ofp_port_features_check(port_mod.advertise, error); if (res == LAGOPUS_RESULT_OK) { dpid = channel_dpid_get(channel); /* call API */ res = ofp_port_mod_modify(dpid, &port_mod, error); if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } } } } } else { res = LAGOPUS_RESULT_INVALID_ARGS; } return res; }
STATIC lagopus_result_t ofp_role_reply_create(struct channel *channel, struct pbuf **pbuf, struct ofp_header *xid_header, struct ofp_role_request *role_request) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; /* reply is ofp_role_request structure. */ struct ofp_role_request role_reply; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && role_request != NULL) { /* alloc */ *pbuf = channel_pbuf_list_get(channel, sizeof(struct ofp_role_request)); if (*pbuf != NULL) { pbuf_plen_set(*pbuf, sizeof(struct ofp_role_request)); /* Fill in header. */ ofp_header_set(&role_reply.header, channel_version_get(channel), OFPT_ROLE_REPLY, (uint16_t) pbuf_plen_get(*pbuf), xid_header->xid); role_reply.role = role_request->role; memset(role_reply.pad, 0, sizeof(role_request->pad)); role_reply.generation_id = role_request->generation_id; /* Encode message. */ ret = ofp_role_request_encode(*pbuf, &role_reply); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) { channel_pbuf_list_unget(channel, *pbuf); *pbuf = NULL; } } else { lagopus_msg_warning("Can't allocate pbuf.\n"); ret = LAGOPUS_RESULT_NO_MEMORY; } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
STATIC lagopus_result_t ofp_get_async_reply_create(struct channel *channel, struct pbuf **pbuf, struct ofp_header *xid_header) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; struct ofp_async_config async_config; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL) { /* alloc */ *pbuf = channel_pbuf_list_get(channel, sizeof(struct ofp_async_config)); if (*pbuf != NULL) { pbuf_plen_set(*pbuf, sizeof(struct ofp_async_config)); /* Copy packet_in_mask, port_status_mask, flow_removed_mask. */ channel_role_mask_get(channel, &async_config); /* Fill in header. */ ofp_header_set(&async_config.header, channel_version_get(channel), OFPT_GET_ASYNC_REPLY, (uint16_t) pbuf_plen_get(*pbuf), xid_header->xid); /* Encode message. */ ret = ofp_async_config_encode(*pbuf, &async_config); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED : ofp_async_config_encode (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("Can't allocate pbuf.\n"); ret = LAGOPUS_RESULT_NO_MEMORY; } if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) { channel_pbuf_list_unget(channel, *pbuf); *pbuf = NULL; } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
/* Send switch features reply. */ STATIC lagopus_result_t ofp_features_reply_create(struct channel *channel, struct pbuf **pbuf, struct ofp_header *xid_header) { struct ofp_switch_features features; lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; if (channel != NULL && pbuf != NULL && xid_header != NULL) { /* alloc */ *pbuf = channel_pbuf_list_get(channel, sizeof(struct ofp_switch_features)); if (*pbuf != NULL) { pbuf_plen_set(*pbuf, sizeof(struct ofp_switch_features)); ret = features_reply_features_get(channel, &features); if (ret == LAGOPUS_RESULT_OK) { /* Fill in header. */ ofp_header_set(&features.header, channel_version_get(channel), OFPT_FEATURES_REPLY, (uint16_t) pbuf_plen_get(*pbuf), xid_header->xid); /* Encode message. */ ret = ofp_switch_features_encode(*pbuf, &features); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("Can't allocate pbuf.\n"); ret = LAGOPUS_RESULT_NO_MEMORY; } if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) { channel_pbuf_list_unget(channel, *pbuf); *pbuf = NULL; } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
/* Send experimenter reply. */ STATIC lagopus_result_t ofp_experimenter_reply_create(struct channel *channel, struct pbuf **pbuf, struct ofp_header *xid_header, struct ofp_experimenter_header *exper_req) { struct ofp_experimenter_header exper_reply; lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; if (channel != NULL && pbuf != NULL && xid_header != NULL && exper_req != NULL) { *pbuf = NULL; /* alloc */ *pbuf = channel_pbuf_list_get(channel, sizeof(struct ofp_experimenter_header)); if (*pbuf != NULL) { pbuf_plen_set(*pbuf, sizeof(struct ofp_experimenter_header)); exper_reply.experimenter = exper_req->experimenter; exper_reply.exp_type = exper_req->exp_type; /* Fill in header. */ ofp_header_set(&exper_reply.header, channel_version_get(channel), OFPT_EXPERIMENTER, (uint16_t) pbuf_plen_get(*pbuf), xid_header->xid); /* Encode message. */ ret = ofp_experimenter_header_encode(*pbuf, &exper_reply); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("Can't allocate pbuf.\n"); ret = LAGOPUS_RESULT_NO_MEMORY; } if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) { channel_pbuf_list_unget(channel, *pbuf); *pbuf = NULL; } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
static lagopus_result_t s_ofpgc_delete(struct pbuf *pbuf, uint64_t dpid, struct ofp_group_mod *group_mod, struct ofp_error *error) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; /* dump trace. */ group_mod_trace(group_mod, NULL); /* check plen. */ if (pbuf_plen_get(pbuf) == 0) { res = ofp_group_mod_delete(dpid, group_mod, error); } else { lagopus_msg_warning("packet decode failed. (size over).\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); res = LAGOPUS_RESULT_OFP_ERROR; } return res; }
static lagopus_result_t ofp_write_channel(struct channel *channel, struct pbuf *pbuf) { lagopus_result_t ret = LAGOPUS_RESULT_OK; struct pbuf *send_pbuf = NULL; if (channel != NULL && pbuf != NULL) { send_pbuf = channel_pbuf_list_get(channel, pbuf_plen_get(pbuf)); if (send_pbuf != NULL) { /* Copy pbuf. */ ret = pbuf_copy(send_pbuf, pbuf); if (ret == LAGOPUS_RESULT_OK) { ret = ofp_header_packet_set(channel, send_pbuf); if (ret == LAGOPUS_RESULT_OK) { channel_send_packet(channel, send_pbuf); ret = LAGOPUS_RESULT_OK; } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("Can't allocate pbuf.\n"); ret = LAGOPUS_RESULT_NO_MEMORY; } if (ret != LAGOPUS_RESULT_OK && send_pbuf != NULL) { channel_pbuf_list_unget(channel, send_pbuf); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
/* SEND */ STATIC lagopus_result_t ofp_packet_in_create(struct packet_in *packet_in, struct pbuf **pbuf) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; uint16_t miss_send_len; uint16_t length = 0; uint16_t remain_length = 0; uint16_t match_total_len = 0; uint8_t tmp_version = 0x00; uint32_t tmp_xid = 0x00; uint16_t tmp_length = 0; if (packet_in != NULL && packet_in->data != NULL && pbuf != NULL) { /* alloc */ *pbuf = pbuf_alloc(OFP_PACKET_MAX_SIZE); if (*pbuf != NULL) { pbuf_plen_set(*pbuf, OFP_PACKET_MAX_SIZE); /* set total_len. */ ret = pbuf_length_get(packet_in->data, &length); if (ret == LAGOPUS_RESULT_OK) { packet_in->ofp_packet_in.total_len = length; /* Fill in header. */ /* tmp_* is replaced later. */ ofp_header_set(&packet_in->ofp_packet_in.header, tmp_version, OFPT_PACKET_IN, tmp_length, tmp_xid); ret = ofp_packet_in_encode(*pbuf, &packet_in->ofp_packet_in); if (ret == LAGOPUS_RESULT_OK) { ret = ofp_match_list_encode(NULL, *pbuf, &packet_in->match_list, &match_total_len); if (ret == LAGOPUS_RESULT_OK) { /* Cut packet. */ remain_length = (uint16_t) pbuf_plen_get(*pbuf); if (packet_in->ofp_packet_in.buffer_id == OFP_NO_BUFFER) { miss_send_len = remain_length; } else { miss_send_len = packet_in->miss_send_len; } if (length < miss_send_len) { miss_send_len = length; } /* exist data */ if (miss_send_len != 0) { /* add padding */ ret = ofp_padding_add(*pbuf, OFP_PACKET_IN_PAD); if (ret == LAGOPUS_RESULT_OK) { /* Cut packet. (remain_length) */ if (miss_send_len + OFP_PACKET_IN_PAD > remain_length) { miss_send_len = remain_length; } if (pbuf_plen_check(*pbuf, miss_send_len) != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED : over data length.\n"); ret = LAGOPUS_RESULT_OUT_OF_RANGE; } else { /* copy data. */ ret = pbuf_copy_with_length(*pbuf, packet_in->data, miss_send_len); if (ret == LAGOPUS_RESULT_OK) { pbuf_plen_reset(*pbuf); } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } } else { lagopus_msg_warning("FAILED : over padding length.\n"); } } else { ret = LAGOPUS_RESULT_OK; } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("Can't allocate pbuf.\n"); ret = LAGOPUS_RESULT_NO_MEMORY; } /* free. */ if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) { pbuf_free(*pbuf); *pbuf = NULL; } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
lagopus_result_t ofp_header_mp_copy(struct pbuf *dst_pbuf, struct pbuf *src_pbuf) { struct ofp_multipart_reply mp_reply; lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; pbuf_info_t cur_src_pbuf_info; pbuf_info_t cur_dst_pbuf_info; pbuf_info_t update_pbuf_info; uint16_t cur_src_length = 0; if (dst_pbuf != NULL && src_pbuf != NULL) { /* Store current dst/src_pbuf info. */ pbuf_info_store(dst_pbuf, &cur_dst_pbuf_info); pbuf_info_store(src_pbuf, &cur_src_pbuf_info); ret = pbuf_length_get(src_pbuf, &cur_src_length); if (ret == LAGOPUS_RESULT_OK) { /* Update src_pbuf info for ofp_multipart_reply_decode. */ pbuf_getp_set(&update_pbuf_info, pbuf_data_get(src_pbuf)); pbuf_putp_set(&update_pbuf_info, pbuf_data_get(src_pbuf) + sizeof(struct ofp_multipart_reply)); pbuf_plen_set(&update_pbuf_info, sizeof(struct ofp_multipart_reply)); pbuf_info_load(src_pbuf, &update_pbuf_info); ret = ofp_multipart_reply_decode(src_pbuf, &mp_reply); if (ret == LAGOPUS_RESULT_OK) { /* Set length/flag in src_pbuf. */ mp_reply.header.length = cur_src_length; mp_reply.flags = OFPMPF_REPLY_MORE; /* Update src_pbuf info for ofp_multipart_reply_encode. */ pbuf_reset(src_pbuf); pbuf_plen_set(src_pbuf, sizeof(struct ofp_multipart_reply)); ret = ofp_multipart_reply_encode(src_pbuf, &mp_reply); if (ret == LAGOPUS_RESULT_OK) { /* Set length/flag in dst_pbuf. */ mp_reply.header.length = sizeof(struct ofp_multipart_reply); mp_reply.flags = 0; /* Update dst_pbuf info for ofp_multipart_reply_encode. */ pbuf_reset(dst_pbuf); pbuf_plen_set(dst_pbuf, pbuf_plen_get(&cur_dst_pbuf_info)); ret = ofp_multipart_reply_encode(dst_pbuf, &mp_reply); if (ret == LAGOPUS_RESULT_OK) { /* Load pbuf info. */ pbuf_info_load(src_pbuf, &cur_src_pbuf_info); } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
/* FlowMod packet receive. */ lagopus_result_t ofp_flow_mod_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header, struct ofp_error *error) { lagopus_result_t ret; uint64_t dpid; struct ofp_flow_mod flow_mod; struct match_list match_list; struct instruction_list instruction_list; if (channel != NULL && pbuf != NULL && xid_header != NULL) { /* Init lists. */ TAILQ_INIT(&match_list); TAILQ_INIT(&instruction_list); /* Parse flow mod header. */ ret = ofp_flow_mod_decode(pbuf, &flow_mod); if (ret == LAGOPUS_RESULT_OK) { ret = flow_mod_flags_check(flow_mod.flags, error); if (ret == LAGOPUS_RESULT_OK) { /* Parse matches. */ ret = ofp_match_parse(channel, pbuf, &match_list, error); if (ret == LAGOPUS_RESULT_OK) { /* Parse instructions. */ if (flow_mod.command == OFPFC_DELETE || flow_mod.command == OFPFC_DELETE_STRICT) { /* skip pbuf. */ ret = pbuf_forward(pbuf, pbuf_plen_get(pbuf)); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { while (pbuf_plen_get(pbuf) > 0) { ret = ofp_instruction_parse(pbuf, &instruction_list, error); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); break; } } } if (ret == LAGOPUS_RESULT_OK) { /* trace. */ flow_mod_trace(&flow_mod, &match_list, &instruction_list); /* Flow add, modify, delete. */ dpid = channel_dpid_get(channel); switch (flow_mod.command) { case OFPFC_ADD: ret = ofp_flow_mod_check_add(dpid, &flow_mod, &match_list, &instruction_list, error); break; case OFPFC_MODIFY: case OFPFC_MODIFY_STRICT: ret = ofp_flow_mod_modify(dpid, &flow_mod, &match_list, &instruction_list, error); break; case OFPFC_DELETE: case OFPFC_DELETE_STRICT: ret = ofp_flow_mod_delete(dpid, &flow_mod, &match_list, error); break; default: ofp_error_set(error, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_COMMAND); ret = LAGOPUS_RESULT_OFP_ERROR; break; } if (ret == LAGOPUS_RESULT_OFP_ERROR) { lagopus_msg_warning("OFP ERROR (%s).\n", lagopus_error_get_string(ret)); } } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); ret = LAGOPUS_RESULT_OFP_ERROR; ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); } /* free. */ if (ret != LAGOPUS_RESULT_OK) { ofp_instruction_list_elem_free(&instruction_list); ofp_match_list_elem_free(&match_list); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }