/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #ifdef IPCOM_KERNEL #undef IPCOM_KERNEL #endif #include "ipnet_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #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 Operate on virtual router with index ." 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 Apply this rule if the source address is " IP_LF); ipcom_printf(" to Apply this rule if the destination address is " IP_LF); ipcom_printf(" proto

Apply this rule if the transport protocol is

" IP_LF); ipcom_printf(" tos Apply this rule if the TOS is " IP_LF); ipcom_printf(" tclass Apply this rule if the traffic class is " IP_LF); ipcom_printf(" ifindex Apply this rule if the ifindex of the incoming interface is " IP_LF); #ifdef IPCOM_USE_INET6 ipcom_printf(" scope Apply this rule if the scope of the address is " 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 Use the routing table with policy ID " 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

The prio of the rule to add [-32768..32767]" IP_LF); ipcom_printf(" Delete/get operation:" IP_LF); ipcom_printf(" id 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 Apply this filter if the source address is " IP_LF); ipcom_printf(" dst Apply this filter if the destination address is " IP_LF); ipcom_printf(" proto

Apply this filter if the transport protocol is

" IP_LF); ipcom_printf(" tos Apply this filter if the TOS is " IP_LF); ipcom_printf(" tclass Apply this filter if the traffic class is " IP_LF); ipcom_printf(" srcport Apply this filter if the source port is " IP_LF); ipcom_printf(" or from srcport to srcportmax " IP_LF); ipcom_printf(" dstport Apply this filter if the destination port is " IP_LF); ipcom_printf(" or from dstport to dstportmax " IP_LF); ipcom_printf(" srcportmax Apply this filter if the source port" IP_LF); ipcom_printf(" from srcport to srcportmax " IP_LF); ipcom_printf(" dstportmax Apply this filter if the destination port" IP_LF); ipcom_printf(" from dstport to dstportmax " IP_LF); ipcom_printf(" local Apply this filter for locally generated packets" IP_LF); ipcom_printf(" handler Apply this filter using 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 Set DSCP with if match this filter" IP_LF); ipcom_printf(" drop-precedence

Set drop precedence with

if match this filter" IP_LF); ipcom_printf(" Handler srTCM arguments:" IP_LF); ipcom_printf(" mode Use mode if match this filter" IP_LF); ipcom_printf(" CIR Set Committed Information Rate to if match this filter" IP_LF); ipcom_printf(" CBS Set Committed Burst Size to if match this filter" IP_LF); ipcom_printf(" EBS Set Excess Burst Size to if match this filter" IP_LF); ipcom_printf(" ds-green Set DSCP with for green packets if match this filter" IP_LF); ipcom_printf(" ds-yellow Set DSCP with for yellow packets if match this filter" IP_LF); ipcom_printf(" ds-red Set DSCP with 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 **************************************************************************** */