Merge c26ed59ecede290aa16461248ceaeea814fa3d68 on remote branch

Change-Id: I02be6148ba32e2b2afa1e474606b23e597e669a0
diff --git a/rmnetctl/cli/rmnetcli.c b/rmnetctl/cli/rmnetcli.c
index c02850b..a40be0a 100644
--- a/rmnetctl/cli/rmnetcli.c
+++ b/rmnetctl/cli/rmnetcli.c
@@ -222,6 +222,31 @@
 	printf(_2TABS"                         by inputting dev name\n\n");
 	printf("rmnetcli -n bridgelink  <dev_name>       Bridge a vnd and a dev");
 	printf(_2TABS" <vnd id>                by specifying dev id and vnd id\n\n");
+	printf("rmnetcli -n flowactivate <real dev>  activate a flow\n");
+	printf(_2TABS" <vnd_name>              string - vnd device name\n\n");
+	printf(_2TABS" <bearer_id>             int - bearer id\n\n");
+	printf(_2TABS" <flow id>               int - flow id\n\n");
+	printf(_2TABS" <ip type>               int - ip type\n\n");
+	printf(_2TABS" <handle>                int - flow handle\n\n");
+	printf("rmnetcli -n flowdel      <real dev> delete a flow\n");
+	printf(_2TABS" <vnd_name>              string - vnd device name\n\n");
+	printf(_2TABS" <bearer_id>              int - bearer id\n\n");
+	printf(_2TABS" <flow id>               int - flow id\n\n");
+	printf(_2TABS" <ip type>               int - ip type\n\n");
+	printf("rmnetcli -n flowcontrol  <real dev>");
+	printf(_2TABS" <vnd_name>              string - vnd device name\n\n");
+	printf(_2TABS" <bearer_id>             int - bearer id\n\n");
+	printf(_2TABS" <seq>                   int - sequence\n\n");
+	printf(_2TABS" <grant size>            int - grant size\n\n");
+	printf(_2TABS" <ack>                   int - ack\n\n");
+	printf("rmnetcli -n systemup      <real dev>\n");
+	printf(_2TABS" <vnd_name>              string - vnd device name\n\n");
+	printf(_2TABS" <instance>              int - bearer id\n\n");
+	printf(_2TABS" <eptype>                int - ep type\n\n");
+	printf(_2TABS" <iface_id>              int - iface id\n\n");
+	printf(_2TABS" <flags>                 int - flags\n\n");
+	printf("rmnetcli -n systemdown    <real dev> <vnd name> <instance>\n\n ");
+
 
 }
 
@@ -345,6 +370,72 @@
 							    argv[2],
 							    &error_number);
 		}
