Commit 93aaaef5 authored by Teodora's avatar Teodora

Add RPC send and receive functionalities

parent 3f98ec50
...@@ -27,6 +27,7 @@ target_compile_definitions(oran_fhlib_5g_mplane PRIVATE OAI_MPLANE) ...@@ -27,6 +27,7 @@ target_compile_definitions(oran_fhlib_5g_mplane PRIVATE OAI_MPLANE)
target_sources(oran_fhlib_5g_mplane PRIVATE target_sources(oran_fhlib_5g_mplane PRIVATE
init-mplane.c init-mplane.c
connect-mplane.c connect-mplane.c
rpc-send-recv.c
) )
pkg_check_modules(libyang REQUIRED libyang) pkg_check_modules(libyang REQUIRED libyang)
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "rpc-send-recv.h"
#include "common/utils/assertions.h"
#ifdef MPLANE_V1
static bool recv_v1(struct nc_session *session, struct nc_rpc *rpc, NC_MSG_TYPE msgtype, const uint64_t msgid, const NC_WD_MODE wd_mode, const int timeout_ms, char **answer)
{
struct nc_reply *reply;
struct nc_reply_data *data_rpl;
struct nc_reply_error *error;
LYD_FORMAT output_format = LYD_XML;
uint32_t ly_wd;
while (1) {
msgtype = nc_recv_reply(session, rpc, msgid, timeout_ms, 0, &reply);
if (msgtype == NC_MSG_ERROR) {
AssertError(false, return false, "[MPLANE] Failed to receive a reply.\n");
} else if (msgtype == NC_MSG_WOULDBLOCK) {
AssertError(false, return false, "[MPLANE] Timeout for receiving a reply expired.\n");
} else if (msgtype == NC_MSG_NOTIF) {
/* read again */
continue;
} else if (msgtype == NC_MSG_REPLY_ERR_MSGID) {
/* unexpected message, try reading again to get the correct reply */
MP_LOG_I("Unexpected reply received - ignoring and waiting for the correct reply.\n");
nc_reply_free(reply);
continue;
}
break;
}
switch (reply->type) {
case NC_RPL_OK:
MP_LOG_I("RPC reply = OK.\n");
break;
case NC_RPL_DATA:
data_rpl = (struct nc_reply_data *)reply;
switch (wd_mode) {
case NC_WD_ALL:
ly_wd = LYP_WD_ALL;
break;
case NC_WD_ALL_TAG:
ly_wd = LYP_WD_ALL_TAG;
break;
case NC_WD_TRIM:
ly_wd = LYP_WD_TRIM;
break;
case NC_WD_EXPLICIT:
ly_wd = LYP_WD_EXPLICIT;
break;
default:
ly_wd = 0; // when wd_mode = NC_WD_UNKNOWN
break;
}
if (nc_rpc_get_type(rpc) == NC_RPC_GETSCHEMA) {
AssertError((!data_rpl->data || (data_rpl->data->schema->nodetype != LYS_RPC) || (data_rpl->data->child == NULL)
|| (data_rpl->data->child->schema->nodetype != LYS_ANYXML)), return false, "[MPLANE] Cannot get schema.\n");
struct lyd_node_anydata *any = (struct lyd_node_anydata *)data_rpl->data->child;
switch (any->value_type) {
case LYD_ANYDATA_CONSTSTRING:
case LYD_ANYDATA_STRING:
*answer = strdup(any->value.str);
break;
case LYD_ANYDATA_DATATREE:
lyd_print_mem(answer, any->value.tree, output_format, LYP_WITHSIBLINGS);
break;
case LYD_ANYDATA_XML:
lyxml_print_mem(answer, any->value.xml, LYXML_PRINT_SIBLINGS);
break;
default:
AssertError(false, return false, "[MPLANE] Unknown yang type.\n");
}
break;
} else if (nc_rpc_get_type(rpc) == NC_RPC_GETCONFIG || nc_rpc_get_type(rpc) == NC_RPC_GET) {
const char *tag = nc_rpc_get_type(rpc) == NC_RPC_GETCONFIG ? "config" : "data";
char *buffer = NULL;
lyd_print_mem(&buffer, data_rpl->data, output_format, LYP_WITHSIBLINGS | LYP_NETCONF | ly_wd);
*answer = calloc(strlen(buffer)+128, sizeof(char));
sprintf(*answer, "<%s xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n%s</%s>", tag, buffer, tag);
} else {
AssertError(false, return false, "[MPLANE] Unknown RPC type.\n");
}
break;
case NC_RPL_ERROR:
error = (struct nc_reply_error *)reply;
for (int i = 0; i < error->count; ++i) {
const struct nc_err *err = &error->err[i];
MP_LOG_I("RPC reply = ERROR\n\
\ttype: %s\n\
\ttag: %s\n\
\tseverity: %s\n\
\tapp-tag: %s\n\
\tpath: %s\n\
\tmessage: %s\n\
\tSID: %s\n",
err->type,
err->tag,
err->severity,
err->apptag,
err->path,
err->message,
err->sid);
for (int j = 0; j < err->attr_count; ++j) {
MP_LOG_I("\tbad-attr #%d: %s\n", j + 1, err->attr[j]);
}
for (int j = 0; j < err->elem_count; ++j) {
MP_LOG_I("\tbad-elem #%d: %s\n", j + 1, err->elem[j]);
}
for (int j = 0; j < err->ns_count; ++j) {
MP_LOG_I("\tbad-ns #%d: %s\n", j + 1, err->ns[j]);
}
for (int j = 0; j < err->other_count; ++j) {
char *str = NULL;
lyxml_print_mem(&str, err->other[j], 0);
MP_LOG_I("\tother #%d:\n%s\n", j + 1, str);
free(str);
}
}
AssertError(false, return false, "[MPLANE] Unable to continue.\n");
break;
default:
AssertError(false, return false, "[MPLANE] Internal error.\n");
nc_reply_free(reply);
}
nc_reply_free(reply);
return true;
}
#elif defined MPLANE_V2
static bool recv_v2(struct nc_session *session, struct nc_rpc *rpc, NC_MSG_TYPE msgtype, const uint64_t msgid, const NC_WD_MODE wd_mode, const int timeout_ms, char **answer)
{
struct lyd_node *envp, *op, *err;
LYD_FORMAT output_format = LYD_XML;
uint32_t ly_wd;
while (1) {
msgtype = nc_recv_reply(session, rpc, msgid, timeout_ms, &envp, &op);
if (msgtype == NC_MSG_ERROR) {
AssertError(false, return false, "[MPLANE] Failed to receive a reply.\n");
} else if (msgtype == NC_MSG_WOULDBLOCK) {
AssertError(false, return false, "[MPLANE] Timeout for receiving a reply for RPC expired.\n");
} else if (msgtype == NC_MSG_NOTIF) { // for SUBSCRIBE
/* read again */
continue;
} else if (msgtype == NC_MSG_REPLY_ERR_MSGID) {
/* unexpected message, try reading again to get the correct reply */
MP_LOG_I("Unexpected reply received - ignoring and waiting for the correct reply.\n");
lyd_free_tree(envp);
lyd_free_tree(op);
continue;
}
break;
}
/* get functionality */
if (op) {
/* data reply */
if (nc_rpc_get_type(rpc) == NC_RPC_GETSCHEMA) {
/* special case */
if (!lyd_child(op) || (lyd_child(op)->schema->nodetype != LYS_ANYXML)) {
AssertError(false, return false, "[MPLANE] Cannot get schema.");
}
struct lyd_node_any *any = (struct lyd_node_any *)lyd_child(op);
switch (any->value_type) {
case LYD_ANYDATA_STRING:
case LYD_ANYDATA_XML:
*answer = strdup(any->value.str);
break;
case LYD_ANYDATA_DATATREE:
lyd_print_mem(answer, any->value.tree, output_format, LYD_PRINT_WITHSIBLINGS);
break;
default:
AssertError(false, return false, "[MPLANE] Unexpected yang type.");
}
} else {
switch (wd_mode) {
case NC_WD_ALL:
ly_wd = LYD_PRINT_WD_ALL;
break;
case NC_WD_ALL_TAG:
ly_wd = LYD_PRINT_WD_ALL_TAG;
break;
case NC_WD_TRIM:
ly_wd = LYD_PRINT_WD_TRIM;
break;
case NC_WD_EXPLICIT:
ly_wd = LYD_PRINT_WD_EXPLICIT;
break;
default:
ly_wd = 0; // when wd_mode = NC_WD_UNKNOWN
break;
}
lyd_print_mem(answer, lyd_child(op), output_format, LYD_PRINT_WITHSIBLINGS | ly_wd);
}
/* edit/validate/commit functionalities */
} else if (!strcmp(LYD_NAME(lyd_child(envp)), "ok")) {
MP_LOG_I("RPC reply = OK.\n");
} else {
LY_LIST_FOR(lyd_child(envp), err) {
struct lyd_node *type, *tag, *severity, *app_tag, *path, *er_msg, *info = NULL;
lyd_find_sibling_opaq_next(lyd_child(err), "error-type", &type);
lyd_find_sibling_opaq_next(lyd_child(err), "error-tag", &tag);
lyd_find_sibling_opaq_next(lyd_child(err), "error-severity", &severity);
lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &app_tag);
lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &path);
lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &er_msg);
MP_LOG_I("RPC reply = ERROR\n\
\ttype: %s\n\
\ttag: %s\n\
\tseverity: %s\n\
\tapp-tag: %s\n\
\tpath: %s\n\
\tmessage: %s\n",
(type ? ((struct lyd_node_opaq *)type)->value : NULL),
(tag ? ((struct lyd_node_opaq *)tag)->value : NULL),
(severity ? ((struct lyd_node_opaq *)severity)->value : NULL),
(app_tag ? ((struct lyd_node_opaq *)app_tag)->value : NULL),
(path ? ((struct lyd_node_opaq *)path)->value : NULL),
(er_msg ? ((struct lyd_node_opaq *)er_msg)->value : NULL));
info = lyd_child(err);
while (!lyd_find_sibling_opaq_next(info, "error-info", &info)) {
char *str = NULL;
lyd_print_mem(&str, lyd_child(info), output_format, LYD_PRINT_WITHSIBLINGS);
MP_LOG_I("\tinfo: %s\n", str);
info = info->next;
free(str);
}
lyd_free_tree(type);
lyd_free_tree(tag);
lyd_free_tree(severity);
lyd_free_tree(app_tag);
lyd_free_tree(path);
lyd_free_tree(er_msg);
lyd_free_tree(info);
}
lyd_free_tree(envp);
lyd_free_tree(op);
AssertError(false, return false, "[MPLANE] Unable to continue.\n");
}
lyd_free_tree(envp);
lyd_free_tree(op);
return true;
}
#endif
bool rpc_send_recv(struct nc_session *session, struct nc_rpc *rpc, const NC_WD_MODE wd_mode, const int timeout_ms, char **answer)
{
uint64_t msgid;
NC_MSG_TYPE msgtype;
msgtype = nc_send_rpc(session, rpc, 1000, &msgid);
if (msgtype == NC_MSG_ERROR) {
AssertError(false, return false, "[MPLANE] Failed to send the RPC.\n");
} else if (msgtype == NC_MSG_WOULDBLOCK) {
AssertError(false, return false, "[MPLANE] Timeout for sending the RPC expired.\n");
}
#ifdef MPLANE_V1
return recv_v1(session, rpc, msgtype, msgid, wd_mode, timeout_ms, answer);
#elif defined MPLANE_V2
return recv_v2(session, rpc, msgtype, msgid, wd_mode, timeout_ms, answer);
#else
AssertError(false, return false, "[MPLANE] Unknown M-plane version found. Tried \"MPLANE_V1\" and \"MPLANE_V2\".\n");
#endif
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef RPC_SEND_RECEIVE_MPLANE_H
#define RPC_SEND_RECEIVE_MPLANE_H
#include "ru-mplane-api.h"
#include <libyang/libyang.h>
#include <nc_client.h>
#define CLI_RPC_REPLY_TIMEOUT 60000 // time [ms] to wait for server reply
bool rpc_send_recv(struct nc_session *session, struct nc_rpc *rpc, const NC_WD_MODE wd_mode, const int timeout_ms, char **answer);
#endif /* RPC_SEND_RECEIVE_MPLANE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment