1*2e192b24SSimon Glass /* 2*2e192b24SSimon Glass * Copyright 2015 Freescale Semiconductor, Inc. 3*2e192b24SSimon Glass * 4*2e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 5*2e192b24SSimon Glass * 6*2e192b24SSimon Glass * Ethernet Switch commands 7*2e192b24SSimon Glass */ 8*2e192b24SSimon Glass 9*2e192b24SSimon Glass #include <common.h> 10*2e192b24SSimon Glass #include <command.h> 11*2e192b24SSimon Glass #include <errno.h> 12*2e192b24SSimon Glass #include <env_flags.h> 13*2e192b24SSimon Glass #include <ethsw.h> 14*2e192b24SSimon Glass 15*2e192b24SSimon Glass static const char *ethsw_name; 16*2e192b24SSimon Glass 17*2e192b24SSimon Glass #define ETHSW_PORT_STATS_HELP "ethsw [port <port_no>] statistics " \ 18*2e192b24SSimon Glass "{ [help] | [clear] } - show an l2 switch port's statistics" 19*2e192b24SSimon Glass 20*2e192b24SSimon Glass static int ethsw_port_stats_help_key_func(struct ethsw_command_def *parsed_cmd) 21*2e192b24SSimon Glass { 22*2e192b24SSimon Glass printf(ETHSW_PORT_STATS_HELP"\n"); 23*2e192b24SSimon Glass 24*2e192b24SSimon Glass return CMD_RET_SUCCESS; 25*2e192b24SSimon Glass } 26*2e192b24SSimon Glass 27*2e192b24SSimon Glass #define ETHSW_LEARN_HELP "ethsw [port <port_no>] learning " \ 28*2e192b24SSimon Glass "{ [help] | show | auto | disable } " \ 29*2e192b24SSimon Glass "- enable/disable/show learning configuration on a port" 30*2e192b24SSimon Glass 31*2e192b24SSimon Glass static int ethsw_learn_help_key_func(struct ethsw_command_def *parsed_cmd) 32*2e192b24SSimon Glass { 33*2e192b24SSimon Glass printf(ETHSW_LEARN_HELP"\n"); 34*2e192b24SSimon Glass 35*2e192b24SSimon Glass return CMD_RET_SUCCESS; 36*2e192b24SSimon Glass } 37*2e192b24SSimon Glass 38*2e192b24SSimon Glass #define ETHSW_FDB_HELP "ethsw [port <port_no>] [vlan <vid>] fdb " \ 39*2e192b24SSimon Glass "{ [help] | show | flush | { add | del } <mac> } " \ 40*2e192b24SSimon Glass "- Add/delete a mac entry in FDB; use show to see FDB entries; " \ 41*2e192b24SSimon Glass "if vlan <vid> is missing, VID 1 will be used" 42*2e192b24SSimon Glass 43*2e192b24SSimon Glass static int ethsw_fdb_help_key_func(struct ethsw_command_def *parsed_cmd) 44*2e192b24SSimon Glass { 45*2e192b24SSimon Glass printf(ETHSW_FDB_HELP"\n"); 46*2e192b24SSimon Glass 47*2e192b24SSimon Glass return CMD_RET_SUCCESS; 48*2e192b24SSimon Glass } 49*2e192b24SSimon Glass 50*2e192b24SSimon Glass #define ETHSW_PVID_HELP "ethsw [port <port_no>] " \ 51*2e192b24SSimon Glass "pvid { [help] | show | <pvid> } " \ 52*2e192b24SSimon Glass "- set/show PVID (ingress and egress VLAN tagging) for a port" 53*2e192b24SSimon Glass 54*2e192b24SSimon Glass static int ethsw_pvid_help_key_func(struct ethsw_command_def *parsed_cmd) 55*2e192b24SSimon Glass { 56*2e192b24SSimon Glass printf(ETHSW_PVID_HELP"\n"); 57*2e192b24SSimon Glass 58*2e192b24SSimon Glass return CMD_RET_SUCCESS; 59*2e192b24SSimon Glass } 60*2e192b24SSimon Glass 61*2e192b24SSimon Glass #define ETHSW_VLAN_HELP "ethsw [port <port_no>] vlan " \ 62*2e192b24SSimon Glass "{ [help] | show | add <vid> | del <vid> } " \ 63*2e192b24SSimon Glass "- add a VLAN to a port (VLAN members)" 64*2e192b24SSimon Glass 65*2e192b24SSimon Glass static int ethsw_vlan_help_key_func(struct ethsw_command_def *parsed_cmd) 66*2e192b24SSimon Glass { 67*2e192b24SSimon Glass printf(ETHSW_VLAN_HELP"\n"); 68*2e192b24SSimon Glass 69*2e192b24SSimon Glass return CMD_RET_SUCCESS; 70*2e192b24SSimon Glass } 71*2e192b24SSimon Glass 72*2e192b24SSimon Glass #define ETHSW_PORT_UNTAG_HELP "ethsw [port <port_no>] untagged " \ 73*2e192b24SSimon Glass "{ [help] | show | all | none | pvid } " \ 74*2e192b24SSimon Glass " - set egress tagging mod for a port" 75*2e192b24SSimon Glass 76*2e192b24SSimon Glass static int ethsw_port_untag_help_key_func(struct ethsw_command_def *parsed_cmd) 77*2e192b24SSimon Glass { 78*2e192b24SSimon Glass printf(ETHSW_PORT_UNTAG_HELP"\n"); 79*2e192b24SSimon Glass 80*2e192b24SSimon Glass return CMD_RET_SUCCESS; 81*2e192b24SSimon Glass } 82*2e192b24SSimon Glass 83*2e192b24SSimon Glass #define ETHSW_EGR_VLAN_TAG_HELP "ethsw [port <port_no>] egress tag " \ 84*2e192b24SSimon Glass "{ [help] | show | pvid | classified } " \ 85*2e192b24SSimon Glass "- Configure VID source for egress tag. " \ 86*2e192b24SSimon Glass "Tag's VID could be the frame's classified VID or the PVID of the port" 87*2e192b24SSimon Glass 88*2e192b24SSimon Glass static int ethsw_egr_tag_help_key_func(struct ethsw_command_def *parsed_cmd) 89*2e192b24SSimon Glass { 90*2e192b24SSimon Glass printf(ETHSW_EGR_VLAN_TAG_HELP"\n"); 91*2e192b24SSimon Glass 92*2e192b24SSimon Glass return CMD_RET_SUCCESS; 93*2e192b24SSimon Glass } 94*2e192b24SSimon Glass 95*2e192b24SSimon Glass #define ETHSW_VLAN_FDB_HELP "ethsw vlan fdb " \ 96*2e192b24SSimon Glass "{ [help] | show | shared | private } " \ 97*2e192b24SSimon Glass "- make VLAN learning shared or private" 98*2e192b24SSimon Glass 99*2e192b24SSimon Glass static int ethsw_vlan_learn_help_key_func(struct ethsw_command_def *parsed_cmd) 100*2e192b24SSimon Glass { 101*2e192b24SSimon Glass printf(ETHSW_VLAN_FDB_HELP"\n"); 102*2e192b24SSimon Glass 103*2e192b24SSimon Glass return CMD_RET_SUCCESS; 104*2e192b24SSimon Glass } 105*2e192b24SSimon Glass 106*2e192b24SSimon Glass #define ETHSW_PORT_INGR_FLTR_HELP "ethsw [port <port_no>] ingress filtering" \ 107*2e192b24SSimon Glass " { [help] | show | enable | disable } " \ 108*2e192b24SSimon Glass "- enable/disable VLAN ingress filtering on port" 109*2e192b24SSimon Glass 110*2e192b24SSimon Glass static int ethsw_ingr_fltr_help_key_func(struct ethsw_command_def *parsed_cmd) 111*2e192b24SSimon Glass { 112*2e192b24SSimon Glass printf(ETHSW_PORT_INGR_FLTR_HELP"\n"); 113*2e192b24SSimon Glass 114*2e192b24SSimon Glass return CMD_RET_SUCCESS; 115*2e192b24SSimon Glass } 116*2e192b24SSimon Glass 117*2e192b24SSimon Glass static struct keywords_to_function { 118*2e192b24SSimon Glass enum ethsw_keyword_id cmd_keyword[ETHSW_MAX_CMD_PARAMS]; 119*2e192b24SSimon Glass int cmd_func_offset; 120*2e192b24SSimon Glass int (*keyword_function)(struct ethsw_command_def *parsed_cmd); 121*2e192b24SSimon Glass } ethsw_cmd_def[] = { 122*2e192b24SSimon Glass { 123*2e192b24SSimon Glass .cmd_keyword = { 124*2e192b24SSimon Glass ethsw_id_enable, 125*2e192b24SSimon Glass ethsw_id_key_end, 126*2e192b24SSimon Glass }, 127*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 128*2e192b24SSimon Glass port_enable), 129*2e192b24SSimon Glass .keyword_function = NULL, 130*2e192b24SSimon Glass }, { 131*2e192b24SSimon Glass .cmd_keyword = { 132*2e192b24SSimon Glass ethsw_id_disable, 133*2e192b24SSimon Glass ethsw_id_key_end, 134*2e192b24SSimon Glass }, 135*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 136*2e192b24SSimon Glass port_disable), 137*2e192b24SSimon Glass .keyword_function = NULL, 138*2e192b24SSimon Glass }, { 139*2e192b24SSimon Glass .cmd_keyword = { 140*2e192b24SSimon Glass ethsw_id_show, 141*2e192b24SSimon Glass ethsw_id_key_end, 142*2e192b24SSimon Glass }, 143*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 144*2e192b24SSimon Glass port_show), 145*2e192b24SSimon Glass .keyword_function = NULL, 146*2e192b24SSimon Glass }, { 147*2e192b24SSimon Glass .cmd_keyword = { 148*2e192b24SSimon Glass ethsw_id_statistics, 149*2e192b24SSimon Glass ethsw_id_help, 150*2e192b24SSimon Glass ethsw_id_key_end, 151*2e192b24SSimon Glass }, 152*2e192b24SSimon Glass .cmd_func_offset = -1, 153*2e192b24SSimon Glass .keyword_function = ðsw_port_stats_help_key_func, 154*2e192b24SSimon Glass }, { 155*2e192b24SSimon Glass .cmd_keyword = { 156*2e192b24SSimon Glass ethsw_id_statistics, 157*2e192b24SSimon Glass ethsw_id_key_end, 158*2e192b24SSimon Glass }, 159*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 160*2e192b24SSimon Glass port_stats), 161*2e192b24SSimon Glass .keyword_function = NULL, 162*2e192b24SSimon Glass }, { 163*2e192b24SSimon Glass .cmd_keyword = { 164*2e192b24SSimon Glass ethsw_id_statistics, 165*2e192b24SSimon Glass ethsw_id_clear, 166*2e192b24SSimon Glass ethsw_id_key_end, 167*2e192b24SSimon Glass }, 168*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 169*2e192b24SSimon Glass port_stats_clear), 170*2e192b24SSimon Glass .keyword_function = NULL, 171*2e192b24SSimon Glass }, { 172*2e192b24SSimon Glass .cmd_keyword = { 173*2e192b24SSimon Glass ethsw_id_learning, 174*2e192b24SSimon Glass ethsw_id_key_end, 175*2e192b24SSimon Glass }, 176*2e192b24SSimon Glass .cmd_func_offset = -1, 177*2e192b24SSimon Glass .keyword_function = ðsw_learn_help_key_func, 178*2e192b24SSimon Glass }, { 179*2e192b24SSimon Glass .cmd_keyword = { 180*2e192b24SSimon Glass ethsw_id_learning, 181*2e192b24SSimon Glass ethsw_id_help, 182*2e192b24SSimon Glass ethsw_id_key_end, 183*2e192b24SSimon Glass }, 184*2e192b24SSimon Glass .cmd_func_offset = -1, 185*2e192b24SSimon Glass .keyword_function = ðsw_learn_help_key_func, 186*2e192b24SSimon Glass }, { 187*2e192b24SSimon Glass .cmd_keyword = { 188*2e192b24SSimon Glass ethsw_id_learning, 189*2e192b24SSimon Glass ethsw_id_show, 190*2e192b24SSimon Glass ethsw_id_key_end, 191*2e192b24SSimon Glass }, 192*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 193*2e192b24SSimon Glass port_learn_show), 194*2e192b24SSimon Glass .keyword_function = NULL, 195*2e192b24SSimon Glass }, { 196*2e192b24SSimon Glass .cmd_keyword = { 197*2e192b24SSimon Glass ethsw_id_learning, 198*2e192b24SSimon Glass ethsw_id_auto, 199*2e192b24SSimon Glass ethsw_id_key_end, 200*2e192b24SSimon Glass }, 201*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 202*2e192b24SSimon Glass port_learn), 203*2e192b24SSimon Glass .keyword_function = NULL, 204*2e192b24SSimon Glass }, { 205*2e192b24SSimon Glass .cmd_keyword = { 206*2e192b24SSimon Glass ethsw_id_learning, 207*2e192b24SSimon Glass ethsw_id_disable, 208*2e192b24SSimon Glass ethsw_id_key_end, 209*2e192b24SSimon Glass }, 210*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 211*2e192b24SSimon Glass port_learn), 212*2e192b24SSimon Glass .keyword_function = NULL, 213*2e192b24SSimon Glass }, { 214*2e192b24SSimon Glass .cmd_keyword = { 215*2e192b24SSimon Glass ethsw_id_fdb, 216*2e192b24SSimon Glass ethsw_id_key_end, 217*2e192b24SSimon Glass }, 218*2e192b24SSimon Glass .cmd_func_offset = -1, 219*2e192b24SSimon Glass .keyword_function = ðsw_fdb_help_key_func, 220*2e192b24SSimon Glass }, { 221*2e192b24SSimon Glass .cmd_keyword = { 222*2e192b24SSimon Glass ethsw_id_fdb, 223*2e192b24SSimon Glass ethsw_id_help, 224*2e192b24SSimon Glass ethsw_id_key_end, 225*2e192b24SSimon Glass }, 226*2e192b24SSimon Glass .cmd_func_offset = -1, 227*2e192b24SSimon Glass .keyword_function = ðsw_fdb_help_key_func, 228*2e192b24SSimon Glass }, { 229*2e192b24SSimon Glass .cmd_keyword = { 230*2e192b24SSimon Glass ethsw_id_fdb, 231*2e192b24SSimon Glass ethsw_id_show, 232*2e192b24SSimon Glass ethsw_id_key_end, 233*2e192b24SSimon Glass }, 234*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 235*2e192b24SSimon Glass fdb_show), 236*2e192b24SSimon Glass .keyword_function = NULL, 237*2e192b24SSimon Glass }, { 238*2e192b24SSimon Glass .cmd_keyword = { 239*2e192b24SSimon Glass ethsw_id_fdb, 240*2e192b24SSimon Glass ethsw_id_flush, 241*2e192b24SSimon Glass ethsw_id_key_end, 242*2e192b24SSimon Glass }, 243*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 244*2e192b24SSimon Glass fdb_flush), 245*2e192b24SSimon Glass .keyword_function = NULL, 246*2e192b24SSimon Glass }, { 247*2e192b24SSimon Glass .cmd_keyword = { 248*2e192b24SSimon Glass ethsw_id_fdb, 249*2e192b24SSimon Glass ethsw_id_add, 250*2e192b24SSimon Glass ethsw_id_add_del_mac, 251*2e192b24SSimon Glass ethsw_id_key_end, 252*2e192b24SSimon Glass }, 253*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 254*2e192b24SSimon Glass fdb_entry_add), 255*2e192b24SSimon Glass .keyword_function = NULL, 256*2e192b24SSimon Glass }, { 257*2e192b24SSimon Glass .cmd_keyword = { 258*2e192b24SSimon Glass ethsw_id_fdb, 259*2e192b24SSimon Glass ethsw_id_del, 260*2e192b24SSimon Glass ethsw_id_add_del_mac, 261*2e192b24SSimon Glass ethsw_id_key_end, 262*2e192b24SSimon Glass }, 263*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 264*2e192b24SSimon Glass fdb_entry_del), 265*2e192b24SSimon Glass .keyword_function = NULL, 266*2e192b24SSimon Glass }, { 267*2e192b24SSimon Glass .cmd_keyword = { 268*2e192b24SSimon Glass ethsw_id_pvid, 269*2e192b24SSimon Glass ethsw_id_key_end, 270*2e192b24SSimon Glass }, 271*2e192b24SSimon Glass .cmd_func_offset = -1, 272*2e192b24SSimon Glass .keyword_function = ðsw_pvid_help_key_func, 273*2e192b24SSimon Glass }, { 274*2e192b24SSimon Glass .cmd_keyword = { 275*2e192b24SSimon Glass ethsw_id_pvid, 276*2e192b24SSimon Glass ethsw_id_help, 277*2e192b24SSimon Glass ethsw_id_key_end, 278*2e192b24SSimon Glass }, 279*2e192b24SSimon Glass .cmd_func_offset = -1, 280*2e192b24SSimon Glass .keyword_function = ðsw_pvid_help_key_func, 281*2e192b24SSimon Glass }, { 282*2e192b24SSimon Glass .cmd_keyword = { 283*2e192b24SSimon Glass ethsw_id_pvid, 284*2e192b24SSimon Glass ethsw_id_show, 285*2e192b24SSimon Glass ethsw_id_key_end, 286*2e192b24SSimon Glass }, 287*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 288*2e192b24SSimon Glass pvid_show), 289*2e192b24SSimon Glass .keyword_function = NULL, 290*2e192b24SSimon Glass }, { 291*2e192b24SSimon Glass .cmd_keyword = { 292*2e192b24SSimon Glass ethsw_id_pvid, 293*2e192b24SSimon Glass ethsw_id_pvid_no, 294*2e192b24SSimon Glass ethsw_id_key_end, 295*2e192b24SSimon Glass }, 296*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 297*2e192b24SSimon Glass pvid_set), 298*2e192b24SSimon Glass .keyword_function = NULL, 299*2e192b24SSimon Glass }, { 300*2e192b24SSimon Glass .cmd_keyword = { 301*2e192b24SSimon Glass ethsw_id_vlan, 302*2e192b24SSimon Glass ethsw_id_key_end, 303*2e192b24SSimon Glass }, 304*2e192b24SSimon Glass .cmd_func_offset = -1, 305*2e192b24SSimon Glass .keyword_function = ðsw_vlan_help_key_func, 306*2e192b24SSimon Glass }, { 307*2e192b24SSimon Glass .cmd_keyword = { 308*2e192b24SSimon Glass ethsw_id_vlan, 309*2e192b24SSimon Glass ethsw_id_help, 310*2e192b24SSimon Glass ethsw_id_key_end, 311*2e192b24SSimon Glass }, 312*2e192b24SSimon Glass .cmd_func_offset = -1, 313*2e192b24SSimon Glass .keyword_function = ðsw_vlan_help_key_func, 314*2e192b24SSimon Glass }, { 315*2e192b24SSimon Glass .cmd_keyword = { 316*2e192b24SSimon Glass ethsw_id_vlan, 317*2e192b24SSimon Glass ethsw_id_show, 318*2e192b24SSimon Glass ethsw_id_key_end, 319*2e192b24SSimon Glass }, 320*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 321*2e192b24SSimon Glass vlan_show), 322*2e192b24SSimon Glass .keyword_function = NULL, 323*2e192b24SSimon Glass }, { 324*2e192b24SSimon Glass .cmd_keyword = { 325*2e192b24SSimon Glass ethsw_id_vlan, 326*2e192b24SSimon Glass ethsw_id_add, 327*2e192b24SSimon Glass ethsw_id_add_del_no, 328*2e192b24SSimon Glass ethsw_id_key_end, 329*2e192b24SSimon Glass }, 330*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 331*2e192b24SSimon Glass vlan_set), 332*2e192b24SSimon Glass .keyword_function = NULL, 333*2e192b24SSimon Glass }, { 334*2e192b24SSimon Glass .cmd_keyword = { 335*2e192b24SSimon Glass ethsw_id_vlan, 336*2e192b24SSimon Glass ethsw_id_del, 337*2e192b24SSimon Glass ethsw_id_add_del_no, 338*2e192b24SSimon Glass ethsw_id_key_end, 339*2e192b24SSimon Glass }, 340*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 341*2e192b24SSimon Glass vlan_set), 342*2e192b24SSimon Glass .keyword_function = NULL, 343*2e192b24SSimon Glass }, { 344*2e192b24SSimon Glass .cmd_keyword = { 345*2e192b24SSimon Glass ethsw_id_untagged, 346*2e192b24SSimon Glass ethsw_id_key_end, 347*2e192b24SSimon Glass }, 348*2e192b24SSimon Glass .cmd_func_offset = -1, 349*2e192b24SSimon Glass .keyword_function = ðsw_port_untag_help_key_func, 350*2e192b24SSimon Glass }, { 351*2e192b24SSimon Glass .cmd_keyword = { 352*2e192b24SSimon Glass ethsw_id_untagged, 353*2e192b24SSimon Glass ethsw_id_help, 354*2e192b24SSimon Glass ethsw_id_key_end, 355*2e192b24SSimon Glass }, 356*2e192b24SSimon Glass .cmd_func_offset = -1, 357*2e192b24SSimon Glass .keyword_function = ðsw_port_untag_help_key_func, 358*2e192b24SSimon Glass }, { 359*2e192b24SSimon Glass .cmd_keyword = { 360*2e192b24SSimon Glass ethsw_id_untagged, 361*2e192b24SSimon Glass ethsw_id_show, 362*2e192b24SSimon Glass ethsw_id_key_end, 363*2e192b24SSimon Glass }, 364*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 365*2e192b24SSimon Glass port_untag_show), 366*2e192b24SSimon Glass .keyword_function = NULL, 367*2e192b24SSimon Glass }, { 368*2e192b24SSimon Glass .cmd_keyword = { 369*2e192b24SSimon Glass ethsw_id_untagged, 370*2e192b24SSimon Glass ethsw_id_all, 371*2e192b24SSimon Glass ethsw_id_key_end, 372*2e192b24SSimon Glass }, 373*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 374*2e192b24SSimon Glass port_untag_set), 375*2e192b24SSimon Glass .keyword_function = NULL, 376*2e192b24SSimon Glass }, { 377*2e192b24SSimon Glass .cmd_keyword = { 378*2e192b24SSimon Glass ethsw_id_untagged, 379*2e192b24SSimon Glass ethsw_id_none, 380*2e192b24SSimon Glass ethsw_id_key_end, 381*2e192b24SSimon Glass }, 382*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 383*2e192b24SSimon Glass port_untag_set), 384*2e192b24SSimon Glass .keyword_function = NULL, 385*2e192b24SSimon Glass }, { 386*2e192b24SSimon Glass .cmd_keyword = { 387*2e192b24SSimon Glass ethsw_id_untagged, 388*2e192b24SSimon Glass ethsw_id_pvid, 389*2e192b24SSimon Glass ethsw_id_key_end, 390*2e192b24SSimon Glass }, 391*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 392*2e192b24SSimon Glass port_untag_set), 393*2e192b24SSimon Glass .keyword_function = NULL, 394*2e192b24SSimon Glass }, { 395*2e192b24SSimon Glass .cmd_keyword = { 396*2e192b24SSimon Glass ethsw_id_egress, 397*2e192b24SSimon Glass ethsw_id_tag, 398*2e192b24SSimon Glass ethsw_id_key_end, 399*2e192b24SSimon Glass }, 400*2e192b24SSimon Glass .cmd_func_offset = -1, 401*2e192b24SSimon Glass .keyword_function = ðsw_egr_tag_help_key_func, 402*2e192b24SSimon Glass }, { 403*2e192b24SSimon Glass .cmd_keyword = { 404*2e192b24SSimon Glass ethsw_id_egress, 405*2e192b24SSimon Glass ethsw_id_tag, 406*2e192b24SSimon Glass ethsw_id_help, 407*2e192b24SSimon Glass ethsw_id_key_end, 408*2e192b24SSimon Glass }, 409*2e192b24SSimon Glass .cmd_func_offset = -1, 410*2e192b24SSimon Glass .keyword_function = ðsw_egr_tag_help_key_func, 411*2e192b24SSimon Glass }, { 412*2e192b24SSimon Glass .cmd_keyword = { 413*2e192b24SSimon Glass ethsw_id_egress, 414*2e192b24SSimon Glass ethsw_id_tag, 415*2e192b24SSimon Glass ethsw_id_show, 416*2e192b24SSimon Glass ethsw_id_key_end, 417*2e192b24SSimon Glass }, 418*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 419*2e192b24SSimon Glass port_egr_vlan_show), 420*2e192b24SSimon Glass .keyword_function = NULL, 421*2e192b24SSimon Glass }, { 422*2e192b24SSimon Glass .cmd_keyword = { 423*2e192b24SSimon Glass ethsw_id_egress, 424*2e192b24SSimon Glass ethsw_id_tag, 425*2e192b24SSimon Glass ethsw_id_pvid, 426*2e192b24SSimon Glass ethsw_id_key_end, 427*2e192b24SSimon Glass }, 428*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 429*2e192b24SSimon Glass port_egr_vlan_set), 430*2e192b24SSimon Glass .keyword_function = NULL, 431*2e192b24SSimon Glass }, { 432*2e192b24SSimon Glass .cmd_keyword = { 433*2e192b24SSimon Glass ethsw_id_egress, 434*2e192b24SSimon Glass ethsw_id_tag, 435*2e192b24SSimon Glass ethsw_id_classified, 436*2e192b24SSimon Glass ethsw_id_key_end, 437*2e192b24SSimon Glass }, 438*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 439*2e192b24SSimon Glass port_egr_vlan_set), 440*2e192b24SSimon Glass .keyword_function = NULL, 441*2e192b24SSimon Glass }, { 442*2e192b24SSimon Glass .cmd_keyword = { 443*2e192b24SSimon Glass ethsw_id_vlan, 444*2e192b24SSimon Glass ethsw_id_fdb, 445*2e192b24SSimon Glass ethsw_id_key_end, 446*2e192b24SSimon Glass }, 447*2e192b24SSimon Glass .cmd_func_offset = -1, 448*2e192b24SSimon Glass .keyword_function = ðsw_vlan_learn_help_key_func, 449*2e192b24SSimon Glass }, { 450*2e192b24SSimon Glass .cmd_keyword = { 451*2e192b24SSimon Glass ethsw_id_vlan, 452*2e192b24SSimon Glass ethsw_id_fdb, 453*2e192b24SSimon Glass ethsw_id_help, 454*2e192b24SSimon Glass ethsw_id_key_end, 455*2e192b24SSimon Glass }, 456*2e192b24SSimon Glass .cmd_func_offset = -1, 457*2e192b24SSimon Glass .keyword_function = ðsw_vlan_learn_help_key_func, 458*2e192b24SSimon Glass }, { 459*2e192b24SSimon Glass .cmd_keyword = { 460*2e192b24SSimon Glass ethsw_id_vlan, 461*2e192b24SSimon Glass ethsw_id_fdb, 462*2e192b24SSimon Glass ethsw_id_show, 463*2e192b24SSimon Glass ethsw_id_key_end, 464*2e192b24SSimon Glass }, 465*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 466*2e192b24SSimon Glass vlan_learn_show), 467*2e192b24SSimon Glass .keyword_function = NULL, 468*2e192b24SSimon Glass }, { 469*2e192b24SSimon Glass .cmd_keyword = { 470*2e192b24SSimon Glass ethsw_id_vlan, 471*2e192b24SSimon Glass ethsw_id_fdb, 472*2e192b24SSimon Glass ethsw_id_shared, 473*2e192b24SSimon Glass ethsw_id_key_end, 474*2e192b24SSimon Glass }, 475*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 476*2e192b24SSimon Glass vlan_learn_set), 477*2e192b24SSimon Glass .keyword_function = NULL, 478*2e192b24SSimon Glass }, { 479*2e192b24SSimon Glass .cmd_keyword = { 480*2e192b24SSimon Glass ethsw_id_vlan, 481*2e192b24SSimon Glass ethsw_id_fdb, 482*2e192b24SSimon Glass ethsw_id_private, 483*2e192b24SSimon Glass ethsw_id_key_end, 484*2e192b24SSimon Glass }, 485*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 486*2e192b24SSimon Glass vlan_learn_set), 487*2e192b24SSimon Glass .keyword_function = NULL, 488*2e192b24SSimon Glass }, { 489*2e192b24SSimon Glass .cmd_keyword = { 490*2e192b24SSimon Glass ethsw_id_ingress, 491*2e192b24SSimon Glass ethsw_id_filtering, 492*2e192b24SSimon Glass ethsw_id_key_end, 493*2e192b24SSimon Glass }, 494*2e192b24SSimon Glass .cmd_func_offset = -1, 495*2e192b24SSimon Glass .keyword_function = ðsw_ingr_fltr_help_key_func, 496*2e192b24SSimon Glass }, { 497*2e192b24SSimon Glass .cmd_keyword = { 498*2e192b24SSimon Glass ethsw_id_ingress, 499*2e192b24SSimon Glass ethsw_id_filtering, 500*2e192b24SSimon Glass ethsw_id_help, 501*2e192b24SSimon Glass ethsw_id_key_end, 502*2e192b24SSimon Glass }, 503*2e192b24SSimon Glass .cmd_func_offset = -1, 504*2e192b24SSimon Glass .keyword_function = ðsw_ingr_fltr_help_key_func, 505*2e192b24SSimon Glass }, { 506*2e192b24SSimon Glass .cmd_keyword = { 507*2e192b24SSimon Glass ethsw_id_ingress, 508*2e192b24SSimon Glass ethsw_id_filtering, 509*2e192b24SSimon Glass ethsw_id_show, 510*2e192b24SSimon Glass ethsw_id_key_end, 511*2e192b24SSimon Glass }, 512*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 513*2e192b24SSimon Glass port_ingr_filt_show), 514*2e192b24SSimon Glass .keyword_function = NULL, 515*2e192b24SSimon Glass }, { 516*2e192b24SSimon Glass .cmd_keyword = { 517*2e192b24SSimon Glass ethsw_id_ingress, 518*2e192b24SSimon Glass ethsw_id_filtering, 519*2e192b24SSimon Glass ethsw_id_enable, 520*2e192b24SSimon Glass ethsw_id_key_end, 521*2e192b24SSimon Glass }, 522*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 523*2e192b24SSimon Glass port_ingr_filt_set), 524*2e192b24SSimon Glass .keyword_function = NULL, 525*2e192b24SSimon Glass }, { 526*2e192b24SSimon Glass .cmd_keyword = { 527*2e192b24SSimon Glass ethsw_id_ingress, 528*2e192b24SSimon Glass ethsw_id_filtering, 529*2e192b24SSimon Glass ethsw_id_disable, 530*2e192b24SSimon Glass ethsw_id_key_end, 531*2e192b24SSimon Glass }, 532*2e192b24SSimon Glass .cmd_func_offset = offsetof(struct ethsw_command_func, 533*2e192b24SSimon Glass port_ingr_filt_set), 534*2e192b24SSimon Glass .keyword_function = NULL, 535*2e192b24SSimon Glass }, 536*2e192b24SSimon Glass }; 537*2e192b24SSimon Glass 538*2e192b24SSimon Glass struct keywords_optional { 539*2e192b24SSimon Glass int cmd_keyword[ETHSW_MAX_CMD_PARAMS]; 540*2e192b24SSimon Glass } cmd_opt_def[] = { 541*2e192b24SSimon Glass { 542*2e192b24SSimon Glass .cmd_keyword = { 543*2e192b24SSimon Glass ethsw_id_port, 544*2e192b24SSimon Glass ethsw_id_port_no, 545*2e192b24SSimon Glass ethsw_id_key_end, 546*2e192b24SSimon Glass }, 547*2e192b24SSimon Glass }, { 548*2e192b24SSimon Glass .cmd_keyword = { 549*2e192b24SSimon Glass ethsw_id_vlan, 550*2e192b24SSimon Glass ethsw_id_vlan_no, 551*2e192b24SSimon Glass ethsw_id_key_end, 552*2e192b24SSimon Glass }, 553*2e192b24SSimon Glass }, { 554*2e192b24SSimon Glass .cmd_keyword = { 555*2e192b24SSimon Glass ethsw_id_port, 556*2e192b24SSimon Glass ethsw_id_port_no, 557*2e192b24SSimon Glass ethsw_id_vlan, 558*2e192b24SSimon Glass ethsw_id_vlan_no, 559*2e192b24SSimon Glass ethsw_id_key_end, 560*2e192b24SSimon Glass }, 561*2e192b24SSimon Glass }, 562*2e192b24SSimon Glass }; 563*2e192b24SSimon Glass 564*2e192b24SSimon Glass static int keyword_match_gen(enum ethsw_keyword_id key_id, int argc, char 565*2e192b24SSimon Glass *const argv[], int *argc_nr, 566*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 567*2e192b24SSimon Glass static int keyword_match_port(enum ethsw_keyword_id key_id, int argc, 568*2e192b24SSimon Glass char *const argv[], int *argc_nr, 569*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 570*2e192b24SSimon Glass static int keyword_match_vlan(enum ethsw_keyword_id key_id, int argc, 571*2e192b24SSimon Glass char *const argv[], int *argc_nr, 572*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 573*2e192b24SSimon Glass static int keyword_match_pvid(enum ethsw_keyword_id key_id, int argc, 574*2e192b24SSimon Glass char *const argv[], int *argc_nr, 575*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 576*2e192b24SSimon Glass static int keyword_match_mac_addr(enum ethsw_keyword_id key_id, int argc, 577*2e192b24SSimon Glass char *const argv[], int *argc_nr, 578*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd); 579*2e192b24SSimon Glass 580*2e192b24SSimon Glass /* 581*2e192b24SSimon Glass * Define properties for each keyword; 582*2e192b24SSimon Glass * keep the order synced with enum ethsw_keyword_id 583*2e192b24SSimon Glass */ 584*2e192b24SSimon Glass struct keyword_def { 585*2e192b24SSimon Glass const char *keyword_name; 586*2e192b24SSimon Glass int (*match)(enum ethsw_keyword_id key_id, int argc, char *const argv[], 587*2e192b24SSimon Glass int *argc_nr, struct ethsw_command_def *parsed_cmd); 588*2e192b24SSimon Glass } keyword[] = { 589*2e192b24SSimon Glass { 590*2e192b24SSimon Glass .keyword_name = "help", 591*2e192b24SSimon Glass .match = &keyword_match_gen, 592*2e192b24SSimon Glass }, { 593*2e192b24SSimon Glass .keyword_name = "show", 594*2e192b24SSimon Glass .match = &keyword_match_gen, 595*2e192b24SSimon Glass }, { 596*2e192b24SSimon Glass .keyword_name = "port", 597*2e192b24SSimon Glass .match = &keyword_match_port 598*2e192b24SSimon Glass }, { 599*2e192b24SSimon Glass .keyword_name = "enable", 600*2e192b24SSimon Glass .match = &keyword_match_gen, 601*2e192b24SSimon Glass }, { 602*2e192b24SSimon Glass .keyword_name = "disable", 603*2e192b24SSimon Glass .match = &keyword_match_gen, 604*2e192b24SSimon Glass }, { 605*2e192b24SSimon Glass .keyword_name = "statistics", 606*2e192b24SSimon Glass .match = &keyword_match_gen, 607*2e192b24SSimon Glass }, { 608*2e192b24SSimon Glass .keyword_name = "clear", 609*2e192b24SSimon Glass .match = &keyword_match_gen, 610*2e192b24SSimon Glass }, { 611*2e192b24SSimon Glass .keyword_name = "learning", 612*2e192b24SSimon Glass .match = &keyword_match_gen, 613*2e192b24SSimon Glass }, { 614*2e192b24SSimon Glass .keyword_name = "auto", 615*2e192b24SSimon Glass .match = &keyword_match_gen, 616*2e192b24SSimon Glass }, { 617*2e192b24SSimon Glass .keyword_name = "vlan", 618*2e192b24SSimon Glass .match = &keyword_match_vlan, 619*2e192b24SSimon Glass }, { 620*2e192b24SSimon Glass .keyword_name = "fdb", 621*2e192b24SSimon Glass .match = &keyword_match_gen, 622*2e192b24SSimon Glass }, { 623*2e192b24SSimon Glass .keyword_name = "add", 624*2e192b24SSimon Glass .match = &keyword_match_mac_addr, 625*2e192b24SSimon Glass }, { 626*2e192b24SSimon Glass .keyword_name = "del", 627*2e192b24SSimon Glass .match = &keyword_match_mac_addr, 628*2e192b24SSimon Glass }, { 629*2e192b24SSimon Glass .keyword_name = "flush", 630*2e192b24SSimon Glass .match = &keyword_match_gen, 631*2e192b24SSimon Glass }, { 632*2e192b24SSimon Glass .keyword_name = "pvid", 633*2e192b24SSimon Glass .match = &keyword_match_pvid, 634*2e192b24SSimon Glass }, { 635*2e192b24SSimon Glass .keyword_name = "untagged", 636*2e192b24SSimon Glass .match = &keyword_match_gen, 637*2e192b24SSimon Glass }, { 638*2e192b24SSimon Glass .keyword_name = "all", 639*2e192b24SSimon Glass .match = &keyword_match_gen, 640*2e192b24SSimon Glass }, { 641*2e192b24SSimon Glass .keyword_name = "none", 642*2e192b24SSimon Glass .match = &keyword_match_gen, 643*2e192b24SSimon Glass }, { 644*2e192b24SSimon Glass .keyword_name = "egress", 645*2e192b24SSimon Glass .match = &keyword_match_gen, 646*2e192b24SSimon Glass }, { 647*2e192b24SSimon Glass .keyword_name = "tag", 648*2e192b24SSimon Glass .match = &keyword_match_gen, 649*2e192b24SSimon Glass }, { 650*2e192b24SSimon Glass .keyword_name = "classified", 651*2e192b24SSimon Glass .match = &keyword_match_gen, 652*2e192b24SSimon Glass }, { 653*2e192b24SSimon Glass .keyword_name = "shared", 654*2e192b24SSimon Glass .match = &keyword_match_gen, 655*2e192b24SSimon Glass }, { 656*2e192b24SSimon Glass .keyword_name = "private", 657*2e192b24SSimon Glass .match = &keyword_match_gen, 658*2e192b24SSimon Glass }, { 659*2e192b24SSimon Glass .keyword_name = "ingress", 660*2e192b24SSimon Glass .match = &keyword_match_gen, 661*2e192b24SSimon Glass }, { 662*2e192b24SSimon Glass .keyword_name = "filtering", 663*2e192b24SSimon Glass .match = &keyword_match_gen, 664*2e192b24SSimon Glass }, 665*2e192b24SSimon Glass }; 666*2e192b24SSimon Glass 667*2e192b24SSimon Glass /* 668*2e192b24SSimon Glass * Function used by an Ethernet Switch driver to set the functions 669*2e192b24SSimon Glass * that must be called by the parser when an ethsw command is given 670*2e192b24SSimon Glass */ 671*2e192b24SSimon Glass int ethsw_define_functions(const struct ethsw_command_func *cmd_func) 672*2e192b24SSimon Glass { 673*2e192b24SSimon Glass int i; 674*2e192b24SSimon Glass void **aux_p; 675*2e192b24SSimon Glass int (*cmd_func_aux)(struct ethsw_command_def *); 676*2e192b24SSimon Glass 677*2e192b24SSimon Glass if (!cmd_func->ethsw_name) 678*2e192b24SSimon Glass return -EINVAL; 679*2e192b24SSimon Glass 680*2e192b24SSimon Glass ethsw_name = cmd_func->ethsw_name; 681*2e192b24SSimon Glass 682*2e192b24SSimon Glass for (i = 0; i < ARRAY_SIZE(ethsw_cmd_def); i++) { 683*2e192b24SSimon Glass /* 684*2e192b24SSimon Glass * get the pointer to the function send by the Ethernet Switch 685*2e192b24SSimon Glass * driver that corresponds to the proper ethsw command 686*2e192b24SSimon Glass */ 687*2e192b24SSimon Glass if (ethsw_cmd_def[i].keyword_function) 688*2e192b24SSimon Glass continue; 689*2e192b24SSimon Glass 690*2e192b24SSimon Glass aux_p = (void *)cmd_func + ethsw_cmd_def[i].cmd_func_offset; 691*2e192b24SSimon Glass 692*2e192b24SSimon Glass cmd_func_aux = (int (*)(struct ethsw_command_def *)) *aux_p; 693*2e192b24SSimon Glass ethsw_cmd_def[i].keyword_function = cmd_func_aux; 694*2e192b24SSimon Glass } 695*2e192b24SSimon Glass 696*2e192b24SSimon Glass return 0; 697*2e192b24SSimon Glass } 698*2e192b24SSimon Glass 699*2e192b24SSimon Glass /* Generic function used to match a keyword only by a string */ 700*2e192b24SSimon Glass static int keyword_match_gen(enum ethsw_keyword_id key_id, int argc, 701*2e192b24SSimon Glass char *const argv[], int *argc_nr, 702*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 703*2e192b24SSimon Glass { 704*2e192b24SSimon Glass if (strcmp(argv[*argc_nr], keyword[key_id].keyword_name) == 0) { 705*2e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = key_id; 706*2e192b24SSimon Glass 707*2e192b24SSimon Glass return 1; 708*2e192b24SSimon Glass } 709*2e192b24SSimon Glass return 0; 710*2e192b24SSimon Glass } 711*2e192b24SSimon Glass 712*2e192b24SSimon Glass /* Function used to match the command's port */ 713*2e192b24SSimon Glass static int keyword_match_port(enum ethsw_keyword_id key_id, int argc, 714*2e192b24SSimon Glass char *const argv[], int *argc_nr, 715*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 716*2e192b24SSimon Glass { 717*2e192b24SSimon Glass unsigned long val; 718*2e192b24SSimon Glass 719*2e192b24SSimon Glass if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd)) 720*2e192b24SSimon Glass return 0; 721*2e192b24SSimon Glass 722*2e192b24SSimon Glass if (*argc_nr + 1 >= argc) 723*2e192b24SSimon Glass return 0; 724*2e192b24SSimon Glass 725*2e192b24SSimon Glass if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) { 726*2e192b24SSimon Glass parsed_cmd->port = val; 727*2e192b24SSimon Glass (*argc_nr)++; 728*2e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_port_no; 729*2e192b24SSimon Glass return 1; 730*2e192b24SSimon Glass } 731*2e192b24SSimon Glass 732*2e192b24SSimon Glass return 0; 733*2e192b24SSimon Glass } 734*2e192b24SSimon Glass 735*2e192b24SSimon Glass /* Function used to match the command's vlan */ 736*2e192b24SSimon Glass static int keyword_match_vlan(enum ethsw_keyword_id key_id, int argc, 737*2e192b24SSimon Glass char *const argv[], int *argc_nr, 738*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 739*2e192b24SSimon Glass { 740*2e192b24SSimon Glass unsigned long val; 741*2e192b24SSimon Glass int aux; 742*2e192b24SSimon Glass 743*2e192b24SSimon Glass if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd)) 744*2e192b24SSimon Glass return 0; 745*2e192b24SSimon Glass 746*2e192b24SSimon Glass if (*argc_nr + 1 >= argc) 747*2e192b24SSimon Glass return 0; 748*2e192b24SSimon Glass 749*2e192b24SSimon Glass if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) { 750*2e192b24SSimon Glass parsed_cmd->vid = val; 751*2e192b24SSimon Glass (*argc_nr)++; 752*2e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_vlan_no; 753*2e192b24SSimon Glass return 1; 754*2e192b24SSimon Glass } 755*2e192b24SSimon Glass 756*2e192b24SSimon Glass aux = *argc_nr + 1; 757*2e192b24SSimon Glass 758*2e192b24SSimon Glass if (keyword_match_gen(ethsw_id_add, argc, argv, &aux, parsed_cmd)) 759*2e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr + 1] = ethsw_id_add; 760*2e192b24SSimon Glass else if (keyword_match_gen(ethsw_id_del, argc, argv, &aux, parsed_cmd)) 761*2e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr + 1] = ethsw_id_del; 762*2e192b24SSimon Glass else 763*2e192b24SSimon Glass return 0; 764*2e192b24SSimon Glass 765*2e192b24SSimon Glass if (*argc_nr + 2 >= argc) 766*2e192b24SSimon Glass return 0; 767*2e192b24SSimon Glass 768*2e192b24SSimon Glass if (strict_strtoul(argv[*argc_nr + 2], 10, &val) != -EINVAL) { 769*2e192b24SSimon Glass parsed_cmd->vid = val; 770*2e192b24SSimon Glass (*argc_nr) += 2; 771*2e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_add_del_no; 772*2e192b24SSimon Glass return 1; 773*2e192b24SSimon Glass } 774*2e192b24SSimon Glass 775*2e192b24SSimon Glass return 0; 776*2e192b24SSimon Glass } 777*2e192b24SSimon Glass 778*2e192b24SSimon Glass /* Function used to match the command's pvid */ 779*2e192b24SSimon Glass static int keyword_match_pvid(enum ethsw_keyword_id key_id, int argc, 780*2e192b24SSimon Glass char *const argv[], int *argc_nr, 781*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 782*2e192b24SSimon Glass { 783*2e192b24SSimon Glass unsigned long val; 784*2e192b24SSimon Glass 785*2e192b24SSimon Glass if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd)) 786*2e192b24SSimon Glass return 0; 787*2e192b24SSimon Glass 788*2e192b24SSimon Glass if (*argc_nr + 1 >= argc) 789*2e192b24SSimon Glass return 1; 790*2e192b24SSimon Glass 791*2e192b24SSimon Glass if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) { 792*2e192b24SSimon Glass parsed_cmd->vid = val; 793*2e192b24SSimon Glass (*argc_nr)++; 794*2e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_pvid_no; 795*2e192b24SSimon Glass } 796*2e192b24SSimon Glass 797*2e192b24SSimon Glass return 1; 798*2e192b24SSimon Glass } 799*2e192b24SSimon Glass 800*2e192b24SSimon Glass /* Function used to match the command's MAC address */ 801*2e192b24SSimon Glass static int keyword_match_mac_addr(enum ethsw_keyword_id key_id, int argc, 802*2e192b24SSimon Glass char *const argv[], int *argc_nr, 803*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 804*2e192b24SSimon Glass { 805*2e192b24SSimon Glass if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd)) 806*2e192b24SSimon Glass return 0; 807*2e192b24SSimon Glass 808*2e192b24SSimon Glass if ((*argc_nr + 1 >= argc) || 809*2e192b24SSimon Glass !is_broadcast_ethaddr(parsed_cmd->ethaddr)) 810*2e192b24SSimon Glass return 1; 811*2e192b24SSimon Glass 812*2e192b24SSimon Glass if (eth_validate_ethaddr_str(argv[*argc_nr + 1])) { 813*2e192b24SSimon Glass printf("Invalid MAC address: %s\n", argv[*argc_nr + 1]); 814*2e192b24SSimon Glass return 0; 815*2e192b24SSimon Glass } 816*2e192b24SSimon Glass 817*2e192b24SSimon Glass eth_parse_enetaddr(argv[*argc_nr + 1], parsed_cmd->ethaddr); 818*2e192b24SSimon Glass 819*2e192b24SSimon Glass if (is_broadcast_ethaddr(parsed_cmd->ethaddr)) { 820*2e192b24SSimon Glass memset(parsed_cmd->ethaddr, 0xFF, sizeof(parsed_cmd->ethaddr)); 821*2e192b24SSimon Glass return 0; 822*2e192b24SSimon Glass } 823*2e192b24SSimon Glass 824*2e192b24SSimon Glass parsed_cmd->cmd_to_keywords[*argc_nr + 1] = ethsw_id_add_del_mac; 825*2e192b24SSimon Glass 826*2e192b24SSimon Glass return 1; 827*2e192b24SSimon Glass } 828*2e192b24SSimon Glass 829*2e192b24SSimon Glass /* Finds optional keywords and modifies *argc_va to skip them */ 830*2e192b24SSimon Glass static void cmd_keywords_opt_check(const struct ethsw_command_def *parsed_cmd, 831*2e192b24SSimon Glass int *argc_val) 832*2e192b24SSimon Glass { 833*2e192b24SSimon Glass int i; 834*2e192b24SSimon Glass int keyw_opt_matched; 835*2e192b24SSimon Glass int argc_val_max; 836*2e192b24SSimon Glass int const *cmd_keyw_p; 837*2e192b24SSimon Glass int const *cmd_keyw_opt_p; 838*2e192b24SSimon Glass 839*2e192b24SSimon Glass /* remember the best match */ 840*2e192b24SSimon Glass argc_val_max = *argc_val; 841*2e192b24SSimon Glass 842*2e192b24SSimon Glass /* 843*2e192b24SSimon Glass * check if our command's optional keywords match the optional 844*2e192b24SSimon Glass * keywords of an available command 845*2e192b24SSimon Glass */ 846*2e192b24SSimon Glass for (i = 0; i < ARRAY_SIZE(ethsw_cmd_def); i++) { 847*2e192b24SSimon Glass keyw_opt_matched = 0; 848*2e192b24SSimon Glass cmd_keyw_p = &parsed_cmd->cmd_to_keywords[keyw_opt_matched]; 849*2e192b24SSimon Glass cmd_keyw_opt_p = &cmd_opt_def[i].cmd_keyword[keyw_opt_matched]; 850*2e192b24SSimon Glass 851*2e192b24SSimon Glass /* 852*2e192b24SSimon Glass * increase the number of keywords that 853*2e192b24SSimon Glass * matched with a command 854*2e192b24SSimon Glass */ 855*2e192b24SSimon Glass while (keyw_opt_matched + *argc_val < 856*2e192b24SSimon Glass parsed_cmd->cmd_keywords_nr && 857*2e192b24SSimon Glass *cmd_keyw_opt_p != ethsw_id_key_end && 858*2e192b24SSimon Glass *(cmd_keyw_p + *argc_val) == *cmd_keyw_opt_p) { 859*2e192b24SSimon Glass keyw_opt_matched++; 860*2e192b24SSimon Glass cmd_keyw_p++; 861*2e192b24SSimon Glass cmd_keyw_opt_p++; 862*2e192b24SSimon Glass } 863*2e192b24SSimon Glass 864*2e192b24SSimon Glass /* 865*2e192b24SSimon Glass * if all our optional command's keywords perfectly match an 866*2e192b24SSimon Glass * optional pattern, then we can move to the next defined 867*2e192b24SSimon Glass * keywords in our command; remember the one that matched the 868*2e192b24SSimon Glass * greatest number of keywords 869*2e192b24SSimon Glass */ 870*2e192b24SSimon Glass if (keyw_opt_matched + *argc_val <= 871*2e192b24SSimon Glass parsed_cmd->cmd_keywords_nr && 872*2e192b24SSimon Glass *cmd_keyw_opt_p == ethsw_id_key_end && 873*2e192b24SSimon Glass *argc_val + keyw_opt_matched > argc_val_max) 874*2e192b24SSimon Glass argc_val_max = *argc_val + keyw_opt_matched; 875*2e192b24SSimon Glass } 876*2e192b24SSimon Glass 877*2e192b24SSimon Glass *argc_val = argc_val_max; 878*2e192b24SSimon Glass } 879*2e192b24SSimon Glass 880*2e192b24SSimon Glass /* 881*2e192b24SSimon Glass * Finds the function to call based on keywords and 882*2e192b24SSimon Glass * modifies *argc_va to skip them 883*2e192b24SSimon Glass */ 884*2e192b24SSimon Glass static void cmd_keywords_check(struct ethsw_command_def *parsed_cmd, 885*2e192b24SSimon Glass int *argc_val) 886*2e192b24SSimon Glass { 887*2e192b24SSimon Glass int i; 888*2e192b24SSimon Glass int keyw_matched; 889*2e192b24SSimon Glass int *cmd_keyw_p; 890*2e192b24SSimon Glass int *cmd_keyw_def_p; 891*2e192b24SSimon Glass 892*2e192b24SSimon Glass /* 893*2e192b24SSimon Glass * check if our command's keywords match the 894*2e192b24SSimon Glass * keywords of an available command 895*2e192b24SSimon Glass */ 896*2e192b24SSimon Glass for (i = 0; i < ARRAY_SIZE(ethsw_cmd_def); i++) { 897*2e192b24SSimon Glass keyw_matched = 0; 898*2e192b24SSimon Glass cmd_keyw_p = &parsed_cmd->cmd_to_keywords[keyw_matched]; 899*2e192b24SSimon Glass cmd_keyw_def_p = ðsw_cmd_def[i].cmd_keyword[keyw_matched]; 900*2e192b24SSimon Glass 901*2e192b24SSimon Glass /* 902*2e192b24SSimon Glass * increase the number of keywords that 903*2e192b24SSimon Glass * matched with a command 904*2e192b24SSimon Glass */ 905*2e192b24SSimon Glass while (keyw_matched + *argc_val < parsed_cmd->cmd_keywords_nr && 906*2e192b24SSimon Glass *cmd_keyw_def_p != ethsw_id_key_end && 907*2e192b24SSimon Glass *(cmd_keyw_p + *argc_val) == *cmd_keyw_def_p) { 908*2e192b24SSimon Glass keyw_matched++; 909*2e192b24SSimon Glass cmd_keyw_p++; 910*2e192b24SSimon Glass cmd_keyw_def_p++; 911*2e192b24SSimon Glass } 912*2e192b24SSimon Glass 913*2e192b24SSimon Glass /* 914*2e192b24SSimon Glass * if all our command's keywords perfectly match an 915*2e192b24SSimon Glass * available command, then we get the function we need to call 916*2e192b24SSimon Glass * to configure the Ethernet Switch 917*2e192b24SSimon Glass */ 918*2e192b24SSimon Glass if (keyw_matched && keyw_matched + *argc_val == 919*2e192b24SSimon Glass parsed_cmd->cmd_keywords_nr && 920*2e192b24SSimon Glass *cmd_keyw_def_p == ethsw_id_key_end) { 921*2e192b24SSimon Glass *argc_val += keyw_matched; 922*2e192b24SSimon Glass parsed_cmd->cmd_function = 923*2e192b24SSimon Glass ethsw_cmd_def[i].keyword_function; 924*2e192b24SSimon Glass return; 925*2e192b24SSimon Glass } 926*2e192b24SSimon Glass } 927*2e192b24SSimon Glass } 928*2e192b24SSimon Glass 929*2e192b24SSimon Glass /* find all the keywords in the command */ 930*2e192b24SSimon Glass static int keywords_find(int argc, char * const argv[], 931*2e192b24SSimon Glass struct ethsw_command_def *parsed_cmd) 932*2e192b24SSimon Glass { 933*2e192b24SSimon Glass int i; 934*2e192b24SSimon Glass int j; 935*2e192b24SSimon Glass int argc_val; 936*2e192b24SSimon Glass int rc = CMD_RET_SUCCESS; 937*2e192b24SSimon Glass 938*2e192b24SSimon Glass for (i = 1; i < argc; i++) { 939*2e192b24SSimon Glass for (j = 0; j < ethsw_id_count; j++) { 940*2e192b24SSimon Glass if (keyword[j].match(j, argc, argv, &i, parsed_cmd)) 941*2e192b24SSimon Glass break; 942*2e192b24SSimon Glass } 943*2e192b24SSimon Glass } 944*2e192b24SSimon Glass 945*2e192b24SSimon Glass /* if there is no keyword match for a word, the command is invalid */ 946*2e192b24SSimon Glass for (i = 1; i < argc; i++) 947*2e192b24SSimon Glass if (parsed_cmd->cmd_to_keywords[i] == ethsw_id_key_end) 948*2e192b24SSimon Glass rc = CMD_RET_USAGE; 949*2e192b24SSimon Glass 950*2e192b24SSimon Glass parsed_cmd->cmd_keywords_nr = argc; 951*2e192b24SSimon Glass argc_val = 1; 952*2e192b24SSimon Glass 953*2e192b24SSimon Glass /* get optional parameters first */ 954*2e192b24SSimon Glass cmd_keywords_opt_check(parsed_cmd, &argc_val); 955*2e192b24SSimon Glass 956*2e192b24SSimon Glass if (argc_val == parsed_cmd->cmd_keywords_nr) 957*2e192b24SSimon Glass return CMD_RET_USAGE; 958*2e192b24SSimon Glass 959*2e192b24SSimon Glass /* 960*2e192b24SSimon Glass * check the keywords and if a match is found, 961*2e192b24SSimon Glass * get the function to call 962*2e192b24SSimon Glass */ 963*2e192b24SSimon Glass cmd_keywords_check(parsed_cmd, &argc_val); 964*2e192b24SSimon Glass 965*2e192b24SSimon Glass /* error if not all commands' parameters were matched */ 966*2e192b24SSimon Glass if (argc_val == parsed_cmd->cmd_keywords_nr) { 967*2e192b24SSimon Glass if (!parsed_cmd->cmd_function) { 968*2e192b24SSimon Glass printf("Command not available for: %s\n", ethsw_name); 969*2e192b24SSimon Glass rc = CMD_RET_FAILURE; 970*2e192b24SSimon Glass } 971*2e192b24SSimon Glass } else { 972*2e192b24SSimon Glass rc = CMD_RET_USAGE; 973*2e192b24SSimon Glass } 974*2e192b24SSimon Glass 975*2e192b24SSimon Glass return rc; 976*2e192b24SSimon Glass } 977*2e192b24SSimon Glass 978*2e192b24SSimon Glass static void command_def_init(struct ethsw_command_def *parsed_cmd) 979*2e192b24SSimon Glass { 980*2e192b24SSimon Glass int i; 981*2e192b24SSimon Glass 982*2e192b24SSimon Glass for (i = 0; i < ETHSW_MAX_CMD_PARAMS; i++) 983*2e192b24SSimon Glass parsed_cmd->cmd_to_keywords[i] = ethsw_id_key_end; 984*2e192b24SSimon Glass 985*2e192b24SSimon Glass parsed_cmd->port = ETHSW_CMD_PORT_ALL; 986*2e192b24SSimon Glass parsed_cmd->vid = ETHSW_CMD_VLAN_ALL; 987*2e192b24SSimon Glass parsed_cmd->cmd_function = NULL; 988*2e192b24SSimon Glass 989*2e192b24SSimon Glass /* We initialize the MAC address with the Broadcast address */ 990*2e192b24SSimon Glass memset(parsed_cmd->ethaddr, 0xff, sizeof(parsed_cmd->ethaddr)); 991*2e192b24SSimon Glass } 992*2e192b24SSimon Glass 993*2e192b24SSimon Glass /* function to interpret commands starting with "ethsw " */ 994*2e192b24SSimon Glass static int do_ethsw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 995*2e192b24SSimon Glass { 996*2e192b24SSimon Glass struct ethsw_command_def parsed_cmd; 997*2e192b24SSimon Glass int rc = CMD_RET_SUCCESS; 998*2e192b24SSimon Glass 999*2e192b24SSimon Glass if (argc == 1 || argc >= ETHSW_MAX_CMD_PARAMS) 1000*2e192b24SSimon Glass return CMD_RET_USAGE; 1001*2e192b24SSimon Glass 1002*2e192b24SSimon Glass command_def_init(&parsed_cmd); 1003*2e192b24SSimon Glass 1004*2e192b24SSimon Glass rc = keywords_find(argc, argv, &parsed_cmd); 1005*2e192b24SSimon Glass 1006*2e192b24SSimon Glass if (rc == CMD_RET_SUCCESS) 1007*2e192b24SSimon Glass rc = parsed_cmd.cmd_function(&parsed_cmd); 1008*2e192b24SSimon Glass 1009*2e192b24SSimon Glass return rc; 1010*2e192b24SSimon Glass } 1011*2e192b24SSimon Glass 1012*2e192b24SSimon Glass #define ETHSW_PORT_CONF_HELP "[port <port_no>] { enable | disable | show } " \ 1013*2e192b24SSimon Glass "- enable/disable a port; show shows a port's configuration" 1014*2e192b24SSimon Glass 1015*2e192b24SSimon Glass U_BOOT_CMD(ethsw, ETHSW_MAX_CMD_PARAMS, 0, do_ethsw, 1016*2e192b24SSimon Glass "Ethernet l2 switch commands", 1017*2e192b24SSimon Glass ETHSW_PORT_CONF_HELP"\n" 1018*2e192b24SSimon Glass ETHSW_PORT_STATS_HELP"\n" 1019*2e192b24SSimon Glass ETHSW_LEARN_HELP"\n" 1020*2e192b24SSimon Glass ETHSW_FDB_HELP"\n" 1021*2e192b24SSimon Glass ETHSW_PVID_HELP"\n" 1022*2e192b24SSimon Glass ETHSW_VLAN_HELP"\n" 1023*2e192b24SSimon Glass ETHSW_PORT_UNTAG_HELP"\n" 1024*2e192b24SSimon Glass ETHSW_EGR_VLAN_TAG_HELP"\n" 1025*2e192b24SSimon Glass ETHSW_VLAN_FDB_HELP"\n" 1026*2e192b24SSimon Glass ETHSW_PORT_INGR_FLTR_HELP"\n" 1027*2e192b24SSimon Glass ); 1028