+		else if (!strcmp(*argv, "flowactivate")) {
+			_RMNETCLI_CHECKNULL(argv[1]);
+			_RMNETCLI_CHECKNULL(argv[2]);
+			_RMNETCLI_CHECKNULL(argv[3]);
+			_RMNETCLI_CHECKNULL(argv[4]);
+			_RMNETCLI_CHECKNULL(argv[5]);
+
+			return_code = rtrmnet_activate_flow(handle, argv[1], argv[2],
+							    _STRTOUI8(argv[3]),
+							    _STRTOI32(argv[4]),
+							    _STRTOUI32(argv[5]),
+							    _STRTOUI32(argv[6]),
+							    &error_number);
+
+		} else if (!strcmp(*argv, "flowdel")) {
+			_RMNETCLI_CHECKNULL(argv[1]);
+			_RMNETCLI_CHECKNULL(argv[2]);
+			_RMNETCLI_CHECKNULL(argv[3]);
+			_RMNETCLI_CHECKNULL(argv[4]);
+			_RMNETCLI_CHECKNULL(argv[5]);
+			return_code = rtrmnet_delete_flow(handle, argv[1], argv[2],
+							_STRTOUI8(argv[3]),
+							_STRTOUI32(argv[4]),
+							_STRTOI32(argv[5]),
+							&error_number);
+		} else if (!strcmp(*argv, "flowcontrol")) {
+			_RMNETCLI_CHECKNULL(argv[1]);
+			_RMNETCLI_CHECKNULL(argv[2]);
+			_RMNETCLI_CHECKNULL(argv[3]);
+			_RMNETCLI_CHECKNULL(argv[4]);
+			_RMNETCLI_CHECKNULL(argv[5]);
+			_RMNETCLI_CHECKNULL(argv[6]);
+
+
+			return_code = rtrmnet_control_flow(handle, argv[1], argv[2],
+							    _STRTOUI8(argv[3]),
+							    _STRTOUI32(argv[4]),
+							    _STRTOUI16(argv[5]),
+							    _STRTOUI8(argv[6]),
+							    &error_number);
+		} else if (!strcmp(*argv, "systemup")) {
+			_RMNETCLI_CHECKNULL(argv[1]);
+			_RMNETCLI_CHECKNULL(argv[2]);
+			_RMNETCLI_CHECKNULL(argv[3]);
+			_RMNETCLI_CHECKNULL(argv[4]);
+			_RMNETCLI_CHECKNULL(argv[5]);
+			_RMNETCLI_CHECKNULL(argv[6]);
+
+
+			return_code = rtrmnet_flow_state_up(handle, argv[1], argv[2],
+							    _STRTOUI32(argv[3]),
+							    _STRTOUI32(argv[4]),
+							    _STRTOUI32(argv[5]),
+							    _STRTOUI32(argv[6]),
+							    &error_number);
+		} else if (!strcmp(*argv, "systemdown")) {
+			_RMNETCLI_CHECKNULL(argv[1]);
+			_RMNETCLI_CHECKNULL(argv[2]);
+			_RMNETCLI_CHECKNULL(argv[3]);
+
+			return_code = rtrmnet_flow_state_down(handle, argv[1], argv[2],
+							    _STRTOUI32(argv[3]),
+							    &error_number);
+		}
+
+
 		goto end;
 	} else {
 		return_code = rmnetctl_init(&handle, &error_number);
diff --git a/rmnetctl/inc/librmnetctl.h b/rmnetctl/inc/librmnetctl.h
index 3d622bf..7ecbcb9 100644
--- a/rmnetctl/inc/librmnetctl.h
+++ b/rmnetctl/inc/librmnetctl.h
@@ -600,5 +600,50 @@
 int rtrmnet_ctl_bridgevnd(rmnetctl_hndl_t *hndl, char *devname, char *vndname,
 			  uint16_t *error_code);
 
+int rtrmnet_activate_flow(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint8_t bearer_id,
+			  uint32_t flow_id,
+			  int ip_type,
+			  uint32_t tcm_handle,
+			  uint16_t *error_code);
+
+int rtrmnet_delete_flow(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint8_t bearer_id,
+			  uint32_t flow_id,
+			  int ip_type,
+			  uint16_t *error_code);
+
+
+
+
+int rtrmnet_control_flow(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint8_t bearer_id,
+			  uint16_t sequence,
+			  uint32_t grantsize,
+			  uint8_t ack,
+			  uint16_t *error_code);
+
+int rtrmnet_flow_state_down(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint32_t instance,
+			  uint16_t *error_code);
+
+
+int rtrmnet_flow_state_up(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint32_t instance,
+			  uint32_t ep_type,
+			  uint32_t ifaceid,
+			  int flags,
+			  uint16_t *error_code);
+
 #endif /* not defined LIBRMNETCTL_H */
 
diff --git a/rmnetctl/src/librmnetctl.c b/rmnetctl/src/librmnetctl.c
index 731681a..d621f43 100644
--- a/rmnetctl/src/librmnetctl.c
+++ b/rmnetctl/src/librmnetctl.c
@@ -86,17 +86,63 @@
 #define NLMSG_TAIL(nmsg) \
     ((struct rtattr *) (((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
 
+#define NLMSG_DATA_SIZE  500
+
+#define CHECK_MEMSCPY(x) ({if (x < 0 ){return RMNETCTL_LIB_ERR;}})
+
 struct nlmsg {
 	struct nlmsghdr nl_addr;
 	struct ifinfomsg ifmsg;
-	char data[500];
+	char data[NLMSG_DATA_SIZE];
 };
 
-
-
 /*===========================================================================
 			LOCAL FUNCTION DEFINITIONS
 ===========================================================================*/
+/* Helper functions
+ * @brief helper function to implement a secure memcpy
+ * @details take source and destination buffer size into
+ *          considerations before copying
+ * @param dst destination buffer
+ * @param dst_size size of destination buffer
+ * @param src source buffer
+ * @param src_size size of source buffer
+ * @return size of the smallest of two buffer
+ */
+
+static inline size_t memscpy(void *dst, size_t dst_size, const void *src,
+			     size_t src_size) {
+	size_t min_size = dst_size < src_size ? dst_size : src_size;
+	memcpy(dst, src, min_size);
+	return min_size;
+}
+
+/*
+* @brief helper function to implement a secure memcpy
+ * for a concatenating buffer where offset is kept
+ * track of
+ * @details take source and destination buffer size into
+ *          considerations before copying
+ * @param dst destination buffer
+ * @param dst_size pointer used to decrement
+ * @param src source buffer
+ * @param src_size size of source buffer
+ * @return size of the remaining buffer
+ */
+
+
+static inline int  memscpy_repeat(void* dst, size_t *dst_size,
+	const void* src, size_t src_size)
+{
+	if( !dst_size || *dst_size <= src_size || !dst || !src)
+		return RMNETCTL_LIB_ERR;
+	else {
+		*dst_size -= memscpy(dst, *dst_size, src, src_size);
+	}
+	return *dst_size;
+}
+
+
 /*!
 * @brief Synchronous method to send and receive messages to and from the kernel
 * using  netlink sockets
@@ -124,7 +170,7 @@
 	uint8_t *request_buf, *response_buf;
 	struct nlmsghdr *nlmsghdr_val;
 	struct rmnet_nl_msg_s *rmnet_nl_msg_s_val;
-	ssize_t bytes_read = -1;
+	ssize_t bytes_read = -1, buffsize = MAX_BUF_SIZE - sizeof(struct nlmsghdr);
 	uint16_t return_code = RMNETCTL_API_ERR_HNDL_INVALID;
 	struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
 	request_buf = NULL;
@@ -165,7 +211,7 @@
 	nlmsghdr_val->nlmsg_pid = hndl->pid;
 	nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
 
-	memcpy((void *)NLMSG_DATA(request_buf), request,
+	memscpy((void *)NLMSG_DATA(request_buf), buffsize, request,
 	sizeof(struct rmnet_nl_msg_s));
 
 	rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
@@ -194,8 +240,8 @@
 		return_code = RMNETCTL_API_ERR_MESSAGE_RECEIVE;
 		break;
 	}
-
-	memcpy(response, (void *)NLMSG_DATA(response_buf),
+	buffsize = MAX_BUF_SIZE - sizeof(struct nlmsghdr);
+	memscpy(response, buffsize, (void *)NLMSG_DATA(response_buf),
 	sizeof(struct rmnet_nl_msg_s));
 	if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
 		return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
@@ -1081,11 +1127,14 @@
 	char *kind = "rmnet";
 	struct nlmsg req;
 	short id;
+	size_t reqsize;
 
-	if (!hndl || !devname || !vndname || !error_code)
+	if (!hndl || !devname || !vndname || !error_code ||
+	   _rmnetctl_check_dev_name(vndname) || _rmnetctl_check_dev_name(devname))
 		return RMNETCTL_INVALID_ARG;
 
 	memset(&req, 0, sizeof(req));
+	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
 	req.nl_addr.nlmsg_type = RTM_NEWLINK;
 	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
 	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL |
@@ -1104,9 +1153,10 @@
 	val = devindex;
 	attrinfo = (struct rtattr *)(((char *)&req) +
 				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
 	attrinfo->rta_type = IFLA_LINK;
 	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-	memcpy(RTA_DATA(attrinfo), &val, sizeof(val));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
 
@@ -1115,12 +1165,14 @@
 				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
 	attrinfo->rta_type =  IFLA_IFNAME;
 	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-	memcpy(RTA_DATA(attrinfo), vndname, strlen(vndname) + 1);
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
 
 	linkinfo = (struct rtattr *)(((char *)&req) +
 				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
 	linkinfo->rta_type = IFLA_LINKINFO;
 	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
@@ -1128,9 +1180,11 @@
 
 	attrinfo = (struct rtattr *)(((char *)&req) +
 				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
 	attrinfo->rta_type =  IFLA_INFO_KIND;
 	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-	memcpy(RTA_DATA(attrinfo), kind, strlen(kind));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
+
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
 
@@ -1146,7 +1200,7 @@
 				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
 	attrinfo->rta_type =  IFLA_VLAN_ID;
 	attrinfo->rta_len = RTA_LENGTH(sizeof(id));
-	memcpy(RTA_DATA(attrinfo), &id, sizeof(id));
+	*(short *)RTA_DATA(attrinfo) = id;
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(sizeof(id)));
 
@@ -1158,7 +1212,8 @@
 					     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
 		attrinfo->rta_type =  IFLA_VLAN_FLAGS;
 		attrinfo->rta_len = RTA_LENGTH(sizeof(flags));
-		memcpy(RTA_DATA(attrinfo), &flags, sizeof(flags));
+		CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flags,
+			       sizeof(flags)));
 		req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 					RTA_ALIGN(RTA_LENGTH(sizeof(flags)));
 	}
@@ -1217,15 +1272,17 @@
 	struct ifla_vlan_flags flags;
 	char *kind = "rmnet";
 	struct nlmsg req;
-	int devindex = 0;
-	int val = 0;
+	int devindex = 0, val = 0;
+	size_t reqsize;
 	short id;
 
 	memset(&req, 0, sizeof(req));
 
-	if (!hndl || !devname || !vndname || !error_code)
+	if (!hndl || !devname || !vndname || !error_code ||
+	    _rmnetctl_check_dev_name(vndname) || _rmnetctl_check_dev_name(devname))
 		return RMNETCTL_INVALID_ARG;
 
+	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
 	req.nl_addr.nlmsg_type = RTM_NEWLINK;
 	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
 	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -1246,16 +1303,17 @@
 
 	attrinfo->rta_type = IFLA_LINK;
 	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
-	memcpy(RTA_DATA(attrinfo), &val, sizeof(val));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
 
-	  /* Set up IFLA info kind  RMNET that has linkinfo and type */
+	/* Set up IFLA info kind  RMNET that has linkinfo and type */
 	attrinfo = (struct rtattr *)(((char *)&req) +
 				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
 	attrinfo->rta_type =  IFLA_IFNAME;
 	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
-	memcpy(RTA_DATA(attrinfo), vndname, strlen(vndname) + 1);
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
 
@@ -1267,19 +1325,18 @@
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(0));
 
-
 	attrinfo = (struct rtattr *)(((char *)&req) +
 				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
 
 	attrinfo->rta_type =  IFLA_INFO_KIND;
 	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
-	memcpy(RTA_DATA(attrinfo), kind, strlen(kind));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
+
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
 
 	datainfo = (struct rtattr *)(((char *)&req) +
 				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
-
 	datainfo->rta_type =  IFLA_INFO_DATA;
 	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
@@ -1290,7 +1347,7 @@
 				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
 	attrinfo->rta_type =  IFLA_VLAN_ID;
 	attrinfo->rta_len = RTA_LENGTH(sizeof(id));
-	memcpy(RTA_DATA(attrinfo), &id, sizeof(id));
+	*(short *)RTA_DATA(attrinfo) = id;
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(sizeof(id)));
 
@@ -1302,7 +1359,8 @@
 					     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
 		attrinfo->rta_type =  IFLA_VLAN_FLAGS;
 		attrinfo->rta_len = RTA_LENGTH(sizeof(flags));
-		memcpy(RTA_DATA(attrinfo), &flags, sizeof(flags));
+		CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flags,
+			       sizeof(flags)));
 		req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 					RTA_ALIGN(RTA_LENGTH(sizeof(flags)));
 	}
@@ -1325,11 +1383,13 @@
 	int devindex = 0, vndindex = 0;
 	struct rtattr *masterinfo;
 	struct nlmsg req;
+	size_t reqsize;
 
-	if (!hndl || !vndname || !devname || !error_code)
+	if (!hndl || !vndname || !devname || !error_code || _rmnetctl_check_dev_name(vndname))
 		return RMNETCTL_INVALID_ARG;
 
 	memset(&req, 0, sizeof(req));
+	reqsize = NLMSG_DATA_SIZE - sizeof(*masterinfo);
 	req.nl_addr.nlmsg_type = RTM_NEWLINK;
 	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
 	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
@@ -1356,7 +1416,7 @@
 
 	masterinfo->rta_type =  IFLA_MASTER;
 	masterinfo->rta_len = RTA_LENGTH(sizeof(vndindex));
-	memcpy(RTA_DATA(masterinfo), &vndindex, sizeof(vndindex));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(masterinfo), &reqsize, &vndindex, sizeof(vndindex)));
 	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
 				RTA_ALIGN(RTA_LENGTH(sizeof(vndindex)));
 
@@ -1367,3 +1427,551 @@
 
 	return rmnet_get_ack(hndl, error_code);
 }
