diff --git a/lib/librte_ctrl_if/Makefile b/lib/librte_ctrl_if/Makefile
index 0da04f7d0..67b9967b4 100644
--- a/lib/librte_ctrl_if/Makefile
+++ b/lib/librte_ctrl_if/Makefile
@@ -46,6 +46,7 @@ LIBABIVER := 1
 
 SRCS-$(CONFIG_RTE_LIBRTE_CTRL_IF) := rte_ctrl_if.c
 SRCS-$(CONFIG_RTE_LIBRTE_CTRL_IF) += rte_nl.c
+SRCS-$(CONFIG_RTE_LIBRTE_CTRL_IF) += rte_ctrl_process.c
 
 #
 # Export include files
diff --git a/lib/librte_ctrl_if/rte_ctrl_process.c b/lib/librte_ctrl_if/rte_ctrl_process.c
new file mode 100644
index 000000000..cfb243f64
--- /dev/null
+++ b/lib/librte_ctrl_if/rte_ctrl_process.c
@@ -0,0 +1,167 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <error.h>
+
+#include <linux/if_link.h>
+
+#include <rte_version.h>
+#include <rte_ethdev.h>
+#include "rte_ctrl_process.h"
+
+static int
+set_mtu(uint8_t port_id, void *in_data)
+{
+	int *mtu = in_data;
+
+	return rte_eth_dev_set_mtu(port_id, *mtu);
+}
+
+static int
+get_stats(uint8_t port_id, void *data, size_t *data_len)
+{
+	struct rte_eth_stats stats;
+	struct rtnl_link_stats64 *if_stats = data;
+	int ret;
+
+	ret = rte_eth_stats_get(port_id, &stats);
+	if (ret < 0)
+		return -EOPNOTSUPP;
+
+	if_stats->rx_packets = stats.ipackets;
+	if_stats->tx_packets = stats.opackets;
+	if_stats->rx_bytes = stats.ibytes;
+	if_stats->tx_bytes = stats.obytes;
+	if_stats->rx_errors = stats.ierrors;
+	if_stats->tx_errors = stats.oerrors;
+	if_stats->rx_dropped = stats.imissed;
+
+	*data_len = sizeof(struct rtnl_link_stats64);
+
+	return 0;
+}
+
+static int
+get_mac(uint8_t port_id, void *data, size_t *data_len)
+{
+	struct ether_addr addr;
+
+	rte_eth_macaddr_get(port_id, &addr);
+	memcpy(data, &addr, sizeof(struct ether_addr));
+
+	*data_len = sizeof(struct ether_addr);
+
+	return 0;
+}
+
+static int
+set_mac(uint8_t port_id, void *in_data)
+{
+	struct ether_addr addr;
+
+	memcpy(&addr, in_data, ETHER_ADDR_LEN);
+
+	return rte_eth_dev_default_mac_addr_set(port_id, &addr);
+}
+
+static int
+start_port(uint8_t port_id)
+{
+	rte_eth_dev_stop(port_id);
+	return rte_eth_dev_start(port_id);
+}
+
+static int
+stop_port(uint8_t port_id)
+{
+	rte_eth_dev_stop(port_id);
+	return 0;
+}
+
+static int
+set_promisc(uint8_t port_id, void *in_data)
+{
+	int *promisc = in_data;
+
+	if (*promisc)
+		rte_eth_promiscuous_enable(port_id);
+	else
+		rte_eth_promiscuous_disable(port_id);
+
+	return 0;
+}
+
+static int
+set_allmulti(uint8_t port_id, void *in_data)
+{
+	int *allmulti = in_data;
+
+	if (*allmulti)
+		rte_eth_allmulticast_enable(port_id);
+	else
+		rte_eth_allmulticast_disable(port_id);
+
+	return 0;
+}
+
+int
+rte_eth_dev_control_process(uint32_t cmd_id, uint8_t port_id, void *in_data,
+		void *out_data, size_t *out_data_len)
+{
+	if (!rte_eth_dev_is_valid_port(port_id))
+		return -ENODEV;
+
+	switch (cmd_id) {
+	case UNCI_REQ_CHANGE_MTU:
+		return set_mtu(port_id, in_data);
+	case UNCI_REQ_GET_STATS:
+		return get_stats(port_id, out_data, out_data_len);
+	case UNCI_REQ_GET_MAC:
+		return get_mac(port_id, out_data, out_data_len);
+	case UNCI_REQ_SET_MAC:
+		return set_mac(port_id, in_data);
+	case UNCI_REQ_START_PORT:
+		return start_port(port_id);
+	case UNCI_REQ_STOP_PORT:
+		return stop_port(port_id);
+	case UNCI_REQ_SET_PROMISC:
+		return set_promisc(port_id, in_data);
+	case UNCI_REQ_SET_ALLMULTI:
+		return set_allmulti(port_id, in_data);
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
diff --git a/lib/librte_ctrl_if/rte_ctrl_process.h b/lib/librte_ctrl_if/rte_ctrl_process.h
new file mode 100644
index 000000000..f67c60107
--- /dev/null
+++ b/lib/librte_ctrl_if/rte_ctrl_process.h
@@ -0,0 +1,50 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_CTRL_ETHTOOL_H_
+#define _RTE_CTRL_ETHTOOL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <exec-env/rte_unci_common.h>
+
+int rte_eth_dev_control_process(uint32_t cmd_id, uint8_t port_id, void *in_data,
+		void *out_data, size_t *out_data_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CTRL_ETHTOOL_H_ */
diff --git a/lib/librte_ctrl_if/rte_nl.c b/lib/librte_ctrl_if/rte_nl.c
index e88b3fc91..920d123a9 100644
--- a/lib/librte_ctrl_if/rte_nl.c
+++ b/lib/librte_ctrl_if/rte_nl.c
@@ -39,6 +39,7 @@
 
 #include <rte_spinlock.h>
 #include <rte_log.h>
+#include "rte_ctrl_process.h"
 #include "rte_nl.h"
 #include "rte_ctrl_if.h"
 
@@ -54,12 +55,139 @@ struct ctrl_if_nl {
 	struct sockaddr_nl dest_addr;
 };
 
+struct ctrl_if_msg_sync {
+	struct unci_nl_msg msg_storage;
+	pthread_mutex_t msg_lock;
+	uint32_t pending_process;
+};
+
+
+/**
+ * Flags values for rte_eth_control_interface_process_msg() API
+ */
+enum control_interface_process_flag {
+	/**< Process if msg available. */
+	RTE_ETHTOOL_CTRL_IF_PROCESS_MSG,
+
+	/**< Discard msg if available, respond with a error value. */
+	RTE_ETHTOOL_CTRL_IF_DISCARD_MSG,
+};
+
 static int sock_fd = -1;
 static pthread_t thread_id;
 
 static struct ctrl_if_nl nl_s;
 static struct ctrl_if_nl nl_r;
 
+static struct ctrl_if_msg_sync ctrl_if_sync = {
+	.msg_lock = PTHREAD_MUTEX_INITIALIZER,
+};
+
+static int
+nl_send(void *buf, size_t len)
+{
+	int ret;
+
+	if (nl_s.nlh.nlmsg_len < len) {
+		RTE_LOG(ERR, CTRL_IF, "Message is too big, len:%zu\n", len);
+		return -1;
+	}
+
+	if (!NLMSG_OK(&nl_s.nlh, NLMSG_SPACE(MAX_PAYLOAD))) {
+		RTE_LOG(ERR, CTRL_IF, "Message is not OK\n");
+		return -1;
+	}
+
+	/* Fill in the netlink message payload */
+	memcpy(NLMSG_DATA(nl_s.nlmsg), buf, len);
+
+	ret = sendmsg(sock_fd, &nl_s.msg, 0);
+
+	if (ret < 0)
+		RTE_LOG(ERR, CTRL_IF, "Failed nl msg send. ret:%d, err:%d\n",
+				ret, errno);
+	return ret;
+}
+
+/* each request sent expects a reply */
+static int
+nl_reply(struct unci_nl_msg *msg)
+{
+	return nl_send((void *)msg, sizeof(struct unci_nl_msg));
+}
+
+static void
+process_msg(struct unci_nl_msg *msg)
+{
+	if (msg->cmd_id > UNCI_REQ_UNKNOWN) {
+		msg->err = rte_eth_dev_control_process(msg->cmd_id,
+				msg->port_id, msg->input_buffer,
+				msg->output_buffer, &msg->output_buffer_len);
+	}
+
+	if (msg->err)
+		memset(msg->output_buffer, 0, msg->output_buffer_len);
+
+	nl_reply(msg);
+}
+
+static int
+control_interface_msg_process(uint32_t flag)
+{
+	struct unci_nl_msg msg_storage;
+	int ret = 0;
+
+	pthread_mutex_lock(&ctrl_if_sync.msg_lock);
+	if (ctrl_if_sync.pending_process == 0) {
+		pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+		return 0;
+	}
+
+	memcpy(&msg_storage, &ctrl_if_sync.msg_storage,
+			sizeof(struct unci_nl_msg));
+	ctrl_if_sync.pending_process = 0;
+	pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+
+	switch (flag) {
+	case RTE_ETHTOOL_CTRL_IF_PROCESS_MSG:
+		process_msg(&msg_storage);
+		break;
+
+	case RTE_ETHTOOL_CTRL_IF_DISCARD_MSG:
+		msg_storage.err = -1;
+		nl_reply(&msg_storage);
+		break;
+
+	default:
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int
+msg_add_and_process(struct nlmsghdr *nlh)
+{
+	pthread_mutex_lock(&ctrl_if_sync.msg_lock);
+
+	if (ctrl_if_sync.pending_process) {
+		pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+		return -1;
+	}
+
+	memcpy(&ctrl_if_sync.msg_storage, NLMSG_DATA(nlh),
+			sizeof(struct unci_nl_msg));
+	ctrl_if_sync.msg_storage.flag = UNCI_MSG_FLAG_RESPONSE;
+	ctrl_if_sync.pending_process = 1;
+
+	pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+
+	control_interface_msg_process(RTE_ETHTOOL_CTRL_IF_PROCESS_MSG);
+
+	return 0;
+}
+
 static void *
 nl_recv(void *arg)
 {
@@ -76,6 +204,8 @@ nl_recv(void *arg)
 					ret, sizeof(struct unci_nl_msg));
 			continue;
 		}
+
+		msg_add_and_process(&nl_r.nlh);
 	}
 
 	return arg;
