void test_ofp_instruction_list_elem_free(void) { lagopus_result_t ret; struct pbuf *test_pbuf; struct instruction_list instruction_list; struct ofp_error error; /* instruction packet. */ char nomal_data[] = "00 03 00 18 00 00 00 00" "00 00 00 10 00 00 01 00 00 30 00 00 00 00 00 00"; /* data */ TAILQ_INIT(&instruction_list); create_packet(nomal_data, &test_pbuf); ret = ofp_instruction_parse(test_pbuf, &instruction_list, &error); TEST_ASSERT_EQUAL_MESSAGE(ret, LAGOPUS_RESULT_OK, "ofp_instruction_parse(nomal) error."); TEST_ASSERT_EQUAL_MESSAGE(TAILQ_EMPTY(&instruction_list), false, "not instruction list error."); /* call func. */ ofp_instruction_list_elem_free(&instruction_list); TEST_ASSERT_EQUAL_MESSAGE(TAILQ_EMPTY(&instruction_list), true, "instruction list error."); }
/* 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; }