Files
m241Neelima/components/ip_net2-6.9/ipnet2/src/ipnet_cmd_qos.c
T
2026-07-30 11:19:44 +05:30

1069 lines
38 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_cmd_qos.c,v $ $Revision: 1.24.10.2 $
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_qos.c,v $
* $Author: svc-cmnet $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#ifdef IPCOM_KERNEL
#undef IPCOM_KERNEL
#endif
#include "ipnet_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_cmd.h>
#include <ipcom_getopt.h>
#include "ipnet.h"
#include "ipnet_policy_routing.h"
#ifdef IPCOM_USE_INET6
#include "ipnet_ip6.h"
#endif
#include "ipnet_qos.h"
#include "ipnet_diffserv.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* Operations */
#define IPNET_CMD_QOS_OP_ADD 1 /* Add something */
#define IPNET_CMD_QOS_OP_DEL 2 /* Delete somthing */
#define IPNET_CMD_QOS_OP_GET 3 /* Get something */
#define IPNET_CMD_QOS_OP_LIST 4 /* List something */
/* Operation types */
#define IPNET_CMD_QOS_T_POLICY_RT 1 /* Policy routing */
#if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA)
#define IPNET_CMD_QOS_T_DS_FILTER 2 /* Differ Server */
#endif
/* Errors */
#define IPNET_CMD_ERR -1
#define IPNET_CMD_ERR_UNSUPPORTED_OP -2
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
*===========================================================================
* Ipnet_cmd_qos
*===========================================================================
*/
typedef struct Ipnet_cmd_qos_struct
{
int sock;
int op; /* Operation IPNET_CMD_QOS_OP_xxx */
int op_type; /* Operation type IPNET_CMD_QOS_T_xxx */
int domain; /* Domain the rule applies to (IP_AF_INET | IP_AF_INET6) */
union
{
struct Ipnet_policy_routing_rule rule;
struct
{
struct Ipnet_ds_filter filter;
struct Ipnet_ds_map map;
struct Ipnet_ds handler;
} ds;
} d;
}
Ipnet_cmd_qos;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_STATIC Ipcom_cmd_int_str_map ipnet_cmd_qos_ops[] =
{
{ IPNET_CMD_QOS_OP_ADD, "add" },
{ IPNET_CMD_QOS_OP_DEL, "del" },
{ IPNET_CMD_QOS_OP_DEL, "delete" },
{ IPNET_CMD_QOS_OP_GET, "get" },
{ IPNET_CMD_QOS_OP_LIST,"list" },
{ -1, IP_NULL }
};
#ifdef IPCOM_USE_INET6
IP_STATIC Ipcom_cmd_int_str_map ipnet_cmd_qos_scope[] =
{
{ IPNET_IP6_SCOPE_GLOBAL, "global" },
{ IPNET_IP6_SCOPE_NODE_LOCAL, "node" },
{ IPNET_IP6_SCOPE_LINK_LOCAL, "link" },
{ IPNET_IP6_SCOPE_SITE_LOCAL, "site" },
{ IPNET_IP6_SCOPE_ORG_LOCAL, "org" },
{ -1, IP_NULL }
};
#endif /* IPCOM_USE_INET6 */
IP_STATIC Ipcom_cmd_int_str_map ipnet_cmd_qos_types[] =
{
{ IPNET_CMD_QOS_T_POLICY_RT, "policy" },
#if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA)
{ IPNET_CMD_QOS_T_DS_FILTER, "filter" },
#endif
{ -1, IP_NULL }
};
#if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA)
IP_STATIC Ipcom_cmd_int_str_map ipnet_cmd_qos_sm_drop_precedence[] =
{
{ IPCOM_PKT_DROP_PRECEDENCE_LOW, "low" },
{ IPCOM_PKT_DROP_PRECEDENCE_MEDIUM, "medium" },
{ IPCOM_PKT_DROP_PRECEDENCE_HIGH, "high" },
{ -1, IP_NULL }
};
IP_STATIC Ipcom_cmd_int_str_map ipnet_cmd_qos_srtcm_mode[] =
{
{ IPNET_DS_SRTCM_MODE_COLOR_BLIND, "blind" },
{ IPNET_DS_SRTCM_MODE_COLOR_AWARE, "aware" },
{ -1, IP_NULL }
};
#endif
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipcom_cmd_qos_print_policy_rule
*===========================================================================
* Description: Prints a policy rule to the standard output.
* Parameters: rule - Rule to print.
* Returns:
*
*/
IP_STATIC void
ipcom_cmd_qos_print_policy_rule(struct Ipnet_policy_routing_rule *rule)
{
char str[48];
ipcom_printf("Policy routing rule id %u prio %d:"IP_LF, (unsigned)rule->id, (int)rule->prio);
ipcom_printf(" %-10s: %-10s"IP_LF, "domain", rule->af == IP_AF_INET ? "INET" : "INET6");
ipcom_printf(" %-10s: %-10u"IP_LF, "table", (unsigned) rule->table);
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_RTKEYSADDR))
ipcom_printf(" %-10s: %-10s"IP_LF, "lookup", "reverse");
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_DS))
ipcom_printf(" %-10s: %-10u"IP_LF, rule->af == IP_AF_INET ? "tos" : "tclass", rule->ds);
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_IFINDEX))
ipcom_printf(" %-10s: %-10u"IP_LF, "ifindex", (unsigned)rule->ifindex);
#ifdef IPCOM_USE_INET6
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_SCOPE))
ipcom_printf(" %-10s: %-10s"IP_LF, "scope",
ipcom_cmd_key_to_str(ipnet_cmd_qos_scope, (int)rule->scope, str, sizeof(str)));
#endif /* IPCOM_USE_INET6 */
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_SADDR))
ipcom_printf(" %-10s: %-10s/%d"IP_LF,
"from",
ipcom_inet_ntop(rule->af, &rule->saddr, str, sizeof(str)),
rule->saddr_prefixlen);
if (IP_BIT_ISSET(rule->mask, IPNET_PR_RULE_DADDR))
ipcom_printf(" %-10s: %-10s/%d"IP_LF,
"to",
ipcom_inet_ntop(rule->af, &rule->daddr, str, sizeof(str)),
rule->daddr_prefixlen);
ipcom_printf(" %-10s: %-10s"IP_LF, "last", rule->last ? "TRUE" : "FALSE");
/* Line break */
ipcom_printf(IP_LF);
}
/*
*===========================================================================
* ipnet_cmd_qos_policy_routing
*===========================================================================
* Description: Handles the policy subcommand.
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipnet_cmd_qos_policy_routing(Ipnet_cmd_qos *cmd, char **argv)
{
IP_STATIC Ipcom_cmd_int_str_map ipnet_cmd_qos_args[] =
{
/* Indexes <10 has must have one integer argument
>=10 to <100 has one argument that needs custom argument parsing
>=100 have no argument */
{ 2, "tos" },
{ 2, "tclass" },
{ 4, "table" },
{ 5, "prio" },
{ 7, "ifindex" },
{ 8, "id" },
{ 8, "index" }, /* Let 'index' be and alias for 'id' since
the documentation said index instead of id */
{ 10, "from" },
#ifdef IPCOM_USE_INET6
{ 11, "scope" },
#endif
{ 12, "to" },
{ 100, "last" },
{ 101, "reverse" },
{ -1, IP_NULL }
};
int c;
int i = 0;
char *p = IP_NULL;
char *str_prefixlen;
Ip_u8 prefix_len;
cmd->d.rule.af = (Ip_u8) cmd->domain;
cmd->d.rule.id = IPNET_PR_ID_NONE;
cmd->d.rule.table = IPCOM_ROUTE_TABLE_DEFAULT;
while (*argv != IP_NULL)
{
c = ipcom_cmd_str_to_key(ipnet_cmd_qos_args, *argv);
if (c == -1)
{
ipcom_printf("'%s' is an unknown argument"IP_LF, *argv);
return IPNET_CMD_ERR;
}
if (c < 100)
{
if (argv[1] == IP_NULL)
{
ipcom_printf("Parameter needed for argument %s"IP_LF, argv[0]);
return IPNET_CMD_ERR;
}
argv++;
if (c < 10)
i = ipcom_atoi(*argv);
else
p = *argv;
}
switch (c)
{
case 2:
IP_BIT_SET(cmd->d.rule.mask, IPNET_PR_RULE_DS);
cmd->d.rule.ds = (Ip_u8) i;
break;
case 4:
cmd->d.rule.table = (Ip_u32) i;
break;
case 5:
cmd->d.rule.prio = (Ip_s16) i;
break;
case 7:
IP_BIT_SET(cmd->d.rule.mask, IPNET_PR_RULE_IFINDEX);
cmd->d.rule.ifindex = (Ip_u32) i;
break;
case 8:
cmd->d.rule.id = (Ip_u32) i;
break;
case 10:
case 12:
str_prefixlen = ipcom_strstr(p, "/");
if (str_prefixlen == IP_NULL || ipcom_strlen(p) <= 1)
prefix_len = 0;
else
{
*str_prefixlen = '\0';
prefix_len = (Ip_u8) ipcom_atoi(str_prefixlen + 1);
}
if (c == 10)
{
if (ipcom_inet_pton(cmd->domain, p, &cmd->d.rule.saddr) != 1)
{
ipcom_printf("'%s' is not a valid IP address" IP_LF, p);
return IPNET_CMD_ERR;
}
IP_BIT_SET(cmd->d.rule.mask, IPNET_PR_RULE_SADDR);
cmd->d.rule.saddr_prefixlen = prefix_len;
}
else
{
if (ipcom_inet_pton(cmd->domain, p, &cmd->d.rule.daddr) != 1)
{
ipcom_printf("'%s' is not a valid IP address" IP_LF, p);
return IPNET_CMD_ERR;
}
IP_BIT_SET(cmd->d.rule.mask, IPNET_PR_RULE_DADDR);
cmd->d.rule.daddr_prefixlen = prefix_len;
}
break;
#ifdef IPCOM_USE_INET6
case 11:
IP_BIT_SET(cmd->d.rule.mask, IPNET_PR_RULE_SCOPE);
if (ipcom_cmd_str_to_key(ipnet_cmd_qos_scope, p) < 0)
{
ipcom_printf("'%s' is not one of global,link,site,node or org"IP_LF, p);
return IPNET_CMD_ERR;
}
cmd->d.rule.scope = (Ip_u32) ipcom_cmd_str_to_key(ipnet_cmd_qos_scope, p);
break;
#endif /* IPCOM_USE_INET6 */
case 100:
cmd->d.rule.last = IP_TRUE;
break;
case 101:
IP_BIT_SET(cmd->d.rule.mask, IPNET_PR_RULE_RTKEYSADDR);
break;
default:
IP_PANIC();
break;
}
argv++;
}
switch (cmd->op)
{
case IPNET_CMD_QOS_OP_ADD:
if (ipcom_socketioctl(cmd->sock, IPNET_SIOCSPRRULE, &cmd->d.rule) < 0)
ipcom_perror("Failed to add policy routing rule");
return 0;
case IPNET_CMD_QOS_OP_DEL:
if (ipcom_socketioctl(cmd->sock, IPNET_SIOCDPRRULE, &cmd->d.rule) < 0)
ipcom_perror("Failed to delete policy routing rule");
return 0;
case IPNET_CMD_QOS_OP_GET:
if (ipcom_socketioctl(cmd->sock, IPNET_SIOCGPRRULE, &cmd->d.rule) < 0)
ipcom_perror("Failed to get policy routing rule");
else
ipcom_cmd_qos_print_policy_rule(&cmd->d.rule);
return 0;
case IPNET_CMD_QOS_OP_LIST:
while (ipcom_socketioctl(cmd->sock, IPNET_SIOCEPRRULE, &cmd->d.rule) == 0)
ipcom_cmd_qos_print_policy_rule(&cmd->d.rule);
return 0;
default:
return IPNET_CMD_ERR_UNSUPPORTED_OP;
}
}
#if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA)
/*
*===========================================================================
* ipcom_cmd_qos_print_ds_infor
*===========================================================================
* Description: Prints a filter to the standard output.
* Parameters: ds_infor - filter information to print.
* Returns: void
*
*/
IP_STATIC void
ipcom_cmd_qos_print_ds_infor(struct Ipnet_ds_get_infor *ds_infor)
{
struct Ipnet_classifier_rule *cr = &ds_infor->f.rule;
struct Ipnet_ds *ds = &ds_infor->ds;
char str[48];
ipcom_printf(" %-20s: %s/%s"IP_LF,
"domain",
cr->af == IP_AF_INET ? "INET" : "INET6",
IP_BIT_ISSET(cr->mask, IPNET_CLS_RULE_LOCAL) ? "local" : "forward");
if (IP_BIT_ISSET(cr->mask, IPNET_CLS_RULE_PROTO))
ipcom_printf(" %-20s: %-10u"IP_LF, "proto", cr->proto);
if (IP_BIT_ISSET(cr->mask, IPNET_CLS_RULE_DS))
ipcom_printf(" %-20s: %-10u"IP_LF, cr->af == IP_AF_INET ? "tos" : "tclass", cr->ds);
if (IP_BIT_ISSET(cr->mask, IPNET_CLS_RULE_SADDR))
ipcom_printf(" %-20s: %s/%d"IP_LF,
"src",
ipcom_inet_ntop(cr->af, &cr->saddr, str, sizeof(str)),
cr->saddr_prefixlen);
if (IP_BIT_ISSET(cr->mask, IPNET_CLS_RULE_DADDR))
ipcom_printf(" %-20s: %s/%d"IP_LF,
"dst",
ipcom_inet_ntop(cr->af, &cr->daddr, str, sizeof(str)),
cr->daddr_prefixlen);
if (IP_BIT_ISSET(cr->mask, IPNET_CLS_RULE_SPORT))
{
if (cr->sport_low == cr->sport_high)
ipcom_printf(" %-20s: %d"IP_LF,
"srcport",
cr->sport_low);
else
ipcom_printf(" %-20s: %-5d -> %-5d"IP_LF,
"srcport",
cr->sport_low,
cr->sport_high);
}
if (IP_BIT_ISSET(cr->mask, IPNET_CLS_RULE_DPORT))
{
if (cr->dport_low == cr->dport_high)
ipcom_printf(" %-20s: %d"IP_LF,
"dstport",
cr->dport_low);
else
ipcom_printf(" %-20s: %-5d -> %-5d"IP_LF,
"dstport",
cr->dport_low,
cr->dport_high);
}
ipcom_printf(" %-20s: %-10s"IP_LF, "handler", ds->name);
if (0 == ipcom_strcmp(ds->name, IPNET_DS_SM_NAME))
{
if (IP_BIT_ISSET(ds->d.sm.mask, IPNET_DS_SM_DS_VAL))
ipcom_printf(" %-20s: 0x%-10x"IP_LF,
"ds-val",
ds->d.sm.ds_value);
if (IP_BIT_ISSET(ds->d.sm.mask, IPNET_DS_SM_DROP_P))
ipcom_printf(" %-20s: %s"IP_LF,
"drop-precedence",
ipcom_cmd_key_to_str(ipnet_cmd_qos_sm_drop_precedence,
ds->d.sm.drop_precedence,
IP_NULL,
0));
}
else if (0 == ipcom_strcmp(ds->name, IPNET_DS_SRTCM_NAME))
{
ipcom_printf(" %-20s: %s"IP_LF,
"mode",
ipcom_cmd_key_to_str(ipnet_cmd_qos_srtcm_mode,
ds->d.srtcm.mode,
IP_NULL,
0));
ipcom_printf(" %-20s: %-10u"IP_LF,
"CIR",
ds->d.srtcm.CIR);
ipcom_printf(" %-20s: %-10u"IP_LF,
"CBS",
ds->d.srtcm.CBS);
ipcom_printf(" %-20s: %-10u"IP_LF,
"EBS",
ds->d.srtcm.EBS);
ipcom_printf(" %-20s: 0x%-10x"IP_LF,
"ds-green",
ds->d.srtcm.ds_green);
ipcom_printf(" %-20s: 0x%-10x"IP_LF,
"ds-yellow",
ds->d.srtcm.ds_yellow);
ipcom_printf(" %-20s: 0x%-10x"IP_LF,
"ds-red",
ds->d.srtcm.ds_red);
}
/* Line break */
ipcom_printf(IP_LF);
}
/*
*===========================================================================
* ipnet_cmd_qos_ds_filter
*===========================================================================
* Description: Handles the differ server subcommand.
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipnet_cmd_qos_ds_filter(Ipnet_cmd_qos *cmd, char **argv)
{
IP_STATIC Ipcom_cmd_int_str_map ipnet_cmd_qos_args[] =
{
/* Indexes <10 has must have one integer argument
>=10 to <100 has one argument that needs custom argument parsing
>=100 have no argument */
{ 2, "tos" },
{ 2, "tclass" },
{ 4, "srcport" },
{ 5, "srcportmax" },
{ 6, "dstport" },
{ 7, "dstportmax" },
{ 8, "proto" },
{ 10, "src" },
{ 11, "dst" },
{ 12, "handler" },
{ 20, "ds-val" },
{ 21, "drop-precedence" },
{ 30, "mode" },
{ 31, "CIR" },
{ 32, "CBS" },
{ 33, "EBS" },
{ 34, "ds-green" },
{ 35, "ds-yellow" },
{ 36, "ds-red" },
{100, "local" },
{ -1, IP_NULL }
};
struct Ipnet_ds_get_infor gi;
int c;
int i = 0;
char *p = IP_NULL;
char *endptr = IP_NULL;
char *str_prefixlen;
Ip_u8 prefix_len;
long l = 0;
cmd->d.ds.filter.rule.af = (Ip_u8) cmd->domain;
while (*argv != IP_NULL)
{
c = ipcom_cmd_str_to_key(ipnet_cmd_qos_args, *argv);
if (c == -1)
{
ipcom_printf("'%s' is an unknown argument."IP_LF, *argv);
return IPNET_CMD_ERR;
}
if (c < 100)
{
if (argv[1] == IP_NULL)
{
ipcom_printf("Parameter needed for argument %s."IP_LF, argv[0]);
return IPNET_CMD_ERR;
}
argv++;
if (c < 10)
i = ipcom_atoi(*argv);
else
p = *argv;
}
switch (c)
{
case 2:
IP_BIT_SET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_DS);
cmd->d.ds.filter.rule.ds = (Ip_u8) i;
break;
case 4:
IP_BIT_SET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_SPORT);
cmd->d.ds.filter.rule.sport_low = (Ip_u16) i;
if (0 == cmd->d.ds.filter.rule.sport_high)
cmd->d.ds.filter.rule.sport_high = cmd->d.ds.filter.rule.sport_low;
break;
case 5:
IP_BIT_SET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_SPORT);
cmd->d.ds.filter.rule.sport_high = (Ip_u16) i;
if (0 == cmd->d.ds.filter.rule.sport_low)
cmd->d.ds.filter.rule.sport_low = cmd->d.ds.filter.rule.sport_high;
break;
case 6:
IP_BIT_SET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_DPORT);
cmd->d.ds.filter.rule.dport_low = (Ip_u16) i;
if (0 == cmd->d.ds.filter.rule.dport_high)
cmd->d.ds.filter.rule.dport_high = cmd->d.ds.filter.rule.dport_low;
break;
case 7:
IP_BIT_SET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_DPORT);
cmd->d.ds.filter.rule.dport_high = (Ip_u16) i;
if (0 == cmd->d.ds.filter.rule.dport_low)
cmd->d.ds.filter.rule.dport_low = cmd->d.ds.filter.rule.dport_high;
break;
case 8:
IP_BIT_SET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_PROTO);
cmd->d.ds.filter.rule.proto = (Ip_u8) i;
break;
case 10:
case 11:
str_prefixlen = ipcom_strstr(p, "/");
if (str_prefixlen == IP_NULL || ipcom_strlen(p) <= 1)
prefix_len = 0;
else
{
*str_prefixlen = '\0';
prefix_len = (Ip_u8) ipcom_atoi(str_prefixlen + 1);
}
if (c == 10)
{
if (ipcom_inet_pton(cmd->d.ds.filter.rule.af, p, &cmd->d.ds.filter.rule.saddr) != 1)
{
ipcom_printf("'%s' is not a valid IP address." IP_LF, p);
return IPNET_CMD_ERR;
}
IP_BIT_SET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_SADDR);
cmd->d.ds.filter.rule.saddr_prefixlen = prefix_len;
}
else
{
if (ipcom_inet_pton(cmd->d.ds.filter.rule.af, p, &cmd->d.ds.filter.rule.daddr) != 1)
{
ipcom_printf("'%s' is not a valid IP address." IP_LF, p);
return IPNET_CMD_ERR;
}
IP_BIT_SET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_DADDR);
cmd->d.ds.filter.rule.daddr_prefixlen = prefix_len;
}
break;
case 12:
ipcom_strncpy(cmd->d.ds.handler.name, p, (Ip_size_t)IPNET_DS_NAME_SIZE);
if ((0 != ipcom_strcmp(cmd->d.ds.handler.name, IPNET_DS_SM_NAME))
&& (0 != ipcom_strcmp(cmd->d.ds.handler.name, IPNET_DS_SRTCM_NAME)))
{
ipcom_printf("'%s' is not a supported handler name."IP_LF, p);
return IPNET_CMD_ERR;
}
break;
case 20:
IP_BIT_SET(cmd->d.ds.handler.d.sm.mask, IPNET_DS_SM_DS_VAL);
cmd->d.ds.handler.d.sm.ds_value = ipcom_strtol(p, &endptr, 16);
if (*endptr != '\0')
{
ipcom_printf("'%s' is not a invalid ds-val, need hex format."IP_LF, p);
return IPNET_CMD_ERR;
}
break;
case 21:
c = ipcom_cmd_str_to_key(ipnet_cmd_qos_sm_drop_precedence, p);
if (c < 0 || c > 255)
{
ipcom_printf("'%s' is an unknown argument."IP_LF, p);
return IPNET_CMD_ERR;
}
IP_BIT_SET(cmd->d.ds.handler.d.sm.mask, IPNET_DS_SM_DROP_P);
cmd->d.ds.handler.d.sm.drop_precedence = (Ip_u8)c;
break;
case 30:
c = ipcom_cmd_str_to_key(ipnet_cmd_qos_srtcm_mode, p);
if (c < 0 || c > 255)
{
ipcom_printf("'%s' is an unknown argument."IP_LF, p);
return IPNET_CMD_ERR;
}
cmd->d.ds.handler.d.srtcm.mode = (Ip_u8)c;
break;
case 31:
cmd->d.ds.handler.d.srtcm.CIR = (Ip_u32)ipcom_strtol(p, &endptr, 10);
if (*endptr != '\0')
{
ipcom_printf("'%s' is not a invalid ds-val, need hex format."IP_LF, p);
return IPNET_CMD_ERR;
}
break;
case 32:
cmd->d.ds.handler.d.srtcm.CBS = (Ip_u32)ipcom_strtol(p, &endptr, 10);
if (*endptr != '\0')
{
ipcom_printf("'%s' is not a invalid ds-val, need hex format."IP_LF, p);
return IPNET_CMD_ERR;
}
break;
case 33:
cmd->d.ds.handler.d.srtcm.EBS = (Ip_u32)ipcom_strtol(p, &endptr, 10);
if (*endptr != '\0')
{
ipcom_printf("'%s' is not a invalid ds-val, need hex format."IP_LF, p);
return IPNET_CMD_ERR;
}
break;
case 34:
l = ipcom_strtol(p, &endptr, 16);
if (*endptr != '\0' || l > 255)
{
ipcom_printf("'%s' is not a invalid ds-val, need hex format."IP_LF, p);
return IPNET_CMD_ERR;
}
cmd->d.ds.handler.d.srtcm.ds_green = (Ip_u8)l;
break;
case 35:
l = ipcom_strtol(p, &endptr, 16);
if (*endptr != '\0' || l > 255)
{
ipcom_printf("'%s' is not a invalid ds-val, need hex format."IP_LF, p);
return IPNET_CMD_ERR;
}
cmd->d.ds.handler.d.srtcm.ds_yellow = (Ip_u8)l;
break;
case 36:
l = ipcom_strtol(p, &endptr, 16);
if (*endptr != '\0' || l > 255)
{
ipcom_printf("'%s' is not a invalid ds-val, need hex format."IP_LF, p);
return IPNET_CMD_ERR;
}
cmd->d.ds.handler.d.srtcm.ds_red = (Ip_u8)l;
break;
case 100:
IP_BIT_SET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_LOCAL);
break;
default:
IP_PANIC();
break;
}
argv++;
}
/* port rang check */
if (IP_BIT_ISSET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_SPORT))
{
if ((0 == cmd->d.ds.filter.rule.sport_low)
|| (0 == cmd->d.ds.filter.rule.sport_high)
|| (cmd->d.ds.filter.rule.sport_low > cmd->d.ds.filter.rule.sport_high))
{
ipcom_printf("src port rang is not valid." IP_LF);
return IPNET_CMD_ERR;
}
}
if (IP_BIT_ISSET(cmd->d.ds.filter.rule.mask, IPNET_CLS_RULE_DPORT))
{
if ((0 == cmd->d.ds.filter.rule.dport_low)
|| (0 == cmd->d.ds.filter.rule.dport_high)
|| (cmd->d.ds.filter.rule.dport_low > cmd->d.ds.filter.rule.dport_high))
{
ipcom_printf("dst port rang is not valid." IP_LF);
return IPNET_CMD_ERR;
}
}
ipcom_memset(&gi, 0, sizeof(gi));
gi.f.id = -1;
switch (cmd->op)
{
case IPNET_CMD_QOS_OP_ADD:
ipcom_memcpy(&gi.f.rule, &cmd->d.ds.filter.rule, sizeof(gi.f.rule));
if (0 == ipcom_socketioctl(cmd->sock, IPNET_SIOCXGDSFILTER, (void *)&gi))
{
ipcom_printf("this filter already exist." IP_LF);
return IPNET_CMD_ERR;
}
if (ipcom_socketioctl(cmd->sock, IPNET_SIOCXADSFILTER, &cmd->d.ds.filter) < 0)
{
ipcom_perror("Failed to add differ server filter");
return IPNET_CMD_ERR;
}
if (ipcom_socketioctl(cmd->sock, IPNET_SIOCXDSCREATE, &cmd->d.ds.handler) < 0)
{
ipcom_perror("Failed to create differ server");
(void)ipcom_socketioctl(cmd->sock, IPNET_SIOCXDDSFILTER, &cmd->d.ds.filter);
return IPNET_CMD_ERR;
}
cmd->d.ds.map.filter_id = cmd->d.ds.filter.id;
cmd->d.ds.map.ds_id = cmd->d.ds.handler.id;
if (ipcom_socketioctl(cmd->sock, IPNET_SIOCXADSMAP, &cmd->d.ds.map) < 0)
{
ipcom_perror("Failed to map filter to ds");
(void)ipcom_socketioctl(cmd->sock, IPNET_SIOCXDDSFILTER, &cmd->d.ds.filter);
(void)ipcom_socketioctl(cmd->sock, IPNET_SIOCXDSDESTROY, &cmd->d.ds.handler);
return IPNET_CMD_ERR;
}
break;
case IPNET_CMD_QOS_OP_DEL:
ipcom_memcpy(&gi.f.rule, &cmd->d.ds.filter.rule, sizeof(gi.f.rule));
if (ipcom_socketioctl(cmd->sock, IPNET_SIOCXGDSFILTER, (void *)&gi) < 0)
{
ipcom_perror("this filter does not exist.");
return IPNET_CMD_ERR;
}
cmd->d.ds.filter.id = gi.f.id;
cmd->d.ds.handler.id = gi.ds.id;
(void)ipcom_socketioctl(cmd->sock, IPNET_SIOCXDDSFILTER, &cmd->d.ds.filter);
(void)ipcom_socketioctl(cmd->sock, IPNET_SIOCXDSDESTROY, &cmd->d.ds.handler);
break;
case IPNET_CMD_QOS_OP_LIST:
case IPNET_CMD_QOS_OP_GET:
do
{
if (ipcom_socketioctl(cmd->sock, IPNET_SIOCXGDSNEXTFILTER, (void *)&gi) < 0)
{
ipcom_perror("Failed to get next filter");
return IPNET_CMD_ERR;
}
if (-1 == gi.f.id)
break;
ipcom_cmd_qos_print_ds_infor(&gi);
} while (IP_TRUE);
break;
default:
return IPNET_CMD_ERR_UNSUPPORTED_OP;
}
return 0;
}
#endif
/*
*===========================================================================
* ipnet_cmd_qos_print_usage
*===========================================================================
* Description: Prints the usage for the command.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipnet_cmd_qos_print_usage(void)
{
ipcom_printf("NAME" IP_LF);
ipcom_printf(" qos - controls the QoS features in IPNET" IP_LF);
ipcom_printf("" IP_LF);
ipcom_printf("SYNOPSIS" IP_LF);
ipcom_printf(" qos [option]... op optype [args]" IP_LF);
ipcom_printf("" IP_LF);
ipcom_printf("DESCRIPTION" IP_LF);
ipcom_printf(" The qos command is used to configure and view the Quality of Service" IP_LF);
ipcom_printf(" features within IPNET, except interface queues which uses 'qc'." IP_LF);
ipcom_printf("" IP_LF);
ipcom_printf(" The following options:" IP_LF);
ipcom_printf(" -4 Use IPv4 as address domain (default)." IP_LF);
ipcom_printf(" -6 Use IPv6 as address domain." IP_LF);
ipcom_printf(" -V <tab> Operate on virtual router with index <tab>." IP_LF);
ipcom_printf("" IP_LF);
ipcom_printf(" The following operations (op) exists:" IP_LF);
ipcom_printf(" add Add something." IP_LF);
ipcom_printf(" delete Delete something." IP_LF);
ipcom_printf(" get Lookup and display something." IP_LF);
ipcom_printf(" list Lookup and display something." IP_LF);
ipcom_printf("" IP_LF);
ipcom_printf(" The following operation types (optype) exists:" IP_LF);
ipcom_printf(" policy Policy routing." IP_LF);
#if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA)
ipcom_printf(" filter Differentiated services(filter and handler)." IP_LF);
#endif
ipcom_printf("" IP_LF);
ipcom_printf(" Policy routing arguments:" IP_LF);
ipcom_printf(" Add operation:" IP_LF);
ipcom_printf(" from <addr> Apply this rule if the source address is <addr>" IP_LF);
ipcom_printf(" to <addr> Apply this rule if the destination address is <addr>" IP_LF);
ipcom_printf(" proto <p> Apply this rule if the transport protocol is <p>" IP_LF);
ipcom_printf(" tos <n> Apply this rule if the TOS is <n>" IP_LF);
ipcom_printf(" tclass <n> Apply this rule if the traffic class is <n>" IP_LF);
ipcom_printf(" ifindex <if> Apply this rule if the ifindex of the incoming interface is <if>" IP_LF);
#ifdef IPCOM_USE_INET6
ipcom_printf(" scope <s> Apply this rule if the scope of the address is <s>" IP_LF);
#endif
ipcom_printf(" reverse If this rule is applied, do the lookup based on src instead of dst" IP_LF);
ipcom_printf(" table <t> Use the routing table with policy ID <t>" IP_LF);
ipcom_printf(" if the rule matches" IP_LF);
ipcom_printf(" last Do not look at any more rules, even if no match" IP_LF);
ipcom_printf(" on this table" IP_LF);
ipcom_printf(" prio <p> The prio of the rule to add [-32768..32767]" IP_LF);
ipcom_printf(" Delete/get operation:" IP_LF);
ipcom_printf(" id <i> The ID of the rule to delete/show" IP_LF);
ipcom_printf("" IP_LF);
#if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA)
ipcom_printf(" Differentiated services arguments:" IP_LF);
ipcom_printf(" Add/Delete operation:" IP_LF);
ipcom_printf(" src <addr> Apply this filter if the source address is <addr>" IP_LF);
ipcom_printf(" dst <addr> Apply this filter if the destination address is <addr>" IP_LF);
ipcom_printf(" proto <p> Apply this filter if the transport protocol is <p>" IP_LF);
ipcom_printf(" tos <n> Apply this filter if the TOS is <n>" IP_LF);
ipcom_printf(" tclass <n> Apply this filter if the traffic class is <n>" IP_LF);
ipcom_printf(" srcport <n> Apply this filter if the source port is <n>" IP_LF);
ipcom_printf(" or from srcport <n> to srcportmax <n>" IP_LF);
ipcom_printf(" dstport <n> Apply this filter if the destination port is <n>" IP_LF);
ipcom_printf(" or from dstport <n> to dstportmax <n>" IP_LF);
ipcom_printf(" srcportmax <n> Apply this filter if the source port" IP_LF);
ipcom_printf(" from srcport <n> to srcportmax <n>" IP_LF);
ipcom_printf(" dstportmax <n> Apply this filter if the destination port" IP_LF);
ipcom_printf(" from dstport <n> to dstportmax <n>" IP_LF);
ipcom_printf(" local Apply this filter for locally generated packets" IP_LF);
ipcom_printf(" handler <str> Apply this filter using <str> handler" IP_LF);
ipcom_printf(" Handler arguments:" IP_LF);
ipcom_printf(" SimpleMarker Apply simple marker if match this filter" IP_LF);
ipcom_printf(" srTCM Apply single rate Three Color Marker if match this filter" IP_LF);
ipcom_printf(" Handler SimpleMarker arguments:" IP_LF);
ipcom_printf(" ds-val <n> Set DSCP with <n> if match this filter" IP_LF);
ipcom_printf(" drop-precedence <p> Set drop precedence with <p> if match this filter" IP_LF);
ipcom_printf(" Handler srTCM arguments:" IP_LF);
ipcom_printf(" mode <m> Use mode <m> if match this filter" IP_LF);
ipcom_printf(" CIR <n> Set Committed Information Rate to <n> if match this filter" IP_LF);
ipcom_printf(" CBS <n> Set Committed Burst Size to <n> if match this filter" IP_LF);
ipcom_printf(" EBS <n> Set Excess Burst Size to <n> if match this filter" IP_LF);
ipcom_printf(" ds-green <n> Set DSCP with <n> for green packets if match this filter" IP_LF);
ipcom_printf(" ds-yellow <n> Set DSCP with <n> for yellow packets if match this filter" IP_LF);
ipcom_printf(" ds-red <n> Set DSCP with <n> for red packets if match this filter" IP_LF);
ipcom_printf(" Example:" IP_LF);
ipcom_printf(" qos add filter dst 192.168.1.0/24 local handler SimpleMarker ds-val 0x10" IP_LF);
ipcom_printf(" qos add filter srcport 21 local handler SimpleMarker ds-val 0x10" IP_LF);
ipcom_printf("" IP_LF);
#endif
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipnet_cmd_qos
*===========================================================================
* Description: The entry point for the 'qos' shell command.
* Parameters:
* Returns:
*
*/
IP_PUBLIC int
ipnet_cmd_qos(int argc, char **argv)
{
Ipnet_cmd_qos cmd;
Ipcom_getopt opt;
int i;
char **arg;
int ret = IPNET_CMD_ERR;
char *op;
char *op_type;
int vr;
ipcom_memset(&cmd, 0, sizeof(cmd));
#ifdef IPCOM_USE_INET
cmd.domain = IP_AF_INET;
#else
cmd.domain = IP_AF_INET6;
#endif
cmd.sock = ipcom_socket(cmd.domain, IP_SOCK_DGRAM, 0);
if (cmd.sock == IP_INVALID_SOCKET)
{
ipcom_perror("Failed to create socket");
goto cleanup;
}
ipcom_getopt_clear_r(&opt);
while ((i = ipcom_getopt_r(argc, argv, "46V:", &opt)) != -1)
{
switch (i)
{
case '4':
cmd.domain = IP_AF_INET;
break;
case '6':
cmd.domain = IP_AF_INET6;
break;
case 'V':
vr = ipcom_atoi(opt.optarg);
if (ipcom_setsockopt(cmd.sock, IP_SOL_SOCKET, IP_SO_X_VR, &vr, sizeof(vr)) < 0)
{
ipcom_perror("Failed to changed VR");
goto cleanup;
}
break;
default:
ipcom_printf("invalid option '%c'"IP_LF, i);
goto cleanup;
}
}
if (argc < opt.optind + 2)
{
ipnet_cmd_qos_print_usage();
goto cleanup;
}
arg = &argv[opt.optind];
op = *arg;
cmd.op = ipcom_cmd_str_to_key(ipnet_cmd_qos_ops, op);
if (cmd.op == -1)
{
ipcom_printf("'%s' is an invalid operation"IP_LF, op);
goto cleanup;
}
arg++;
op_type = *arg;
cmd.op_type = ipcom_cmd_str_to_key(ipnet_cmd_qos_types, op_type);
arg++;
switch (cmd.op_type)
{
case IPNET_CMD_QOS_T_POLICY_RT:
ret = ipnet_cmd_qos_policy_routing(&cmd, arg);
break;
#if defined(IPNET_USE_DIFFSERV) && !defined(IPNET_DIFFSERV_CLASSIFIER_MODE_BA)
case IPNET_CMD_QOS_T_DS_FILTER:
ret = ipnet_cmd_qos_ds_filter(&cmd, arg);
break;
#endif
default:
ipcom_printf("'%s' is an invalid operation type"IP_LF, op_type);
break;
}
if (ret == IPNET_CMD_ERR_UNSUPPORTED_OP)
ipcom_printf("The operation %s is not supported by type %s" IP_LF, op, op_type);
cleanup:
ipcom_socketclose(cmd.sock);
return ret;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/