librmnetctl: Egress qos for rmnet driver
Additional flow control support added for rmnet driver. Supported by the addition of IFLA_VLAN_EGRESS_QOS netlink attributes in rmnet driver and this RTM_NEWLINK message configuration api. • flow_activate (uint16 bearer_id, uint32 flow_id, uint8 ip_type, uint32 tcm_handle) • flow_delete (uint16 bearer_id) • flow_control (uint16 bearer_id, uint32 grant_size, uint16 seq, uint8 ack) • flow_state_up (uint16 instance, uint32 ep_type, uint32 iface_id) • flow_state_down (uint16 instance) CRs-Fixed: 2224576 Change-Id: Ib8b337c840631ef8a3d36884e42a4faea153ba18
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
parent
2b07e91d73
commit
d0f3eca57d
@@ -222,6 +222,31 @@ static void rmnet_api_usage(void)
|
||||
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 @@ static int rmnet_api_call(int argc, char *argv[])
|
||||
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);
|
||||
|
||||
@@ -600,5 +600,50 @@ int rtrmnet_ctl_changevnd(rmnetctl_hndl_t *hndl, char *devname, char *vndname,
|
||||
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 */
|
||||
|
||||
|
||||
@@ -1367,3 +1367,541 @@ int rtrmnet_ctl_bridgevnd(rmnetctl_hndl_t *hndl, char *devname, char *vndname,
|
||||
|
||||
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;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&flowinfo, 0, sizeof(flowinfo));
|
||||
|
||||
|
||||
if (!hndl || !devname || !error_code)
|
||||
return RMNETCTL_INVALID_ARG;
|
||||
|
||||
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)));
|
||||
memcpy(RTA_DATA(attrinfo), &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));
|
||||
memcpy(RTA_DATA(attrinfo), 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)));
|
||||
memcpy(RTA_DATA(attrinfo), 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));
|
||||
memcpy(RTA_DATA(attrinfo), &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;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&flowinfo, 0, sizeof(flowinfo));
|
||||
|
||||
if (!hndl || !devname || !error_code)
|
||||
return RMNETCTL_INVALID_ARG;
|
||||
|
||||
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)));
|
||||
memcpy(RTA_DATA(attrinfo), &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));
|
||||
memcpy(RTA_DATA(attrinfo), 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)));
|
||||
memcpy(RTA_DATA(attrinfo), 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));
|
||||
memcpy(RTA_DATA(attrinfo), &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;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&flowinfo, 0, sizeof(flowinfo));
|
||||
|
||||
|
||||
if (!hndl || !devname || !error_code)
|
||||
return RMNETCTL_INVALID_ARG;
|
||||
|
||||
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)));
|
||||
memcpy(RTA_DATA(attrinfo), &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));
|
||||
memcpy(RTA_DATA(attrinfo), 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)));
|
||||
memcpy(RTA_DATA(attrinfo), 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));
|
||||
memcpy(RTA_DATA(attrinfo), &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;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&flowinfo, 0, sizeof(flowinfo));
|
||||
|
||||
|
||||
if (!hndl || !devname || !error_code)
|
||||
return RMNETCTL_INVALID_ARG;
|
||||
|
||||
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)));
|
||||
memcpy(RTA_DATA(attrinfo), &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));
|
||||
memcpy(RTA_DATA(attrinfo), 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)));
|
||||
memcpy(RTA_DATA(attrinfo), 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));
|
||||
memcpy(RTA_DATA(attrinfo), &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;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&flowinfo, 0, sizeof(flowinfo));
|
||||
|
||||
|
||||
if (!hndl || !devname || !error_code)
|
||||
return RMNETCTL_INVALID_ARG;
|
||||
|
||||
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)));
|
||||
memcpy(RTA_DATA(attrinfo), &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));
|
||||
memcpy(RTA_DATA(attrinfo), 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)));
|
||||
memcpy(RTA_DATA(attrinfo), 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));
|
||||
memcpy(RTA_DATA(attrinfo), &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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user