lagopus_result_t ofp_port_status_handle(struct port_status *port_status, uint64_t dpid) { lagopus_result_t ret; struct pbuf *send_pbuf = NULL; if (port_status != NULL) { /* PortStatus. */ ret = ofp_port_status_create(port_status, &send_pbuf); if (ret == LAGOPUS_RESULT_OK) { ret = ofp_role_channel_write(send_pbuf, dpid, OFPT_PORT_STATUS, port_status->ofp_port_status.reason); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Socket write error (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED : ofp_port_status_create (%s).\n", lagopus_error_get_string(ret)); } /* free. */ if (send_pbuf != NULL) { pbuf_free(send_pbuf); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
/* Experimenter packet receive. */ lagopus_result_t ofp_experimenter_request_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; struct pbuf *send_pbuf = NULL; struct ofp_experimenter_header exper_req; if (channel != NULL && pbuf != NULL && xid_header != NULL) { /* Parse packet. */ ret = ofp_experimenter_header_decode(pbuf, &exper_req); if (ret == LAGOPUS_RESULT_OK) { /* Experimenter request reply. */ ret = ofp_experimenter_reply_create(channel, &send_pbuf, xid_header, &exper_req); 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)); ret = LAGOPUS_RESULT_OFP_ERROR; } if (ret != LAGOPUS_RESULT_OK && send_pbuf != NULL) { channel_pbuf_list_unget(channel, send_pbuf); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
/* Send PacketIn packet. */ lagopus_result_t ofp_packet_in_handle(struct packet_in *packet_in, uint64_t dpid) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; struct pbuf *send_pbuf = NULL; if (packet_in != NULL && packet_in->data != NULL) { /* PacketIn. */ ret = ofp_packet_in_create(packet_in, &send_pbuf); if (ret == LAGOPUS_RESULT_OK) { ret = ofp_role_channel_write(send_pbuf, dpid, OFPT_PACKET_IN, packet_in->ofp_packet_in.reason); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Socket write error (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("Arg is NULL.\n"); ret = LAGOPUS_RESULT_INVALID_ARGS; } /* free. */ if (send_pbuf != NULL) { pbuf_free(send_pbuf); } return ret; }
/* Group mod received. */ lagopus_result_t ofp_group_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_group_mod group_mod; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { /* Parse group_mod header. */ res = ofp_group_mod_decode(pbuf, &(group_mod)); if (res == LAGOPUS_RESULT_OK) { /* check type */ res = s_group_type_check(group_mod.type, error); if (res == LAGOPUS_RESULT_OK) { /* exec group_mod command. */ dpid = channel_dpid_get(channel); switch (group_mod.command) { case OFPGC_ADD: res = s_ofpgc_add(pbuf, dpid, &group_mod, error); break; case OFPGC_MODIFY: res = s_ofpgc_modify(pbuf, dpid, &group_mod, error); break; case OFPGC_DELETE: res = s_ofpgc_delete(pbuf, dpid, &group_mod, error); break; default: lagopus_msg_warning("unknown group_mod command.\n"); ofp_error_set(error, OFPET_GROUP_MOD_FAILED, OFPGMFC_BAD_COMMAND); res = LAGOPUS_RESULT_OFP_ERROR; break; } } if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("group_mod decode error (%s)\n", lagopus_error_get_string(res)); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); res = LAGOPUS_RESULT_OFP_ERROR; } } else { /* params are NULL */ res = LAGOPUS_RESULT_INVALID_ARGS; } return res; }
lagopus_result_t ofp_get_async_request_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header, struct ofp_error *error) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; struct pbuf *send_pbuf = NULL; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { ret = pbuf_plen_check(pbuf, xid_header->length); if (ret == LAGOPUS_RESULT_OK) { /* Parse packet. */ ret = ofp_header_handle(channel, pbuf, error); if (ret == LAGOPUS_RESULT_OK) { /* dump trace. */ get_async_request_trace(xid_header); /* Reply send.*/ ret = ofp_get_async_reply_create(channel, &send_pbuf, xid_header); if (ret == LAGOPUS_RESULT_OK) { channel_send_packet(channel, send_pbuf); } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); ret = LAGOPUS_RESULT_OFP_ERROR; } if (ret != LAGOPUS_RESULT_OK && send_pbuf != NULL) { channel_pbuf_list_unget(channel, send_pbuf); } } else { lagopus_msg_warning("bad length.\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); ret = LAGOPUS_RESULT_OFP_ERROR; } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
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; }
lagopus_result_t ofp_meter_features_request_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_meter_features ofp_meter_features; struct pbuf_list *send_pbuf_list = NULL; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { if (pbuf_plen_equal_check(pbuf, 0) == LAGOPUS_RESULT_OK) { /* get datas */ memset(&ofp_meter_features, 0, sizeof(ofp_meter_features)); dpid = channel_dpid_get(channel); res = ofp_meter_features_get(dpid, &ofp_meter_features, error); if (res == LAGOPUS_RESULT_OK) { /* create desc reply. */ res = ofp_meter_features_reply_create(channel, &send_pbuf_list, &ofp_meter_features, xid_header); if (res == LAGOPUS_RESULT_OK) { /* send desc reply */ res = channel_send_packet_list(channel, send_pbuf_list); if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Socket write error (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("reply creation failed, (%s).\n", lagopus_error_get_string(res)); } /* free. */ if (send_pbuf_list != NULL) { pbuf_list_free(send_pbuf_list); } } } else { lagopus_msg_warning("over packet length.\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); res = LAGOPUS_RESULT_OFP_ERROR; } } else { res = LAGOPUS_RESULT_INVALID_ARGS; } 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; 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; }
/* Group Features Request packet receive. */ lagopus_result_t ofp_group_features_request_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_group_features group_features; struct pbuf_list *pbuf_list = NULL; if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { if (pbuf_plen_equal_check(pbuf, 0) == LAGOPUS_RESULT_OK) { dpid = channel_dpid_get(channel); ret = ofp_group_features_get(dpid, &group_features, error); if (ret == LAGOPUS_RESULT_OK) { ret = ofp_group_features_reply_create(channel, &pbuf_list, &group_features, xid_header); if (ret == LAGOPUS_RESULT_OK) { /* write packets. */ ret = channel_send_packet_list(channel, pbuf_list); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Can't write\n"); } } 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("over packet length.\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); ret = LAGOPUS_RESULT_OFP_ERROR; } /* free. */ if (pbuf_list != NULL) { pbuf_list_free(pbuf_list); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
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; }
/* Features Request packet receive. */ lagopus_result_t ofp_features_request_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header, struct ofp_error *error) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; struct pbuf *send_pbuf = NULL; /* Parse packet. */ ret = ofp_header_handle(channel, pbuf, error); if (ret == LAGOPUS_RESULT_OK) { /* Features request reply. */ ret = ofp_features_reply_create(channel, &send_pbuf, xid_header); if (ret == LAGOPUS_RESULT_OK) { features_request_trace(xid_header); channel_send_packet(channel, send_pbuf); ret = LAGOPUS_RESULT_OK; } 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); } return ret; }
/* 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; }
bool ofp_header_version_check(struct channel *channel, struct ofp_header *header) { bool ret = false; uint8_t bridge_ofp_version; uint64_t dpid; if (channel != NULL && header != NULL) { dpid = channel_dpid_get(channel); ret = dpmgr_bridge_ofp_version_get(dpid, &bridge_ofp_version); if (ret == LAGOPUS_RESULT_OK) { if (bridge_ofp_version == header->version) { ret = true; } else { lagopus_msg_warning("Unsupported ofp version : %"PRIu8".\n", header->version); ret = false; } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); ret = false; } } else { lagopus_msg_warning("Arg is NULL.\n"); ret = false; } return ret; }
/* Table mod received. */ lagopus_result_t ofp_table_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_table_mod table_mod; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { /* Parse table_mod header. */ res = ofp_table_mod_decode(pbuf, &(table_mod)); if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("table_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. */ table_mod_trace(&table_mod); /* check flag. */ res = ofp_table_mod_config_check(table_mod.config, error); if (res == LAGOPUS_RESULT_OK) { dpid = channel_dpid_get(channel); /* set table_mod */ res = ofp_table_mod_set(dpid, &table_mod, error); 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)); } } } else { res = LAGOPUS_RESULT_INVALID_ARGS; } return res; }
/* 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; }
lagopus_result_t ofp_header_length_set(struct pbuf *pbuf, uint16_t length) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; pbuf_info_t cur_pbuf_info; pbuf_info_t update_pbuf_info; struct ofp_header header; if (pbuf != NULL) { /* Store current pbuf info. */ pbuf_info_store(pbuf, &cur_pbuf_info); /* 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) { /* Set length.*/ header.length = length; /* Update pbuf info for ofp_header_encode. */ pbuf_reset(pbuf); pbuf_plen_set(pbuf, sizeof(struct ofp_header)); ret = ofp_header_encode(pbuf, &header); 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 { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
static void s_destroy_channel(struct channel *channel) { if (channel != NULL) { lagopus_result_t ret; ret = channel_free(channel); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_fatal("channel_free error (%s)\n", lagopus_error_get_string(ret)); } } }
/* 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; }
lagopus_result_t check_packet_parse_array_expect_error(ofp_handler_proc_t handler_proc, const char *packet[], int array_len, const struct ofp_error *expected_error) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; struct channel *channel = create_data_channel(); struct ofp_header xid_header; struct pbuf *pbuf; struct ofp_error error; bool error_has_occurred = false; int i; for (i = 0; i < array_len; i++) { lagopus_msg_debug(1, "packet[%d] start ... %s\n", i, packet[i]); /* create packet */ create_packet(packet[i], &pbuf); /* parse header */ if (ofp_header_decode_sneak_test(pbuf, &xid_header) != LAGOPUS_RESULT_OK) { pbuf_free(pbuf); s_destroy_static_data(); TEST_FAIL_MESSAGE("handler_test_utils.c: cannot decode header\n"); return LAGOPUS_RESULT_OFP_ERROR; } /* call func & check */ res = (handler_proc)(channel, pbuf, &xid_header, &error); lagopus_msg_debug(1, "packet[%d] done ... %s\n", i, lagopus_error_get_string(res)); if (res == LAGOPUS_RESULT_OK) { TEST_ASSERT_EQUAL_MESSAGE(0, pbuf->plen, "handler_test_utils.c: packet data len error."); } else if (res == LAGOPUS_RESULT_OFP_ERROR) { error_has_occurred = true; if (expected_error != NULL) { TEST_ASSERT_EQUAL_OFP_ERROR(expected_error, &error); } pbuf_free(pbuf); break; } /* free */ pbuf_free(pbuf); } /* free */ s_destroy_static_data(); if (error_has_occurred == true) { TEST_ASSERT_EQUAL_OFP_ERROR(expected_error, &error); } return res; }
static lagopus_result_t features_reply_features_get(struct channel *channel, struct ofp_switch_features *features) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; datastore_bridge_info_t info; size_t i; /* set ids/reserved. */ features->datapath_id = channel_dpid_get(channel); features->auxiliary_id = channel_auxiliary_id_get(channel); features->reserved = 0; if ((ret = ofp_bridgeq_mgr_info_get(features->datapath_id, &info)) != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); goto done; } /* set max. */ features->n_buffers = info.max_buffered_packets; features->n_tables = info.max_tables; /* set capabilities. */ features->capabilities = 0; for (i = 0; i < capabilities_size; i++) { if ((ret = features_reply_features_capability_set( info.capabilities, i, &features->capabilities)) != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); goto done; } } done: return ret; }
static lagopus_result_t snmpmgr_thread_loop(const lagopus_thread_t *selfptr, void *arg) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; lagopus_chrono_t interval = DEFAULT_SNMPMGR_LOOP_INTERVAL_NSEC; global_state_t global_state; shutdown_grace_level_t l; (void)selfptr; (void)arg; /* open the session to AgentX master agent here. */ init_snmp(SNMP_TYPE); /* wait all modules start */ if ((ret = global_state_wait_for(GLOBAL_STATE_STARTED, &global_state, &l, -1 /* forever! */)) != LAGOPUS_RESULT_OK) { lagopus_perror(ret); } else { if (global_state != GLOBAL_STATE_STARTED) { lagopus_exit_fatal("must not happen. die!\n"); } } /* all modules have started, then send a coldStart trap */ (void)send_coldStart_trap(); lagopus_msg_info("SNMP manager started (as a thread).\n"); /* main loop */ while (keep_running) { (void)lagopus_mutex_lock(&snmp_lock); ret = internal_snmpmgr_poll(interval); (void)lagopus_mutex_unlock(&snmp_lock); if (ret != LAGOPUS_RESULT_OK && ret != LAGOPUS_RESULT_TIMEDOUT) { lagopus_msg_warning("failed to poll SNMP AgentX request: %s", lagopus_error_get_string(ret)); } check_status_and_send_traps(); } /* stop SNMP */ snmp_shutdown(SNMP_TYPE); (void)lagopus_mutex_lock(&snmp_state_lock); if (state != SNMPMGR_RUNNABLE) { state = SNMPMGR_NONE; } (void)lagopus_mutex_unlock(&snmp_state_lock); return LAGOPUS_RESULT_OK; }
/* Desc Request packet receive. */ lagopus_result_t ofp_desc_request_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_desc ofp_desc; struct pbuf_list *send_pbuf_list = NULL; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { dpid = channel_dpid_get(channel); /* get datas */ memset(&ofp_desc, 0, sizeof(ofp_desc)); res = ofp_desc_get(dpid, &ofp_desc, error); if (res == LAGOPUS_RESULT_OK) { /* create desc reply. */ res = ofp_desc_reply_create(channel, &send_pbuf_list, &ofp_desc, xid_header); if (res == LAGOPUS_RESULT_OK) { /* send desc reply */ res = channel_send_packet_list(channel, send_pbuf_list); if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Socket write error (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("reply creation failed, (%s).\n", lagopus_error_get_string(res)); } pbuf_list_free(send_pbuf_list); } } else { res = LAGOPUS_RESULT_INVALID_ARGS; } return res; }
/* Experimenter multipart packet receive. */ lagopus_result_t ofp_experimenter_mp_request_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; struct pbuf_list *pbuf_list = NULL; struct ofp_experimenter_multipart_header exper_req; if (channel != NULL && pbuf != NULL && xid_header != NULL) { /* Parse packet. */ ret = ofp_experimenter_multipart_header_decode(pbuf, &exper_req); if (ret == LAGOPUS_RESULT_OK) { /* Experimenter request reply. */ ret = ofp_experimenter_mp_reply_create(channel, &pbuf_list, xid_header, &exper_req); if (ret == LAGOPUS_RESULT_OK) { ret = channel_send_packet_list(channel, pbuf_list); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Can't write.\n"); ret = LAGOPUS_RESULT_OFP_ERROR; } } 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; } /* free. */ if (pbuf_list != NULL) { pbuf_list_free(pbuf_list); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
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; }
void count_ifNumber(int32_t *ifNumber) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; size_t v; if (ifNumber != NULL) { struct port_stat *port_stat; if ((ret = dp_get_port_stat(&port_stat)) == LAGOPUS_RESULT_OK) { dataplane_count_ifNumber(port_stat, &v); *ifNumber = (int32_t)v; port_stat_release(port_stat); free(port_stat); } else { lagopus_msg_error("cannot count ports: %s\n", lagopus_error_get_string(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 ofp_port_status_create(struct port_status *port_status, struct pbuf **pbuf) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; uint8_t tmp_version = 0x00; uint32_t tmp_xid = 0; if (port_status != NULL && pbuf != NULL) { /* alloc */ *pbuf = pbuf_alloc(sizeof(struct ofp_port_status)); if (pbuf != NULL) { pbuf_plen_set(*pbuf, sizeof(struct ofp_port_status)); /* Fill in header. */ /* tmp_* is replaced later. */ ofp_header_set(&port_status->ofp_port_status.header, tmp_version, OFPT_PORT_STATUS, sizeof(struct ofp_port_status), tmp_xid); ret = ofp_port_status_encode(*pbuf, &port_status->ofp_port_status); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("FAILED : ofp_port_status_encode (%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); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
lagopus_result_t ofp_set_async_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header, struct ofp_error *error) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; struct ofp_async_config async_config; if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { ret = pbuf_plen_check(pbuf, xid_header->length); if (ret == LAGOPUS_RESULT_OK) { /* Parse packet. */ ret = ofp_async_config_decode(pbuf, &async_config); if (ret == LAGOPUS_RESULT_OK) { /* dump trace. */ set_async_trace(&async_config); /* Copy packet_in_mask, port_status_mask, flow_removed_mask. */ channel_role_mask_set(channel, &async_config); } else { lagopus_msg_warning("FAILED : ofp_config_decode (%s).\n", lagopus_error_get_string(ret)); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); ret = LAGOPUS_RESULT_OFP_ERROR; } } else { lagopus_msg_warning("bad length.\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); ret = LAGOPUS_RESULT_OFP_ERROR; } } 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; }