+
+
+int rtrmnet_activate_flow(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint8_t bearer_id,
+			  uint32_t flow_id,
+			  int ip_type,
+			  uint32_t tcm_handle,
+			  uint16_t *error_code)
+{
+	struct rtattr *attrinfo, *datainfo, *linkinfo;
+	struct tcmsg  flowinfo;
+	char *kind = "rmnet";
+	struct nlmsg req;
+	int devindex = 0;
+	int val = 0;
+	size_t reqsize =0;
+
+	memset(&req, 0, sizeof(req));
+	memset(&flowinfo, 0, sizeof(flowinfo));
+
+
+	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+		_rmnetctl_check_dev_name(vndname))
+		return RMNETCTL_INVALID_ARG;
+
+	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
+	req.nl_addr.nlmsg_type = RTM_NEWLINK;
+	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	req.nl_addr.nlmsg_seq = hndl->transaction_id;
+	hndl->transaction_id++;
+
+	/* Get index of devname*/
+	devindex = if_nametoindex(devname);
+	if (devindex < 0) {
+		*error_code = errno;
+		return RMNETCTL_KERNEL_ERR;
+	}
+
+	/* Setup link attr with devindex as data */
+	val = devindex;
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	attrinfo->rta_type = IFLA_LINK;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+
+	/* Set up IFLA info kind  RMNET that has linkinfo and type */
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_IFNAME;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+
+	linkinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	linkinfo->rta_type = IFLA_LINKINFO;
+	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_INFO_KIND;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
+
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+
+	datainfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	datainfo->rta_type =  IFLA_INFO_DATA;
+	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	flowinfo.tcm_handle = tcm_handle;
+	flowinfo.tcm_family = 0x1;
+	flowinfo.tcm__pad1 = bearer_id;
+	flowinfo.tcm_ifindex = ip_type;
+	flowinfo.tcm_parent = flow_id;
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
+	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
+
+	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
+
+	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
+
+	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+		return RMNETCTL_LIB_ERR;
+	}
+
+	return rmnet_get_ack(hndl, error_code);
+}
+
+
+int rtrmnet_delete_flow(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint8_t bearer_id,
+			  uint32_t flow_id,
+			  int ip_type,
+			  uint16_t *error_code)
+{
+	struct rtattr *attrinfo, *datainfo, *linkinfo;
+	struct tcmsg  flowinfo;
+	char *kind = "rmnet";
+	struct nlmsg req;
+	int devindex = 0;
+	int val = 0;
+	size_t reqsize;
+
+	memset(&req, 0, sizeof(req));
+	memset(&flowinfo, 0, sizeof(flowinfo));
+
+	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+		_rmnetctl_check_dev_name(vndname))
+		return RMNETCTL_INVALID_ARG;
+
+	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
+	req.nl_addr.nlmsg_type = RTM_NEWLINK;
+	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	req.nl_addr.nlmsg_seq = hndl->transaction_id;
+	hndl->transaction_id++;
+
+	/* Get index of devname*/
+	devindex = if_nametoindex(devname);
+	if (devindex < 0) {
+		*error_code = errno;
+		return RMNETCTL_KERNEL_ERR;
+	}
+
+	/* Setup link attr with devindex as data */
+	val = devindex;
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	attrinfo->rta_type = IFLA_LINK;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+
+	/* Set up IFLA info kind  RMNET that has linkinfo and type */
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_IFNAME;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+
+	linkinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	linkinfo->rta_type = IFLA_LINKINFO;
+	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_INFO_KIND;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
+
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+
+	datainfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	datainfo->rta_type =  IFLA_INFO_DATA;
+	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	flowinfo.tcm_family = 0x2;
+	flowinfo.tcm_ifindex = ip_type;
+	flowinfo.tcm__pad1 = bearer_id;
+	flowinfo.tcm_parent = flow_id;
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
+	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
+
+
+	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
+
+	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
+
+	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+		return RMNETCTL_LIB_ERR;
+	}
+
+	return rmnet_get_ack(hndl, error_code);
+}
+
+int rtrmnet_control_flow(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint8_t bearer_id,
+			  uint16_t sequence,
+			  uint32_t grantsize,
+			  uint8_t ack,
+			  uint16_t *error_code)
+{
+	struct rtattr *attrinfo, *datainfo, *linkinfo;
+	struct tcmsg  flowinfo;
+	char *kind = "rmnet";
+	struct nlmsg req;
+	int devindex = 0;
+	int val = 0;
+	size_t reqsize;
+
+	memset(&req, 0, sizeof(req));
+	memset(&flowinfo, 0, sizeof(flowinfo));
+
+	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+		_rmnetctl_check_dev_name(vndname))
+		return RMNETCTL_INVALID_ARG;
+
+	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
+	req.nl_addr.nlmsg_type = RTM_NEWLINK;
+	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	req.nl_addr.nlmsg_seq = hndl->transaction_id;
+	hndl->transaction_id++;
+
+	/* Get index of devname*/
+	devindex = if_nametoindex(devname);
+	if (devindex < 0) {
+		*error_code = errno;
+		return RMNETCTL_KERNEL_ERR;
+	}
+
+	/* Setup link attr with devindex as data */
+	val = devindex;
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	attrinfo->rta_type = IFLA_LINK;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+
+	/* Set up IFLA info kind  RMNET that has linkinfo and type */
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_IFNAME;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+
+	linkinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	linkinfo->rta_type = IFLA_LINKINFO;
+	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	attrinfo->rta_type =  IFLA_INFO_KIND;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+
+	datainfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	datainfo->rta_type =  IFLA_INFO_DATA;
+	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	flowinfo.tcm_family = 0x3;
+	flowinfo.tcm__pad1 = bearer_id;
+	flowinfo.tcm__pad2 = sequence;
+	flowinfo.tcm_parent = ack;
+	flowinfo.tcm_info = grantsize;
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
+	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
+
+	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
+	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
+
+	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+		return RMNETCTL_LIB_ERR;
+	}
+
+	return rmnet_get_ack(hndl, error_code);
+}
+
+
+int rtrmnet_flow_state_up(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint32_t instance,
+			  uint32_t ep_type,
+			  uint32_t ifaceid,
+			  int flags,
+			  uint16_t *error_code)
+{
+	struct rtattr *attrinfo, *datainfo, *linkinfo;
+	struct tcmsg  flowinfo;
+	char *kind = "rmnet";
+	struct nlmsg req;
+	int devindex = 0;
+	int val = 0;
+	size_t reqsize;
+
+	memset(&req, 0, sizeof(req));
+	memset(&flowinfo, 0, sizeof(flowinfo));
+
+	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+		_rmnetctl_check_dev_name(vndname))
+		return RMNETCTL_INVALID_ARG;
+
+	reqsize = NLMSG_DATA_SIZE - sizeof(*attrinfo);
+	req.nl_addr.nlmsg_type = RTM_NEWLINK;
+	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	req.nl_addr.nlmsg_seq = hndl->transaction_id;
+	hndl->transaction_id++;
+
+	/* Get index of devname*/
+	devindex = if_nametoindex(devname);
+	if (devindex < 0) {
+		*error_code = errno;
+		return RMNETCTL_KERNEL_ERR;
+	}
+
+	/* Setup link attr with devindex as data */
+	val = devindex;
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	attrinfo->rta_type = IFLA_LINK;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+
+	/* Set up IFLA info kind  RMNET that has linkinfo and type */
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_IFNAME;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+
+	linkinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	linkinfo->rta_type = IFLA_LINKINFO;
+	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_INFO_KIND;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
+
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+
+	datainfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	datainfo->rta_type =  IFLA_INFO_DATA;
+	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	flowinfo.tcm_handle = instance;
+	flowinfo.tcm_family = 0x4;
+	flowinfo.tcm_ifindex = flags;
+	flowinfo.tcm_parent = ifaceid;
+	flowinfo.tcm_info = ep_type;
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
+	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
+
+	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
+	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
+
+	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+		return RMNETCTL_LIB_ERR;
+	}
+
+	return rmnet_get_ack(hndl, error_code);
+}
+
+
+int rtrmnet_flow_state_down(rmnetctl_hndl_t *hndl,
+			  char *devname,
+			  char *vndname,
+			  uint32_t instance,
+			  uint16_t *error_code)
+{
+	struct rtattr *attrinfo, *datainfo, *linkinfo;
+	struct tcmsg  flowinfo;
+	char *kind = "rmnet";
+	struct nlmsg req;
+	int devindex = 0;
+	int val = 0;
+	size_t reqsize;
+
+	memset(&req, 0, sizeof(req));
+	memset(&flowinfo, 0, sizeof(flowinfo));
+
+	if (!hndl || !devname || !error_code ||_rmnetctl_check_dev_name(devname) ||
+		_rmnetctl_check_dev_name(vndname))
+		return RMNETCTL_INVALID_ARG;
+
+	reqsize = NLMSG_DATA_SIZE - sizeof(struct rtattr);
+	req.nl_addr.nlmsg_type = RTM_NEWLINK;
+	req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	req.nl_addr.nlmsg_seq = hndl->transaction_id;
+	hndl->transaction_id++;
+
+	/* Get index of devname*/
+	devindex = if_nametoindex(devname);
+	if (devindex < 0) {
+		*error_code = errno;
+		return RMNETCTL_KERNEL_ERR;
+	}
+
+	/* Setup link attr with devindex as data */
+	val = devindex;
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	attrinfo->rta_type = IFLA_LINK;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &val, sizeof(val)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(val)));
+
+	/* Set up IFLA info kind  RMNET that has linkinfo and type */
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_IFNAME;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, vndname, strlen(vndname) + 1));
+
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1));
+
+	linkinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	linkinfo->rta_type = IFLA_LINKINFO;
+	linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	attrinfo->rta_type =  IFLA_INFO_KIND;
+	attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, kind, strlen(kind)));
+
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(strlen(kind)));
+
+	datainfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+
+	datainfo->rta_type =  IFLA_INFO_DATA;
+	datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(0));
+
+	flowinfo.tcm_handle = instance;
+	flowinfo.tcm_family = 0x5;
+
+	attrinfo = (struct rtattr *)(((char *)&req) +
+				     NLMSG_ALIGN(req.nl_addr.nlmsg_len));
+	attrinfo->rta_type =  IFLA_VLAN_EGRESS_QOS;
+	attrinfo->rta_len = RTA_LENGTH(sizeof(flowinfo));
+	CHECK_MEMSCPY(memscpy_repeat(RTA_DATA(attrinfo), &reqsize, &flowinfo, sizeof(flowinfo)));
+	req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) +
+				RTA_ALIGN(RTA_LENGTH(sizeof(flowinfo)));
+
+
+	datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo;
+	linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo;
+
+	if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) {
+		*error_code = RMNETCTL_API_ERR_MESSAGE_SEND;
+		return RMNETCTL_LIB_ERR;
+	}
+
+	return rmnet_get_ack(hndl, error_code);
+}