/****************************************************************************** ** ** FILE NAME : ppacmd.c ** PROJECT : PPA Configuration Utility ** MODULES : Packet Acceleration ** ** DATE : 10 JUN 2008 ** AUTHOR : Mark Smith ** DESCRIPTION : PPA (Routing Acceleration) User Configuration Utility ** COPYRIGHT : Copyright (c) 2009 ** Lantiq Deutschland GmbH ** Am Campeon 3; 85579 Neubiberg, Germany ** ** For licensing information, see the file 'LICENSE' in the root folder of ** this software module. ** ** ** *******************************************************************************/ #include #include #include #include #include #include #include #include #include #define CONFIG_IFX_PPA_MFE #define CONFIG_IFX_PPA_QOS_WFQ #define CONFIG_IFX_PPA_QOS_RATE_SHAPING #ifdef CONFIG_IFX_PPA_QOS_WFQ #define CONFIG_IFX_PPA_QOS #endif #ifdef CONFIG_IFX_PPA_QOS_RATE_SHAPING #define CONFIG_IFX_PPA_QOS #endif #define PPACMD_VERION_MAJOR 2 #define PPACMD_VERION_MID 3 #define PPACMD_VERION_MINOR 0 extern int inet_aton(const char *cp, void *inp); #include #define PPA_DEVICE "/dev/ifx_ppa" #define PPA_CMD_NAME "ppacmd" #define PPACMD_DEBUG 1 #if PPACMD_DEBUG int enable_debug = 0; char *debug_enable_file="/var/ppa_gdb_enable"; #define IFX_DBG(args...) if( enable_debug) printf(args) #else #define IFX_DBG(args...) #endif #define IFX_PPACMD_PRINT(args...) printf(args) #define PPA_CMD_OK 0 #define PPA_CMD_ERR 1 #define PPA_CMD_HELP 2 #define PPA_CMD_DONE 3 #define PPA_CMD_NOT_AVAIL 4 #define OPT_ENABLE_LAN 1 #define OPT_DISABLE_LAN 2 #define OPT_ENABLE_WAN 3 #define OPT_DISABLE_WAN 4 #define OPT_VLAN_AWARE 1 #define OPT_OUTER_VLAN_AWARE 2 #define PPA_MAX_CMD_OPTS 20 #define NIPQUAD(addr) \ ((unsigned char *)&addr)[0], \ ((unsigned char *)&addr)[1], \ ((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[3] #define NUM_ENTITY(x) (sizeof(x) / sizeof(*(x))) #define ENABLE_IPV6 1 typedef struct ppa_cmd_opts_t { int opt; char *optarg; } PPA_CMD_OPTS; typedef struct ppa_cmd_t { const char *name; // command string int ioctl_cmd; // ioctl command value void (*print_help)(int); // function to print help for the command: 0 means detail, 1 mean simple one int (*parse_options)(PPA_CMD_OPTS *,PPA_CMD_DATA *); // int (*do_command)(struct ppa_cmd_t *,PPA_CMD_DATA *); // function to do error checking on options and fill out PPA_CMD_DATA void (*print_data)(PPA_CMD_DATA *); // print any returned values from PPA driver const struct option *long_opts; // long options for command const char *short_opts; // short options for command } PPA_COMMAND; #define MAX_CMD_OPTS 8 #define PPACMD_MAX_FILENAME 32 static int g_output_to_file = 0; static char g_output_filename[PPACMD_MAX_FILENAME]={0}; #define DEFAULT_OUTPUT_FILENAME "/var/tmp.dat" static void ppa_print_help(void); static int ppa_parse_simple_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata); /* int SaveDataToFile(char *FileName, char *data, int len ) return 0: means sucessful return -1: fail to save data to file */ int SaveDataToFile(char *FileName, char *data, int len ) { FILE *pFile; if( data == NULL ) return -1; if( FileName == NULL || strlen(FileName) == 0 ) FileName = DEFAULT_OUTPUT_FILENAME; //IFX_DBG("SaveDataToFile %s ( bytes: %d from buffer %p)\n", FileName, len, data ); pFile = fopen(FileName, "wb"); if( pFile == NULL ) { IFX_PPACMD_PRINT("SaveDataToFile: fail to open file %s\n", FileName ); return -1; } fwrite (data , 1 , len , pFile ); fflush(pFile); fclose (pFile); return 0; } static void print_session_flags( uint32_t flags) { static const char *str_flag[] = { "IS_REPLY", // 0x00000001 "BRIDGING_VCI_CHECK", "SESSION_IS_TCP", "INVALID", "ADDED_IN_HW", // 0x00000010 "CAN_NOT_ACCEL", "STATIC", "DROP", "VALID_NAT_IP", // 0x00000100 "VALID_NAT_PORT", "VALID_NAT_SNAT", "INVALID", "VALID_VLAN_INS", // 0x00001000 "VALID_VLAN_RM", "SESSION_VALID_OUT_VLAN_INS", "SESSION_VALID_OUT_VLAN_RM", "VALID_PPPOE", // 0x00010000 "VALID_NEW_SRC_MAC", "VALID_MTU", "VALID_NEW_DSCP", "SESSION_VALID_DSLWAN_QID", // 0x00100000 "SESSION_TX_ITF_IPOA", "SESSION_TX_ITF_PPPOA", "INVALID", "SRC_MAC_DROP_EN", // 0x01000000 "INVALID", "INVALID", "INVALID", "LAN_ENTRY", // 0x10000000 "WAN_ENTRY", "INVALID", "INVALID", }; int flag; unsigned long bit; int i; flag = 0; for ( bit = 1, i = 0; bit; bit <<= 1, i++ ) { if ( (flags & bit) ) { if ( flag++ ) IFX_PPACMD_PRINT( "|"); IFX_PPACMD_PRINT( str_flag[i]); //IFX_PPACMD_PRINT( " "); } } } int stricmp(const char * p1, const char * p2) { int c1, c2; while ( *p1 && *p2 ) { c1 = *p1 >= 'A' && *p1 <= 'Z' ? *p1 + 'a' - 'A' : *p1; c2 = *p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2; if ( (c1 -= c2) ) return c1; p1++; p2++; } return *p1 - *p2; } unsigned long my_strtoul( const char *nptr ) { unsigned long tmp; if( nptr == NULL ) return 0; if( nptr[0] == ':' ) /*dec value, like 3 */ return strtoul(nptr+1, NULL, 10); else if( nptr[0] == '@' ) /*ip string format: like 192.168.1.1 */ { tmp = 0; inet_aton(nptr+1, &tmp); return tmp; } else if( strlen(nptr) >= 2 && nptr[0] == '0' && ( nptr[1] == 'x' || nptr[1] == 'X') ) /*hex value start with 0x */ { return strtoul(nptr, NULL, 16); } else /*by default it is decimal value */ { return strtoul(nptr, NULL, 10); } } /* =========================================================================================== ppa_do_ioctl_cmd =========================================================================================== */ static int ppa_do_ioctl_cmd(int ioctl_cmd, void *data) { int ret = PPA_CMD_OK; int fd = 0; if ((fd = open (PPA_DEVICE, O_RDWR)) < 0) { IFX_PPACMD_PRINT ("\n [%s] : open PPA device (%s) failed. (errno=%d)\n", __FUNCTION__, PPA_DEVICE, errno); ret = PPA_CMD_ERR; } else { if (ioctl (fd, ioctl_cmd, data) < 0) { IFX_PPACMD_PRINT ("\n [%s] : ioctl failed. (errno=%d)\n", __FUNCTION__, errno); ret = PPA_CMD_ERR; } close (fd); } return ret; } /* ==================================================================================== Input conversion functions These sunctions convert input strings to the appropriate data types for the ioctl commands. =================================================================================== */ static void stomac(char *s,unsigned char mac_addr[]) { unsigned int mac[PPA_ETH_ALEN]; sscanf(s,"%2x:%2x:%2x:%2x:%2x:%2x",&mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]); mac_addr[5] = mac[5]; mac_addr[4] = mac[4]; mac_addr[3] = mac[3]; mac_addr[2] = mac[2]; mac_addr[1] = mac[1]; mac_addr[0] = mac[0]; return; } /* ==================================================================================== Generic option sets These option sets are shared among several commands. =================================================================================== */ static const char ppa_no_short_opts[] = "h"; static struct option ppa_no_long_opts[] = { { 0,0,0,0 } }; static const char ppa_if_short_opts[] = "i:h"; static struct option ppa_if_long_opts[] = { {"interface", required_argument, NULL, 'i'}, { 0,0,0,0 } }; static const char ppa_mac_short_opts[] = "m:h"; static const struct option ppa_mac_long_opts[] = { {"macaddr", required_argument, NULL, 'm'}, { 0,0,0,0 } }; static const char ppa_if_mac_short_opts[] = "i:m:h"; static const struct option ppa_if_mac_long_opts[] = { {"interface", required_argument, NULL, 'i'}, {"macaddr", required_argument, NULL, 'm'}, { 0,0,0,0 } }; static const char ppa_output_short_opts[] = "o:h"; static const char ppa_if_output_short_opts[] = "i:o:h"; static const char ppa_init_short_opts[] = "f:l:w:b:m:c:h"; static const struct option ppa_init_long_opts[] = { {"file", required_argument, NULL, 'f'}, {"lan", required_argument, NULL, 'l'}, {"wan", required_argument, NULL, 'w'}, {"bridge", required_argument, NULL, 'b'}, {"multicast",required_argument, NULL, 'm'}, {"checksum", required_argument, NULL, 'c'}, {"help", no_argument, NULL, 'h'}, { 0,0,0,0 } }; static int ppa_do_cmd(PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { return ppa_do_ioctl_cmd(pcmd->ioctl_cmd,pdata); } /* ==================================================================================== command: init description: Initialize the Packet Processing Acceleration Module options: None ==================================================================================== */ typedef enum { INIT_CMD_INVALID = -1, INIT_CMD_COMMENT, INIT_CMD_SECTION, INIT_CMD_END, INIT_CMD_L3_VERIFY, INIT_CMD_L4_VERIFY, INIT_CMD_DROP_ON_ERROR, INIT_CMD_DROP_ON_UNICAST_MISS, INIT_CMD_DROP_ON_MULTICAST_MISS, INIT_CMD_NUM_ENTRIES, INIT_CMD_MULTICAST_ENTRIES, INIT_CMD_BRIDGE_ENTRIES, INIT_CMD_TCP_HITS_TO_ADD, INIT_CMD_UDP_HITS_TO_ADD, INIT_CMD_INTERFACE } INIT_CMD; const char *cfg_names[] = { "comment", "section", "end", "ip-header-check", "tcp-udp-header-check", "drop-on-error", "unicast-drop-on-miss", "multicast-drop-on-miss", "max-unicast-sessions", "max-multicast-sessions", "max-bridging-sessions", "tcp-threshold", "udp-threshold", "interface" }; typedef enum { SECTION_NONE, SECTION_WAN, SECTION_LAN } SECTION_NAME; typedef enum { ERR_MULTIPLE_SECTIONS, ERR_INVALID_SECTION_NAME, ERR_INVALID_COMMAND, ERR_NOT_IN_SECTION, ERR_IN_SECTION, ERR_INVALID_RANGE } INIT_FILE_ERR; static void ppa_print_init_help(int summary) { if( !summary ) { IFX_PPACMD_PRINT("init [-f ] [-l ] [-w ] [-m ] [-b ] [-c enable| disable> ]\n"); IFX_PPACMD_PRINT("\t\t-l/w/m/b: to set maximum LAN/WAN/Multicast/Bridge Acceeration entries\n"); IFX_PPACMD_PRINT("\t\t-c : to enable/disable checksum checking\n"); } else IFX_PPACMD_PRINT("init [-f ]\n"); return; } static INIT_CMD parse_init_config_line(char *buf, char **val) { char *p_cmd, *p_end; int ndx; INIT_CMD ret_cmd = INIT_CMD_INVALID; int eol_seen = 0; if (buf[0] == '#') return INIT_CMD_COMMENT; p_cmd = buf; while (*p_cmd != '\n' && isspace(*p_cmd)) // skip leading white space while checking for eol p_cmd++; if (*p_cmd == '\n') return INIT_CMD_COMMENT; // empty line p_end = p_cmd; // null terminate the command while (!isspace(*p_end)) p_end++; if (*p_end == '\n') eol_seen = 1; *p_end = '\0'; for (ndx = 0; ndx < (sizeof(cfg_names)/sizeof(char *)); ndx++) { if ( strcasecmp(cfg_names[ndx], p_cmd ) == 0) { // return the following string if present if (!eol_seen) { p_cmd = p_end + 1; while (*p_cmd != '\n' && isspace(*p_cmd)) p_cmd++; p_end = p_cmd; while (!isspace(*p_end)) p_end++; *p_end = '\0'; *val = p_cmd; } else { *val = NULL; // no parameter present } ret_cmd = ndx; break; } } return ret_cmd; } static int parse_init_config_file(char *filename, PPA_CMD_INIT_INFO *pinfo) { FILE *fd; char cmd_line[128]; char *val; int linenum = 0; INIT_CMD cmd; int is_enable, num_entries, num_hits; SECTION_NAME curr_section = SECTION_NONE; PPA_VERIFY_CHECKS *pchecks; int seen_wan_section = 0, seen_lan_section = 0; //int if_index = 0; int num_wanifs = 0, num_lanifs = 0; INIT_FILE_ERR err; fd = fopen(filename,"r"); if (fd != NULL) { while ( fgets(cmd_line, 128, fd) != NULL) { linenum++; cmd = parse_init_config_line(cmd_line, &val); switch(cmd) { case INIT_CMD_COMMENT: break; case INIT_CMD_SECTION: if (!strcasecmp("wan", val)) { if(seen_wan_section) { err = ERR_MULTIPLE_SECTIONS; goto parse_error; } curr_section = SECTION_WAN; } else if (!strcasecmp("lan", val)) { if (seen_lan_section) { err = ERR_MULTIPLE_SECTIONS; goto parse_error; } curr_section = SECTION_LAN; } else { err = ERR_INVALID_SECTION_NAME; goto parse_error; } break; case INIT_CMD_END: if (curr_section == SECTION_NONE) { err = ERR_NOT_IN_SECTION; goto parse_error; } if (curr_section == SECTION_WAN) { pinfo->num_wanifs = num_wanifs; seen_wan_section = 1; } else { pinfo->num_lanifs = num_lanifs; seen_lan_section = 1; } curr_section = SECTION_NONE; break; case INIT_CMD_L3_VERIFY: case INIT_CMD_L4_VERIFY: case INIT_CMD_DROP_ON_ERROR: case INIT_CMD_DROP_ON_UNICAST_MISS: case INIT_CMD_DROP_ON_MULTICAST_MISS: if (!strcasecmp("enable", val)) is_enable = 1; else if (!strcasecmp("disable", val)) is_enable = 0; else { err = ERR_INVALID_COMMAND; goto parse_error; } if (curr_section == SECTION_NONE) { err = ERR_NOT_IN_SECTION; goto parse_error; } if (curr_section == SECTION_LAN) pchecks = &(pinfo->lan_rx_checks); else pchecks = &(pinfo->wan_rx_checks); switch(cmd) { case INIT_CMD_L3_VERIFY: pchecks->f_ip_verify = is_enable; break; case INIT_CMD_L4_VERIFY: pchecks->f_tcp_udp_verify = is_enable; break; case INIT_CMD_DROP_ON_ERROR: pchecks->f_tcp_udp_err_drop = is_enable; break; case INIT_CMD_DROP_ON_UNICAST_MISS: pchecks->f_drop_on_no_hit = is_enable; break; case INIT_CMD_DROP_ON_MULTICAST_MISS: pchecks->f_mc_drop_on_no_hit = is_enable; break; default: err = ERR_INVALID_COMMAND; goto parse_error; } break; case INIT_CMD_NUM_ENTRIES: case INIT_CMD_BRIDGE_ENTRIES: case INIT_CMD_MULTICAST_ENTRIES: num_entries = atoi(val); if (num_entries > 1000 || num_entries < 0) { err = ERR_INVALID_RANGE; goto parse_error; } if (cmd == INIT_CMD_NUM_ENTRIES) { if (curr_section == SECTION_WAN) pinfo->max_wan_source_entries = num_entries; else if (curr_section == SECTION_LAN) pinfo->max_lan_source_entries = num_entries; else { err = ERR_NOT_IN_SECTION; goto parse_error; } } else { if (curr_section != SECTION_NONE) { err = ERR_IN_SECTION; goto parse_error; } if (cmd == INIT_CMD_BRIDGE_ENTRIES) pinfo->max_bridging_entries = num_entries; else pinfo->max_mc_entries = num_entries; } break; case INIT_CMD_TCP_HITS_TO_ADD: case INIT_CMD_UDP_HITS_TO_ADD: num_hits = atoi(val); if (num_hits < 0) { err = ERR_INVALID_COMMAND; goto parse_error; } if (cmd == INIT_CMD_TCP_HITS_TO_ADD) pinfo->add_requires_min_hits = num_hits; else pinfo->add_requires_min_hits = num_hits; break; case INIT_CMD_INTERFACE: if (curr_section == SECTION_NONE) { err = ERR_NOT_IN_SECTION; goto parse_error; } if (curr_section == SECTION_WAN) { if ( num_wanifs < sizeof(pinfo->p_wanifs) / sizeof(pinfo->p_wanifs[0]) ) { strncpy(pinfo->p_wanifs[num_wanifs].ifname, val, PPA_IF_NAME_SIZE); pinfo->p_wanifs[num_wanifs].if_flags = 0; num_wanifs++; } } else if (curr_section == SECTION_LAN) { if ( num_wanifs < sizeof(pinfo->p_lanifs) / sizeof(pinfo->p_lanifs[0]) ) { strncpy(pinfo->p_lanifs[num_lanifs].ifname, val, PPA_IF_NAME_SIZE); pinfo->p_lanifs[num_lanifs].if_flags = PPA_F_LAN_IF; num_lanifs++; } } break; default: err = ERR_INVALID_COMMAND; goto parse_error; } } } return PPA_CMD_OK; // error messages parse_error: switch(err) { case ERR_MULTIPLE_SECTIONS: IFX_PPACMD_PRINT("error: multiple section definitions - line %d\n", linenum); break; case ERR_INVALID_SECTION_NAME: IFX_PPACMD_PRINT("error: invalid section name - line %d\n", linenum); break; case ERR_INVALID_COMMAND: IFX_PPACMD_PRINT("error: invalid command - line %d\n", linenum); break; case ERR_NOT_IN_SECTION: IFX_PPACMD_PRINT("error: command not within valid section - line %d\n", linenum); break; case ERR_IN_SECTION: IFX_PPACMD_PRINT("error: command within section - line %d\n", linenum); break; case ERR_INVALID_RANGE: IFX_PPACMD_PRINT("error: parameter outside allowed range - line %d\n", linenum); break; } return PPA_CMD_ERR; } static int ppa_parse_init_cmd(PPA_CMD_OPTS *popts,PPA_CMD_DATA *pdata) { unsigned int i; PPA_CMD_INIT_INFO *pinfo = &pdata->init_info; PPA_CMD_VERSION_INFO ver; PPA_CMD_MAX_ENTRY_INFO max_entries; uint32_t f_incorrect_fw = 1; // Default PPA Settings pinfo->lan_rx_checks.f_ip_verify = 0; pinfo->lan_rx_checks.f_tcp_udp_verify = 0; pinfo->lan_rx_checks.f_tcp_udp_err_drop = 0; pinfo->lan_rx_checks.f_drop_on_no_hit = 0; pinfo->lan_rx_checks.f_mc_drop_on_no_hit = 0; pinfo->wan_rx_checks.f_ip_verify = 0; pinfo->wan_rx_checks.f_tcp_udp_verify = 0; pinfo->wan_rx_checks.f_tcp_udp_err_drop = 0; pinfo->wan_rx_checks.f_drop_on_no_hit = 0; pinfo->wan_rx_checks.f_mc_drop_on_no_hit = 0; pinfo->num_lanifs = 0; memset(pinfo->p_lanifs, 0, sizeof(pinfo->p_lanifs)); pinfo->num_wanifs = 0; memset(pinfo->p_wanifs, 0, sizeof(pinfo->p_wanifs)); pinfo->max_lan_source_entries = 0; pinfo->max_wan_source_entries = 0; pinfo->max_mc_entries = 0; pinfo->max_bridging_entries = 0; pinfo->add_requires_min_hits = 1; if( ppa_do_ioctl_cmd(PPA_CMD_GET_VERSION, &ver ) != PPA_CMD_OK ) return -EIO; if( ppa_do_ioctl_cmd(PPA_CMD_GET_MAX_ENTRY, &max_entries) != PPA_CMD_OK ) { return -EIO; } pinfo->max_lan_source_entries = max_entries.entries.max_lan_entries; pinfo->max_wan_source_entries = max_entries.entries.max_wan_entries; pinfo->max_mc_entries = max_entries.entries.max_mc_entries; pinfo->max_bridging_entries = max_entries.entries.max_bridging_entries; if( ver.ppe_fw_ver.family ) f_incorrect_fw = 0; else f_incorrect_fw = 1; if( f_incorrect_fw ) { IFX_PPACMD_PRINT("Wrong PPE FW version:family-%u, itf-%u\n", (unsigned int)ver.ppe_fw_ver.family, (unsigned int)ver.ppe_fw_ver.itf); return PPA_CMD_ERR; } // Override any default setting from configuration file (if specified) while(popts->opt) { switch(popts->opt) { case 'f': if ( parse_init_config_file( popts->optarg, &pdata->init_info) ) { IFX_PPACMD_PRINT("%s: error reading PPA configuration file: %s\n", PPA_CMD_NAME, popts->optarg); return PPA_CMD_ERR; } break; case 'l': if( my_strtoul( popts->optarg ) < pinfo->max_lan_source_entries ) pinfo->max_lan_source_entries = my_strtoul( popts->optarg ); break; case 'w': if( my_strtoul( popts->optarg ) < pinfo->max_wan_source_entries ) pinfo->max_wan_source_entries = my_strtoul( popts->optarg ); break; case 'm': if( my_strtoul( popts->optarg ) < pinfo->max_mc_entries ) pinfo->max_mc_entries = my_strtoul( popts->optarg ); break; case 'b': if( my_strtoul( popts->optarg ) < pinfo->max_bridging_entries ) pinfo->max_bridging_entries = my_strtoul( popts->optarg ); break; case 'c': if( strcmp(popts->optarg, "enable" ) == 0) { pinfo->lan_rx_checks.f_ip_verify = 1; pinfo->lan_rx_checks.f_tcp_udp_verify = 1; pinfo->wan_rx_checks.f_ip_verify = 1; pinfo->wan_rx_checks.f_tcp_udp_verify = 1; } else if( strcmp(popts->optarg, "disable" ) == 0) { pinfo->lan_rx_checks.f_ip_verify = 0; pinfo->lan_rx_checks.f_tcp_udp_verify = 0; pinfo->wan_rx_checks.f_ip_verify = 0; pinfo->wan_rx_checks.f_tcp_udp_verify = 0; } break; default: return PPA_CMD_ERR; } popts++; } IFX_DBG("LAN SETTINGS\n"); IFX_DBG(" IP Verify: %s\n", pinfo->lan_rx_checks.f_ip_verify ? "enable":"disable"); IFX_DBG(" UDP Verify: %s\n", pinfo->lan_rx_checks.f_tcp_udp_verify ? "enable":"disable"); IFX_DBG("TCP/UDP Error Drop: %s\n", pinfo->lan_rx_checks.f_tcp_udp_err_drop ? "enable":"disable"); IFX_DBG(" DROP on HIT: %s\n", pinfo->lan_rx_checks.f_drop_on_no_hit ? "enable":"disable"); IFX_DBG(" MC Drop on HIT: %s\n", pinfo->lan_rx_checks.f_mc_drop_on_no_hit ? "enable":"disable"); IFX_DBG("WAN SETTINGS\n"); IFX_DBG(" IP Verify: %s\n", pinfo->wan_rx_checks.f_ip_verify ? "enable":"disable"); IFX_DBG(" UDP Verify: %s\n", pinfo->wan_rx_checks.f_tcp_udp_verify ? "enable":"disable"); IFX_DBG("TCP/UDP Error Drop: %s\n", pinfo->wan_rx_checks.f_tcp_udp_err_drop ? "enable":"disable"); IFX_DBG(" DROP on HIT: %s\n", pinfo->wan_rx_checks.f_drop_on_no_hit ? "enable":"disable"); IFX_DBG(" MC Drop on HIT: %s\n", pinfo->wan_rx_checks.f_mc_drop_on_no_hit ? "enable":"disable"); IFX_DBG("INTERFACES\n"); IFX_DBG("Number of LAN IF: %lu\n", pinfo->num_lanifs); for ( i = 0; i < pinfo->num_lanifs; i++ ) IFX_DBG(" %s (%08lX)\n", pinfo->p_lanifs[i].ifname, pinfo->p_lanifs[i].if_flags); IFX_DBG("Number of WAN IF: %lu\n",pinfo->num_wanifs); for ( i = 0; i < pinfo->num_wanifs; i++ ) IFX_DBG(" %s %08lX)\n", pinfo->p_wanifs[i].ifname, pinfo->p_wanifs[i].if_flags); IFX_DBG("OTHER\n"); IFX_DBG(" Max. LAN Entries: %lu\n", pinfo->max_lan_source_entries); IFX_DBG(" Max. WAN Entries: %lu\n", pinfo->max_wan_source_entries); IFX_DBG(" Max. MC Entries: %lu\n", pinfo->max_mc_entries); IFX_DBG("Max. Bridge Entries: %lu\n", pinfo->max_bridging_entries); IFX_DBG(" Min. Hits: %lu\n", pinfo->add_requires_min_hits); return PPA_CMD_OK; } static void ppa_print_init_fake_cmd(PPA_CMD_DATA *pdata) { /* By default, we will enable ppa LAN/WAN acceleratation */ PPA_CMD_ENABLE_INFO enable_info; memset( &enable_info, 0, sizeof(enable_info)) ; enable_info.lan_rx_ppa_enable = 1; enable_info.wan_rx_ppa_enable = 1; if( ppa_do_ioctl_cmd(PPA_CMD_ENABLE, &enable_info ) != PPA_CMD_OK ) { IFX_PPACMD_PRINT("ppacmd control to enable lan/wan failed\n"); return ; } } /* ==================================================================================== command: exit description: Remove the Packet Processing Acceleration Module options: None ==================================================================================== */ static void ppa_print_exit_help(int summary) { IFX_PPACMD_PRINT("exit\n"); return; } static int ppa_parse_exit_cmd(PPA_CMD_OPTS *popts,PPA_CMD_DATA *pdata) { if (popts->opt != 0) return PPA_CMD_ERR; IFX_DBG("EXIT COMMAND\n"); return PPA_CMD_OK; } /* ==================================================================================== command: control description: Enable and Disable Packet Processing Acceleration for WAN and/or LAN interfaces. options: Enable and/or Disable parameters ==================================================================================== */ static const struct option ppa_control_long_opts[] = { {"enable-lan", no_argument, NULL, OPT_ENABLE_LAN}, {"disable-lan", no_argument, NULL, OPT_DISABLE_LAN}, {"enable-wan", no_argument, NULL, OPT_ENABLE_WAN}, {"disable-wan", no_argument, NULL, OPT_DISABLE_WAN}, { 0,0,0,0 } }; static void ppa_print_control_help(int summary) { IFX_PPACMD_PRINT("control {--enable-lan|--disable-lan} {--enable-wan|--disable-wan} \n"); return; } static int ppa_parse_control_cmd(PPA_CMD_OPTS *popts,PPA_CMD_DATA *pdata) { unsigned int lan_opt = 0, wan_opt = 0; while(popts->opt) { switch(popts->opt) { case OPT_ENABLE_LAN: pdata->ena_info.lan_rx_ppa_enable = 1; lan_opt++; break; case OPT_DISABLE_LAN: pdata->ena_info.lan_rx_ppa_enable = 0; lan_opt++; break; case OPT_ENABLE_WAN: pdata->ena_info.wan_rx_ppa_enable = 1; wan_opt++; break; case OPT_DISABLE_WAN: pdata->ena_info.wan_rx_ppa_enable = 0; wan_opt++; break; } popts++; } /* Allow only one of the parameters for LAN or WAN to be specified */ if (wan_opt > 1 || lan_opt > 1) return PPA_CMD_ERR; if (wan_opt ==0 && lan_opt == 0) /*sgh add: without this checking, all lan/wan acceleration will be disabled if user run command "ppacmd control" without any parameter */ return PPA_CMD_ERR; IFX_DBG("PPA CONTROL: LAN = %s WAN = %s\n", pdata->ena_info.lan_rx_ppa_enable ? "enable" : "disable", pdata->ena_info.wan_rx_ppa_enable ? "enable" : "disable"); return PPA_CMD_OK; } /* ==================================================================================== command: status description: Display Packet Processing Acceleration status for WAN and/or LAN interfaces. options: None ==================================================================================== */ static void ppa_print_status_help(int summary) { IFX_PPACMD_PRINT("status [-o outfile] \n"); return; } static int ppa_parse_status_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int out_opt = 0; while(popts->opt) { if (popts->opt == 'o') { g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); out_opt++; } else { return PPA_CMD_ERR; } } if (out_opt > 1) return PPA_CMD_ERR; IFX_DBG("PPA STATUS\n"); return PPA_CMD_OK; } static void ppa_print_status(PPA_CMD_DATA *pdata) { if( pdata->ena_info.flags == 0 ) IFX_PPACMD_PRINT("PPA not initialized yet\n"); else { IFX_PPACMD_PRINT("LAN Acceleration is %s.\n", pdata->ena_info.lan_rx_ppa_enable ? "enabled": "disabled"); IFX_PPACMD_PRINT("WAN Acceleration is %s.\n", pdata->ena_info.wan_rx_ppa_enable ? "enabled": "disabled"); } } /* ==================================================================================== command: setmac description: Set Ethernet MAC address options: None ==================================================================================== */ static void ppa_print_set_mac_help(int summary) { IFX_PPACMD_PRINT("setmac -i -m \n"); return; } static int ppa_parse_set_mac_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int if_opt = 0, mac_opt = 0; while(popts->opt) { if (popts->opt == 'i') { strncpy(pdata->if_mac.ifname,popts->optarg,PPA_IF_NAME_SIZE); if_opt++; } else if (popts->opt == 'm') { stomac(popts->optarg,pdata->if_mac.mac); mac_opt++; } else { return PPA_CMD_ERR; } popts++; } if (mac_opt != 1 || if_opt != 1) return PPA_CMD_ERR; IFX_DBG("PPA SET MAC: %s = %02x:%02x:%02x:%02x:%02x:%02x\n", pdata->if_mac.ifname, pdata->if_mac.mac[0], pdata->if_mac.mac[1], pdata->if_mac.mac[2], pdata->if_mac.mac[3], pdata->if_mac.mac[4], pdata->if_mac.mac[5]); return PPA_CMD_OK; } /* ==================================================================================== Generic add/delete/get interface functions. The add/delete WAN interface commands share the same data structures and command options so they are combined into one set of functions and shared by each. ==================================================================================== */ static int ppa_parse_add_del_if_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { int opt = 0; while (popts->opt) { if (popts->opt == 'i') { strncpy(pdata->if_info.ifname,popts->optarg,PPA_IF_NAME_SIZE); opt ++; } else { return PPA_CMD_ERR; } popts++; } if( opt != 1 ) return PPA_CMD_ERR; IFX_DBG("PPA ADD/DEL IF: %s \n", pdata->if_info.ifname); return PPA_CMD_OK; } static void ppa_print_lan_netif_cmd(PPA_CMD_DATA *pdata) { int i; if( !g_output_to_file ) { for(i=0; iall_if_info.num_ifinfos; i++ ) IFX_PPACMD_PRINT("[%2d] %15s\n", i, pdata->all_if_info.ifinfo[i].ifname ); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->all_if_info), sizeof(pdata->all_if_info) ); } } static void ppa_print_get_lan_netif_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) IFX_PPACMD_PRINT("LAN IF: ---\n"); ppa_print_lan_netif_cmd(pdata); } static void ppa_print_get_wan_netif_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) IFX_PPACMD_PRINT("WAN IF: ---\n"); ppa_print_lan_netif_cmd(pdata); } /* ==================================================================================== command: addwan delwan getwan description: Add WAN interface to PPA options: ==================================================================================== */ static void ppa_print_add_wan_help(int summary) { IFX_PPACMD_PRINT("addwan -i \n"); return; } static void ppa_print_del_wan_help(int summary) { IFX_PPACMD_PRINT("delwan -i \n"); return; } static void ppa_print_get_wan_help(int summary) { IFX_PPACMD_PRINT("getwan [-o outfile] \n"); return; } /* ==================================================================================== command: addlan dellan getlan description: options: ==================================================================================== */ static void ppa_print_add_lan_help(int summary) { IFX_PPACMD_PRINT("addlan -i \n"); return; } static void ppa_print_del_lan_help(int summary) { IFX_PPACMD_PRINT("dellan -i \n"); return; } static void ppa_print_get_lan_help(int summary) { IFX_PPACMD_PRINT("getlan [ -o outfile\n"); return; } /* ==================================================================================== command: getmac description: Get Ethernet MAC address options: interface for MAC address ==================================================================================== */ static void ppa_print_get_mac_help(int summary) { IFX_PPACMD_PRINT("getmac -i [-o outfile] \n"); return; } static int ppa_parse_get_mac_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int if_opt = 0, out_opt = 0; while (popts->opt) { if (popts->opt == 'i') { strncpy(pdata->if_info.ifname,popts->optarg,PPA_IF_NAME_SIZE); if_opt++; } else if (popts->opt == 'o') { g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); out_opt++; } else { return PPA_CMD_ERR; } popts++; } // Each parameter must be specified just once. if (out_opt > 1 || if_opt != 1) return PPA_CMD_ERR; IFX_DBG("PPA GET MAC: %s\n", pdata->if_info.ifname); return PPA_CMD_OK; } static void ppa_print_get_mac_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("%02x:%02x:%02x:%02x:%02x:%02x\n", pdata->if_mac.mac[0],pdata->if_mac.mac[1],pdata->if_mac.mac[2], pdata->if_mac.mac[3],pdata->if_mac.mac[4],pdata->if_mac.mac[5] ); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->if_mac), sizeof(pdata->if_mac) ); } } /* ==================================================================================== command: addbr description: options: ==================================================================================== */ static void ppa_add_mac_entry_help(int summary) { IFX_PPACMD_PRINT("addbr -m -i \n"); return; } static int ppa_parse_add_mac_entry_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int if_opt = 0, mac_opt = 0; while (popts->opt) { if (popts->opt == 'i') { strncpy(pdata->mac_entry.ifname,popts->optarg,PPA_IF_NAME_SIZE); if_opt++; } else if (popts->opt == 'm') { stomac(popts->optarg,pdata->mac_entry.mac_addr); mac_opt++; } else { return PPA_CMD_ERR; } popts++; } // Each parameter must be specified just once. if (mac_opt != 1 || if_opt != 1) return PPA_CMD_ERR; IFX_DBG("PPA ADD MAC: %s = %02x:%02x:%02x:%02x:%02x:%02x\n", pdata->mac_entry.ifname, pdata->mac_entry.mac_addr[0], pdata->mac_entry.mac_addr[1], pdata->mac_entry.mac_addr[2], pdata->mac_entry.mac_addr[3], pdata->mac_entry.mac_addr[4], pdata->mac_entry.mac_addr[5]); return PPA_CMD_OK; } /* ==================================================================================== command: delbr description: options: ==================================================================================== */ static void ppa_del_mac_entry_help(int summary) { IFX_PPACMD_PRINT("delbr -m \n"); return; } static int ppa_parse_del_mac_entry_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int mac_opt = 0; while (popts->opt) { if (popts->opt == 'm') { stomac(popts->optarg,pdata->mac_entry.mac_addr); mac_opt++; } else { return PPA_CMD_ERR; } popts++; } // MAC parameter must be specified just once. if (mac_opt != 1) return PPA_CMD_ERR; IFX_DBG("PPA DEL MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", pdata->mac_entry.mac_addr[0], pdata->mac_entry.mac_addr[1], pdata->mac_entry.mac_addr[2], pdata->mac_entry.mac_addr[3], pdata->mac_entry.mac_addr[4], pdata->mac_entry.mac_addr[5]); return PPA_CMD_OK; } /* ==================================================================================== command: setvif description: Set interface VLAN configuration. options: ==================================================================================== */ static const char ppa_set_vlan_if_cfg_short_opts[] = "i:V:c:O:h"; static const struct option ppa_set_vlan_if_cfg_long_opts[] = { {"interface", required_argument, NULL, 'i'}, {"vlan-type", required_argument, NULL, 'V'}, {"tag-control", required_argument, NULL, 'c'}, {"outer-tag-control", required_argument, NULL, 'O'}, {"vlan-aware", no_argument, NULL, OPT_VLAN_AWARE}, {"outer-tag-control", no_argument, NULL, OPT_OUTER_VLAN_AWARE}, { 0,0,0,0 } }; static void ppa_set_vlan_if_cfg_help(int summary) { if (summary) { IFX_PPACMD_PRINT("setvif -i -V -c -O \n"); IFX_PPACMD_PRINT("\t\t := {src-ip-addr|eth-type|ingress-vid|port} \n"); IFX_PPACMD_PRINT("\t\t := {insert|remove|replace|none} \n"); } else { IFX_PPACMD_PRINT("setvif -i -V -c -O \n"); IFX_PPACMD_PRINT("\t\t := {src-ip-addr|eth-type|ingress-vid|port} \n"); IFX_PPACMD_PRINT("\t\t := {insert|remove|replace|none} \n"); } IFX_PPACMD_PRINT("\t\tThis command is for A4/D4 only at present\n"); return; } static int ppa_parse_set_vlan_if_cfg_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int vlan_type_opt = 0, in_tag_opt = 0, out_tag_opt = 0; unsigned int in_aware_opt = 0, out_aware_opt = 0, if_opt = 0; while (popts->opt) { switch(popts->opt) { case 'V': if (strcmp("src-ip-addr",popts->optarg) == 0) pdata->br_vlan.vlan_cfg.src_ip_based_vlan = 1; else if (strcmp("eth-type",popts->optarg) == 0) pdata->br_vlan.vlan_cfg.eth_type_based_vlan = 1; else if (strcmp("ingress-vid",popts->optarg) == 0) pdata->br_vlan.vlan_cfg.vlanid_based_vlan = 1; else if (strcmp("port",popts->optarg) == 0) pdata->br_vlan.vlan_cfg.port_based_vlan = 1; else return PPA_CMD_ERR; vlan_type_opt++; break; case 'c': if (strcmp("insert",popts->optarg) == 0) pdata->br_vlan.vlan_tag_ctrl.insertion = 1; else if (strcmp("remove",popts->optarg) == 0) pdata->br_vlan.vlan_tag_ctrl.remove = 1; else if (strcmp("replace",popts->optarg) == 0) pdata->br_vlan.vlan_tag_ctrl.replace = 1; else if (strcmp("none",popts->optarg) == 0) pdata->br_vlan.vlan_tag_ctrl.unmodified = 1; else return PPA_CMD_ERR; in_tag_opt++; break; case 'O': if (strcmp("insert",popts->optarg) == 0) pdata->br_vlan.vlan_tag_ctrl.out_insertion = 1; else if (strcmp("remove",popts->optarg) == 0) pdata->br_vlan.vlan_tag_ctrl.out_remove = 1; else if (strcmp("replace",popts->optarg) == 0) pdata->br_vlan.vlan_tag_ctrl.out_replace = 1; else if (strcmp("none",popts->optarg) == 0) pdata->br_vlan.vlan_tag_ctrl.out_unmodified = 1; else return PPA_CMD_ERR; out_tag_opt++; break; case 'i': strncpy(pdata->br_vlan.if_name,popts->optarg,PPA_IF_NAME_SIZE); if_opt++; break; case OPT_VLAN_AWARE: pdata->br_vlan.vlan_cfg.vlan_aware = 1; in_aware_opt++; break; case OPT_OUTER_VLAN_AWARE: pdata->br_vlan.vlan_cfg.out_vlan_aware = 1; out_aware_opt++; break; default: return PPA_CMD_ERR; } popts++; } if ( /*vlan_type_opt > 1 ||*/ if_opt != 1 || in_tag_opt > 1 || out_tag_opt > 1 || in_aware_opt > 1 || out_aware_opt > 1) return PPA_CMD_ERR; // Set default values is not specified in command line if (vlan_type_opt == 0) pdata->br_vlan.vlan_cfg.port_based_vlan = 1; if (in_tag_opt == 0) pdata->br_vlan.vlan_tag_ctrl.unmodified = 1; if (out_tag_opt == 0) pdata->br_vlan.vlan_tag_ctrl.out_unmodified = 1; IFX_DBG("VLAN TYPE:%s\n", pdata->br_vlan.if_name); IFX_DBG(" SRC IP VLAN: %s\n", pdata->br_vlan.vlan_cfg.src_ip_based_vlan ? "enable" : "disable"); IFX_DBG(" ETH TYPE VLAN: %s\n", pdata->br_vlan.vlan_cfg.eth_type_based_vlan ? "enable" : "disable"); IFX_DBG(" VID VLAN: %s\n", pdata->br_vlan.vlan_cfg.vlanid_based_vlan ? "enable" : "disable"); IFX_DBG("PORT BASED VLAN: %s\n", pdata->br_vlan.vlan_cfg.port_based_vlan ? "enable" : "disable"); IFX_DBG("TAG CONTROL\n"); IFX_DBG(" INSERT: %s\n", pdata->br_vlan.vlan_tag_ctrl.insertion ? "enable" : "disable"); IFX_DBG(" REMOVE: %s\n", pdata->br_vlan.vlan_tag_ctrl.remove ? "enable" : "disable"); IFX_DBG(" REPLACE: %s\n", pdata->br_vlan.vlan_tag_ctrl.replace ? "enable" : "disable"); IFX_DBG(" OUT INSERT: %s\n",pdata->br_vlan.vlan_tag_ctrl.out_insertion ? "enable" : "disable"); IFX_DBG(" OUT REMOVE: %s\n", pdata->br_vlan.vlan_tag_ctrl.out_remove ? "enable" : "disable"); IFX_DBG(" OUT REPLACE: %s\n", pdata->br_vlan.vlan_tag_ctrl.out_replace ? "enable" : "disable"); IFX_DBG(" VLAN AWARE: %s\n", pdata->br_vlan.vlan_cfg.vlan_aware ? "enable" : "disable"); IFX_DBG("OUT VLAN AWARE: %s\n", pdata->br_vlan.vlan_cfg.out_vlan_aware ? "enable" : "disable"); return PPA_CMD_OK; } /* ==================================================================================== command: description: options: ==================================================================================== */ static void ppa_get_vlan_if_cfg_help(int summary) { IFX_PPACMD_PRINT("getvif -i [-o outfile] \n"); IFX_PPACMD_PRINT("\t\tThis command is for A4/D4 only at present\n"); return; } static int ppa_parse_get_vlan_if_cfg_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int out_opts = 0, if_opts = 0; while (popts->opt) { if (popts->opt == 'i') { strcpy(pdata->br_vlan.if_name, popts->optarg); if_opts++; } else if (popts->opt == 'o') { g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); out_opts++; } else { return PPA_CMD_ERR; } popts++; } if (out_opts > 1 || if_opts != 1) return PPA_CMD_ERR; IFX_DBG("PPA GET VLAN CFG: %s\n", pdata->br_vlan.if_name); return PPA_CMD_OK; } static void ppa_print_get_vif(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { //vlan_tag_ctrl, &cmd_info.br_vlan.vlan_cfg, c IFX_PPACMD_PRINT("%s: ", pdata->br_vlan.if_name); if( pdata->br_vlan.vlan_cfg.eth_type_based_vlan ) IFX_PPACMD_PRINT(" ether-type based, "); if( pdata->br_vlan.vlan_cfg.src_ip_based_vlan) IFX_PPACMD_PRINT(" src-ip based, "); if( pdata->br_vlan.vlan_cfg.vlanid_based_vlan ) IFX_PPACMD_PRINT(" vlan id based, "); if( pdata->br_vlan.vlan_cfg.port_based_vlan ) IFX_PPACMD_PRINT(" port based,"); IFX_PPACMD_PRINT( "%s, ", pdata->br_vlan.vlan_cfg.vlan_aware ? "inner vlan aware":"inner vlan no"); IFX_PPACMD_PRINT( "%s, ", pdata->br_vlan.vlan_cfg.out_vlan_aware ? "out vlan aware":"outlvan vlan no"); if( pdata->br_vlan.vlan_tag_ctrl.unmodified ) IFX_PPACMD_PRINT("inner-vlan unmodified, "); else if( pdata->br_vlan.vlan_tag_ctrl.insertion ) IFX_PPACMD_PRINT("inner-vlan insert, "); else if( pdata->br_vlan.vlan_tag_ctrl.remove ) IFX_PPACMD_PRINT("inner-vlan remove, "); else if( pdata->br_vlan.vlan_tag_ctrl.replace ) IFX_PPACMD_PRINT("inner-vlan replace, "); if( pdata->br_vlan.vlan_tag_ctrl.out_unmodified ) IFX_PPACMD_PRINT("out-vlan unmodified, "); else if( pdata->br_vlan.vlan_tag_ctrl.out_insertion ) IFX_PPACMD_PRINT("out-vlan insert, "); else if( pdata->br_vlan.vlan_tag_ctrl.out_remove ) IFX_PPACMD_PRINT("out-vlan remove, "); else if( pdata->br_vlan.vlan_tag_ctrl.out_replace ) IFX_PPACMD_PRINT("out-vlan replace, "); IFX_PPACMD_PRINT("\n"); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->br_vlan), sizeof(pdata->br_vlan) ); } } /* ==================================================================================== command: addvfilter description: options: ==================================================================================== */ typedef struct vlan_ctrl { char* cmd_str; //command char op; //qid } vlan_ctrl; vlan_ctrl vlan_ctrl_list[]={{"none", 0},{"remove", 1},{"insert", 2},{"replace", 3} }; static const char ppa_add_vlan_filter_short_opts[] = "t:V:i:a:e:o:q:d:c:r:h"; static const struct option ppa_add_vlan_filter_long_opts[] = { {"vlan-tag", required_argument, NULL, 't'}, {"ingress-vid", required_argument, NULL, 'V'}, {"interface", required_argument, NULL, 'i'}, {"src-ipaddr", required_argument, NULL, 'a'}, {"eth-type", required_argument, NULL, 'e'}, {"out-vlan-id", required_argument, NULL, 'o'}, {"dest_qos", required_argument, NULL, 'q'}, {"dst-member", required_argument, NULL, 'd'}, {"inner-vctrl", required_argument, NULL, 'r'}, {"outer-vctrl", required_argument, NULL, 'c'}, { 0,0,0,0 } }; static void ppa_add_vlan_filter_help(int summary) { IFX_PPACMD_PRINT("addvfilter {-i |-a |-e |-V } -t -o -q \n\t\t\t -d -c -r \n"); IFX_PPACMD_PRINT("\t\tparameter c/r: for tag based vlan filter only\n"); IFX_PPACMD_PRINT("\t\tvlan_filter, 0, sizeof(pdata->vlan_filter) ); while(popts->opt) { switch(popts->opt) { case 't': /*inner vlan: for all kinds of vlan filters */ pdata->vlan_filter.vlan_filter_cfg.vlan_info.vlan_vci = my_strtoul(popts->optarg); tag_opts++; break; case 'i': /*port based vlan filter: for comparing */ strncpy(pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ifname, popts->optarg, PPA_IF_NAME_SIZE-1); pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags = PPA_F_VLAN_FILTER_IFNAME; match_opts++; break; case 'a': /*ip based vlan filter: for comparing*/ inet_aton(popts->optarg, &pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ip_src); pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags = PPA_F_VLAN_FILTER_IP_SRC; match_opts++; break; case 'e': /*protocol based vlan filter: for comparing */ pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.eth_protocol = my_strtoul(popts->optarg); pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags = PPA_F_VLAN_FILTER_ETH_PROTO; match_opts++; break; case 'V': /*vlan tag based vlan filter: for comparing */ pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ingress_vlan_tag = my_strtoul(popts->optarg); pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags = PPA_F_VLAN_FILTER_VLAN_TAG; match_opts++; break; case 'o': /*outer vlan: for all kinds of vlan filters */ pdata->vlan_filter.vlan_filter_cfg.vlan_info.out_vlan_id= my_strtoul(popts->optarg); out_vlan_id_opts++; break; case 'd': /*member list: for all kinds of vlan filters */ if( vlan_if_member_opts < PPA_MAX_IFS_NUM ) { strncpy(pdata->vlan_filter.vlan_filter_cfg.vlan_info.vlan_if_membership[vlan_if_member_opts].ifname, popts->optarg, sizeof(pdata->vlan_filter.vlan_filter_cfg.vlan_info.vlan_if_membership[vlan_if_member_opts].ifname) ); vlan_if_member_opts++; pdata->vlan_filter.vlan_filter_cfg.vlan_info.num_ifs = vlan_if_member_opts; } break; case 'q': /*qid: for all kinds of vlan filters */ pdata->vlan_filter.vlan_filter_cfg.vlan_info.qid = my_strtoul(popts->optarg); qid_opts++; break; case 'c': //inner vlan ctrl: only for vlan tag based vlan filter case 'r': //out vlan ctrl:: only for vlan tag based vlan filter for(i=0; ioptarg ) == 0 ) { if( popts->opt == 'c' ) { vlan_ctrl = vlan_ctrl_list[i].op << 2; pdata->vlan_filter.vlan_filter_cfg.vlan_info.inner_vlan_tag_ctrl = 0; for(j=0; j<8; j++) { pdata->vlan_filter.vlan_filter_cfg.vlan_info.inner_vlan_tag_ctrl |= vlan_ctrl << ( 4 * j ); } inner_vlan_ctrl_opts++; break; } else { vlan_ctrl = (vlan_ctrl_list[i].op); pdata->vlan_filter.vlan_filter_cfg.vlan_info.out_vlan_tag_ctrl = 0; for(j=0; j<8; j++) { pdata->vlan_filter.vlan_filter_cfg.vlan_info.out_vlan_tag_ctrl |= vlan_ctrl << ( 4 * j); } out_vlan_ctrl_opts++; break; } } } break; default: IFX_PPACMD_PRINT("not known parameter: %c\n", popts->opt); return PPA_CMD_ERR; } popts++; } /* Check that match field is not defined more than once and VLAN tag is specified */ if ( ( match_opts != 1) || (tag_opts != 1) || (out_vlan_id_opts !=1) || (vlan_if_member_opts == 0) ) { if( match_opts != 1) IFX_PPACMD_PRINT( "match_opts wrong:%d\n", match_opts); else if( tag_opts != 1) IFX_PPACMD_PRINT( "tag_opts wrong:%d\n", tag_opts); else if( out_vlan_id_opts != 1) IFX_PPACMD_PRINT( "out_vlan_id_opts wrong:%d\n", out_vlan_id_opts); else if( vlan_if_member_opts != 1) IFX_PPACMD_PRINT( "vlan_if_member_opts wrong:%d\n", vlan_if_member_opts); return PPA_CMD_ERR; } if( qid_opts == 0 ) { pdata->vlan_filter.vlan_filter_cfg.vlan_info.qid = PPA_INVALID_QID; } if( pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags == PPA_F_VLAN_FILTER_VLAN_TAG ) { if( (inner_vlan_ctrl_opts != 1) || (out_vlan_ctrl_opts != 1) ) { IFX_PPACMD_PRINT("vlan control wrong: inner_vlan_ctrl_opts=%d, out_vlan_ctrl_opts=%d\n", inner_vlan_ctrl_opts , out_vlan_ctrl_opts); return PPA_CMD_ERR; } } else { if(( inner_vlan_ctrl_opts != 0) ||( out_vlan_ctrl_opts != 0 ) ) { IFX_PPACMD_PRINT("vlan control wrong 2: inner_vlan_ctrl_opts=%d, out_vlan_ctrl_opts=%d\n", inner_vlan_ctrl_opts , out_vlan_ctrl_opts); return PPA_CMD_ERR; } } IFX_DBG("INNER VLAN TAG: 0x%x\n", (unsigned int) pdata->vlan_filter.vlan_filter_cfg.vlan_info.vlan_vci); IFX_DBG("OUT VLAN TAG: 0x%x\n", (unsigned int) pdata->vlan_filter.vlan_filter_cfg.vlan_info.out_vlan_id); IFX_DBG("MATCH FIELD\n"); switch(pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags) { case PPA_F_VLAN_FILTER_VLAN_TAG: IFX_DBG("VLAN TAG: %04lX\n", pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ingress_vlan_tag); IFX_DBG("INNER VLAN CTRL: %s\n", vlan_ctrl_list[ (pdata->vlan_filter.vlan_filter_cfg.vlan_info.inner_vlan_tag_ctrl >> 2 ) & 0x3].cmd_str); IFX_DBG("OUT VLAN CTRL: %s\n", vlan_ctrl_list[ (pdata->vlan_filter.vlan_filter_cfg.vlan_info.out_vlan_tag_ctrl ) & 0x3].cmd_str); break; case PPA_F_VLAN_FILTER_IFNAME: IFX_DBG( "IF NAME: %s\n", pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ifname); break; case PPA_F_VLAN_FILTER_IP_SRC: IFX_DBG("IP SRC: %08lX\n", pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ip_src); break; case PPA_F_VLAN_FILTER_ETH_PROTO: IFX_DBG("ETH TYPE: %04lX\n",pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.eth_protocol); break; } for(i=0; i< pdata->vlan_filter.vlan_filter_cfg.vlan_info.num_ifs; i++ ) { IFX_DBG("Dest member[%d]=%s\n", i, pdata->vlan_filter.vlan_filter_cfg.vlan_info.vlan_if_membership[i].ifname); } return PPA_CMD_OK; } /* ==================================================================================== command: delvfilter description: options: ==================================================================================== */ static const char ppa_del_vlan_filter_short_opts[] = "V:i:a:e:h"; static const struct option ppa_del_vlan_filter_long_opts[] = { {"ingress-vid", required_argument, NULL, 'V'}, {"interface", required_argument, NULL, 'i'}, {"src-ipaddr", required_argument, NULL, 'a'}, {"eth-type", required_argument, NULL, 'e'}, { 0,0,0,0 } }; static void ppa_del_vlan_filter_help(int summary) { IFX_PPACMD_PRINT("delvfilter {-i |-a |-e |-V } \n"); IFX_PPACMD_PRINT("\t\tThis command is for A4/D4 only at present\n"); return; } static int ppa_parse_del_vlan_filter_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int match_opts = 0; while(popts->opt) { switch(popts->opt) { case 'i': /*port based vlan filter: for comparing */ strncpy(pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ifname, popts->optarg, PPA_IF_NAME_SIZE); pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags = PPA_F_VLAN_FILTER_IFNAME; match_opts++; break; case 'a': /*ip based vlan filter: for comparing*/ inet_aton(popts->optarg, &pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ip_src); pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags = PPA_F_VLAN_FILTER_IP_SRC; match_opts++; break; case 'e': /*protocol based vlan filter: for comparing */ pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.eth_protocol = my_strtoul(popts->optarg); pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags = PPA_F_VLAN_FILTER_ETH_PROTO; match_opts++; break; case 'V': /*vlan tag based vlan filter: for comparing */ pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ingress_vlan_tag = my_strtoul(popts->optarg); pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags = PPA_F_VLAN_FILTER_VLAN_TAG; match_opts++; break; default: return PPA_CMD_ERR; } popts++; } /* Check that match field is not defined more than once and VLAN tag is specified */ if ( match_opts != 1) return PPA_CMD_ERR; switch(pdata->vlan_filter.vlan_filter_cfg.match_field.match_flags) { case PPA_F_VLAN_FILTER_VLAN_TAG: IFX_DBG("VLAN TAG: %04lX\n", pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ingress_vlan_tag); break; case PPA_F_VLAN_FILTER_IFNAME: IFX_DBG(" IF NAME: %s\n", pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ifname); break; case PPA_F_VLAN_FILTER_IP_SRC: IFX_DBG(" IP SRC: %08lX\n", pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.ip_src); break; case PPA_F_VLAN_FILTER_ETH_PROTO: IFX_DBG("ETH TYPE: %04lX\n",pdata->vlan_filter.vlan_filter_cfg.match_field.match_field.eth_protocol); break; } return PPA_CMD_OK; } /* ==================================================================================== command: getvfiltercount description: get vlan fitlers counter options: ==================================================================================== */ static void ppa_get_vfilter_count_help(int summary) { IFX_PPACMD_PRINT("getvfilternum [-o file ]\n"); IFX_PPACMD_PRINT("\t\tThis command is for A4/D4 only at present\n"); return; } static int ppa_parse_get_vfilter_count(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { int res; res = ppa_parse_simple_cmd( popts, pdata ); if( res != PPA_CMD_OK ) return res; pdata->count_info.flag = 0; return PPA_CMD_OK; } /* ==================================================================================== command: getfilters description: get all vlan fitlers information options: ==================================================================================== */ static void ppa_get_all_vlan_filter_help(int summary) { IFX_PPACMD_PRINT("getvfilters [-o file ]\n"); IFX_PPACMD_PRINT("\t\tThis command is for A4/D4 only at present\n"); return; } static int ppa_get_all_vlan_filter_cmd (PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_VLAN_ALL_FILTER_CONFIG *psession_buffer; PPA_CMD_DATA cmd_info; int res = PPA_CMD_OK, i, j, size; uint32_t flag = PPA_CMD_GET_ALL_VLAN_FILTER_CFG; unsigned char bfCorrectType = 0; //get session count first before malloc memroy cmd_info.count_info.flag = 0; if( ppa_do_ioctl_cmd(PPA_CMD_GET_COUNT_VLAN_FILTER, &cmd_info ) != PPA_CMD_OK ) return -EIO; if( cmd_info.count_info.count == 0 ) { IFX_DBG("vfilter count=0\n"); if( g_output_to_file ) SaveDataToFile(g_output_filename, (char *)(&cmd_info.count_info), sizeof(cmd_info.count_info) ); return PPA_CMD_OK; } //malloc memory and set value correctly size = sizeof(PPA_CMD_COUNT_INFO) + sizeof(PPA_CMD_VLAN_FILTER_CONFIG) * ( 1 + cmd_info.count_info.count ) ; psession_buffer = (PPA_CMD_VLAN_ALL_FILTER_CONFIG *) malloc( size ); if( psession_buffer == NULL ) { IFX_PPACMD_PRINT("Malloc %d bytes failed\n", size ); return PPA_CMD_NOT_AVAIL; } memset( psession_buffer, 0, sizeof(size) ); psession_buffer->count_info.count = cmd_info.count_info.count; psession_buffer->count_info.flag = 0; //get session information if( (res = ppa_do_ioctl_cmd(flag, psession_buffer ) != PPA_CMD_OK ) ) { free( psession_buffer ); return res; } IFX_DBG("Vfilter count=%u. \n", (unsigned int)psession_buffer->count_info.count); if( !g_output_to_file ) { for(i=0; icount_info.count; i++ ) { IFX_PPACMD_PRINT("[%02d] ", i ); if( psession_buffer->filters[i].vlan_filter_cfg.match_field.match_flags == PPA_F_VLAN_FILTER_VLAN_TAG ) { bfCorrectType = 1; IFX_PPACMD_PRINT("Vlan tag based:vlan %u. Qos:%u. ", (unsigned int)psession_buffer->filters[i].vlan_filter_cfg.match_field.match_field.ingress_vlan_tag, (unsigned int)psession_buffer->filters[i].vlan_filter_cfg.vlan_info.qid); } else if( psession_buffer->filters[i].vlan_filter_cfg.match_field.match_flags == PPA_F_VLAN_FILTER_IFNAME ) { bfCorrectType = 1; IFX_PPACMD_PRINT("Port based: %s. Qos:%d. ", psession_buffer->filters[i].vlan_filter_cfg.match_field.match_field.ifname, psession_buffer->filters[i].vlan_filter_cfg.vlan_info.qid); } else if( psession_buffer->filters[i].vlan_filter_cfg.match_field.match_flags == PPA_F_VLAN_FILTER_IP_SRC) { bfCorrectType = 1; IFX_PPACMD_PRINT("Src ip based: %u.%u.%u.%u. Qos:%d. ", NIPQUAD( psession_buffer->filters[i].vlan_filter_cfg.match_field.match_field.ip_src) , psession_buffer->filters[i].vlan_filter_cfg.vlan_info.qid); } else if( psession_buffer->filters[i].vlan_filter_cfg.match_field.match_flags == PPA_F_VLAN_FILTER_ETH_PROTO) { bfCorrectType = 1; IFX_PPACMD_PRINT("Ether type based: %04x. Qos:%u. ", (unsigned int)psession_buffer->filters[i].vlan_filter_cfg.match_field.match_field.eth_protocol, (unsigned int)psession_buffer->filters[i].vlan_filter_cfg.vlan_info.qid); } if( bfCorrectType ) { IFX_PPACMD_PRINT("Inner/Out VLAN:%03X/%03x ", (unsigned int)psession_buffer->filters[i].vlan_filter_cfg.vlan_info.vlan_vci, (unsigned int)psession_buffer->filters[i].vlan_filter_cfg.vlan_info.out_vlan_id ); IFX_PPACMD_PRINT("Dst members:"); for(j=0; jfilters[i].vlan_filter_cfg.vlan_info.num_ifs ; j++ ) { if( i == 0 ) IFX_PPACMD_PRINT("%s", psession_buffer->filters[i].vlan_filter_cfg.vlan_info.vlan_if_membership[j].ifname); else IFX_PPACMD_PRINT(",%s", psession_buffer->filters[i].vlan_filter_cfg.vlan_info.vlan_if_membership[j].ifname); } IFX_PPACMD_PRINT("."); if (psession_buffer->filters[i].vlan_filter_cfg.match_field.match_flags == PPA_F_VLAN_FILTER_VLAN_TAG ) { IFX_PPACMD_PRINT("\tInner/Out vlan control:%s/%s ", vlan_ctrl_list[ (psession_buffer->filters[i].vlan_filter_cfg.vlan_info.inner_vlan_tag_ctrl >> 2) & 0x3].cmd_str, vlan_ctrl_list[ (psession_buffer->filters[i].vlan_filter_cfg.vlan_info.out_vlan_tag_ctrl >> 0) & 0x3].cmd_str); } } IFX_PPACMD_PRINT("\n"); } } else { SaveDataToFile(g_output_filename, (char *)(psession_buffer), size ); } free( psession_buffer ); return PPA_CMD_OK; } /*multicast bridging/routing */ static const char ppa_mc_add_short_opts[] = "s:g:l:w:f:t:h"; //need to further implement add/remove/modify vlan and enable new dscp and its value static const struct option ppa_mc_add_long_opts[] = { {"bridging_flag", required_argument, NULL, 's'}, /*0-means routing, 1 means bridging */ /*{"multicat mac address", required_argument, NULL, 'm'}, */ /*for bridging only as ritech suggest. I may not help at present */ {"multicast group", required_argument, NULL, 'g'}, {"down interface", required_argument, NULL, 'l'}, {"up interface", required_argument, NULL, 'w'}, {"flag", required_argument, NULL, 'f'}, {"qid", required_argument, NULL, 't'}, { 0,0,0,0 } }; static void ppa_add_mc_help( int summary) { IFX_PPACMD_PRINT("addmc [-s ] -g ip-group -l -w\n"); // [ -m ] -t qid is for future only IFX_PPACMD_PRINT(" option -s: must be 1 for multicast bridging. For multicast routing, it can be 0 or skipp this option \n"); IFX_PPACMD_PRINT(" option -l: if not set this parameter, it means to delete the multicast group \n"); return; } static int ppa_parse_add_mc_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int lan_if_opts=0, g_opts=0; memset(pdata, 0, sizeof(*pdata) ); while(popts->opt) { switch(popts->opt) { case 's': pdata->mc_add_info.bridging_flag = my_strtoul(popts->optarg); IFX_DBG("addmc mode: %s\n", pdata->mc_add_info.bridging_flag ? "bridging":"routing" ); break; #ifdef PPA_MC_FUTURE_USE case 'm': stomac(popts->optarg, pdata->mc_add_info.mac); IFX_DBG("addmc mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", pdata->mc_add_info.mac[0], pdata->mc_add_info.mac[1], pdata->mc_add_info.mac[2], pdata->mc_add_info.mac[3], pdata->mc_add_info.mac[4], pdata->mc_add_info.mac[5]); break; #endif case 'g': inet_aton(popts->optarg, &pdata->mc_add_info.mc.mcast_addr); g_opts ++; IFX_DBG("addmc group ip: %d.%d.%d.%d\n", NIPQUAD( pdata->mc_add_info.mc.mcast_addr) ); break; case 'l': if( lan_if_opts > PPA_MAX_MC_IFS_NUM ) return PPA_CMD_ERR; //not to accelerated since too many lan interrace join the same group strcpy(pdata->mc_add_info.lan_ifname[lan_if_opts], popts->optarg); IFX_DBG("addmc lan if:%s,lan_if_opts:%d\n", pdata->mc_add_info.lan_ifname[lan_if_opts], lan_if_opts+1 ); lan_if_opts++; break; case 'w': strncpy(pdata->mc_add_info.src_ifname, popts->optarg, sizeof(pdata->mc_add_info.src_ifname)-1); IFX_DBG("addmc wan if:%s\n", pdata->mc_add_info.src_ifname); break; case 't': //future only pdata->mc_add_info.mc.mc_extra.dslwan_qid_remark = 1; pdata->mc_add_info.mc.mc_extra.dslwan_qid = my_strtoul( popts->optarg); IFX_DBG("addmc qid:%d (flag=%d)\n",pdata->mc_add_info.mc.mc_extra.dslwan_qid, pdata->mc_add_info.mc.mc_extra.dslwan_qid_remark); break; default: IFX_PPACMD_PRINT("mc_add not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } /* Check that match field is not defined more than once and VLAN tag is specified */ if( g_opts != 1 ) return PPA_CMD_ERR; pdata->mc_add_info.num_ifs = lan_if_opts; return PPA_CMD_OK; } /* ==================================================================================== command: getmcextra description: get multicast extra information, like vlan/dscp options: ==================================================================================== */ static const char ppa_get_mc_extra_short_opts[] = "g:o:h"; //need to further implement add/remove/modify vlan and enable new dscp and its value static const struct option ppa_get_mc_extra_long_opts[] = { {"multicast group", required_argument, NULL, 'g'}, {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static void ppa_get_mc_extra_help( int summary) { IFX_PPACMD_PRINT("getmcextra -g [-o file ]\n"); // [ -m ] return; } static int ppa_parse_get_mc_extra_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int g_opt=0; memset(pdata, 0, sizeof(*pdata) ); while(popts->opt) { switch(popts->opt) { case 'g': inet_aton(popts->optarg, &pdata->mc_entry.mcast_addr); IFX_DBG("getmcextra group ip: %d.%d.%d.%d\n", NIPQUAD( pdata->mc_entry.mcast_addr) ); g_opt ++; break; case 'o': g_output_to_file = 1; strncpy(g_output_filename, popts->optarg, PPACMD_MAX_FILENAME); break; default: IFX_PPACMD_PRINT("getmcextra not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( g_opt != 1) return PPA_CMD_ERR; return PPA_CMD_OK; } static void ppa_print_get_mc_extra_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("multicast group %d.%d.%d.%d extra properties:\n", NIPQUAD(pdata->mc_entry.mcast_addr)); if(pdata->mc_entry. mc_extra.dscp_remark ) IFX_PPACMD_PRINT("\tnew_dscp=%04x. ", (unsigned int)pdata->mc_entry.mc_extra.new_dscp ); else IFX_PPACMD_PRINT("Not new dscp editing. "); if(pdata->mc_entry.mc_extra.vlan_insert ) IFX_PPACMD_PRINT("\tNew inner vlan =%04x. ", (unsigned int)(pdata->mc_entry.mc_extra.vlan_prio<<13) + (pdata->mc_entry.mc_extra.vlan_cfi<<12) + pdata->mc_entry.mc_extra.vlan_id); else if(pdata->mc_entry.mc_extra.vlan_remove ) IFX_PPACMD_PRINT("Remove inner vlan. "); else IFX_PPACMD_PRINT("No inner vlan editing. "); if(pdata->mc_entry.mc_extra.out_vlan_insert ) IFX_PPACMD_PRINT("New outvlan=%04x. ", (unsigned int)pdata->mc_entry.mc_extra.out_vlan_tag ); else if(pdata->mc_entry.mc_extra.out_vlan_remove ) IFX_PPACMD_PRINT("Remove out vlan. "); else IFX_PPACMD_PRINT("No out vlan editing. "); if( pdata->mc_entry.mc_extra.dslwan_qid_remark ) IFX_PPACMD_PRINT("qid: %d\n", pdata->mc_entry.mc_extra.dslwan_qid ); IFX_PPACMD_PRINT("\n"); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->mc_entry), sizeof(pdata->mc_entry) ); } } /* ==================================================================================== command: getmcnum description: get multicast groups count options: ==================================================================================== */ static void ppa_get_mc_count_help(int summary) { IFX_PPACMD_PRINT("getmcnum [-o file ]\n"); return; } static int ppa_parse_get_mc_count_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { int res; res = ppa_parse_simple_cmd( popts, pdata ); if( res != PPA_CMD_OK ) return res; pdata->count_info.flag = 0; return PPA_CMD_OK; } /* ==================================================================================== command: getmcgroups description: get all multicast groups information options: ==================================================================================== */ static void ppa_get_mc_groups_help( int summary) { IFX_PPACMD_PRINT("getmcgroups [-o file ]\n"); // [ -m ] return; } static int ppa_get_mc_groups_cmd (PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_MC_GROUPS_INFO *psession_buffer; PPA_CMD_DATA cmd_info; int res = PPA_CMD_OK, i, j, size; uint32_t flag = PPA_CMD_GET_MC_GROUPS; //get session count first before malloc memroy cmd_info.count_info.flag = 0; if( ppa_do_ioctl_cmd(PPA_CMD_GET_COUNT_MC_GROUP, &cmd_info ) != PPA_CMD_OK ) return -EIO; if( cmd_info.count_info.count == 0 ) { IFX_PPACMD_PRINT("MC groups count=0\n"); if( g_output_to_file ) SaveDataToFile(g_output_filename, (char *)(&cmd_info.count_info), sizeof(cmd_info.count_info) ); return PPA_CMD_OK; } //malloc memory and set value correctly size = sizeof(PPA_CMD_COUNT_INFO) + sizeof(PPA_CMD_MC_GROUP_INFO) * ( 1 + cmd_info.count_info.count ) ; psession_buffer = (PPA_CMD_MC_GROUPS_INFO *) malloc( size ); if( psession_buffer == NULL ) { IFX_PPACMD_PRINT("Malloc %d bytes failed\n", size ); return PPA_CMD_NOT_AVAIL; } memset( psession_buffer, 0, sizeof(size) ); psession_buffer->count_info.count = cmd_info.count_info.count; psession_buffer->count_info.flag = 0; //get session information if( (res = ppa_do_ioctl_cmd(flag, psession_buffer ) != PPA_CMD_OK ) ) { free( psession_buffer ); return res; } IFX_DBG("MC groups count=%u. \n", (unsigned int)psession_buffer->count_info.count); if( !g_output_to_file ) { for(i=0; icount_info.count; i++ ) { //format like: [002] 239. 2. 2. 3 (route) qid 0 vlan 0000/04x From nas0 to eth0 ADDED_IN_HW|VALID_PPPOE|VALID_NEW_SRC_MAC IFX_PPACMD_PRINT("[%03u] %3u.%3u.%3u.%3u (%s) qid(%2u) dscp(%2u) vlan (%04x/%04x) ", i, NIPQUAD(psession_buffer->mc_group_list[i].mc.mcast_addr), psession_buffer->mc_group_list[i].bridging_flag ? "bridge":"route ", (unsigned int)psession_buffer->mc_group_list[i].mc.mc_extra.dslwan_qid, (unsigned int)psession_buffer->mc_group_list[i].mc.mc_extra.new_dscp, (unsigned int)( psession_buffer->mc_group_list[i].mc.mc_extra.vlan_prio << 13) |( psession_buffer->mc_group_list[i].mc.mc_extra.vlan_cfi << 12) | psession_buffer->mc_group_list[i].mc.mc_extra.vlan_id, (unsigned int)psession_buffer->mc_group_list[i].mc.mc_extra.out_vlan_tag); if( strlen(psession_buffer->mc_group_list[i].src_ifname ) == 0 ) IFX_PPACMD_PRINT("From N/A "); else { IFX_PPACMD_PRINT("From %s ", psession_buffer->mc_group_list[i].src_ifname); } if( psession_buffer->mc_group_list[i].num_ifs ==0 ||psession_buffer->mc_group_list[i].lan_ifname[0] == 0 ) IFX_PPACMD_PRINT("to N/A"); else { IFX_PPACMD_PRINT("to "); for(j=0; jmc_group_list[i].num_ifs; j++) { if( j == 0 ) IFX_PPACMD_PRINT("%s", psession_buffer->mc_group_list[i].lan_ifname[j]); else IFX_PPACMD_PRINT("/%s", psession_buffer->mc_group_list[i].lan_ifname[j]); } } IFX_PPACMD_PRINT("\n\t "); print_session_flags( psession_buffer->mc_group_list[i].mc.flags ); IFX_PPACMD_PRINT("\n"); } } else { SaveDataToFile(g_output_filename, (char *)(psession_buffer), size ); } free( psession_buffer ); return PPA_CMD_OK; } /* ==================================================================================== command: setmcextra description: set multicast extra information, like vlan/dscp options: ==================================================================================== */ static const char ppa_set_mc_extra_short_opts[] = "g:q:i:o:t:h"; //need to further implement add/remove/modify vlan and enable new dscp and its value static const struct option ppa_set_mc_extra_long_opts[] = { {"multicast group", required_argument, NULL, 'g'}, {"dscp", required_argument, NULL, 'q'}, {"inner vlan", required_argument, NULL, 'i'}, {"outer vlan", required_argument, NULL, 'o'}, {"qid", required_argument, NULL, 't'}, { 0,0,0,0 } }; static void ppa_set_mc_extra_help( int summary) { IFX_PPACMD_PRINT("setmcextra -g [-q ] [-i |remove>] [-o |remove] \n"); // [-t ] for future only if( !summary ) { IFX_PPACMD_PRINT(" dscp: 4 bits ( Only for A5/D5)\n"); IFX_PPACMD_PRINT(" vlan_tag: 16 bits: priority(3 bits), cfi(1 bit) and vlan id (10bits) \n"); } return; } static int ppa_parse_set_mc_extra_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int g_opt=0, q_opt=0, inner_vlan_opt=0, out_vlan_opt=0; char *insert_format="insert:"; char *remove_format="remove"; uint32_t vlanid ; memset(pdata, 0, sizeof(*pdata) ); while(popts->opt) { switch(popts->opt) { case 'g': //multicast group inet_aton(popts->optarg, &pdata->mc_entry.mcast_addr); g_opt ++; break; case 'q': //dscp pdata->mc_entry.mc_extra.new_dscp = my_strtoul(popts->optarg); pdata->mc_entry.mc_extra.dscp_remark = 1; pdata->mc_entry.flags |= PPA_F_SESSION_NEW_DSCP; q_opt ++; break; case 'i': //inner vlan if( strncmp( popts->optarg, insert_format, strlen(insert_format) ) == 0 ) { char *p = popts->optarg +strlen(insert_format); vlanid = my_strtoul( p); if( vlanid == 0 ) return PPA_CMD_ERR; pdata->mc_entry.mc_extra.vlan_insert= 1; pdata->mc_entry.mc_extra.vlan_prio = ( vlanid >> 13 ) & 7; pdata->mc_entry.mc_extra.vlan_cfi = ( vlanid >> 12 ) & 1; pdata->mc_entry.mc_extra.vlan_id = vlanid & 0xFFF; } else if( strncmp( popts->optarg, remove_format, strlen(remove_format) ) == 0 ) { pdata->mc_entry.mc_extra.vlan_remove = 1; } inner_vlan_opt ++; pdata->mc_entry.flags |= PPA_F_SESSION_VLAN; break; case 'o': //outer vlan if( strncmp( popts->optarg, insert_format, strlen(insert_format) ) == 0 ) { char *p = popts->optarg +strlen(insert_format); vlanid = my_strtoul( p); if( vlanid == 0 ) return PPA_CMD_ERR; pdata->mc_entry.mc_extra.out_vlan_insert= 1; pdata->mc_entry.mc_extra.out_vlan_tag = vlanid; } else if( strncmp( popts->optarg, remove_format, strlen(remove_format) ) == 0 ) { pdata->mc_entry.mc_extra.out_vlan_remove = 1; } out_vlan_opt ++; pdata->mc_entry.flags |= PPA_F_SESSION_OUT_VLAN; break; case 't': //future only { pdata->mc_entry.mc_extra.dslwan_qid_remark = 1; pdata->mc_entry.mc_extra.dslwan_qid = my_strtoul( popts->optarg); } default: IFX_PPACMD_PRINT("set_mc_extra not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( g_opt != 1 || inner_vlan_opt >1 || out_vlan_opt > 1 ) return PPA_CMD_ERR; IFX_DBG("setmcextra: %d.%d.%d.%d\n", NIPQUAD( pdata->mc_entry.mcast_addr) ); if( pdata->mc_entry.mc_extra.dscp_remark ) IFX_DBG("\tNew dscp: 0x%x\n", pdata->mc_entry.mc_extra.new_dscp ); if( pdata->mc_entry.mc_extra.vlan_insert ) { vlanid = ( pdata->mc_entry.mc_extra.vlan_prio<< 13 ) + (pdata->mc_entry.mc_extra.vlan_cfi << 12) + pdata->mc_entry.mc_extra.vlan_id; IFX_DBG("\tNew inner vlan: %04x\n", (unsigned int)vlanid ); } else if( pdata->mc_entry.mc_extra.vlan_remove) { IFX_DBG("\tRemove inner vlan. \n"); } if( pdata->mc_entry.mc_extra.out_vlan_insert ) { IFX_DBG("\tNew outer vlan: %04x\n", (unsigned int)pdata->mc_entry.mc_extra.out_vlan_tag); } else if( pdata->mc_entry.mc_extra.out_vlan_remove) { IFX_DBG("\tRemove outer vlan. \n"); } if( pdata->mc_entry.mc_extra.dslwan_qid_remark ) IFX_DBG("\tNew dslwan_qid:%0u\n", (unsigned int)pdata->mc_entry.mc_extra.dslwan_qid); return PPA_CMD_OK; } /* ==================================================================================== command: getlansessionum/getwansessionnum description: get LAN/WAN session count options: ==================================================================================== */ static void ppa_get_lan_session_count_help( int summary) { IFX_PPACMD_PRINT("getlansessionnum [-o file ]\n"); return; } static void ppa_get_wan_session_count_help( int summary) { IFX_PPACMD_PRINT("getwansessionnum [-o file ]\n"); return; } static const char ppa_get_simple_short_opts[] = "o:h"; static const struct option ppa_get_simple_long_opts[] = { {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; /*this is a simple template parse command. At most there is only one parameter for saving result to file */ static int ppa_parse_simple_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { while(popts->opt) { switch(popts->opt) { case 'o': g_output_to_file = 1; strncpy(g_output_filename, popts->optarg, PPACMD_MAX_FILENAME); break; default: IFX_PPACMD_PRINT("addmc not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } return PPA_CMD_OK; } static int ppa_parse_get_lan_session_count(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { int res; res = ppa_parse_simple_cmd( popts, pdata ); if( res != PPA_CMD_OK ) return res; pdata->count_info.flag =0; return PPA_CMD_OK; } static int ppa_parse_get_wan_session_count(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { int res = ppa_parse_simple_cmd( popts, pdata ); if( res != PPA_CMD_OK ) return res; pdata->count_info.flag = 0; return PPA_CMD_OK; } /* ==================================================================================== command: getlansessions/getwansessions description: get LAN/WAN all session detail information options: ==================================================================================== */ static void ppa_get_lan_sessions_help( int summary) { IFX_PPACMD_PRINT("getlansessions [-o file ]\n"); // [ -m ] return; } static void ppa_get_wan_sessions_help( int summary) { IFX_PPACMD_PRINT("getwansessions [-o file ]\n"); // [ -m ] return; } static int ppa_get_sessions (PPA_COMMAND *pcmd, uint32_t flag) { PPA_CMD_SESSIONS_INFO *psession_buffer; PPA_CMD_DATA cmd_info; int res = PPA_CMD_OK, i, size; //get session count first before malloc memroy cmd_info.count_info.flag = 0; if( ppa_do_ioctl_cmd(PPA_CMD_GET_COUNT_LAN_SESSION, &cmd_info ) != PPA_CMD_OK ) return -EIO; if( cmd_info.count_info.count == 0 ) { IFX_DBG("session count=0. \n"); if( g_output_to_file ) SaveDataToFile(g_output_filename, (char *)(&cmd_info.count_info), sizeof(cmd_info.count_info) ); return PPA_CMD_OK; } //malloc memory and set value correctly size = sizeof(PPA_CMD_COUNT_INFO) + sizeof(PPA_CMD_SESSION_ENTRY) * ( 1 + cmd_info.count_info.count ) ; psession_buffer = (PPA_CMD_SESSIONS_INFO *) malloc( size ); if( psession_buffer == NULL ) return PPA_CMD_NOT_AVAIL; memset( psession_buffer, 0, sizeof(size) ); psession_buffer->count_info.count = cmd_info.count_info.count; psession_buffer->count_info.flag = flag; //get session information if( (res = ppa_do_ioctl_cmd(flag, psession_buffer ) != PPA_CMD_OK ) ) { free( psession_buffer ); return res; } if( !g_output_to_file ) { if( flag == PPA_CMD_GET_LAN_SESSIONS ) IFX_PPACMD_PRINT("\nLAN Session Information: %u -------\n", (unsigned int)psession_buffer->count_info.count ); else if( flag == PPA_CMD_GET_WAN_SESSIONS ) IFX_PPACMD_PRINT("\nWAN Session Information: %u -------\n", (unsigned int)psession_buffer->count_info.count ); else { IFX_PPACMD_PRINT("Wrong flag: 0x%x\n", (unsigned int)flag ); free(psession_buffer); return -EIO; } for(i=0; icount_info.count; i++ ) { //print format: (source ip : port) -> ( dst_ip : dst_port ) nat ( nat_ip: nat_port ) IFX_PPACMD_PRINT("[%03d]", i); if( psession_buffer->session_list[i].ip_proto == 0x11 ) //UDP IFX_PPACMD_PRINT("udp"); else if( psession_buffer->session_list[i].ip_proto == 6) IFX_PPACMD_PRINT("tcp"); else IFX_PPACMD_PRINT("---"); IFX_PPACMD_PRINT(": %8s (%3d.%3d.%3d.%3d:%5d) -> %8s (%3d.%3d.%3d.%3d:%5d) NAT (%3d.%3d.%3d.%3d:%5d)\n", psession_buffer->session_list[i].rx_if_name, NIPQUAD(psession_buffer->session_list[i].src_ip), psession_buffer->session_list[i].src_port, psession_buffer->session_list[i].tx_if_name, NIPQUAD(psession_buffer->session_list[i].dst_ip), psession_buffer->session_list[i].dst_port, NIPQUAD(psession_buffer->session_list[i].nat_ip), psession_buffer->session_list[i].nat_port ); } } else { SaveDataToFile(g_output_filename, (char *)(psession_buffer), size ); } free( psession_buffer ); return PPA_CMD_OK; } static int ppa_get_lan_sessions_cmd (PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { return ppa_get_sessions(pcmd, PPA_CMD_GET_LAN_SESSIONS); } static int ppa_get_wan_sessions_cmd (PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { return ppa_get_sessions(pcmd, PPA_CMD_GET_WAN_SESSIONS); } /* ==================================================================================== command: delvfilter description: delete one vlan filter options: ==================================================================================== */ /*delete all vfilter */ static void ppa_del_all_vfilter_help( int summary) { IFX_PPACMD_PRINT("delallvfilter\n"); // [ -m ] IFX_PPACMD_PRINT("\t\tThis command is for A4/D4 only at present\n"); return; } /* ==================================================================================== command: getversion description: get ppa/ppe driver/ppe fw version options: ==================================================================================== */ static void ppa_get_version_help( int summary) { IFX_PPACMD_PRINT("getversion [-o file ]\n"); // [ -m ] return; } PPA_VERSION ppa_api_ver; PPA_VERSION ppa_stack_al_ver; PPA_VERSION ppe_hal_ver; PPA_VERSION ppe_fw_ver; static void ppa_print_get_version_cmd(PPA_CMD_DATA *pdata) { char *dr_ver_family_str[] = { "Reserved", "Danube", "Twinpass", "Amazon-SE", "Reserved", "AR9", "GR9" }; if( !g_output_to_file ) { IFX_PPACMD_PRINT("PPA SubSystem version info:v%u.%u.%u\n", (unsigned int)pdata->ver.ppa_subsys_ver.major, (unsigned int)pdata->ver.ppa_subsys_ver.mid, (unsigned int)pdata->ver.ppa_subsys_ver.minor ); IFX_PPACMD_PRINT("\tPPA ppacmd utility tool info:%u.%u.%u\n", PPACMD_VERION_MAJOR, PPACMD_VERION_MID, PPACMD_VERION_MINOR); IFX_PPACMD_PRINT("\tPPA API driver info:%u.%u.%u.%u.%u.%u.%u\n", (unsigned int)pdata->ver.ppa_api_ver.family, (unsigned int)pdata->ver.ppa_api_ver.type, (unsigned int)pdata->ver.ppa_api_ver.itf, (unsigned int)pdata->ver.ppa_api_ver.mode, (unsigned int)pdata->ver.ppa_api_ver.major, (unsigned int)pdata->ver.ppa_api_ver.mid, (unsigned int)pdata->ver.ppa_api_ver.minor); IFX_PPACMD_PRINT("\tPPA Stack Adaption Layer driver info:%u.%u.%u.%u.%u.%u.%u\n", (unsigned int)pdata->ver.ppa_stack_al_ver.family, (unsigned int)pdata->ver.ppa_stack_al_ver.type, (unsigned int)pdata->ver.ppa_stack_al_ver.itf, (unsigned int)pdata->ver.ppa_stack_al_ver.mode, (unsigned int)pdata->ver.ppa_stack_al_ver.major, (unsigned int)pdata->ver.ppa_stack_al_ver.mid, (unsigned int)pdata->ver.ppa_stack_al_ver.minor); IFX_PPACMD_PRINT("\tPPE HAL driver info:%u.%u.%u.%u.%u.%u.%u\n", (unsigned int)pdata->ver.ppe_hal_ver.family, (unsigned int)pdata->ver.ppe_hal_ver.type, (unsigned int)pdata->ver.ppe_hal_ver.itf, (unsigned int)pdata->ver.ppe_hal_ver.mode, (unsigned int)pdata->ver.ppe_hal_ver.major, (unsigned int)pdata->ver.ppe_hal_ver.mid, (unsigned int)pdata->ver.ppe_hal_ver.minor); IFX_PPACMD_PRINT("\tPPE FW info:%u.%u.%u.%u.%u.%u.%u", (unsigned int)pdata->ver.ppe_fw_ver.family, (unsigned int)pdata->ver.ppe_fw_ver.type, (unsigned int)pdata->ver.ppe_fw_ver.itf, (unsigned int)pdata->ver.ppe_fw_ver.mode, (unsigned int)pdata->ver.ppe_fw_ver.major, (unsigned int)pdata->ver.ppe_fw_ver.mid, (unsigned int)pdata->ver.ppe_fw_ver.minor); if( pdata->ver.ppe_fw_ver.family < NUM_ENTITY(dr_ver_family_str) ) IFX_PPACMD_PRINT("( for %s )", dr_ver_family_str[pdata->ver.ppe_fw_ver.family] ); IFX_PPACMD_PRINT("\n"); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->ver), sizeof(pdata->ver) ); } } /*get bridge mac count */ static void ppa_get_br_count_help( int summary) { IFX_PPACMD_PRINT("getbrnum [-o file ]\n"); return; } static int ppa_parse_get_br_count(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { int res = ppa_parse_simple_cmd( popts, pdata ); if( res != PPA_CMD_OK ) return res; pdata->count_info.flag = 0; return PPA_CMD_OK; } static void ppa_print_get_count_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("The count is %u\n", (unsigned int)pdata->count_info.count ); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->count_info), sizeof(pdata->count_info) ); } } /*get all bridge mac information */ static void ppa_get_all_br_help( int summary) { IFX_PPACMD_PRINT("getbrs [-o file ]\n"); // [ -m ] return; } static int ppa_get_all_br_cmd (PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_ALL_MAC_INFO *psession_buffer; PPA_CMD_DATA cmd_info; int res = PPA_CMD_OK, i, size; uint32_t flag = PPA_CMD_GET_ALL_MAC; //get session count first before malloc memroy cmd_info.count_info.flag = 0; if( ppa_do_ioctl_cmd(PPA_CMD_GET_COUNT_MAC, &cmd_info ) != PPA_CMD_OK ) return -EIO; if( cmd_info.count_info.count == 0 ) { IFX_DBG("bridge mac count=0\n"); if( g_output_to_file ) SaveDataToFile(g_output_filename, (char *)(&cmd_info.count_info), sizeof(cmd_info.count_info) ); return PPA_CMD_OK; } //malloc memory and set value correctly size = sizeof(PPA_CMD_COUNT_INFO) + sizeof(PPA_CMD_MAC_ENTRY) * ( 1 + cmd_info.count_info.count ) ; psession_buffer = (PPA_CMD_ALL_MAC_INFO *) malloc( size ); if( psession_buffer == NULL ) { IFX_PPACMD_PRINT("Malloc %d bytes failed\n", size ); return PPA_CMD_NOT_AVAIL; } memset( psession_buffer, 0, sizeof(size) ); psession_buffer->count_info.count = cmd_info.count_info.count; psession_buffer->count_info.flag = 0; //get session information if( (res = ppa_do_ioctl_cmd(flag, psession_buffer ) != PPA_CMD_OK ) ) { free( psession_buffer ); return res; } IFX_DBG("bridge mac count=%u. \n", (unsigned int)psession_buffer->count_info.count); if( !g_output_to_file ) { for(i=0; icount_info.count; i++ ) { //format like: [002] 239. 2. 2. 3 (route) qid 0 vlan 0000/04x From nas0 to eth0 ADDED_IN_HW|VALID_PPPOE|VALID_NEW_SRC_MAC IFX_PPACMD_PRINT("[%03d] %02x:%02x:%02x:%02x:%02x:%02x %s\n", i, psession_buffer->session_list[i].mac_addr[0], psession_buffer->session_list[i].mac_addr[1], psession_buffer->session_list[i].mac_addr[2], psession_buffer->session_list[i].mac_addr[3], psession_buffer->session_list[i].mac_addr[4], psession_buffer->session_list[i].mac_addr[5], psession_buffer->session_list[i].ifname ); } } else { SaveDataToFile(g_output_filename, (char *)(psession_buffer), size ); } free( psession_buffer ); return PPA_CMD_OK; } /*GET ALL WAN MII0 VLAND Rage */ static void ppa_get_wan_mii0_vlan_range_count_help(int summary) { IFX_PPACMD_PRINT("getvlanrangenum [-o file ]\n"); return; } /*Add WAN MII0 VLAN RANGE */ static void ppa_add_wan_mii0_vlan_range_help( int summary) { IFX_PPACMD_PRINT("addvlanrange -s -e \n"); return; } static int ppa_parse_add_wan_mii0_vlan_range_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int s_opt=0, e_opt=0; memset(pdata, 0, sizeof(*pdata) ); while(popts->opt) { switch(popts->opt) { case 's': //multicast group pdata->wan_vlanid_range.start_vlan_range = my_strtoul(popts->optarg); s_opt ++; break; case 'e': //dscp pdata->wan_vlanid_range.end_vlan_range = my_strtoul(popts->optarg); e_opt ++; break; default: IFX_PPACMD_PRINT("ppa_parse_add_wan_mii0_vlan_range_cmd not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( s_opt != 1 || e_opt != 1 ) return PPA_CMD_ERR; IFX_DBG("ppa_parse_add_wan_mii0_vlan_range_cmd: from 0x%x to 0x%x\n", (unsigned int)pdata->wan_vlanid_range.start_vlan_range, (unsigned int)pdata->wan_vlanid_range.end_vlan_range ); return PPA_CMD_OK; } static const char ppa_add_wan_mii0_vlan_range_short_opts[] = "s:e:h"; //need to further implement add/remove/modify vlan and enable new dscp and its value static const struct option ppa_add_wan_mii0_vlan_range_long_opts[] = { {"start", required_argument, NULL, 's'}, {"end", required_argument, NULL, 'd'}, { 0,0,0,0 } }; static void ppa_get_wan_mii0_all_vlan_range_help(int summary) { IFX_PPACMD_PRINT("getvlanranges [-o file ]\n"); return; } static int ppa_wan_mii0_all_vlan_range_cmd (PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_VLAN_RANGES *psession_buffer; PPA_CMD_DATA cmd_info; int res = PPA_CMD_OK, i, size; uint32_t flag = PPA_CMD_WAN_MII0_VLAN_RANGE_GET; //get session count first before malloc memroy cmd_info.count_info.flag = 0; if( ppa_do_ioctl_cmd(PPA_CMD_GET_COUNT_WAN_MII0_VLAN_RANGE, &cmd_info ) != PPA_CMD_OK ) return -EIO; if( cmd_info.count_info.count == 0 ) { IFX_DBG("wan mii vlan range count=%d\n", (unsigned int)cmd_info.count_info.count); if( g_output_to_file ) SaveDataToFile(g_output_filename, (char *)(&cmd_info.count_info), sizeof(cmd_info.count_info) ); return PPA_CMD_OK; } //malloc memory and set value correctly size = sizeof(PPA_CMD_COUNT_INFO) + sizeof(PPA_VLAN_RANGE) * ( 1 + cmd_info.count_info.count ) ; psession_buffer = (PPA_CMD_VLAN_RANGES *) malloc( size ); if( psession_buffer == NULL ) { IFX_PPACMD_PRINT("Malloc %d bytes failed\n", size ); return PPA_CMD_NOT_AVAIL; } memset( psession_buffer, 0, sizeof(size) ); psession_buffer->count_info.count = cmd_info.count_info.count; psession_buffer->count_info.flag = 0; //get session information if( (res = ppa_do_ioctl_cmd(flag, psession_buffer ) != PPA_CMD_OK ) ) { free( psession_buffer ); return res; } IFX_DBG("wanmii0 vlan range count=%d. \n", (unsigned int)psession_buffer->count_info.count); if( !g_output_to_file ) { for(i=0; icount_info.count; i++ ) { IFX_PPACMD_PRINT("[%02d] from %03x to %03x\n", i, (unsigned int)psession_buffer->ranges[i].start_vlan_range, (unsigned int)psession_buffer->ranges[i].end_vlan_range ); } } else { SaveDataToFile(g_output_filename, (char *)(psession_buffer), size ); } free( psession_buffer ); return PPA_CMD_OK; } static void ppa_get_sizeof_help(int summary) { IFX_PPACMD_PRINT("\n"); //purposely don't display this command since it is not for customer return; } static void ppa_print_get_sizeof_cmd( PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("one unicast session size =%d \n", (unsigned int)pdata->size_info.rout_session_size); IFX_PPACMD_PRINT("one multicast session size =%d\n", (unsigned int)pdata->size_info.mc_session_size ); IFX_PPACMD_PRINT("one bridge session size =%d \n", (unsigned int)pdata->size_info.br_session_size ); IFX_PPACMD_PRINT("netif size =%d\n", (unsigned int)pdata->size_info.netif_size ); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->size_info), sizeof(pdata->size_info) ); } return; } /*ppacmd setbr: set bridge mac address learning hook enable/disable---begin*/ static void ppa_set_br_help( int summary) { IFX_PPACMD_PRINT("ppa setbr [-f 0/1]\n"); return; } static const char ppa_set_br_short_opts[] = "f:h"; static const struct option ppa_set_br_long_opts[] ={ {"flag", required_argument, NULL, 'f'}, { 0,0,0,0 } }; static int ppa_set_br_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { memset( pdata, 0, sizeof(PPA_CMD_BRIDGE_ENABLE_INFO) ); while(popts->opt) { switch(popts->opt) { case 'f': pdata->br_enable_info.bridge_enable= my_strtoul(popts->optarg);; break; default: IFX_PPACMD_PRINT("ppa_set_br_cmd not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } return PPA_CMD_OK; } /*ppacmd setbr: set bridge mac address learning hook enable/disable ---end*/ /*ppacmd getbrstatus: get bridge mac address learning hook status: enabled/disabled---begin*/ static void ppa_get_br_status_help( int summary) { IFX_PPACMD_PRINT("getbrstatus [-o outfile]\n"); return; } static const char ppa_get_br_status_short_opts[] = "o:h"; static const struct option ppa_get_br_status_long_opts[] ={ {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static int ppa_get_br_status_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { memset( pdata, 0, sizeof(PPA_CMD_BRIDGE_ENABLE_INFO) ); while(popts->opt) { switch(popts->opt) { case 'o': g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); break; default: IFX_PPACMD_PRINT("ppa_get_br_status_cmd not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } return PPA_CMD_OK; } static void ppa_print_get_br_status_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("The bridge mac learning hook is %s\n", pdata->br_enable_info.bridge_enable ? "enabled":"disabled"); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->br_enable_info), sizeof(pdata->br_enable_info) ); } } int get_portid(char *ifname) { PPA_CMD_PORTID_INFO portid; memset( &portid, 0, sizeof(portid)); strncpy( portid.ifname, ifname, sizeof(portid.ifname)); if( ppa_do_ioctl_cmd(PPA_CMD_GET_PORTID, &portid ) != PPA_CMD_OK ) { IFX_PPACMD_PRINT("ppacmd get portid failed\n"); return -1; } return portid.portid; } /*ppacmd ppa_get_br_status_cmd: ---end*/ #ifdef CONFIG_IFX_PPA_QOS /*ppacmd getqnum: get eth1 queue number ---begin*/ static void ppa_get_qnum_help( int summary) { IFX_PPACMD_PRINT("getqnum [-p portid] [-i ifname] [-o outfile]\n"); if (!summary ) IFX_PPACMD_PRINT("note: one or only one of portid or ifname must be specified\n"); return; } static const char ppa_get_qnum_short_opts[] = "p:o:i:h"; static const struct option ppa_get_qnum_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"interface", required_argument, NULL, 'i'}, {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static int ppa_parse_get_qnum_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA* pdata) { int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_QUEUE_NUM_INFO) ); while(popts->opt) { switch(popts->opt) { case 'p': pdata->qnum_info.portid = my_strtoul(popts->optarg);\ p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qnum_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'o': g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); break; default: return PPA_CMD_ERR; } popts++; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_get_qnum_cmd: portid=%d, queue_num=%d\n", (unsigned int)pdata->qnum_info.portid, (unsigned int)pdata->qnum_info.queue_num); return PPA_CMD_OK; } static void ppa_print_get_qnum_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("The queue number( of port id %d ) is %d\n", (unsigned int)pdata->qnum_info.portid, (unsigned int)pdata->qnum_info.queue_num); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->qnum_info), sizeof(pdata->qnum_info) ); } } /*ppacmd getqnum: get eth1 queue number ---end*/ /*ppacmd getmib: get qos mib counter ---begin*/ static void ppa_get_qmib_help( int summary) { IFX_PPACMD_PRINT("getqmib [-p portid] [-i ifname] <-q queuid> [-o outfile]\n"); if( !summary ) { IFX_PPACMD_PRINT("note: one or only one of portid or ifname must be specified\n"); IFX_PPACMD_PRINT(" if queueid is not provided, then it will get all queue's mib coutners\n"); } return; } static const char ppa_get_qmib_short_opts[] = "p:i:q:o:h"; static const struct option ppa_get_qmib_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"queueid", required_argument, NULL, 'q'}, {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static int ppa_parse_get_qmib_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA* pdata) { int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_QOS_MIB_INFO) ); pdata->qos_mib_info.queueid = -1; while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_mib_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_mib_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'q': pdata->qos_mib_info.queueid= my_strtoul(popts->optarg); break; case 'o': g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); break; default: return PPA_CMD_ERR; } popts++; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_get_qmib_cmd: portid=%d, queueid=%d\n", (unsigned int)pdata->qos_mib_info.portid, (unsigned int)pdata->qos_mib_info.queueid); return PPA_CMD_OK; } static int ppa_get_qmib_do_cmd(PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_QUEUE_NUM_INFO qnum_info; PPA_CMD_QOS_MIB_INFO mib_info; int i, j, start_i, end_i=0; int res; memset( &qnum_info, 0, sizeof(qnum_info) ); qnum_info.portid = pdata->qos_mib_info.portid; if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_QOS_QUEUE_MAX_NUM, &qnum_info ) != PPA_CMD_OK ) ) { IFX_PPACMD_PRINT("ioctl PPA_CMD_GET_QOS_QUEUE_MAX_NUM fail\n"); return IFX_FAILURE; } if( pdata->qos_mib_info.queueid != -1 ) // set queueid already, then use it { start_i = pdata->qos_mib_info.queueid; if( start_i >= qnum_info.queue_num -1 ) start_i = qnum_info.queue_num -1; end_i = start_i + 1; IFX_PPACMD_PRINT("Need to read queue %d's mib counter\n", start_i); } else { start_i = 0; end_i = qnum_info.queue_num; IFX_PPACMD_PRINT("Need to read mib counter from queue %d to %d\n", start_i, end_i-1 ); } for(i=start_i; iqos_mib_info.portid; mib_info.queueid = i; if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_QOS_MIB, &mib_info) == PPA_CMD_OK ) ) { if( !g_output_to_file ) { if( i== start_i ) IFX_PPACMD_PRINT("MIB rx_pkt/rx_bytes tx_pkt/tx_bytes cpu_small_drop/cpu_drop fast_small_drop/fast_drop_cnt\n"); IFX_PPACMD_PRINT(" %2d: 0x%08x/0x%08x 0x%08x/0x%08x 0x%08x/0x%08x 0x%08x/0x%08x\n", i, (unsigned int)mib_info.mib.total_rx_pkt, (unsigned int)mib_info.mib.total_rx_bytes, (unsigned int)mib_info.mib.total_tx_pkt, (unsigned int)mib_info.mib.total_tx_bytes, (unsigned int)mib_info.mib.cpu_path_small_pkt_drop_cnt, (unsigned int)mib_info.mib.cpu_path_total_pkt_drop_cnt, (unsigned int)mib_info.mib.fast_path_small_pkt_drop_cnt, (unsigned int)mib_info.mib.fast_path_total_pkt_drop_cnt ); } else { /*note, currently only last valid flow info is saved to file and all other flow informations are all overwritten */ SaveDataToFile(g_output_filename, (char *)(&mib_info), sizeof(mib_info) ); } j++; } } return IFX_SUCCESS; } /*ppacmd getqmib: get eth1 queue number ---end*/ #ifdef CONFIG_IFX_PPA_QOS_WFQ /*ppacmd setctrlwfq ---begin*/ static void ppa_set_ctrl_wfq_help( int summary) { IFX_PPACMD_PRINT("setctrlwfq [-p portid] [-i ifname] <-c enable | disable> [-m manual_wfq]\n"); if( !summary ) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); IFX_PPACMD_PRINT("note: manual_wfq 0 -- default weight\n"); IFX_PPACMD_PRINT("note: manual_wfq 1 -- use user specified weight directly\n"); IFX_PPACMD_PRINT("note: manual_wfq other_value-- use user specified mapping \n"); } return; } static const char ppa_set_ctrl_wfq_short_opts[] = "p:c:i:m:h"; static const struct option ppa_set_ctrl_wfq_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"control", required_argument, NULL, 'c'}, {"manual", required_argument, NULL, 'm'}, { 0,0,0,0 } }; static int ppa_parse_set_ctrl_wfq_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int c_opt=0; int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_QOS_CTRL_INFO) ); while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_ctrl_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_ctrl_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'c': if( strcmp("enable" , popts->optarg) == 0 ) pdata->qos_ctrl_info.enable = 1; else pdata->qos_ctrl_info.enable = 0; c_opt = 1; break; case 'm': pdata->qos_ctrl_info.flags= my_strtoul(popts->optarg); //use manual set WFQ weight break; default: return PPA_CMD_ERR; } popts++; } if( c_opt == 0 ) { IFX_PPACMD_PRINT("Need enter control option\n"); return PPA_CMD_ERR; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_set_ctrl_wfq_cmd: portid=%d, ctrl=%s\n", (unsigned int)pdata->qos_ctrl_info.portid, pdata->qos_ctrl_info.enable ? "enabled":"disable"); return PPA_CMD_OK; } /*ppacmd setctrlwfq ---end*/ /*ppacmd getctrlwfq ---begin*/ static void ppa_get_ctrl_wfq_help( int summary) { IFX_PPACMD_PRINT("getctrlwfq [-p portid] [-i ifname] [-o outfile]\n"); if( !summary ) IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return; } static const char ppa_get_ctrl_wfq_short_opts[] = "p:i:o:h"; static const struct option ppa_get_ctrl_wfq_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static int ppa_parse_get_ctrl_wfq_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_QOS_CTRL_INFO) ); while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_ctrl_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_ctrl_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'o': g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); break; default: return PPA_CMD_ERR; } popts++; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_get_ctrl_wfq_cmd: portid=%d, ctrl=%s\n", (unsigned int)pdata->qos_ctrl_info.portid, pdata->qos_ctrl_info.enable? "enabled":"disabled"); return PPA_CMD_OK; } static void ppa_print_get_ctrl_wfq_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("The wfq of port id %d is %s\n", (unsigned int)pdata->qos_ctrl_info.portid, pdata->qos_ctrl_info.enable ? "enabled":"disabled"); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->qos_ctrl_info), sizeof(pdata->qos_ctrl_info) ); } } /*ppacmd getctrlwfq ---end*/ /*ppacmd setwfq ---begin*/ static void ppa_set_wfq_help( int summary) { IFX_PPACMD_PRINT("setwfq [-p portid] [-i ifname] <-q queuid> <-w weight-level < its value from 0~ 100 in hex value) ]\n"); if( !summary ) IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return; } static const char ppa_set_wfq_short_opts[] = "p:q:w:i:h"; static const struct option ppa_set_wfq_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"queuid", required_argument, NULL, 'q'}, {"weight-level", required_argument, NULL, 'w'}, { 0,0,0,0 } }; static int ppa_parse_set_wfq_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA*pdata) { unsigned int w_opt=0, q_opt=0; int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_WFQ_INFO) ); while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_wfq_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_wfq_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'q': pdata->qos_wfq_info.queueid = my_strtoul(popts->optarg); q_opt = 1; break; case 'w': pdata->qos_wfq_info.weight = my_strtoul(popts->optarg); w_opt = 1; break; default: IFX_PPACMD_PRINT("ppa_parse_set_wfq_cmd not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( q_opt == 0 ) { IFX_PPACMD_PRINT("Need enter queueid\n"); return PPA_CMD_ERR; } if( w_opt == 0 ) { IFX_PPACMD_PRINT("Need enter weight\n"); return PPA_CMD_ERR; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_set_wfq_cmd: portid=%d, queueid=%d, weight=%d\n", (unsigned int)pdata->qos_wfq_info.portid, (unsigned int)pdata->qos_wfq_info.queueid, (unsigned int)pdata->qos_wfq_info.weight); return PPA_CMD_OK; } /*ppacmd setwfq ---end*/ /*ppacmd resetwfq ---begin*/ static void ppa_reset_wfq_help( int summary) { IFX_PPACMD_PRINT("resetwfq [-p portid] [-i ifname] <-q queuid>\n"); if( !summary ) IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return; } static const char ppa_reset_wfq_short_opts[] = "p:q:i:h"; static const struct option ppa_reset_wfq_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"queuid", required_argument, NULL, 'q'}, { 0,0,0,0 } }; static int ppa_parse_reset_wfq_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int q_opt=0; int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_WFQ_INFO) ); while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_wfq_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_wfq_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'q': pdata->qos_wfq_info.queueid = my_strtoul(popts->optarg); q_opt = 1; break; default: IFX_PPACMD_PRINT("ppa_parse_reset_wfq_cmd not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( q_opt == 0 ) { IFX_PPACMD_PRINT("Need enter queueid\n"); return PPA_CMD_ERR; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_reset_wfq_cmd: portid=%d, queueid=%d\n", (unsigned int)pdata->qos_wfq_info.portid, (unsigned int)pdata->qos_wfq_info.queueid); return PPA_CMD_OK; } /*ppacmd resetwfq ---end*/ /*ppacmd getwfq ---begin*/ static void ppa_get_wfq_help( int summary) { IFX_PPACMD_PRINT("getwfq [-p portid] [-i ifname] <-q queuid> [-o outfile]\n"); if( !summary ) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); IFX_PPACMD_PRINT(" if queueid is not provided, then it will get all queue's wfq\n"); } return; } static const char ppa_get_wfq_short_opts[] = "p:q:o:i:h"; static const struct option ppa_get_wfq_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"queuid", required_argument, NULL, 'q'}, {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static int ppa_parse_get_wfq_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int q_opt=0; int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_WFQ_INFO) ); pdata->qos_wfq_info.queueid = -1; while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_wfq_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_wfq_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'q': pdata->qos_wfq_info.queueid = my_strtoul(popts->optarg); q_opt = 1; break; case 'o': g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); break; default: return PPA_CMD_ERR; } popts++; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_get_wfq_cmd: portid=%d, queueid=%d\n", (unsigned int)pdata->qos_wfq_info.portid, (unsigned int)pdata->qos_wfq_info.queueid); return PPA_CMD_OK; } static int ppa_get_wfq_do_cmd(PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_QUEUE_NUM_INFO qnum_info; PPA_CMD_WFQ_INFO info; int i, start_i, end_i=0; int res; memset( &qnum_info, 0, sizeof(qnum_info) ); qnum_info.portid = pdata->qos_wfq_info.portid; if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_QOS_QUEUE_MAX_NUM, &qnum_info ) != PPA_CMD_OK ) ) { IFX_PPACMD_PRINT("ioctl PPA_CMD_GET_QOS_QUEUE_MAX_NUM fail\n"); return IFX_FAILURE; } if( pdata->qos_wfq_info.queueid != -1 ) // set queuid already, then use it { start_i = pdata->qos_wfq_info.queueid; if( start_i >= qnum_info.queue_num -1 ) start_i = qnum_info.queue_num -1; end_i = start_i + 1; IFX_DBG("Need to read wfq from queue %d \n", start_i); } else { start_i = 0; end_i = qnum_info.queue_num; IFX_DBG("Need to read wfq from queue %d to %d\n", start_i, end_i-1 ); } for(i=start_i; iqos_wfq_info.portid; info.queueid = i; if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_QOS_WFQ, &info) == PPA_CMD_OK ) ) { if( !g_output_to_file ) { IFX_PPACMD_PRINT(" queue %2d wfq rate: %d\n", i, (unsigned int)info.weight ); } else { /*note, currently only last valid flow info is saved to file and all other flow informations are all overwritten */ SaveDataToFile(g_output_filename, (char *)(&info), sizeof(info) ); } } } return IFX_SUCCESS; } /*ppacmd getwfq ---end*/ #endif //enod of CONFIG_IFX_PPA_QOS_WFQ #ifdef CONFIG_IFX_PPA_QOS_RATE_SHAPING /*ppacmd setctrlrate ---begin*/ static void ppa_set_ctrl_rate_help( int summary) { IFX_PPACMD_PRINT("setctrlrate [-p portid] [-i ifname] <-c enable | disable>\n"); if( !summary ) IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return; } static const char ppa_set_ctrl_rate_short_opts[] = "p:c:i:h"; static const struct option ppa_set_ctrl_rate_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"control", required_argument, NULL, 'c'}, { 0,0,0,0 } }; static int ppa_parse_set_ctrl_rate_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int c_opt=0; int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_QOS_CTRL_INFO) ); while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_ctrl_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_ctrl_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'c': if( strcmp("enable" , popts->optarg) == 0 ) pdata->qos_ctrl_info.enable = 1; else pdata->qos_ctrl_info.enable = 0; c_opt = 1; break; default: return PPA_CMD_ERR; } popts++; } if( c_opt == 0 ) { IFX_PPACMD_PRINT("Need enter control option\n"); return PPA_CMD_ERR; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_set_ctrl_rate_cmd: portid=%d, ctrl=%s\n", (unsigned int)pdata->qos_ctrl_info.portid, pdata->qos_ctrl_info.enable ? "enabled":"disable"); return PPA_CMD_OK; } /*ppacmd setctrlrate ---end*/ /*ppacmd getctrlrate ---begin*/ static void ppa_get_ctrl_rate_help( int summary) { IFX_PPACMD_PRINT("getctrlrate [-p portid] [-i ifname] [-o outfile]\n"); if( !summary ) IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return; } static const char ppa_get_ctrl_rate_short_opts[] = "p:i:h"; static const struct option ppa_get_ctrl_rate_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static int ppa_parse_get_ctrl_rate_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_QOS_CTRL_INFO) ); while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_ctrl_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_ctrl_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'o': g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); break; default: return PPA_CMD_ERR; } popts++; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_get_ctrl_rate_cmd: portid=%d\n", (unsigned int)pdata->qos_ctrl_info.portid); return PPA_CMD_OK; } static void ppa_print_get_ctrl_rate_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("The rate of port id %d is %s\n", (unsigned int)pdata->qos_ctrl_info.portid, pdata->qos_ctrl_info.enable ? "enabled":"disabled"); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->qos_ctrl_info), sizeof(pdata->qos_ctrl_info) ); } } /*ppacmd getctrlrate ---end*/ /*ppacmd setrate ---begin*/ static void ppa_set_rate_help( int summary) { IFX_PPACMD_PRINT("setrate [-p portid] [-i ifname] <-q queuid> <-r rate> <-b burst>\n"); if( !summary ) IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return; } static const char ppa_set_rate_short_opts[] = "p:i:q:r:b:h"; static const struct option ppa_set_rate_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"queuid", required_argument, NULL, 'q'}, {"rate", required_argument, NULL, 'r'}, {"burst", required_argument, NULL, 'b'}, { 0,0,0,0 } }; static int ppa_set_rate_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA*pdata) { unsigned int r_opt=0, q_opt=0; int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_RATE_INFO) ); q_opt = 1; //by default if no queue id is specified, it will be regarded as port based rate shaping. pdata->qos_rate_info.queueid = -1; while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_rate_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_rate_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'q': pdata->qos_rate_info.queueid = my_strtoul(popts->optarg); q_opt = 1; break; case 'r': pdata->qos_rate_info.rate = my_strtoul(popts->optarg); r_opt = 1; break; case 'b': pdata->qos_rate_info.burst = my_strtoul(popts->optarg); r_opt = 1; break; default: return PPA_CMD_ERR; } popts++; } if( q_opt == 0 ) { IFX_PPACMD_PRINT("Need enter queueid\n"); return PPA_CMD_ERR; } if( r_opt == 0 ) { IFX_PPACMD_PRINT("Need enter rate\n"); return PPA_CMD_ERR; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_set_rate_cmd: portid=%d, queueid=%d, rate=%d burst=%d\n", (unsigned int)pdata->qos_rate_info.portid, (unsigned int)pdata->qos_rate_info.queueid, (unsigned int)pdata->qos_rate_info.rate, (unsigned int)pdata->qos_rate_info.burst); return PPA_CMD_OK; } /*ppacmd setrate ---end*/ /*ppacmd resetrate ---begin*/ static void ppa_reset_rate_help( int summary) { IFX_PPACMD_PRINT("resetrate [-p portid] [-i ifname] <-q queuid>\n"); if( !summary ) IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return; } static const char ppa_reset_rate_short_opts[] = "p:q:i:h"; static const struct option ppa_reset_rate_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"queuid", required_argument, NULL, 'q'}, { 0,0,0,0 } }; static int ppa_parse_reset_rate_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int q_opt=0; int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_RATE_INFO) ); pdata->qos_rate_info.burst = -1; while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_rate_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_rate_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'q': pdata->qos_rate_info.queueid = my_strtoul(popts->optarg); q_opt = 1; break; default: IFX_PPACMD_PRINT("ppa_parse_reset_rate_cmd not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( q_opt == 0 ) { IFX_PPACMD_PRINT("Need enter queueid\n"); return PPA_CMD_ERR; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_reset_rate_cmd: portid=%d, queueid=%d\n", (unsigned int)pdata->qos_rate_info.portid, (unsigned int)pdata->qos_rate_info.queueid); return PPA_CMD_OK; } /*ppacmd resetrate ---end*/ /*ppacmd getrate ---begin*/ static void ppa_get_rate_help( int summary) { IFX_PPACMD_PRINT("getrate [-p portid] [-i ifname] <-q queuid> [-o outfile]\n"); if( !summary ) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); IFX_PPACMD_PRINT(" if queueid is not provided, then get all queue's rate information\n"); } return; } static const char ppa_get_rate_short_opts[] = "p:q:o:i:h"; static const struct option ppa_get_rate_long_opts[] ={ {"portid", required_argument, NULL, 'p'}, {"ifname", required_argument, NULL, 'i'}, {"queuid", required_argument, NULL, 'q'}, {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static int ppa_parse_get_rate_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int q_opt=0; int p_opt=0, i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_RATE_INFO) ); pdata->qos_rate_info.queueid = -1; while(popts->opt) { switch(popts->opt) { case 'p': pdata->qos_rate_info.portid = my_strtoul(popts->optarg); p_opt ++; break; case 'i': if( get_portid(popts->optarg) >= 0 ) { pdata->qos_rate_info.portid = get_portid(popts->optarg); i_opt ++; } else { IFX_PPACMD_PRINT("The portid of %s is not exist.\n", popts->optarg); return PPA_CMD_ERR; } break; case 'q': pdata->qos_rate_info.queueid = my_strtoul(popts->optarg); q_opt = 1; break; case 'o': g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); break; default: IFX_PPACMD_PRINT("ppa_parse_get_rate_cmd not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( p_opt + i_opt != 1) { IFX_PPACMD_PRINT("note: one or only one of portid and ifname must be specified\n"); return PPA_CMD_ERR; } IFX_DBG("ppa_parse_get_rate_cmd: portid=%d, queueid=%d\n", (unsigned int)pdata->qos_rate_info.portid, (unsigned int)pdata->qos_rate_info.queueid); return PPA_CMD_OK; } static int ppa_get_rate_do_cmd(PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_QUEUE_NUM_INFO qnum_info; PPA_CMD_RATE_INFO info; int i=0, j=0, start_i, end_i=0; int res; memset( &qnum_info, 0, sizeof(qnum_info) ); qnum_info.portid = pdata->qos_rate_info.portid; if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_QOS_QUEUE_MAX_NUM, &qnum_info ) != PPA_CMD_OK ) ) { IFX_PPACMD_PRINT("ioctl PPA_CMD_GET_QOS_QUEUE_MAX_NUM fail\n"); return IFX_FAILURE; } if( pdata->qos_rate_info.queueid!= -1 ) // set index already, then use it { memset( &info, 0, sizeof(info) ); info.portid = pdata->qos_rate_info.portid; info.queueid = pdata->qos_rate_info.queueid; if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_QOS_RATE, &info) == PPA_CMD_OK ) ) { if( !g_output_to_file ) { IFX_PPACMD_PRINT(" Rate Burst\n"); if( pdata->qos_rate_info.queueid < qnum_info.queue_num ) IFX_PPACMD_PRINT(" queue %2d: %08d(kbps) 0x%04d\n", (unsigned int)info.queueid, (unsigned int)info.rate, (unsigned int)info.burst ); else IFX_PPACMD_PRINT(" port : %08d(kbps) 0x%04d\n", (unsigned int)info.rate, (unsigned int)info.burst ); } else { /*note, currently only last valid flow info is saved to file and all other flow informations are all overwritten */ SaveDataToFile(g_output_filename, (char *)(&info), sizeof(info) ); } j++; } } else { start_i = 0; end_i = qnum_info.queue_num; IFX_DBG("Need to read rate shaping from queue %d to %d\n", start_i, end_i-1 ); for(i=start_i; iqos_rate_info.portid; info.queueid = i; if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_QOS_RATE, &info) == PPA_CMD_OK ) ) { if( !g_output_to_file ) { if( i == start_i ) IFX_PPACMD_PRINT(" Rate Burst\n"); IFX_PPACMD_PRINT(" queue %2d: %07d(kbps) 0x%04d\n", i, (unsigned int)info.rate, (unsigned int)info.burst ); } else { /*note, currently only last valid flow info is saved to file and all other flow informations are all overwritten */ SaveDataToFile(g_output_filename, (char *)(&info), sizeof(info) ); } j++; } } if( pdata->qos_rate_info.queueid == -1 ) { memset( &info, 0, sizeof(info) ); info.portid = pdata->qos_rate_info.portid; info.queueid = qnum_info.queue_num; if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_QOS_RATE, &info) == PPA_CMD_OK ) ) { if( !g_output_to_file ) { IFX_PPACMD_PRINT(" port : %07d(kbps) 0x%04d\n", (unsigned int)info.rate, (unsigned int)info.burst ); } else { /*note, currently only last valid flow info is saved to file and all other flow informations are all overwritten */ SaveDataToFile(g_output_filename, (char *)(&info), sizeof(info) ); } j++; } } } return IFX_SUCCESS; } /*ppacmd getrate ---end*/ #endif //enod of CONFIG_IFX_PPA_QOS_RATE_SHAPING #endif /*end if CONFIG_IFX_PPA_QOS */ /*ppacmd gethook: get all exported hook number ---begin*/ static void ppa_get_hook_count_help( int summary) { IFX_PPACMD_PRINT("gethooknum [-o outfile]\n"); return; } static const char ppa_get_hook_short_opts[] = "o:h"; static const struct option ppa_get_hook_long_opts[] ={ {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static void ppa_print_get_hook_count_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("There are %u exported hook \n", (unsigned int) pdata->count_info.count); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->count_info), sizeof(pdata->count_info) ); } } /*ppacmd gethook: get all exported hook number ---end*/ /*ppacmd gethooklist: get all exported hook list ---begin*/ static void ppa_get_hook_list_help( int summary) { IFX_PPACMD_PRINT("gethooklist [-o outfile]\n"); return; } static const char ppa_get_hook_list_short_opts[] = "o:h"; static const struct option ppa_get_hook_list_long_opts[] ={ {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static int ppa_get_hook_list_cmd(PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_DATA cmd_info; PPA_CMD_HOOK_LIST_INFO *phook_list; int res = PPA_CMD_OK, i, size; //get session count first before malloc memroy cmd_info.count_info.flag = 0; cmd_info.count_info.count = 0; if( ppa_do_ioctl_cmd(PPA_CMD_GET_HOOK_COUNT, &cmd_info ) != PPA_CMD_OK ) { IFX_DBG("ppa_do_ioctl_cmd: PPA_CMD_GET_HOOK_COUNT failed\n"); return -EIO; } if( cmd_info.count_info.count <= 0 ) { IFX_DBG("Note, there is no exported PPA hooks at all\n"); return -EIO; } IFX_DBG("There are %u hook mapped\n", (unsigned int) cmd_info.count_info.count ); //malloc memory and set value correctly size = sizeof(PPA_CMD_HOOK_LIST_INFO) + cmd_info.count_info.count * sizeof(PPA_HOOK_INFO); phook_list = (PPA_CMD_HOOK_LIST_INFO *) malloc( size ); if( phook_list == NULL ) { IFX_DBG("Malloc failed in ppa_get_hook_list_cmd\n"); return PPA_CMD_NOT_AVAIL; } phook_list->hook_count = cmd_info.count_info.count; phook_list->flag = 0; //get session information if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_HOOK_LIST, phook_list ) != PPA_CMD_OK ) ) { free( phook_list ); IFX_DBG("ppa_get_hook_list_cmd ioctl failed\n"); return res; } if( !g_output_to_file ) { for(i=0; ihook_count; i++) { IFX_PPACMD_PRINT("%02d: %-50s-%-11s ( hook address 0x%x to 0x%x)\n", i, phook_list->list[i].hookname, phook_list->list[i].hook_flag? "hooked":"not hooked",(unsigned int) phook_list->list[i].hook_addr, phook_list->list[i].hook_flag?(unsigned int) phook_list->list[i].real_func:0); } } else { SaveDataToFile(g_output_filename, (char *)(phook_list), size ); } return PPA_CMD_OK; } /*ppacmd gethooklist: get all exported hook list ---end*/ /*ppacmd sethook: set hook to enable/dsiable ---begin*/ static void ppa_set_hook_help( int summary) { IFX_PPACMD_PRINT("setthook <-n hookname > <-c enable | disable > ]\n"); return; } static const char ppa_set_hook_short_opts[] = "n:c:h"; static const struct option ppa_set_hook_long_opts[] ={ {"hookname", required_argument, NULL, 'n'}, {"control", required_argument, NULL, 'c'}, { 0,0,0,0 } }; static int ppa_parse_set_hook_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int hookname_opt = 0, control_opt = 0; memset( &pdata->hook_control_info, 0, sizeof(pdata->hook_control_info)) ; while(popts->opt) { if (popts->opt == 'n') { strncpy(pdata->hook_control_info.hookname, popts->optarg, sizeof(pdata->hook_control_info.hookname) ); hookname_opt++; } else if (popts->opt == 'c') { if( stricmp( popts->optarg, "enable" ) == 0 ) pdata->hook_control_info.enable = 1; control_opt++; } else { return PPA_CMD_ERR; } popts++; } if (hookname_opt != 1 || control_opt >=2) return PPA_CMD_ERR; IFX_DBG("sethook: try to %s %s \n", pdata->hook_control_info.enable ? "enable":"disable", pdata->hook_control_info.hookname); return PPA_CMD_OK; } /*ppacmd sethook: set hook to enable/dsiable ---end*/ /*ppacmd r ( getmem ) ---begin*/ static void ppa_get_mem_help( int summary) { if( !summary ) IFX_PPACMD_PRINT("r <-a address> <-f offset> <-s size> <-p repeat> [-o outfile]\n"); return; } static const char ppa_get_mem_short_opts[] = "a:f:s:p:n:o:h"; static const struct option ppa_get_mem_long_opts[] ={ {"address", required_argument, NULL, 'a'}, {"offset", required_argument, NULL, 'f'}, {"size", required_argument, NULL, 's'}, {"repeat", required_argument, NULL, 'n'}, {"save-to-file", required_argument, NULL, 'o'}, { 0,0,0,0 } }; static int ppa_parse_get_mem_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int a_opt=0, f_opt=0, s_opt=0, n_opt=0; memset( &pdata->read_mem_info, 0, sizeof(pdata->read_mem_info) ); pdata->read_mem_info.repeat = 1; /*default read only */ pdata->read_mem_info.size = 32; /*default read 32 bits */ pdata->read_mem_info.shift= 32 -pdata->read_mem_info.size ; while(popts->opt) { switch(popts->opt) { case 'a': pdata->read_mem_info.addr = my_strtoul(popts->optarg); a_opt ++; break; case 'f': pdata->read_mem_info.shift = my_strtoul(popts->optarg); if( pdata->read_mem_info.size >= 32 - pdata->read_mem_info.shift ) pdata->read_mem_info.size = 32 - pdata->read_mem_info.shift; f_opt ++; break; case 's': pdata->read_mem_info.size = my_strtoul(popts->optarg); if( pdata->read_mem_info.shift > 32 - pdata->read_mem_info.size ) pdata->read_mem_info.shift= 32 - pdata->read_mem_info.size; s_opt ++; break; case 'n': pdata->read_mem_info.repeat = my_strtoul(popts->optarg); n_opt ++; break; case 'o': g_output_to_file = 1; strncpy(g_output_filename,popts->optarg,PPACMD_MAX_FILENAME); break; default: IFX_PPACMD_PRINT("r not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( a_opt != 1 || f_opt >= 2 || s_opt >= 2 || n_opt >= 2) { IFX_PPACMD_PRINT("Wrong parameter\n"); return PPA_CMD_ERR; } if( pdata->read_mem_info.size == 0 ) { pdata->read_mem_info.size = 32 - pdata->read_mem_info.shift; } if( pdata->read_mem_info.size > 32 ) { IFX_PPACMD_PRINT("Wrong size value: %d ( it should be 1 ~ 32 )\n", (unsigned int)pdata->read_mem_info.size); return PPA_CMD_ERR; } if( pdata->read_mem_info.shift >= 32 ) { IFX_PPACMD_PRINT("Wrong shift value: %d ( it should be 0 ~ 31 )\n", (unsigned int)pdata->read_mem_info.shift); return PPA_CMD_ERR; } if( pdata->read_mem_info.shift + pdata->read_mem_info.size > 32 ) { IFX_PPACMD_PRINT("Wrong shift/size value: %d/%d (The sum should <= 32 ))\n", (unsigned int)pdata->read_mem_info.shift, (unsigned int)pdata->read_mem_info.size); return PPA_CMD_ERR; } IFX_DBG("r: address=0x%x, offset=%d, size=%d, repeat=%d\n", (unsigned int )pdata->read_mem_info.addr, (unsigned int )pdata->read_mem_info.shift, (unsigned int )pdata->read_mem_info.size, (unsigned int )pdata->read_mem_info.repeat ); return PPA_CMD_OK; } static int ppa_get_mem_cmd(PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_READ_MEM_INFO *buffer; int i, size; int num_per_line=8; size = sizeof(pdata->read_mem_info) + sizeof(pdata->read_mem_info.buffer) * pdata->read_mem_info.repeat ; buffer = (PPA_CMD_READ_MEM_INFO *) malloc( size ); if( buffer == NULL ) { IFX_PPACMD_PRINT("Malloc %d bytes failed\n", size ); return PPA_CMD_NOT_AVAIL; } memset( buffer, 0, sizeof(size) ); memcpy( (void *)buffer, &pdata->read_mem_info, sizeof(pdata->read_mem_info) ); buffer->flag = 0; //get session information if( ppa_do_ioctl_cmd(PPA_CMD_READ_MEM, buffer ) != PPA_CMD_OK ) { free( buffer ); return IFX_FAILURE; } if( !g_output_to_file ) { IFX_PPACMD_PRINT("The value from address %x:----------------------------", (unsigned int)buffer->addr ); for(i=0; irepeat; i++ ) { if( i % num_per_line == 0 ) IFX_PPACMD_PRINT("\n%08x: ", (unsigned int )buffer->addr + i * 4 ); if( buffer->size <= 4 ) { IFX_PPACMD_PRINT( "%01x ", (unsigned int )buffer->buffer[i] ); } else if( buffer->size <=8 ) { IFX_PPACMD_PRINT( "%02x ", (unsigned int )buffer->buffer[i] ); } else if( buffer->size <=12 ) { IFX_PPACMD_PRINT( "%03x ", (unsigned int )buffer->buffer[i] ); } else if( buffer->size <=16 ) { IFX_PPACMD_PRINT( "%04x ", (unsigned int )buffer->buffer[i] ); } else if( buffer->size <=20 ) { IFX_PPACMD_PRINT( "%05x ", (unsigned int )buffer->buffer[i] ); } else if( buffer->size <=24 ) { IFX_PPACMD_PRINT( "%06x ", (unsigned int )buffer->buffer[i] ); } else if( buffer->size <=28 ) { IFX_PPACMD_PRINT( "%07x ", (unsigned int )buffer->buffer[i] ); } else { IFX_PPACMD_PRINT( "%08x ", (unsigned int )buffer->buffer[i] ); } } IFX_PPACMD_PRINT("\n" ); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->read_mem_info), sizeof(pdata->read_mem_info) ); } free( buffer ); return IFX_SUCCESS; } /*ppacmd r ( getmem ) ---end*/ /*ppacmd w ( setmem ) ---begin*/ static void ppa_set_mem_help( int summary) { if( !summary ) IFX_PPACMD_PRINT("w <-a address> <-f offset> <-s size> <-v value> <-p repeat> \n"); return; } static const char ppa_set_mem_short_opts[] = "a:f:s:v:n:p:h"; static const struct option ppa_set_mem_long_opts[] ={ {"address", required_argument, NULL, 'a'}, {"offset", required_argument, NULL, 'f'}, {"size", required_argument, NULL, 's'}, {"repeat", required_argument, NULL, 'n'}, {"value", required_argument, NULL, 'v'}, { 0,0,0,0 } }; static int ppa_parse_set_mem_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int a_opt=0, f_opt=0, s_opt=0, n_opt=0, v_opt=0; memset( &pdata->set_mem_info, 0, sizeof(pdata->set_mem_info) ); pdata->set_mem_info.repeat = 1; /*default read only */ pdata->set_mem_info.size = 32; /*default read 32 bits */ pdata->set_mem_info.shift= 0; pdata->set_mem_info.value= 0; while(popts->opt) { switch(popts->opt) { case 'a': pdata->set_mem_info.addr = my_strtoul(popts->optarg); a_opt ++; break; case 'f': pdata->set_mem_info.shift = my_strtoul(popts->optarg); if( pdata->set_mem_info.size > 32 - pdata->set_mem_info.shift ) pdata->set_mem_info.size = 32 - pdata->set_mem_info.shift; f_opt ++; break; case 's': pdata->set_mem_info.size = my_strtoul(popts->optarg); if( pdata->set_mem_info.shift > 32 - pdata->set_mem_info.size ) pdata->set_mem_info.shift= 32 - pdata->set_mem_info.size; s_opt ++; break; case 'n': pdata->set_mem_info.repeat = my_strtoul(popts->optarg); n_opt ++; break; case 'v': pdata->set_mem_info.value = my_strtoul(popts->optarg); v_opt ++; break; default: return PPA_CMD_ERR; } popts++; } if( a_opt != 1 || f_opt >= 2 || s_opt >= 2 || n_opt >= 2 || v_opt != 1) { IFX_PPACMD_PRINT("Wrong parameter\n"); return PPA_CMD_ERR; } if( pdata->set_mem_info.size == 0 ) { pdata->set_mem_info.size = 32 - pdata->set_mem_info.shift; } if( pdata->set_mem_info.size > 32 ) { IFX_PPACMD_PRINT("Wrong size value: %d ( it should be 1 ~ 32 )\n", (unsigned int)pdata->set_mem_info.size); return PPA_CMD_ERR; } if( pdata->set_mem_info.shift >= 32 ) { IFX_PPACMD_PRINT("Wrong shift value: %d ( it should be 0 ~ 31 )\n", (unsigned int)pdata->set_mem_info.shift); return PPA_CMD_ERR; } if( pdata->set_mem_info.shift + pdata->set_mem_info.size > 32) { IFX_PPACMD_PRINT("Wrong shift/size value: %d/%d (The sum should <= 32 ))\n", (unsigned int)pdata->set_mem_info.shift, (unsigned int)pdata->set_mem_info.size); return PPA_CMD_ERR; } IFX_DBG("w: address=0x%x, offset=%d, size=%d, value=0x%x, repeat=%d\n", (unsigned int )pdata->set_mem_info.addr, (unsigned int )pdata->set_mem_info.shift, (unsigned int )pdata->set_mem_info.size, (unsigned int ) pdata->set_mem_info.value , (unsigned int ) pdata->set_mem_info.repeat ); return PPA_CMD_OK; } /*ppacmd w ( setmem ) ---end*/ /*ppacmd controlmf: enable multiple field ---begin*/ static void ppa_set_mf_help( int summary) { IFX_PPACMD_PRINT("setmf <-c enable|disable > \n"); return; } static const char ppa_set_mf_short_opts[] = "c:h"; static const struct option ppa_set_mf_long_opts[] ={ {"control", required_argument, NULL, 'c'}, { 0,0,0,0 } }; static int ppa_parse_set_mf_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int c_opt=0; memset( pdata, 0, sizeof(PPA_CMD_ENABLE_MULTIFIELD_INFO ) ); while(popts->opt) { switch(popts->opt) { case 'c': if( stricmp(popts->optarg, "enable") == 0 ) pdata->mf_info.enable_multifield = 1; c_opt ++; break; default: IFX_PPACMD_PRINT("controlmf not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( c_opt != 1) { IFX_PPACMD_PRINT("Wrong parameter\n"); return PPA_CMD_ERR; } IFX_DBG("To %s multiple filed feature.\n", pdata->mf_info.enable_multifield ? "enable":"disable"); return PPA_CMD_OK; } /*ppacmd controlmf: enable multiple field ---end*/ /*ppacmd getmf: get multiple field status: enabled/disabled ---begin*/ static void ppa_get_mf_status_help( int summary) { IFX_PPACMD_PRINT("getmf [-o outfile]> \n"); return; } static void ppa_print_get_mf_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("The multiple filed feature is %s\n", pdata->mf_info.enable_multifield ? "enabled": "disabled"); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->mf_info), sizeof(pdata->mf_info) ); } } /*ppacmd getmf: get multiple field status: enabled/disabled --end*/ /*ppacmd getmfmaxnum: get max multiple field flow number: ---------------------------------begin*/ static void ppa_get_mf_count_help( int summary) { IFX_PPACMD_PRINT("getmfmaxnum [-o outfile]>\n"); return; } static void ppa_print_get_mf_count_cmd(PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("The multiple filed flow count is %u\n", (unsigned int) pdata->count_info.count); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->count_info), sizeof(pdata->count_info) ); } } /*ppacmd getmfmaxnum: get max multiple field flow number: ---------------------------------end*/ void ppa_mf_flow_display(PPA_MULTIFIELD_FLOW_INFO *flow, int32_t index) { uint32_t full_id, mask; IFX_DBG("\tMultiple field flow[%d] information: \n", index); if( flow->cfg0.vlan_info.bfauto ) { IFX_DBG("\tAcclerate packet From %s to %s via queue %d %s\n", flow->cfg0.vlan_info.vlan_info_auto.rx_ifname, flow->cfg0.vlan_info.vlan_info_auto.tx_ifname, flow->cfg0.queue_id, flow->cfg0.fwd_cpu ?"fwd to CPU":"as original Destination"); IFX_DBG("\tFlow classification info:\n"); } else { IFX_DBG("\tAcclerate packet From port id %d to %d via queue %d %s\n", flow->cfg0.vlan_info.vlan_info_manual.rx_if_id, flow->cfg0.vlan_info.vlan_info_manual.tx_if_id, flow->cfg0.queue_id, flow->cfg0.fwd_cpu ?"fwd to CPU":"as original Destination"); if( flow->cfg0.vlan_info.vlan_info_manual.action_out_vlan_insert ) { VLAN_ID_CONBINE(full_id, flow->cfg0.vlan_info.vlan_info_manual.new_out_vlan_pri, flow->cfg0.vlan_info.vlan_info_manual.new_out_vlan_cfi, flow->cfg0.vlan_info.vlan_info_manual.new_out_vlan_vid ); full_id |= (flow->cfg0.vlan_info.vlan_info_manual.new_out_vlan_tpid << 16 ); IFX_DBG("\tNew out vlan id 0x%04x\n", (unsigned int)full_id ); } if( flow->cfg0.vlan_info.vlan_info_manual.action_in_vlan_insert ) { VLAN_ID_CONBINE(full_id, flow->cfg0.vlan_info.vlan_info_manual.new_in_vlan_pri, flow->cfg0.vlan_info.vlan_info_manual.new_in_vlan_cfi, flow->cfg0.vlan_info.vlan_info_manual.new_in_vlan_vid ); IFX_DBG("\tNew in vlan id 0x%04x\n", (unsigned int)full_id ); } if( flow->cfg0.vlan_info.vlan_info_manual.action_out_vlan_remove ||flow->cfg0.vlan_info.vlan_info_manual.action_in_vlan_remove) IFX_DBG("\tRemove: %s %s \n", flow->cfg0.vlan_info.vlan_info_manual.action_out_vlan_remove?"outer vlan":"", flow->cfg0.vlan_info.vlan_info_manual.action_in_vlan_remove?"inner vlan":""); IFX_DBG("\tFlow classification info:\n"); IFX_DBG("\tvlan number: 0x%01x/0x%01x\n", flow->cfg0.vlan_info.vlan_info_manual.is_vlan, flow->cfg0.vlan_info.vlan_info_manual.is_vlan_mask); VLAN_ID_CONBINE(full_id, flow->cfg0.vlan_info.vlan_info_manual.out_vlan_pri, flow->cfg0.vlan_info.vlan_info_manual.out_vlan_cfi, flow->cfg0.vlan_info.vlan_info_manual.out_vlan_vid ); VLAN_ID_CONBINE(mask, flow->cfg0.vlan_info.vlan_info_manual.out_vlan_pri_mask, flow->cfg0.vlan_info.vlan_info_manual.out_vlan_cfi_mask, flow->cfg0.vlan_info.vlan_info_manual.out_vlan_vid_mask); IFX_DBG("\tmatch out vlan id 0x%04x/0x%04x\n", (unsigned int)full_id, (unsigned int)mask ); VLAN_ID_CONBINE(full_id, flow->cfg0.vlan_info.vlan_info_manual.in_vlan_pri, flow->cfg0.vlan_info.vlan_info_manual.in_vlan_cfi, flow->cfg0.vlan_info.vlan_info_manual.in_vlan_vid ); VLAN_ID_CONBINE(mask, flow->cfg0.vlan_info.vlan_info_manual.in_vlan_pri_mask, flow->cfg0.vlan_info.vlan_info_manual.in_vlan_cfi_mask, flow->cfg0.vlan_info.vlan_info_manual.in_vlan_vid_mask); IFX_DBG("\tmatch in vlan id 0x%04x/0x%04x\n", (unsigned int)full_id, (unsigned int)mask ); } IFX_DBG("\tDSCP: 0x%x/0x%x\n", flow->cfg0.dscp, flow->cfg0.dscp_mask ); IFX_DBG("\tEther Type: 0x%x/0x%x\n", flow->cfg0.ether_type, flow->cfg0.ether_type_mask); IFX_DBG("\tIPV4 flag: 0x%x/0x%x\n", flow->cfg0.ipv4, flow->cfg0.ipv4_mask); IFX_DBG("\tIPV6 flag: 0x%x/0x%x\n", flow->cfg0.ipv6, flow->cfg0.ipv6_mask); IFX_DBG("\tL3 off0: 0x%x/0x%x\n", flow->cfg0.l3_off0, flow->cfg0.l3_off0_mask); IFX_DBG("\tL3 off1: 0x%x/0x%x\n", flow->cfg0.l3_off1, flow->cfg0.l3_off1_mask); IFX_DBG("\tSource ip: 0x%x(%u.%u.%u.%u)/0x%x\n", (unsigned int)flow->cfg0.s_ip, NIPQUAD(flow->cfg0.s_ip),(unsigned int)flow->cfg0.s_ip_mask); IFX_DBG("\tPacket length: 0x%x/0x%x\n", (unsigned int)flow->cfg0.pkt_length, (unsigned int)flow->cfg0.pkt_length_mask); IFX_DBG("\tpppoe flag: 0x%x/0x%x\n", (unsigned int)flow->cfg0.pppoe_session, (unsigned int)flow->cfg0.pppoe_session_mask); } /*ppacmd addmfflow: add a multiple field flow --------------------------------------------------begin*/ static void ppa_mf_flow_help( char *cmd, int summary) { IFX_PPACMD_PRINT("%s <-a > <-s rx-ifname > <-d tx-ifname>\n", cmd); IFX_PPACMD_PRINT("\t%s <-s rx-port-id > <-d tx-port-id >\n", cmd); IFX_PPACMD_PRINT("\t [-n vlan-number/mask] [-o match-out-vlan/mask] [-i match-in-vlan/mask]\n"); IFX_PPACMD_PRINT("\t [-c insert|remove outvlan ] [ -m insert|remove inner vlan] [-x new-out-vlan] [-g new-inner-vlan]\n"); if( !summary ) { IFX_PPACMD_PRINT("\t Other supported optional parameters: \n"); IFX_PPACMD_PRINT("\t [-e ether-type(16bits)/mask] [-p pppoe-session(1bit)/mask] [-t dscp(tos)/maks] [-r ipversion (4|6)] \n"); IFX_PPACMD_PRINT("\t [-f soruce-ip/mask] [-u l3_off0/mask] [-w l3_off1/mask ] [-k packet_leng/mask] [-z fwd_to_cpu] [-q queue-id] \n"); IFX_PPACMD_PRINT("\t Note\n"); IFX_PPACMD_PRINT("\t 1. If parrameter -a is used, it must be put in first \n"); IFX_PPACMD_PRINT("\t 2. For mask, 0 mean to compare this corresponding bit, 1 mean don't compare the bit \n"); IFX_PPACMD_PRINT("\t 3. Out/in vlan id format: vlan priority (3 bits), cfi (1 bit) and vlan id (12 bits), over all 16 bits \n"); IFX_PPACMD_PRINT("\t 4. Vlan-number: 2 bits \n"); IFX_PPACMD_PRINT("\t 5. Packet length: less than and equal compare after L2 packet length divided 64 \n"); } return; } static void ppa_add_mf_flow_help( int summary) { ppa_mf_flow_help("addmfflow", summary); return; } static const char ppa_add_mf_flow_short_opts[] = "as:d:n:o:i:c:m:x:g:e:p:t:r:f:u:w:z:k:q:h"; static const struct option ppa_add_mf_flow_long_opts[] ={ /*simple auto way to add multiple field flow, like eth1.50 bridge to eth0 */ {"auto-vlan", no_argument, NULL, 'a'}, {"rx-ifname", required_argument, NULL, 's'}, {"tx-ifname", required_argument, NULL, 'd'}, /*manual way to provide detail information */ {"from-portid", required_argument, NULL, 's'}, {"to-portid", required_argument, NULL,'d'}, {"vlan-num", required_argument, NULL, 'n'}, // ??? why need it, difficult for transparent bridging {"match-out-vlan", required_argument, NULL, 'o'}, //vlanid/pri/cfi and its mask {"match-in-vlan", required_argument, NULL, 'i'}, //vlanid and its mask {"out-vlan-control", required_argument, NULL, 'c'}, // out vlan action: remove/insert {"in-vlan-control", required_argument, NULL, 'm'}, // inner vlan action: remove/insert {"new-out-vlan", required_argument, NULL, 'x'}, // include new vlan id/vlan priority/vlan cfi {"new-in-vlan", required_argument, NULL, 'g'}, //include new vlan id/vlan priority/vlan cfi /*all below parameter shared together by simple auto way and manual way */ {"ether-type", required_argument, NULL, 'e'}, //include ethernet type and its mask {"pppoe-session", required_argument, NULL, 'p'}, {"dscp", required_argument, NULL, 't'}, //dscp and(tos)/its mask {"ipver", required_argument, NULL, 'r'}, //match ipv4 or ipv6 {"src-ip", required_argument, NULL, 'f'}, //include source ip and its mask {"l3_off0", required_argument, NULL, 'u'}, //include l3_off0 and its mask {"l3_off1", required_argument, NULL, 'w'}, //include l3_off1 and its mask {"fwd_cpu", required_argument, NULL, 'z'}, // forward to CPU or keep original destionation {"pkt_len", required_argument, NULL, 'k'}, // packet length {"queuid", required_argument, NULL, 'q'}, //queue id { 0,0,0,0 } }; static void ppa_get_value_mask(char *s, char **value, char**mask) { char *splitter="/"; *value = NULL; *mask = NULL; *value=strtok(s, splitter); if( *value ) { *mask = strtok( NULL,splitter); } } static int ppa_parse_add_mf_flow_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int s_opt=0, d_opt=0, n_opt=0, o_opt=0, i_opt=0, c_opt=0, m_opt=0, g_opt=0, e_opt=0, p_opt=0, t_opt=0, r4_opt=0, r6_opt=0, x_opt=0, f_opt=0, u_opt=0, w_opt=0,z_opt=0, q_opt=0; char *value; char *mask; uint32_t temp; memset( pdata, 0, sizeof(pdata->mf_flow_info ) ); pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.is_vlan_mask = -1; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_pri_mask= -1; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_cfi_mask = -1; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_vid_mask = -1; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_pri_mask= -1; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_cfi_mask = -1; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_vid_mask = -1; pdata->mf_flow_info.flow.cfg0.ether_type_mask = -1; pdata->mf_flow_info.flow.cfg0.pppoe_session_mask = -1; pdata->mf_flow_info.flow.cfg0.dscp_mask = -1; pdata->mf_flow_info.flow.cfg0.ipv4_mask = -1; pdata->mf_flow_info.flow.cfg0.ipv6_mask = -1; pdata->mf_flow_info.flow.cfg0.s_ip_mask = -1; pdata->mf_flow_info.flow.cfg0.l3_off0_mask = -1; pdata->mf_flow_info.flow.cfg0.l3_off1_mask = -1; pdata->mf_flow_info.flow.cfg0.pkt_length_mask = -1; while(popts->opt) { switch(popts->opt) { case 'a': pdata->mf_flow_info.flow.cfg0.vlan_info.bfauto= 1; break; case 's': //rx interface name or port id if ( pdata->mf_flow_info.flow.cfg0.vlan_info.bfauto ) { strncpy( pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_auto.rx_ifname, popts->optarg, sizeof(pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_auto.rx_ifname) ); } else { pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.rx_if_id = my_strtoul(popts->optarg); if( pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.rx_if_id >=16 ) { IFX_PPACMD_PRINT("Wrong src port id: %s\n", popts->optarg); return IFX_FAILURE; } } s_opt ++; break; case 'd': //tx interface name or port id if ( pdata->mf_flow_info.flow.cfg0.vlan_info.bfauto ) { strncpy( pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_auto.tx_ifname, popts->optarg, sizeof(pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_auto.rx_ifname) ); } else { pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.tx_if_id = my_strtoul(popts->optarg); if( pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.tx_if_id >= 16 ) { IFX_PPACMD_PRINT("Wrong dst port id: %s\n", popts->optarg); return IFX_FAILURE; } } d_opt ++; break; case 'n': //vlan tag number ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong vlan tag num/mask\n"); return IFX_FAILURE; } pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.is_vlan = my_strtoul(value); if( mask == NULL ) pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.is_vlan_mask = -1; else pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.is_vlan_mask = my_strtoul(mask); n_opt ++; break; case 'o': //match out vlan ( prio 3 bits, cfi 1 bits and 12 bits vlan id )/and mask ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong out vlan tag/mask\n"); return IFX_FAILURE; } temp = my_strtoul(value); VLAN_ID_SPLIT(temp, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_pri, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_cfi, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_vid); if( mask == NULL ) { pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_pri_mask= 0; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_cfi_mask = 0; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_vid_mask = 0; } else { temp = my_strtoul(mask); VLAN_ID_SPLIT(temp, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_pri_mask, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_cfi_mask, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.out_vlan_vid_mask ); } o_opt ++; break; case 'i': //match inner vlan ( prio 3 bits, cfi 1 bits and 12 bits vlan id )/and mask ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong out vlan tag/mask\n"); return IFX_FAILURE; } temp = my_strtoul(value); VLAN_ID_SPLIT(temp, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_pri , pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_cfi, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_vid ); if( mask == NULL ) { pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_pri_mask= 0; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_cfi_mask = 0; pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_vid_mask = 0; } else { temp = my_strtoul(mask); VLAN_ID_SPLIT(temp, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_pri_mask, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_cfi_mask, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.in_vlan_vid_mask ); } i_opt ++; break; case 'c': //out vlan action: remove or insert if( stricmp(popts->optarg, "insert") == 0 ) pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.action_out_vlan_insert = 1; else if( stricmp(popts->optarg, "remove") == 0 ) pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.action_out_vlan_remove= 1; else { IFX_PPACMD_PRINT("Wrong out vlan control. It should be insert or remove\n"); return IFX_FAILURE; } c_opt ++; break; case 'm': //inner vlan action: remove or insert if( stricmp(popts->optarg, "insert") == 0 ) pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.action_in_vlan_insert = 1; else if( stricmp(popts->optarg, "remove") == 0 ) pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.action_in_vlan_remove= 1; else { IFX_PPACMD_PRINT("Wrong inner vlan control. It should be insert or remove\n"); return IFX_FAILURE; } m_opt ++; break; case 'x': //new out vlan (rio 3 bits, cfi 1 bits and 12 bits vlan id) temp = my_strtoul( popts->optarg); VLAN_ID_SPLIT( temp, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.new_out_vlan_pri, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.new_out_vlan_cfi, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.new_out_vlan_vid ); pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.new_out_vlan_tpid = temp >> 16; x_opt ++; break; case 'g': //new inner vlan (rio 3 bits, cfi 1 bits and 12 bits vlan id) temp = my_strtoul( popts->optarg); VLAN_ID_SPLIT( temp, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.new_in_vlan_pri, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.new_in_vlan_cfi, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.new_in_vlan_vid ); g_opt ++; break; case 'e': //ethernet type and its mask ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong Ethernet type\n"); return IFX_FAILURE; } pdata->mf_flow_info.flow.cfg0.ether_type = my_strtoul(value); if( mask == NULL ) { pdata->mf_flow_info.flow.cfg0.ether_type_mask = 0; } else { pdata->mf_flow_info.flow.cfg0.ether_type_mask = my_strtoul(mask); } e_opt ++; break; case 'p': //pppoe-session ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong pppoe-session flag type\n"); return IFX_FAILURE; } pdata->mf_flow_info.flow.cfg0.pppoe_session = my_strtoul(value); if( mask == NULL ) { pdata->mf_flow_info.flow.cfg0.pppoe_session_mask = 0; } else { pdata->mf_flow_info.flow.cfg0.pppoe_session_mask = my_strtoul(mask); } p_opt ++; break; case 't': //dscp(tos) and its mask ( 8 bits) ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong DSCP/TOS/mask\n"); return IFX_FAILURE; } pdata->mf_flow_info.flow.cfg0.dscp = my_strtoul(value); if( mask == NULL ) { pdata->mf_flow_info.flow.cfg0.dscp_mask = 0; } else { pdata->mf_flow_info.flow.cfg0.dscp_mask = my_strtoul(mask); } t_opt ++; break; case 'r': //ip vversion: 4 or 6 if( strcmp( popts->optarg, "4") == 0 ) { r4_opt ++; pdata->mf_flow_info.flow.cfg0.ipv4 = 1; pdata->mf_flow_info.flow.cfg0.ipv4_mask = 0; } else if( strcmp( popts->optarg, "6") == 0 ) { r6_opt ++; pdata->mf_flow_info.flow.cfg0.ipv6 = 1; pdata->mf_flow_info.flow.cfg0.ipv6_mask = 0; } break; case 'f': //source ip and its mask ( 32 bits )---for ipv4 only ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong soruce ip/mask\n"); return IFX_FAILURE; } pdata->mf_flow_info.flow.cfg0.s_ip = my_strtoul(value); if( mask == NULL ) { pdata->mf_flow_info.flow.cfg0.s_ip_mask = 0; } else { pdata->mf_flow_info.flow.cfg0.s_ip_mask = my_strtoul(mask); } f_opt ++; break; case 'u': //l3_off0 and its mask ( 32bits) ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong l3_off0/mask\n"); return IFX_FAILURE; } pdata->mf_flow_info.flow.cfg0.l3_off0 = my_strtoul(value); if( mask == NULL ) { pdata->mf_flow_info.flow.cfg0.l3_off0_mask = 0; } else { pdata->mf_flow_info.flow.cfg0.l3_off0_mask = my_strtoul(mask); } u_opt ++; break; case 'w': //l3_off1 and tis mask ( 32bits) ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong l3_off1/mask\n"); return IFX_FAILURE; } pdata->mf_flow_info.flow.cfg0.l3_off1 = my_strtoul(value); if( mask == NULL ) { pdata->mf_flow_info.flow.cfg0.l3_off1_mask = 0; } else { pdata->mf_flow_info.flow.cfg0.l3_off1_mask = my_strtoul(mask); } w_opt ++; break; case 'k': //packet length ppa_get_value_mask( popts->optarg, &value, &mask); if( value == NULL ) { IFX_PPACMD_PRINT("Wrong packet length\n"); return IFX_FAILURE; } pdata->mf_flow_info.flow.cfg0.pkt_length= my_strtoul(value); if( mask == NULL ) { pdata->mf_flow_info.flow.cfg0.pkt_length_mask = 0; } else { pdata->mf_flow_info.flow.cfg0.pkt_length_mask = my_strtoul(mask); } w_opt ++; break; case 'z': // whether keep original destionation or forward to CPU only temp = my_strtoul(popts->optarg); if( temp ) pdata->mf_flow_info.flow.cfg0.fwd_cpu =1; else pdata->mf_flow_info.flow.cfg0.fwd_cpu =0; z_opt ++; break; case 'q': //destionantion queue id pdata->mf_flow_info.flow.cfg0.queue_id = my_strtoul(popts->optarg); q_opt ++; break; default: return PPA_CMD_ERR; } popts++; } if( s_opt != 1 || d_opt != 1) { IFX_PPACMD_PRINT("Wrong parameter: rx/tx name or rx/tx port ID is a must !\n"); return PPA_CMD_ERR; } if( pdata->mf_flow_info.flow.cfg0.vlan_info.bfauto ) { if( strcmp(pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_auto.rx_ifname, pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_auto.tx_ifname )== 0 ) { IFX_PPACMD_PRINT("tx/rx cannot be same iinterface:%s\n", pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_auto.rx_ifname ); return PPA_CMD_ERR; } } else { if( pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.rx_if_id == pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.tx_if_id ) { IFX_PPACMD_PRINT("tx/rx cannot be same port id:%d\n", pdata->mf_flow_info.flow.cfg0.vlan_info.vlan_info_manual.rx_if_id ); return PPA_CMD_ERR; } } ppa_mf_flow_display( &pdata->mf_flow_info.flow, pdata->mf_flow_info.index); return PPA_CMD_OK; } static void ppa_print_add_mf_flow_cmd( PPA_CMD_DATA *pdata) { IFX_DBG("Added multiple field flow to index %d\n", pdata->mf_flow_info.index); } /*ppacmd addmfflow: enable multiple field ---end*/ /*ppacmd gettmfflow: get all multiple field flow information ------------------------------------------begin*/ static void ppa_get_mf_flow_help( int summary) { IFX_PPACMD_PRINT("getmfflow [-i index] [-o outfile]> \n"); return; } static const char ppa_get_mf_flow_short_opts[] = "o:i:h"; static const struct option ppa_get_mf_flow_long_opts[] = { {"save-to-file", required_argument, NULL, 'o'}, {"index", required_argument, NULL, 'i'}, { 0,0,0,0 } }; static int ppa_parse_get_mf_flow_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { pdata->mf_flow_info.index = -1; while(popts->opt) { switch(popts->opt) { case 'o': g_output_to_file = 1; strncpy(g_output_filename, popts->optarg, PPACMD_MAX_FILENAME); break; case 'i': pdata->mf_flow_info.index = my_strtoul(popts->optarg); break; default: return PPA_CMD_ERR; } popts++; } return PPA_CMD_OK; } static int ppa_get_mf_flow_cmd(PPA_COMMAND *pcmd, PPA_CMD_DATA *pdata) { PPA_CMD_COUNT_INFO count_info; PPA_CMD_MULTIFIELD_FLOW_INFO flow_info; int i, j, start_i, end_i=0; int res; memset( &count_info, 0, sizeof(count_info) ); if( (res = ppa_do_ioctl_cmd(PPA_CMD_GET_MULTIFIELD_ENTRY_MAX, &count_info ) != PPA_CMD_OK ) ) { IFX_PPACMD_PRINT("ioctl PPA_CMD_GET_MULTIFIELD_ENTRY_MAX fail\n"); return IFX_FAILURE; } if( pdata->mf_flow_info.index != -1 ) // set index already, then use it { start_i = pdata->mf_flow_info.index; if( start_i >= count_info.count -1 ) start_i = count_info.count -1; end_i = start_i + 1; } else { start_i = 0; end_i = count_info.count; } IFX_DBG("Need to read multiple field flow information from %d to %d\n", start_i, end_i-1 ); for(i=start_i; i \n"); return; } static const char ppa_del_mf_flow_index_short_opts[] = "i:h"; static const struct option ppa_del_mf_flow_index_long_opts[] ={ {"index", required_argument, NULL, 'i'}, { 0,0,0,0 } }; static int ppa_parse_del_mf_flow_index_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int i_opt=0; memset( pdata, 0, sizeof(PPA_CMD_ENABLE_MULTIFIELD_INFO ) ); while(popts->opt) { switch(popts->opt) { case 'i': pdata->mf_flow_info.index= my_strtoul(popts->optarg); i_opt ++; break; default: IFX_PPACMD_PRINT("delmf not support parameter -%c \n", popts->opt); return PPA_CMD_ERR; } popts++; } if( i_opt != 1) { IFX_PPACMD_PRINT("Wrong parameter\n"); return PPA_CMD_ERR; } IFX_DBG("Try to delete multiple field flow entry %u\n", (unsigned int)pdata->mf_flow_info.index ); return PPA_CMD_OK; } /*ppacmd delmfflowindex: enable multiple field ---end*/ /*ppacmd ppa_get_portid ---begin */ static const char ppa_get_portid_short_opts[] = "i:h"; static const struct option ppa_get_portid_long_opts[] ={ {"ifname", required_argument, NULL, 'i'}, { 0,0,0,0 } }; static void ppa_get_portid_help( int summary) { IFX_PPACMD_PRINT("getportid <-i ifname> \n"); return; } static int ppa_parse_get_portid_cmd(PPA_CMD_OPTS *popts, PPA_CMD_DATA *pdata) { unsigned int i_opt = 0; memset( pdata, 0, sizeof(pdata->portid_info ) ); while(popts->opt) { switch(popts->opt) { case 'i': strncpy(pdata->portid_info.ifname, popts->optarg, sizeof(pdata->portid_info.ifname) ); i_opt ++; break; default: return PPA_CMD_ERR; } popts++; } if( i_opt != 1) { IFX_PPACMD_PRINT("Wrong parameter.\n"); return PPA_CMD_ERR; } return PPA_CMD_OK; } static void ppa_print_get_portid_cmd( PPA_CMD_DATA *pdata) { if( !g_output_to_file ) { IFX_PPACMD_PRINT("The %s's port id is %d\n", pdata->portid_info.ifname, (unsigned int)pdata->portid_info.portid); } else { SaveDataToFile(g_output_filename, (char *)(&pdata->portid_info), sizeof(pdata->portid_info) ); } return; } /*ppacmd ppa_get_portid ---end */ /* =============================================================================== Command definitions =============================================================================== */ static PPA_COMMAND ppa_cmd[] = { { "init", PPA_CMD_INIT, ppa_print_init_help, ppa_parse_init_cmd, ppa_do_cmd, ppa_print_init_fake_cmd, ppa_init_long_opts, ppa_init_short_opts }, { "exit", PPA_CMD_EXIT, ppa_print_exit_help, ppa_parse_exit_cmd, ppa_do_cmd, NULL, ppa_no_long_opts, ppa_no_short_opts }, { "control", PPA_CMD_ENABLE, ppa_print_control_help, ppa_parse_control_cmd, ppa_do_cmd, NULL, ppa_control_long_opts, ppa_no_short_opts }, { "status", PPA_CMD_GET_STATUS, ppa_print_status_help, ppa_parse_status_cmd, ppa_do_cmd, ppa_print_status, ppa_no_long_opts, ppa_output_short_opts }, { "setmac", PPA_CMD_SET_IF_MAC, ppa_print_set_mac_help, ppa_parse_set_mac_cmd, ppa_do_cmd, NULL, ppa_if_mac_long_opts, ppa_if_mac_short_opts }, { "getmac", PPA_CMD_GET_IF_MAC, ppa_print_get_mac_help, ppa_parse_get_mac_cmd, ppa_do_cmd, ppa_print_get_mac_cmd, ppa_if_long_opts, ppa_if_output_short_opts }, { "addwan", PPA_CMD_ADD_WAN_IF, ppa_print_add_wan_help, ppa_parse_add_del_if_cmd, ppa_do_cmd, NULL, ppa_if_long_opts, ppa_if_short_opts }, { "addlan", PPA_CMD_ADD_LAN_IF, ppa_print_add_lan_help, ppa_parse_add_del_if_cmd, ppa_do_cmd, NULL, ppa_if_long_opts, ppa_if_short_opts }, { "delwan", PPA_CMD_DEL_WAN_IF, ppa_print_del_wan_help, ppa_parse_add_del_if_cmd, ppa_do_cmd, NULL, ppa_if_long_opts, ppa_if_short_opts }, { "dellan", PPA_CMD_DEL_LAN_IF, ppa_print_del_lan_help, ppa_parse_add_del_if_cmd, ppa_do_cmd, NULL, ppa_if_long_opts, ppa_if_short_opts }, { "getwan", PPA_CMD_GET_WAN_IF, ppa_print_get_wan_help, ppa_parse_simple_cmd, ppa_do_cmd, ppa_print_get_wan_netif_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getlan", PPA_CMD_GET_LAN_IF, ppa_print_get_lan_help, ppa_parse_simple_cmd, ppa_do_cmd, ppa_print_get_lan_netif_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "addbr", PPA_CMD_ADD_MAC_ENTRY, ppa_add_mac_entry_help, ppa_parse_add_mac_entry_cmd, ppa_do_cmd, NULL, ppa_if_mac_long_opts, ppa_if_mac_short_opts }, { "delbr", PPA_CMD_DEL_MAC_ENTRY, ppa_del_mac_entry_help, ppa_parse_del_mac_entry_cmd, ppa_do_cmd, NULL, ppa_mac_long_opts, ppa_mac_short_opts }, { "getbrnum", PPA_CMD_GET_COUNT_MAC, ppa_get_br_count_help, ppa_parse_get_br_count, ppa_do_cmd, ppa_print_get_count_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getbrs", PPA_CMD_GET_ALL_MAC, ppa_get_all_br_help, ppa_parse_simple_cmd, ppa_get_all_br_cmd, NULL, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "setvif", PPA_CMD_SET_VLAN_IF_CFG, ppa_set_vlan_if_cfg_help, ppa_parse_set_vlan_if_cfg_cmd, ppa_do_cmd, NULL, ppa_set_vlan_if_cfg_long_opts, ppa_set_vlan_if_cfg_short_opts }, { "getvif", PPA_CMD_GET_VLAN_IF_CFG, ppa_get_vlan_if_cfg_help, ppa_parse_get_vlan_if_cfg_cmd, ppa_do_cmd, ppa_print_get_vif, ppa_if_long_opts, ppa_if_output_short_opts }, { "addvfilter", PPA_CMD_ADD_VLAN_FILTER_CFG, ppa_add_vlan_filter_help, ppa_parse_add_vlan_filter_cmd, ppa_do_cmd, NULL, ppa_add_vlan_filter_long_opts, ppa_add_vlan_filter_short_opts }, { "delvfilter", PPA_CMD_DEL_VLAN_FILTER_CFG, ppa_del_vlan_filter_help, ppa_parse_del_vlan_filter_cmd, ppa_do_cmd, NULL, ppa_del_vlan_filter_long_opts, ppa_del_vlan_filter_short_opts }, { "getvfilternum", PPA_CMD_GET_COUNT_VLAN_FILTER, ppa_get_vfilter_count_help, ppa_parse_get_vfilter_count, ppa_do_cmd, ppa_print_get_count_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getvfilters", PPA_CMD_GET_ALL_VLAN_FILTER_CFG, ppa_get_all_vlan_filter_help, ppa_parse_simple_cmd, ppa_get_all_vlan_filter_cmd, NULL, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "delallvfilter", PPA_CMD_DEL_ALL_VLAN_FILTER_CFG, ppa_del_all_vfilter_help, ppa_parse_simple_cmd, ppa_do_cmd, NULL, ppa_no_long_opts, ppa_no_short_opts }, { "addmc", PPA_CMD_ADD_MC, ppa_add_mc_help, ppa_parse_add_mc_cmd, ppa_do_cmd, NULL, ppa_mc_add_long_opts, ppa_mc_add_short_opts }, { "getmcnum", PPA_CMD_GET_COUNT_MC_GROUP, ppa_get_mc_count_help, ppa_parse_get_mc_count_cmd, ppa_do_cmd, ppa_print_get_count_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getmcgroups", PPA_CMD_GET_MC_GROUPS, ppa_get_mc_groups_help, ppa_parse_simple_cmd, ppa_get_mc_groups_cmd, NULL, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getmcextra", PPA_CMD_GET_MC_ENTRY, ppa_get_mc_extra_help, ppa_parse_get_mc_extra_cmd, ppa_do_cmd, ppa_print_get_mc_extra_cmd, ppa_get_mc_extra_long_opts, ppa_get_mc_extra_short_opts }, { "setmcextra", PPA_CMD_MODIFY_MC_ENTRY, ppa_set_mc_extra_help, ppa_parse_set_mc_extra_cmd, ppa_do_cmd, NULL, ppa_set_mc_extra_long_opts, ppa_set_mc_extra_short_opts }, { "getlansessionnum", PPA_CMD_GET_COUNT_LAN_SESSION, ppa_get_lan_session_count_help, ppa_parse_get_lan_session_count, ppa_do_cmd, ppa_print_get_count_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getlansessions", PPA_CMD_GET_LAN_SESSIONS, ppa_get_lan_sessions_help, ppa_parse_simple_cmd, ppa_get_lan_sessions_cmd, NULL, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getwansessionnum", PPA_CMD_GET_COUNT_WAN_SESSION, ppa_get_wan_session_count_help, ppa_parse_get_wan_session_count, ppa_do_cmd, ppa_print_get_count_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getwansessions", PPA_CMD_GET_WAN_SESSIONS, ppa_get_wan_sessions_help, ppa_parse_simple_cmd, ppa_get_wan_sessions_cmd, NULL, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getversion", PPA_CMD_GET_VERSION, ppa_get_version_help, ppa_parse_simple_cmd, ppa_do_cmd, ppa_print_get_version_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getvlanrangenum", PPA_CMD_GET_COUNT_WAN_MII0_VLAN_RANGE, ppa_get_wan_mii0_vlan_range_count_help, ppa_parse_get_mc_count_cmd, //share function at present ppa_do_cmd, ppa_print_get_count_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "addvlanrange", PPA_CMD_WAN_MII0_VLAN_RANGE_ADD, ppa_add_wan_mii0_vlan_range_help, ppa_parse_add_wan_mii0_vlan_range_cmd, ppa_do_cmd, NULL, ppa_add_wan_mii0_vlan_range_long_opts, ppa_add_wan_mii0_vlan_range_short_opts, }, { "getvlanranges", PPA_CMD_WAN_MII0_VLAN_RANGE_GET, ppa_get_wan_mii0_all_vlan_range_help, ppa_parse_simple_cmd, ppa_wan_mii0_all_vlan_range_cmd, NULL, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "setbr", // to enable/disable bridge mac learning hook PPA_CMD_BRIDGE_ENABLE, ppa_set_br_help, ppa_set_br_cmd, ppa_do_cmd, NULL, ppa_set_br_long_opts, ppa_set_br_short_opts, }, { "getbrstatus", //get bridge mac learning hook status: enabled or disabled PPA_CMD_GET_BRIDGE_STATUS, ppa_get_br_status_help, ppa_get_br_status_cmd, ppa_do_cmd, ppa_print_get_br_status_cmd, ppa_get_br_status_long_opts, ppa_get_br_status_short_opts, }, #ifdef CONFIG_IFX_PPA_QOS { "getqnum", // get maximum eth1 queue number PPA_CMD_GET_QOS_QUEUE_MAX_NUM, ppa_get_qnum_help, ppa_parse_get_qnum_cmd, ppa_do_cmd, ppa_print_get_qnum_cmd, ppa_get_qnum_long_opts, ppa_get_qnum_short_opts, }, { "getqmib", // get maximum eth1 queue number PPA_CMD_GET_QOS_MIB, ppa_get_qmib_help, ppa_parse_get_qmib_cmd, ppa_get_qmib_do_cmd, NULL, ppa_get_qmib_long_opts, ppa_get_qmib_short_opts, }, #ifdef CONFIG_IFX_PPA_QOS_WFQ { "setctrlwfq", //set wfq to enable/disable PPA_CMD_SET_CTRL_QOS_WFQ, ppa_set_ctrl_wfq_help, ppa_parse_set_ctrl_wfq_cmd, ppa_do_cmd, NULL, ppa_set_ctrl_wfq_long_opts, ppa_set_ctrl_wfq_short_opts, }, { "getctrlwfq", //get wfq control status: PPA_CMD_GET_CTRL_QOS_WFQ, ppa_get_ctrl_wfq_help, ppa_parse_get_ctrl_wfq_cmd, ppa_do_cmd, ppa_print_get_ctrl_wfq_cmd, ppa_get_ctrl_wfq_long_opts, ppa_get_ctrl_wfq_short_opts, }, { "setwfq", //set wfq weight PPA_CMD_SET_QOS_WFQ, ppa_set_wfq_help, ppa_parse_set_wfq_cmd, ppa_do_cmd, NULL, ppa_set_wfq_long_opts, ppa_set_wfq_short_opts, }, { "resetwfq", //reset WFQ weight PPA_CMD_RESET_QOS_WFQ, ppa_reset_wfq_help, ppa_parse_reset_wfq_cmd, ppa_do_cmd, NULL, ppa_reset_wfq_long_opts, ppa_reset_wfq_short_opts, }, { "getwfq", //get WFQ weight PPA_CMD_GET_QOS_WFQ, ppa_get_wfq_help, ppa_parse_get_wfq_cmd, ppa_get_wfq_do_cmd, NULL, ppa_get_wfq_long_opts, ppa_get_wfq_short_opts, }, #endif //endof CONFIG_IFX_PPA_QOS_WFQ #ifdef CONFIG_IFX_PPA_QOS_RATE_SHAPING { "setctrlrate", //set rate shaping to enable/disable PPA_CMD_SET_CTRL_QOS_RATE, ppa_set_ctrl_rate_help, ppa_parse_set_ctrl_rate_cmd, ppa_do_cmd, NULL, ppa_set_ctrl_rate_long_opts, ppa_set_ctrl_rate_short_opts, }, { "getctrlrate", //get rate shaping control status: PPA_CMD_GET_CTRL_QOS_RATE, ppa_get_ctrl_rate_help, ppa_parse_get_ctrl_rate_cmd, ppa_do_cmd, ppa_print_get_ctrl_rate_cmd, ppa_get_ctrl_rate_long_opts, ppa_get_ctrl_rate_short_opts, }, { "setrate", //set rate shaping PPA_CMD_SET_QOS_RATE, ppa_set_rate_help, ppa_set_rate_cmd, ppa_do_cmd, NULL, ppa_set_rate_long_opts, ppa_set_rate_short_opts, }, { "resetrate", //reset rate shaping PPA_CMD_RESET_QOS_RATE, ppa_reset_rate_help, ppa_parse_reset_rate_cmd, ppa_do_cmd, NULL, ppa_reset_rate_long_opts, ppa_reset_rate_short_opts, }, { "getrate", //get ate shaping PPA_CMD_GET_QOS_RATE, ppa_get_rate_help, ppa_parse_get_rate_cmd, ppa_get_rate_do_cmd, NULL, ppa_get_rate_long_opts, ppa_get_rate_short_opts, }, #endif //endof CONFIG_IFX_PPA_QOS_RATE_SHAPING #endif //end if CONFIG_IFX_PPA_QOS { "gethooknum", //get all registered hook number PPA_CMD_GET_HOOK_COUNT, ppa_get_hook_count_help, ppa_parse_simple_cmd, ppa_do_cmd, ppa_print_get_hook_count_cmd, ppa_get_hook_long_opts, ppa_get_hook_short_opts, }, { "gethooklist", //get all registered hook list PPA_CMD_GET_HOOK_LIST, ppa_get_hook_list_help, ppa_parse_simple_cmd, ppa_get_hook_list_cmd, NULL, ppa_get_hook_list_long_opts, ppa_get_hook_list_short_opts, }, { "sethook", //enable/disable one registered hook PPA_CMD_SET_HOOK, ppa_set_hook_help, ppa_parse_set_hook_cmd, ppa_do_cmd, NULL, ppa_set_hook_long_opts, ppa_set_hook_short_opts, }, { "r", // read memory value PPA_CMD_READ_MEM, ppa_get_mem_help, ppa_parse_get_mem_cmd, ppa_get_mem_cmd, NULL, ppa_get_mem_long_opts, ppa_get_mem_short_opts, }, { "w", // //set memory value PPA_CMD_SET_MEM, ppa_set_mem_help, ppa_parse_set_mem_cmd, ppa_do_cmd, NULL, ppa_set_mem_long_opts, ppa_set_mem_short_opts, }, #ifdef CONFIG_IFX_PPA_MFE { "setmf", //enable/disable multiple field feature PPA_CMD_ENABLE_MULTIFIELD, ppa_set_mf_help, ppa_parse_set_mf_cmd, ppa_do_cmd, NULL, ppa_set_mf_long_opts, ppa_set_mf_short_opts, }, { "getmf", //get multiple field feature status: enabled or disabled PPA_CMD_GET_MULTIFIELD_STATUS, ppa_get_mf_status_help, ppa_parse_simple_cmd, ppa_do_cmd, ppa_print_get_mf_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "getmfmaxnum", //get all multiple field flows information PPA_CMD_GET_MULTIFIELD_ENTRY_MAX, ppa_get_mf_count_help, ppa_parse_simple_cmd, ppa_do_cmd, ppa_print_get_mf_count_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { "addmfflow", //add one multiple field flow PPA_CMD_ADD_MULTIFIELD, ppa_add_mf_flow_help, ppa_parse_add_mf_flow_cmd, ppa_do_cmd, ppa_print_add_mf_flow_cmd, ppa_add_mf_flow_long_opts, ppa_add_mf_flow_short_opts, }, { "getmfflow", //del one multiple field flow PPA_CMD_GET_MULTIFIELD, ppa_get_mf_flow_help, ppa_parse_get_mf_flow_cmd, ppa_get_mf_flow_cmd, //note, here dont use ppa_do_cmd for we need to get all flow info via multiple ioctl, not just one NULL, ppa_get_mf_flow_long_opts, ppa_get_mf_flow_short_opts, }, { "delmfflow", // //get maximum eth1 queue number PPA_CMD_DEL_MULTIFIELD, ppa_del_mf_flow_help, ppa_parse_add_mf_flow_cmd, /*share same function with addmflow */ ppa_do_cmd, NULL, ppa_add_mf_flow_long_opts, ppa_add_mf_flow_short_opts, }, { "delmfflowindex", // //get maximum eth1 queue number PPA_CMD_DEL_MULTIFIELD_VIA_INDEX, ppa_del_mf_flow_index_help, ppa_parse_del_mf_flow_index_cmd, ppa_do_cmd, NULL, ppa_del_mf_flow_index_long_opts, ppa_add_mf_flow_short_opts, }, #endif { "getportid", // get the port id PPA_CMD_GET_PORTID, ppa_get_portid_help, ppa_parse_get_portid_cmd, ppa_do_cmd, ppa_print_get_portid_cmd, ppa_get_portid_long_opts, ppa_get_portid_short_opts }, { "size", //we had better put this command at last since we hide the command usage. PPA_CMD_GET_SIZE, ppa_get_sizeof_help, ppa_parse_simple_cmd, ppa_do_cmd, ppa_print_get_sizeof_cmd, ppa_get_simple_long_opts, ppa_get_simple_short_opts }, { NULL, 0, NULL, NULL, NULL, NULL, NULL } }; /* ==================================================================================== command: ppa_cmd_help Function description: prints help text options: argv ==================================================================================== */ static void ppa_print_help(void) { PPA_COMMAND *pcmd; IFX_PPACMD_PRINT("Usage: %s {options} \n", PPA_CMD_NAME); IFX_PPACMD_PRINT("Commands: \n"); for(pcmd = ppa_cmd; pcmd->name != NULL; pcmd++) if(pcmd->print_help) { IFX_PPACMD_PRINT("\t"); (*pcmd->print_help)(1); } #if PPACMD_DEBUG IFX_PPACMD_PRINT("\tNote: Create a file %s will enable ppacmd debug mode !\n", debug_enable_file ); #endif return; } /* ==================================================================================== command: ppa_cmd_help Function description: prints help text options: argv ==================================================================================== */ static void ppa_print_cmd_help(PPA_COMMAND *pcmd) { if(pcmd->print_help) { IFX_PPACMD_PRINT("Usage: %s ", PPA_CMD_NAME); (*pcmd->print_help)(0); } return; } /* =============================================================================== Command processing functions =============================================================================== */ /* =========================================================================================== =========================================================================================== */ static int get_ppa_cmd(char *cmd_str, PPA_COMMAND **pcmd) { int i; // Locate the command where the name matches the cmd_str and return // the index in the command array. for (i = 0; ppa_cmd[i].name; i++) { if (strcmp(cmd_str, ppa_cmd[i].name) == 0) { *pcmd = &ppa_cmd[i]; return PPA_CMD_OK; } } return PPA_CMD_ERR; } /* =========================================================================================== =========================================================================================== */ static int ppa_parse_cmd(int ac, char **av, PPA_COMMAND *pcmd, PPA_CMD_OPTS *popts) { int opt, opt_idx, ret = PPA_CMD_OK; int num_opts; // Fill out the PPA_CMD_OPTS array with the option value and argument for // each option that is found. If option is help, display command help and // do not process command. for (num_opts = 0; num_opts < PPA_MAX_CMD_OPTS; num_opts++) { opt = getopt_long(ac - 1, av + 1, pcmd->short_opts, pcmd->long_opts, &opt_idx); if (opt != -1) { if (opt == 'h') // help { ret = PPA_CMD_HELP; return ret; } else if (opt == '?') // missing argument or invalid option { ret = PPA_CMD_ERR; break; } popts->opt = opt; popts->optarg = optarg; popts++; } else break; } return ret; } /* =========================================================================================== =========================================================================================== */ static int ppa_parse_cmd_line(int ac, char **av, PPA_COMMAND **pcmd, PPA_CMD_DATA **data) { int ret = PPA_CMD_ERR; PPA_CMD_DATA *pdata = NULL; PPA_CMD_OPTS *popts = NULL; if ((ac <= 1) || (av == NULL)) { return PPA_CMD_HELP; } pdata = malloc(sizeof(PPA_CMD_DATA)); if (pdata == NULL) return PPA_CMD_NOT_AVAIL; memset(pdata, 0, sizeof(PPA_CMD_DATA)); popts = malloc(sizeof(PPA_CMD_OPTS)*PPA_MAX_CMD_OPTS); if (popts == NULL) { free(pdata); return PPA_CMD_NOT_AVAIL; } memset(popts, 0, sizeof(PPA_CMD_OPTS)*PPA_MAX_CMD_OPTS); ret = get_ppa_cmd(av[1], pcmd); if (ret == PPA_CMD_OK) { ret = ppa_parse_cmd(ac, av, *pcmd, popts); if ( ret == PPA_CMD_OK ) { ret = (*pcmd)->parse_options(popts,pdata); if ( ret == PPA_CMD_OK ) *data = pdata; } else { IFX_PPACMD_PRINT("Wrong parameter\n"); ret = PPA_CMD_HELP; } } else { IFX_PPACMD_PRINT("Unknown commands: %s\n", av[1]); } free(popts); return ret; } /* =========================================================================================== =========================================================================================== */ int main(int argc, char** argv) { int ret; PPA_CMD_DATA *pdata = NULL; PPA_COMMAND *pcmd; opterr = 0; //suppress option error messages #ifdef PPACMD_DEBUG { FILE *fp; fp = fopen(debug_enable_file, "r"); if( fp != NULL ) { enable_debug = 1; fclose(fp); } } #endif if( argc == 1) { ppa_print_help(); return 0; } ret = ppa_parse_cmd_line (argc, argv, &pcmd, &pdata); if (ret == PPA_CMD_OK) { if (pcmd->do_command) { ret = pcmd->do_command(pcmd,pdata); if (ret == PPA_CMD_OK && pcmd->print_data) pcmd->print_data(pdata); } free(pdata); } else if (ret == PPA_CMD_HELP) { ppa_print_cmd_help(pcmd); } return ret; }