aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrej Kozemcak <andrej.kozemcak@pantheon.tech>2019-02-14 13:15:22 +0100
committerAndrej Kozemcak <andrej.kozemcak@pantheon.tech>2019-03-20 16:13:15 +0100
commit52002bff61ccdd95a3e69094f8e6a99eaf2c0b32 (patch)
treefe63846d48bec1e555c36f47564506ae3e662cc3
parent7dd61fc820323344c7479dd767a2ee0f84abd810 (diff)
Plugin - init NAT
Change-Id: I072b3bc018812d9f51cb7269bfdbb98b19db873c Signed-off-by: Andrej Kozemcak <andrej.kozemcak@pantheon.tech>
-rw-r--r--src/plugins/CMakeLists.txt1
-rw-r--r--src/plugins/ietf/ietf_nat.c532
-rw-r--r--src/plugins/ietf/ietf_nat.h25
-rw-r--r--src/plugins/sc_plugins.c2
-rw-r--r--src/plugins/sys_util.c87
-rw-r--r--src/plugins/sys_util.h40
-rw-r--r--src/scvpp/src/sc_vpp_comm.c13
-rw-r--r--src/scvpp/src/sc_vpp_comm.h10
8 files changed, 710 insertions, 0 deletions
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
index 72a87bd..d8dba04 100644
--- a/src/plugins/CMakeLists.txt
+++ b/src/plugins/CMakeLists.txt
@@ -57,6 +57,7 @@ set(PLUGINS_SOURCES
sc_model.c
sys_util.c
ietf/ietf_interface.c
+ ietf/ietf_nat.c
openconfig/openconfig_interfaces.c
openconfig/openconfig_local_routing.c
)
diff --git a/src/plugins/ietf/ietf_nat.c b/src/plugins/ietf/ietf_nat.c
new file mode 100644
index 0000000..86c8570
--- /dev/null
+++ b/src/plugins/ietf/ietf_nat.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#include "ietf_nat.h"
+#include "sc_vpp_comm.h"
+#include "sc_vpp_interface.h"
+#include "sc_vpp_nat.h"
+
+#include <assert.h>
+#include <string.h>
+#include <sysrepo.h>
+#include <sysrepo/xpath.h>
+#include <sysrepo/values.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "../sys_util.h"
+
+static int ietf_nat_mod_cb(
+ __attribute__((unused)) sr_session_ctx_t *session,
+ __attribute__((unused)) const char *module_name,
+ __attribute__((unused)) sr_notif_event_t event,
+ __attribute__((unused)) void *private_ctx)
+{
+ SRP_LOG_INF("Module subscribe: %s", module_name);
+
+ return SR_ERR_OK;
+}
+
+/**
+ * @brief Wrapper struct for VAPI address range payload.
+ */
+struct address_range_t {
+ nat44_add_del_address_range_t payload; //< VAPI payload for address range.
+ bool last_ip_address_set; //< Variable last_ip_address in payload is set.
+};
+
+// Check input structure, set VAPI payload and call VAPI function to set
+// nat44 address range.
+static sr_error_t set_address_range(struct address_range_t *address_r)
+{
+ sr_error_t rc = SR_ERR_OK;
+// char tmp_ip1[VPP_IP4_ADDRESS_STRING_LEN];
+// char tmp_ip2[VPP_IP4_ADDRESS_STRING_LEN];
+
+ ARG_CHECK(SR_ERR_INVAL_ARG, address_r);
+
+ //if end of IP range not provided, then range size = 1 with only first ip
+ if (!address_r->last_ip_address_set) {
+ memcpy(&address_r->payload.last_ip_address[0],
+ &address_r->payload.first_ip_address[0],
+ VPP_IP4_ADDRESS_LEN);
+ }
+
+ if (hardntohlu32(address_r->payload.last_ip_address) <
+ hardntohlu32(address_r->payload.first_ip_address)) {
+ SRP_LOG_ERR_MSG("End address less than start address");
+ return SR_ERR_INVAL_ARG;
+ }
+
+// strncpy(tmp_ip1, sc_ntoa(address_r->payload.first_ip_address),
+// VPP_IP4_ADDRESS_STRING_LEN);
+// strncpy(tmp_ip2, sc_ntoa(address_r->payload.last_ip_address),
+// VPP_IP4_ADDRESS_STRING_LEN);
+// SRP_LOG_DBG("Fist ip address: %s, last ip address: %s, twice_nat: %u,"
+// "is_add: %u", tmp_ip1, tmp_ip2, address_r->payload.twice_nat,
+// address_r->payload.is_add);
+
+ int rv = nat44_add_del_addr_range(&address_r->payload);
+ if (0 != rv) {
+ SRP_LOG_ERR_MSG("Failed set address range.");
+ rc = SR_ERR_OPERATION_FAILED;
+ }
+
+ return rc;
+}
+
+// parse leaf from this xpath:
+// /ietf-nat:nat/instances/instance[id='%s']/policy[id='%s']/external-ip-address-pool[pool-id='%s']/
+static int parse_instance_policy_external_ip_address_pool(
+ const sr_val_t *val, struct address_range_t *address_range)
+{
+ int rc;
+ char tmp_str[VPP_IP4_PREFIX_STRING_LEN] = {0};
+ uint8_t prefix = 0;
+
+ ARG_CHECK2(SR_ERR_INVAL_ARG, val, address_range);
+
+ if (sr_xpath_node_name_eq(val->xpath, "pool-id")) {
+ SRP_LOG_WRN("%s not supported.", val->xpath);
+ } else if(sr_xpath_node_name_eq(val->xpath, "external-ip-pool")) {
+ rc = get_address_from_prefix(tmp_str, val->data.string_val,
+ VPP_IP4_ADDRESS_STRING_LEN, &prefix);
+ if (0 != rc) {
+ SRP_LOG_ERR_MSG("Error translate");
+ return SR_ERR_INVAL_ARG;
+ }
+
+ rc = sc_aton(tmp_str, address_range->payload.first_ip_address,
+ VPP_IP4_ADDRESS_LEN);
+ if (0 != rc) {
+ SRP_LOG_ERR_MSG("Failed convert string IP address to int.");
+ return SR_ERR_INVAL_ARG;
+ }
+
+ if (prefix < VPP_IP4_HOST_PREFIX_LEN) {
+ // External IP pool is represented as IPv4 prefix in YANG module.
+ // VPP support range from first IPv4 address to last IPv4 address, not prefix.
+ // In this concept the broadcast IPv4 address of this IPv4 prefix,
+ // represent last IPv4 address for VPP
+ get_last_ip_address(
+ (sc_ipv4_addr*) &address_range->payload.last_ip_address[0],
+ (sc_ipv4_addr*) &address_range->payload.first_ip_address[0],
+ prefix);
+ address_range->last_ip_address_set = true;
+ }
+ }
+
+ return SR_ERR_OK;
+}
+
+// XPATH: /ietf-nat:nat/instances/instance[id='%s']/policy[id='%s']/external-ip-address-pool[pool-id='%s']/
+static int instances_instance_policy_external_ip_address_pool_cb(
+ sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
+ __attribute__((unused)) void *private_ctx)
+{
+ sr_error_t rc = SR_ERR_OK;
+ sr_change_iter_t *it = NULL;
+ sr_change_oper_t oper;
+ sr_val_t *old_val = NULL;
+ sr_val_t *new_val = NULL;
+ bool create = false;
+ bool delete = false;
+ struct address_range_t new_address_r = {0};
+ struct address_range_t old_address_r = {0};
+
+ ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath);
+
+ new_address_r.payload.vrf_id = ~0;
+ old_address_r.payload.vrf_id = ~0;
+
+ SRP_LOG_DBG("'%s' modified, event=%d", xpath, event);
+
+ if (event != SR_EV_APPLY) {
+ return SR_ERR_OK;
+ }
+
+ if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
+ // in example he calls even on fale
+ sr_free_change_iter(it);
+ return SR_ERR_OK;
+ }
+
+ while (sr_get_change_next(ds, it, &oper,
+ &old_val, &new_val) == SR_ERR_OK) {
+
+ SRP_LOG_DBG("A change detected in '%s', op=%d",
+ new_val ? new_val->xpath : old_val->xpath, oper);
+
+ switch (oper) {
+ case SR_OP_CREATED:
+ create = true;
+ rc = parse_instance_policy_external_ip_address_pool(new_val,
+ &new_address_r);
+ break;
+
+ case SR_OP_MODIFIED:
+ delete = true;
+ rc = parse_instance_policy_external_ip_address_pool(old_val,
+ &old_address_r);
+ if (SR_ERR_OK != rc) {
+ break;
+ }
+
+ create = true;
+ rc = parse_instance_policy_external_ip_address_pool(new_val,
+ &new_address_r);
+ break;
+
+ case SR_OP_MOVED:
+ break;
+
+ case SR_OP_DELETED:
+ delete = true;
+ rc = parse_instance_policy_external_ip_address_pool(old_val,
+ &old_address_r);
+ break;
+ }
+
+ sr_free_val(old_val);
+ sr_free_val(new_val);
+
+ if (SR_ERR_OK != rc) {
+ rc = SR_ERR_OPERATION_FAILED;
+ goto error;
+ }
+ }
+
+ if (delete) {
+ old_address_r.payload.is_add = 0;
+ rc = set_address_range(&old_address_r);
+ if (SR_ERR_OK != rc) {
+ goto error;
+ }
+ }
+
+ if (create) {
+ new_address_r.payload.is_add = 1;
+ rc = set_address_range(&new_address_r);
+ if (SR_ERR_OK != rc) {
+ goto error;
+ }
+ }
+
+error:
+ sr_free_change_iter(it);
+ return rc;
+}
+
+enum mapping_type {
+ STATIC,
+ DYNAMIC_IMPLICIT,
+ DYNAMIC_EXPLICIT,
+ UNKNOWN,
+};
+
+/**
+ * @brief Wrapper struct for VAPI static mapping payload.
+ */
+struct static_mapping_t {
+ enum mapping_type mtype; //< Mapping type
+ bool local_ip_address_set; //< Variable are set in payload.
+ bool external_ip_address_set; //< Variable are set in payload.
+ bool protocol_set; //< Variable are set in payload.
+ bool local_port_set; //< Variable are set in payload.
+ bool external_port_set; //< Variable are set in payload.
+ bool external_sw_if_index_set; //< Variable are set in payload.
+ bool vrf_id_set; //< Variable are set in payload.
+ bool twice_nat_set; //< Variable are set in payload.
+ nat44_add_del_static_mapping_t payload; //< VAPI payload for static mapping
+};
+
+// Check input structure, set VAPI payload and call VAPI function to set
+// nat44 static mapping.
+static sr_error_t set_static_mapping(struct static_mapping_t *mapping)
+{
+ int rc = 0;
+// char tmp_ip1[VPP_IP4_ADDRESS_STRING_LEN];
+// char tmp_ip2[VPP_IP4_ADDRESS_STRING_LEN];
+
+ ARG_CHECK(SR_ERR_INVAL_ARG, mapping);
+
+ if ((mapping->local_port_set != mapping->external_port_set) ||
+ !mapping->local_ip_address_set || !mapping->external_ip_address_set) {
+ SRP_LOG_ERR_MSG("NAT44 parameter missing.");
+
+ return SR_ERR_VALIDATION_FAILED;
+ }
+
+ if (!mapping->local_port_set && !mapping->external_port_set) {
+ mapping->payload.addr_only= 1;
+ mapping->payload.twice_nat = 0;
+ } else {
+ mapping->payload.addr_only= 0;
+ mapping->payload.twice_nat = 1;
+ if (!mapping->protocol_set) {
+
+ SRP_LOG_ERR_MSG("NAT44 protocol missing.");
+ return SR_ERR_VALIDATION_FAILED;
+ }
+ }
+
+ mapping->payload.external_sw_if_index = ~0;
+
+// strncpy(tmp_ip1, sc_ntoa(mapping->payload.local_ip_address),
+// VPP_IP4_ADDRESS_STRING_LEN);
+// strncpy(tmp_ip2, sc_ntoa(mapping->payload.external_ip_address),
+// VPP_IP4_ADDRESS_STRING_LEN);
+// SRP_LOG_DBG("Local ip address: %s, external ip address: %s, addr_only: %u,"
+// " protocol: %u, local port: %u, external port: %u, twice_nat: %u,"
+// "is_add: %u", tmp_ip1, tmp_ip2, mapping->payload.addr_only,
+// mapping->payload.protocol, mapping->payload.local_port,
+// mapping->payload.external_port, mapping->payload.twice_nat,
+// mapping->payload.is_add);
+
+ rc = nat44_add_del_static_mapping(&mapping->payload);
+ if (0 != rc) {
+ SRP_LOG_ERR_MSG("Failed set static mapping");
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ return SR_ERR_OK;
+}
+
+// parse leaf from this xpath:
+// /ietf-nat:nat/instances/instance[id='%s']/mapping-table/mapping-entry[index='%s']/
+static int parse_instance_mapping_table_mapping_entry(
+ const sr_val_t *val,
+ struct static_mapping_t *mapping)
+{
+ int rc;
+ char tmp_str[VPP_IP4_PREFIX_STRING_LEN] = {0};
+
+ ARG_CHECK2(SR_ERR_INVAL_ARG, val, mapping);
+
+ sr_xpath_ctx_t state = {0};
+
+ if(sr_xpath_node_name_eq(val->xpath, "type")) {
+ if (!strncmp("static", val->data.string_val, strlen("static"))) {
+ mapping->mtype = STATIC;
+ } else if (!strncmp("dynamic-implicit", val->data.string_val,
+ strlen("dynamic-implicit"))) {
+ mapping->mtype = DYNAMIC_IMPLICIT;
+ } else if (!strncmp("dynamic-explicit", val->data.string_val,
+ strlen("dynamic-explicit"))) {
+ mapping->mtype = DYNAMIC_EXPLICIT;
+ }
+ } else if(sr_xpath_node_name_eq(val->xpath, "transport-protocol")) {
+ if (SR_UINT8_T != val->type) {
+ SRP_LOG_ERR("Wrong transport-protocol, type, current type: %d.",
+ val->type);
+ return SR_ERR_INVAL_ARG;
+ }
+
+ mapping->payload.protocol = val->data.uint8_val;
+ mapping->protocol_set = true;
+ } else if(sr_xpath_node_name_eq(val->xpath, "internal-src-address")) {
+ if (SR_STRING_T != val->type) {
+ SRP_LOG_ERR("Wrong internal-src-address, type, current type: %d.",
+ val->type);
+ return SR_ERR_INVAL_ARG;
+ }
+
+ rc = get_address_from_prefix(tmp_str, val->data.string_val,
+ VPP_IP4_PREFIX_STRING_LEN, NULL);
+ if (0 != rc) {
+ SRP_LOG_ERR_MSG("Error translate");
+ return SR_ERR_INVAL_ARG;
+ }
+
+ rc = sc_aton(tmp_str, mapping->payload.local_ip_address,
+ VPP_IP4_ADDRESS_LEN);
+ if (0 != rc) {
+ SRP_LOG_ERR_MSG("Failed convert string IP address to int.");
+ return SR_ERR_INVAL_ARG;
+ }
+
+ mapping->local_ip_address_set = true;
+ } else if(sr_xpath_node_name_eq(val->xpath, "external-src-address")) {
+ if (SR_STRING_T != val->type) {
+ SRP_LOG_ERR("Wrong external-src-address, type, current type: %d.",
+ val->type);
+ return SR_ERR_INVAL_ARG;
+ }
+
+ rc = get_address_from_prefix(tmp_str, val->data.string_val,
+ VPP_IP4_ADDRESS_STRING_LEN, NULL);
+ if (0 != rc) {
+ SRP_LOG_ERR_MSG("Error translate");
+ return SR_ERR_INVAL_ARG;
+ }
+
+ rc = sc_aton(tmp_str, mapping->payload.external_ip_address,
+ VPP_IP4_ADDRESS_LEN);
+ if (0 != rc) {
+ SRP_LOG_ERR_MSG("Failed convert string IP address to int.");
+ return SR_ERR_INVAL_ARG;
+ }
+
+ mapping->external_ip_address_set = true;
+ } else if (sr_xpath_node(val->xpath, "internal-src-port", &state)) {
+ sr_xpath_recover(&state);
+ if(sr_xpath_node_name_eq(val->xpath, "start-port-number")) {
+ mapping->local_port_set = true;
+ mapping->payload.local_port = val->data.uint16_val;
+ }
+ } else if (sr_xpath_node(val->xpath, "external-src-port", &state)) {
+ sr_xpath_recover(&state);
+ if(sr_xpath_node_name_eq(val->xpath, "start-port-number")) {
+ mapping->external_port_set = true;
+ mapping->payload.external_port = val->data.uint16_val;
+ }
+ }
+
+ return SR_ERR_OK;
+}
+
+// XPATH: /ietf-nat:nat/instances/instance[id='%s']/mapping-table/mapping-entry[index='%s']/
+static int instances_instance_mapping_table_mapping_entry_cb(
+ sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
+ __attribute__((unused)) void *private_ctx)
+{
+ sr_error_t rc = SR_ERR_OK;
+ sr_change_iter_t *it = NULL;
+ sr_change_oper_t oper;
+ sr_val_t *old_val = NULL;
+ sr_val_t *new_val = NULL;
+ bool create = false;
+ bool delete = false;
+ struct static_mapping_t new_mapping = {0};
+ struct static_mapping_t old_mapping = {0};
+
+ ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath);
+
+ new_mapping.mtype = UNKNOWN;
+ old_mapping.mtype = UNKNOWN;
+
+ SRP_LOG_DBG("'%s' modified, event=%d", xpath, event);
+
+ if (event != SR_EV_APPLY) {
+ return SR_ERR_OK;
+ }
+
+ if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
+ // in example he calls even on fale
+ sr_free_change_iter(it);
+ return SR_ERR_OK;
+ }
+
+ while (sr_get_change_next(ds, it, &oper,
+ &old_val, &new_val) == SR_ERR_OK) {
+
+ SRP_LOG_DBG("A change detected in '%s', op=%d",
+ new_val ? new_val->xpath : old_val->xpath, oper);
+
+ switch (oper) {
+ case SR_OP_CREATED:
+ create = true;
+ rc = parse_instance_mapping_table_mapping_entry(new_val,
+ &new_mapping);
+ break;
+
+ case SR_OP_MODIFIED:
+ delete = true;
+ rc = parse_instance_mapping_table_mapping_entry(old_val,
+ &old_mapping);
+ if (SR_ERR_OK != rc) {
+ break;
+ }
+
+ create = true;
+ rc = parse_instance_mapping_table_mapping_entry(new_val,
+ &new_mapping);
+ break;
+
+ case SR_OP_MOVED:
+ break;
+
+ case SR_OP_DELETED:
+ delete = true;
+ rc = parse_instance_mapping_table_mapping_entry(old_val,
+ &old_mapping);
+ break;
+ }
+
+ sr_free_val(old_val);
+ sr_free_val(new_val);
+
+ if (SR_ERR_OK != rc) {
+ rc = SR_ERR_OPERATION_FAILED;
+ goto error;
+ }
+ }
+
+ if (delete) {
+ old_mapping.payload.is_add = 0;
+ if (STATIC == old_mapping.mtype) {
+ rc = set_static_mapping(&old_mapping);
+ if (SR_ERR_OK != rc) {
+ goto error;
+ }
+ }
+ }
+
+ if (create) {
+ new_mapping.payload.is_add = 1;
+ if (STATIC == new_mapping.mtype) {
+ rc = set_static_mapping(&new_mapping);
+ if (SR_ERR_OK != rc) {
+ goto error;
+ }
+ }
+ }
+
+error:
+ sr_free_change_iter(it);
+ return rc;
+}
+
+const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE] = {
+ {
+ .xpath = "ietf-nat",
+ .method = MODULE,
+ .datastore = SR_DS_RUNNING,
+ .cb.mcb = ietf_nat_mod_cb,
+ .private_ctx = NULL,
+ .priority = 0,
+ .opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY | SR_SUBSCR_CTX_REUSE
+ },
+ {
+ .xpath = "/ietf-nat:nat/instances/instance/policy/external-ip-address-pool",
+ .method = XPATH,
+ .datastore = SR_DS_RUNNING,
+ .cb.scb = instances_instance_policy_external_ip_address_pool_cb,
+ .private_ctx = NULL,
+ .priority = 0,
+ .opts = SR_SUBSCR_CTX_REUSE
+ },
+ {
+ .xpath = "/ietf-nat:nat/instances/instance/mapping-table/mapping-entry",
+ .method = XPATH,
+ .datastore = SR_DS_RUNNING,
+ .cb.scb = instances_instance_mapping_table_mapping_entry_cb,
+ .private_ctx = NULL,
+ .priority = 0,
+ .opts = SR_SUBSCR_CTX_REUSE
+ },
+};
diff --git a/src/plugins/ietf/ietf_nat.h b/src/plugins/ietf/ietf_nat.h
new file mode 100644
index 0000000..7495209
--- /dev/null
+++ b/src/plugins/ietf/ietf_nat.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+#ifndef __IETF_NAT_H__
+#define __IETF_NAT_H__
+
+#include "../sc_model.h"
+
+#define IETF_NAT_SIZE 3
+extern const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE];
+
+#endif
diff --git a/src/plugins/sc_plugins.c b/src/plugins/sc_plugins.c
index 093939c..87ea2d7 100644
--- a/src/plugins/sc_plugins.c
+++ b/src/plugins/sc_plugins.c
@@ -17,6 +17,7 @@
#include "sc_model.h"
#include "ietf/ietf_interface.h"
+#include "ietf/ietf_nat.h"
#include "openconfig/openconfig_interfaces.h"
#include "openconfig/openconfig_local_routing.h"
@@ -36,6 +37,7 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx)
/* Use the same sr_subscription_ctx for all models */
model_register(&plugin_main, ietf_interfaces_xpaths, IETF_INTERFACES_SIZE);
+ model_register(&plugin_main, ietf_nat_xpaths, IETF_NAT_SIZE);
model_register(&plugin_main, oc_interfaces_xpaths, OC_INTERFACES_SIZE);
model_register(&plugin_main, oc_local_routing_xpaths, OC_LROUTING_SIZE);
diff --git a/src/plugins/sys_util.c b/src/plugins/sys_util.c
index 7bd0937..a3ee0c9 100644
--- a/src/plugins/sys_util.c
+++ b/src/plugins/sys_util.c
@@ -81,3 +81,90 @@ int ip_prefix_split(const char* ip_prefix)
//return mask length
return mask;
}
+
+/**
+ * @brief Get IPv4 host address from IPv4 prefix.
+ *
+ * @param[out] dst Host IPv4 address.
+ * @param[in] src IPv4 Prefix.
+ * @param[in] length dst buffer length.
+ * @param[out] prefix Get Prefix length, optional value. Can be NULL.
+ * @return -1 when failure, 0 on success.
+ */
+int get_address_from_prefix(char *dst, const char *src, size_t length,
+ uint8_t *prefix_length)
+{
+ ARG_CHECK2(-1, src, dst);
+
+ size_t size = 0;
+ char *p = strchr(src, '/');
+ if (NULL == p) {
+ return -1;
+ }
+
+ size = p - src;
+
+ // + 1, need size for \0
+ if ((size + 1) > length) {
+ return -1;
+ }
+
+ strncpy(dst, src, size);
+
+ if (NULL != prefix_length) {
+ *prefix_length = atoi(++p);
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Get IPv4 broadcast IP address form IPv4 network address.
+ *
+ * @param[out] broadcat Broadcast Ipv4 address.
+ * @param[in] network Network IPv4 address.
+ * @param[in] prefix Prefix number.
+ * @return -1 when failure, 0 on success.
+ */
+int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network,
+ uint8_t prefix_length)
+{
+ uint8_t mask = ~0;
+ uint8_t tmp_p = prefix_length;
+ int i;
+
+ ARG_CHECK2(-1, network, broadcast);
+
+ if (32 < prefix_length) {
+ SRP_LOG_ERR_MSG("Prefix length to big.");
+ return -1;
+ }
+
+ for (i = 0; i < 4 ; i++) {
+ broadcast->address[i] = network->address[i] |
+ (mask >> (tmp_p > 8 ? 8 : tmp_p));
+ if (tmp_p >= 8) {
+ tmp_p -= 8;
+ } else {
+ tmp_p = 0;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Get last IPv4 address from the IP range.
+ *
+ * @param[out] last_ip_address Last Ipv4 address.
+ * @param[in] first_ip_address First IPv4 address.
+ * @param[in] prefix Prefix number.
+ * @return -1 when failure, 0 on success.
+ */
+int get_last_ip_address(sc_ipv4_addr* last_ip_address,
+ const sc_ipv4_addr* first_ip_address,
+ uint8_t prefix_length)
+{
+ return get_network_broadcast(last_ip_address, first_ip_address,
+ prefix_length);
+}
diff --git a/src/plugins/sys_util.h b/src/plugins/sys_util.h
index 6c227c3..d449712 100644
--- a/src/plugins/sys_util.h
+++ b/src/plugins/sys_util.h
@@ -34,4 +34,44 @@ void log_recv_event(sr_notif_event_t event, const char *msg);
void log_recv_oper(sr_change_oper_t oper, const char *msg);
int ip_prefix_split(const char* ip_prefix);
+/**
+ * @brief Get IPv4 host address from IPv4 prefix.
+ *
+ * @param[out] dst Host IPv4 address.
+ * @param[in] src IPv4 Prefix.
+ * @param[in] length dst buffer length.
+ * @param[out] prefix Get Prefix length, optional value. Can be NULL.
+ * @return -1 when failure, 0 on success.
+ */
+int get_address_from_prefix(char* dst, const char* src, size_t length,
+ uint8_t* prefix_length);
+
+typedef struct
+{
+ uint8_t address[4];
+} sc_ipv4_addr;
+
+/**
+ * @brief Get IPv4 broadcast IP address form IPv4 network address.
+ *
+ * @param[out] broadcat Broadcast Ipv4 address.
+ * @param[in] network Network IPv4 address.
+ * @param[in] prefix Prefix number.
+ * @return -1 when failure, 0 on success.
+ */
+int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network,
+ uint8_t prefix_length);
+
+/**
+ * @brief Get last IPv4 address from the IP range.
+ *
+ * @param[out] last_ip_address Last Ipv4 address.
+ * @param[in] first_ip_address First IPv4 address.
+ * @param[in] prefix Prefix number.
+ * @return -1 when failure, 0 on success.
+ */
+int get_last_ip_address(sc_ipv4_addr *last_ip_address,
+ const sc_ipv4_addr *first_ip_address,
+ uint8_t prefix_length);
+
#endif /* __SYS_UTIL_H__ */
diff --git a/src/scvpp/src/sc_vpp_comm.c b/src/scvpp/src/sc_vpp_comm.c
index 241b4ce..cd0b035 100644
--- a/src/scvpp/src/sc_vpp_comm.c
+++ b/src/scvpp/src/sc_vpp_comm.c
@@ -98,3 +98,16 @@ char* sc_ntoa(const u8 * buf)
memcpy(&addr, buf, sizeof(addr));
return inet_ntoa(addr);
}
+
+/**
+ * @brief Function converts the u8 array from network byte order to host byte order.
+ *
+ * @param[in] host IPv4 address.
+ * @return host byte order value.
+ */
+uint32_t hardntohlu32(uint8_t host[4])
+{
+ uint32_t tmp = host[3] | host[2] | host[1] | host[0];
+
+ return ntohl(tmp);
+}
diff --git a/src/scvpp/src/sc_vpp_comm.h b/src/scvpp/src/sc_vpp_comm.h
index 2405259..eeeaaf9 100644
--- a/src/scvpp/src/sc_vpp_comm.h
+++ b/src/scvpp/src/sc_vpp_comm.h
@@ -31,6 +31,8 @@ DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
#define VPP_IP4_ADDRESS_LEN 4
#define VPP_IP6_ADDRESS_LEN 16
#define VPP_IP4_ADDRESS_STRING_LEN 16
+#define VPP_IP4_PREFIX_STRING_LEN 19
+#define VPP_IP4_HOST_PREFIX_LEN 32
#define VPP_IP6_ADDRESS_STRING_LEN 46
#define VPP_MAC_ADDRESS_LEN 8
#define VPP_TAG_LEN VPP_INTFC_NAME_LEN
@@ -112,6 +114,14 @@ api_name##_cb (vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last,
int sc_aton(const char *cp, u8 * buf, size_t length);
char * sc_ntoa(const u8 * buf);
+/**
+ * @brief Function converts the u8 array from network byte order to host byte order.
+ *
+ * @param[in] host IPv4 address.
+ * @return host byte order value.
+ */
+uint32_t hardntohlu32(uint8_t host[4]);
+
/*
* VPP
*/