lagopus_result_t ofp_header_packet_set(struct channel *channel, struct pbuf *pbuf) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; uint16_t cur_length; pbuf_info_t cur_pbuf_info; pbuf_info_t update_pbuf_info; struct ofp_header header; if (channel != NULL && pbuf != NULL) { /* Store current pbuf info. */ pbuf_info_store(pbuf, &cur_pbuf_info); ret = pbuf_length_get(pbuf, &cur_length); if (ret == LAGOPUS_RESULT_OK) { /* Update pbuf info for ofp_header_decode_sneak. */ pbuf_getp_set(&update_pbuf_info, pbuf_data_get(pbuf)); pbuf_putp_set(&update_pbuf_info, pbuf_data_get(pbuf) + sizeof(struct ofp_header)); pbuf_plen_set(&update_pbuf_info, sizeof(struct ofp_header)); pbuf_info_load(pbuf, &update_pbuf_info); ret = ofp_header_decode_sneak(pbuf, &header); if (ret == LAGOPUS_RESULT_OK) { /* Update pbuf info for ofp_header_create. */ pbuf_reset(pbuf); pbuf_plen_set(pbuf, (size_t) cur_length); ret = ofp_header_create(channel, header.type, NULL, &header, pbuf); if (ret == LAGOPUS_RESULT_OK) { /* Load pbuf info. */ pbuf_info_load(pbuf, &cur_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 { return LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
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; uint16_t len = 0; if (channel != NULL && pbuf != NULL) { ret = pbuf_length_get(pbuf, &len); if (ret == LAGOPUS_RESULT_OK) { send_pbuf = channel_pbuf_list_get(channel, (size_t) len); 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; } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } if (ret != LAGOPUS_RESULT_OK && send_pbuf != NULL) { channel_pbuf_list_unget(channel, send_pbuf); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
void test_pbuf_length_get_bad_pointer(void) { struct pbuf *pbuf = pbuf_alloc(PBUF_LENGTH); lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; uint16_t length = 0; /* create test data. */ pbuf->putp = pbuf->getp - 1; /* call func. */ ret = pbuf_length_get(pbuf, &length); TEST_ASSERT_EQUAL_MESSAGE(LAGOPUS_RESULT_OUT_OF_RANGE, ret, "pbuf_length_get error."); TEST_ASSERT_EQUAL_MESSAGE(0, length, "pbuf length error."); pbuf_free(pbuf); }
/* 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; }
/* Send experimenter multipart reply. */ STATIC lagopus_result_t ofp_experimenter_mp_reply_create( struct channel *channel, struct pbuf_list **pbuf_list, struct ofp_header *xid_header, struct ofp_experimenter_multipart_header *exper_req) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; uint16_t tmp_length = 0; uint16_t length = 0; struct ofp_multipart_reply mp_reply; struct pbuf *pbuf = NULL; struct ofp_experimenter_multipart_header exper_reply; if (channel != NULL && pbuf_list != NULL && xid_header != NULL && exper_req != NULL) { /* alloc */ *pbuf_list = pbuf_list_alloc(); if (*pbuf_list != NULL) { pbuf = pbuf_list_last_get(*pbuf_list); if (pbuf != NULL) { pbuf_plen_set(pbuf, pbuf_size_get(pbuf)); /* Fill in header. */ memset(&mp_reply, 0, sizeof(mp_reply)); ofp_header_set(&mp_reply.header, channel_version_get(channel), OFPT_MULTIPART_REPLY, tmp_length, xid_header->xid); mp_reply.type = OFPMP_EXPERIMENTER; mp_reply.flags = 0; /* Encode multipart reply. */ ret = ofp_multipart_reply_encode(pbuf, &mp_reply); if (ret == LAGOPUS_RESULT_OK) { exper_reply.experimenter = exper_req->experimenter; exper_reply.exp_type = exper_req->exp_type; /* Encode message. */ ret = ofp_experimenter_multipart_header_encode( pbuf, &exper_reply); if (ret == LAGOPUS_RESULT_OK) { /* set length for last pbuf. */ ret = pbuf_length_get(pbuf, &length); if (ret == LAGOPUS_RESULT_OK) { ret = ofp_header_length_set(pbuf, length); if (ret == LAGOPUS_RESULT_OK) { pbuf_plen_reset(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("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; } } else { lagopus_msg_warning("Can't allocate pbuf_list.\n"); ret = LAGOPUS_RESULT_NO_MEMORY; } if (ret != LAGOPUS_RESULT_OK && *pbuf_list != NULL) { pbuf_list_free(*pbuf_list); *pbuf_list = NULL; } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
/* Packetout packet receive. */ lagopus_result_t ofp_packet_out_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header, struct ofp_error *error) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; struct eventq_data *eventq_data = NULL; struct pbuf *data_pbuf = NULL; struct pbuf *req_pbuf = NULL; uint64_t dpid; uint16_t data_len = 0; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { dpid = channel_dpid_get(channel); /* create packet_out */ eventq_data = malloc(sizeof(*eventq_data)); if (eventq_data != NULL) { memset(eventq_data, 0, sizeof(*eventq_data)); /* Init action-list. */ TAILQ_INIT(&eventq_data->packet_out.action_list); eventq_data->packet_out.data = NULL; eventq_data->packet_out.req = NULL; /* decode. */ if ((res = ofp_packet_out_decode( pbuf, &(eventq_data->packet_out.ofp_packet_out))) != LAGOPUS_RESULT_OK) { lagopus_msg_warning("packet_out decode error.\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); res = LAGOPUS_RESULT_OFP_ERROR; } else if ((res = ofp_action_parse( pbuf, eventq_data->packet_out.ofp_packet_out.actions_len, &(eventq_data->packet_out.action_list), error)) != LAGOPUS_RESULT_OK) { lagopus_msg_warning("action_list decode error.\n"); } else { /* decode success */ /* set eventq_data members */ eventq_data->type = LAGOPUS_EVENTQ_PACKET_OUT; eventq_data->free = ofp_packet_out_free; eventq_data->packet_out.channel_id = channel_id_get(channel); /* copy packet_out.data if needed */ res = pbuf_length_get(pbuf, &data_len); if (res == LAGOPUS_RESULT_OK) { if (data_len != 0) { if (eventq_data->packet_out.ofp_packet_out.buffer_id == OFP_NO_BUFFER) { /* alloc packet_out.data */ data_pbuf = pbuf_alloc(data_len); if (data_pbuf != NULL) { res = pbuf_copy_with_length(data_pbuf, pbuf, data_len); if (res == LAGOPUS_RESULT_OK) { eventq_data->packet_out.data = data_pbuf; } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("Can't allocate data_pbuf.\n"); res = LAGOPUS_RESULT_NO_MEMORY; } } else { lagopus_msg_warning("Not empty data filed in request(buffer_id = %x).\n", eventq_data->packet_out.ofp_packet_out.buffer_id); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BUFFER_UNKNOWN); res = LAGOPUS_RESULT_OFP_ERROR; } } else { res = LAGOPUS_RESULT_OK; } /* Copy request for ofp_error. */ if (res == LAGOPUS_RESULT_OK && error->req != NULL) { req_pbuf = pbuf_alloc(OFP_ERROR_MAX_SIZE); if (req_pbuf != NULL) { res = pbuf_copy(req_pbuf, error->req); if (res == LAGOPUS_RESULT_OK) { eventq_data->packet_out.req = req_pbuf; } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("Can't allocate data_pbuf.\n"); res = LAGOPUS_RESULT_NO_MEMORY; } } if (res == LAGOPUS_RESULT_OK) { /* dump trace.*/ packet_out_trace(&eventq_data->packet_out.ofp_packet_out, &eventq_data->packet_out.action_list); /* send to DataPlane */ res = ofp_handler_event_dataq_put(dpid, eventq_data); if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } if (res != LAGOPUS_RESULT_OK && eventq_data != NULL) { ofp_packet_out_free(eventq_data); } } else { /* channel_pbuf_list_get returns NULL */ res = LAGOPUS_RESULT_NO_MEMORY; } } else { /* params are NULL */ res = LAGOPUS_RESULT_INVALID_ARGS; } return res; }
STATIC lagopus_result_t ofp_meter_features_reply_create(struct channel *channel, struct pbuf_list **pbuf_list, struct ofp_meter_features *ofp_meter_features, struct ofp_header *xid_header) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; uint16_t length = 0; struct pbuf *pbuf = NULL; struct ofp_multipart_reply ofpmp_reply; /* check params */ if (channel != NULL && pbuf_list != NULL && ofp_meter_features != NULL && xid_header != NULL) { /* alloc */ *pbuf_list = NULL; *pbuf_list = pbuf_list_alloc(); if (*pbuf_list != NULL) { /* alloc&get tail of pbuf_list */ pbuf = pbuf_list_last_get(*pbuf_list); if (pbuf != NULL) { /* set data. */ memset(&ofpmp_reply, 0, sizeof(ofpmp_reply)); ofp_header_set(&ofpmp_reply.header, channel_version_get(channel), OFPT_MULTIPART_REPLY, 0, /* length set in ofp_header_length_set() */ xid_header->xid); ofpmp_reply.type = OFPMP_METER_FEATURES; /* encode message. */ pbuf_plen_set(pbuf, pbuf_size_get(pbuf)); res = ofp_multipart_reply_encode_list(*pbuf_list, &pbuf, &ofpmp_reply); if (res == LAGOPUS_RESULT_OK) { res = ofp_meter_features_encode_list(*pbuf_list, &pbuf, ofp_meter_features); if (res == LAGOPUS_RESULT_OK) { /* set packet length */ res = pbuf_length_get(pbuf, &length); if (res == LAGOPUS_RESULT_OK) { res = ofp_header_length_set(pbuf, length); if (res == LAGOPUS_RESULT_OK) { pbuf_plen_reset(pbuf); } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { res = LAGOPUS_RESULT_NO_MEMORY; } } else { res = LAGOPUS_RESULT_NO_MEMORY; } } else { res = LAGOPUS_RESULT_INVALID_ARGS; } return res; }